c456-cli 0.1.6 → 0.2.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.
Files changed (3) hide show
  1. package/README.md +30 -8
  2. package/dist/index.js +224 -69
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -83,19 +83,31 @@ c456 config show
83
83
 
84
84
  ## 常用命令
85
85
 
86
- ### 收录(intake)
86
+ ### 数据管理(5 大类)
87
87
 
88
88
  ```bash
89
- # 按 URL 创建 tool 收录(-B 为站点,-u 为收录目标)
90
- c456 -B https://c456.example.com intake new -k tool -u "https://github.com/owner/repo" --auto-resolve-url
89
+ # 工具
90
+ c456 tool new -u "https://github.com/owner/repo" --auto-resolve-url
91
+
92
+ # 渠道
93
+ c456 channel new -u "https://example.com" --auto-resolve-url
91
94
 
92
95
  # 纯文本信号(可无 URL)
93
- c456 intake new -k signal -t "标题" -b "正文"
96
+ c456 signal new -t "标题" -b "正文"
97
+
98
+ c456 signal show <id>
99
+ c456 signal list -q "关键词" --stage raw
100
+ c456 signal refine <id> --to cleaned --ai
101
+ c456 signal update <id> --refinement-status approved
102
+
103
+ # 打法(M1/M2 仍为独立资源;M3 会逐步合回 Intake)
104
+ c456 playbook new -t "标题" -b "Markdown 正文"
105
+ c456 playbook show <id>
106
+ c456 playbook list -q "关键词"
94
107
 
95
- c456 intake show <id>
96
- c456 intake list -k signal -q "关键词"
97
- c456 intake update <id> -t "新标题"
98
- c456 intake delete <id> --force
108
+ # 讲解
109
+ c456 walkthrough new -t "标题" --cast-file ./demo.cast
110
+ c456 walkthrough list
99
111
  ```
100
112
 
101
113
  ### 资料抓取(fetch)
@@ -111,6 +123,16 @@ c456 search signals -q "关键词"
111
123
  c456 search playbooks -q "关键词"
112
124
  ```
113
125
 
126
+ ### AI 自动识别入口(intake)
127
+
128
+ `intake` 保留为 **AI 识别与录入** 的入口:当你不确定应该落到 signal/tool/channel/playbook 时使用。
129
+
130
+ ```bash
131
+ c456 intake new -t "疑似工具/渠道/信号" -b "一段描述或粘贴内容"
132
+ ```
133
+
134
+ 当 AI 判断不在 `signal/tool/channel/playbook/walkthrough` 五类范围内,会返回 422 并给出错误提示;若识别为 `walkthrough`,会提示改用 `walkthrough` 子命令(因为需要媒体文件/外链)。
135
+
114
136
  ### 打法(playbook)
115
137
 
116
138
  ```bash
package/dist/index.js CHANGED
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/index.js
4
- import { Command as Command7 } from "commander";
4
+ import { Command as Command9 } from "commander";
5
5
 
6
6
  // package.json
