@yizhuan-cli/cli 0.1.16 → 0.1.17-beta.0

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/README.md CHANGED
@@ -36,6 +36,8 @@ yizhuan config path
36
36
  yizhuan config show
37
37
  yizhuan execute --ability membership
38
38
  yizhuan execute --ability works --query "百家号昨天新增了哪些作品"
39
+ yizhuan execute --ability works --params '{"mode":"comments","platform":"douyin","workId":"123456","count":20}'
40
+ yizhuan execute --ability works --params '{"mode":"comments","platform":"douyin","title":"作品标题","count":20}'
39
41
  yizhuan execute --ability hot_topics --platform douyin
40
42
  yizhuan execute --ability hot_topics --params '{"platform":"douyin"}'
41
43
  yizhuan execute --ability accounts --params '{"mode":"public_search","platform":"toutiao","keyword":"张三"}'
@@ -72,6 +74,9 @@ yizhuan execute --ability hot_topics --params "{\"platform\":\"douyin\"}"
72
74
  ## 支持的典型能力
73
75
 
74
76
  - 作品查询:`yizhuan execute --ability works --query "AI 相关的热门作品有哪些"`
77
+ - 作品评论:`yizhuan execute --ability works --params '{"mode":"comments","platform":"douyin","workId":"123456","count":20}'`
78
+ - 按标题查询评论:`yizhuan execute --ability works --params '{"mode":"comments","platform":"douyin","title":"作品标题"}'`;标题必须唯一匹配,多个候选时 CLI 会要求补充条件。
79
+ - 微信公众号/视频号评论:`yizhuan execute --ability works --params '{"mode":"comments","platform":"weixin","workId":"https://mp.weixin.qq.com/s/文章链接","count":20}'`;这两个平台的 `workId` 使用作品链接。
75
80
  - 作者查询:`yizhuan execute --ability accounts --query "查询张三这个作者"`
76
81
  - 作者指标筛选:`yizhuan execute --ability author_query --params '{"platform_id":2,"min_follower":500000,"min_total_likes":100000}'`
77
82
  - 作者全网搜索:`yizhuan execute --ability accounts --params '{"mode":"public_search","platform":"toutiao","keyword":"张三"}'`
@@ -82,6 +87,8 @@ yizhuan execute --ability hot_topics --params "{\"platform\":\"douyin\"}"
82
87
  - 竞品动态筛选:`yizhuan execute --ability radar --params '{"mode":"timeline","timeRange":"7d","platform":"baijiahao","keyword":"AI"}'`
83
88
  - 取消关注雷达作者:先查询关注列表拿到 `articleId`,再执行 `yizhuan execute --ability radar --params '{"mode":"unfollow","articleId":"205169870"}'`
84
89
  - 会员查询:`yizhuan execute --ability membership --query "我的会员什么时候到期"`
90
+ - 内容提取:`yizhuan execute --ability content_extract --url "https://example.com/article"`
91
+ - 易撰作品内容提取:`yizhuan execute --ability content_extract --params '{"contentId":12345}'`
85
92
 
86
93
  如果你是通过 Codex、Cursor、Claude Code 这类 Agent 使用 CLI,也可以直接用自然语言提问,例如:
87
94
 
@@ -90,3 +97,5 @@ yizhuan execute --ability hot_topics --params "{\"platform\":\"douyin\"}"
90
97
  - `查询 AI 相关的热门文章`
91
98
  - `取消关注陈某某先生`
92
99
  - `我的会员什么时候到期`
100
+
101
+ 纯创作请求(例如“写一篇中秋文章”)由当前 Agent 完成,不调用 `content_extract`;CLI 只提供真实内容素材,不负责生成、改写或发布。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yizhuan-cli/cli",
3
- "version": "0.1.16",
3
+ "version": "0.1.17-beta.0",
4
4
  "description": "易撰命令行工具,用于通过 API Key 查询易撰真实数据。",
5
5
  "private": false,
6
6
  "type": "module",
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: yizhuan-cli
3
3
  description: |
4
- 安装、配置并使用易撰 CLI(yizhuan 命令)查询真实数据的全量 Skill,处理作品、作者、全网搜索、热点、竞品动态、会员、灵感、收藏和一键检测;若已安装用户明确指定平台对应的 yizhuan-<platform> Skill,必须优先使用对应的拆分平台 Skill。业务数据禁止臆造。
4
+ 安装、配置并使用易撰 CLI(yizhuan 命令)查询真实数据、提取文章/视频/图文内容的全量 Skill;若已安装用户明确指定平台对应的 yizhuan-<platform> Skill,必须优先使用对应的拆分平台 Skill。业务数据禁止臆造,文章创作由当前 Agent 完成。
5
5
  ---
