aiconductor-cli 1.5.0 → 1.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +13 -10
- package/README.md +2 -0
- package/api_docs/xhs_user_info_v2.md +5 -1
- package/api_docs/xhs_user_notes_v3.md +2 -0
- package/package.json +1 -1
- package/src/api.js +17 -1
- package/src/api.test.js +34 -0
- package/.agents/plans/2026-10-28T11-20-16-943Z-plan.md +0 -161
package/AGENTS.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## 项目概述
|
|
4
4
|
|
|
5
|
-
`aiconductor-cli` 是 AIConductor 平台 API 的命令行封装:Node.js >= 18、CommonJS、唯一运行时依赖 `commander`,发布到 npm 供 agent 与终端用户直接调用。七组命令覆盖网页发布、豆包搜索、热点简报、抖音数据、小红书数据、公众号数据;`.
|
|
5
|
+
`aiconductor-cli` 是 AIConductor 平台 API 的命令行封装:Node.js >= 18、CommonJS、唯一运行时依赖 `commander`,发布到 npm 供 agent 与终端用户直接调用。七组命令覆盖网页发布、豆包搜索、热点简报、抖音数据、小红书数据、公众号数据;`.agents/skills/` 存放面向 agent 的工作流(pi 在项目受信任时会自动发现项目级 `.agents/skills/`),指导如何调用这些命令,其中对外发布的技能(`xhs-note-publish`、`douyin-script-extract`)还要满足 WorkBuddy 上架字段,见 `references/workbuddy技能规范.md`。`README.md` 是对外命令契约,本文档是开发与维护契约。
|
|
6
6
|
|
|
7
7
|
## 项目结构与模块组织
|
|
8
8
|
|
|
@@ -21,7 +21,7 @@ src/commands/
|
|
|
21
21
|
src/api.test.js 全部自动化测试(api 映射 + 纯格式化/聚合函数)
|
|
22
22
|
api_docs/<endpoint>.md 每个平台接口的请求/响应/计费契约(`aiconductor-platform` 对应文件的整文件副本)
|
|
23
23
|
references/ 平台侧规范(workbuddy技能规范.md),不参与 CLI 运行;已 gitignore + npmignore,只在本机
|
|
24
|
-
.
|
|
24
|
+
.agents/skills/<name>/ SKILL.md(路由与执行)+ references/(按条件加载)+ 可选 scripts/;仓库里唯一入库的 .agents 子目录
|
|
25
25
|
```
|
|
26
26
|
|
|
27
27
|
推导规则:命令组名与文件名**不一一对应**(`webpage` → `md_publish.js`,`search` → `web_search.js`),找实现先看 `bin/aiconductor-cli.js` 的注册处。命令文件只做四件事:解析选项、调用 `src/api.js`、格式化输出、`process.exit`;共享逻辑进 `src/lib/cli-utils.js`,HTTP 与鉴权细节不允许出现在命令文件里。
|
|
@@ -43,7 +43,7 @@ references/ 平台侧规范(workbuddy技能规范.md),不参
|
|
|
43
43
|
| 新增/修改接口契约 | platform 侧插件与 `api_docs`,再覆盖到 `aiconductor-cli/api_docs/` |
|
|
44
44
|
| CLI 接入 | `src/api.js`(端点常量 + `httpPost` + `stripBilling`)→ `src/commands/<组>.js` → `bin/aiconductor-cli.js` 注册 |
|
|
45
45
|
| 测试 | `src/api.test.js`,请求字段抄 `api_docs`,不抄实现 |
|
|
46
|
-
| 对外文档与技能 | `README.md`、`.
|
|
46
|
+
| 对外文档与技能 | `README.md`、`.agents/skills/*/SKILL.md` |
|
|
47
47
|
|
|
48
48
|
### 鉴权与计费的两侧分工
|
|
49
49
|
|
|
@@ -68,10 +68,10 @@ platform 侧还有、CLI 未接 10 个:`wx_rss_reader`、`flow_wx_history_arti
|
|
|
68
68
|
| 命令 | 用途 |
|
|
69
69
|
|---|---|
|
|
70
70
|
| `npm install` | 安装唯一依赖 `commander`(有 lock) |
|
|
71
|
-
| `npm test` | `node --test`,
|
|
71
|
+
| `npm test` | `node --test`,27 个用例,离线打桩,不需要 API Key |
|
|
72
72
|
| `node bin/aiconductor-cli.js --help` | 不安装也能本地运行,核对命令面 |
|
|
73
73
|
| `node bin/aiconductor-cli.js <组> <子命令> --help` | 核对某个命令的参数与默认值;CLI 契约以它为准 |
|
|
74
|
-
| `npm pack --dry-run` | 确认发布内容:含 `src/**`(含测试)、`api_docs/`、`AGENTS.md`,不含 `.
|
|
74
|
+
| `npm pack --dry-run` | 确认发布内容:含 `src/**`(含测试)、`api_docs/`、`AGENTS.md`,不含 `.agents/` 与 `references/`(平台侧规范只在本机,已从 `.npmignore`/`.gitignore` 排掉) |
|
|
75
75
|
|
|
76
76
|
无构建步骤、无 lint/formatter、无 CI。
|
|
77
77
|
|
|
@@ -83,7 +83,7 @@ platform 侧还有、CLI 未接 10 个:`wx_rss_reader`、`flow_wx_history_arti
|
|
|
83
83
|
2. 需要新端点时先读 `api_docs/<endpoint>.md`,在 `src/api.js` 加端点常量与函数,复用 `httpPost` + `stripBilling`。
|
|
84
84
|
3. 在 `bin/aiconductor-cli.js` 注册子命令与选项——这是**唯一注册点**。`-k, --api-key`、`-f, --format` 每个命令各自声明,没有全局注入;可重复选项用 `collect`。
|
|
85
85
|
4. 跑 `node bin/aiconductor-cli.js <组> <子命令> --help` 核对命令面,跑 `npm test`。
|
|
86
|
-
5. 同步受影响产物:`README.md`(synopsis、选项表、示例)、对应的 `.
|
|
86
|
+
5. 同步受影响产物:`README.md`(synopsis、选项表、示例)、对应的 `.agents/skills/*/SKILL.md`(命令、选项、`data.data.*` 路径)、`src/api.test.js`(改了请求映射或格式化时)。
|
|
87
87
|
|
|
88
88
|
### 新增平台接口
|
|
89
89
|
|
|
@@ -94,11 +94,13 @@ platform 侧还有、CLI 未接 10 个:`wx_rss_reader`、`flow_wx_history_arti
|
|
|
94
94
|
|
|
95
95
|
### 维护 skill
|
|
96
96
|
|
|
97
|
-
-
|
|
97
|
+
- 技能放 `.agents/skills/<name>/`(2026-11-04 从 `.codex/skills/` 迁来,内容逐字未变,`git mv` 效果):pi 从 cwd 向上到仓库根发现项目级 `.agents/skills/`(`dist/core/package-manager.js` 的 `collectAncestorAgentsSkillDirs`),`.codex/skills/` 从来不是 pi 的发现路径。代价:项目里有 `.agents/skills/` 会触发**项目信任门禁**(`hasTrustRequiringProjectResources` 返回 true),未信任时这 11 个技能不加载。**这是故意的**(2026-11-04):本仓技能是**上架产物**(WorkBuddy / 技能仓库的发布件),不是本机开发时要用的上下文,所以 `~/.pi/agent/trust.json` 已给 `D:/Development/aiconductor-cli` 显式写 `false`——pi 不弹信任提示、技能不进上下文;需要某条技能内容时直接 `read .agents/skills/<name>/SKILL.md`,**不要为了加载它去信任项目**。
|
|
98
|
+
- `.gitignore` 用 `.agents/*` + `!.agents/skills/` 只放行技能,`.agents/ledger.md`、`.agents/plans/` 属本机脚手架不入库——**别把 `.agents/` 整目录 ignore**,那会让技能从版本控制里消失(`git status` 表现为 `.codex/` 全删、新目录全是 `??`)。
|
|
99
|
+
- 目录名、frontmatter `name`、实际调用的命令必须一致;`description` 写能力 + 用户原话触发 + 与相邻 skill 的边界(简报→content-briefing,单点搜索→doubao-search,网页→webpage-publish,抖音数据→douyin-toolbox,抖音文案→douyin-script-extract,抖音选题→douyin-topic-radar,抖音评论→douyin-comment-insight,抖音账号→douyin-account-analyze,小红书→xhs-note-publish,公众号发文列表→wx-account-articles,单篇公众号数据→wx-article-data)。
|
|
98
100
|
- `SKILL.md` 只放路由、决策、命令行、响应路径、安全规则;长选项表、安装与密钥恢复放 `references/`,并写明何时读。
|
|
99
101
|
- 默认 JSON 输出,文档写稳定的 `data.data.*` 路径(`outputResult` 会额外包一层 `{success, data}`)。
|
|
100
102
|
- 用户请求执行即等同授权:不要每次预检安装或密钥;安装说明只在需要时读一次,修复后重试原命令一次。
|
|
101
|
-
- 安装说明被复制成
|
|
103
|
+
- 安装说明被复制成 11 份 `references/aiconductor-skills-setup.md`(技能是独立安装单元,无法跨目录引用);改它必须同步 11 份。改完跑 `md5sum .agents/skills/*/references/aiconductor-skills-setup.md | awk '{print $1}' | sort -u | wc -l`,结果必须是 **1**。
|
|
102
104
|
|
|
103
105
|
### 上架到 WorkBuddy
|
|
104
106
|
|
|
@@ -122,6 +124,7 @@ platform 侧还有、CLI 未接 10 个:`wx_rss_reader`、`flow_wx_history_arti
|
|
|
122
124
|
- **小红书发布是两段式**:本地文件或 Base64 先经 `r2Upload` 换成临时公开 URL(`valid_days` 仅 1 或 7,默认 7;图片单张 ≤ 32MB,本地视频 ≤ 100MB),再调用计费接口生成 H5 页与二维码。Base64 参数支持 `@文件路径`。
|
|
123
125
|
- **热点简报是部分成功语义**:热榜与小红书热榜并行请求,任一成功即返回 `success:true`,失败写入 `data.failed_sources` / `data.failed_services`;仅两个服务都失败才退出 1。不要简化成"全有或全无"。
|
|
124
126
|
- **`wx` 组线上真实字段**(2026-11-04 实测调用):`wx_article_data` 返回 `read` / `zan` / `looking`(在看)/ `share_num` / `collect_num` / `comment_count`;`wx_history_articles` 用 `--name` 定位时业务层只有 `mp_nickname` 与 `mp_ghid`——**`api_docs` 写的 `mp_wxid` / `head_img` 实际不返回**;文章项字段与文档一致(`post_time_str` / `read` / `zan` / `original` / `url` / `digest`)。改 formatter 按实测字段,不要按文档新增字段。
|
|
127
|
+
- **`wx_history_articles` 的上游失败藏在 `data.code`**:平台侧仍回 `success:true`,只有 `data.code` 非 0 才是失败(实测 `107` = 名称/链接对不上,`20001` = 平台侧上游故障),`src/api.js` 的 `throwOnWxHistoryFailure` 把它转成 `api_error`(退出码 1)。别用「数组为空」推断「这个号没发文」。
|
|
125
128
|
- **抖音字段单位不统一**:`video-search` 的 `video.duration` 是**毫秒**,`user-videos` 的 `duration` 是 `"MM:SS"` 字符串——同名不同单位,跨端点复用代码必翻车。
|
|
126
129
|
- **抖音时间戳是北京时间编码**:`create_time` 按 UTC 渲染出来就是北京时间,**不要再 +8 小时**(2026-10-28 实测 `video-search`/`video-comments`/`user-videos` 三处:+8 会让半小时前发的视频落到 7 小时后)。`user-videos` 另带 `create_time_formatted`,同口径。
|
|
127
130
|
- **密钥解析**:`-k` > `AICONDUCTOR_API_KEY` > **当前工作目录**的 `.env`(不向上查找);缺失时 `resolveKeyOrExit` 打印错误并退出 1。
|
|
@@ -147,7 +150,7 @@ platform 侧还有、CLI 未接 10 个:`wx_rss_reader`、`flow_wx_history_arti
|
|
|
147
150
|
|
|
148
151
|
## 最短验证闭环
|
|
149
152
|
|
|
150
|
-
`npm test`(
|
|
153
|
+
`npm test`(27 个用例,离线打桩,不需要 API Key)。改动涉及 `bin/`、`README.md`、skill 文字或新增命令时,再补一条人工核对:`node bin/aiconductor-cli.js <组> <子命令> --help`——`bin/` 的接线没有自动化测试覆盖。
|
|
151
154
|
|
|
152
155
|
## 任务执行与报告约定
|
|
153
156
|
|
|
@@ -172,7 +175,7 @@ platform 侧还有、CLI 未接 10 个:`wx_rss_reader`、`flow_wx_history_arti
|
|
|
172
175
|
|
|
173
176
|
- 格式 `<tag>: <描述>`,tag 取自既有历史:`feat:`、`fix:`、`refactor:`、`docs:`、`skills:`、`search:`、`content:`、`release:`;agent 提交在前面加 `[Agent]`(如 `[Agent] release(cli): 1.4.0 —— ...`),描述可用中文。
|
|
174
177
|
- 发版提交只改 `package.json` + `package-lock.json` 的版本号;发版前先跑 `npm test`。
|
|
175
|
-
- 新增或修改 skill 必须随 `.
|
|
178
|
+
- 新增或修改 skill 必须随 `.agents/skills/**` 一起进 Git(`.npmignore` 已排除 `.agents/`,所以技能在仓库里版本化、不进 npm 包)。
|
|
176
179
|
- 历史只有单作者、无 PR 记录,可直接在 `master` 提交;若走 PR,描述写清命令面/API 影响与验证命令,保持 diff 聚焦。
|
|
177
180
|
|
|
178
181
|
## 安全与配置
|
package/README.md
CHANGED
|
@@ -374,6 +374,8 @@ aiconductor-cli wx history "https://mp.weixin.qq.com/s?__biz=xxxx" -f text
|
|
|
374
374
|
|
|
375
375
|
返回路径:`article-data` 的互动数据在 `data.data`(`read` / `zan` / `looking` / `share_num` / `collect_num` / `comment_count`,text 模式渲染成阅读/点赞/在看/分享/收藏/评论,未知字段原样输出);`history` 的文章在 `data.data.data[]`(标题 `title`、时间 `post_time_str`、阅读 `read`、点赞 `zan`、链接 `url`)。
|
|
376
376
|
|
|
377
|
+
`history` 另带 `data.data.code`(上游返回码):`0` 才表示成功;非 0(如 `107` 名称/链接对不上、`20001` 平台侧上游故障)时 CLI 以退出码 1 报 `api_error`,不会用空列表冒充成功。
|
|
378
|
+
|
|
377
379
|
### 通用选项
|
|
378
380
|
|
|
379
381
|
所有命令支持:
|
|
@@ -5,7 +5,11 @@
|
|
|
5
5
|
- **鉴权**: 请求头 `Authorization: Bearer <api_key>`(兼容 body/query 中 `api_key` 参数)
|
|
6
6
|
|
|
7
7
|
## 功能说明
|
|
8
|
-
根据用户ID
|
|
8
|
+
根据用户ID获取小红书用户详情,包括基本信息、互动数据(关注/粉丝/获赞与收藏/获赞/收藏)、标签等。按次计费。
|
|
9
|
+
|
|
10
|
+
> **数据源变更(2026-11-05)**:上游由 YDDM `/xhs/user_detail`(实测 8.2s)切换为 TikHub `GET /api/v1/xiaohongshu/app_v2/get_user_info`(实测 2.3s),**入参与出参形状完全不变**:
|
|
11
|
+
> `user_info.basic_info{nickname, avatar, red_id, gender, ip_location, desc}` + `user_info.interactions[5]{type, name, count}`(关注/粉丝/获赞与收藏/获赞/收藏)+ `user_info.tags[string]`。
|
|
12
|
+
> 两个口径差异需知悉:① `ip_location` 统一给**中文省份**(优先取资料地区省份,回落英文 IP 归属地,如 `福建`);② `获赞与收藏` 取上游自带的合计值,缺失时用 `获赞 + 收藏` 兜底。
|
|
9
13
|
|
|
10
14
|
## 请求参数
|
|
11
15
|
|
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
## 功能说明
|
|
8
8
|
根据用户 ID 获取小红书用户笔记列表,支持自动翻页(cursor 机制),兼容图文与视频笔记,按页计费。费用以 api_services 表配置为准(service_code: `xhs_user_notes_v2`)。
|
|
9
9
|
|
|
10
|
+
> **数据源变更(2026-11-05)**:上游由 YDDM `/xhs/user_post2`(持续返回 `code 5003 网络连接失败`,接口表现为 `success:true` + 空 `notes`)切换为 TikHub `GET /api/v1/xiaohongshu/app_v2/get_user_posted_notes`(实测 20 条/页、1.9s)。**入参与出参形状完全不变**,与 `xhs_user_notes_v2` 同一上游、同一输出结构(差别只在 `desc` 等字段的原始内容)。
|
|
11
|
+
|
|
10
12
|
## 请求参数
|
|
11
13
|
|
|
12
14
|
| 参数名 | 类型 | 必填 | 默认值 | 说明 |
|
package/package.json
CHANGED
package/src/api.js
CHANGED
|
@@ -176,6 +176,22 @@ function throwOnBusinessFailure(resp) {
|
|
|
176
176
|
return resp;
|
|
177
177
|
}
|
|
178
178
|
|
|
179
|
+
/**
|
|
180
|
+
* wx_history_articles 把上游失败塞在 HTTP 200 + success:true 的 data.code 里
|
|
181
|
+
* (api_docs:data.code 为 0 才算成功,平台侧并不改写成 success:false)。
|
|
182
|
+
* 不认这个码,就会把「上游挂了」当成「这个号没有文章」。
|
|
183
|
+
* @param {object} resp
|
|
184
|
+
* @returns {object}
|
|
185
|
+
*/
|
|
186
|
+
function throwOnWxHistoryFailure(resp) {
|
|
187
|
+
const inner = resp && resp.data;
|
|
188
|
+
if (inner && typeof inner.code === "number" && inner.code !== 0) {
|
|
189
|
+
const detail = resp.message || inner.msg || "上游返回失败";
|
|
190
|
+
throw Object.assign(new Error(`${detail}(上游错误码 ${inner.code})`), { type: "api_error" });
|
|
191
|
+
}
|
|
192
|
+
return resp;
|
|
193
|
+
}
|
|
194
|
+
|
|
179
195
|
function contentTypeForFilename(filename) {
|
|
180
196
|
const types = {
|
|
181
197
|
".avif": "image/avif",
|
|
@@ -638,7 +654,7 @@ async function wxHistoryArticles(apiKey, params = {}) {
|
|
|
638
654
|
const resp = await httpPost(API_HOST, WX_HISTORY_ARTICLES_PATH, body, {
|
|
639
655
|
Authorization: `Bearer ${apiKey}`,
|
|
640
656
|
});
|
|
641
|
-
return throwOnBusinessFailure(stripBilling(resp));
|
|
657
|
+
return throwOnWxHistoryFailure(throwOnBusinessFailure(stripBilling(resp)));
|
|
642
658
|
}
|
|
643
659
|
|
|
644
660
|
/**
|
package/src/api.test.js
CHANGED
|
@@ -433,6 +433,40 @@ test("wx endpoints turn HTTP 200 business failures into api_error", async () =>
|
|
|
433
433
|
);
|
|
434
434
|
});
|
|
435
435
|
|
|
436
|
+
test("wx history treats an upstream code inside a successful response as a failure", async () => {
|
|
437
|
+
// 2026-11-05 线上实测:平台仍回 success:true,把上游失败塞进 data.code(api_docs:code 0 为成功),
|
|
438
|
+
// 文章数组为空。若照 success 判断,会把「上游挂了」报成「这个号最近没发文」。
|
|
439
|
+
const upstreamFailure = {
|
|
440
|
+
success: true,
|
|
441
|
+
message: "未能获取到任何数据。请检查参数或账户余额。",
|
|
442
|
+
billing: { pages_billed: 0, transaction_ids: [] },
|
|
443
|
+
data: { code: 20001, msg: "error", data: [], now_page: 0, now_page_articles_num: 0 },
|
|
444
|
+
};
|
|
445
|
+
|
|
446
|
+
await assert.rejects(
|
|
447
|
+
() => captureRequest(() => wxHistoryArticles("test-key", { name: "人民日报" }), upstreamFailure),
|
|
448
|
+
(err) =>
|
|
449
|
+
err.type === "api_error" &&
|
|
450
|
+
err.message.includes("未能获取到任何数据") &&
|
|
451
|
+
err.message.includes("20001")
|
|
452
|
+
);
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
test("wx history still resolves an empty page when the upstream code is 0", async () => {
|
|
456
|
+
const emptyButOk = {
|
|
457
|
+
success: true,
|
|
458
|
+
message: "微信公众号历史文章获取完成。成功获取 1 页数据,共 0 篇文章。",
|
|
459
|
+
data: { code: 0, msg: "success", data: [], now_page: 1 },
|
|
460
|
+
};
|
|
461
|
+
|
|
462
|
+
const request = await captureRequest(
|
|
463
|
+
() => wxHistoryArticles("test-key", { name: "不存在的号" }),
|
|
464
|
+
emptyButOk
|
|
465
|
+
);
|
|
466
|
+
assert.deepEqual(request.result.data.data, []);
|
|
467
|
+
assert.equal(request.result.success, true);
|
|
468
|
+
});
|
|
469
|
+
|
|
436
470
|
test("wx history formatter lists documented article fields", () => {
|
|
437
471
|
const text = formatHistoryText({
|
|
438
472
|
data: {
|
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
# 抖音三技能上架计划
|
|
2
|
-
|
|
3
|
-
目标:在 `douyin-script-extract` 之外再补 3 个可独立上架的流量入口,每个都能用一句话说清"用户为什么装它",且交付物比裸命令多出加工价值。
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 一、稳定层(承诺,入库)
|
|
8
|
-
|
|
9
|
-
### 1. 共同骨架(三个技能一致,不逐条重复)
|
|
10
|
-
|
|
11
|
-
| 项 | 约定 |
|
|
12
|
-
|---|---|
|
|
13
|
-
| 目录 | `.codex/skills/<name>/`,同时镜像到 `~/.agents/skills/<name>/`,两处正文逐字一致 |
|
|
14
|
-
| frontmatter | 8 项必填 + `author: "AI指挥家"` + `examples_zh/en` 各 3 条(用能跑通的真链接) |
|
|
15
|
-
| 正文开头 | `## 概述`,口吻"默认已装好 CLI 与 API Key",故障才读 `references/aiconductor-skills-setup.md` |
|
|
16
|
-
| 验真 | 外层 `success`/退出码不可信,一律落 `data.data.success`;失败给 `message` |
|
|
17
|
-
| 不写价格 | 单价、扣费、"免费"不进 SKILL.md;余额不足这类故障信息可以写 |
|
|
18
|
-
| 交付纪律 | 数字必须有出处(哪条数据算出来的),结论必须挂原话或原作品,不编造 |
|
|
19
|
-
| 时区 | `create_time` 是 Unix 时间戳,统一显式转北京时间再展示,禁止把 UTC 当本地 |
|
|
20
|
-
| 字段降级 | 上游透传字段可能缺(TikHub 侧变动),缺字段时降级展示,不报错也不猜 |
|
|
21
|
-
|
|
22
|
-
### 2. 三个技能的规格
|
|
23
|
-
|
|
24
|
-
#### A. `douyin-topic-radar` — 抖音爆款选题
|
|
25
|
-
|
|
26
|
-
- **用户话术**:最近什么在爆 / 这个赛道谁做起来了 / 找几个对标 / 我该拍什么
|
|
27
|
-
- **命令**:`aiconductor-cli douyin video-search <keyword>`
|
|
28
|
-
- **预设分档**(技能的核心价值,用户不需要知道参数存在)
|
|
29
|
-
|
|
30
|
-
| 档位 | 参数 | 用途 |
|
|
31
|
-
|---|---|---|
|
|
32
|
-
| 近一周最热 | `--sort-type 1 --publish-time 7 --max-pages 1` | 默认档,看当下 |
|
|
33
|
-
| 半年爆款池 | `--sort-type 1 --publish-time 180 --max-pages 2` | 找可复刻的长期爆款 |
|
|
34
|
-
| 最新动向 | `--sort-type 2 --publish-time 1 --max-pages 1` | 追热点 |
|
|
35
|
-
| 长视频对标 | `--sort-type 1 --filter-duration 5-10000` | 口播/知识类 |
|
|
36
|
-
|
|
37
|
-
- **多关键词**:用户给一个赛道词时,自动扩 3–4 个同义词(AI编程 / AI写代码 / 程序员用AI),串行跑,按 `aweme_id` 合并去重
|
|
38
|
-
- **交付契约**
|
|
39
|
-
1. Top N 表:点赞 / 评论 / 时长 / 发布时间(北京时间)/ 作者 / 标题
|
|
40
|
-
2. 共性:时长区间、发布时间段、标题钩子类型、内容形式(口播/实拍/图文)
|
|
41
|
-
3. 选题建议 3–5 条,每条挂"哪几条爆款支撑"
|
|
42
|
-
4. 数据口径一句:点赞是抓取时点快照,非实时
|
|
43
|
-
- **过滤**:时长 < 10 秒(切片/图文)、重复搬运(同 desc)、点赞低于本批中位数
|
|
44
|
-
- **边界**:不下载视频、不分析评论、不提取文案
|
|
45
|
-
- **已知坑**
|
|
46
|
-
- `max_seconds` 上限 **50 秒**,翻页会被截断且 `success` 仍为 `true`、`has_more=1` → 必须提示"未取全"
|
|
47
|
-
- 搜索是关键词匹配不是赛道,关键词太泛会灌进无关内容,需要 `--filter-duration` 收窄
|
|
48
|
-
|
|
49
|
-
#### B. `douyin-comment-insight` — 抖音评论洞察
|
|
50
|
-
|
|
51
|
-
- **用户话术**:评论区在吵什么 / 用户对 XX 的真实反馈 / 这条视频为什么被骂
|
|
52
|
-
- **命令**:`aiconductor-cli douyin video-comments <video_url> --max-count 50`
|
|
53
|
-
- **交付契约**
|
|
54
|
-
1. 热评 Top 10:原话引用 + 点赞数(按 `digg_count` 降序,不按接口顺序)
|
|
55
|
-
2. 争议点:正反两派各自的原话,各 1–2 条
|
|
56
|
-
3. 用户诉求/高频提问:问得最多的问题
|
|
57
|
-
4. 情绪倾向:只给"按原话看,X 多于 Y",**不给编造的百分比**
|
|
58
|
-
5. 一句话结论
|
|
59
|
-
- **过滤**:广告引流(私信/加V/主页)、纯表情、互喷、完全重复
|
|
60
|
-
- **纪律**:结论必须挂原话;必须说明"样本是前 50 条,不代表全量民意"
|
|
61
|
-
- **边界**:不抓二级评论(只用 `reply_comment_total` 给数量)、不爬作者主页
|
|
62
|
-
- **已知坑**:`is_folded` 折叠评论、无评论/评论关闭、视频已删
|
|
63
|
-
|
|
64
|
-
#### C. `douyin-account-audit` — 抖音账号拆解
|
|
65
|
-
|
|
66
|
-
- **用户话术**:扒一下这个号 / 他为什么火 / 找几个这个领域的号
|
|
67
|
-
- **命令链**:`user-detail` → `user-videos` →(可选)对 Top3 调 `video-info`
|
|
68
|
-
- **找号模式**:用户只给赛道词时,先 `user-search <关键词> --fans-range … --user-type …`,再按简介/作品二次筛
|
|
69
|
-
- **交付契约**
|
|
70
|
-
1. 账号画像:昵称 / 粉丝 / 获赞 / 作品数 / 认证 / 简介 / IP 属地
|
|
71
|
-
2. 更新频率:由 `create_time` 算近 N 条的周更条数
|
|
72
|
-
3. 内容结构:按主题分组,各组点赞中位数与爆款数
|
|
73
|
-
4. 爆款率:点赞 ≥ 该号中位数 × 3 的作品占比
|
|
74
|
-
5. 可复制点 3 条,每条挂具体作品
|
|
75
|
-
6. 口径一句:只分析了最近 N 条,不是全量
|
|
76
|
-
- **脚本**:`scripts/profile.mjs`(纯统计,无网络)
|
|
77
|
-
- 输入:`user-videos` 的原始 JSON;输出:结构化摘要(时间跨度、周更频率、中位数、爆款清单)
|
|
78
|
-
- 理由:爆款率/频率这类口径每次手写必漂,固化成脚本才可复现
|
|
79
|
-
- 三个技能里**只有它带脚本**;另外两个的排序过滤是单行逻辑,先不写,等 eval 发现重复劳动再抽
|
|
80
|
-
- **已知坑**
|
|
81
|
-
- `user-videos` 默认 1 页 / 50 秒;**`max_seconds` 上限 180**(已与服务方确认,`api_docs/douyin_user_videos.md` 同步为 180)。大号要取全就得显式调到 180,但仍必须在交付物里说明「只看了最近 N 条」
|
|
82
|
-
- 大号一页约 20–30 条,必须一开始就说清"只看最近 N 条"
|
|
83
|
-
- 私密/隐藏作品拿不到,粉丝数增长历史拿不到(只有当前值)
|
|
84
|
-
|
|
85
|
-
### 3. 验收标准(每个技能都要过)
|
|
86
|
-
|
|
87
|
-
- [ ] `node bin/aiconductor-cli.js douyin <cmd> --help` 与技能里写的参数逐项一致
|
|
88
|
-
- [ ] frontmatter 8 项齐全,`name == 目录名`,`references/` 路径可达
|
|
89
|
-
- [ ] 真实调用至少 1 次:字段路径对得上、时间戳是北京时间、交付物符合契约
|
|
90
|
-
- [ ] 失败分支实测 1 次(错链接/无评论/空结果),能识别且话术对
|
|
91
|
-
- [ ] 全文零价格词(`元/计费/扣费/付费/免费/按次`)
|
|
92
|
-
- [ ] 两个副本正文逐字一致;提交到项目仓库与技能库
|
|
93
|
-
- [ ] **目录本身可直接上架 WorkBuddy**:根目录 `SKILL.md`、`references/` 随目录一起走、不依赖目录外任何文件
|
|
94
|
-
- [ ] 交付时附一份可复制的上架清单(见第四节)
|
|
95
|
-
|
|
96
|
-
---
|
|
97
|
-
|
|
98
|
-
## 二、可变层(脚手架,随实现修订)
|
|
99
|
-
|
|
100
|
-
### 实施顺序与粒度
|
|
101
|
-
|
|
102
|
-
| 步 | 动作 | 产出 |
|
|
103
|
-
|---|---|---|
|
|
104
|
-
| 1 | `douyin-topic-radar` 起草 + 真实跑 1 个关键词 | SKILL.md + references |
|
|
105
|
-
| 2 | 按交付契约手工核一遍(Top N 表、共性、建议是否挂得住) | 修订记录 |
|
|
106
|
-
| 3 | `douyin-comment-insight` 起草 + 真实跑 1 条视频 | SKILL.md + references |
|
|
107
|
-
| 4 | `douyin-account-audit` 起草 + `scripts/profile.mjs` + 真实跑 1 个号 | SKILL.md + references + scripts |
|
|
108
|
-
| 5 | 三技能交叉检查:命名/描述不互抢、边界互不重叠 | 一次 diff |
|
|
109
|
-
| 6 | 提交(每个技能一个 commit) | 两个仓库 |
|
|
110
|
-
|
|
111
|
-
### 真实调用成本与授权
|
|
112
|
-
|
|
113
|
-
三个技能各需 1–2 次真实调用,合计约 1 元级。执行前单独确认(项目规矩:带 Key 的计费调用先问)。
|
|
114
|
-
|
|
115
|
-
### 风险
|
|
116
|
-
|
|
117
|
-
1. **同名技能互抢**:三个 description 必须写清边界(选题=找什么拍 / 评论=看反馈 / 拆号=看一个账号),否则平台内部排序自己打自己
|
|
118
|
-
2. **setup 副本增至 9 份**:改一次密钥说明要改 9 处。可选先做一件事——加一条比对命令(`md5sum` 全部副本),漂移立刻可见;不新增脚本
|
|
119
|
-
3. **字段漂移**:`video_search` 是 TikHub 透传,字段名可能变;技能里写成"缺字段降级",不硬依赖
|
|
120
|
-
4. **样本偏差**:搜索只返回前 N 页、评论只前 50 条、账号只最近 N 条;三个技能都必须把这句话写在交付物里,不能默认用户知道
|
|
121
|
-
|
|
122
|
-
---
|
|
123
|
-
|
|
124
|
-
## 四、WorkBuddy 交付格式(最终产物)
|
|
125
|
-
|
|
126
|
-
每个技能交出去的东西必须能直接上传,不靠二次解释:
|
|
127
|
-
|
|
128
|
-
```text
|
|
129
|
-
<skill-name>/
|
|
130
|
-
├── SKILL.md # 8 项必填 frontmatter + 概述 + 执行/失败/限制
|
|
131
|
-
└── references/
|
|
132
|
-
└── aiconductor-skills-setup.md # 安装与密钥兜底,随目录走
|
|
133
|
-
(douyin-account-audit 额外带 scripts/profile.mjs)
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
硬性要求:
|
|
137
|
-
|
|
138
|
-
- 目录名 == `name`;根下必须有 `SKILL.md`
|
|
139
|
-
- 引用的文件全在目录内,用 Markdown 链接 `[references/x.md](references/x.md)`
|
|
140
|
-
- 不依赖仓库内的其他路径(技能是独立安装单元)
|
|
141
|
-
- 不写价格(单价/扣费/"免费");余额不足这类故障提示可以写
|
|
142
|
-
- 中文名、英文名、中英简介、中英案例各就各位(详情页直接读这些字段)
|
|
143
|
-
|
|
144
|
-
交付时额外给一份**上架清单**(可整段复制进 WorkBuddy 后台表单):
|
|
145
|
-
|
|
146
|
-
| 项 | 内容 |
|
|
147
|
-
|---|---|
|
|
148
|
-
| 技能标识 / 目录 | `<name>` |
|
|
149
|
-
| 中文名 / 英文名 | `display_name` / `display_name_en` |
|
|
150
|
-
| 中文简介 / 英文简介 | `description_zh` / `description_en` |
|
|
151
|
-
| 使用案例 ×3(中/英) | `examples_zh` / `examples_en`,用能真跑通的链接 |
|
|
152
|
-
| 作者 | AI指挥家 |
|
|
153
|
-
| 版本 | 1.0.0 |
|
|
154
|
-
|
|
155
|
-
---
|
|
156
|
-
|
|
157
|
-
## 五、未决问题(开工前请确认)
|
|
158
|
-
|
|
159
|
-
1. 命名是否接受:`douyin-topic-radar`(抖音爆款选题)、`douyin-comment-insight`(抖音评论洞察)、`douyin-account-audit`(抖音账号拆解)
|
|
160
|
-
2. 达人筛选并入账号拆解的"找号模式",不单独上架——是否同意
|
|
161
|
-
3. 是否先做第 1 个跑通再继续,还是三个一起起草完再统一直真实测
|