Sfoglia il codice sorgente

chore(release): bump @vocmarket/voc-skill to 0.3.26

Unify token/billing 口径 across skills: read sk- from settings.json/.fmode/voc-credentials, 缺token先自救, only real 402 -> studio/?balance=fmodeapi (apig-pay only for r: session token). Dedupe douyin/xhs recharge copy into voc-api-catalog index + error-codes.md. Add JustOne ecommerce-gateway provider. EPERM installer hardening. Covers 0.3.22 -> 0.3.26.
gangvy 2 mesi fa
parent
commit
8fd1b09288
38 ha cambiato i file con 3111 aggiunte e 404 eliminazioni
  1. 1 1
      claude-code/claude-code-voc-intelligence/.claude-plugin/plugin.json
  2. 21 10
      claude-code/claude-code-voc-intelligence/README.md
  3. 55 123
      claude-code/claude-code-voc-intelligence/bin/claude-voc.js
  4. 1 1
      claude-code/claude-code-voc-intelligence/docs/capability-map.md
  5. 664 0
      claude-code/claude-code-voc-intelligence/mcp/catalog/params/douyin.json
  6. 338 1
      claude-code/claude-code-voc-intelligence/mcp/catalog/params/xiaohongshu.json
  7. 1433 33
      claude-code/claude-code-voc-intelligence/mcp/catalog/voc-social-endpoints.json
  8. 96 1
      claude-code/claude-code-voc-intelligence/mcp/src/core/credentials.js
  9. 57 1
      claude-code/claude-code-voc-intelligence/mcp/src/core/payment-links.js
  10. 16 12
      claude-code/claude-code-voc-intelligence/mcp/src/features/fmode-image-analysis/image-analysis.js
  11. 53 0
      claude-code/claude-code-voc-intelligence/mcp/src/providers/ecommerce-gateway.js
  12. 13 3
      claude-code/claude-code-voc-intelligence/mcp/src/providers/voc-gateway.js
  13. 11 8
      claude-code/claude-code-voc-intelligence/mcp/src/server.js
  14. 13 27
      claude-code/claude-code-voc-intelligence/mcp/src/tools/douyin-trend-run.js
  15. 71 42
      claude-code/claude-code-voc-intelligence/mcp/src/tools/voc-api-catalog-run.js
  16. 13 27
      claude-code/claude-code-voc-intelligence/mcp/src/tools/xiaohongshu-trend-run.js
  17. 2 2
      claude-code/claude-code-voc-intelligence/package-lock.json
  18. 1 1
      claude-code/claude-code-voc-intelligence/package.json
  19. 3 3
      claude-code/claude-code-voc-intelligence/scripts/smoke-mcp.js
  20. 26 8
      claude-code/claude-code-voc-intelligence/scripts/smoke-package.js
  21. 1 1
      claude-code/claude-code-voc-intelligence/skill-package-manifest.json
  22. 12 18
      claude-code/claude-code-voc-intelligence/skills/douyin-trend-intelligence/SKILL.md
  23. 1 3
      claude-code/claude-code-voc-intelligence/skills/douyin-trend-intelligence/references/live-mode.md
  24. 2 2
      claude-code/claude-code-voc-intelligence/skills/douyin-trend-intelligence/references/user-workflow.md
  25. 6 4
      claude-code/claude-code-voc-intelligence/skills/fmode-image-analysis/SKILL.md
  26. 53 8
      claude-code/claude-code-voc-intelligence/skills/voc-api-catalog/SKILL.md
  27. 79 0
      claude-code/claude-code-voc-intelligence/skills/voc-api-catalog/references/error-codes.md
  28. 1 1
      claude-code/claude-code-voc-intelligence/skills/voc-business-workflow/SKILL.md
  29. 3 3
      claude-code/claude-code-voc-intelligence/skills/voc-competitor-map/SKILL.md
  30. 2 2
      claude-code/claude-code-voc-intelligence/skills/voc-content-plan/SKILL.md
  31. 3 3
      claude-code/claude-code-voc-intelligence/skills/voc-issue-pool/SKILL.md
  32. 3 3
      claude-code/claude-code-voc-intelligence/skills/voc-problem-deep-dive/SKILL.md
  33. 1 1
      claude-code/claude-code-voc-intelligence/skills/voc-speaking-script/SKILL.md
  34. 12 18
      claude-code/claude-code-voc-intelligence/skills/xiaohongshu-trend-intelligence/SKILL.md
  35. 7 19
      claude-code/claude-code-voc-intelligence/skills/xiaohongshu-trend-intelligence/references/live-mode.md
  36. 5 5
      claude-code/claude-code-voc-intelligence/skills/xiaohongshu-trend-intelligence/references/user-workflow.md
  37. 6 6
      dist/npm/claude-code-voc-npm-package-manifest.json
  38. 26 3
      openclaw-skills/douyin/douyin-video-transcript/SKILL.md

+ 1 - 1
claude-code/claude-code-voc-intelligence/.claude-plugin/plugin.json