6
6
 
7
7
  # 易撰 CLI
@@ -40,6 +40,9 @@ yizhuan doctor
40
40
  | 配置状态 | `yizhuan config show` |
41
41
  | 作品 | `yizhuan execute --ability works --query "百家号昨天新增了哪些作品"` |
42
42
  | 作品检索 | `yizhuan execute --ability works --params '{"mode":"search","keyword":"AI"}'` |
43
+ | 作品评论(明确 ID) | `yizhuan execute --ability works --params '{"mode":"comments","platform":"douyin","workId":"123456","count":20}'` |
44
+ | 作品评论(按标题定位) | `yizhuan execute --ability works --params '{"mode":"comments","platform":"douyin","title":"作品标题"}'` |
45
+ | 微信公众号/视频号评论 | `yizhuan execute --ability works --params '{"mode":"comments","platform":"weixin","workId":"https://mp.weixin.qq.com/s/文章链接","count":20}'` |
43
46
  | 指定作者作品 | `yizhuan query --json '{"intent":"works_search","scope":"public","platform":"toutiao","authorName":"大名府名人","timeRange":"3d"}'` |
44
47
  | 高级作品筛选 | `yizhuan query --json '{"intent":"works_search","scope":"public","platform":"weibo","categories":["娱乐","情感"],"content_type":"video","min_views":100000,"min_comments":10000,"sort_by":"views","order":"desc"}'` |
45
48
  | 作者查询 | `yizhuan execute --ability accounts --query "张三"` |
@@ -53,10 +56,14 @@ yizhuan doctor
53
56
  | 会员 | `yizhuan execute --ability membership` |
54
57
  | 我的灵感 / 灵感库 / 收藏作品 | `yizhuan execute --ability favorites` |
55
58
  | 一键检测 | 将标题和正文写入临时 JSON 文件后执行 `yizhuan execute --ability detection --json-file <file>` |
59
+ | 提取文章/视频/图文 | `yizhuan execute --ability content_extract --params '{"url":"https://..."}'` |
56
60
 
57
61
  ## 调用规则
58
62
 
59
63
  - 需要真实易撰数据时必须调用 CLI,不直接猜测结果。
64
+ - 用户只说“写一篇中秋文章”等纯创作请求时,不调用 CLI,由当前 Agent 直接创作。
65
+ - 用户要求提取文章正文、视频口播文字或图文素材时,使用 `content_extract`;来源可以是 `url` 或易撰 `contentId`。
66
+ - 用户要求“根据易撰热门内容创作”时,先调用查询/提取能力获取真实素材,再由当前 Agent 完成创作;CLI 不生成、改写、生成标题或发布内容。
60
67
  - 一键检测的原创度检测当前只有百度引擎。展示检测结果时使用 `data.originalScore` 和 `data.originalEngine`;不得把历史兼容字段 `_360`、`sogou`、`zonghe` 展示为检测引擎或额外得分。
61
68
  - 一键检测支持 `submit`、`get` 和 `wait` 模式。`wait` 必须按照服务端 `pollAfterSeconds` 轮询;pending、failed、timeout 状态必须如实报告,成功、失败或超时后均清理包含标题和正文的临时 JSON 文件。
62
69
  - PowerShell 使用单引号包裹 JSON。终端可能改写引号时,将不含密钥的请求对象写入文件,再使用 `--json-file`。
@@ -71,6 +78,10 @@ yizhuan doctor
71
78
  - 关注公开作者时,先用 `author_search` 取得并选定完整作者资料,再调用 `accounts` 的 `mode=follow_public_author`;必须传该结果的 `platform`、`extAuthorId` 和 `nickname`。`nickname` 必须是公开搜索结果中的作者名称,绝不能将 `extAuthorId` 作为名称写入。
72
79
  - 公开作者结果中的 `workCount: 0` 可能是上游未返回作品数后的缺省值,不代表作者没有作品;是否有作品必须以 `works_search` 的结果为准。
73
80
  - 作品复合筛选优先使用统一协议 `intent=works_search`。平台使用 `platform`,分类使用 `categories`,内容类型使用 `content_type`,最低阅读/播放和评论分别使用 `min_views`、`min_comments`;需要固定顺序时显式传 `sort_by` 和 `order`。不得把作品查询改成作者、雷达或热点查询。