7
7
  var package_default = {
8
8
  name: "c456-cli",
9
- version: "0.1.6",
9
+ version: "0.2.0",
10
10
  description: "C456 CLI - \u5185\u5BB9\u5F55\u5165\u4E0E\u6574\u7406\u5DE5\u5177",
11
11
  type: "module",
12
12
  bin: {
@@ -284,8 +284,8 @@ function readTextFile(path) {
284
284
  }
285
285
 
286
286
  // src/commands/intake.js
287
- var intake = new Command().name("intake").description("\u6536\u5F55\u7BA1\u7406 - \u521B\u5EFA\u3001\u66F4\u65B0\u3001\u5220\u9664\u5DE5\u5177/\u6E20\u9053/\u4FE1\u53F7");
288
- intake.command("new").description("\u521B\u5EFA\u65B0\u6536\u5F55").option("-u, --url <url>", "\u76EE\u6807 URL\uFF08tool/channel \u65F6\u53EF\u9009\uFF1B\u914D\u5408 --auto-resolve-url \u53EF\u81EA\u52A8\u89E3\u6790\u8D44\u6599\uFF09").option("-k, --kind <type>", "\u7C7B\u578B\uFF1Asignal/tool/channel\uFF08\u9ED8\u8BA4 signal\uFF09", "signal").option("-t, --title <title>", "\u6807\u9898\uFF08tool/channel \u5FC5\u586B\uFF09").option("-b, --body <text>", "\u6B63\u6587/\u63CF\u8FF0\uFF08\u4E0D\u63A8\u8350\u76F4\u63A5\u4F20\uFF1B\u8BF7\u7528 --body-file\uFF09").option("--body-file <path>", "\u6B63\u6587\u6587\u4EF6\u8DEF\u5F84\uFF08type: markdown_kramdown\uFF1B\u5EFA\u8BAE\u5199\u5230\u5F53\u524D\u76EE\u5F55 .tmp/\uFF09").option("--profile-data-json <json>", "\u8D44\u6599\u6BB5 JSON\uFF08tool/channel\uFF09").option("--auto-resolve-url", "\u81EA\u52A8\u89E3\u6790 URL \u5E76\u586B\u5145\u8D44\u6599\u6BB5 profile_data\uFF08\u4EC5 tool/channel\uFF1B\u4F1A\u53D1\u8D77\u7F51\u7EDC\u8BF7\u6C42\uFF09").action(async (opts, cmd) => {
287
+ var intake = new Command().name("intake").description("AI \u5F55\u5165\u5165\u53E3 - \u81EA\u52A8\u8BC6\u522B\u7C7B\u578B\u5E76\u521B\u5EFA\uFF08signal/tool/channel/playbook\uFF1Bwalkthrough \u9700\u8D70 walkthrough \u547D\u4EE4\uFF09");
288
+ intake.command("new").description("AI \u81EA\u52A8\u8BC6\u522B\u5E76\u521B\u5EFA\uFF08\u65E7\u7684 kind \u624B\u52A8\u521B\u5EFA\u8BF7\u6539\u7528 signal/tool/channel \u5B50\u547D\u4EE4\uFF09").option("-u, --url <url>", "\u53EF\u9009\uFF1A\u76EE\u6807 URL\uFF08\u6709\u65F6\u6709\u52A9\u4E8E AI \u5224\u65AD\uFF09").option("--hint <type>", "\u53EF\u9009\uFF1A\u63D0\u793A\u7C7B\u578B signal/tool/channel/playbook\uFF08\u4E0D\u4F1A\u5F3A\u5236\uFF09").option("-t, --title <title>", "\u53EF\u9009\uFF1A\u6807\u9898\uFF08AI \u53EF\u80FD\u4F1A\u91CD\u5199\uFF09").option("-b, --body <text>", "\u6B63\u6587/\u63CF\u8FF0\uFF08\u4E0D\u63A8\u8350\u76F4\u63A5\u4F20\uFF1B\u8BF7\u7528 --body-file\uFF09").option("--body-file <path>", "\u6B63\u6587\u6587\u4EF6\u8DEF\u5F84\uFF08type: markdown_kramdown\uFF1B\u5EFA\u8BAE\u5199\u5230\u5F53\u524D\u76EE\u5F55 .tmp/\uFF09").option("--dry-run", "\u53EA\u505A\u8BC6\u522B\u4E0E\u8349\u7A3F\u751F\u6210\uFF0C\u4E0D\u843D\u5E93\uFF08\u82E5\u670D\u52A1\u7AEF\u652F\u6301\uFF09").action(async (opts, cmd) => {
289
289
  const { apiKey, baseUrl, client } = resolveApi(cmd);
290
290
  if (!apiKey) {
291
291
  console.error("\u9519\u8BEF\uFF1A\u672A\u914D\u7F6E API Key");
@@ -298,57 +298,22 @@ intake.command("new").description("\u521B\u5EFA\u65B0\u6536\u5F55").option("-u,
298
298
  process.exit(1);
299
299
  }
300
300
  const bodyText = opts.bodyFile ? readTextFile(opts.bodyFile) : opts.body || "";
301
- const body = {
302
- kind: opts.kind,
301
+ const payload = {
303
302
  title: opts.title || "",
304
- body: bodyText
303
+ body: bodyText,
304
+ url: opts.url || "",
305
+ hint: opts.hint || "",
306
+ dry_run: Boolean(opts.dryRun)
305
307
  };
306
- if (opts.url) {
307
- body.url = opts.url;
308
- }
309
- if (opts.profileDataJson) {
310
- body.profile_data_json = opts.profileDataJson;
311
- }
312
- const kind = String(opts.kind ?? "signal");
313
- if (opts.autoResolveUrl) {
314
- if (!opts.url) {
315
- console.error("\u9519\u8BEF\uFF1A\u4F7F\u7528 --auto-resolve-url \u65F6\u5FC5\u987B\u540C\u65F6\u63D0\u4F9B -u/--url");
316
- process.exit(1);
317
- }
318
- if (kind !== "tool" && kind !== "channel") {
319
- console.error("\u9519\u8BEF\uFF1A--auto-resolve-url \u4EC5\u9002\u7528\u4E8E -k tool \u6216 -k channel");
320
- process.exit(1);
321
- }
322
- body.auto_resolve_url = true;
323
- }
324
- const result = await client.post("/intakes", body);
325
- console.log("\u2705 \u6536\u5F55\u521B\u5EFA\u6210\u529F");
326
- console.log(` ID: ${result.data.id}`);
327
- console.log(` \u7C7B\u578B\uFF1A${result.data.kind}`);
328
- console.log(` \u6807\u9898\uFF1A${result.data.title || "(\u65E0)"}`);
308
+ const result = await client.post("/intakes/ai", payload);
309
+ console.log("\u2705 AI \u8BC6\u522B\u6210\u529F");
310
+ if (result.data.kind) console.log(` \u8BC6\u522B\u7C7B\u578B\uFF1A${result.data.kind}`);
311
+ if (result.data.id) console.log(` ID: ${result.data.id}`);
312
+ if (result.data.title) console.log(` \u6807\u9898\uFF1A${result.data.title}`);
329
313
  console.log("\n--- JSON ---");
330
- console.log(
331
- JSON.stringify(
332
- {
333
- id: result.data.id,
334
- kind: result.data.kind,
335
- title: result.data.title || ""
336
- },
337
- null,
338
- 2
339
- )
340
- );
314
+ console.log(JSON.stringify(result.data, null, 2));
341
315
  } catch (err) {
342
316
  console.error(`\u274C \u521B\u5EFA\u5931\u8D25\uFF1A${err.message}`);
343
- const kind = String(opts.kind ?? "signal");
344
- const urlHint = Boolean(opts.url) && kind === "signal" && err instanceof ApiError && err.status === 422;
345
- if (urlHint) {
346
- console.error("");
347
- console.error("\u63D0\u793A\uFF1A\u5F53\u524D\u4E3A signal\uFF08\u9ED8\u8BA4\uFF09\u3002\u82E5\u8981\u89E3\u6790 URL \u7684\u8D44\u6599\u6BB5\uFF0C\u8BF7\u4F7F\u7528 `-k tool`/`-k channel` \u5E76\u663E\u5F0F\u5F00\u542F `--auto-resolve-url`\u3002");
348
- console.error(" \u793A\u4F8B\uFF1A");
349
- console.error(' c456 -B <\u7AD9\u70B9> intake new -k channel -u "<\u9891\u9053\u6216\u4E3B\u9875 URL>" --auto-resolve-url');
350
- console.error(' c456 -B <\u7AD9\u70B9> intake new -k tool -u "<\u5DE5\u5177 / \u4ED3\u5E93 URL>" --auto-resolve-url');
351
- }
352
317
  process.exit(1);
353
318
  }
354
319
  });
@@ -455,9 +420,196 @@ intake.command("list").description("\u5217\u51FA\u6536\u5F55\uFF08\u5206\u9875\u
455
420
  });
456
421
  var intake_default = intake;
457
422
 
458
- // src/commands/fetch.js
423
+ // src/commands/signal.js
424
+ import { Command as Command3 } from "commander";
425
+
426
+ // src/commands/_intake_kind_helpers.js
459
427
  import { Command as Command2 } from "commander";
460
- var fetchProfile = new Command2().name("fetch").description("\u8D44\u6599\u6293\u53D6 - \u4ECE URL \u81EA\u52A8\u89E3\u6790\u5E73\u53F0\u8D44\u6599");
428
+ function requireApiKey(apiKey) {
429
+ if (!apiKey) {
430
+ console.error("\u9519\u8BEF\uFF1A\u672A\u914D\u7F6E API Key");
431
+ console.error("\u4F7F\u7528 c456 config set-key <token> \u914D\u7F6E\uFF0C\u6216\u8BBE\u7F6E C456_API_KEY \u73AF\u5883\u53D8\u91CF");
432
+ process.exit(1);
433
+ }
434
+ }
435
+ function buildKindCommand(kind, label) {
436
+ const cmd = new Command2().name(kind).description(`${label} \u7BA1\u7406 - \u521B\u5EFA\u3001\u66F4\u65B0\u3001\u5220\u9664\u3001\u5217\u8868`);
437
+ cmd.command("new").description(`\u521B\u5EFA\u65B0${label}`).option("-u, --url <url>", "\u76EE\u6807 URL\uFF08tool/channel \u65F6\u53EF\u9009\uFF1B\u914D\u5408 --auto-resolve-url \u53EF\u81EA\u52A8\u89E3\u6790\u8D44\u6599\uFF09").option("-t, --title <title>", "\u6807\u9898\uFF08tool/channel \u5FC5\u586B\uFF1Bsignal \u53EF\u9009\uFF09").option("-b, --body <text>", "\u6B63\u6587/\u63CF\u8FF0\uFF08\u4E0D\u63A8\u8350\u76F4\u63A5\u4F20\uFF1B\u8BF7\u7528 --body-file\uFF09").option("--body-file <path>", "\u6B63\u6587\u6587\u4EF6\u8DEF\u5F84\uFF08type: markdown_kramdown\uFF1B\u5EFA\u8BAE\u5199\u5230\u5F53\u524D\u76EE\u5F55 .tmp/\uFF09").option("--profile-data-json <json>", "\u8D44\u6599\u6BB5 JSON\uFF08tool/channel\uFF09").option("--auto-resolve-url", "\u81EA\u52A8\u89E3\u6790 URL \u5E76\u586B\u5145\u8D44\u6599\u6BB5 profile_data\uFF08\u4EC5 tool/channel\uFF1B\u4F1A\u53D1\u8D77\u7F51\u7EDC\u8BF7\u6C42\uFF09").action(async (opts, cmd2) => {
438
+ const { apiKey, client } = resolveApi(cmd2);
439
+ requireApiKey(apiKey);
440
+ if (opts.body && opts.bodyFile) {
441
+ console.error("\u9519\u8BEF\uFF1A--body \u4E0E --body-file \u4E0D\u80FD\u540C\u65F6\u4F7F\u7528");
442
+ process.exit(1);
443
+ }
444
+ const bodyText = opts.bodyFile ? readTextFile(opts.bodyFile) : opts.body || "";
445
+ const body = {
446
+ kind,
447
+ title: opts.title || "",
448
+ body: bodyText
449
+ };
450
+ if (opts.url) body.url = opts.url;
451
+ if (opts.profileDataJson) body.profile_data_json = opts.profileDataJson;
452
+ if (opts.autoResolveUrl) {
453
+ if (!opts.url) {
454
+ console.error("\u9519\u8BEF\uFF1A\u4F7F\u7528 --auto-resolve-url \u65F6\u5FC5\u987B\u540C\u65F6\u63D0\u4F9B -u/--url");
455
+ process.exit(1);
456
+ }
457
+ if (kind !== "tool" && kind !== "channel") {
458
+ console.error("\u9519\u8BEF\uFF1A--auto-resolve-url \u4EC5\u9002\u7528\u4E8E tool \u6216 channel");
459
+ process.exit(1);
460
+ }
461
+ body.auto_resolve_url = true;
462
+ }
463
+ try {
464
+ const result = await client.post("/intakes", body);
465
+ console.log(`\u2705 ${label}\u521B\u5EFA\u6210\u529F`);
466
+ console.log(` ID: ${result.data.id}`);
467
+ console.log(` \u7C7B\u578B\uFF1A${result.data.kind}`);
468
+ console.log(` \u6807\u9898\uFF1A${result.data.title || "(\u65E0)"}`);
469
+ } catch (err) {
470
+ console.error(`\u274C \u521B\u5EFA\u5931\u8D25\uFF1A${err.message}`);
471
+ process.exit(1);
472
+ }
473
+ });
474
+ cmd.command("show").description(`\u67E5\u770B${label}\u8BE6\u60C5`).argument("<id>", `${label} ID`).action(async (id, opts, cmd2) => {
475
+ const { apiKey, client } = resolveApi(cmd2);
476
+ requireApiKey(apiKey);
477
+ try {
478
+ const result = await client.get(`/intakes/${id}`);
479
+ const data = result.data;
480
+ console.log(`ID: ${data.id}`);
481
+ console.log(`\u7C7B\u578B\uFF1A${data.kind}`);
482
+ console.log(`\u6807\u9898\uFF1A${data.title || "(\u65E0)"}`);
483
+ if (data.stage) console.log(`\u6F0F\u6597\uFF1A${data.stage} / ${data.refinementStatus || ""}`.trim());
484
+ if (data.derivedFromId) console.log(`\u4E0A\u6E38\uFF1AIntake #${data.derivedFromId}`);
485
+ console.log(`\u6B63\u6587\uFF1A${data.body || "(\u65E0)"}`);
486
+ } catch (err) {
487
+ console.error(`\u274C \u67E5\u8BE2\u5931\u8D25\uFF1A${err.message}`);
488
+ process.exit(1);
489
+ }
490
+ });
491
+ cmd.command("update").description(`\u66F4\u65B0${label}`).argument("<id>", `${label} ID`).option("-t, --title <title>", "\u65B0\u6807\u9898").option("-b, --body <text>", "\u65B0\u6B63\u6587\uFF08\u4E0D\u63A8\u8350\u76F4\u63A5\u4F20\uFF1B\u8BF7\u7528 --body-file\uFF09").option("--body-file <path>", "\u65B0\u6B63\u6587\u6587\u4EF6\u8DEF\u5F84\uFF08type: markdown_kramdown\uFF1B\u5EFA\u8BAE\u5199\u5230\u5F53\u524D\u76EE\u5F55 .tmp/\uFF09").option("--favorited", "\u6807\u8BB0\u4E3A\u6536\u85CF").option("--unfavorited", "\u53D6\u6D88\u6536\u85CF").option("--refinement-status <status>", "\u6F0F\u6597\u5904\u7406\u72B6\u6001\uFF08signal\uFF09\uFF1Aapproved/ai_drafting/ai_drafted/rejected/dropped").action(async (id, opts, cmd2) => {
492
+ const { apiKey, client } = resolveApi(cmd2);
493
+ requireApiKey(apiKey);
494
+ const body = {};
495
+ if (opts.title) body.title = opts.title;
496
+ if (opts.body && opts.bodyFile) {
497
+ console.error("\u9519\u8BEF\uFF1A--body \u4E0E --body-file \u4E0D\u80FD\u540C\u65F6\u4F7F\u7528");
498
+ process.exit(1);
499
+ }
500
+ if (opts.bodyFile) body.body = readTextFile(opts.bodyFile);
501
+ if (opts.body) body.body = opts.body;
502
+ if (opts.favorited) body.favorited = true;
503
+ if (opts.unfavorited) body.favorited = false;
504
+ if (opts.refinementStatus) body.refinement_status = opts.refinementStatus;
505
+ try {
506
+ await client.patch(`/intakes/${id}`, body);
507
+ console.log(`\u2705 ${label}\u66F4\u65B0\u6210\u529F`);
508
+ } catch (err) {
509
+ console.error(`\u274C \u66F4\u65B0\u5931\u8D25\uFF1A${err.message}`);
510
+ process.exit(1);
511
+ }
512
+ });
513
+ cmd.command("delete").description(`\u5220\u9664${label}`).argument("<id>", `${label} ID`).option("-f, --force", "\u5F3A\u5236\u5220\u9664\uFF08\u65E0\u9700\u786E\u8BA4\uFF09").action(async (id, opts, cmd2) => {
514
+ const { apiKey, client } = resolveApi(cmd2);
515
+ requireApiKey(apiKey);
516
+ if (!opts.force) {
517
+ const readline = await import("node:readline");
518
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
519
+ const answer = await new Promise((resolve) => {
520
+ rl.question("\u786E\u8BA4\u5220\u9664\uFF1F(y/N): ", (ans) => {
521
+ rl.close();
522
+ resolve(ans.toLowerCase());
523
+ });
524
+ });
525
+ if (answer !== "y" && answer !== "yes") {
526
+ console.log("\u5DF2\u53D6\u6D88");
527
+ return;
528
+ }
529
+ }
530
+ try {
531
+ await client.delete(`/intakes/${id}`);
532
+ console.log(`\u2705 ${label}\u5DF2\u5220\u9664`);
533
+ } catch (err) {
534
+ console.error(`\u274C \u5220\u9664\u5931\u8D25\uFF1A${err.message}`);
535
+ process.exit(1);
536
+ }
537
+ });
538
+ cmd.command("list").description(`\u5217\u51FA${label}\uFF08\u5206\u9875\uFF09`).option("-q, --query <text>", "\u641C\u7D22\u5173\u952E\u8BCD").option("-p, --page <num>", "\u9875\u7801\uFF081-10000\uFF09", "1").option("-n, --per-page <num>", "\u6BCF\u9875\u6570\u91CF\uFF081-100\uFF0C\u9ED8\u8BA4 20\uFF09", "20").option("--stage <stage>", "\uFF08signal\uFF09\u6F0F\u6597\u9636\u6BB5\uFF1Araw/cleaned/curated/playbook").option("--refinement-status <status>", "\uFF08signal\uFF09\u5904\u7406\u72B6\u6001\uFF1Aapproved/ai_drafting/ai_drafted/rejected/dropped").option("--include-dropped", "\uFF08signal\uFF09\u5305\u542B dropped\uFF08\u9ED8\u8BA4\u9690\u85CF\uFF09").option("--derived-from-id <id>", "\uFF08signal\uFF09\u53EA\u770B\u76F4\u63A5\u5B50\u9879").option("--tree-root-id <id>", "\uFF08signal\uFF09\u67E5\u770B\u67D0\u68F5\u6D3E\u751F\u6811\uFF08\u542B\u6839\uFF09").action(async (opts, cmd2) => {
539
+ const { apiKey, client } = resolveApi(cmd2);
540
+ requireApiKey(apiKey);
541
+ const params = {
542
+ kind,
543
+ q: opts.query,
544
+ page: opts.page,
545
+ per_page: opts.perPage
546
+ };
547
+ if (kind === "signal") {
548
+ if (opts.stage) params.stage = opts.stage;
549
+ if (opts.refinementStatus) params.refinement_status = opts.refinementStatus;
550
+ if (opts.includeDropped) params.include_dropped = 1;
551
+ if (opts.derivedFromId) params.derived_from_id = opts.derivedFromId;
552
+ if (opts.treeRootId) params.tree_root_id = opts.treeRootId;
553
+ }
554
+ try {
555
+ const result = await client.get("/intakes", params);
556
+ const { data, meta } = result;
557
+ const perPage = metaPerPage(meta);
558
+ const totalPages = Math.max(1, Math.ceil(meta.total / perPage));
559
+ console.log(`\u5171 ${meta.total} \u6761${label}\uFF08\u7B2C ${meta.page}/${totalPages} \u9875\uFF09
560
+ `);
561
+ data.forEach((item) => {
562
+ const stage = item.stage ? ` ${item.stage}/${item.refinementStatus || ""}` : "";
563
+ console.log(`\u2022 [${item.id}] ${item.kind}${stage}`);
564
+ console.log(` ${item.title || item.listSummary || "(\u65E0\u6807\u9898)"}`);
565
+ });
566
+ } catch (err) {
567
+ console.error(`\u274C \u67E5\u8BE2\u5931\u8D25\uFF1A${err.message}`);
568
+ const urlHint = Boolean(opts.url) && kind === "signal" && err instanceof ApiError && err.status === 422;
569
+ if (urlHint) {
570
+ console.error("");
571
+ console.error("\u63D0\u793A\uFF1A\u82E5\u8981\u89E3\u6790 URL \u7684\u8D44\u6599\u6BB5\uFF0C\u8BF7\u4F7F\u7528 tool/channel \u547D\u4EE4\u5E76\u663E\u5F0F\u5F00\u542F --auto-resolve-url\u3002");
572
+ }
573
+ process.exit(1);
574
+ }
575
+ });
576
+ return cmd;
577
+ }
578
+
579
+ // src/commands/signal.js
580
+ var signalCmd = buildKindCommand("signal", "\u4FE1\u53F7");
581
+ signalCmd.command("refine").description("\u6D3E\u751F\u4E0B\u4E00\u7EA7\uFF08raw\u2192cleaned / cleaned\u2192curated / curated\u2192playbook\uFF09").argument("<id>", "\u4FE1\u53F7 Intake ID").requiredOption("--to <stage>", "\u76EE\u6807\u9636\u6BB5\uFF1Acleaned/curated/playbook").option("--ai", "\u4F7F\u7528 AI \u8D77\u8349\uFF08mode=ai\uFF09").option("--manual", "\u624B\u52A8\u6D3E\u751F\uFF08\u9ED8\u8BA4\uFF09").action(async (id, opts, cmd) => {
582
+ const { apiKey, client } = resolveApi(cmd);
583
+ if (!apiKey) {
584
+ console.error("\u9519\u8BEF\uFF1A\u672A\u914D\u7F6E API Key");
585
+ process.exit(1);
586
+ }
587
+ const mode = opts.ai ? "ai" : "";
588
+ const result = await client.post(`/intakes/${id}/refinements`, { target_stage: opts.to, mode });
589
+ console.log("\u2705 \u5DF2\u6D3E\u751F");
590
+ console.log(` \u5B50\u9879 ID: ${result.data.id}`);
591
+ console.log(` stage: ${result.data.stage} / ${result.data.refinementStatus}`);
592
+ });
593
+ signalCmd.command("redraft").description("\u5BF9\u5931\u8D25\u7684 AI \u8D77\u8349\u91CD\u8BD5\uFF08rejected\u2192ai_drafting\uFF0C\u5E76\u5165\u961F Job\uFF09").argument("<id>", "\u5B50\u4FE1\u53F7 Intake ID\uFF08refinement_status=rejected\uFF09").action(async (id, opts, cmd) => {
594
+ const { apiKey, client } = resolveApi(cmd);
595
+ if (!apiKey) {
596
+ console.error("\u9519\u8BEF\uFF1A\u672A\u914D\u7F6E API Key");
597
+ process.exit(1);
598
+ }
599
+ await client.patch(`/intakes/${id}`, { refinement_status: "ai_drafting" });
600
+ console.log("\u2705 \u5DF2\u63D0\u4EA4\u91CD\u8BD5\u8D77\u8349");
601
+ });
602
+ var signal_default = signalCmd;
603
+
604
+ // src/commands/tool.js
605
+ var tool_default = buildKindCommand("tool", "\u5DE5\u5177");
606
+
607
+ // src/commands/channel.js
608
+ var channel_default = buildKindCommand("channel", "\u6E20\u9053");
609
+
610
+ // src/commands/fetch.js
611
+ import { Command as Command4 } from "commander";
612
+ var fetchProfile = new Command4().name("fetch").description("\u8D44\u6599\u6293\u53D6 - \u4ECE URL \u81EA\u52A8\u89E3\u6790\u5E73\u53F0\u8D44\u6599");
461
613
  fetchProfile.command("profile").description("\u6293\u53D6\u6307\u5B9A URL \u7684\u8D44\u6599\u6BB5\u6570\u636E").requiredOption("-u, --url <url>", "\u76EE\u6807 URL").requiredOption(
462
614
  "-p, --profile-id <type>",
463
615
  [
@@ -491,8 +643,8 @@ fetchProfile.command("profile").description("\u6293\u53D6\u6307\u5B9A URL \u7684
491
643
  var fetch_default = fetchProfile;
492
644
 
493
645
  // src/commands/search.js
494
- import { Command as Command3 } from "commander";
495
- var searchCmd = new Command3().name("search").description("\u641C\u7D22 - \u67E5\u627E\u53EF\u5173\u8054\u7684\u6536\u5F55\u6216\u6253\u6CD5");
646
+ import { Command as Command5 } from "commander";
647
+ var searchCmd = new Command5().name("search").description("\u641C\u7D22 - \u67E5\u627E\u53EF\u5173\u8054\u7684\u6536\u5F55\u6216\u6253\u6CD5");
496
648
  searchCmd.command("signals").description("\u641C\u7D22\u6536\u5F55\uFF08\u7528\u4E8E\u4FE1\u53F7\u5173\u8054\uFF09").option("-q, --query <text>", "\u641C\u7D22\u5173\u952E\u8BCD", "").option("-k, --kind <type>", "\u7C7B\u578B\u8FC7\u6EE4\uFF1Asignal/tool/channel").option("-l, --limit <num>", "\u7ED3\u679C\u6570\u91CF\u9650\u5236", "20").action(async (opts, cmd) => {
497
649
  const { apiKey, client } = resolveApi(cmd);
498
650
  if (!apiKey) {
@@ -561,8 +713,8 @@ searchCmd.command("playbooks").description("\u641C\u7D22\u6253\u6CD5\uFF08\u7528
561
713
  var search_default = searchCmd;
562
714
 
563
715
  // src/commands/playbook.js
564
- import { Command as Command4 } from "commander";
565
- var playbookCmd = new Command4().name("playbook").description("\u6253\u6CD5\u7BA1\u7406 - \u521B\u5EFA\u3001\u66F4\u65B0\u3001\u5220\u9664\u6253\u6CD5");
716
+ import { Command as Command6 } from "commander";
717
+ var playbookCmd = new Command6().name("playbook").description("\u6253\u6CD5\u7BA1\u7406 - \u521B\u5EFA\u3001\u66F4\u65B0\u3001\u5220\u9664\u6253\u6CD5");
566
718
  playbookCmd.command("new").description("\u521B\u5EFA\u65B0\u6253\u6CD5").requiredOption("-t, --title <title>", "\u6253\u6CD5\u6807\u9898").option("-b, --body <text>", "\u6253\u6CD5\u6B63\u6587\uFF08\u4E0D\u63A8\u8350\u76F4\u63A5\u4F20\uFF1B\u8BF7\u7528 --body-file\uFF09").option("--body-file <path>", "\u6253\u6CD5\u6B63\u6587\u6587\u4EF6\u8DEF\u5F84\uFF08type: markdown_kramdown\uFF1B\u5EFA\u8BAE\u5199\u5230\u5F53\u524D\u76EE\u5F55 .tmp/\uFF09").option("--ref-intake <id>", "\u5F15\u7528\u6536\u5F55 ID\uFF08\u53EF\u591A\u6B21\u6307\u5B9A\uFF09").option("--ref-playbook <id>", "\u5F15\u7528\u6253\u6CD5 ID\uFF08\u53EF\u591A\u6B21\u6307\u5B9A\uFF09").action(async (opts, cmd) => {
567
719
  const { apiKey, client } = resolveApi(cmd);
568
720
  if (!apiKey) {
@@ -715,9 +867,9 @@ playbookCmd.command("list").description("\u5217\u51FA\u6253\u6CD5\uFF08\u5206\u9
715
867
  var playbook_default = playbookCmd;
716
868
 
717
869
  // src/commands/walkthrough.js
718
- import { Command as Command5 } from "commander";
719
- var walkthroughCmd = new Command5().name("walkthrough").description("\u8BB2\u89E3\uFF08Walkthrough\uFF09\u7BA1\u7406 - \u521B\u5EFA\u3001\u66F4\u65B0\u3001\u5220\u9664\u8BB2\u89E3");
720
- function requireApiKey(apiKey) {
870
+ import { Command as Command7 } from "commander";
871
+ var walkthroughCmd = new Command7().name("walkthrough").description("\u8BB2\u89E3\uFF08Walkthrough\uFF09\u7BA1\u7406 - \u521B\u5EFA\u3001\u66F4\u65B0\u3001\u5220\u9664\u8BB2\u89E3");
872
+ function requireApiKey2(apiKey) {
721
873
  if (!apiKey) {
722
874
  console.error("\u9519\u8BEF\uFF1A\u672A\u914D\u7F6E API Key");
723
875
  process.exit(1);
@@ -744,7 +896,7 @@ function buildWalkthroughFields(opts) {
744
896
  }
745
897
  walkthroughCmd.command("new").description("\u521B\u5EFA\u65B0\u8BB2\u89E3").requiredOption("-t, --title <title>", "\u6807\u9898").option("-s, --summary <text>", "\u6458\u8981\uFF08\u4E0D\u63A8\u8350\u76F4\u63A5\u4F20\uFF1B\u8BF7\u7528 --summary-file\uFF09").option("--summary-file <path>", "\u6458\u8981\u6587\u4EF6\u8DEF\u5F84\uFF08\u5EFA\u8BAE\u5199\u5230\u5F53\u524D\u76EE\u5F55 .tmp/\uFF09").option("-b, --body <text>", "\u6B63\u6587\uFF08\u4E0D\u63A8\u8350\u76F4\u63A5\u4F20\uFF1B\u8BF7\u7528 --body-file\uFF09").option("--body-file <path>", "\u6B63\u6587\u6587\u4EF6\u8DEF\u5F84\uFF08type: markdown_kramdown\uFF1B\u5EFA\u8BAE\u5199\u5230\u5F53\u524D\u76EE\u5F55 .tmp/\uFF09").option("--source-kind <kind>", "\u6765\u6E90\uFF1Aupload/external_url\uFF08\u9ED8\u8BA4 upload\uFF09", "upload").option("--external-url <url>", "asciinema.org \u94FE\u63A5\uFF08source-kind=external_url \u65F6\u5FC5\u586B\uFF09").option("--cast-file <path>", ".cast \u6587\u4EF6\u8DEF\u5F84\uFF08source-kind=upload \u65F6\u5FC5\u586B\uFF09").option("--poster-at <seconds>", "\u5C01\u9762\u9884\u89C8\u79D2\u6570\uFF08>=0 \u7684\u6574\u6570\uFF09").action(async (opts, cmd) => {
746
898
  const { apiKey, client } = resolveApi(cmd);
747
- requireApiKey(apiKey);
899
+ requireApiKey2(apiKey);
748
900
  const sourceKind = ensureSourceKind(opts.sourceKind);
749
901
  const posterAt = opts.posterAt !== void 0 ? Number.parseInt(String(opts.posterAt), 10) : void 0;
750
902
  if (opts.body && opts.bodyFile) {
@@ -798,7 +950,7 @@ walkthroughCmd.command("new").description("\u521B\u5EFA\u65B0\u8BB2\u89E3").requ
798
950
  });
799
951
  walkthroughCmd.command("list").description("\u5217\u51FA\u8BB2\u89E3\uFF08\u5206\u9875\uFF09").option("-q, --query <text>", "\u641C\u7D22\u5173\u952E\u8BCD").option("-p, --page <num>", "\u9875\u7801\uFF081-10000\uFF09", "1").option("-n, --per-page <num>", "\u6BCF\u9875\u6570\u91CF\uFF081-100\uFF0C\u9ED8\u8BA4 20\uFF09", "20").action(async (opts, cmd) => {
800
952
  const { apiKey, client } = resolveApi(cmd);
801
- requireApiKey(apiKey);
953
+ requireApiKey2(apiKey);
802
954
  const result = await client.get("/walkthroughs", {
803
955
  q: opts.query,
804
956
  page: opts.page,
@@ -817,7 +969,7 @@ walkthroughCmd.command("list").description("\u5217\u51FA\u8BB2\u89E3\uFF08\u5206
817
969
  });
818
970
  walkthroughCmd.command("show").description("\u67E5\u770B\u8BB2\u89E3\u8BE6\u60C5").argument("<id>", "\u8BB2\u89E3 ID").action(async (id, opts, cmd) => {
819
971
  const { apiKey, client } = resolveApi(cmd);
820
- requireApiKey(apiKey);
972
+ requireApiKey2(apiKey);
821
973
  const result = await client.get(`/walkthroughs/${id}`);
822
974
  const w = result.data;
823
975
  console.log(`ID: ${w.id}`);
@@ -831,7 +983,7 @@ ${w.body || "(\u65E0)"}`);
831
983
  });
832
984
  walkthroughCmd.command("update").description("\u66F4\u65B0\u8BB2\u89E3").argument("<id>", "\u8BB2\u89E3 ID").option("-t, --title <title>", "\u65B0\u6807\u9898").option("-s, --summary <text>", "\u65B0\u6458\u8981\uFF08\u4E0D\u63A8\u8350\u76F4\u63A5\u4F20\uFF1B\u8BF7\u7528 --summary-file\uFF09").option("--summary-file <path>", "\u65B0\u6458\u8981\u6587\u4EF6\u8DEF\u5F84\uFF08\u5EFA\u8BAE\u5199\u5230\u5F53\u524D\u76EE\u5F55 .tmp/\uFF09").option("-b, --body <text>", "\u65B0\u6B63\u6587\uFF08\u4E0D\u63A8\u8350\u76F4\u63A5\u4F20\uFF1B\u8BF7\u7528 --body-file\uFF09").option("--body-file <path>", "\u65B0\u6B63\u6587\u6587\u4EF6\u8DEF\u5F84\uFF08type: markdown_kramdown\uFF1B\u5EFA\u8BAE\u5199\u5230\u5F53\u524D\u76EE\u5F55 .tmp/\uFF09").option("--publication-status <status>", "\u53D1\u5E03\u72B6\u6001\uFF1Apending_review/private").option("--source-kind <kind>", "\u6765\u6E90\uFF1Aupload/external_url").option("--external-url <url>", "asciinema.org \u94FE\u63A5\uFF08source-kind=external_url\uFF09").option("--cast-file <path>", ".cast \u6587\u4EF6\u8DEF\u5F84\uFF08\u4E0A\u4F20\u66FF\u6362\uFF09").option("--poster-at <seconds>", "\u5C01\u9762\u9884\u89C8\u79D2\u6570\uFF08>=0 \u7684\u6574\u6570\uFF09").action(async (id, opts, cmd) => {
833
985
  const { apiKey, client } = resolveApi(cmd);
834
- requireApiKey(apiKey);
986
+ requireApiKey2(apiKey);
835
987
  const posterAt = opts.posterAt !== void 0 ? Number.parseInt(String(opts.posterAt), 10) : void 0;
836
988
  if (opts.body && opts.bodyFile) {
837
989
  console.error("\u9519\u8BEF\uFF1A--body \u4E0E --body-file \u4E0D\u80FD\u540C\u65F6\u4F7F\u7528");
@@ -871,7 +1023,7 @@ walkthroughCmd.command("update").description("\u66F4\u65B0\u8BB2\u89E3").argumen
871
1023
  });
872
1024
  walkthroughCmd.command("delete").description("\u5220\u9664\u8BB2\u89E3").argument("<id>", "\u8BB2\u89E3 ID").option("-f, --force", "\u5F3A\u5236\u5220\u9664\uFF08\u65E0\u9700\u786E\u8BA4\uFF09").action(async (id, opts, cmd) => {
873
1025
  const { apiKey, client } = resolveApi(cmd);
874
- requireApiKey(apiKey);
1026
+ requireApiKey2(apiKey);
875
1027
  if (!opts.force) {
876
1028
  const readline = await import("node:readline");
877
1029
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
@@ -892,8 +1044,8 @@ walkthroughCmd.command("delete").description("\u5220\u9664\u8BB2\u89E3").argumen
892
1044
  var walkthrough_default = walkthroughCmd;
893
1045
 
894
1046
  // src/commands/config.js
895
- import { Command as Command6 } from "commander";
896
- var configCmd = new Command6().name("config").description("\u914D\u7F6E\u7BA1\u7406 - \u8BBE\u7F6E API Key \u548C\u7CFB\u7EDF\u5730\u5740");
1047
+ import { Command as Command8 } from "commander";
1048
+ var configCmd = new Command8().name("config").description("\u914D\u7F6E\u7BA1\u7406 - \u8BBE\u7F6E API Key \u548C\u7CFB\u7EDF\u5730\u5740");
897
1049
  configCmd.command("set-key").description("\u8BBE\u7F6E API Key").argument("<token>", "API Key \u4EE4\u724C").action((token, cmd) => {
898
1050
  const config = loadConfig();
899
1051
  config.apiKey = token;
@@ -989,18 +1141,21 @@ ${body}
989
1141
  }
990
1142
 
991
1143
  // src/index.js
992
- var program = new Command7();
1144
+ var program = new Command9();
993
1145
  program.name("c456").description("C456 CLI - \u5FEB\u901F\u5185\u5BB9\u5F55\u5165\u4E0E\u6574\u7406\u5DE5\u5177").version(package_default.version);
994
1146
  program.addHelpText("before", () => getHelpBanner());
995
1147
  program.option(
996
1148
  "-B, --base-url <url>",
997
1149
  "C456 \u7AD9\u70B9\u6839\u5730\u5740\uFF1B\u672A\u4F20\u5219\u4F7F\u7528 C456_URL \u73AF\u5883\u53D8\u91CF\u6216 ~/.config/c456/config.json \u7684 baseUrl\uFF0C\u9ED8\u8BA4 https://c456.com"
998
1150
  );
999
- program.addCommand(intake_default);
1151
+ program.addCommand(signal_default);
1152
+ program.addCommand(tool_default);
1153
+ program.addCommand(channel_default);
1000
1154
  program.addCommand(fetch_default);
1001
1155
  program.addCommand(search_default);
1002
1156
  program.addCommand(playbook_default);
1003
1157
  program.addCommand(walkthrough_default);
1158
+ program.addCommand(intake_default);
1004
1159
  program.addCommand(config_default);
1005
1160
  program.on("--help", () => {
1006
1161
  console.log("\n\u793A\u4F8B:");
@@ -1008,7 +1163,7 @@ program.on("--help", () => {
1008
1163
  console.log(" c456 config set-key your-api-token");
1009
1164
  console.log("");
1010
1165
  console.log(" # \u81EA\u6258\u7BA1\u7AD9\u70B9 + \u6309 URL \u6536\u5F55\u5DE5\u5177\uFF08-B=\u7AD9\u70B9\uFF0C-u=\u76EE\u6807 URL\uFF09");
1011
- console.log(' c456 -B https://c456.example.com intake new -k tool -u "https://github.com/owner/repo"');
1166
+ console.log(' c456 -B https://c456.example.com tool new -u "https://github.com/owner/repo" --auto-resolve-url');
1012
1167
  console.log("");
1013
1168
  console.log(" # \u641C\u7D22\u6536\u5F55");
1014
1169
  console.log(' c456 search signals -q "AI agent"');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "c456-cli",
3
- "version": "0.1.6",
3
+ "version": "0.2.0",
4
4
  "description": "C456 CLI - 内容录入与整理工具",
5
5
  "type": "module",
6
6
  "bin": {