@@ -1,7 +1,7 @@
 {
   "name": "voc-intelligence",
   "description": "VOC intelligence skills for Claude Code: end-to-end VOC business workflows, Xiaohongshu and Douyin trend reports, live social VOC collection, Fmode Doubao image analysis, token/recharge checks, evidence-card outputs, prioritized issue pools, single-problem deep dives, competitor maps, 7-day content plans, VOC-backed speaking script co-creation, boss/operator action plans, and multi-turn memory.",
-  "version": "0.3.17",
+  "version": "0.3.26",
   "author": {
     "name": "nkkj-BrainHack"
   }

+ 21 - 10
claude-code/claude-code-voc-intelligence/README.md

@@ -266,22 +266,33 @@ voc_business_workflow_run
 
 ## token 和充值口径
 
-sample 模式不需要 token。live 模式需要 VOC-AI 数据服务 token。
+sample 模式不需要 token。live 模式需要一把可用的 token——**两条链任一可用即可采集**:
 
-允许读取 token 的位置:
+1. **NewAPI(fmode-api)计费 SK**(`sk-` 开头,优先):就是 Claude Code 的 `ANTHROPIC_AUTH_TOKEN`,装好技能包后通常**已经具备**,不必手动再配。读取来源:
+   - 本次请求参数 `newapiToken` / `fmodeApiKey`
+   - `.env.local` / 环境变量 `FMODE_API_KEY`、`NEWAPI_TOKEN`
+   - `~/.claude/voc-credentials.json` 的 `fmodeApiKey`
+   - `~/.fmode/config.json`(FmodeStudio 保存路径)的 `newapiToken` / `fmodeApiKey`
+   - `~/.claude/settings.json` 的 `env.ANTHROPIC_AUTH_TOKEN`(`sk-` 开头、且 `ANTHROPIC_BASE_URL` 指向 fmode)
+2. **VOC-AI 数据服务会话 token**(`r:` 开头,回退):读取来源——本次请求参数、`.env.local` / 环境变量 `VOC_TOKEN`·`VOC_SOCIAL_TOKEN`、`~/.claude/voc-credentials.json` 的 `vocToken`·`token`
 
-- 本次请求参数
-- 当前工作区 `.env.local`
-- 系统环境变量
-- `~/.claude/voc-credentials.json`
+同一网关 `server.fmode.cn/api/voc-social` 对上述任一有效 token 都接受 `Bearer`,**`sk-` 不是「类型错误」**。`voc_*_token_check` 与实际采集(`voc_api_call` / `voc_*_trend_run`)口径一致,会识别以上**全部**来源;不必在采集前强制先跑检测。
 
 Claude Code 技能包不读取 `~/.openclaw/voc-credentials.json`。
 
-如果没有 token 或余额不足,应给用户充值/开通链接,不要暴露底层接口 403、权限堆栈或上游响应体:
+缺 token 多数是**配置/读取**问题,不是余额不足:应先引导自救(从上述来源读 SK、用 `FMODE_API_KEY` 重试),**只有确认确实是 402 余额不足时**才给充值/开通链接,且不要暴露底层接口 403、权限堆栈或上游响应体。两条链对应**两个不同的充值入口**,不要搭错
 
-```text
-https://app.fmode.cn/dev/apig-pay/?apigid=Vo3ROWEvDy&fun_id=HOkkX72PMF
-```
+- **NewAPI(fmode-api)计费 SK**(`sk-` 开头,多数缺 token 场景走这条)→ fmode-api 余额充值:
+
+  ```text
+  https://app.fmode.cn/dev/studio/?balance=fmodeapi
+  ```
+
+- **VOC-AI 数据服务会话 token**(`r:` 开头)→ apig-pay 充值:
+
+  ```text
+  https://app.fmode.cn/dev/apig-pay/?apigid=Vo3ROWEvDy&fun_id=HOkkX72PMF
+  ```
 
 ## 记忆能力
 

+ 55 - 123
claude-code/claude-code-voc-intelligence/bin/claude-voc.js

@@ -124,6 +124,40 @@ function ensureDir(dirPath) {
   fs.mkdirSync(dirPath, { recursive: true });
 }
 
+// Remove an existing install dir, resilient to Windows locks.
+// A normal recursive remove fails with EPERM/EBUSY when the directory is held
+// by a running process — most commonly a Claude Code session / VSCode terminal
+// whose current working directory is inside the plugin dir. Such a directory
+// can still be *renamed* even though it cannot be deleted, so on failure we move
+// it aside and install fresh, then best-effort delete the moved-aside copy.
+function removeDirResilient(targetDir) {
+  try {
+    fs.rmSync(targetDir, { recursive: true, force: true, maxRetries: 10, retryDelay: 200 });
+    return;
+  } catch (err) {
+    if (!['EPERM', 'EBUSY', 'EACCES', 'ENOTEMPTY'].includes(err.code)) throw err;
+    const asidePath = `${targetDir}.held-${Date.now()}`;
+    try {
+      fs.renameSync(targetDir, asidePath);
+    } catch (renameErr) {
+      const e = new Error(
+        `无法更新技能目录(被占用):${targetDir}\n` +
+        `原因:该目录正被一个运行中的进程占用(常见是该工作区里仍开着的 Claude Code 会话或 VSCode 终端,其当前目录在该插件目录内)。\n` +
+        `请关闭占用该目录的 Claude Code 会话/终端后重试安装。\n` +
+        `(${err.code}: ${err.message}; rename fallback failed: ${renameErr.code || renameErr.message})`
+      );
+      e.code = err.code;
+      throw e;
+    }
+    console.log(`Existing skill directory was in use; moved aside to: ${asidePath}`);
+    try {
+      fs.rmSync(asidePath, { recursive: true, force: true, maxRetries: 5, retryDelay: 200 });
+    } catch (cleanupErr) {
+      console.log(`Note: moved-aside copy is still in use and was not deleted. Remove it later: ${asidePath}`);
+    }
+  }
+}
+
 function isInside(parentDir, childDir) {
   const relative = path.relative(path.resolve(parentDir), path.resolve(childDir));
   return relative === '' || (!!relative && !relative.startsWith('..') && !path.isAbsolute(relative));
@@ -264,8 +298,8 @@ function workspaceTrendSkillText(options) {
     '',
     `- 用户要求${options.platform}趋势情报、内容趋势、评论分析、真实采集、live采集或社媒 VOC 时,必须运行本技能包的工具或 MCP,不要只凭经验回答。`,
     '- 用户说“live / 真实采集 / 进入 live / 实时采集 / 抓真实数据”时,必须运行 live 模式工具。不要回复“我不能实时抓取外部数据”。本技能包已经提供本地 VOC 采集入口。',
-    '- live 模式返回 `needs_token`、`needs_recharge` 或 `needs_valid_token` 时,必须把工具输出里的 `assistantMessage` 原样转述给用户,尤其不能省略充值/开通链接。',
-    '- 如果工具输出里有 `nextActions`,至少转述其中带 `apig-pay` 的充值链接。',
+    '- live 模式返回 `needs_token`、`needs_recharge` 或 `needs_valid_token` 时,必须把工具输出里的 `assistantMessage` 原样转述给用户。`needs_token` 是缺 token、不是没钱:先引导自救(读 `~/.claude/settings.json` 的 `sk-` token),不要劝充值。',
+    '- 如果工具输出里有 `nextActions`,转述其中的自救/充值链接(以工具实际返回为准,不要写死某个链接)。',
     '- 第一轮只说“初步判断 / 机会假设 / 待校准”,不要说成最终结论。',
     '- 后续用户说“保留、不要、更偏、这个不准”等反馈时,运行偏好更新命令沉淀记忆。',
     '',
@@ -273,8 +307,8 @@ function workspaceTrendSkillText(options) {
     '',
     '- If the user asks for live collection, real collection, or entering live mode, run the local VOC tool in live mode.',
     '- Do not answer that you cannot fetch external data. The local VOC tool is the approved collection entry.',
-    '- If the tool returns `needs_token`, `needs_recharge`, or `needs_valid_token`, paste its `assistantMessage` to the user and keep the payment URL visible.',
-    '- The payment URL must be shown when there is no token or insufficient balance: `https://app.fmode.cn/dev/apig-pay/?apigid=Vo3ROWEvDy&fun_id=HOkkX72PMF`',
+    '- If the tool returns `needs_token`, `needs_recharge`, or `needs_valid_token`, paste its `assistantMessage` to the user verbatim.',
+    '- `needs_token` is recoverable: an `sk-` fmode key (Claude Code `ANTHROPIC_AUTH_TOKEN`) lets collection run — guide self-rescue first, do not push recharge. Only a real `402` needs recharge. 完整口径见下方「充值 / 计费口径」。',
     '',
     '## sample 命令',
     '',
@@ -296,19 +330,11 @@ function workspaceTrendSkillText(options) {
     `node ${quotedPath(preferenceUpdater)} --message "<用户反馈原文>" --memory ${quotedPath(defaultMemoryPath)} --result-prefix ${options.resultPrefix}`,
     '```',
     '',
-    '## 充值链接口径',
-    '',
-    '没有 token 或余额不足时,用户必须看到:',
-    '',
-    '```text',
-    'https://app.fmode.cn/dev/apig-pay/?apigid=Vo3ROWEvDy&fun_id=HOkkX72PMF',
-    '```',
+    '## 充值 / 计费口径(简版;完整对照见 voc-api-catalog 技能的「错误码速查」references/error-codes.md)',
     '',
-    '套餐入口可作为补充:',
-    '',
-    '```text',
-    'https://app.fmode.cn/dev/apig-pay/#/workshop/99',
-    '```',
+    '- 缺 token(`needs_token`)= 可恢复、不是没钱:先自救读 `~/.claude/settings.json` 的 `sk-` fmode key(或 `~/.fmode/config.json` / `~/.claude/voc-credentials.json`),用 `FMODE_API_KEY=sk-…` 重试,不要劝充值。',
+    '- 只有真 `402 余额不足` 才充值,入口 `https://app.fmode.cn/dev/studio/?balance=fmodeapi`(NewAPI/fmode-api 计费);`401`=token、`403`=权限,都不充值。`apig-pay/?apigid=Vo3ROWEvDy&fun_id=HOkkX72PMF` 仅限 `r:` 会话 token 余额补充。',
+    '- 实际充值/自救链接以工具返回的 `assistantMessage` / `nextActions` 为准,不要写死。',
     ''
   ].join('\n');
 }
@@ -328,53 +354,6 @@ function workspaceSkillText(targetDir) {
     liveOutput: 'outputs/claude-code-xhs-live',
     resultPrefix: 'XHS_PREF_RESULT'
   });
-  const trendRunner = path.join(targetDir, 'mcp', 'src', 'tools', 'xiaohongshu-trend-run.js');
-  const preferenceUpdater = path.join(targetDir, 'mcp', 'src', 'tools', 'xiaohongshu-preference-update.js');
-  const profilePath = path.join(targetDir, 'memory-templates', 'xiaohongshu-trend-profile.json');
-  const defaultMemoryPath = path.join(WORKSPACE_ROOT, 'outputs', 'claude-code-xhs-memory', 'xiaohongshu-trend-memory.json');
-
-  return [
-    '---',
-    'name: xiaohongshu-trend-intelligence',
-    'description: Build Xiaohongshu trend intelligence reports from industry direction, audience, keywords, notes, and comments. Use when the user asks for 小红书趋势情报、行业趋势、女性客户消费决策、设计元素洞察、家装全屋定制趋势、内容选题 or social VOC analysis.',
-    'allowed-tools: Read Write Bash(node *)',
-    '---',
-    '',
-    '# 小红书趋势情报官',
-    '',
-    '你是面向业务用户的“小红书趋势情报官”。用户要的是第一轮样本观察、机会假设和待确认问题,不是技术日志。',
-    '',
-    '## 必须执行',
-    '',
-    '- 当用户要求做小红书趋势情报、行业趋势、女性客户消费决策、家装全屋定制趋势、设计元素洞察或内容选题时,优先运行下面的 sample 工具命令。',
-    '- 不要只凭经验回答,也不要只返回文件路径。',
-    '- 工具输出里会有 `assistantMessage`,请把它的正文直接发给用户。',
-    '- 第一轮只能说“初步判断 / 机会假设 / 待校准”,不要说成最终结论。',
-    '- 后续用户说“保留、不要、更偏、这个不准”等反馈时,运行偏好更新命令沉淀记忆。',
-    '',
-    '## sample 趋势情报命令',
-    '',
-    '```bash',
-    `node ${quotedPath(trendRunner)} --collection-mode sample --profile ${quotedPath(profilePath)} --output "outputs/claude-code-xhs-sample" --assistant-message-only`,
-    '```',
-    '',
-    '运行后把命令输出正文直接发给用户。不要展示 JSON、summary、data、files 或调试日志。',
-    '',
-    '## 偏好更新命令',
-    '',
-    '```bash',
-    `node ${quotedPath(preferenceUpdater)} --message "<用户反馈原文>" --memory ${quotedPath(defaultMemoryPath)} --result-prefix XHS_PREF_RESULT`,
-    '```',
-    '',
-    '## 推荐用户启动话术',
-    '',
-    '```text',
-    '帮我做一份家装全屋定制行业的小红书趋势情报。',
-    '先用演示样例跑通流程,不要真实采集。',
-    '在聊天里给我第一轮样本观察和待确认问题。',
-    '```',
-    ''
-  ].join('\n');
 }
 
 function workspaceDouyinSkillText(targetDir) {
@@ -392,53 +371,6 @@ function workspaceDouyinSkillText(targetDir) {
     liveOutput: 'outputs/claude-code-douyin-live',
     resultPrefix: 'DOUYIN_PREF_RESULT'
   });
-  const trendRunner = path.join(targetDir, 'mcp', 'src', 'tools', 'douyin-trend-run.js');
-  const preferenceUpdater = path.join(targetDir, 'mcp', 'src', 'tools', 'douyin-preference-update.js');
-  const profilePath = path.join(targetDir, 'memory-templates', 'douyin-trend-profile.json');
-  const defaultMemoryPath = path.join(WORKSPACE_ROOT, 'outputs', 'claude-code-douyin-memory', 'douyin-trend-memory.json');
-
-  return [
-    '---',
-    'name: douyin-trend-intelligence',
-    'description: Build Douyin trend intelligence reports from industry direction, audience, keywords, videos, and comments. Use when the user asks for 抖音趋势情报、视频评论、口播选题、短视频开头、内容趋势 or social VOC analysis.',
-    'allowed-tools: Read Write Bash(node *)',
-    '---',
-    '',
-    '# 抖音趋势情报官',
-    '',
-    '你是面向业务用户的“抖音趋势情报官”。用户要的是第一轮样本观察、机会假设和待确认问题,不是技术日志。',
-    '',
-    '## 必须执行',
-    '',
-    '- 当用户要求做抖音趋势情报、视频评论、口播选题、短视频开头或内容趋势时,优先运行下面的 sample 工具命令。',
-    '- 不要只凭经验回答,也不要只返回文件路径。',
-    '- 工具输出里会有 `assistantMessage`,请把它的正文直接发给用户。',
-    '- 第一轮只能说“初步判断 / 机会假设 / 待校准”,不要说成最终结论。',
-    '- 后续用户说“保留、不要、更偏、这个不准”等反馈时,运行偏好更新命令沉淀记忆。',
-    '',
-    '## sample 趋势情报命令',
-    '',
-    '```bash',
-    `node ${quotedPath(trendRunner)} --collection-mode sample --profile ${quotedPath(profilePath)} --output "outputs/claude-code-douyin-sample" --assistant-message-only`,
-    '```',
-    '',
-    '运行后把命令输出正文直接发给用户。不要展示 JSON、summary、data、files 或调试日志。',
-    '',
-    '## 偏好更新命令',
-    '',
-    '```bash',
-    `node ${quotedPath(preferenceUpdater)} --message "<用户反馈原文>" --memory ${quotedPath(defaultMemoryPath)} --result-prefix DOUYIN_PREF_RESULT`,
-    '```',
-    '',
-    '## 推荐用户启动话术',
-    '',
-    '```text',
-    '帮我做一份家装全屋定制行业的抖音趋势情报。',
-    '先用演示样例跑通流程,不要真实采集。',
-    '在聊天里给我第一轮样本观察和待确认问题。',
-    '```',
-    ''
-  ].join('\n');
 }
 
 function workspaceProblemDeepDiveSkillText(targetDir) {
@@ -468,19 +400,19 @@ function workspaceProblemDeepDiveSkillText(targetDir) {
     '## 命令',
     '',
     '```bash',
-    `node ${quotedPath(deepDiveRunner)} --issue "怎么选" --industry "家居定制" --scenario "线上获客" --audience "意向用户" --assistant-message-only`,
+    `node ${quotedPath(deepDiveRunner)} --issue "怎么选" --industry "<你的行业>" --scenario "线上获客" --audience "意向用户" --assistant-message-only`,
     '```',
     '',
     '## 带记忆的多轮迭代',
     '',
     '```bash',
-    `node ${quotedPath(deepDiveRunner)} --issue "怎么选" --industry "家居定制" --scenario "线上获客" --audience "意向用户" --memory "outputs/voc-problem-memory.json" --feedback "老板不想做直播带看,更想先改评论区回复和方案说明" --blocked-actions "直播带看" --preferred-actions "评论区回复,方案说明" --assistant-message-only`,
+    `node ${quotedPath(deepDiveRunner)} --issue "怎么选" --industry "<你的行业>" --scenario "线上获客" --audience "意向用户" --memory "outputs/voc-problem-memory.json" --feedback "老板不想做直播带看,更想先改评论区回复和方案说明" --blocked-actions "直播带看" --preferred-actions "评论区回复,方案说明" --assistant-message-only`,
     '```',
     '',
     '自然语言反馈也可以直接传入 `feedback`,工具会尝试自动提取偏好和屏蔽动作:',
     '',
     '```bash',
-    `node ${quotedPath(deepDiveRunner)} --issue "怎么选" --project "示例品牌A" --industry "家居定制" --scenario "线上获客" --audience "意向用户" --feedback "这个品牌不想做直播带看,更想先改评论区回复和方案说明" --assistant-message-only`,
+    `node ${quotedPath(deepDiveRunner)} --issue "怎么选" --project "示例品牌A" --industry "<你的行业>" --scenario "线上获客" --audience "意向用户" --feedback "这个品牌不想做直播带看,更想先改评论区回复和方案说明" --assistant-message-only`,
     '```',
     '',
     '运行后把命令输出正文直接发给用户。不要展示 JSON、summary、data、files 或调试日志。',
@@ -513,13 +445,13 @@ function workspaceIssuePoolSkillText(targetDir) {
     '## 命令',
     '',
     '```bash',
-    `node ${quotedPath(issuePoolRunner)} --project "示例品牌A" --industry "家居定制" --scenario "线上获客" --audience "意向用户" --evidence "第一次买不知道怎么选,怕踩雷。,价格有点高,不确定值不值。,咨询的时候没人理。" --assistant-message-only`,
+    `node ${quotedPath(issuePoolRunner)} --project "示例品牌A" --industry "<你的行业>" --scenario "线上获客" --audience "意向用户" --evidence "第一次买不知道怎么选,怕踩雷。,价格有点高,不确定值不值。,咨询的时候没人理。" --assistant-message-only`,
     '```',
     '',
     '带报告文件:',
     '',
     '```bash',
-    `node ${quotedPath(issuePoolRunner)} --project "示例品牌A" --industry "家居定制" --report "outputs/douyin-trend-report.md" --assistant-message-only`,
+    `node ${quotedPath(issuePoolRunner)} --project "示例品牌A" --industry "<你的行业>" --report "outputs/douyin-trend-report.md" --assistant-message-only`,
     '```',
     '',
     '运行后把命令输出正文直接发给用户。不要展示 JSON、summary、data、files 或调试日志。',
@@ -545,7 +477,7 @@ function workspaceContentPlanSkillText(targetDir) {
     '## 命令',
     '',
     '```bash',
-    `node ${quotedPath(runner)} --brand "示例品牌A" --industry "家居定制" --issues "第一次买怕踩雷;觉得价格贵;怕质量不稳定" --assistant-message-only`,
+    `node ${quotedPath(runner)} --brand "示例品牌A" --industry "<你的行业>" --issues "第一次买怕踩雷;觉得价格贵;怕质量不稳定" --assistant-message-only`,
     '```',
     '',
     '运行后把正文直接发给用户,不要展示 JSON。',
@@ -571,7 +503,7 @@ function workspaceSpeakingScriptSkillText(targetDir) {
     '## 命令',
     '',
     '```bash',
-    `node ${quotedPath(runner)} --brand "示例品牌A" --industry "家居定制" --topic "第一次买怎么选不踩雷" --user-issue "第一次买怕选错" --evidence "第一次买不知道怎么选,怕踩雷" --assistant-message-only`,
+    `node ${quotedPath(runner)} --brand "示例品牌A" --industry "<你的行业>" --topic "第一次买怎么选不踩雷" --user-issue "第一次买怕选错" --evidence "第一次买不知道怎么选,怕踩雷" --assistant-message-only`,
     '```',
     '',
     '改稿:',
@@ -603,7 +535,7 @@ function workspaceCompetitorMapSkillText(targetDir) {
     '## 命令',
     '',
     '```bash',
-    `node ${quotedPath(runner)} --brand "示例品牌A" --city "本地" --category "家居定制" --assistant-message-only`,
+    `node ${quotedPath(runner)} --brand "示例品牌A" --city "本地" --category "<你的品类>" --assistant-message-only`,
     '```',
     '',
     '运行后把正文直接发给用户,不要展示 JSON。',
@@ -627,7 +559,7 @@ function workspaceBusinessWorkflowSkillText(targetDir) {
     '## 命令',
     '',
     '```bash',
-    `node ${quotedPath(runner)} --brand "示例品牌A" --industry "家居定制" --platform douyin --collection-mode sample --keywords "家居定制怎么选,第一次买怎么对比,售后" --assistant-message-only`,
+    `node ${quotedPath(runner)} --brand "示例品牌A" --industry "<你的行业>" --platform douyin --collection-mode sample --keywords "<你的品类>怎么选,第一次买怎么对比,售后" --assistant-message-only`,
     '```',
     '',
     '真实采集时把 `--collection-mode sample` 换成 `--collection-mode live`。如果工具提示没有 token、余额不足或没有样本,直接把工具正文发给用户,并保留充值/降级建议。',
@@ -717,15 +649,15 @@ function printNextSteps(targetDir) {
   }
   console.log('');
   console.log('Try this prompt in Claude Code:');
-  console.log('  帮我看一下家装全屋定制最近用户在关心什么,并告诉我先改哪里、下周发什么。');
+  console.log('  帮我看一下 {你的行业/品类} 最近用户在关心什么,并告诉我先改哪里、下周发什么。');
   console.log('');
   console.log('Or try:');
-  console.log('  帮我做一份家装全屋定制行业的小红书趋势情报。');
+  console.log('  帮我做一份 {你的行业/品类} 的小红书趋势情报。');
   console.log('  先用演示样例跑通流程,不要真实采集。');
   console.log('  在聊天里给我第一轮样本观察和待确认问题。');
   console.log('');
   console.log('Or try:');
-  console.log('  帮我做一份家装全屋定制行业的抖音趋势情报。');
+  console.log('  帮我做一份 {你的行业/品类} 的抖音趋势情报。');
   console.log('  先用演示样例跑通流程,不要真实采集。');
   console.log('  在聊天里给我第一轮样本观察和待确认问题。');
   console.log('');
@@ -739,7 +671,7 @@ function install(opts) {
       if (!canOverwriteTarget(opts.target, opts)) {
         throw new Error(`Target already exists. Use --force to overwrite custom target: ${opts.target}`);
       }
-      fs.rmSync(opts.target, { recursive: true, force: true });
+      removeDirResilient(opts.target);
     }
     ensureDir(opts.target);
     const copied = copyDirRecursive(SOURCE_ROOT, opts.target);

+ 1 - 1
claude-code/claude-code-voc-intelligence/docs/capability-map.md

@@ -13,7 +13,7 @@
 | 一次跑完整经营闭环 | `voc-business-workflow` | `voc_business_workflow_run` | 市场声音、问题池、Top 问题动作、7 天内容计划、第一条口播稿 |
 | 先演示流程,不真实采集 | 小红书/抖音趋势 skill | `voc_xiaohongshu_trend_run` / `voc_douyin_trend_run`,`collectionMode=sample` | 第一轮样本观察、机会假设、待确认问题 |
 | 真实采集行业趋势 | 小红书/抖音趋势 skill | `voc_xiaohongshu_trend_run` / `voc_douyin_trend_run`,`collectionMode=live` | 真实笔记/视频、评论证据、趋势假设 |
-| 检查 token 是否可用 | 平台趋势 skill | `voc_xiaohongshu_token_check` / `voc_douyin_token_check` | 是否已配置、无 token 时给充值链接 |
+| 检查 token 是否可用 | 平台趋势 skill | `voc_xiaohongshu_token_check` / `voc_douyin_token_check` | 是否已配置(识别 SK/会话 token 全部来源);缺 token 多是配置/读取问题,先按来源自救读 SK,确认 402 余额不足才给充值 |
 | 用户回答校准问题 | 平台趋势 skill | `voc_xiaohongshu_preference_update` / `voc_douyin_preference_update` | 保存偏好、屏蔽方向、下一轮聚焦 |
 | 把评论整理成问题池 | `voc-issue-pool` | `voc_issue_pool_run` | 问题优先级、状态、证据、影响环节、建议动作 |
 | 判断哪些问题最影响生意 | `voc-issue-pool` | `voc_issue_pool_run` | 本周优先推进的问题和下一步深挖入口 |

+ 664 - 0
claude-code/claude-code-voc-intelligence/mcp/catalog/params/douyin.json

@@ -6116,5 +6116,669 @@
       "default": 10,
       "desc": "每页数量/Page size"
     }
+  ],
+  "douyin.xingtu.audience_distribution": [
+    {
+      "name": "oAuthorId",
+      "in": "query",
+      "type": "string",
+      "required": true,
+      "desc": "作者唯一ID。"
+    },
+    {
+      "name": "platform",
+      "in": "query",
+      "type": "string",
+      "required": false,
+      "default": "SHORT_VIDEO",
+      "desc": "平台类型。 可用值: - `SHORT_VIDEO`: 短视频 - `LIVE_STREAMING`: 直播 - `PICTURE_TEXT`: 图文 - `SHORT_DRAMA`: 短剧"
+    },
+    {
+      "name": "linkType",
+      "in": "query",
+      "type": "string",
+      "required": false,
+      "default": "CONNECTED",
+      "desc": "链接类型过滤器。 可用值: - `CONNECTED`: 已连接 - `AWARE`: 已知晓 - `INTERESTED`: 感兴趣 - `LIKE`: 喜欢 - `FOLLOW`: 关注"
+    }
+  ],
+  "douyin.xingtu.audience_touchpoint_distribution": [
+    {
+      "name": "oAuthorId",
+      "in": "query",
+      "type": "string",
+      "required": true,
+      "desc": "作者唯一ID。"
+    },
+    {
+      "name": "platform",
+      "in": "query",
+      "type": "string",
+      "required": false,
+      "default": "SHORT_VIDEO",
+      "desc": "平台类型。 可用值: - `SHORT_VIDEO`: 短视频 - `LIVE_STREAMING`: 直播 - `PICTURE_TEXT`: 图文 - `SHORT_DRAMA`: 短剧"
+    }
+  ],
+  "douyin.xingtu.comment_keyword_analysis": [
+    {
+      "name": "oAuthorId",
+      "in": "query",
+      "type": "string",
+      "required": true,
+      "desc": "作者唯一ID。"
+    }
+  ],
+  "douyin.xingtu.commerce_seeding_base_info": [
+    {
+      "name": "oAuthorId",
+      "in": "query",
+      "type": "string",
+      "required": true,
+      "desc": "作者唯一ID。"
+    },
+    {
+      "name": "range",
+      "in": "query",
+      "type": "string",
+      "required": false,
+      "default": "DAY_90",
+      "desc": "时间范围。 可用值: - `DAY_30`:最近 30 天 - `DAY_90`:最近 90 天"
+    }
+  ],
+  "douyin.xingtu.content_keyword_analysis": [
+    {
+      "name": "oAuthorId",
+      "in": "query",
+      "type": "string",
+      "required": true,
+      "desc": "作者唯一ID。"
+    }
+  ],
+  "douyin.xingtu.conversion_analysis": [
+    {
+      "name": "oAuthorId",
+      "in": "query",
+      "type": "string",
+      "required": true,
+      "desc": "作者唯一ID。"
+    },
+    {
+      "name": "platform",
+      "in": "query",
+      "type": "string",
+      "required": false,
+      "default": "SHORT_VIDEO",
+      "desc": "平台类型。 可用值: - `SHORT_VIDEO`: 短视频 - `LIVE_STREAMING`: 直播 - `PICTURE_TEXT`: 图文 - `SHORT_DRAMA`: 短剧"
+    },
+    {
+      "name": "range",
+      "in": "query",
+      "type": "string",
+      "required": false,
+      "default": "DAY_30",
+      "desc": "时间范围。 可用值: - `DAY_30`:最近 30 天 - `DAY_90`:最近 90 天"
+    }
+  ],
+  "douyin.xingtu.conversion_resources": [
+    {
+      "name": "oAuthorId",
+      "in": "query",
+      "type": "string",
+      "required": true,
+      "desc": "作者唯一ID。"
+    },
+    {
+      "name": "platform",
+      "in": "query",
+      "type": "string",
+      "required": false,
+      "default": "SHORT_VIDEO",
+      "desc": "平台类型。 可用值: - `SHORT_VIDEO`: 短视频 - `LIVE_STREAMING`: 直播 - `PICTURE_TEXT`: 图文 - `SHORT_DRAMA`: 短剧"
+    },
+    {
+      "name": "industryId",
+      "in": "query",
+      "type": "string",
+      "required": false,
+      "default": "ALL",
+      "desc": "行业类别。 可用值: - `ALL`: 全部 - `ELECTRONICS_AND_APPLIANCES`: 电子与家电 - `FOOD_AND_BEVERAGE`: 食品饮料 - `CLOTHING_AND_ACCESSORIES`: 服装配饰 - `HEALTHCARE_AND_MEDICAL`: 医疗健康 - `BUSINESS_SERVICES`: 商业服务 - `LOCAL_SERVICES`: 本地服务 - `REAL_ESTATE`: 房地产 - `HOME_AND_BUILDING_MATERIALS`: 家居建材 - `EDUCATION_AND_TRAINING`: 教育培训 - `TRAVEL_AND_TOURISM`: 旅游出行 - `PUBLIC_SERVICES`: 公共服务 - `GAMES`: 游戏 - `RETAIL`: 零售 - `TRANSPORTATION_EQUIPMENT`: 运输设备 - `AUTOMOTIVE`: 汽车 - `AGRICULTURE_FORESTRY_FISHERY`: 农林牧渔 - `CHEMICAL_AND_ENERGY`: 化工能源 - `ELECTRONICS_AND_ELECTRICAL`: 电子电气 - `MACHINERY_EQUIPMENT`: 机械设备 - `CULTURE_SPORTS_ENTERTAINMENT`: 文化体育娱乐 - `MEDIA_AND_INFORMATION`: 媒体信息 - `LOGISTICS`: 物流 - `TELECOMMUNICATIONS`: 电信 - `FINANCIAL_SERVICES`: 金融服务 - `CATERING_SERVICES`: 餐饮服务 - `SOFTWARE_TOOLS`: 软件工具 - `FRANCHISING_AND_INVESTMENT`: 加盟投资 - `BEAUTY_AND_COSMETICS`: 美容化妆 - `MOTHER_BABY_AND_PET`: 母婴宠物 - `DAILY_CHEMICALS`: 日化用品 - `PHYSICAL_BOOKS`: 实体书籍 - `SOCIAL_AND_COMMUNICATION`: 社交通讯 - `MEDICAL_INSTITUTIONS`: 医疗机构"
+    },
+    {
+      "name": "range",
+      "in": "query",
+      "type": "string",
+      "required": false,
+      "default": "DAY_30",
+      "desc": "时间范围。 可用值: - `DAY_30`:最近 30 天 - `DAY_90`:最近 90 天"
+    },
+    {
+      "name": "detailType",
+      "in": "query",
+      "type": "string",
+      "required": false,
+      "default": "VIDEO",
+      "desc": "资源类型。 可用值: - `VIDEO`: 视频 - `PRODUCT`: 商品"
+    },
+    {
+      "name": "page",
+      "in": "query",
+      "type": "integer",
+      "required": false,
+      "default": 1,
+      "desc": "页码。"
+    }
+  ],
+  "douyin.xingtu.cost_performance_analysis": [
+    {
+      "name": "oAuthorId",
+      "in": "query",
+      "type": "string",
+      "required": true,
+      "desc": "作者唯一ID。"
+    },
+    {
+      "name": "platform",
+      "in": "query",
+      "type": "string",
+      "required": false,
+      "default": "SHORT_VIDEO",
+      "desc": "平台类型。 可用值: - `SHORT_VIDEO`: 短视频 - `LIVE_STREAMING`: 直播 - `PICTURE_TEXT`: 图文 - `SHORT_DRAMA`: 短剧"
+    }
+  ],
+  "douyin.xingtu.creator_business_card": [
+    {
+      "name": "oAuthorId",
+      "in": "query",
+      "type": "string",
+      "required": true,
+      "desc": "作者唯一ID。"
+    }
+  ],
+  "douyin.xingtu.creator_channel_metrics": [
+    {
+      "name": "oAuthorId",
+      "in": "query",
+      "type": "string",
+      "required": true,
+      "desc": "作者唯一ID。"
+    },
+    {
+      "name": "platform",
+      "in": "query",
+      "type": "string",
+      "required": false,
+      "default": "SHORT_VIDEO",
+      "desc": "平台类型。 可用值: - `SHORT_VIDEO`: 短视频 - `LIVE_STREAMING`: 直播 - `PICTURE_TEXT`: 图文 - `SHORT_DRAMA`: 短剧"
+    }
+  ],
+  "douyin.xingtu.creator_commerce_spread_info": [
+    {
+      "name": "oAuthorId",
+      "in": "query",
+      "type": "string",
+      "required": true,
+      "desc": "作者唯一ID。"
+    }
+  ],
+  "douyin.xingtu.creator_contract_base_info": [
+    {
+      "name": "oAuthorId",
+      "in": "query",
+      "type": "string",
+      "required": true,
+      "desc": "作者唯一ID。"
+    },
+    {
+      "name": "range",
+      "in": "query",
+      "type": "string",
+      "required": false,
+      "default": "90",
+      "desc": "时间范围。 可用值: - `DAY_30`:最近 30 天 - `DAY_90`:最近 90 天"
+    }
+  ],
+  "douyin.xingtu.creator_link_metrics": [
+    {
+      "name": "oAuthorId",
+      "in": "query",
+      "type": "string",
+      "required": true,
+      "desc": "作者唯一ID。"
+    },
+    {
+      "name": "platform",
+      "in": "query",
+      "type": "string",
+      "required": false,
+      "default": "SHORT_VIDEO",
+      "desc": "平台类型。 可用值: - `SHORT_VIDEO`: 短视频 - `LIVE_STREAMING`: 直播 - `PICTURE_TEXT`: 图文 - `SHORT_DRAMA`: 短剧"
+    },
+    {
+      "name": "industryTag",
+      "in": "query",
+      "type": "string",
+      "required": false,
+      "default": "ALL",
+      "desc": "行业标签。 可用值: - `ALL`: 全部 - `ELECTRONICS_AND_APPLIANCES`: 电子与家电 - `FOOD_AND_BEVERAGE`: 食品与饮料 - `CLOTHING_AND_ACCESSORIES`: 服装与配饰 - `HEALTHCARE_AND_MEDICAL`: 医疗健康 - `BUSINESS_SERVICES`: 商业服务 - `LOCAL_SERVICES`: 本地服务 - `REAL_ESTATE`: 房地产 - `HOME_AND_BUILDING_MATERIALS`: 家居建材 - `EDUCATION_AND_TRAINING`: 教育培训 - `TRAVEL_AND_TOURISM`: 旅游观光 - `PUBLIC_SERVICES`: 公共服务 - `GAMES`: 游戏 - `RETAIL`: 零售 - `TRANSPORTATION_EQUIPMENT`: 运输设备 - `AUTOMOTIVE`: 汽车 - `AGRICULTURE_FORESTRY_FISHERY`: 农林牧渔 - `CHEMICAL_AND_ENERGY`: 化工能源 - `ELECTRONICS_AND_ELECTRICAL`: 电子电气 - `MACHINERY_EQUIPMENT`: 机械设备 - `CULTURE_SPORTS_ENTERTAINMENT`: 文化体育娱乐 - `MEDIA_AND_INFORMATION`: 媒体信息 - `LOGISTICS`: 物流 - `TELECOMMUNICATIONS`: 电信 - `FINANCIAL_SERVICES`: 金融服务 - `CATERING_SERVICES`: 餐饮服务 - `SOFTWARE_TOOLS`: 软件工具 - `FRANCHISING_AND_INVESTMENT`: 加盟投资 - `BEAUTY_AND_COSMETICS`: 美容化妆品 - `MOTHER_BABY_AND_PET`: 母婴宠物 - `DAILY_CHEMICALS`: 日化用品 - `PHYSICAL_BOOKS`: 实体书籍 - `SOCIAL_AND_COMMUNICATION`: 社交通讯 - `MEDICAL_INSTITUTIONS`: 医疗机构"
+    }
+  ],
+  "douyin.xingtu.creator_link_structure": [
+    {
+      "name": "oAuthorId",
+      "in": "query",
+      "type": "string",
+      "required": true,
+      "desc": "作者唯一ID。"
+    },
+    {
+      "name": "platform",
+      "in": "query",
+      "type": "string",
+      "required": false,
+      "default": "SHORT_VIDEO",
+      "desc": "平台类型。 可用值: - `SHORT_VIDEO`: 短视频 - `LIVE_STREAMING`: 直播 - `PICTURE_TEXT`: 图文 - `SHORT_DRAMA`: 短剧"
+    }
+  ],
+  "douyin.xingtu.creator_order_experience": [
+    {
+      "name": "oAuthorId",
+      "in": "query",
+      "type": "string",
+      "required": true,
+      "desc": "作者唯一ID。"
+    },
+    {
+      "name": "period",
+      "in": "query",
+      "type": "string",
+      "required": false,
+      "default": "DAY_30",
+      "desc": "时间周期。 可用值: - `DAY_30`:最近 30 天 - `DAY_90`:最近 90 天"
+    }
+  ],
+  "douyin.xingtu.creator_profile": [
+    {
+      "name": "oAuthorId",
+      "in": "query",
+      "type": "string",
+      "required": true,
+      "desc": "作者唯一ID。"
+    },
+    {
+      "name": "platform",
+      "in": "query",
+      "type": "string",
+      "required": false,
+      "default": "SHORT_VIDEO",
+      "desc": "平台类型。 可用值: - `SHORT_VIDEO`: 短视频 - `LIVE_STREAMING`: 直播 - `PICTURE_TEXT`: 图文 - `SHORT_DRAMA`: 短剧"
+    }
+  ],
+  "douyin.xingtu.creator_search_light": [
+    {
+      "name": "keyword",
+      "in": "query",
+      "type": "string",
+      "required": true,
+      "desc": "搜索关键词。"
+    },
+    {
+      "name": "platformSource",
+      "in": "query",
+      "type": "string",
+      "required": true,
+      "desc": "平台来源。 可用值: - `_1`: 抖音 - `_2`: 头条 - `_3`: 西瓜"
+    },
+    {
+      "name": "page",
+      "in": "query",
+      "type": "integer",
+      "required": true,
+      "desc": "页码。"
+    }
+  ],
+  "douyin.xingtu.creator_search": [
+    {
+      "name": "keyword",
+      "in": "query",
+      "type": "string",
+      "required": false,
+      "desc": "搜索关键词。"
+    },
+    {
+      "name": "page",
+      "in": "query",
+      "type": "integer",
+      "required": false,
+      "default": 1,
+      "desc": "用于分页的页码。"
+    },
+    {
+      "name": "searchType",
+      "in": "query",
+      "type": "string",
+      "required": false,
+      "default": "NICKNAME",
+      "desc": "搜索条件类型。 可用值: - `NICKNAME`: 按昵称 - `CONTENT`: 按内容"
+    },
+    {
+      "name": "followerRange",
+      "in": "query",
+      "type": "string",
+      "required": false,
+      "desc": "粉丝数量范围(例如:10-100)。"
+    },
+    {
+      "name": "kolPriceType",
+      "in": "query",
+      "type": "string",
+      "required": false,
+      "desc": "KOL价格类型。 可选值: - `VIDEO_1_20S`: 视频1-20秒 - `VIDEO_21_60S`: 视频21-60秒 - `VIDEO_OVER_60S`: 视频60秒以上 - `CUSTOM_SHORT_DRAMA_EPISODE`: 短剧集 - `NATURAL_PLAY_CPM`: 自然播放CPM - `SHORT_LIVE_SEEDING_VIDEO`: 短视频种草视频 - `SHORT_LIVE_WARMUP_VIDEO`: 短视频预热视频 - `CELEBRITY_SHORT_LIVE_SEEDING`: 明星短视频种草 - `CELEBRITY_SHORT_LIVE_WARMUP`: 明星短视频预热 - `CELEBRITY_VIDEO`: 明星视频 - `COLLECTION_VIDEO`: 合集视频 - `DOUYIN_SHORT_VIDEO_CO_CREATION_MAIN_CREATOR`: 抖音短视频共创-主创 - `DOUYIN_SHORT_VIDEO_CO_CREATION_PARTICIPANT`: 抖音短视频共创-参与方"
+    },
+    {
+      "name": "kolPriceRange",
+      "in": "query",
+      "type": "string",
+      "required": false,
+      "desc": "KOL 价格范围(例如:10000-50000)。"
+    },
+    {
+      "name": "contentTag",
+      "in": "query",
+      "type": "string",
+      "required": false,
+      "desc": "创作者分类筛选。传入星图页面的分类标签,用逗号分隔。一级标签映射为tag,二级标签映射为tag_level_two。旧的tag-1和tag_level_two-7 ID格式已弃用。"
+    }
+  ],
+  "douyin.xingtu.creator_side_base_info": [
+    {
+      "name": "oAuthorId",
+      "in": "query",
+      "type": "string",
+      "required": true,
+      "desc": "作者唯一ID。"
+    }
+  ],
+  "douyin.xingtu.creator_visibility_status": [
+    {
+      "name": "oAuthorId",
+      "in": "query",
+      "type": "string",
+      "required": true,
+      "desc": "作者唯一ID。"
+    },
+    {
+      "name": "platform",
+      "in": "query",
+      "type": "string",
+      "required": false,
+      "default": "SHORT_VIDEO",
+      "desc": "平台类型。 可用值: - `SHORT_VIDEO`: 短视频 - `LIVE_STREAMING`: 直播 - `PICTURE_TEXT`: 图文 - `SHORT_DRAMA`: 短剧"
+    }
+  ],
+  "douyin.xingtu.follower_distribution": [
+    {
+      "name": "oAuthorId",
+      "in": "query",
+      "type": "string",
+      "required": true,
+      "desc": "作者唯一ID。"
+    },
+    {
+      "name": "authorType",
+      "in": "query",
+      "type": "string",
+      "required": false,
+      "default": "FAN",
+      "desc": "作者类型过滤器。 可用值: - `FAN`: 粉丝 - `DIE_HARD_FAN`: 铁杆粉丝"
+    }
+  ],
+  "douyin.xingtu.follower_growth_trend": [
+    {
+      "name": "oAuthorId",
+      "in": "query",
+      "type": "string",
+      "required": true,
+      "desc": "作者唯一ID。"
+    },
+    {
+      "name": "startDate",
+      "in": "query",
+      "type": "string",
+      "required": true,
+      "desc": "开始日期 (yyyy-MM-dd)。"
+    },
+    {
+      "name": "endDate",
+      "in": "query",
+      "type": "string",
+      "required": true,
+      "desc": "结束日期 (yyyy-MM-dd)。"
+    }
+  ],
+  "douyin.xingtu.item_report_analysis": [
+    {
+      "name": "itemId",
+      "in": "query",
+      "type": "string",
+      "required": true,
+      "desc": "项目的唯一 ID。"
+    }
+  ],
+  "douyin.xingtu.item_report_trends": [
+    {
+      "name": "itemId",
+      "in": "query",
+      "type": "string",
+      "required": true,
+      "desc": "项目的唯一 ID。"
+    }
+  ],
+  "douyin.xingtu.live_statistics": [
+    {
+      "name": "oAuthorId",
+      "in": "query",
+      "type": "string",
+      "required": true,
+      "desc": "作者唯一ID。"
+    },
+    {
+      "name": "liveType",
+      "in": "query",
+      "type": "string",
+      "required": false,
+      "default": "1",
+      "desc": "直播间类型筛选。 可选值: - `ALL`:所有直播间 - `GAME`:游戏直播间 - `ECOMMERCE`:电商直播间 - `OTHER`:其他直播间"
+    },
+    {
+      "name": "period",
+      "in": "query",
+      "type": "string",
+      "required": false,
+      "default": "30",
+      "desc": "直播数据时间段。 可选值: - `DAY_30`:最近30天 - `DAY_90`:最近90天"
+    },
+    {
+      "name": "onlyStarOrder",
+      "in": "query",
+      "type": "boolean",
+      "required": false,
+      "default": false,
+      "desc": "是否仅包含巨量星图市场订单。"
+    },
+    {
+      "name": "flowType",
+      "in": "query",
+      "type": "string",
+      "required": false,
+      "default": "0",
+      "desc": "流程类型过滤器。 可用值: - `EXCLUDE`:排除 - `INCLUDE`:包含"
+    }
+  ],
+  "douyin.xingtu.live_watch_distribution": [
+    {
+      "name": "oAuthorId",
+      "in": "query",
+      "type": "string",
+      "required": true,
+      "desc": "作者唯一ID。"
+    },
+    {
+      "name": "liveCrowdType",
+      "in": "query",
+      "type": "string",
+      "required": false,
+      "default": "2",
+      "desc": "直播观众画像类型。 可选值: - `AUDIENCE`:观众画像 - `FANS`:粉丝画像"
+    },
+    {
+      "name": "liveType",
+      "in": "query",
+      "type": "string",
+      "required": false,
+      "default": "1",
+      "desc": "直播间类型筛选。 可选值: - `ALL`:所有直播间 - `GAME`:游戏直播间 - `ECOMMERCE`:电商直播间 - `OTHER`:其他直播间"
+    }
+  ],
+  "douyin.xingtu.marketing_metrics": [
+    {
+      "name": "oAuthorId",
+      "in": "query",
+      "type": "string",
+      "required": true,
+      "desc": "作者唯一ID。"
+    },
+    {
+      "name": "platform",
+      "in": "query",
+      "type": "string",
+      "required": false,
+      "default": "SHORT_VIDEO",
+      "desc": "平台类型。 可用值: - `SHORT_VIDEO`: 短视频 - `LIVE_STREAMING`: 直播 - `PICTURE_TEXT`: 图文 - `SHORT_DRAMA`: 短剧"
+    }
+  ],
+  "douyin.xingtu.recommended_videos": [
+    {
+      "name": "oAuthorId",
+      "in": "query",
+      "type": "string",
+      "required": true,
+      "desc": "作者唯一ID。"
+    },
+    {
+      "name": "platform",
+      "in": "query",
+      "type": "string",
+      "required": false,
+      "default": "SHORT_VIDEO",
+      "desc": "平台类型。 可用值: - `SHORT_VIDEO`: 短视频 - `LIVE_STREAMING`: 直播 - `PICTURE_TEXT`: 图文 - `SHORT_DRAMA`: 短剧"
+    }
+  ],
+  "douyin.xingtu.showcase_items": [
+    {
+      "name": "oAuthorId",
+      "in": "query",
+      "type": "string",
+      "required": true,
+      "desc": "作者唯一ID。"
+    },
+    {
+      "name": "platform",
+      "in": "query",
+      "type": "string",
+      "required": false,
+      "default": "SHORT_VIDEO",
+      "desc": "平台类型。 可用值: - `SHORT_VIDEO`: 短视频 - `LIVE_STREAMING`: 直播 - `PICTURE_TEXT`: 图文 - `SHORT_DRAMA`: 短剧"
+    },
+    {
+      "name": "onlyAssign",
+      "in": "query",
+      "type": "boolean",
+      "required": false,
+      "default": false,
+      "desc": "是否仅包含已分配的项目。"
+    },
+    {
+      "name": "flowType",
+      "in": "query",
+      "type": "string",
+      "required": false,
+      "default": "EXCLUDE",
+      "desc": "流程类型过滤器。 可用值: - `EXCLUDE`:排除 - `INCLUDE`:包含"
+    }
+  ],
+  "douyin.xingtu.spread_metrics": [
+    {
+      "name": "oAuthorId",
+      "in": "query",
+      "type": "string",
+      "required": true,
+      "desc": "作者唯一ID。"
+    },
+    {
+      "name": "platform",
+      "in": "query",
+      "type": "string",
+      "required": false,
+      "default": "SHORT_VIDEO",
+      "desc": "平台类型。 可用值: - `SHORT_VIDEO`: 短视频 - `LIVE_STREAMING`: 直播 - `PICTURE_TEXT`: 图文 - `SHORT_DRAMA`: 短剧"
+    },
+    {
+      "name": "range",
+      "in": "query",
+      "type": "string",
+      "required": false,
+      "default": "DAY_30",
+      "desc": "时间范围。 可用值: - `DAY_30`:最近 30 天 - `DAY_90`:最近 90 天"
+    },
+    {
+      "name": "type",
+      "in": "query",
+      "type": "string",
+      "required": false,
+      "default": "PERSONAL_VIDEO",
+      "desc": "视频类型。 可用值: - `PERSONAL_VIDEO`: 个人视频 - `XINTU_VIDEO`: 星图视频"
+    },
+    {
+      "name": "onlyAssign",
+      "in": "query",
+      "type": "boolean",
+      "required": false,
+      "default": false,
+      "desc": "是否仅包含已分配的视频。"
+    },
+    {
+      "name": "flowType",
+      "in": "query",
+      "type": "string",
+      "required": false,
+      "default": "EXCLUDE",
+      "desc": "流程类型过滤器。 可用值: - `EXCLUDE`:排除 - `INCLUDE`:包含"
+    }
+  ],
+  "douyin.xingtu.video_details": [
+    {
+      "name": "itemId",
+      "in": "query",
+      "type": "string",
+      "required": true,
+      "desc": "项目的唯一 ID。"
+    }
+  ],
+  "douyin.xingtu.video_distribution": [
+    {
+      "name": "oAuthorId",
+      "in": "query",
+      "type": "string",
+      "required": true,
+      "desc": "作者唯一ID。"
+    },
+    {
+      "name": "platform",
+      "in": "query",
+      "type": "string",
+      "required": false,
+      "default": "SHORT_VIDEO",
+      "desc": "平台类型。 可用值: - `SHORT_VIDEO`: 短视频 - `LIVE_STREAMING`: 直播 - `PICTURE_TEXT`: 图文 - `SHORT_DRAMA`: 短剧"
+    }
   ]
 }

File diff suppressed because it is too large
+ 338 - 1
claude-code/claude-code-voc-intelligence/mcp/catalog/params/xiaohongshu.json


+ 1433 - 33
claude-code/claude-code-voc-intelligence/mcp/catalog/voc-social-endpoints.json

@@ -1,6 +1,6 @@
 {
-  "version": "1.2.0",
-  "updatedAt": "2026-06-22",
+  "version": "1.4.0",
+  "updatedAt": "2026-06-26",
   "gateway": {
     "social": {
       "baseUrl": "https://server.fmode.cn/api/voc-social",
@@ -9,98 +9,140 @@
       "billing": "每次转发调用扣除 1 次社交平台 API 额度(缓存命中也会计费)。",
       "note": "这是一个通用转发网关:任意 proxyPath 都会被透传到我们的中转上游。本清单列出已验证的抖音、小红书常用接口;未列出的接口可以直接用 voc_api_call 传 rawPath + method + params 调用,无需改代码。",
       "rawPathHint": "调用未在清单中的接口时,把相对路径填到 voc_api_call 的 rawPath,例如 douyin/search/fetch_general_search_v2,并按对应平台的参数规则拼 query/body。"
+    },
+    "ecommerce": {
+      "baseUrl": "https://server.fmode.cn/api/voc-e-commerce",
+      "auth": "Authorization: Bearer <NewAPI fmode-api token(sk- 开头,优先)或平台 sessionToken(回退)>",
+      "upstream": "公司 voc-e-commerce 代理,按 proxyPath 透传到创作者数据上游,对外不暴露任何上游供应商名称。",
+      "billing": "每次成功调用按平台规则计费一次;计费优先走 NewAPI(fmode-api)额度,sk- token 鉴权失败时自动回退平台 sessionToken。402=余额不足(引导 fmode-api 充值),401=token 缺失/失效,403=账号禁用/无权限。",
+      "note": "创作者数据网关:清单内已登记抖音星图、小红书蒲公英(PGY)的创作者搜索、画像、受众/粉丝分布、内容与评论关键词、笔记/视频绩效与性价比等结构化数据(channel=ecommerce)。这是公开市场层面的创作者经营数据,服务创作者生态理解、竞对达人布局、受众匹配与内容方向验证,不用于替用户做投放采买决策。endpoint 带 channel=\"ecommerce\" 时 voc_api_call 自动选用本网关;清单里没有的接口可直接用 voc_api_call 传 rawPath + method + params + channel=\"ecommerce\" 调用,无需改代码。",
+      "rawPathHint": "调用未登记的电商接口时,把 proxyPath 传给 voc_api_call 的 rawPath 并加 channel=\"ecommerce\",例如 douyin-xingtu/gw/api/data_sp/author_cp_info/v1。"
     }
   },
   "platforms": [
     {
       "key": "douyin",
       "label": "抖音",
-      "status": "verified"
+      "status": "verified",
+      "channel": "social"
     },
     {
       "key": "tiktok",
       "label": "TikTok",
-      "status": "available"
+      "status": "available",
+      "channel": "social"
     },
     {
       "key": "instagram",
       "label": "Instagram",
-      "status": "available"
+      "status": "available",
+      "channel": "social"
     },
     {
       "key": "linkedin",
       "label": "LinkedIn",
-      "status": "available"
+      "status": "available",
+      "channel": "social"
     },
     {
       "key": "weibo",
       "label": "微博",
-      "status": "available"
+      "status": "available",
+      "channel": "social"
     },
     {
       "key": "bilibili",
       "label": "哔哩哔哩",
-      "status": "available"
+      "status": "available",
+      "channel": "social"
     },
     {
       "key": "xiaohongshu",
       "label": "小红书",
-      "status": "verified"
+      "status": "verified",
+      "channel": "social"
     },
     {
       "key": "youtube",
       "label": "YouTube",
-      "status": "available"
+      "status": "available",
+      "channel": "social"
     },
     {
       "key": "kuaishou",
       "label": "快手",
-      "status": "available"
+      "status": "available",
+      "channel": "social"
     },
     {
       "key": "zhihu",
       "label": "知乎",
-      "status": "available"
+      "status": "available",
+      "channel": "social"
     },
     {
       "key": "reddit",
       "label": "Reddit",
-      "status": "available"
+      "status": "available",
+      "channel": "social"
     },
     {
       "key": "wechat",
       "label": "微信/视频号",
-      "status": "available"
+      "status": "available",
+      "channel": "social"
     },
     {
       "key": "pipixia",
       "label": "皮皮虾",
-      "status": "available"
+      "status": "available",
+      "channel": "social"
     },
     {
       "key": "lemon8",
       "label": "Lemon8",
-      "status": "available"
+      "status": "available",
+      "channel": "social"
     },
     {
       "key": "twitter",
       "label": "Twitter/X",
-      "status": "available"
+      "status": "available",
+      "channel": "social"
     },
     {
       "key": "threads",
       "label": "Threads",
-      "status": "available"
+      "status": "available",
+      "channel": "social"
     },
     {
       "key": "toutiao",
       "label": "今日头条",
-      "status": "available"
+      "status": "available",
+      "channel": "social"
     },
     {
       "key": "xigua",
       "label": "西瓜视频",
-      "status": "available"
+      "status": "available",
+      "channel": "social"
+    },
+    {
+      "key": "douyin",
+      "label": "抖音星图",
+      "channel": "ecommerce",
+      "status": "verified",
+      "idField": "star_id",
+      "detailParam": "oAuthorId"
+    },
+    {
+      "key": "xiaohongshu",
+      "label": "小红书蒲公英(PGY 商单博主)",
+      "channel": "ecommerce",
+      "status": "verified",
+      "idField": "userId",
+      "detailParam": "userId"
     }
   ],
   "paramStore": "params/<platform>.json(按需取,每个文件以接口 id 为键存完整参数 schema)",
@@ -723,8 +765,8 @@
       "platform": "xiaohongshu",
       "channel": "social",
       "title": "小红书笔记评论",
-      "summary": "按 note_id 拉取小红书笔记的一级评论。VOC 主力接口。",
-      "proxyPath": "xiaohongshu/app/get_note_comments",
+      "summary": "按 note_id 拉取小红书笔记的一级评论(App V2,VOC 口碑主力接口)。",
+      "proxyPath": "xiaohongshu/app_v2/get_note_comments",
       "method": "GET",
       "paramsIn": "query",
       "tags": [
@@ -742,34 +784,34 @@
           "in": "query",
           "type": "string",
           "required": true,
-          "desc": "笔记 id(note_id)。"
+          "desc": "笔记 id(note_id),来自 search_notes 返回的 note.id。"
         },
         {
-          "name": "start",
+          "name": "share_text",
           "in": "query",
           "type": "string",
           "required": false,
           "default": "",
-          "desc": "分页游标,首页留空,翻页用上一次返回的 start。"
+          "desc": "可选:小红书分享文案/链接,与 note_id 二选一。"
         },
         {
-          "name": "sort_strategy",
+          "name": "xsec_token",
           "in": "query",
-          "type": "integer",
+          "type": "string",
           "required": false,
-          "default": 1,
-          "desc": "排序:1 默认。"
+          "default": "",
+          "desc": "可选安全令牌,来自 search_notes 返回的 note.xsec_token;部分笔记风控需要。"
         }
       ],
-      "responseHint": "返回评论列表,含 comment_id、文本、点赞、子评论数;翻页用返回的 start。"
+      "responseHint": "返回评论列表,含 comment_id、文本、点赞、子评论数;翻页用返回的游标。"
     },
     {
       "id": "xiaohongshu.sub_comments",
       "platform": "xiaohongshu",
       "channel": "social",
       "title": "小红书评论回复(楼中楼)",
-      "summary": "按 note_id + comment_id 拉取某条评论下的回复,用于深挖讨论。",
-      "proxyPath": "xiaohongshu/app/get_sub_comments",
+      "summary": "按 note_id + comment_id 拉取某条评论下的回复(App V2),用于深挖讨论。",
+      "proxyPath": "xiaohongshu/app_v2/get_note_sub_comments",
       "method": "GET",
       "paramsIn": "query",
       "tags": [
@@ -835,7 +877,7 @@
           "in": "query",
           "type": "string",
           "required": true,
-          "desc": "用户 id(user_id),来自笔记/搜索返回。"
+          "desc": "用户 id(24 位 hex),来自 search_notes 返回的 note.user.userid;注意不是数字 red_id。"
         }
       ],
       "responseHint": "返回用户资料对象,含粉丝数、获赞收藏、简介。"
@@ -20008,6 +20050,1364 @@
       "requiredParams": [
         "username"
       ]
+    },
+    {
+      "id": "douyin.xingtu.audience_distribution",
+      "platform": "douyin",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "抖音星图·受众分布",
+      "summary": "获取抖音巨量星图受众分布数据,包括人口统计和兴趣基础的受众细分,用于创作者评估、活动规划和市场研究。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "douyin-xingtu/gw/api/data_sp/author_audience_distribution/v1",
+      "requiredParams": [
+        "oAuthorId"
+      ],
+      "tags": [
+        "抖音",
+        "douyin",
+        "星图",
+        "xingtu",
+        "达人",
+        "电商",
+        "ecommerce",
+        "audience",
+        "distribution",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "douyin.xingtu.audience_touchpoint_distribution",
+      "platform": "douyin",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "抖音星图·受众触点分布",
+      "summary": "获取抖音巨量星图受众触点分布数据,包括细分细分、受众构成和分布信号,用于创作者评估、活动规划和市场研究。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "douyin-xingtu/gw/api/data_sp/author_touch_distribution/v1",
+      "requiredParams": [
+        "oAuthorId"
+      ],
+      "tags": [
+        "抖音",
+        "douyin",
+        "星图",
+        "xingtu",
+        "达人",
+        "电商",
+        "ecommerce",
+        "audience",
+        "touchpoint",
+        "distribution",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "douyin.xingtu.comment_keyword_analysis",
+      "platform": "douyin",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "抖音星图·评论关键词分析",
+      "summary": "获取抖音巨量星图KOL评论关键词分析数据,包括核心指标、趋势信号和性能指标,用于受众语言分析和评论主题研究。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "douyin-xingtu/gw/api/data/get_author_hot_comment_tokens/v1",
+      "requiredParams": [
+        "oAuthorId"
+      ],
+      "tags": [
+        "抖音",
+        "douyin",
+        "星图",
+        "xingtu",
+        "达人",
+        "电商",
+        "ecommerce",
+        "comment",
+        "keyword",
+        "analysis",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "douyin.xingtu.commerce_seeding_base_info",
+      "platform": "douyin",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "抖音星图·商业种草基础信息",
+      "summary": "获取抖音巨量星图作者商业种草基础信息数据,包括基线指标、商业信号和种草指标,用于产品种草分析、创作者审查和活动策划。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "douyin-xingtu/gw/api/aggregator/get_author_commerce_seed_base_info/v1",
+      "requiredParams": [
+        "oAuthorId"
+      ],
+      "tags": [
+        "抖音",
+        "douyin",
+        "星图",
+        "xingtu",
+        "达人",
+        "电商",
+        "ecommerce",
+        "commerce",
+        "seeding",
+        "base",
+        "info",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "douyin.xingtu.content_keyword_analysis",
+      "platform": "douyin",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "抖音星图·内容关键词分析",
+      "summary": "获取抖音巨量星图KOL内容关键词分析数据,包括核心指标、趋势信号和性能指标,用于内容主题分析和创作者定位研究。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "douyin-xingtu/gw/api/gauthor/get_author_content_hot_keywords/v1",
+      "requiredParams": [
+        "oAuthorId"
+      ],
+      "tags": [
+        "抖音",
+        "douyin",
+        "星图",
+        "xingtu",
+        "达人",
+        "电商",
+        "ecommerce",
+        "content",
+        "keyword",
+        "analysis",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "douyin.xingtu.conversion_analysis",
+      "platform": "douyin",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "抖音星图·转化分析",
+      "summary": "获取抖音巨量星图转化分析数据,包括转化效率和商业性能指标,用于创作者评估、活动规划和市场研究。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "douyin-xingtu/gw/api/data_sp/get_author_convert_ability/v1",
+      "requiredParams": [
+        "oAuthorId"
+      ],
+      "tags": [
+        "抖音",
+        "douyin",
+        "星图",
+        "xingtu",
+        "达人",
+        "电商",
+        "ecommerce",
+        "conversion",
+        "analysis",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "douyin.xingtu.conversion_resources",
+      "platform": "douyin",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "抖音星图·转化资源",
+      "summary": "获取抖音巨量星图转化资源数据,包括与抖音星图创作者转化活动相关的商品,用于商业分析和活动优化。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "douyin-xingtu/gw/api/data_sp/get_author_convert_videos_or_products/v1",
+      "requiredParams": [
+        "oAuthorId"
+      ],
+      "tags": [
+        "抖音",
+        "douyin",
+        "星图",
+        "xingtu",
+        "达人",
+        "电商",
+        "ecommerce",
+        "conversion",
+        "resources",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "douyin.xingtu.cost_performance_analysis",
+      "platform": "douyin",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "抖音星图·性价比分析",
+      "summary": "获取抖音巨量星图成本性能分析数据,包括定价、曝光和参与效率指标,用于创作者评估、活动规划和市场研究。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "douyin-xingtu/gw/api/data_sp/author_cp_info/v1",
+      "requiredParams": [
+        "oAuthorId"
+      ],
+      "tags": [
+        "抖音",
+        "douyin",
+        "星图",
+        "xingtu",
+        "达人",
+        "电商",
+        "ecommerce",
+        "cost",
+        "performance",
+        "analysis",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "douyin.xingtu.creator_business_card",
+      "platform": "douyin",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "抖音星图·创作者名片",
+      "summary": "获取抖音巨量星图创作者名片数据,包括名片资料字段,用于创作者查询、审核及活动资格评估。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "douyin-xingtu/gw/api/gauthor/author_get_business_card_info/v1",
+      "requiredParams": [
+        "oAuthorId"
+      ],
+      "tags": [
+        "抖音",
+        "douyin",
+        "星图",
+        "xingtu",
+        "达人",
+        "电商",
+        "ecommerce",
+        "creator",
+        "business",
+        "card",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "douyin.xingtu.creator_channel_metrics",
+      "platform": "douyin",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "抖音星图·创作者渠道指标",
+      "summary": "获取抖音巨量星图创作者渠道指标数据,包括平台分布和渠道性能数据,用于创作者评估。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "douyin-xingtu/gw/api/author/get_author_platform_channel_info_v2/v1",
+      "requiredParams": [
+        "oAuthorId"
+      ],
+      "tags": [
+        "抖音",
+        "douyin",
+        "星图",
+        "xingtu",
+        "达人",
+        "电商",
+        "ecommerce",
+        "creator",
+        "channel",
+        "metrics",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "douyin.xingtu.creator_commerce_spread_info",
+      "platform": "douyin",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "抖音星图·创作者电商传播信息",
+      "summary": "获取抖音巨量星图作者商业传播信息数据,包括传播指标,用于创作者评估以进行活动策划和媒体购买。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "douyin-xingtu/gw/api/aggregator/get_author_commerce_spread_info/v1",
+      "requiredParams": [
+        "oAuthorId"
+      ],
+      "tags": [
+        "抖音",
+        "douyin",
+        "星图",
+        "xingtu",
+        "达人",
+        "电商",
+        "ecommerce",
+        "creator",
+        "commerce",
+        "spread",
+        "info",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "douyin.xingtu.creator_contract_base_info",
+      "platform": "douyin",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "抖音星图·创作者合同基础信息",
+      "summary": "获取抖音巨量星图创作者合同基础信息数据,包括合同相关基线指标和近期合作信号,用于创作者审核、活动策划和市场研究。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "douyin-xingtu/gw/api/aggregator/get_author_contract_base_info",
+      "requiredParams": [
+        "oAuthorId"
+      ],
+      "tags": [
+        "抖音",
+        "douyin",
+        "星图",
+        "xingtu",
+        "达人",
+        "电商",
+        "ecommerce",
+        "creator",
+        "contract",
+        "base",
+        "info",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "douyin.xingtu.creator_link_metrics",
+      "platform": "douyin",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "抖音星图·创作者链接指标",
+      "summary": "获取抖音巨量星图创作者链接指标数据,包括创作者排名、流量结构和相关性能指标,用于创作者评估、活动规划和市场研究。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "douyin-xingtu/gw/api/data_sp/get_author_link_info/v1",
+      "requiredParams": [
+        "oAuthorId"
+      ],
+      "tags": [
+        "抖音",
+        "douyin",
+        "星图",
+        "xingtu",
+        "达人",
+        "电商",
+        "ecommerce",
+        "creator",
+        "link",
+        "metrics",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "douyin.xingtu.creator_link_structure",
+      "platform": "douyin",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "抖音星图·创作者链接结构",
+      "summary": "获取抖音巨量星图创作者链接结构数据,包括参与度和转化指标,用于创作者表现分析。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "douyin-xingtu/gw/api/data_sp/author_link_struct/v1",
+      "requiredParams": [
+        "oAuthorId"
+      ],
+      "tags": [
+        "抖音",
+        "douyin",
+        "星图",
+        "xingtu",
+        "达人",
+        "电商",
+        "ecommerce",
+        "creator",
+        "link",
+        "structure",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "douyin.xingtu.creator_order_experience",
+      "platform": "douyin",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "抖音星图·创作者订单经验",
+      "summary": "获取抖音巨量星图创作者订单体验数据,包括商业历史和交易相关指标,用于创作者评估、活动规划和市场研究。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "douyin-xingtu/gw/api/aggregator/get_author_order_experience/v1",
+      "requiredParams": [
+        "oAuthorId"
+      ],
+      "tags": [
+        "抖音",
+        "douyin",
+        "星图",
+        "xingtu",
+        "达人",
+        "电商",
+        "ecommerce",
+        "creator",
+        "order",
+        "experience",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "douyin.xingtu.creator_profile",
+      "platform": "douyin",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "抖音星图·创作者资料",
+      "summary": "获取抖音巨量星图创作者资料数据,包括受众和定价数据,用于网红审核、基准分析和活动规划。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "douyin-xingtu/gw/api/author/get_author_base_info/v1",
+      "requiredParams": [
+        "oAuthorId"
+      ],
+      "tags": [
+        "抖音",
+        "douyin",
+        "星图",
+        "xingtu",
+        "达人",
+        "电商",
+        "ecommerce",
+        "creator",
+        "profile",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "douyin.xingtu.creator_search",
+      "platform": "douyin",
+      "channel": "ecommerce",
+      "wave": "search",
+      "title": "抖音星图·创作者搜索",
+      "summary": "获取抖音巨量星图创作者搜索数据,包括筛选条件、返回资料和受众信息,用于发现、比较和建立候选名单。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "douyin-xingtu/gw/api/gsearch/search_for_author_square/v1",
+      "requiredParams": [],
+      "tags": [
+        "抖音",
+        "douyin",
+        "星图",
+        "xingtu",
+        "达人",
+        "电商",
+        "ecommerce",
+        "creator",
+        "search"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "douyin.xingtu.creator_search_light",
+      "platform": "douyin",
+      "channel": "ecommerce",
+      "wave": "search",
+      "title": "抖音星图·创作者搜索轻量版",
+      "summary": "获取抖音巨量星图KOL关键词搜索数据,包括匹配创作者和发现数据,用于创作者来源和建立候选名单。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "douyin-xingtu/search-kol-simple/v1",
+      "requiredParams": [
+        "keyword",
+        "platformSource",
+        "page"
+      ],
+      "tags": [
+        "抖音",
+        "douyin",
+        "星图",
+        "xingtu",
+        "达人",
+        "电商",
+        "ecommerce",
+        "creator",
+        "search",
+        "light"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "douyin.xingtu.creator_side_base_info",
+      "platform": "douyin",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "抖音星图·创作者侧基础信息",
+      "summary": "获取抖音巨量星图作者侧边基础信息数据,包括创作者主页侧边卡片显示的30天粉丝增长率。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "douyin-xingtu/gw/api/aggregator/get_author_side_base_info/v1",
+      "requiredParams": [
+        "oAuthorId"
+      ],
+      "tags": [
+        "抖音",
+        "douyin",
+        "星图",
+        "xingtu",
+        "达人",
+        "电商",
+        "ecommerce",
+        "creator",
+        "side",
+        "base",
+        "info",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "douyin.xingtu.creator_visibility_status",
+      "platform": "douyin",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "抖音星图·创作者可见性状态",
+      "summary": "获取抖音巨量星图创作者可见性状态数据,包括可用状态、发现资格和活动显示信号,用于创作者评估、活动规划和市场研究。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "douyin-xingtu/gw/api/data_sp/check_author_display/v1",
+      "requiredParams": [
+        "oAuthorId"
+      ],
+      "tags": [
+        "抖音",
+        "douyin",
+        "星图",
+        "xingtu",
+        "达人",
+        "电商",
+        "ecommerce",
+        "creator",
+        "visibility",
+        "status",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "douyin.xingtu.follower_distribution",
+      "platform": "douyin",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "抖音星图·粉丝分布",
+      "summary": "获取抖音巨量星图粉丝分布数据,包括受众细分以及位置和人口统计细分,用于创作者评估、活动规划和市场研究。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "douyin-xingtu/gw/api/data_sp/get_author_fans_distribution/v1",
+      "requiredParams": [
+        "oAuthorId"
+      ],
+      "tags": [
+        "抖音",
+        "douyin",
+        "星图",
+        "xingtu",
+        "达人",
+        "电商",
+        "ecommerce",
+        "follower",
+        "distribution",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "douyin.xingtu.follower_growth_trend",
+      "platform": "douyin",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "抖音星图·粉丝增长趋势",
+      "summary": "获取抖音巨量星图粉丝增长趋势数据,包括历史受众随时间变化,用于创作者评估、活动策划和市场研究。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "douyin-xingtu/gw/api/data_sp/get_author_daily_fans/v1",
+      "requiredParams": [
+        "oAuthorId",
+        "startDate",
+        "endDate"
+      ],
+      "tags": [
+        "抖音",
+        "douyin",
+        "星图",
+        "xingtu",
+        "达人",
+        "电商",
+        "ecommerce",
+        "follower",
+        "growth",
+        "trend",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "douyin.xingtu.item_report_analysis",
+      "platform": "douyin",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "抖音星图·视频报告分析",
+      "summary": "获取抖音巨量星图视频报告分析数据,包括表现解读,用于创作者评估、活动策划和市场研究。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "douyin-xingtu/gw/api/data_sp/item_report_th_analysis/v1",
+      "requiredParams": [
+        "itemId"
+      ],
+      "tags": [
+        "抖音",
+        "douyin",
+        "星图",
+        "xingtu",
+        "达人",
+        "电商",
+        "ecommerce",
+        "item",
+        "report",
+        "analysis",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "douyin.xingtu.item_report_trends",
+      "platform": "douyin",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "抖音星图·视频报告趋势",
+      "summary": "获取抖音巨量星图视频报告趋势数据,包括基于时间的视频表现指标变化,用于创作者评估、活动策划和市场研究。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "douyin-xingtu/gw/api/data_sp/item_report_trend/v1",
+      "requiredParams": [
+        "itemId"
+      ],
+      "tags": [
+        "抖音",
+        "douyin",
+        "星图",
+        "xingtu",
+        "达人",
+        "电商",
+        "ecommerce",
+        "item",
+        "report",
+        "trends",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "douyin.xingtu.live_statistics",
+      "platform": "douyin",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "抖音星图·直播统计",
+      "summary": "获取抖音巨量星图直播首页统计数据,包括近期直播间数量、平均观看人数、ACU、PCU、观看时长、粉丝观看率、互动率、电商范围及转化指标,用于直播创作者评估和活动策划。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "douyin-xingtu/gw/api/aggregator/get_author_live_statistics/v1",
+      "requiredParams": [
+        "oAuthorId"
+      ],
+      "tags": [
+        "抖音",
+        "douyin",
+        "星图",
+        "xingtu",
+        "达人",
+        "电商",
+        "ecommerce",
+        "live",
+        "statistics",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "douyin.xingtu.live_watch_distribution",
+      "platform": "douyin",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "抖音星图·直播观看分布",
+      "summary": "获取抖音巨量星图直播首页观看分布数据,包括粉丝或观众画像细分,如性别、年龄、城市等级、省份、设备品牌、兴趣标签及人群总结,用于直播观众分析。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "douyin-xingtu/gw/api/aggregator/get_author_live_watch_distribution/v1",
+      "requiredParams": [
+        "oAuthorId"
+      ],
+      "tags": [
+        "抖音",
+        "douyin",
+        "星图",
+        "xingtu",
+        "达人",
+        "电商",
+        "ecommerce",
+        "live",
+        "watch",
+        "distribution",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "douyin.xingtu.marketing_metrics",
+      "platform": "douyin",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "抖音星图·营销指标",
+      "summary": "获取抖音巨量星图营销指标数据,包括刊例价详情和商业服务指标,用于创作者评估、活动策划和平台研究。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "douyin-xingtu/gw/api/author/get_author_marketing_info/v1",
+      "requiredParams": [
+        "oAuthorId"
+      ],
+      "tags": [
+        "抖音",
+        "douyin",
+        "星图",
+        "xingtu",
+        "达人",
+        "电商",
+        "ecommerce",
+        "marketing",
+        "metrics",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "douyin.xingtu.recommended_videos",
+      "platform": "douyin",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "抖音星图·推荐视频",
+      "summary": "获取抖音巨量星图推荐视频数据,包括使用的内容参考,用于创作者评估。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "douyin-xingtu/gw/api/data_sp/author_rec_videos_v2/v1",
+      "requiredParams": [
+        "oAuthorId"
+      ],
+      "tags": [
+        "抖音",
+        "douyin",
+        "星图",
+        "xingtu",
+        "达人",
+        "电商",
+        "ecommerce",
+        "recommended",
+        "videos",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "douyin.xingtu.showcase_items",
+      "platform": "douyin",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "抖音星图·展示商品",
+      "summary": "获取抖音巨量星图展示项目数据,包括与账户关联的商品和视频,用于创作者评估、活动规划和市场研究。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "douyin-xingtu/gw/api/author/get_author_show_items_v2/v1",
+      "requiredParams": [
+        "oAuthorId"
+      ],
+      "tags": [
+        "抖音",
+        "douyin",
+        "星图",
+        "xingtu",
+        "达人",
+        "电商",
+        "ecommerce",
+        "showcase",
+        "items",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "douyin.xingtu.spread_metrics",
+      "platform": "douyin",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "抖音星图·传播指标",
+      "summary": "获取抖音巨量星图传播指标数据,包括曝光、传播和相关表现指标,用于创作者评估、活动策划和平台研究。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "douyin-xingtu/gw/api/data_sp/get_author_spread_info/v1",
+      "requiredParams": [
+        "oAuthorId"
+      ],
+      "tags": [
+        "抖音",
+        "douyin",
+        "星图",
+        "xingtu",
+        "达人",
+        "电商",
+        "ecommerce",
+        "spread",
+        "metrics",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "douyin.xingtu.video_details",
+      "platform": "douyin",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "抖音星图·视频详情",
+      "summary": "获取抖音巨量星图视频报告详情数据,包括关键指标和使用的报告字段,用于视频表现分析。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "douyin-xingtu/gw/api/data_sp/item_report_detail/v1",
+      "requiredParams": [
+        "itemId"
+      ],
+      "tags": [
+        "抖音",
+        "douyin",
+        "星图",
+        "xingtu",
+        "达人",
+        "电商",
+        "ecommerce",
+        "video",
+        "details",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "douyin.xingtu.video_distribution",
+      "platform": "douyin",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "抖音星图·视频分布",
+      "summary": "获取抖音巨量星图视频分发数据,包括已发布视频的内容性能细分,用于创作者评估、活动规划和市场研究。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "douyin-xingtu/gw/api/data_sp/author_video_distribution/v1",
+      "requiredParams": [
+        "oAuthorId"
+      ],
+      "tags": [
+        "抖音",
+        "douyin",
+        "星图",
+        "xingtu",
+        "达人",
+        "电商",
+        "ecommerce",
+        "video",
+        "distribution",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "xiaohongshu.pgy.content_square_notes",
+      "platform": "xiaohongshu",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "小红书蒲公英·内容广场笔记",
+      "summary": "按业务类型、排名指标、时间范围和关键词搜索小红书蒲公英内容广场笔记。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "xiaohongshu-pgy/api/pgy/content_square/search_note_v2/v1",
+      "requiredParams": [],
+      "tags": [
+        "小红书",
+        "xiaohongshu",
+        "蒲公英",
+        "pgy",
+        "pugongying",
+        "达人",
+        "博主",
+        "电商",
+        "ecommerce",
+        "content",
+        "square",
+        "notes",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "xiaohongshu.pgy.cost_effectiveness_analysis",
+      "platform": "xiaohongshu",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "小红书蒲公英·成本效益分析",
+      "summary": "获取小红书蒲公英成本效益分析数据,包括定价、覆盖范围和互动效率指标,用于活动评估。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "xiaohongshu-pgy/api/solar/kol/dataV2/costEffective/v1",
+      "requiredParams": [
+        "userId"
+      ],
+      "tags": [
+        "小红书",
+        "xiaohongshu",
+        "蒲公英",
+        "pgy",
+        "pugongying",
+        "达人",
+        "博主",
+        "电商",
+        "ecommerce",
+        "cost",
+        "effectiveness",
+        "analysis",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "xiaohongshu.pgy.creator_content_tags",
+      "platform": "xiaohongshu",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "小红书蒲公英·创作者内容标签",
+      "summary": "获取小红书蒲公英创作者内容标签数据,包括描述发布主题和内容焦点的主题标签,用于创作者评估、活动策划和创作者对标。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "xiaohongshu-pgy/api/solar/kol/dataV2/kolContentTags/v1",
+      "requiredParams": [
+        "userId"
+      ],
+      "tags": [
+        "小红书",
+        "xiaohongshu",
+        "蒲公英",
+        "pgy",
+        "pugongying",
+        "达人",
+        "博主",
+        "电商",
+        "ecommerce",
+        "creator",
+        "content",
+        "tags",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "xiaohongshu.pgy.creator_core_metrics",
+      "platform": "xiaohongshu",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "小红书蒲公英·创作者核心指标",
+      "summary": "获取小红书蒲公英创作者核心指标数据,包括互动和内容指标,用于对标、审核和活动策划。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "xiaohongshu-pgy/api/pgy/kol/data/core_data/v1",
+      "requiredParams": [
+        "userId"
+      ],
+      "tags": [
+        "小红书",
+        "xiaohongshu",
+        "蒲公英",
+        "pgy",
+        "pugongying",
+        "达人",
+        "博主",
+        "电商",
+        "ecommerce",
+        "creator",
+        "core",
+        "metrics",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "xiaohongshu.pgy.creator_feature_tags",
+      "platform": "xiaohongshu",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "小红书蒲公英·创作者特征标签",
+      "summary": "获取小红书蒲公英创作者特征标签数据,包括平台标签、分类标签和分类信号,用于细分、发现和创作者分类。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "xiaohongshu-pgy/api/solar/kol/dataV2/kolFeatureTags/v1",
+      "requiredParams": [
+        "userId"
+      ],
+      "tags": [
+        "小红书",
+        "xiaohongshu",
+        "蒲公英",
+        "pgy",
+        "pugongying",
+        "达人",
+        "博主",
+        "电商",
+        "ecommerce",
+        "creator",
+        "feature",
+        "tags",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "xiaohongshu.pgy.creator_note_list",
+      "platform": "xiaohongshu",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "小红书蒲公英·创作者笔记列表",
+      "summary": "获取小红书蒲公英用户发布笔记数据,包括笔记元数据和互动信号,用于创作者监控和活动研究。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "xiaohongshu-pgy/api/solar/kol/dataV2/notesDetail/v1",
+      "requiredParams": [
+        "userId"
+      ],
+      "tags": [
+        "小红书",
+        "xiaohongshu",
+        "蒲公英",
+        "pgy",
+        "pugongying",
+        "达人",
+        "博主",
+        "电商",
+        "ecommerce",
+        "creator",
+        "note",
+        "list",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "xiaohongshu.pgy.creator_note_list_pro",
+      "platform": "xiaohongshu",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "小红书蒲公英·创作者笔记列表 Pro",
+      "summary": "获取小红书蒲公英创作者笔记列表数据,包括内容元数据、发布时间和互动指标,用于内容分析。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "xiaohongshu-pgy/get-kol-note-list/v1",
+      "requiredParams": [
+        "kolId",
+        "adSwitch",
+        "orderType"
+      ],
+      "tags": [
+        "小红书",
+        "xiaohongshu",
+        "蒲公英",
+        "pgy",
+        "pugongying",
+        "达人",
+        "博主",
+        "电商",
+        "ecommerce",
+        "creator",
+        "note",
+        "list",
+        "pro",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "xiaohongshu.pgy.creator_profile",
+      "platform": "xiaohongshu",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "小红书蒲公英·创作者资料",
+      "summary": "获取小红书蒲公英创作者资料数据,包括受众和定价数据,用于影响者审核、基准分析和活动规划。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "xiaohongshu-pgy/api/solar/cooperator/user/blogger/userId/v1",
+      "requiredParams": [
+        "userId"
+      ],
+      "tags": [
+        "小红书",
+        "xiaohongshu",
+        "蒲公英",
+        "pgy",
+        "pugongying",
+        "达人",
+        "博主",
+        "电商",
+        "ecommerce",
+        "creator",
+        "profile",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "xiaohongshu.pgy.creator_search",
+      "platform": "xiaohongshu",
+      "channel": "ecommerce",
+      "wave": "search",
+      "title": "小红书蒲公英·创作者搜索",
+      "summary": "获取小红书蒲公英创作者搜索数据,包括过滤器、返回的档案和受众,用于发现、比较和候选名单构建。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "xiaohongshu-pgy/api/solar/cooperator/blogger/v2/v1",
+      "requiredParams": [],
+      "tags": [
+        "小红书",
+        "xiaohongshu",
+        "蒲公英",
+        "pgy",
+        "pugongying",
+        "达人",
+        "博主",
+        "电商",
+        "ecommerce",
+        "creator",
+        "search"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "xiaohongshu.pgy.data_summary",
+      "platform": "xiaohongshu",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "小红书蒲公英·数据摘要",
+      "summary": "获取小红书蒲公英摘要数据,包括活动、互动和受众增长,用于创作者评估、活动策划和创作者基准测试。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "xiaohongshu-pgy/api/solar/kol/dataV3/dataSummary/v1",
+      "requiredParams": [
+        "userId"
+      ],
+      "tags": [
+        "小红书",
+        "xiaohongshu",
+        "蒲公英",
+        "pgy",
+        "pugongying",
+        "达人",
+        "博主",
+        "电商",
+        "ecommerce",
+        "data",
+        "summary",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "xiaohongshu.pgy.follower_distribution",
+      "platform": "xiaohongshu",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "小红书蒲公英·粉丝分布",
+      "summary": "获取小红书蒲公英粉丝分布数据,包括受众人口统计、兴趣和分布指标,用于创作者评估、活动策划和创作者基准测试。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "xiaohongshu-pgy/api/solar/kol/data/userId/fans_profile/v1",
+      "requiredParams": [
+        "userId"
+      ],
+      "tags": [
+        "小红书",
+        "xiaohongshu",
+        "蒲公英",
+        "pgy",
+        "pugongying",
+        "达人",
+        "博主",
+        "电商",
+        "ecommerce",
+        "follower",
+        "distribution",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "xiaohongshu.pgy.follower_growth_history",
+      "platform": "xiaohongshu",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "小红书蒲公英·粉丝增长历史",
+      "summary": "获取小红书蒲公英粉丝增长历史数据,包括历史点、趋势信号和增长指标,用于趋势跟踪、受众分析和创作者表现监控。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "xiaohongshu-pgy/api/solar/kol/data/userId/fans_overall_new_history/v1",
+      "requiredParams": [
+        "userId"
+      ],
+      "tags": [
+        "小红书",
+        "xiaohongshu",
+        "蒲公英",
+        "pgy",
+        "pugongying",
+        "达人",
+        "博主",
+        "电商",
+        "ecommerce",
+        "follower",
+        "growth",
+        "history",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "xiaohongshu.pgy.follower_summary",
+      "platform": "xiaohongshu",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "小红书蒲公英·粉丝摘要",
+      "summary": "获取小红书蒲公英粉丝概览数据,包括增长和互动指标,用于受众分析和创作者对标。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "xiaohongshu-pgy/api/solar/kol/dataV3/fansSummary/v1",
+      "requiredParams": [
+        "userId"
+      ],
+      "tags": [
+        "小红书",
+        "xiaohongshu",
+        "蒲公英",
+        "pgy",
+        "pugongying",
+        "达人",
+        "博主",
+        "电商",
+        "ecommerce",
+        "follower",
+        "summary",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "xiaohongshu.pgy.note_details",
+      "platform": "xiaohongshu",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "小红书蒲公英·笔记详情",
+      "summary": "获取小红书蒲公英笔记详情数据,包括媒体和互动信号,用于内容分析、归档和活动回顾。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "xiaohongshu-pgy/api/solar/note/noteId/detail/v1",
+      "requiredParams": [
+        "noteId"
+      ],
+      "tags": [
+        "小红书",
+        "xiaohongshu",
+        "蒲公英",
+        "pgy",
+        "pugongying",
+        "达人",
+        "博主",
+        "电商",
+        "ecommerce",
+        "note",
+        "details",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "xiaohongshu.pgy.note_performance_metrics",
+      "platform": "xiaohongshu",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "小红书蒲公英·笔记表现指标",
+      "summary": "获取小红书蒲公英笔记表现指标数据,包括核心指标、趋势信号和表现指标,用于内容效率分析、创作者基准测试和活动策划。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "xiaohongshu-pgy/api/solar/kol/dataV3/notesRate/v1",
+      "requiredParams": [
+        "userId"
+      ],
+      "tags": [
+        "小红书",
+        "xiaohongshu",
+        "蒲公英",
+        "pgy",
+        "pugongying",
+        "达人",
+        "博主",
+        "电商",
+        "ecommerce",
+        "note",
+        "performance",
+        "metrics",
+        "detail"
+      ],
+      "billing": 1
+    },
+    {
+      "id": "xiaohongshu.pgy.similar_creators",
+      "platform": "xiaohongshu",
+      "channel": "ecommerce",
+      "wave": "detail",
+      "title": "小红书蒲公英·相似创作者",
+      "summary": "获取小红书蒲公英相似创作者数据,包括受众信号,用于创作者发现、对标和候选名单构建。",
+      "method": "GET",
+      "paramsIn": "query",
+      "proxyPath": "xiaohongshu-pgy/api/solar/kol/get_similar_kol/v1",
+      "requiredParams": [
+        "userId"
+      ],
+      "tags": [
+        "小红书",
+        "xiaohongshu",
+        "蒲公英",
+        "pgy",
+        "pugongying",
+        "达人",
+        "博主",
+        "电商",
+        "ecommerce",
+        "similar",
+        "creators",
+        "detail"
+      ],
+      "billing": 1
     }
   ]
 }

+ 96 - 1
claude-code/claude-code-voc-intelligence/mcp/src/core/credentials.js

@@ -64,6 +64,56 @@ function readEnvLocalFiles() {
   }, {});
 }
 
+// 合并读取 Claude Code 的 settings env(用户级 + 项目级,含 .local 覆盖文件)。
+// Claude Code 用户的 fmode newapi SK 默认就放在这里的 env.ANTHROPIC_AUTH_TOKEN。
+function readClaudeSettingsEnv() {
+  const files = [
+    path.join(os.homedir(), '.claude', 'settings.json'),
+    path.join(os.homedir(), '.claude', 'settings.local.json'),
+    path.join(process.cwd(), '.claude', 'settings.json'),
+    path.join(process.cwd(), '.claude', 'settings.local.json'),
+  ];
+  const merged = {};
+  for (const filePath of files) {
+    const json = readJsonMaybe(filePath);
+    const env = json && typeof json.env === 'object' && json.env ? json.env : null;
+    if (!env) continue;
+    for (const [key, value] of Object.entries(env)) {
+      if (merged[key] === undefined && typeof value === 'string' && value.trim()) {
+        merged[key] = value;
+      }
+    }
+  }
+  return merged;
+}
+
+// 读取 ~/.fmode/config.json(及项目级 ./.fmode/config.json)里的 newapi token。
+function readFmodeConfig() {
+  const files = [
+    path.join(os.homedir(), '.fmode', 'config.json'),
+    path.join(process.cwd(), '.fmode', 'config.json'),
+  ];
+  const merged = {};
+  for (const filePath of files) {
+    const json = readJsonMaybe(filePath);
+    for (const [key, value] of Object.entries(json || {})) {
+      if (merged[key] === undefined) merged[key] = value;
+    }
+  }
+  return merged;
+}
+
+// 仅当 ANTHROPIC_AUTH_TOKEN 看起来是 fmode 的 newapi SK 时才采纳:
+// - 必须 sk- 开头,且排除真 Anthropic 官方 key(sk-ant- 开头);
+// - 若 settings 里设了 ANTHROPIC_BASE_URL,必须指向 fmode(否则这把 token 是发往别处的,不能拿来当 fmode 计费 token)。
+function pickFmodeAnthropicToken(env) {
+  const token = env && typeof env.ANTHROPIC_AUTH_TOKEN === 'string' ? env.ANTHROPIC_AUTH_TOKEN.trim() : '';
+  if (!token || !/^sk-/i.test(token) || /^sk-ant-/i.test(token)) return '';
+  const base = String((env && (env.ANTHROPIC_BASE_URL || env.ANTHROPIC_API_BASE)) || '').toLowerCase();
+  if (base && !base.includes('fmode')) return '';
+  return token;
+}
+
 function readVocToken(input = {}) {
   const workspaceEnv = readEnvLocalFiles();
   const claudeCreds = readJsonMaybe(path.join(os.homedir(), '.claude', 'voc-credentials.json'));
@@ -90,10 +140,55 @@ function readXiaohongshuToken(input = {}) {
   return readVocToken(input);
 }
 
+// NewAPI(fmode-api)计费 token,以 sk- 开头。
+// 计费已迁移到 NewAPI:优先用它发请求,鉴权失败再回退平台 sessionToken(apig,原路径保留)。
+// 关键:这把 sk- 就是 Claude Code 的 env.ANTHROPIC_AUTH_TOKEN(在 ~/.claude/settings.json),
+// 默认装完技能不必再手动配置——这里直接从 settings.json / 进程环境读取它,避免「明明配了 SK 却判缺 token、被甩进老付费框」的死循环。
+// 取值优先级:显式入参 → .env.local / 环境变量 FMODE_API_KEY·NEWAPI_TOKEN
+//   → ~/.claude/voc-credentials.json 的 fmodeApiKey → ~/.fmode/config.json 的 newapiToken/fmodeApiToken
+//   → Claude Code env(进程注入 + ~/.claude/settings.json)的 ANTHROPIC_AUTH_TOKEN(sk-、且 base 指向 fmode)。
+function readNewApiToken(input = {}) {
+  const workspaceEnv = readEnvLocalFiles();
+  const claudeCreds = readJsonMaybe(path.join(os.homedir(), '.claude', 'voc-credentials.json'));
+  const fmodeConfig = readFmodeConfig();
+  const claudeEnv = readClaudeSettingsEnv();
+  return firstNonEmpty([
+    input.newapiToken,
+    input.newApiToken,
+    input.fmodeApiKey,
+    input.fmodeApiToken,
+    workspaceEnv.NEWAPI_TOKEN,
+    workspaceEnv.NEW_API_TOKEN,
+    workspaceEnv.FMODE_API_KEY,
+    workspaceEnv.FMODE_API_TOKEN,
+    process.env.NEWAPI_TOKEN,
+    process.env.NEW_API_TOKEN,
+    process.env.FMODE_API_KEY,
+    process.env.FMODE_API_TOKEN,
+    claudeCreds.fmodeApiKey,
+    claudeCreds.fmodeApiToken,
+    fmodeConfig.newapiToken,
+    fmodeConfig.newApiToken,
+    fmodeConfig.fmodeApiKey,
+    fmodeConfig.fmodeApiToken,
+    // Claude Code 显式写在 settings.json env 里的 fmode key(少见,但优先于自动推断的 ANTHROPIC_AUTH_TOKEN)
+    claudeEnv.FMODE_API_KEY,
+    claudeEnv.NEWAPI_TOKEN,
+    // Claude Code 默认入口:进程注入的 ANTHROPIC_AUTH_TOKEN(Claude Code 会把 settings.env 注入子进程)
+    pickFmodeAnthropicToken(process.env),
+    // 兜底:直接读 ~/.claude/settings.json 里的 env.ANTHROPIC_AUTH_TOKEN(独立运行、未被注入时)
+    pickFmodeAnthropicToken(claudeEnv),
+  ]);
+}
+
 module.exports = {
   readVocToken,
   readXiaohongshuToken,
+  readNewApiToken,
   readEnvFileMaybe,
   readWorkspaceEnvLocal,
-  envLocalCandidates
+  envLocalCandidates,
+  readClaudeSettingsEnv,
+  readFmodeConfig,
+  pickFmodeAnthropicToken
 };

+ 57 - 1
claude-code/claude-code-voc-intelligence/mcp/src/core/payment-links.js

@@ -2,6 +2,9 @@ const VOC_SOCIAL_APIG_ID = 'Vo3ROWEvDy';
 const VOC_RECHARGE_FUN_ID = 'HOkkX72PMF';
 const VOC_RECHARGE_BASE_URL = 'https://app.fmode.cn/dev/apig-pay/';
 const PARSE_USERS_ME_URL = 'https://server.fmode.cn/parse/users/me';
+
+// NewAPI(fmode-api)余额充值入口。携带 ?balance=fmodeapi 会自动打开余额充值弹窗。
+const FMODE_API_RECHARGE_URL = 'https://app.fmode.cn/dev/studio/?balance=fmodeapi';
 const DEFAULT_WORKSHOP_PACKAGE_SLUG = '99';
 const VOC_WORKSHOP_PACKAGE_SLUGS = {
   trial199: '19-9',
@@ -123,6 +126,55 @@ function buildWrongTokenTypeMessage(paymentUrl, recharge = {}, options = {}) {
   ].join('\n');
 }
 
+// 没读到 NewAPI(fmode-api)的 sk- 计费 token 时的提示。
+// 关键:这是「没读到 SK」这种**可恢复**状态,不是余额不足、也不是功能用不了——
+// 先引导 agent 从 Claude Code 的 settings.json 取 SK 重试,充值只作为最后兜底(且仅真 402 才需要)。
+function buildMissingNewApiTokenMessage(paymentUrl, recharge = {}, options = {}) {
+  const platformLabel = options.platformLabel || '小红书';
+  const lines = [
+    `还没读到 NewAPI(fmode-api)计费 token,暂时不能进行真实 ${platformLabel} 采集——但这是**配置/读取**问题,不是余额不足,也不代表这个功能用不了。`,
+    '',
+    '这把计费 token 就是 Claude Code 的 `ANTHROPIC_AUTH_TOKEN`(`sk-` 开头),通常配在用户级 `~/.claude/settings.json` 的 `env` 里。',
+    '',
+    '请按这个顺序自救(优先,不要直接让用户去点充值):',
+    '1. 读取 `~/.claude/settings.json` 的 `env.ANTHROPIC_AUTH_TOKEN`(确认是 `sk-` 开头、`ANTHROPIC_BASE_URL` 指向 `api.fmode.cn`)。',
+    '2. 用 `FMODE_API_KEY=sk-…`(或入参 `newapiToken`)把它传给本工具,重新调用一次。',
+    '3. 仍报缺 token / 鉴权失败时,才考虑回退 `r:` 开头的会话 token,或确认是否真的 `402 余额不足`。'
+  ];
+  // 这是 newapi(fmode-api)计费链,兜底充值必须指向 fmode-api 余额充值入口
+  // (studio/?balance=fmodeapi),不是 VOC 采集会话 token 的 apig-pay 链接。
+  const fmodeApiRechargeUrl = options.fmodeApiRechargeUrl || FMODE_API_RECHARGE_URL;
+  lines.push('', `(仅当确认是 fmode-api 余额不足时才充值:${fmodeApiRechargeUrl})`);
+  lines.push('', '系统只会用 token 发起请求,绝不在报告、日志或聊天输出里回显 token。');
+  return lines.join('\n');
+}
+
+function buildFmodeApiRechargeUrl() {
+  return FMODE_API_RECHARGE_URL;
+}
+
+// NewAPI(fmode-api)余额不足(HTTP 402)时的充值提示。
+function buildFmodeApiRechargeMessage(paymentUrl = FMODE_API_RECHARGE_URL, options = {}) {
+  const platformLabel = options.platformLabel || '小红书';
+  return [
+    `VOC-AI 数据服务余额不足(fmode-api 计费额度已用尽),暂时不能继续真实 ${platformLabel} 采集。`,
+    '',
+    `请打开充值链接补充余额:${paymentUrl}`,
+    '',
+    '链接会自动打开余额充值弹窗;充值后用相同参数重试即可。底层鉴权/上游响应不会展示给用户。'
+  ].join('\n');
+}
+
+// 用户被禁用或无该接口权限(HTTP 403,区别于余额不足)。
+function buildPermissionDeniedMessage(options = {}) {
+  const platformLabel = options.platformLabel || '小红书';
+  return [
+    `当前账号被禁用或没有该 ${platformLabel} 接口的访问权限,暂时不能调用(这不是余额不足、也不是关键词/类目问题)。`,
+    '',
+    '请联系服务方确认账号状态或接口权限后重试。底层鉴权/上游响应不会展示给用户。'
+  ].join('\n');
+}
+
 module.exports = {
   VOC_SOCIAL_APIG_ID,
   VOC_RECHARGE_FUN_ID,
@@ -131,6 +183,10 @@ module.exports = {
   buildVocRechargeUrl,
   buildVocWorkshopUrl,
   buildMissingTokenMessage,
+  buildMissingNewApiTokenMessage,
   buildRechargeRequiredMessage,
-  buildWrongTokenTypeMessage
+  buildWrongTokenTypeMessage,
+  buildFmodeApiRechargeUrl,
+  buildFmodeApiRechargeMessage,
+  buildPermissionDeniedMessage
 };

+ 16 - 12
claude-code/claude-code-voc-intelligence/mcp/src/features/fmode-image-analysis/image-analysis.js

@@ -1,6 +1,6 @@
 const fs = require('fs');
 const path = require('path');
-const { readVocToken, readEnvFileMaybe, envLocalCandidates } = require('../../core/credentials');
+const { readVocToken, readNewApiToken, readEnvFileMaybe, envLocalCandidates } = require('../../core/credentials');
 const { buildVocRechargeInfo } = require('../../core/payment-links');
 const { okResult, errorResult } = require('../../core/result-envelope');
 
@@ -30,12 +30,12 @@ async function analyzeFmodeImage(input = {}) {
   if (!token) {
     const recharge = await buildVocRechargeInfo();
     return friendlyResult('needs_token', buildMissingTokenMessage(recharge.paymentUrl, recharge), {
-      summary: { imageCount: images.length, model: provider.model },
+      summary: { imageCount: images.length, model: provider.model, errorKind: 'missing_token', recoverable: true },
       data: { recharge, model: provider.model, imageCount: images.length },
       nextActions: [
-        `打开开通/充值链接:${recharge.paymentUrl}`,
-        '在当前工作区 .env.local 配置 VOC_TOKEN / FMODE_TOKEN / TIHAO_SESSION_TOKEN',
-        '或在 MCP 工具参数中传入 vocToken / sessionToken / fmodeToken。'
+        '从 ~/.claude/settings.json 取 env.ANTHROPIC_AUTH_TOKEN(sk-,base 指向 api.fmode.cn),用 FMODE_API_KEY=sk-… 或入参 newapiToken/fmodeToken 传入后重试',
+        '在当前工作区 .env.local 配置 FMODE_API_KEY / VOC_TOKEN / FMODE_TOKEN / TIHAO_SESSION_TOKEN',
+        '仅当确认是 402 余额不足时才打开充值链接,缺 token 不是没钱、也不代表功能用不了'
       ]
     });
   }
@@ -61,8 +61,8 @@ async function analyzeFmodeImage(input = {}) {
   }
 
   if (response.status === 401) {
-    return friendlyResult('needs_valid_token', '当前平台 token 无效或已过期,请换成有效的 vocToken / sessionToken / fmodeToken 后重试。', {
-      summary: { imageCount: images.length, model: provider.model },
+    return friendlyResult('needs_valid_token', 'token 鉴权没过(无效/过期/类型不对),这是**可恢复**问题,不代表功能用不了、也不是没钱。优先从 `~/.claude/settings.json` 取 `env.ANTHROPIC_AUTH_TOKEN`(`sk-`)用 `FMODE_API_KEY=sk-…` 传入重试;仍不行再换有效 vocToken / sessionToken。', {
+      summary: { imageCount: images.length, model: provider.model, errorKind: 'auth', recoverable: true },
       data: { model: provider.model, imageCount: images.length }
     });
   }
@@ -216,7 +216,11 @@ function resolveFmodeToken(input = {}) {
     process.env.DOUBAO_VISION_TOKEN,
     process.env.VIDEO_ANALYSIS_TOKEN,
     process.env.TIHAO_SESSION_TOKEN,
-    readVocToken(input)
+    readVocToken(input),
+    // 兜底:NewAPI(fmode-api)的 sk- 计费 token——它就是 Claude Code 的
+    // ANTHROPIC_AUTH_TOKEN(~/.claude/settings.json 的 env),api.fmode.cn 直接认。
+    // 默认装完技能即用,避免「明明配了 SK 却判缺 token」的死循环。
+    readNewApiToken(input)
   ]);
 }
 
@@ -371,12 +375,12 @@ function buildAssistantMessage({ analysis, provider, images, files }) {
 function buildMissingTokenMessage(paymentUrl, recharge = {}) {
   const packageUrl = recharge.recommendedPackageUrl || recharge.workshopUrl || paymentUrl;
   return [
-    '还没有检测到可用于 Fmode 图片分析的平台 token,暂时不能调用 Doubao vision 模型。',
+    '还没读到可用于 Fmode 图片分析的计费 token,暂时不能调用 vision 模型——这是**配置/读取**问题,不是余额不足,也不代表这个功能用不了。',
     '',
-    `开通/充值链接:${paymentUrl}`,
-    `套餐入口:${packageUrl}`,
+    '这把计费 token 就是 Claude Code 的 `ANTHROPIC_AUTH_TOKEN`(`sk-` 开头),通常配在用户级 `~/.claude/settings.json` 的 `env` 里(`ANTHROPIC_BASE_URL` 指向 `api.fmode.cn`)。',
+    '请优先取出它,用 `FMODE_API_KEY=sk-…`(或入参 `newapiToken`/`fmodeToken`)传给本工具重试;也可写进当前工作区 `.env.local`。',
     '',
-    '开通后,可把平台 token 配置到当前工作区 `.env.local`,字段可用 `VOC_TOKEN`、`FMODE_TOKEN` 或 `TIHAO_SESSION_TOKEN`;也可以在工具参数中传入 `vocToken` / `sessionToken` / `fmodeToken`。',
+    `(仅当确认是 402 余额不足时才充值:${paymentUrl},套餐入口:${packageUrl})`,
     '',
     '系统只会把 token 用作接口鉴权,不会在聊天、报告、日志或输出文件里回显。'
   ].join('\n');

+ 53 - 0
claude-code/claude-code-voc-intelligence/mcp/src/providers/ecommerce-gateway.js

@@ -0,0 +1,53 @@
+// 创作者数据中转网关(voc-e-commerce)。用于抖音星图、小红书蒲公英(PGY)的创作者侧
+// 结构化数据接口(创作者搜索、画像、受众/粉丝分布、内容与评论关键词、笔记/视频绩效、
+// 报价与性价比等)。鉴权、计费、错误分类、重试逻辑全部复用社媒网关(voc-gateway)的
+// 共享实现,只是根地址不同;对外不暴露任何上游数据供应商名称。
+const {
+  buildGatewayUrl,
+  requestJson,
+  classifyApiError,
+  redactSecret,
+  unwrapData
+} = require('./voc-gateway');
+
+const ECOMMERCE_GATEWAY_ROOT = 'https://server.fmode.cn/api/voc-e-commerce';
+
+function resolveEcommerceRoot(baseUrl) {
+  return String(
+    baseUrl ||
+      process.env.VOC_ECOMMERCE_API_BASE_URL ||
+      process.env.VOC_ECOMMERCE_GATEWAY_URL ||
+      ECOMMERCE_GATEWAY_ROOT
+  ).replace(/\/$/, '');
+}
+
+// 与 callSocialGateway 完全一致的「优先 newapi sk-、鉴权失败回退 sessionToken」逻辑,
+// 只是走 voc-e-commerce 根地址。402(余额不足)/403(无权限)不回退。
+async function callEcommerceGateway({ proxyPath, method = 'GET', query = {}, body, token, fallbackToken, baseUrl, retries = 3 } = {}) {
+  const root = resolveEcommerceRoot(baseUrl);
+  const url = buildGatewayUrl(root, proxyPath, query);
+  const upper = String(method || 'GET').toUpperCase();
+  const requestOptions = {
+    method: upper,
+    body: upper === 'GET' ? undefined : body,
+    retries
+  };
+  try {
+    return await requestJson(url, token, requestOptions);
+  } catch (error) {
+    const canFallback = fallbackToken && fallbackToken !== token && error && error.kind === 'auth';
+    if (!canFallback) throw error;
+    return requestJson(url, fallbackToken, requestOptions);
+  }
+}
+
+module.exports = {
+  ECOMMERCE_GATEWAY_ROOT,
+  resolveEcommerceRoot,
+  buildGatewayUrl,
+  classifyApiError,
+  redactSecret,
+  unwrapData,
+  requestJson,
+  callEcommerceGateway
+};

+ 13 - 3
claude-code/claude-code-voc-intelligence/mcp/src/providers/voc-gateway.js

@@ -139,15 +139,25 @@ async function requestJson(url, token, { method = 'GET', body, retries = 3 } = {
   throw lastError;
 }
 
-async function callSocialGateway({ proxyPath, method = 'GET', query = {}, body, token, baseUrl, retries = 3 } = {}) {
+// 优先用 newapi 的 sk- token 发请求;若该 token 鉴权失败(kind === 'auth',例如服务端
+// 尚未迁移 / 该号未入仓 / token 未被接受)且提供了回退 token(平台 sessionToken),自动用
+// 回退 token 重试一次。402(余额不足)/403(无权限)不回退。
+async function callSocialGateway({ proxyPath, method = 'GET', query = {}, body, token, fallbackToken, baseUrl, retries = 3 } = {}) {
   const root = resolveSocialRoot(baseUrl);
   const url = buildGatewayUrl(root, proxyPath, query);
   const upper = String(method || 'GET').toUpperCase();
-  return requestJson(url, token, {
+  const requestOptions = {
     method: upper,
     body: upper === 'GET' ? undefined : body,
     retries
-  });
+  };
+  try {
+    return await requestJson(url, token, requestOptions);
+  } catch (error) {
+    const canFallback = fallbackToken && fallbackToken !== token && error && error.kind === 'auth';
+    if (!canFallback) throw error;
+    return requestJson(url, fallbackToken, requestOptions);
+  }
 }
 
 module.exports = {

+ 11 - 8
claude-code/claude-code-voc-intelligence/mcp/src/server.js

@@ -2,7 +2,7 @@
 const { McpServer } = require('@modelcontextprotocol/sdk/server/mcp.js');
 const { StdioServerTransport } = require('@modelcontextprotocol/sdk/server/stdio.js');
 const { z } = require('zod');
-const { readXiaohongshuToken, readVocToken } = require('./core/credentials');
+const { readXiaohongshuToken, readVocToken, readNewApiToken } = require('./core/credentials');
 const { runXiaohongshuTrend } = require('./tools/xiaohongshu-trend-run');
 const { updateXiaohongshuPreference } = require('./tools/xiaohongshu-preference-update');
 const { runDouyinTrend } = require('./tools/douyin-trend-run');
@@ -15,7 +15,7 @@ const { runVocSpeakingScript } = require('./tools/voc-speaking-script-run');
 const { runBusinessWorkflow } = require('./tools/voc-business-workflow-run');
 const { analyzeFmodeImage } = require('./tools/fmode-image-analysis');
 const { searchVocApis, getVocApiDoc, callVocApi } = require('./tools/voc-api-catalog-run');
-const { buildVocRechargeInfo, buildMissingTokenMessage } = require('./core/payment-links');
+const { buildVocRechargeInfo, buildMissingTokenMessage, buildMissingNewApiTokenMessage } = require('./core/payment-links');
 
 function asToolResult(result) {
   const normalized = normalizeToolResult(result);
@@ -61,7 +61,7 @@ function normalizeToolResult(result = {}) {
 function createServer() {
   const server = new McpServer({
     name: 'voc-intelligence',
-    version: '0.3.17'
+    version: '0.3.24'
   });
 
   server.registerTool(
@@ -454,7 +454,7 @@ function createServer() {
       }
     },
     async input => {
-      const token = readXiaohongshuToken(input);
+      const token = readXiaohongshuToken(input) || readNewApiToken(input);
       const recharge = token ? null : await buildVocRechargeInfo();
       const result = {
         status: token ? 'ok' : 'needs_token',
@@ -462,7 +462,7 @@ function createServer() {
         data: recharge ? { recharge } : {},
         assistantMessage: token
           ? '\u5c0f\u7ea2\u4e66 live \u91c7\u96c6 Token \u5df2\u914d\u7f6e\uff0c\u53ef\u4ee5\u5c1d\u8bd5\u5c0f\u89c4\u6a21\u771f\u5b9e\u91c7\u96c6\u3002'
-          : buildMissingTokenMessage(recharge.paymentUrl)
+          : buildMissingNewApiTokenMessage(recharge.paymentUrl, recharge, { platformLabel: '\u5c0f\u7ea2\u4e66' })
       };
       return asToolResult(result);
     }
@@ -486,7 +486,7 @@ function createServer() {
       }
     },
     async input => {
-      const token = readVocToken(input);
+      const token = readVocToken(input) || readNewApiToken(input);
       const recharge = token ? null : await buildVocRechargeInfo();
       const result = {
         status: token ? 'ok' : 'needs_token',
@@ -494,7 +494,7 @@ function createServer() {
         data: recharge ? { recharge } : {},
         assistantMessage: token
           ? '\u6296\u97f3 live \u91c7\u96c6 Token \u5df2\u914d\u7f6e\uff0c\u53ef\u4ee5\u5f00\u59cb\u5c0f\u89c4\u6a21\u771f\u5b9e\u91c7\u96c6\u3002'
-          : buildMissingTokenMessage(recharge.paymentUrl, recharge, { platformLabel: '\u6296\u97f3' })
+          : buildMissingNewApiTokenMessage(recharge.paymentUrl, recharge, { platformLabel: '\u6296\u97f3' })
       };
       return asToolResult(result);
     }
@@ -735,7 +735,7 @@ function createServer() {
       description: [
         'Invoke any VOC social forwarding interface and return the upstream data.',
         'Provide a catalog id (preferred) or a rawPath + method for unlisted interfaces, plus a params object assembled from the interface doc.',
-        'Requires an r: session token (not an sk- AIGate key). Input/parameter errors, upstream instability, auth, and billing are reported distinctly and are never disguised as \u201cno data / category unsupported\u201d.'
+        'Prefer the NewAPI (fmode-api) sk- billing token; if it is missing or unauthorized, automatically falls back to an r: session token. Input/parameter errors, upstream instability, auth, and billing are reported distinctly and are never disguised as \u201cno data / category unsupported\u201d.'
       ].join(' '),
       inputSchema: {
         id: z.string().optional().describe('Catalog interface id, e.g. douyin.search_general.'),
@@ -747,6 +747,9 @@ function createServer() {
         body: z.object({}).passthrough().optional().describe('Optional explicit request body.'),
         retries: z.number().int().min(0).max(8).optional(),
         baseUrl: z.string().optional(),
+        newapiToken: z.string().optional().describe('Preferred NewAPI (fmode-api) sk- billing token. Used only for this run and never echoed back.'),
+        newApiToken: z.string().optional().describe('Alias of newapiToken.'),
+        fmodeApiKey: z.string().optional().describe('Alias of newapiToken.'),
         vocToken: z.string().optional().describe('Optional VOC social r: session token. Used only for this run and never echoed back.'),
         token: z.string().optional().describe('Alias of vocToken. Never echoed back.'),
         douyinToken: z.string().optional(),

+ 13 - 27
claude-code/claude-code-voc-intelligence/mcp/src/tools/douyin-trend-run.js

@@ -2,7 +2,7 @@
 const fs = require('fs');
 const path = require('path');
 const { okResult, errorResult } = require('../core/result-envelope');
-const { readVocToken } = require('../core/credentials');
+const { readVocToken, readNewApiToken } = require('../core/credentials');
 const { buildSampleDataset } = require('../features/douyin-trend/sample-data');
 const { collectLiveDataset } = require('../features/douyin-trend/live-collector');
 const { cacheEvidenceAssets } = require('../features/xiaohongshu-trend/assets');
@@ -11,9 +11,9 @@ const { trendMemoryPath, readTrendMemory } = require('../features/douyin-trend/p
 const { buildNoSampleFallbackMessage } = require('../core/evidence-quality');
 const {
   buildVocRechargeInfo,
-  buildMissingTokenMessage,
+  buildMissingNewApiTokenMessage,
   buildRechargeRequiredMessage,
-  buildWrongTokenTypeMessage
+  buildFmodeApiRechargeUrl
 } = require('../core/payment-links');
 
 function parseArgs(argv) {
@@ -180,29 +180,14 @@ async function runDouyinTrend(input = {}) {
     dataset = buildSampleDataset(profile);
     warnings.push('P0 阶段使用 sample 演示数据,真实采集需要接入 VOC 服务。');
   } else if (collectionMode === 'live') {
-    const token = readVocToken(input);
-    if (token && /^\s*sk-/i.test(token)) {
-      const recharge = await buildVocRechargeInfo();
-      return {
-        status: 'needs_valid_token',
-        assistantMessage: buildWrongTokenTypeMessage(recharge.paymentUrl, recharge, { platformLabel: '抖音' }),
-        summary: { requestedCollectionMode: collectionMode, tokenType: 'sk-' },
-        data: { requestedCollectionMode: collectionMode, recharge },
-        files: [],
-        nextActions: [
-          '从充值/开通页复制以 r: 开头的会话 token(不是 sk- 开头的 AIGate API Key)',
-          `打开充值/开通链接:${recharge.paymentUrl}`,
-          '配置正确的 r: token 后重新运行 live 模式'
-        ],
-        warnings: [],
-        errors: []
-      };
-    }
+    // 计费优先走 newapi 的 sk- token(与 voc_api_call 一致,server.fmode.cn/api/voc-social 同一网关
+    // 已验证 Bearer sk- 可采集),读不到再回退平台会话 token。不再把 sk- 误判为「类型错误」。
+    const token = readNewApiToken(input) || readVocToken(input);
     if (!token) {
       const recharge = await buildVocRechargeInfo();
       return {
         status: 'needs_token',
-        assistantMessage: buildMissingTokenMessage(recharge.paymentUrl, recharge, { platformLabel: '抖音' }),
+        assistantMessage: buildMissingNewApiTokenMessage(recharge.paymentUrl, recharge, { platformLabel: '抖音' }),
         summary: { requestedCollectionMode: collectionMode },
         data: {
           requestedCollectionMode: collectionMode,
@@ -210,8 +195,9 @@ async function runDouyinTrend(input = {}) {
         },
         files: [],
         nextActions: [
-          `打开充值/开通链接:${recharge.paymentUrl}`,
-          '充值完成后配置 session token,再重新运行 live 模式',
+          '从 ~/.claude/settings.json 读取 env.ANTHROPIC_AUTH_TOKEN(sk- 开头)或用 FMODE_API_KEY/newapiToken 入参重试',
+          '仍读不到时,再回退 r: 开头的会话 token,或确认是否真的 402 余额不足',
+          `确认确实是 fmode-api 余额不足/未开通时,再前往充值:${buildFmodeApiRechargeUrl()}`,
           '如果只是录制教学,可以先用 sample 模式演示完整流程'
         ],
         warnings: [],
@@ -351,11 +337,11 @@ async function runDouyinTrend(input = {}) {
           assistantMessage: [
             '当前 VOC-AI 数据服务 token 没有通过校验,暂时不能进行真实抖音采集。',
             '',
-            '这是 token 无效或类型不对,不是关键词/类目问题:抖音采集需要从充值/开通页复制的、以 r: 开头的会话 token(不要用 sk- 开头的 AIGate API Key)。',
+            '这是 token 鉴权问题,不是关键词/类目问题:可能是 fmode newapi(sk-)token 未开通/未入仓,或回退的会话 token 已失效。',
             '',
-            '请确认已完成 VOC-AI 数据服务开通/充值,并重新配置以 r: 开头的 session token。',
+            '请先确认 ~/.claude/settings.json 的 env.ANTHROPIC_AUTH_TOKEN(sk- 开头、base 指向 fmode)有效;仍失败时再回退 r: 会话 token,或确认是否 402 余额不足。',
             '',
-            `充值/开通链接:${recharge.paymentUrl}`
+            `(仅当确认余额不足时才充值:${recharge.paymentUrl}`
           ].join('\n'),
           summary: {
             videoCount: 0,

+ 71 - 42
claude-code/claude-code-voc-intelligence/mcp/src/tools/voc-api-catalog-run.js

@@ -1,4 +1,4 @@
-const { readVocToken } = require('../core/credentials');
+const { readVocToken, readNewApiToken } = require('../core/credentials');
 const {
   listEndpoints,
   findEndpoint,
@@ -8,11 +8,14 @@ const {
   loadCatalog
 } = require('../core/api-catalog');
 const { callSocialGateway, redactSecret } = require('../providers/voc-gateway');
+const { callEcommerceGateway } = require('../providers/ecommerce-gateway');
 const {
   buildVocRechargeInfo,
   buildMissingTokenMessage,
-  buildRechargeRequiredMessage,
-  buildWrongTokenTypeMessage
+  buildMissingNewApiTokenMessage,
+  buildFmodeApiRechargeUrl,
+  buildFmodeApiRechargeMessage,
+  buildPermissionDeniedMessage
 } = require('../core/payment-links');
 const { okResult, errorResult } = require('../core/result-envelope');
 
@@ -40,7 +43,11 @@ async function searchVocApis(input = {}) {
   const lines = [
     '## VOC 转发接口清单',
     '',
-    `网关:${catalog.gateway?.social?.baseUrl || ''}(通用转发,任意 proxyPath 透传到我们的中转上游;每次调用计费 1 次)。`,
+    `社媒网关:${catalog.gateway?.social?.baseUrl || ''}(小红书/抖音内容、评论等,channel=social,默认)。`,
+    catalog.gateway?.ecommerce?.baseUrl
+      ? `创作者数据网关:${catalog.gateway.ecommerce.baseUrl}(抖音星图/小红书蒲公英创作者搜索·画像·受众·绩效等结构化数据,channel=ecommerce)。`
+      : '',
+    '通用转发:任意 proxyPath 透传到对应上游,每次调用计费 1 次;通道由接口的 channel 字段决定,未登记接口可传 channel 覆盖。',
     query ? `匹配关键词「${query}」的接口(${results.length} 条):` : `全部已登记接口(${results.length} 条):`,
     '',
     ...results.map(
@@ -83,7 +90,7 @@ async function getVocApiDoc(input = {}) {
     '',
     endpoint.summary || '',
     '',
-    `请求:${endpoint.method} ${endpoint.proxyPath}(计费 ${endpoint.billing || 1} 次)`,
+    `请求:${endpoint.method} ${endpoint.proxyPath}(计费 ${endpoint.billing || 1} 次,通道 ${endpoint.channel || 'social'})`,
     '',
     '参数:',
     ...paramLines,
@@ -95,11 +102,11 @@ async function getVocApiDoc(input = {}) {
     JSON.stringify(template, null, 2),
     '```',
     '',
-    'token 用从充值/开通页复制的、以 r: 开头的会话 token(不要用 sk- 开头的 AIGate Key)。'
+    'token 优先用 NewAPI(fmode-api)的 sk- token(计费已迁移);没有 sk- 时回退用充值/开通页复制的、以 r: 开头的会话 token。'
   ].filter(line => line !== '');
   return okResult({
     assistantMessage: lines.join('\n'),
-    summary: { id: endpoint.id, method: endpoint.method, proxyPath: endpoint.proxyPath },
+    summary: { id: endpoint.id, method: endpoint.method, proxyPath: endpoint.proxyPath, channel: endpoint.channel || 'social' },
     data: { endpoint, callTemplate: template }
   });
 }
@@ -156,34 +163,28 @@ async function callVocApi(input = {}) {
   }
   if (endpoint) endpoint = hydrateEndpoint(endpoint);
 
-  const token = readVocToken(input);
+  // 计费优先走 NewAPI(fmode-api)的 sk- token;该 token 鉴权失败(含「未入仓」类报错)时
+  // 自动回退平台 sessionToken 重试。注意:以前因为 sk- 直接请求会命中「入仓」错误,这里曾经
+  // 直接拒绝 sk- token;现在改为「优先 sk-、鉴权失败再回退 sessionToken」,并对外只给友好提示。
+  const explicitNewApi = readNewApiToken(input);
+  const vocToken = readVocToken(input);
+  // 兼容用户把 sk- 直接填进 VOC_TOKEN 的情况:该槽里若是 sk-,也当作 newapi token。
+  const skFromVocToken = isSkToken(vocToken) ? vocToken : '';
+  const newapiToken = explicitNewApi || skFromVocToken;
+  const sessionToken = isSkToken(vocToken) ? '' : vocToken;
+  const token = newapiToken || sessionToken;
+  const fallbackToken = (newapiToken && sessionToken && newapiToken !== sessionToken) ? sessionToken : '';
   if (!token) {
     const recharge = await buildVocRechargeInfo();
     return {
       status: 'needs_token',
-      assistantMessage: buildMissingTokenMessage(recharge.paymentUrl, recharge, { platformLabel: '社交平台' }),
-      summary: { endpoint: endpoint?.id || rawPath },
+      assistantMessage: buildMissingNewApiTokenMessage(recharge.paymentUrl, recharge, { platformLabel: '社交平台' }),
+      summary: { endpoint: endpoint?.id || rawPath, errorKind: 'missing_token', recoverable: true },
       data: { recharge },
       files: [],
       nextActions: [
-        `打开充值/开通链接:${recharge.paymentUrl}`,
-        '配置以 r: 开头的会话 token 后重新调用'
-      ],
-      warnings: [],
-      errors: []
-    };
-  }
-  if (isSkToken(token)) {
-    const recharge = await buildVocRechargeInfo();
-    return {
-      status: 'needs_valid_token',
-      assistantMessage: buildWrongTokenTypeMessage(recharge.paymentUrl, recharge, { platformLabel: '社交平台' }),
-      summary: { endpoint: endpoint?.id || rawPath, tokenType: 'sk-' },
-      data: { recharge },
-      files: [],
-      nextActions: [
-        '从充值/开通页复制以 r: 开头的会话 token(不是 sk- 开头的 AIGate API Key)',
-        `打开充值/开通链接:${recharge.paymentUrl}`
+        '从 ~/.claude/settings.json 取 env.ANTHROPIC_AUTH_TOKEN(sk-),用 FMODE_API_KEY=sk-… 或入参 newapiToken 传入后重新调用',
+        '仍不行再回退以 r: 开头的会话 token;仅当确认是 402 余额不足时才打开充值链接'
       ],
       warnings: [],
       errors: []
@@ -221,20 +222,28 @@ async function callVocApi(input = {}) {
     body = parts.body;
   }
 
+  // 已登记接口可带 channel 字段:social 走社媒中转网关(voc-social,小红书/抖音内容评论等),
+  // ecommerce 走创作者数据网关(voc-e-commerce,星图/蒲公英创作者侧结构化数据)。两套网关鉴权、计费、
+  // 错误处理完全同源,只是根地址不同。VOC 默认 social;未登记的 rawPath 调用可用 input.channel 覆盖。
+  const channel = String((endpoint && endpoint.channel) || input.channel || 'social').toLowerCase();
+  const callGateway = channel === 'ecommerce' ? callEcommerceGateway : callSocialGateway;
+
   try {
-    const result = await callSocialGateway({
+    const result = await callGateway({
       proxyPath,
       method,
       query,
       body,
       token,
+      fallbackToken,
       baseUrl: input.baseUrl,
       retries: Number.isFinite(input.retries) ? input.retries : 3
     });
     return okResult({
-      assistantMessage: `调用成功:${proxyPath}(${method})。`,
+      assistantMessage: `调用成功:${proxyPath}(${method},${channel} 通道)。`,
       summary: {
         endpoint: endpoint?.id || proxyPath,
+        channel,
         method,
         proxyPath,
         billing: endpoint?.billing || 1,
@@ -248,33 +257,53 @@ async function callVocApi(input = {}) {
     const safeMessage = redactSecret(error && error.message ? error.message : 'request failed');
 
     if (kind === 'auth') {
-      const recharge = await buildVocRechargeInfo({ token });
+      // sk- 与 sessionToken(若有)都未通过校验。不把底层「未入仓」/鉴权报错甩给用户,只给友好提示。
+      const recharge = await buildVocRechargeInfo({ token: sessionToken || token });
       return {
         status: 'needs_valid_token',
         assistantMessage: [
-          '当前 VOC-AI 数据服务 token 没有通过校验,暂时不能调用该接口。',
+          '当前 token 没有通过校验,暂时不能调用该接口——这是 token 缺失/无效/失效的**可恢复**问题,不是关键词/类目/参数问题,也不代表这个功能用不了、更不是余额不足。',
+          '',
+          '优先自救:NewAPI(fmode-api)计费用的 `sk-` 就是 Claude Code 的 `ANTHROPIC_AUTH_TOKEN`(在 `~/.claude/settings.json` 的 `env` 里)。请取出它(确认 `sk-` 开头、`ANTHROPIC_BASE_URL` 指向 `api.fmode.cn`),用 `FMODE_API_KEY=sk-…` 或入参 `newapiToken` 传入后重试。',
           '',
-          '这是 token 无效或类型不对,不是关键词/类目/参数问题:需要从充值/开通页复制的、以 r: 开头的会话 token(不要用 sk- 开头的 AIGate API Key)。',
+          '若 `sk-` 仍校验不过,再回退以 `r:` 开头的会话 token。',
           '',
-          `请打开充值/开通链接:${recharge.paymentUrl}`
+          `(仅当确认是 402 余额不足时才需充值:${recharge.paymentUrl})`
         ].join('\n'),
-        summary: { endpoint: endpoint?.id || proxyPath, errorKind: kind, httpStatus },
+        summary: { endpoint: endpoint?.id || proxyPath, channel, errorKind: kind, httpStatus, recoverable: true },
         data: { recharge },
         files: [],
-        nextActions: [`打开充值/开通链接:${recharge.paymentUrl}`, '配置以 r: 开头的 session token 后重试'],
+        nextActions: [
+          '从 ~/.claude/settings.json 取 env.ANTHROPIC_AUTH_TOKEN(sk-),用 FMODE_API_KEY=sk-… 或入参 newapiToken 传入后重试',
+          '仍不行再回退以 r: 开头的 session token;仅当确认是 402 余额不足时才打开充值链接'
+        ],
         warnings: [],
         errors: []
       };
     }
     if (kind === 'billing') {
-      const recharge = await buildVocRechargeInfo({ token });
+      // 402:NewAPI(fmode-api)余额不足,跳转 fmode-api 余额充值弹窗。
+      const fmodeApiRechargeUrl = buildFmodeApiRechargeUrl();
       return {
         status: 'needs_recharge',
-        assistantMessage: buildRechargeRequiredMessage(recharge.paymentUrl, recharge, { platformLabel: '社交平台' }),
-        summary: { endpoint: endpoint?.id || proxyPath, errorKind: kind, httpStatus },
-        data: { recharge },
+        assistantMessage: buildFmodeApiRechargeMessage(fmodeApiRechargeUrl, { platformLabel: '社交平台' }),
+        summary: { endpoint: endpoint?.id || proxyPath, channel, errorKind: kind, httpStatus },
+        data: { recharge: { paymentUrl: fmodeApiRechargeUrl, kind: 'fmode-api' } },
+        files: [],
+        nextActions: [`打开充值链接补充余额:${fmodeApiRechargeUrl}`],
+        warnings: [],
+        errors: []
+      };
+    }
+    if (kind === 'permission') {
+      // 403:用户被禁用/无权限,区别于余额不足,不引导充值。
+      return {
+        status: 'needs_permission',
+        assistantMessage: buildPermissionDeniedMessage({ platformLabel: '社交平台' }),
+        summary: { endpoint: endpoint?.id || proxyPath, channel, errorKind: kind, httpStatus },
+        data: {},
         files: [],
-        nextActions: [`打开充值链接补充额度:${recharge.paymentUrl}`],
+        nextActions: ['联系服务方确认账号状态或接口权限后重试'],
         warnings: [],
         errors: []
       };
@@ -287,7 +316,7 @@ async function callVocApi(input = {}) {
           '',
           '这不是余额不足,也不是类目不支持:请检查参数是否符合接口文档(可用 voc_api_doc 查看),修正后重试。'
         ].join('\n'),
-        summary: { endpoint: endpoint?.id || proxyPath, errorKind: kind, httpStatus },
+        summary: { endpoint: endpoint?.id || proxyPath, channel, errorKind: kind, httpStatus },
         data: { message: safeMessage },
         files: [],
         nextActions: ['用 voc_api_doc 核对参数', '修正参数后重新调用'],

+ 13 - 27
claude-code/claude-code-voc-intelligence/mcp/src/tools/xiaohongshu-trend-run.js

@@ -2,7 +2,7 @@
 const fs = require('fs');
 const path = require('path');
 const { okResult, errorResult } = require('../core/result-envelope');
-const { readXiaohongshuToken } = require('../core/credentials');
+const { readXiaohongshuToken, readNewApiToken } = require('../core/credentials');
 const { buildSampleDataset } = require('../features/xiaohongshu-trend/sample-data');
 const { collectLiveDataset } = require('../features/xiaohongshu-trend/live-collector');
 const { cacheEvidenceAssets } = require('../features/xiaohongshu-trend/assets');
@@ -11,9 +11,9 @@ const { trendMemoryPath, readTrendMemory } = require('../features/xiaohongshu-tr
 const { buildNoSampleFallbackMessage } = require('../core/evidence-quality');
 const {
   buildVocRechargeInfo,
-  buildMissingTokenMessage,
+  buildMissingNewApiTokenMessage,
   buildRechargeRequiredMessage,
-  buildWrongTokenTypeMessage
+  buildFmodeApiRechargeUrl
 } = require('../core/payment-links');
 
 function parseArgs(argv) {
@@ -150,29 +150,14 @@ async function runXiaohongshuTrend(input = {}) {
     dataset = buildSampleDataset(profile);
     warnings.push('P0 阶段使用 sample 演示数据,真实采集需要接入 VOC 服务。');
   } else if (collectionMode === 'live') {
-    const token = readXiaohongshuToken(input);
-    if (token && /^\s*sk-/i.test(token)) {
-      const recharge = await buildVocRechargeInfo();
-      return {
-        status: 'needs_valid_token',
-        assistantMessage: buildWrongTokenTypeMessage(recharge.paymentUrl, recharge, { platformLabel: '小红书' }),
-        summary: { requestedCollectionMode: collectionMode, tokenType: 'sk-' },
-        data: { requestedCollectionMode: collectionMode, recharge },
-        files: [],
-        nextActions: [
-          '从充值/开通页复制以 r: 开头的会话 token(不是 sk- 开头的 AIGate API Key)',
-          `打开充值/开通链接:${recharge.paymentUrl}`,
-          '配置正确的 r: token 后重新运行 live 模式'
-        ],
-        warnings: [],
-        errors: []
-      };
-    }
+    // 计费优先走 newapi 的 sk- token(与 voc_api_call 一致,server.fmode.cn/api/voc-social 同一网关
+    // 已验证 Bearer sk- 可采集),读不到再回退平台会话 token。不再把 sk- 误判为「类型错误」。
+    const token = readNewApiToken(input) || readXiaohongshuToken(input);
     if (!token) {
       const recharge = await buildVocRechargeInfo();
       return {
         status: 'needs_token',
-        assistantMessage: buildMissingTokenMessage(recharge.paymentUrl, recharge),
+        assistantMessage: buildMissingNewApiTokenMessage(recharge.paymentUrl, recharge, { platformLabel: '小红书' }),
         summary: { requestedCollectionMode: collectionMode },
         data: {
           requestedCollectionMode: collectionMode,
@@ -180,8 +165,9 @@ async function runXiaohongshuTrend(input = {}) {
         },
         files: [],
         nextActions: [
-          `打开充值/开通链接:${recharge.paymentUrl}`,
-          '充值完成后配置 session token,再重新运行 live 模式',
+          '从 ~/.claude/settings.json 读取 env.ANTHROPIC_AUTH_TOKEN(sk- 开头)或用 FMODE_API_KEY/newapiToken 入参重试',
+          '仍读不到时,再回退 r: 开头的会话 token,或确认是否真的 402 余额不足',
+          `确认确实是 fmode-api 余额不足/未开通时,再前往充值:${buildFmodeApiRechargeUrl()}`,
           '如果只是录制教学,可以先用 sample 模式演示完整流程'
         ],
         warnings: [],
@@ -292,11 +278,11 @@ async function runXiaohongshuTrend(input = {}) {
           assistantMessage: [
             '当前 VOC-AI 数据服务 token 没有通过校验,暂时不能进行真实小红书采集。',
             '',
-            '这是 token 无效或类型不对,不是关键词/类目问题:小红书采集需要从充值/开通页复制的、以 r: 开头的会话 token(不要用 sk- 开头的 AIGate API Key)。',
+            '这是 token 鉴权问题,不是关键词/类目问题:可能是 fmode newapi(sk-)token 未开通/未入仓,或回退的会话 token 已失效。',
             '',
-            '请确认已完成 VOC-AI 数据服务开通/充值,并重新配置以 r: 开头的 session token。',
+            '请先确认 ~/.claude/settings.json 的 env.ANTHROPIC_AUTH_TOKEN(sk- 开头、base 指向 fmode)有效;仍失败时再回退 r: 会话 token,或确认是否 402 余额不足。',
             '',
-            `充值/开通链接:${recharge.paymentUrl}`
+            `(仅当确认余额不足时才充值:${recharge.paymentUrl}`
           ].join('\n'),
           summary: {
             noteCount: 0,

+ 2 - 2
claude-code/claude-code-voc-intelligence/package-lock.json

@@ -1,12 +1,12 @@
 {
   "name": "@vocmarket/voc-skill",
-  "version": "0.3.21",
+  "version": "0.3.24",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
       "name": "@vocmarket/voc-skill",
-      "version": "0.3.21",
+      "version": "0.3.24",
       "dependencies": {
         "@modelcontextprotocol/sdk": "^1.29.0",
         "zod": "^4.4.3"

+ 1 - 1
claude-code/claude-code-voc-intelligence/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@vocmarket/voc-skill",
-  "version": "0.3.21",
+  "version": "0.3.26",
   "description": "Claude Code VOC intelligence skills for Xiaohongshu and Douyin trend reports, live social VOC collection, Fmode image analysis, single-issue deep dives, boss/operator action plans, and multi-turn memory.",
   "type": "commonjs",
   "bin": {

+ 3 - 3
claude-code/claude-code-voc-intelligence/scripts/smoke-mcp.js

@@ -304,13 +304,13 @@ async function main() {
     const apiCallSentinel = 'sk-SMOKE_WRONG_TOKEN_TYPE';
     const apiCallResult = await client.callTool({
       name: 'voc_api_call',
-      arguments: { id: 'douyin.search_general', params: { keyword: '律师' }, vocToken: apiCallSentinel }
+      arguments: { id: 'douyin.search_general', params: { keyword: '律师' }, newapiToken: apiCallSentinel, vocToken: 'r:SMOKE_INVALID_SESSION_TOKEN' }
     });
     const apiCallStructured = apiCallResult.structuredContent || {};
     if (apiCallStructured.status !== 'needs_valid_token') {
-      throw new Error(`Expected voc_api_call to reject sk- token as needs_valid_token, got: ${JSON.stringify(apiCallStructured)}`);
+      throw new Error(`Expected voc_api_call to map invalid sk-/r: tokens to needs_valid_token (token problem, not 余额不足), got: ${JSON.stringify(apiCallStructured)}`);
     }
-    if (JSON.stringify(apiCallStructured).includes(apiCallSentinel)) {
+    if (JSON.stringify(apiCallStructured).includes(apiCallSentinel) || JSON.stringify(apiCallStructured).includes('r:SMOKE_INVALID_SESSION_TOKEN')) {
       throw new Error('voc_api_call leaked the request-scoped token');
     }
 

+ 26 - 8
claude-code/claude-code-voc-intelligence/scripts/smoke-package.js

@@ -94,6 +94,11 @@ async function smokeNoTokenRechargePrompt() {
     HOME: process.env.HOME,
     VOC_TOKEN: process.env.VOC_TOKEN,
     VOC_SOCIAL_TOKEN: process.env.VOC_SOCIAL_TOKEN,
+    FMODE_API_KEY: process.env.FMODE_API_KEY,
+    FMODE_API_TOKEN: process.env.FMODE_API_TOKEN,
+    NEWAPI_TOKEN: process.env.NEWAPI_TOKEN,
+    NEW_API_TOKEN: process.env.NEW_API_TOKEN,
+    ANTHROPIC_AUTH_TOKEN: process.env.ANTHROPIC_AUTH_TOKEN,
   };
   const tempHome = path.join(os.tmpdir(), 'claude-voc-no-token-smoke');
   const tempWorkspace = path.join(os.tmpdir(), 'claude-voc-no-token-workspace-smoke');
@@ -106,6 +111,11 @@ async function smokeNoTokenRechargePrompt() {
     [
       'VOC_TOKEN',
       'VOC_SOCIAL_TOKEN',
+      'FMODE_API_KEY',
+      'FMODE_API_TOKEN',
+      'NEWAPI_TOKEN',
+      'NEW_API_TOKEN',
+      'ANTHROPIC_AUTH_TOKEN',
     ].forEach(key => delete process.env[key]);
     const result = await runXiaohongshuTrend({
       collectionMode: 'live',
@@ -113,10 +123,9 @@ async function smokeNoTokenRechargePrompt() {
       output: path.join(OUTPUT_ROOT, 'no-token')
     });
     const body = String(result.assistantMessage || '');
-    const hasPaymentUrl = /apig-pay/.test(body) && /Vo3ROWEvDy/.test(body);
-    const hasEarlyPaymentUrl = /apig-pay/.test(body.slice(0, 180));
-    const hasNextActionUrl = (result.nextActions || []).some(action => /apig-pay/.test(String(action)));
-    if (result.status !== 'needs_token' || !hasPaymentUrl || !hasEarlyPaymentUrl || !hasNextActionUrl || (result.errors || []).length) {
+    const hasRechargeUrl = /balance=fmodeapi/.test(body);
+    const hasNextActionUrl = (result.nextActions || []).some(action => /balance=fmodeapi/.test(String(action)));
+    if (result.status !== 'needs_token' || !hasRechargeUrl || !hasNextActionUrl || (result.errors || []).length) {
       throw new Error('no-token live path did not return a clean recharge prompt');
     }
   } finally {
@@ -138,6 +147,11 @@ async function smokeDouyinNoTokenRechargePrompt() {
     HOME: process.env.HOME,
     VOC_TOKEN: process.env.VOC_TOKEN,
     VOC_SOCIAL_TOKEN: process.env.VOC_SOCIAL_TOKEN,
+    FMODE_API_KEY: process.env.FMODE_API_KEY,
+    FMODE_API_TOKEN: process.env.FMODE_API_TOKEN,
+    NEWAPI_TOKEN: process.env.NEWAPI_TOKEN,
+    NEW_API_TOKEN: process.env.NEW_API_TOKEN,
+    ANTHROPIC_AUTH_TOKEN: process.env.ANTHROPIC_AUTH_TOKEN,
   };
   const tempHome = path.join(os.tmpdir(), 'claude-voc-douyin-no-token-smoke');
   const tempWorkspace = path.join(os.tmpdir(), 'claude-voc-douyin-no-token-workspace-smoke');
@@ -150,6 +164,11 @@ async function smokeDouyinNoTokenRechargePrompt() {
     [
       'VOC_TOKEN',
       'VOC_SOCIAL_TOKEN',
+      'FMODE_API_KEY',
+      'FMODE_API_TOKEN',
+      'NEWAPI_TOKEN',
+      'NEW_API_TOKEN',
+      'ANTHROPIC_AUTH_TOKEN',
     ].forEach(key => delete process.env[key]);
     const result = await runDouyinTrend({
       collectionMode: 'live',
@@ -157,10 +176,9 @@ async function smokeDouyinNoTokenRechargePrompt() {
       output: path.join(OUTPUT_ROOT, 'douyin-no-token')
     });
     const body = String(result.assistantMessage || '');
-    const hasPaymentUrl = /apig-pay/.test(body) && /Vo3ROWEvDy/.test(body);
-    const hasEarlyPaymentUrl = /apig-pay/.test(body.slice(0, 180));
-    const hasNextActionUrl = (result.nextActions || []).some(action => /apig-pay/.test(String(action)));
-    if (result.status !== 'needs_token' || !hasPaymentUrl || !hasEarlyPaymentUrl || !hasNextActionUrl || (result.errors || []).length) {
+    const hasRechargeUrl = /balance=fmodeapi/.test(body);
+    const hasNextActionUrl = (result.nextActions || []).some(action => /balance=fmodeapi/.test(String(action)));
+    if (result.status !== 'needs_token' || !hasRechargeUrl || !hasNextActionUrl || (result.errors || []).length) {
       throw new Error('douyin no-token live path did not return a clean recharge prompt');
     }
   } finally {

+ 1 - 1
claude-code/claude-code-voc-intelligence/skill-package-manifest.json

@@ -1,6 +1,6 @@
 {
   "name": "claude-code-voc-intelligence",
-  "version": "0.3.17",
+  "version": "0.3.26",
   "description": "Claude Code native VOC intelligence package for cross-industry social VOC workflows. Includes Xiaohongshu and Douyin trend intelligence, live token checks, evidence-card reports, single-issue VOC deep dives, boss/operator action plans, and scoped multi-turn memory.",
   "plugin": "voc-intelligence",
   "skills": [

+ 12 - 18
claude-code/claude-code-voc-intelligence/skills/douyin-trend-intelligence/SKILL.md

@@ -13,7 +13,7 @@ allowed-tools: Read Write Bash(node *)
 - 用户要求抖音趋势情报、视频评论、口播选题、短视频开头、内容趋势或社媒 VOC 时,必须运行本技能包的工具或 MCP,不要只凭经验回答。
 - 用户说“live / 真实采集 / 进入 live / 实时采集 / 抓真实数据”时,必须运行 live 模式工具。不要回复“我不能实时抓取外部数据”。本技能包已经提供本地 VOC 采集入口。
 - live 模式返回 `needs_token`、`needs_recharge` 或 `needs_valid_token` 时,必须把工具输出里的 `assistantMessage` 原样转述给用户,尤其不能省略充值/开通链接。
-- 如果工具输出里有 `nextActions`,至少转述其中带 `apig-pay` 的充值链接。
+- 如果工具输出里有 `nextActions`,转述其中的自救/充值链接(以工具实际返回为准,不要写死某个链接)
 - 第一轮只说“初步判断 / 机会假设 / 待校准”,不要说成最终结论。
 - 后续用户说“保留、不要、更偏、这个不准”等反馈时,运行偏好更新命令沉淀记忆。
 
@@ -21,8 +21,8 @@ allowed-tools: Read Write Bash(node *)
 
 - If the user asks for live collection, real collection, or entering live mode, run the local VOC tool in live mode.
 - Do not answer that you cannot fetch external data. The local VOC tool is the approved collection entry.
-- If the tool returns `needs_token`, `needs_recharge`, or `needs_valid_token`, paste its `assistantMessage` to the user and keep the payment URL visible.
-- The payment URL must be shown when there is no token or insufficient balance: `https://app.fmode.cn/dev/apig-pay/?apigid=Vo3ROWEvDy&fun_id=HOkkX72PMF`
+- If the tool returns `needs_token`, `needs_recharge`, or `needs_valid_token`, paste its `assistantMessage` to the user verbatim, including whatever self-rescue/recharge link the tool returns.
+- `needs_token` is recoverable: an `sk-` fmode newapi key (Claude Code's `ANTHROPIC_AUTH_TOKEN` in `~/.claude/settings.json`, or `~/.fmode/config.json` / `~/.claude/voc-credentials.json`) lets collection run — guide self-rescue first, do not push recharge. Only a real `402` needs recharge. 完整口径见下方「充值 / 计费口径」。
 
 ## 禁止事项(Hard Guardrails)
 
@@ -30,14 +30,14 @@ live 采集失败时,严禁做以下任何一件事:
 
 - 严禁退回/降级到联网搜索(web search)、`yt-dlp`、`ffmpeg`、手动让用户上传 mp4,或任何“绕过 VOC 接口”的抓取方式。本技能包的 VOC 本地采集是唯一批准的真实数据入口。
 - 严禁输出“VOC 只支持某些类目”“律师/某赛道不可用”“系统设计上有类目限制”这类结论。这是错误结论:任何关键词(律师、法律、医美、教育、专业服务等)都能采集,与类目无关。
-- live 失败的真正原因只可能是这几类:token 无效或类型不对(需要 `r:` 开头的会话 token,而不是 `sk-` 开头的 AIGate API Key)、未开通或额度不足、上游接口抖动(5xx,需重试)。必须如实把工具返回的 `assistantMessage` 转述给用户,不要自行编造原因。
+- live 失败的真正原因只可能是这几类:缺 token 或 token 无效(**`sk-` 开头的 fmode newapi key 即可采集**——它就是 `~/.claude/settings.json` 的 `ANTHROPIC_AUTH_TOKEN`,也可来自 `~/.fmode/config.json` / `~/.claude/voc-credentials.json`;缺 token 先按提示自救读取,不要劝充值)、额度不足(真 402 才充值)、上游接口抖动(5xx,需重试)。必须如实把工具返回的 `assistantMessage` 转述给用户,不要自行编造原因。
 - 只有在工具明确返回 `needs_keyword_fix` 时才允许调整关键词;返回 `needs_valid_token` / `needs_token` / `needs_recharge` 时不要换关键词,要转述充值/开通链接。
 
 English (same rules):
 
 - On live failure, NEVER fall back to web search, `yt-dlp`, `ffmpeg`, or asking the user to upload an mp4. The local VOC tool is the only approved real-data path.
 - NEVER conclude that VOC is limited to certain categories or that a vertical (e.g. lawyers) is unsupported. Any keyword works; this is never a category problem.
-- The only real causes are: invalid/wrong-type token (need an `r:` session token, not an `sk-` AIGate key), not activated / no balance, or upstream 5xx jitter (retry). Relay the tool's `assistantMessage` verbatim instead of inventing a reason.
+- The only real causes are: missing/invalid token (an `sk-` fmode newapi key — Claude Code's `ANTHROPIC_AUTH_TOKEN` — is valid for collection; self-rescue by reading it first, don't push recharge), insufficient balance (only a real 402 needs recharge), or upstream 5xx jitter (retry). Relay the tool's `assistantMessage` verbatim instead of inventing a reason.
 - Only adjust keywords when the tool returns `needs_keyword_fix`. For `needs_valid_token` / `needs_token` / `needs_recharge`, do not change keywords — surface the payment/activation link.
 
 ## Douyin Live Quick Repair
@@ -71,24 +71,18 @@ node "<插件目录>/mcp/src/tools/douyin-trend-run.js" --collection-mode live -
 
 运行后把命令输出正文直接发给用户。不要展示 JSON、summary、data、files 或调试日志。
 
-## 充值链接口径
+## 充值 / 计费口径(简版;完整对照见 voc-api-catalog 技能的「错误码速查」references/error-codes.md)
 
-没有 token 或余额不足时,用户必须看到:
-
-```text
-https://app.fmode.cn/dev/apig-pay/?apigid=Vo3ROWEvDy&fun_id=HOkkX72PMF
-```
-
-套餐入口可作为补充:
-
-```text
-https://app.fmode.cn/dev/apig-pay/#/workshop/99
-```
+- 缺 token(`needs_token`)= 可恢复、不是没钱:先自救读 `~/.claude/settings.json` 的 `sk-` fmode key(或 `~/.fmode/config.json` / `~/.claude/voc-credentials.json`),用 `FMODE_API_KEY=sk-…` 重试,不要劝充值。
+- 只有真 `402 余额不足` 才充值,入口 `https://app.fmode.cn/dev/studio/?balance=fmodeapi`(NewAPI/fmode-api 计费);`401`=token、`403`=权限,都不充值。`apig-pay/?apigid=Vo3ROWEvDy&fun_id=HOkkX72PMF` 仅限 `r:` 会话 token 余额补充。
+- 实际充值/自救链接以工具返回的 `assistantMessage` / `nextActions` 为准,不要写死。
 
 ## 推荐用户启动话术
 
+> 通用模板:把 `{你的行业/品类}` 替换成用户真实所在的行业或品类,不要内置任何特定行业。
+
 ```text
-帮我做一份家装全屋定制行业的抖音趋势情报。
+帮我做一份 {你的行业/品类} 的抖音趋势情报。
 先用演示样例跑通流程,不要真实采集。
 在聊天里给我第一轮样本观察和待确认问题。
 ```

+ 1 - 3
claude-code/claude-code-voc-intelligence/skills/douyin-trend-intelligence/references/live-mode.md

@@ -2,10 +2,8 @@
 
 ## 默认规则
 
-- 先检查 token
 - 样本量保持小
-- 没 token 时给充值链接,不要暴露 403
-- 余额不足时也给充值链接,不要暴露底层错误
+- 计费/充值口径走简版:缺 token 先自救(读 `~/.claude/settings.json` 的 `sk-` fmode key 重试),不要直接甩充值链接、不要暴露 401/403;只有真 `402` 才给充值链接 `https://app.fmode.cn/dev/studio/?balance=fmodeapi`。**完整口径(401/402/403 对照、回退、apig-pay `r:` 补充链)见 voc-api-catalog 技能的「错误码速查」references/error-codes.md**
 - 用户只需要看到“怎么继续”
 
 ## 推荐默认参数

+ 2 - 2
claude-code/claude-code-voc-intelligence/skills/douyin-trend-intelligence/references/user-workflow.md

@@ -4,8 +4,8 @@
 
 1. 先判断用户是不是要“样例演示”还是“真实采集”
 2. 样例演示直接跑 `voc_douyin_trend_run` 的 `sample` 模式
-3. 真实采集先跑 `voc_douyin_token_check`
-4. token 可用后,再跑 `voc_douyin_trend_run` 的 `live` 模式
+3. 真实采集**直接跑 `voc_douyin_trend_run` 的 `live` 模式**即可——大多数装好 Claude Code(带 fmode `sk-` key)的机器已经具备采集所需 token,**不必先做检测**
+4. 只有当 `live` 明确报「缺 token / 鉴权失败」时,再用 `voc_douyin_token_check` 诊断;它会识别全部来源(`~/.claude/settings.json` 的 `ANTHROPIC_AUTH_TOKEN`、`~/.claude/voc-credentials.json` 的 `fmodeApiKey`、`~/.fmode/config.json` 等)。按提示自救(读 SK / 重试),**确认确实是 402 余额不足时才给充值链接**,不要一上来就把用户甩去充值
 5. 用户反馈“保留、不要、更偏、这个不准”时,跑 `voc_douyin_preference_update`
 
 ## 用户常见输入

+ 6 - 4
claude-code/claude-code-voc-intelligence/skills/fmode-image-analysis/SKILL.md

@@ -5,6 +5,8 @@ description: Analyze images, screenshots, posters, UI captures, charts, product
 
 # Fmode Image Analysis
 
+> 图像/视频分析**推荐改用 `fmode-vision` 技能包**(功能更完整:单轮/多轮聚焦分析、视频帧分析、批量处理)。本技能是 Claude Code 内置 MCP 工具 `fmode_image_analysis` 的轻量图片识别入口/回退,适合“当前对话里已有图片、需要快速识图”的场景;需要更精细或视频/批量处理时,引导用户/Agent 改用 `fmode-vision`。
+
 ## Core Rule
 
 Use MCP tool `fmode_image_analysis` for image understanding. Do not ask the user to install a VS Code image-recognition plugin when this installed Fmode tool can handle the image.
@@ -15,7 +17,7 @@ Default to:
 
 - `baseUrl`: `https://api.fmode.cn`
 - `path`: `v1/chat/completions`
-- `model`: `doubao-seed-2-0-pro-260215`
+- `model`: `doubao-seed-2-0-pro-260215`(默认/推荐,**不强制使用单一模型**——可按可用权限改用其他多模态模型,如 `gpt-4o` 等;通过工具入参 `model` 覆盖即可)
 
 Auth and billing should use the configured platform user token. Never hardcode or echo tokens.
 
@@ -84,11 +86,11 @@ Environment variables:
 - `DOUBAO_VISION_TOKEN`
 - `VIDEO_ANALYSIS_TOKEN`
 
-Friendly states:
+Friendly states (aligned with the fmode-api billing 口径 — self-rescue first, recharge only on a real 402):
 
-- Missing token: return `needs_token` with the platform open/recharge link and `errors=[]`.
+- Missing token (`needs_token`): this is not a balance problem — guide self-rescue first. Read the `sk-` fmode key from `~/.claude/settings.json` (`env.ANTHROPIC_AUTH_TOKEN`), `~/.fmode/config.json`, or `~/.claude/voc-credentials.json`. Do NOT push a recharge link here.
 - Invalid token: return `needs_valid_token` and ask for a valid platform token.
-- Not opened or quota exhausted: return `needs_recharge` with the open/recharge link and `errors=[]`.
+- Quota exhausted / real 402: return `needs_recharge` with the fmode-api recharge link `https://app.fmode.cn/dev/studio/?balance=fmodeapi` and `errors=[]`.
 - Success: return `ok` with the analysis in chat.
 
 Do not expose raw upstream errors, `Authorization`, bearer tokens, session tokens, stack traces, or model keys.

+ 53 - 8
claude-code/claude-code-voc-intelligence/skills/voc-api-catalog/SKILL.md

@@ -1,6 +1,6 @@
 ---
 name: voc-api-catalog
-description: 清单驱动的 VOC 社交数据采集。把所有转发接口做成清单,按需查清单、读参数文档,自己拼参数完成任意行业/任意方向的社交数据采集(目前覆盖抖音、TikTok、小红书、Instagram、YouTube、Twitter/X、LinkedIn、微博、B站、快手、知乎、Reddit、Threads、微信视频号 等 18 个国内外社媒平台)。当用户要采集某关键词的社交内容/评论、要调用某个社交数据接口、或现有专用工具不覆盖某接口时使用。
+description: 清单驱动的 VOC 数据采集,覆盖两类情报源。把所有转发接口做成清单,按需查清单、读参数文档,自己拼参数完成任意行业/任意方向的数据采集。两条通道:①社媒内容(channel=social,默认)覆盖抖音、TikTok、小红书、Instagram、YouTube、Twitter/X、LinkedIn、微博、B站、快手、知乎、Reddit、Threads、微信视频号 等 18 个国内外社媒平台的搜索/评论/详情;②创作者侧情报(channel=ecommerce覆盖抖音星图、小红书蒲公英(PGY)的创作者搜索、画像、受众/粉丝分布、内容与评论关键词、笔记/视频绩效与性价比等结构化数据,用于理解创作者生态、竞对达人布局、受众匹配与内容方向验证。当用户要采集某关键词的社交内容/评论、要做竞对/创作者生态/受众洞察/选题/内容战略相关的分析、要调用某个数据接口、或现有专用工具不覆盖某接口时使用。
 ---
 
 # VOC 接口清单驱动采集
@@ -15,6 +15,15 @@ VOC 后端是一个**通用转发网关**(`https://server.fmode.cn/api/voc-soc
 
 清单里没有的接口,也可以直接用 `voc_api_call` 传 `rawPath` + `method` + `params` 调用,无需改代码。
 
+## 两条通道:社媒内容 vs 创作者侧情报(channel)
+
+清单里每个接口都带 `channel` 字段,`voc_api_call` 据此**自动**选用对应网关,你通常无需关心:
+
+- `channel="social"`(默认):走社媒中转网关 `https://server.fmode.cn/api/voc-social`。抖音/小红书等 18 平台的内容搜索、评论、用户/笔记详情等 VOC 口碑采集走这条。
+- `channel="ecommerce"`:走创作者数据网关 `https://server.fmode.cn/api/voc-e-commerce`。抖音星图、小红书蒲公英(PGY)的**创作者侧结构化数据**(创作者搜索、画像、受众/粉丝分布、内容与评论关键词、笔记/视频绩效、报价与性价比等)走这条。这些是公开市场层面的创作者经营数据,VOC 用它服务**创作者生态理解、竞对达人布局、受众匹配与内容方向验证**,不是用来替用户做投放采买决策。
+
+两套网关**鉴权、计费、错误处理完全同源**(同一把 `sk-`/`r:` token、同样的 401/402/403 语义、同样的回退逻辑),只是根地址不同。调用清单里**没有**的创作者数据接口时,传 `rawPath` 的同时显式带 `channel="ecommerce"` 即可路由到该网关(社媒接口不传 channel 默认 social)。
+
 ## 工具
 
 - `voc_api_search`:检索接口清单。入参 `query`(关键词,可选)、`platform`(如 douyin / tiktok / xiaohongshu / instagram / youtube / twitter / linkedin 等 18 个平台 key,可选)、`tag`(可选)。返回接口 id、标题、method、proxyPath、必填参数。
@@ -33,23 +42,59 @@ VOC 后端是一个**通用转发网关**(`https://server.fmode.cn/api/voc-soc
 4. `voc_api_call` 用真实关键词调用;翻页/拉评论时把上一次返回里的 cursor / id 透传进下一次调用。
 5. 用返回数据继续后续分析(可交给 voc-issue-pool、voc-content-plan 等技能)。
 
-## Token
+## 创作者侧情报(channel=ecommerce)
+
+抖音星图 / 小红书蒲公英(PGY)的创作者数据是 VOC 在**创作者生态**维度的情报源——它服务的是 VOC 一贯的「内容战略、竞对理解、受众洞察、选题与脚本」闭环,而**不是**「替用户挑达人投广告」。同一套数据用来回答这些 VOC 问题:
+
+- **创作者生态 / 竞对达人布局**:某品类、某竞品周边在合作哪些量级的创作者、内容走什么方向、谁的影响力在涨。
+- **受众匹配**:某创作者的粉丝画像 / 受众分布是否贴合品牌目标人群,用于判断内容触达的相关性。
+- **内容方向验证**:某类内容主题在创作者侧的真实表现与受众反馈(内容关键词、评论热词、笔记/视频绩效),为选题与脚本提供事实依据。
+- **创作者能力的客观评估**:用公开绩效 / 性价比数据客观描述一个创作者的内容能力与转化表现(作为洞察结论,不是采买建议)。
+
+数据按「**先定位创作者、再补结构化数据**」两步取:
+
+1. **定位创作者**(拿到创作者列表与 id):
+   - 抖音星图:`douyin.xingtu.creator_search`(按 `keyword` 搜,可按粉丝量级 / 报价 / 内容标签筛)或轻量版 `douyin.xingtu.creator_search_light`;返回项里的 `star_id` 即详情接口入参 `oAuthorId`。
+   - 小红书蒲公英:`xiaohongshu.pgy.creator_search`(按 `keyword` 搜)或 `xiaohongshu.pgy.content_square_notes`(从内容广场反查创作者 / 笔记);返回项里的 `userId` 即详情接口入参。`xiaohongshu.pgy.similar_creators` 可由一个创作者扩展出同类创作者,快速铺开生态图。
+2. **补结构化数据**(用第一步拿到的 id 逐个补,按情报目的取所需接口):
+   - 画像与受众匹配:抖音 `douyin.xingtu.creator_profile` / `marketing_metrics` / `audience_distribution` / `follower_distribution`;小红书 `xiaohongshu.pgy.creator_profile` / `creator_core_metrics` / `creator_content_tags` / `creator_feature_tags` / `follower_distribution`。
+   - 内容方向与绩效基准:抖音 `douyin.xingtu.content_keyword_analysis` / `comment_keyword_analysis` / `recommended_videos` / `item_report_analysis`;小红书 `xiaohongshu.pgy.creator_note_list` / `note_performance_metrics`。
+   - 能力与性价比的客观评估:抖音 `douyin.xingtu.cost_performance_analysis` / `conversion_analysis`;小红书 `xiaohongshu.pgy.cost_effectiveness_analysis`。
+3. 把这些创作者侧事实**喂给下游 VOC 技能**(voc-competitor-map 做竞对达人布局、voc-content-plan / voc-speaking-script 做选题与脚本、voc-issue-pool 补充创作者 / 受众视角),形成洞察结论,而非「该投谁」的采买清单。
 
-采集需要从充值/开通页复制的、以 `r:` 开头的会话 token(session token)。
-**不要**用 `~/.claude/voc-credentials.json` 里 `sk-` 开头的 AIGate API Key —— 后端不认它,会被工具直接判为 `needs_valid_token`。
+> 提示:`voc_api_search` 用「星图 创作者」「蒲公英 画像」「受众分布」「性价比」等词即可定位这些接口;`voc_api_doc` 会在请求行标注「通道 ecommerce」并列出参数。清单已登记抖音星图 32 个 + 小红书蒲公英 16 个创作者数据接口,未登记的可直接用 `voc_api_call` 传 `rawPath` + `channel="ecommerce"` 调用。
+
+## Token(计费已迁移 NewAPI)
+
+请求头统一 `Authorization: Bearer ${token}`,**优先用 NewAPI(fmode-api)的 `sk-` token**。
+
+> **这把 `sk-` 计费 token 是什么、从哪来**:它就是 **Claude Code 自己的 `ANTHROPIC_AUTH_TOKEN`**——配在用户级 **`~/.claude/settings.json` 的 `env.ANTHROPIC_AUTH_TOKEN`**(`sk-` 开头,且 `ANTHROPIC_BASE_URL` 指向 `api.fmode.cn`)。Claude Code 用户**装完技能即用,无需任何额外配置**:工具会自动从这里(以及进程环境)读到它。所以 newapi(fmode-api)≠ 某个要单独开通的东西,它用的就是你正在用的这把 fmode key。
+
+- 取值优先级:入参 `newapiToken`/`fmodeApiKey` → `.env.local` / 环境变量 `FMODE_API_KEY`·`NEWAPI_TOKEN` → `~/.claude/voc-credentials.json` 的 `fmodeApiKey` → `~/.fmode/config.json` 的 `newapiToken`/`fmodeApiToken` → **`~/.claude/settings.json` 的 `env.ANTHROPIC_AUTH_TOKEN`(Claude Code 默认入口,`sk-` 开头)**。
+- `sk-` 鉴权失败(401,含「未入仓」类报错)且存在 `r:` 开头的会话 token 时,工具会**自动回退**用 `r:` sessionToken 走原 apig 接口重试一次(过渡期:服务端未迁完 / 该号未入仓)。此回退是**正常**的原始付费路径,不是出故障。
+- 兼容:若把 `sk-` 直接填进 `VOC_TOKEN`,也会被当作 NewAPI token 使用。
+- token **绝不回显**;底层鉴权/入仓原始报错不甩给用户,只给友好提示。
+
+> **缺 token / token 无效时该怎么自救(重要,别进死循环)**:这是**可恢复**状态,不是「技能用不了」。先确认 `~/.claude/settings.json` 的 `env.ANTHROPIC_AUTH_TOKEN` 是否为 `sk-` 开头的 fmode key;若工具仍报缺 token,把它取出来用 `FMODE_API_KEY=sk-…`(或入参 `newapiToken`)传给工具再调一次。**不要**因为提示里出现充值/付费链接就让用户去点充值——**只有真正 `402 余额不足` 才需要充值**,缺 token 只是没读到这把 SK 而已。
+
+> 错误码(401/402/403 等)的完整对照、真实报文样例与处理纪律见 **`references/error-codes.md`**。
 
 ## 禁止事项(护栏)
 
 - 禁止把**入参/参数错误**(`needs_input`)误报成「采集不到数据 / 该关键词没结果 / 类目不支持」。参数错就如实说参数错,并用 `voc_api_doc` 核对后重试。
 - 禁止把**上游不稳定**(`upstream_unstable`,如 5xx / 连接超时 / fetch failed)误报成「关键词问题 / 类目不支持 / 余额不足」。如实说明是上游接口波动,稍后重试。
 - 禁止把 **token 无效/类型不对**(`needs_valid_token`)误报成「余额不足」或「类目不支持」。
+- 禁止把**缺 token / token 无效**(`needs_token` / `needs_valid_token`)误报成「这个技能用不了 / 功能不可用」——它是**可恢复**的:SK 就在 `~/.claude/settings.json` 的 `env.ANTHROPIC_AUTH_TOKEN`,取出来用 `FMODE_API_KEY=sk-…` 传入重试即可,别因此放弃或去点充值。
 - 禁止输出「某行业不可用 / 系统只支持某类目」这类结论——**任何行业、任何关键词都能采集**,前提只是 token 类型正确且有额度。
 - 失败时禁止退回 web search / yt-dlp / ffmpeg / 让用户手动传媒体文件来「绕过」采集。
 
-## 状态码含义
+## 状态码含义(详表见 `references/error-codes.md`)
 
 - `ok`:调用成功,`data.result` 是上游返回数据。
-- `needs_token` / `needs_valid_token`:没配置 token,或 token 类型不对(sk-)。提示配置 `r:` token。
-- `needs_recharge`:额度不足,提示充值。
+- `needs_token`:没读到任何 token(**可恢复,不是没钱、不是功能用不了**)——优先去 `~/.claude/settings.json` 取 `env.ANTHROPIC_AUTH_TOKEN`(`sk-`)用 `FMODE_API_KEY=sk-…` 传入重试。`needs_valid_token`:token 缺失/失效/无效(HTTP 401)——**不是没钱**,提示配置有效 `sk-`(或回退 `r:`)token。
+- `needs_recharge`:**仅 HTTP 402(余额不足)**,提示充值,跳 `https://app.fmode.cn/dev/studio/?balance=fmodeapi`。
+- `needs_permission`:**HTTP 403(账号禁用/无权限)**,**≠ 余额不足**,不引导充值,提示联系服务方确认权限。
 - `needs_input`:必填参数缺失或参数错误(不是类目/余额问题)。
-- `upstream_unstable`:上游接口报错或波动,稍后重试。
+- `upstream_unstable`:上游接口报错或波动(5xx / fetch failed),稍后重试。
+
+> ⚠️ 不要把 **403/401** 一律说成「余额不足」。只有 **402** 才是真的没钱要充值;403 是权限、401 是 token 问题。

+ 79 - 0
claude-code/claude-code-voc-intelligence/skills/voc-api-catalog/references/error-codes.md

@@ -0,0 +1,79 @@
+# VOC 社交数据采集 · 错误码速查
+
+> 给 Agent 按需查阅。**核心纪律:不是所有报错都是「余额不足」,也不是所有报错都代表「功能用不了」。** 只有 **HTTP 402** 才提示充值;
+> **401 = token 问题**(缺失/失效/类型不对),**403 = 账号禁用/无权限**,都**不是没钱**,不要引导充值。
+> **缺 token / 401 是可恢复的**:NewAPI 计费用的 `sk-` 就是 Claude Code 的 `ANTHROPIC_AUTH_TOKEN`(在 `~/.claude/settings.json` 的 `env` 里),取出来用 `FMODE_API_KEY=sk-…` 传入重试即可,**别当成「这个技能不能用」而放弃或去点充值**。
+
+适用范围:`voc_api_call` / `voc_api_doc`,**两条通道同源**——社媒网关 `https://server.fmode.cn/api/voc-social/<proxyPath>`(`channel=social`,默认)与创作者数据网关 `https://server.fmode.cn/api/voc-e-commerce/<proxyPath>`(`channel=ecommerce`)的鉴权、计费、错误码语义完全一致,下表对两者通用。本速查也是各 trend / 采集技能充值计费口径的**单一权威来源**,技能里只放简版摘要并指回这里。
+
+## 一、总览表(HTTP 状态 → 含义 → 工具返回 → 给客户的话术 → Agent 动作)
+
+| HTTP | 后端 `mess` 样例 | 判定 kind | 工具 status | 给客户 Agent 的话术 | Agent 该做什么 |
+|------|------------------|-----------|-------------|----------------------|----------------|
+| 200 | —(`{"code":200,"data":{...}}`) | — | `ok` | 正常返回 | 直接用 `data.result` |
+| 401 | `Invalid NewAPI token` / `Missing NewAPI token` / `请输入API_KEY或用户sessionToken` / `当前用户不存在,无使用权限` | `auth` | `needs_valid_token`(无任何 token 时 `needs_token`) | 「token 缺失/失效/类型不对,**不是没钱、也不是关键词/类目问题,更不是功能用不了**」 | **先**从 `~/.claude/settings.json` 取 `env.ANTHROPIC_AUTH_TOKEN`(`sk-`),用 `FMODE_API_KEY=sk-…` 传入重试;不行再回退 `r:` sessionToken |
+| 402 | `余额不足` / `额度不足` | `billing` | `needs_recharge` | 「余额不足,请充值」 | 给充值链接 `https://app.fmode.cn/dev/studio/?balance=fmodeapi`(自动打开余额弹窗) |
+| 403 | `用户禁用` / `无权限` / `permission`(**不含**余额/开通关键词) | `permission` | `needs_permission` | 「账号被禁用或没有该接口权限,**≠ 余额不足**」 | 联系服务方确认账号状态/接口权限,**不要**引导充值 |
+| 403 | 含 `未开通` / `没开通` / `余额` / `额度` / `insufficient` / `balance` | `billing` | `needs_recharge` | 「需开通/充值后使用」 | 给充值/开通链接 |
+| 400 / 422 | `参数` / `入参` / `keyword` / `bad request` | `request` | `needs_input` | 「参数有误,**不是没数据/不是类目不支持**」 | 用 `voc_api_doc` 核对参数后重试 |
+| 5xx / 连接失败 | `fetch failed` / 超时 / `500` | `upstream` | `upstream_unstable` | 「上游接口波动」 | 稍后重试,不要误报成关键词/余额问题 |
+
+## 二、真实报文样例(实打抓取)
+
+```text
+# 有效 sk- token(NewAPI / fmode-api)
+HTTP 200  {"code":200,"data":{"code":0,"data":{...}}}
+
+# sk- token 无效/写错
+HTTP 401  {"code":401,"mess":"Invalid NewAPI token"}
+
+# 发的是旧版 Parse sessionToken(r:),后端已迁 NewAPI 计费
+HTTP 401  {"code":401,"mess":"Missing NewAPI token"}
+
+# 完全没带 Authorization
+HTTP 401  {"code":401,"mess":"请输入API_KEY或用户sessionToken"}
+
+# token 对应的用户不存在
+HTTP 401  {"code":401,"mess":"当前用户不存在,无使用权限"}
+
+# 余额不足(NewAPI 计费额度用尽)—— 仅此情形才引导充值
+HTTP 402  {"code":402,"mess":"余额不足"}
+
+# 用户被禁用 / 无该接口权限(区别于余额不足)
+HTTP 403  {"code":403,"mess":"用户禁用或无权限"}
+```
+
+## 三、Token 优先级与回退(避开「入仓」错误)
+
+计费已迁移到 **NewAPI(fmode-api)**,请求头统一 `Authorization: Bearer ${token}`:
+
+> **这把 `sk-` 是什么**:它就是 **Claude Code 自己的 `ANTHROPIC_AUTH_TOKEN`**(配在 `~/.claude/settings.json` 的 `env`,`sk-` 开头,`ANTHROPIC_BASE_URL` 指向 `api.fmode.cn`)。所以 Claude Code 用户**装完即用、零额外配置**,工具会自动从 settings.json / 进程环境读到它。newapi(fmode-api)不是要单独开通的东西,就是你正在用的这把 fmode key。
+
+1. **优先**用 NewAPI 的 `sk-` token,取值优先级:
+   入参 `newapiToken/fmodeApiKey` → `.env.local` / 环境变量 `FMODE_API_KEY`/`NEWAPI_TOKEN` → `~/.claude/voc-credentials.json` 的 `fmodeApiKey` → `~/.fmode/config.json` 的 `newapiToken/fmodeApiToken` → **`~/.claude/settings.json` 的 `env.ANTHROPIC_AUTH_TOKEN`(Claude Code 默认入口)**。
+   - 兼容历史:若 `VOC_TOKEN` 槽里填的就是 `sk-`,也当作 NewAPI token 使用。
+   - 若工具报 `needs_token`/`needs_valid_token`:先去 `~/.claude/settings.json` 取 `env.ANTHROPIC_AUTH_TOKEN`,用 `FMODE_API_KEY=sk-…` 传入重试——**这是缺 token 的标准自救,不是去点充值**。
+2. 若 `sk-` token **鉴权失败(kind=auth / 401,含「未入仓」类报错)** 且存在平台 `r:` sessionToken,**自动回退** sessionToken 重试一次。这正是规避「用户拿 token 请求时遇到入仓错误」的方式——不再因为 token 是 `sk-` 就直接拒绝。
+3. **402(余额不足)/ 403(无权限)不回退**——它们是终态,按上表处理。
+
+> **充值入口分两条链(按实际走哪条计费而定)**:
+> - `sk-` NewAPI / fmode-api 计费链(默认,绝大多数缺额场景)→ `https://app.fmode.cn/dev/studio/?balance=fmodeapi`
+> - `r:` 会话 token 链(仅当走 `r:` sessionToken 回退路径、该 token 余额不足时)→ `https://app.fmode.cn/dev/apig-pay/?apigid=Vo3ROWEvDy&fun_id=HOkkX72PMF`
+>
+> 运行时以工具返回的 `assistantMessage` / `nextActions` 链接为准转述,不要在话术里写死某一条。
+4. 底层「未入仓」/鉴权原始报错**不甩给用户**,对外只给上表的友好提示。
+
+## 四、判定规则摘要(`classifyApiError`)
+
+判定顺序(命中即返回):
+
+1. 文案含「用户/账号信息不存在、未登录、登录失效、请输入…token、sessiontoken」→ `auth`
+2. `status===401` 或文案含「invalid token / 无效token / 未授权 / unauthorized」→ `auth`
+3. `status===402` 或文案含「余额不足 / 额度不足 / 未开通 / 开通…权限 / insufficient / balance / quota / payment / 充值」→ `billing`
+4. `status===403` **且**含余额/开通类关键词 → `billing`
+5. 文案含「参数 / 入参 / keyword / 关键词 / bad request」或 `status∈{400,422}` → `request`
+6. `status>=500` → `upstream`
+7. `status===403` 或文案含「permission / 权限 / 无权限」→ `permission`
+8. 其它 → `upstream`
+
+> 注意第 4 与第 7 条的区别:**带「余额/开通」关键词的 403 才当充值**;**纯权限 403 一律 `permission`,不充值**。

+ 1 - 1
claude-code/claude-code-voc-intelligence/skills/voc-business-workflow/SKILL.md

@@ -40,7 +40,7 @@ description: Run the full VOC business workflow from natural boss language: coll
 ## 用户可说的话
 
 ```text
-帮我看一下家居定制最近用户在关心什么,并告诉我先改哪里、下周发什么。
+帮我看一下 {你的行业/品类} 最近用户在关心什么,并告诉我先改哪里、下周发什么。
 ```
 
 ```text

+ 3 - 3
claude-code/claude-code-voc-intelligence/skills/voc-competitor-map/SKILL.md

@@ -21,13 +21,13 @@ allowed-tools: Read Write Bash(node *)
 ## CLI 命令
 
 ```bash
-node "<插件目录>/mcp/src/tools/voc-competitor-map-run.js" --brand "示例品牌A" --city "本地" --category "家居定制" --assistant-message-only
+node "<插件目录>/mcp/src/tools/voc-competitor-map-run.js" --brand "示例品牌A" --city "本地" --category "<你的品类>" --assistant-message-only
 ```
 
 带竞品名单:
 
 ```bash
-node "<插件目录>/mcp/src/tools/voc-competitor-map-run.js" --brand "示例品牌A" --city "本地" --category "家居定制" --competitors "竞品A,竞品B,竞品C" --assistant-message-only
+node "<插件目录>/mcp/src/tools/voc-competitor-map-run.js" --brand "示例品牌A" --city "本地" --category "<你的品类>" --competitors "竞品A,竞品B,竞品C" --assistant-message-only
 ```
 
 ## 输出结构
@@ -48,7 +48,7 @@ node "<插件目录>/mcp/src/tools/voc-competitor-map-run.js" --brand "示例品
 ## 典型用户话术
 
 ```text
-我是做家居定制的,不知道竞品是谁,帮我先做一份竞品图谱。
+我是做 {你的行业/品类} 的,不知道竞品是谁,帮我先做一份竞品图谱。
 ```
 
 ```text

+ 2 - 2
claude-code/claude-code-voc-intelligence/skills/voc-content-plan/SKILL.md

@@ -22,7 +22,7 @@ allowed-tools: Read Write Bash(node *)
 ## CLI 命令
 
 ```bash
-node "<插件目录>/mcp/src/tools/voc-content-plan-run.js" --brand "示例品牌A" --industry "家居定制" --issues "第一次买怕踩雷;觉得价格贵;怕质量不稳定" --evidence-text "用户评论:第一次买不知道怎么选,怕踩雷;价格有点高,不知道方案值不值。" --assistant-message-only
+node "<插件目录>/mcp/src/tools/voc-content-plan-run.js" --brand "示例品牌A" --industry "<你的行业>" --issues "第一次买怕踩雷;觉得价格贵;怕质量不稳定" --evidence-text "用户评论:第一次买不知道怎么选,怕踩雷;价格有点高,不知道方案值不值。" --assistant-message-only
 ```
 
 带报告文件:
@@ -34,7 +34,7 @@ node "<插件目录>/mcp/src/tools/voc-content-plan-run.js" --brand "示例品
 多问题示例:
 
 ```bash
-node "<插件目录>/mcp/src/tools/voc-content-plan-run.js" --brand "示例品牌A" --industry "家居定制" --issues "第一次买怎么选最稳;贵在哪/值在哪;怎么对比才不踩雷;质量怎么判断;哪几种方案更适合;售后怎么兜底;优惠规则怎么讲清楚" --evidence-text "用户评论:第一次买不知道怎么选,怕踩雷;价格有点高,不确定值不值;担心质量和售后。" --assistant-message-only
+node "<插件目录>/mcp/src/tools/voc-content-plan-run.js" --brand "示例品牌A" --industry "<你的行业>" --issues "第一次买怎么选最稳;贵在哪/值在哪;怎么对比才不踩雷;质量怎么判断;哪几种方案更适合;售后怎么兜底;优惠规则怎么讲清楚" --evidence-text "用户评论:第一次买不知道怎么选,怕踩雷;价格有点高,不确定值不值;担心质量和售后。" --assistant-message-only
 ```
 
 ## 输出结构

+ 3 - 3
claude-code/claude-code-voc-intelligence/skills/voc-issue-pool/SKILL.md

@@ -27,19 +27,19 @@ allowed-tools: Read Write Bash(node *)
 - When the user asks for a VOC report around business pain points, first build or request a clean evidence set, then run `voc_issue_pool_run`; only after that should a single top issue be sent to `voc_problem_deep_dive_run`.
 
 ```bash
-node "<插件目录>/mcp/src/tools/voc-issue-pool-run.js" --project "示例品牌A" --industry "家居定制" --scenario "线上获客" --audience "意向用户" --evidence "第一次买不知道怎么选,怕踩雷。,价格有点高,不确定值不值。,咨询忙起来没人理。" --assistant-message-only
+node "<插件目录>/mcp/src/tools/voc-issue-pool-run.js" --project "示例品牌A" --industry "<你的行业>" --scenario "线上获客" --audience "意向用户" --evidence "第一次买不知道怎么选,怕踩雷。,价格有点高,不确定值不值。,咨询忙起来没人理。" --assistant-message-only
 ```
 
 带报告文件:
 
 ```bash
-node "<插件目录>/mcp/src/tools/voc-issue-pool-run.js" --project "示例品牌A" --industry "家居定制" --report "outputs/douyin-trend-report.md" --assistant-message-only
+node "<插件目录>/mcp/src/tools/voc-issue-pool-run.js" --project "示例品牌A" --industry "<你的行业>" --report "outputs/douyin-trend-report.md" --assistant-message-only
 ```
 
 更新状态:
 
 ```bash
-node "<插件目录>/mcp/src/tools/voc-issue-pool-run.js" --project "示例品牌A" --industry "家居定制" --resolved-issues "选择门槛/决策" --assistant-message-only
+node "<插件目录>/mcp/src/tools/voc-issue-pool-run.js" --project "示例品牌A" --industry "<你的行业>" --resolved-issues "选择门槛/决策" --assistant-message-only
 ```
 
 ## 输出结构

+ 3 - 3
claude-code/claude-code-voc-intelligence/skills/voc-problem-deep-dive/SKILL.md

@@ -38,19 +38,19 @@ allowed-tools: Read Write Bash(node *)
 - If live collection returns `needs_token`, `needs_recharge`, or `needs_valid_token`, repeat the tool's user-facing `assistantMessage` and do not replace it with a generic strategy suggestion.
 
 ```bash
-node "<插件目录>/mcp/src/tools/voc-problem-deep-dive-run.js" --issue "怎么选" --industry "家居定制" --scenario "线上获客" --audience "意向用户" --assistant-message-only
+node "<插件目录>/mcp/src/tools/voc-problem-deep-dive-run.js" --issue "怎么选" --industry "<你的行业>" --scenario "线上获客" --audience "意向用户" --assistant-message-only
 ```
 
 带记忆的多轮迭代:
 
 ```bash
-node "<插件目录>/mcp/src/tools/voc-problem-deep-dive-run.js" --issue "怎么选" --industry "家居定制" --scenario "线上获客" --audience "意向用户" --memory "outputs/voc-problem-memory.json" --feedback "老板不想做试用体验,更想先改评论区回复和案例展示" --blocked-actions "试用体验" --preferred-actions "评论区回复,案例展示" --assistant-message-only
+node "<插件目录>/mcp/src/tools/voc-problem-deep-dive-run.js" --issue "怎么选" --industry "<你的行业>" --scenario "线上获客" --audience "意向用户" --memory "outputs/voc-problem-memory.json" --feedback "老板不想做试用体验,更想先改评论区回复和案例展示" --blocked-actions "试用体验" --preferred-actions "评论区回复,案例展示" --assistant-message-only
 ```
 
 自然语言反馈也可以直接传入 `feedback`,工具会尝试自动提取偏好和屏蔽动作:
 
 ```bash
-node "<插件目录>/mcp/src/tools/voc-problem-deep-dive-run.js" --issue "怎么选" --project "示例品牌A" --industry "家居定制" --scenario "线上获客" --audience "意向用户" --feedback "这个品牌不想做试用体验,更想先改评论区回复和案例展示" --assistant-message-only
+node "<插件目录>/mcp/src/tools/voc-problem-deep-dive-run.js" --issue "怎么选" --project "示例品牌A" --industry "<你的行业>" --scenario "线上获客" --audience "意向用户" --feedback "这个品牌不想做试用体验,更想先改评论区回复和案例展示" --assistant-message-only
 ```
 
 如果用户反馈“这个有效”“这个无效”“跑了 7 天有效果/没效果”,要把对应动作传入 `validatedActions` 或 `rejectedActions`,也可以直接放进 `feedback`。工具会沉淀动作验证次数,后续排序会自动提高有效动作、降低无效动作,并说明“为什么优先推荐这些动作”。

+ 1 - 1
claude-code/claude-code-voc-intelligence/skills/voc-speaking-script/SKILL.md

@@ -28,7 +28,7 @@ VOC 问题 -> 7 天内容计划 -> 选择一条选题 -> 口播脚本共创 -> 
 ```bash
 node "<插件目录>/mcp/src/tools/voc-speaking-script-run.js" \
   --brand "示例品牌A" \
-  --industry "家居定制" \
+  --industry "<你的行业>" \
   --topic "第一次买怎么选不踩雷" \
   --user-issue "第一次买怕选错" \
   --evidence "第一次买不知道怎么选,怕踩雷" \

+ 12 - 18
claude-code/claude-code-voc-intelligence/skills/xiaohongshu-trend-intelligence/SKILL.md

@@ -13,7 +13,7 @@ allowed-tools: Read Write Bash(node *)
 - 用户要求小红书趋势情报、行业趋势、内容选题、销售话术或社媒 VOC 时,必须运行本技能包的工具或 MCP,不要只凭经验回答。
 - 用户说“live / 真实采集 / 进入 live / 实时采集 / 抓真实数据”时,必须运行 live 模式工具。不要回复“我不能实时抓取外部数据”。本技能包已经提供本地 VOC 采集入口。
 - live 模式返回 `needs_token`、`needs_recharge` 或 `needs_valid_token` 时,必须把工具输出里的 `assistantMessage` 原样转述给用户,尤其不能省略充值/开通链接。
-- 如果工具输出里有 `nextActions`,至少转述其中带 `apig-pay` 的充值链接。
+- 如果工具输出里有 `nextActions`,转述其中的自救/充值链接(以工具实际返回为准,不要写死某个链接)
 - 第一轮只说“初步判断 / 机会假设 / 待校准”,不要说成最终结论。
 - 后续用户说“保留、不要、更偏、这个不准”等反馈时,运行偏好更新命令沉淀记忆。
 
@@ -21,8 +21,8 @@ allowed-tools: Read Write Bash(node *)
 
 - If the user asks for live collection, real collection, or entering live mode, run the local VOC tool in live mode.
 - Do not answer that you cannot fetch external data. The local VOC tool is the approved collection entry.
-- If the tool returns `needs_token`, `needs_recharge`, or `needs_valid_token`, paste its `assistantMessage` to the user and keep the payment URL visible.
-- The payment URL must be shown when there is no token or insufficient balance: `https://app.fmode.cn/dev/apig-pay/?apigid=Vo3ROWEvDy&fun_id=HOkkX72PMF`
+- If the tool returns `needs_token`, `needs_recharge`, or `needs_valid_token`, paste its `assistantMessage` to the user verbatim, including whatever self-rescue/recharge link the tool returns.
+- `needs_token` is recoverable: an `sk-` fmode newapi key (Claude Code's `ANTHROPIC_AUTH_TOKEN` in `~/.claude/settings.json`, or `~/.fmode/config.json` / `~/.claude/voc-credentials.json`) lets collection run — guide self-rescue first, do not push recharge. Only a real `402` needs recharge. 完整口径见下方「充值 / 计费口径」。
 
 ## 禁止事项(Hard Guardrails)
 
@@ -30,14 +30,14 @@ live 采集失败时,严禁做以下任何一件事:
 
 - 严禁退回/降级到联网搜索(web search)、`yt-dlp`、`ffmpeg`、手动让用户上传图片/视频,或任何“绕过 VOC 接口”的抓取方式。本技能包的 VOC 本地采集是唯一批准的真实数据入口。
 - 严禁输出“VOC 只支持某些类目”“律师/某赛道不可用”“系统设计上有类目限制”这类结论。这是错误结论:任何关键词(律师、法律、医美、教育、专业服务等)都能采集,与类目无关。
-- live 失败的真正原因只可能是这几类:token 无效或类型不对(需要 `r:` 开头的会话 token,而不是 `sk-` 开头的 AIGate API Key)、未开通或额度不足、上游接口抖动(5xx,需重试)。必须如实把工具返回的 `assistantMessage` 转述给用户,不要自行编造原因。
+- live 失败的真正原因只可能是这几类:缺 token 或 token 无效(**`sk-` 开头的 fmode newapi key 即可采集**——它就是 `~/.claude/settings.json` 的 `ANTHROPIC_AUTH_TOKEN`,也可来自 `~/.fmode/config.json` / `~/.claude/voc-credentials.json`;缺 token 先按提示自救读取,不要劝充值)、额度不足(真 402 才充值)、上游接口抖动(5xx,需重试)。必须如实把工具返回的 `assistantMessage` 转述给用户,不要自行编造原因。
 - 只有在工具明确返回 `needs_keyword_fix` 时才允许调整关键词;返回 `needs_valid_token` / `needs_token` / `needs_recharge` 时不要换关键词,要转述充值/开通链接。
 
 English (same rules):
 
 - On live failure, NEVER fall back to web search, `yt-dlp`, `ffmpeg`, or asking the user to upload media. The local VOC tool is the only approved real-data path.
 - NEVER conclude that VOC is limited to certain categories or that a vertical (e.g. lawyers) is unsupported. Any keyword works; this is never a category problem.
-- The only real causes are: invalid/wrong-type token (need an `r:` session token, not an `sk-` AIGate key), not activated / no balance, or upstream 5xx jitter (retry). Relay the tool's `assistantMessage` verbatim instead of inventing a reason.
+- The only real causes are: missing/invalid token (an `sk-` fmode newapi key — Claude Code's `ANTHROPIC_AUTH_TOKEN` — is valid for collection; self-rescue by reading it first, don't push recharge), insufficient balance (only a real 402 needs recharge), or upstream 5xx jitter (retry). Relay the tool's `assistantMessage` verbatim instead of inventing a reason.
 - Only adjust keywords when the tool returns `needs_keyword_fix`. For `needs_valid_token` / `needs_token` / `needs_recharge`, do not change keywords — surface the payment/activation link.
 
 ## sample 命令
@@ -54,24 +54,18 @@ node "<插件目录>/mcp/src/tools/xiaohongshu-trend-run.js" --collection-mode l
 
 运行后把命令输出正文直接发给用户。不要展示 JSON、summary、data、files 或调试日志。
 
-## 充值链接口径
+## 充值 / 计费口径(简版;完整对照见 voc-api-catalog 技能的「错误码速查」references/error-codes.md)
 
-没有 token 或余额不足时,用户必须看到:
-
-```text
-https://app.fmode.cn/dev/apig-pay/?apigid=Vo3ROWEvDy&fun_id=HOkkX72PMF
-```
-
-套餐入口可作为补充:
-
-```text
-https://app.fmode.cn/dev/apig-pay/#/workshop/99
-```
+- 缺 token(`needs_token`)= 可恢复、不是没钱:先自救读 `~/.claude/settings.json` 的 `sk-` fmode key(或 `~/.fmode/config.json` / `~/.claude/voc-credentials.json`),用 `FMODE_API_KEY=sk-…` 重试,不要劝充值。
+- 只有真 `402 余额不足` 才充值,入口 `https://app.fmode.cn/dev/studio/?balance=fmodeapi`(NewAPI/fmode-api 计费);`401`=token、`403`=权限,都不充值。`apig-pay/?apigid=Vo3ROWEvDy&fun_id=HOkkX72PMF` 仅限 `r:` 会话 token 余额补充。
+- 实际充值/自救链接以工具返回的 `assistantMessage` / `nextActions` 为准,不要写死。
 
 ## 推荐用户启动话术
 
+> 通用模板:把 `{你的行业/品类}` 替换成用户真实所在的行业或品类,不要内置任何特定行业。
+
 ```text
-帮我做一份家装全屋定制行业的小红书趋势情报。
+帮我做一份 {你的行业/品类} 的小红书趋势情报。
 先用演示样例跑通流程,不要真实采集。
 在聊天里给我第一轮样本观察和待确认问题。
 ```

+ 7 - 19
claude-code/claude-code-voc-intelligence/skills/xiaohongshu-trend-intelligence/references/live-mode.md

@@ -25,10 +25,10 @@ live 模式默认保持小规模:
 
 系统也会尝试从本机环境读取 token。
 
-如果没有 token,或者余额不足,不要直接把底层报错甩给用户,应该返回
+不要直接把底层报错甩给用户:
 
-- 充值链接
-- 下一步操作
+- 缺 token:先自救——读 `~/.claude/settings.json` 的 `sk-` fmode key(或 `~/.fmode/config.json` / `~/.claude/voc-credentials.json`)用 `FMODE_API_KEY=sk-…` 重试,不要直接给充值链接
+- 只有真正余额不足(`402`)才给充值链接 + 下一步操作。完整口径见下方「充值入口」与 voc-api-catalog 的「错误码速查」。
 
 不要把 `403`、授权失败文案、原始响应体直接暴露给用户。
 
@@ -41,23 +41,11 @@ live 模式默认保持小规模:
 
 保留 `xsec_token`,否则网页端可能打不开。
 
-## 充值入口
+## 充值入口(仅 402 余额不足时,简版)
 
-常见充值入口示例:
-
-```text
-https://app.fmode.cn/dev/apig-pay/#/workshop
-https://app.fmode.cn/dev/apig-pay/#/workshop/19-9
-https://app.fmode.cn/dev/apig-pay/#/workshop/99
-https://app.fmode.cn/dev/apig-pay/#/workshop/299
-https://app.fmode.cn/dev/apig-pay/#/workshop/699
-```
-
-如果只是 VOC 数据服务余额,也可以用:
-
-```text
-https://app.fmode.cn/dev/apig-pay/?apigid=Vo3ROWEvDy&fun_id=HOkkX72PMF
-```
+- `sk-` NewAPI/fmode-api 计费链(默认):`https://app.fmode.cn/dev/studio/?balance=fmodeapi`
+- `apig-pay/?apigid=Vo3ROWEvDy&fun_id=HOkkX72PMF` 仅限 `r:` 会话 token 余额补充。
+- 完整 401/402/403 对照与回退逻辑见 **voc-api-catalog 技能的「错误码速查」references/error-codes.md**(单一权威来源)。
 
 ## 结论
 

+ 5 - 5
claude-code/claude-code-voc-intelligence/skills/xiaohongshu-trend-intelligence/references/user-workflow.md

@@ -41,12 +41,12 @@
 
 ## 第三步:切 live
 
-如果用户要真实采集,先检查 token 和余额
+如果用户要真实采集,**直接跑 `live` 模式即可**——大多数装好 Claude Code(带 fmode `sk-` key)的机器已经具备采集所需 token,不必先做检测
 
-- 有 token 且可用,继续 live 采集
-- 没 token,返回充值链接
-- 余额不足,也返回充值链接
-- 不要把底层 403 直接丢给用户
+- 直接 live:能采到就继续
+- 只有 live 明确报「缺 token / 鉴权失败」时,才用 `voc_xiaohongshu_token_check` 诊断(它会识别 `settings.json` 的 `ANTHROPIC_AUTH_TOKEN`、`voc-credentials.json` 的 `fmodeApiKey`、`~/.fmode/config.json` 等所有来源)
+- 缺 token 多是**配置/读取**问题,不是余额不足:先按提示自救(读 SK、用 `FMODE_API_KEY` 重试),**确认确实是 402 余额不足时才返回充值链接**
+- 不要把底层 403 直接丢给用户,也不要一上来就把用户甩去充值
 
 ## 第四步:继续迭代
 

+ 6 - 6
dist/npm/claude-code-voc-npm-package-manifest.json

@@ -1,11 +1,11 @@
 {
   "name": "@vocmarket/voc-skill",
-  "version": "0.3.19",
-  "generatedAt": "2026-06-22T12:26:12.183Z",
-  "tarball": "dist/npm/vocmarket-voc-skill-0.3.19.tgz",
-  "tarballBytes": 167587,
-  "unpackedBytes": 624387,
-  "entryCount": 93,
+  "version": "0.3.26",
+  "generatedAt": "2026-06-27T04:20:38.110Z",
+  "tarball": "dist/npm/vocmarket-voc-skill-0.3.26.tgz",
+  "tarballBytes": 322257,
+  "unpackedBytes": 1887899,
+  "entryCount": 113,
   "installCommands": [
     "npm install -g @vocmarket/voc-skill",
     "claude-voc install",

+ 26 - 3
openclaw-skills/douyin/douyin-video-transcript/SKILL.md

@@ -1,12 +1,35 @@
 ---
 name: douyin-video-transcript
-description: 抖音视频逐字稿转写技能,输入抖音分享链接、真实媒体 URL、本地音视频文件或人工文案,解析/下载媒体并通过 provider 输出统一 transcript.json/txt。
-version: 0.2.2
+description: 抖音视频逐字稿转写技能,输入抖音分享链接、真实媒体 URL、本地音视频文件或人工文案,解析/下载媒体并通过 provider 输出统一 transcript.json/txt。需要语音转文字(ASR)时优先检测并使用独立技能 fmode-listen(Fmode 网关 ASR)。
+version: 0.2.3
 author: nkkj-BrainHack
 ---
 
 # 抖音视频逐字稿转写
 
+## ⭐ 语音转写优先用 fmode-listen 技能(必读,放在最前)
+
+当本技能需要做**语音/音频转文字(ASR)**这一步时,**优先使用独立技能 `fmode-listen`**,不要在本技能里新增 ASR provider。`fmode-listen` 走 Fmode 网关 `POST /api/listen/transcribe`:newapi 计费、按音频真实时长扣费,讯飞凭据只在服务端,客户端只需一把 fmode token(且 runner 会自动读取 `~/.claude/settings.json` 的 `sk-` token,不会再进旧付费弹窗死循环)。它是 `iflytek-gateway` 这条网关能力的正式独立技能版。
+
+**第 1 步:检测 fmode-listen 是否已安装**(以下任一目录存在即算已装):
+
+- 工作区级:`./.claude/skills/fmode-listen/`
+- 用户级:`~/.claude/skills/fmode-listen/`(Windows:`%USERPROFILE%\.claude\skills\fmode-listen\`)
+- 或用一条命令校验(缺文件会报 missing):`npx --yes fmode-listen@latest check`
+
+**第 2 步:未安装则先安装**:
+
+- 装到工作区:`npx --yes fmode-listen@latest workspace`
+- 装到用户级:`npx --yes fmode-listen@latest install`
+
+**第 3 步:调用 fmode-listen 转写**:
+
+```bash
+npx --yes fmode-listen@latest transcribe -- <音频或视频文件> --out result.json
+```
+
+> 兜底:本技能下方原有的 `iflytek-gateway`(apig) / `iflytek-ist` / `openai` 等 provider 原样保留,仅在不便使用 fmode-listen 时作为后备;fmode 网关 ASR 的正式路径是 fmode-listen 技能。
+
 ## 目标
 
 为口播爆款拆解和每日稿件日报提供逐字稿输入。P0 支持两条路径:
@@ -103,4 +126,4 @@ node "$env:USERPROFILE\.openclaw\tools\douyin-video-transcriber.js" --provider m
 
 ## 下游
 
-将 `transcript.json` 放入日报 runner 的 `--transcripts` 输入后,`douyin-speaking-daily-report` 会按 `awemeId` 匹配视频,并在证据链中标注“逐字稿:已提供(provider)”。
+将 `transcript.json` 放入日报 runner 的 `--transcripts` 输入后,`douyin-speaking-daily-report` 会按 `awemeId` 匹配视频,并在证据链中标注“逐字稿:已提供(provider)”。

Some files were not shown because too many files changed in this diff