81
+ - 查询作品评论使用 `works` 的 `mode=comments`。有明确平台作品 ID 时传 `platform` + `workId`;只有作品标题时传 `platform` + `title`,CLI 会先检索作品,只有标题唯一匹配且能解析平台作品 ID 才继续查询。多个候选返回 `AMBIGUOUS_WORK`,不得自行猜测。
82
+ - 微信公众号和微信视频号评论通过登录采集机获取,平台分别传 `weixin`/`wxgzh` 和 `wxsph`/`视频号`,`workId` 必须是作品链接;这两个平台暂不支持 `cursor` 和 `parentId`。
83
+ - 作品评论默认返回一页、最多 50 条,未传 `count` 时按 20 条处理。需要继续翻页时,必须将上一页返回的 `data.cursor` 原样传回,依据 `data.hasMore` 停止;不得把评论数 `metrics.commentCount` 当作评论正文,也不得声称结果是“最新”或“热门”。
84
+ - 作品评论返回 `data.items[].text`、`user`、`likeCount`、`replyCount`、`ipLabel`、`createdAt` 等字段。查询评论回复时可额外传 `parentId`。评论发布、删除、点赞不属于本 Skill 能力。
74
85
  - 当前 CLI 不支持按单篇作品 URL 或平台侧 `articleId` 精确查询作品详情。用户提供作品链接或文章 ID 时,直接说明该能力暂不支持;不得将完整链接或纯文章 ID 改作 `keyword` 搜索,也不得把这种搜索返回的 `empty` 解读为全网不存在该作品。
75
86
  - 作品查询返回后必须逐项核对用户要求的分类、类型和指标阈值;低于阈值或缺少必要指标的项目不得作为符合条件的结果展示,也不得擅自放宽条件。展示总数必须使用返回的 `data.total`,不能把当前页条数当成总数。
76
87
  - 作者累计指标筛选使用 `author_query`,不得改成作品指标或擅自降低阈值。必须逐项映射用户给出的所有条件:粉丝使用 `min_follower` / `max_follower`,点赞使用 `min_total_likes` / `max_total_likes`,阅读使用 `min_total_views` / `max_total_views`,关注使用 `min_friends` / `max_friends`,作品数使用 `min_work_count` / `max_work_count`;复合条件不得遗漏任何字段。例如“百家号粉丝大于50万,点赞大于10万”必须同时传 `platform_id:2`、`min_follower:500000` 和 `min_total_likes:100000`。
@@ -8,7 +8,7 @@
8
8
  "files": [
9
9
  {
10
10
  "path": "SKILL.md",
11
- "sha256": "a46185057b4fa09503ba1773d3e8912a9a448c845f16c39759e5e19b246a1e39"
11
+ "sha256": "b58b68be1bd53fb3c9c572e8ccefcf000ad837c4f54d5269959d23f2c12150d4"
12
12
  }
13
13
  ]
14
14
  }
package/src/index.js CHANGED
@@ -26,7 +26,8 @@ const ABILITIES = new Set([
26
26
  'work_query',
27
27
  'membership_info',
28
28
  'favorites_query',
29
- 'detection'
29
+ 'detection',
30
+ 'content_extract'
30
31
  ])
31
32
 
32
33
  const PARAM_FLAG_KEYS = [
@@ -43,7 +44,9 @@ const PARAM_FLAG_KEYS = [
43
44
  'authorId',
44
45
  'extAuthorId',
45
46
  'collectionType',
46
- 'metric'
47
+ 'metric',
48
+ 'url', 'contentType', 'contentId', 'content_id', 'platformCode', 'platform_code',
49
+ 'outputFormat', 'output_format', 'includeImages', 'includeTranscriptSegments', 'source'
47
50
  ]
48
51
 
49
52
  function printHelp() {
@@ -64,12 +67,15 @@ Usage:
64
67
 
65
68
  Examples:
66
69
  yizhuan execute --ability works --query "百家号昨天新增了哪些作品"
70
+ yizhuan execute --ability works --params '{"mode":"comments","platform":"douyin","workId":"123456","count":20}'
71
+ yizhuan execute --ability works --params '{"mode":"comments","platform":"douyin","title":"作品标题","count":20}'
67
72
  yizhuan execute --ability hot_topics --platform douyin
68
73
  yizhuan execute --ability hot_topics --params '{"platform":"douyin"}'
69
74
  yizhuan execute --ability accounts --params '{"mode":"public_search","platform":"toutiao","keyword":"张三"}'
70
75
  yizhuan execute --ability radar --params '{"mode":"following"}'
71
76
  yizhuan execute --ability radar --mode timeline --timeRange 7d
72
77
  yizhuan execute --ability detection --json-file detection.json
78
+ yizhuan execute --ability content_extract --url "https://example.com/article"
73
79
  yizhuan execute --ability radar --params '{"mode":"unfollow","articleId":"205169870"}'
74
80
 
75
81
  Notes:
@@ -92,6 +98,7 @@ Abilities:
92
98
  public_author_search 作者全网搜索,兼容低层能力
93
99
  public_work_search 作品全网搜索,兼容低层能力
94
100
  detection 一键检测(原创/风险)
101
+ content_extract 提取文章、视频和图文内容
95
102
 
96
103
  Config:
97
104
  ${CONFIG_PATH}
@@ -220,7 +227,18 @@ function readConfig() {
220
227
 
221
228
  return {
222
229
  apiBaseUrl: String(config.apiBaseUrl).replace(/\/+$/, ''),
223
- apiKey: String(config.apiKey)
230
+ apiKey: String(config.apiKey),
231
+ telemetryEnabled: process.env.YIZHUAN_TELEMETRY !== '0'
232
+ }
233
+ }
234
+
235
+ function buildRequestHeaders(config) {
236
+ return {
237
+ authorization: config.apiKey,
238
+ 'content-type': 'application/json',
239
+ 'x-device-type': 'pc',
240
+ 'x-yizhuan-cli-version': readPackageVersion(),
241
+ 'x-yizhuan-telemetry': config.telemetryEnabled ? '1' : '0'
224
242
  }
225
243
  }
226
244
 
@@ -235,7 +253,16 @@ function stripWrappingQuotes(text) {
235
253
  return value
236
254
  }
237
255
 
238
- const OPAQUE_ID_KEYS = new Set(['extAuthorId', 'ext_author_id', 'author_id'])
256
+ // Platform work IDs can exceed Number.MAX_SAFE_INTEGER (Douyin aweme IDs are
257
+ // commonly 19 digits). Keep them opaque even when params use loose key=value
258
+ // parsing; JSON input already preserves quoted strings.
259
+ const OPAQUE_ID_KEYS = new Set([
260
+ 'extAuthorId',
261
+ 'ext_author_id',
262
+ 'author_id',
263
+ 'workId',
264
+ 'work_id'
265
+ ])
239
266
 
240
267
  function coerceScalar(value, key) {
241
268
  const text = stripWrappingQuotes(value).replace(/\\_/g, '_').trim()
@@ -435,11 +462,7 @@ async function execute(args) {
435
462
  const config = readConfig()
436
463
  const response = await fetch(`${config.apiBaseUrl}/api/cli.execute`, {
437
464
  method: 'POST',
438
- headers: {
439
- authorization: config.apiKey,
440
- 'content-type': 'application/json',
441
- 'x-device-type': 'pc'
442
- },
465
+ headers: buildRequestHeaders(config),
443
466
  body: JSON.stringify({
444
467
  json: {
445
468
  ability,
@@ -471,11 +494,7 @@ async function execute(args) {
471
494
  if (Date.now() >= deadline) break
472
495
  const poll = await fetch(`${config.apiBaseUrl}/api/cli.execute`, {
473
496
  method: 'POST',
474
- headers: {
475
- authorization: config.apiKey,
476
- 'content-type': 'application/json',
477
- 'x-device-type': 'pc'
478
- },
497
+ headers: buildRequestHeaders(config),
479
498
  body: JSON.stringify({
480
499
  json: { ability: 'detection', params: { mode: 'get', id: result.data.id } }
481
500
  })
@@ -522,11 +541,7 @@ async function query(args) {
522
541
  const config = readConfig()
523
542
  const response = await fetch(`${config.apiBaseUrl}/api/agent.query`, {
524
543
  method: 'POST',
525
- headers: {
526
- authorization: config.apiKey,
527
- 'content-type': 'application/json',
528
- 'x-device-type': 'pc'
529
- },
544
+ headers: buildRequestHeaders(config),
530
545
  body: JSON.stringify({ json: request })
531
546
  })
532
547
  const text = await response.text()