c456-cli 0.1.6 → 0.3.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/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 Command10 } 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.3.0",
10
10
  description: "C456 CLI - \u5185\u5BB9\u5F55\u5165\u4E0E\u6574\u7406\u5DE5\u5177",
11
11
  type: "module",
12
12
  bin: {
@@ -14,6 +14,8 @@ var package_default = {
14
14
  },
15
15
  files: [
16
16
  "dist",
17
+ "docs",
18
+ "skills",
17
19
  "README.md"
18
20
  ],
19
21
  scripts: {
@@ -284,8 +286,8 @@ function readTextFile(path) {
284
286
  }
285
287
 
286
288
  // 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) => {
289
+ 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");
290
+ 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
291
  const { apiKey, baseUrl, client } = resolveApi(cmd);
290
292
  if (!apiKey) {
291
293
  console.error("\u9519\u8BEF\uFF1A\u672A\u914D\u7F6E API Key");
@@ -298,57 +300,22 @@ intake.command("new").description("\u521B\u5EFA\u65B0\u6536\u5F55").option("-u,
298
300
  process.exit(1);
299
301
  }
300
302
  const bodyText = opts.bodyFile ? readTextFile(opts.bodyFile) : opts.body || "";
301
- const body = {
302
- kind: opts.kind,
303
+ const payload = {
303
304
  title: opts.title || "",
304
- body: bodyText
305
+ body: bodyText,
306
+ url: opts.url || "",
307
+ hint: opts.hint || "",
308
+ dry_run: Boolean(opts.dryRun)
305
309
  };
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)"}`);
310
+ const result = await client.post("/intakes/ai", payload);
311
+ console.log("\u2705 AI \u8BC6\u522B\u6210\u529F");
312
+ if (result.data.kind) console.log(` \u8BC6\u522B\u7C7B\u578B\uFF1A${result.data.kind}`);
313
+ if (result.data.id) console.log(` ID: ${result.data.id}`);
314
+ if (result.data.title) console.log(` \u6807\u9898\uFF1A${result.data.title}`);
329
315
  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
- );
316
+ console.log(JSON.stringify(result.data, null, 2));
341
317
  } catch (err) {
342
318
  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
319
  process.exit(1);
353
320
  }
354
321
  });
@@ -373,7 +340,7 @@ intake.command("show").description("\u67E5\u770B\u6536\u5F55\u8BE6\u60C5").argum
373
340
  process.exit(1);
374
341
  }
375
342
  });
376
- intake.command("update").description("\u66F4\u65B0\u6536\u5F55").argument("<id>", "\u6536\u5F55 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").action(async (id, opts, cmd) => {
343
+ intake.command("update").description("\u66F4\u65B0\u6536\u5F55").argument("<id>", "\u6536\u5F55 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("--profile-data-json <json>", "tool/channel\uFF1Aprofile_data \u7247\u6BB5\uFF08JSON \u5B57\u7B26\u4E32\uFF0C\u4E0E API \u5408\u5E76\u89C4\u5219\u4E00\u81F4\uFF09").option("--profile-data-json-file <path>", "\u4ECE\u6587\u4EF6\u8BFB\u53D6 profile_data \u7247\u6BB5 JSON\uFF08\u4E0E --profile-data-json \u4E92\u65A5\uFF09").option("--favorited", "\u6807\u8BB0\u4E3A\u6536\u85CF").option("--unfavorited", "\u53D6\u6D88\u6536\u85CF").action(async (id, opts, cmd) => {
377
344
  const { apiKey, client } = resolveApi(cmd);
378
345
  if (!apiKey) {
379
346
  console.error("\u9519\u8BEF\uFF1A\u672A\u914D\u7F6E API Key");
@@ -387,8 +354,33 @@ intake.command("update").description("\u66F4\u65B0\u6536\u5F55").argument("<id>"
387
354
  }
388
355
  if (opts.bodyFile) body.body = readTextFile(opts.bodyFile);
389
356
  if (opts.body) body.body = opts.body;
357
+ if (opts.profileDataJson && opts.profileDataJsonFile) {
358
+ console.error("\u9519\u8BEF\uFF1A--profile-data-json \u4E0E --profile-data-json-file \u4E0D\u80FD\u540C\u65F6\u4F7F\u7528");
359
+ process.exit(1);
360
+ }
361
+ if (opts.profileDataJsonFile) {
362
+ try {
363
+ body.profile_data = JSON.parse(readTextFile(opts.profileDataJsonFile));
364
+ } catch (e) {
365
+ console.error(`\u9519\u8BEF\uFF1A\u65E0\u6CD5\u89E3\u6790 profile_data JSON\uFF08${e.message}\uFF09`);
366
+ process.exit(1);
367
+ }
368
+ } else if (opts.profileDataJson) {
369
+ try {
370
+ body.profile_data = JSON.parse(opts.profileDataJson);
371
+ } catch (e) {
372
+ console.error(`\u9519\u8BEF\uFF1A\u65E0\u6CD5\u89E3\u6790 --profile-data-json\uFF08${e.message}\uFF09`);
373
+ process.exit(1);
374
+ }
375
+ }
390
376
  if (opts.favorited) body.favorited = true;
391
377
  if (opts.unfavorited) body.favorited = false;
378
+ if (Object.keys(body).length === 0) {
379
+ console.error(
380
+ "\u9519\u8BEF\uFF1A\u8BF7\u81F3\u5C11\u63D0\u4F9B --title\u3001--body/--body-file\u3001--profile-data-json/--profile-data-json-file \u6216 --favorited/--unfavorited"
381
+ );
382
+ process.exit(1);
383
+ }
392
384
  try {
393
385
  await client.patch(`/intakes/${id}`, body);
394
386
  console.log("\u2705 \u6536\u5F55\u66F4\u65B0\u6210\u529F");
@@ -455,9 +447,196 @@ intake.command("list").description("\u5217\u51FA\u6536\u5F55\uFF08\u5206\u9875\u
455
447
  });
456
448
  var intake_default = intake;
457
449
 
458
- // src/commands/fetch.js
450
+ // src/commands/signal.js
451
+ import { Command as Command3 } from "commander";
452
+
453
+ // src/commands/_intake_kind_helpers.js
459
454
  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");
455
+ function requireApiKey(apiKey) {
456
+ if (!apiKey) {
457
+ console.error("\u9519\u8BEF\uFF1A\u672A\u914D\u7F6E API Key");
458
+ console.error("\u4F7F\u7528 c456 config set-key <token> \u914D\u7F6E\uFF0C\u6216\u8BBE\u7F6E C456_API_KEY \u73AF\u5883\u53D8\u91CF");
459
+ process.exit(1);
460
+ }
461
+ }
462
+ function buildKindCommand(kind, label) {
463
+ const cmd = new Command2().name(kind).description(`${label} \u7BA1\u7406 - \u521B\u5EFA\u3001\u66F4\u65B0\u3001\u5220\u9664\u3001\u5217\u8868`);
464
+ 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) => {
465
+ const { apiKey, client } = resolveApi(cmd2);
466
+ requireApiKey(apiKey);
467
+ if (opts.body && opts.bodyFile) {
468
+ console.error("\u9519\u8BEF\uFF1A--body \u4E0E --body-file \u4E0D\u80FD\u540C\u65F6\u4F7F\u7528");
469
+ process.exit(1);
470
+ }
471
+ const bodyText = opts.bodyFile ? readTextFile(opts.bodyFile) : opts.body || "";
472
+ const body = {
473
+ kind,
474
+ title: opts.title || "",
475
+ body: bodyText
476
+ };
477
+ if (opts.url) body.url = opts.url;
478
+ if (opts.profileDataJson) body.profile_data_json = opts.profileDataJson;
479
+ if (opts.autoResolveUrl) {
480
+ if (!opts.url) {
481
+ console.error("\u9519\u8BEF\uFF1A\u4F7F\u7528 --auto-resolve-url \u65F6\u5FC5\u987B\u540C\u65F6\u63D0\u4F9B -u/--url");
482
+ process.exit(1);
483
+ }
484
+ if (kind !== "tool" && kind !== "channel") {
485
+ console.error("\u9519\u8BEF\uFF1A--auto-resolve-url \u4EC5\u9002\u7528\u4E8E tool \u6216 channel");
486
+ process.exit(1);
487
+ }
488
+ body.auto_resolve_url = true;
489
+ }
490
+ try {
491
+ const result = await client.post("/intakes", body);
492
+ console.log(`\u2705 ${label}\u521B\u5EFA\u6210\u529F`);
493
+ console.log(` ID: ${result.data.id}`);
494
+ console.log(` \u7C7B\u578B\uFF1A${result.data.kind}`);
495
+ console.log(` \u6807\u9898\uFF1A${result.data.title || "(\u65E0)"}`);
496
+ } catch (err) {
497
+ console.error(`\u274C \u521B\u5EFA\u5931\u8D25\uFF1A${err.message}`);
498
+ process.exit(1);
499
+ }
500
+ });
501
+ cmd.command("show").description(`\u67E5\u770B${label}\u8BE6\u60C5`).argument("<id>", `${label} ID`).action(async (id, opts, cmd2) => {
502
+ const { apiKey, client } = resolveApi(cmd2);
503
+ requireApiKey(apiKey);
504
+ try {
505
+ const result = await client.get(`/intakes/${id}`);
506
+ const data = result.data;
507
+ console.log(`ID: ${data.id}`);
508
+ console.log(`\u7C7B\u578B\uFF1A${data.kind}`);
509
+ console.log(`\u6807\u9898\uFF1A${data.title || "(\u65E0)"}`);
510
+ if (data.stage) console.log(`\u6F0F\u6597\uFF1A${data.stage} / ${data.refinementStatus || ""}`.trim());
511
+ if (data.derivedFromId) console.log(`\u4E0A\u6E38\uFF1AIntake #${data.derivedFromId}`);
512
+ console.log(`\u6B63\u6587\uFF1A${data.body || "(\u65E0)"}`);
513
+ } catch (err) {
514
+ console.error(`\u274C \u67E5\u8BE2\u5931\u8D25\uFF1A${err.message}`);
515
+ process.exit(1);
516
+ }
517
+ });
518
+ 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) => {
519
+ const { apiKey, client } = resolveApi(cmd2);
520
+ requireApiKey(apiKey);
521
+ const body = {};
522
+ if (opts.title) body.title = opts.title;
523
+ if (opts.body && opts.bodyFile) {
524
+ console.error("\u9519\u8BEF\uFF1A--body \u4E0E --body-file \u4E0D\u80FD\u540C\u65F6\u4F7F\u7528");
525
+ process.exit(1);
526
+ }
527
+ if (opts.bodyFile) body.body = readTextFile(opts.bodyFile);
528
+ if (opts.body) body.body = opts.body;
529
+ if (opts.favorited) body.favorited = true;
530
+ if (opts.unfavorited) body.favorited = false;
531
+ if (opts.refinementStatus) body.refinement_status = opts.refinementStatus;
532
+ try {
533
+ await client.patch(`/intakes/${id}`, body);
534
+ console.log(`\u2705 ${label}\u66F4\u65B0\u6210\u529F`);
535
+ } catch (err) {
536
+ console.error(`\u274C \u66F4\u65B0\u5931\u8D25\uFF1A${err.message}`);
537
+ process.exit(1);
538
+ }
539
+ });
540
+ 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) => {
541
+ const { apiKey, client } = resolveApi(cmd2);
542
+ requireApiKey(apiKey);
543
+ if (!opts.force) {
544
+ const readline = await import("node:readline");
545
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
546
+ const answer = await new Promise((resolve) => {
547
+ rl.question("\u786E\u8BA4\u5220\u9664\uFF1F(y/N): ", (ans) => {
548
+ rl.close();
549
+ resolve(ans.toLowerCase());
550
+ });
551
+ });
552
+ if (answer !== "y" && answer !== "yes") {
553
+ console.log("\u5DF2\u53D6\u6D88");
554
+ return;
555
+ }
556
+ }
557
+ try {
558
+ await client.delete(`/intakes/${id}`);
559
+ console.log(`\u2705 ${label}\u5DF2\u5220\u9664`);
560
+ } catch (err) {
561
+ console.error(`\u274C \u5220\u9664\u5931\u8D25\uFF1A${err.message}`);
562
+ process.exit(1);
563
+ }
564
+ });
565
+ 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) => {
566
+ const { apiKey, client } = resolveApi(cmd2);
567
+ requireApiKey(apiKey);
568
+ const params = {
569
+ kind,
570
+ q: opts.query,
571
+ page: opts.page,
572
+ per_page: opts.perPage
573
+ };
574
+ if (kind === "signal") {
575
+ if (opts.stage) params.stage = opts.stage;
576
+ if (opts.refinementStatus) params.refinement_status = opts.refinementStatus;
577
+ if (opts.includeDropped) params.include_dropped = 1;
578
+ if (opts.derivedFromId) params.derived_from_id = opts.derivedFromId;
579
+ if (opts.treeRootId) params.tree_root_id = opts.treeRootId;
580
+ }
581
+ try {
582
+ const result = await client.get("/intakes", params);
583
+ const { data, meta } = result;
584
+ const perPage = metaPerPage(meta);
585
+ const totalPages = Math.max(1, Math.ceil(meta.total / perPage));
586
+ console.log(`\u5171 ${meta.total} \u6761${label}\uFF08\u7B2C ${meta.page}/${totalPages} \u9875\uFF09
587
+ `);
588
+ data.forEach((item) => {
589
+ const stage = item.stage ? ` ${item.stage}/${item.refinementStatus || ""}` : "";
590
+ console.log(`\u2022 [${item.id}] ${item.kind}${stage}`);
591
+ console.log(` ${item.title || item.listSummary || "(\u65E0\u6807\u9898)"}`);
592
+ });
593
+ } catch (err) {
594
+ console.error(`\u274C \u67E5\u8BE2\u5931\u8D25\uFF1A${err.message}`);
595
+ const urlHint = Boolean(opts.url) && kind === "signal" && err instanceof ApiError && err.status === 422;
596
+ if (urlHint) {
597
+ console.error("");
598
+ 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");
599
+ }
600
+ process.exit(1);
601
+ }
602
+ });
603
+ return cmd;
604
+ }
605
+
606
+ // src/commands/signal.js
607
+ var signalCmd = buildKindCommand("signal", "\u4FE1\u53F7");
608
+ 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) => {
609
+ const { apiKey, client } = resolveApi(cmd);
610
+ if (!apiKey) {
611
+ console.error("\u9519\u8BEF\uFF1A\u672A\u914D\u7F6E API Key");
612
+ process.exit(1);
613
+ }
614
+ const mode = opts.ai ? "ai" : "";
615
+ const result = await client.post(`/intakes/${id}/refinements`, { target_stage: opts.to, mode });
616
+ console.log("\u2705 \u5DF2\u6D3E\u751F");
617
+ console.log(` \u5B50\u9879 ID: ${result.data.id}`);
618
+ console.log(` stage: ${result.data.stage} / ${result.data.refinementStatus}`);
619
+ });
620
+ 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) => {
621
+ const { apiKey, client } = resolveApi(cmd);
622
+ if (!apiKey) {
623
+ console.error("\u9519\u8BEF\uFF1A\u672A\u914D\u7F6E API Key");
624
+ process.exit(1);
625
+ }
626
+ await client.patch(`/intakes/${id}`, { refinement_status: "ai_drafting" });
627
+ console.log("\u2705 \u5DF2\u63D0\u4EA4\u91CD\u8BD5\u8D77\u8349");
628
+ });
629
+ var signal_default = signalCmd;
630
+
631
+ // src/commands/tool.js
632
+ var tool_default = buildKindCommand("tool", "\u5DE5\u5177");
633
+
634
+ // src/commands/channel.js
635
+ var channel_default = buildKindCommand("channel", "\u6E20\u9053");
636
+
637
+ // src/commands/fetch.js
638
+ import { Command as Command4 } from "commander";
639
+ var fetchProfile = new Command4().name("fetch").description("\u8D44\u6599\u6293\u53D6 - \u4ECE URL \u81EA\u52A8\u89E3\u6790\u5E73\u53F0\u8D44\u6599");
461
640
  fetchProfile.command("profile").description("\u6293\u53D6\u6307\u5B9A URL \u7684\u8D44\u6599\u6BB5\u6570\u636E").requiredOption("-u, --url <url>", "\u76EE\u6807 URL").requiredOption(
462
641
  "-p, --profile-id <type>",
463
642
  [
@@ -491,8 +670,8 @@ fetchProfile.command("profile").description("\u6293\u53D6\u6307\u5B9A URL \u7684
491
670
  var fetch_default = fetchProfile;
492
671
 
493
672
  // 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");
673
+ import { Command as Command5 } from "commander";
674
+ var searchCmd = new Command5().name("search").description("\u641C\u7D22 - \u67E5\u627E\u53EF\u5173\u8054\u7684\u6536\u5F55\u6216\u6253\u6CD5");
496
675
  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
676
  const { apiKey, client } = resolveApi(cmd);
498
677
  if (!apiKey) {
@@ -561,8 +740,8 @@ searchCmd.command("playbooks").description("\u641C\u7D22\u6253\u6CD5\uFF08\u7528
561
740
  var search_default = searchCmd;
562
741
 
563
742
  // 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");
743
+ import { Command as Command6 } from "commander";
744
+ var playbookCmd = new Command6().name("playbook").description("\u6253\u6CD5\u7BA1\u7406 - \u521B\u5EFA\u3001\u66F4\u65B0\u3001\u5220\u9664\u6253\u6CD5");
566
745
  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
746
  const { apiKey, client } = resolveApi(cmd);
568
747
  if (!apiKey) {
@@ -715,9 +894,9 @@ playbookCmd.command("list").description("\u5217\u51FA\u6253\u6CD5\uFF08\u5206\u9
715
894
  var playbook_default = playbookCmd;
716
895
 
717
896
  // 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) {
897
+ import { Command as Command7 } from "commander";
898
+ var walkthroughCmd = new Command7().name("walkthrough").description("\u8BB2\u89E3\uFF08Walkthrough\uFF09\u7BA1\u7406 - \u521B\u5EFA\u3001\u66F4\u65B0\u3001\u5220\u9664\u8BB2\u89E3");
899
+ function requireApiKey2(apiKey) {
721
900
  if (!apiKey) {
722
901
  console.error("\u9519\u8BEF\uFF1A\u672A\u914D\u7F6E API Key");
723
902
  process.exit(1);
@@ -744,7 +923,7 @@ function buildWalkthroughFields(opts) {
744
923
  }
745
924
  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
925
  const { apiKey, client } = resolveApi(cmd);
747
- requireApiKey(apiKey);
926
+ requireApiKey2(apiKey);
748
927
  const sourceKind = ensureSourceKind(opts.sourceKind);
749
928
  const posterAt = opts.posterAt !== void 0 ? Number.parseInt(String(opts.posterAt), 10) : void 0;
750
929
  if (opts.body && opts.bodyFile) {
@@ -798,7 +977,7 @@ walkthroughCmd.command("new").description("\u521B\u5EFA\u65B0\u8BB2\u89E3").requ
798
977
  });
799
978
  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
979
  const { apiKey, client } = resolveApi(cmd);
801
- requireApiKey(apiKey);
980
+ requireApiKey2(apiKey);
802
981
  const result = await client.get("/walkthroughs", {
803
982
  q: opts.query,
804
983
  page: opts.page,
@@ -817,7 +996,7 @@ walkthroughCmd.command("list").description("\u5217\u51FA\u8BB2\u89E3\uFF08\u5206
817
996
  });
818
997
  walkthroughCmd.command("show").description("\u67E5\u770B\u8BB2\u89E3\u8BE6\u60C5").argument("<id>", "\u8BB2\u89E3 ID").action(async (id, opts, cmd) => {
819
998
  const { apiKey, client } = resolveApi(cmd);
820
- requireApiKey(apiKey);
999
+ requireApiKey2(apiKey);
821
1000
  const result = await client.get(`/walkthroughs/${id}`);
822
1001
  const w = result.data;
823
1002
  console.log(`ID: ${w.id}`);
@@ -831,7 +1010,7 @@ ${w.body || "(\u65E0)"}`);
831
1010
  });
832
1011
  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
1012
  const { apiKey, client } = resolveApi(cmd);
834
- requireApiKey(apiKey);
1013
+ requireApiKey2(apiKey);
835
1014
  const posterAt = opts.posterAt !== void 0 ? Number.parseInt(String(opts.posterAt), 10) : void 0;
836
1015
  if (opts.body && opts.bodyFile) {
837
1016
  console.error("\u9519\u8BEF\uFF1A--body \u4E0E --body-file \u4E0D\u80FD\u540C\u65F6\u4F7F\u7528");
@@ -871,7 +1050,7 @@ walkthroughCmd.command("update").description("\u66F4\u65B0\u8BB2\u89E3").argumen
871
1050
  });
872
1051
  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
1052
  const { apiKey, client } = resolveApi(cmd);
874
- requireApiKey(apiKey);
1053
+ requireApiKey2(apiKey);
875
1054
  if (!opts.force) {
876
1055
  const readline = await import("node:readline");
877
1056
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
@@ -891,9 +1070,131 @@ walkthroughCmd.command("delete").description("\u5220\u9664\u8BB2\u89E3").argumen
891
1070
  });
892
1071
  var walkthrough_default = walkthroughCmd;
893
1072
 
1073
+ // src/commands/asset.js
1074
+ import { createHash } from "node:crypto";
1075
+ import { extname } from "node:path";
1076
+ import { Command as Command8 } from "commander";
1077
+
1078
+ // src/mediaLibraryFingerprint.js
1079
+ function normalizeForFingerprint(markdown) {
1080
+ const OMIT = "__C456_ASSET_URL_OMITTED__";
1081
+ const dquote = /!\[([^\]]*)\]\(\s*(https?:\/\/[^\s)]+)\s+"(c456:asset\/(\d+))"\s*\)/g;
1082
+ const squote = /!\[([^\]]*)\]\(\s*(https?:\/\/[^\s)]+)\s+'(c456:asset\/(\d+))'\s*\)/g;
1083
+ let s = String(markdown ?? "");
1084
+ s = s.replace(dquote, (_m, alt, _url, title) => `![${alt}](${OMIT} "${title}")`);
1085
+ s = s.replace(squote, (_m, alt, _url, title) => `![${alt}](${OMIT} '${title}')`);
1086
+ return s;
1087
+ }
1088
+
1089
+ // src/commands/asset.js
1090
+ var extToMime = {
1091
+ ".png": "image/png",
1092
+ ".jpg": "image/jpeg",
1093
+ ".jpeg": "image/jpeg",
1094
+ ".gif": "image/gif",
1095
+ ".webp": "image/webp",
1096
+ ".svg": "image/svg+xml"
1097
+ };
1098
+ function guessImageContentType(filePath) {
1099
+ const ext = extname(filePath).toLowerCase();
1100
+ return extToMime[ext] || "application/octet-stream";
1101
+ }
1102
+ var assetCmd = new Command8().name("asset").description("\u7D20\u6750\u5E93\uFF08\u56FE\u7247\uFF09\u2014 \u4E0A\u4F20\u3001\u5217\u8868\u3001\u7EED\u671F\u6B63\u6587\u4E2D\u7684\u9884\u89C8\u94FE\u63A5");
1103
+ function requireApiKey3(apiKey) {
1104
+ if (!apiKey) {
1105
+ console.error("\u9519\u8BEF\uFF1A\u672A\u914D\u7F6E API Key");
1106
+ process.exit(1);
1107
+ }
1108
+ }
1109
+ function sha256HexUtf8(markdown) {
1110
+ return createHash("sha256").update(normalizeForFingerprint(markdown), "utf8").digest("hex");
1111
+ }
1112
+ assetCmd.command("upload").description("\u4E0A\u4F20\u56FE\u7247\u5230\u7D20\u6750\u5E93").requiredOption("-f, --file <path>", "\u672C\u5730\u56FE\u7247\u8DEF\u5F84").action(async (opts, cmd) => {
1113
+ const { apiKey, client } = resolveApi(cmd);
1114
+ requireApiKey3(apiKey);
1115
+ const result = await client.postMultipart(
1116
+ "/assets",
1117
+ {},
1118
+ {
1119
+ fieldName: "file",
1120
+ filePath: opts.file,
1121
+ filename: void 0,
1122
+ contentType: guessImageContentType(opts.file)
1123
+ }
1124
+ );
1125
+ const d = result.data;
1126
+ console.log("\u2705 \u4E0A\u4F20\u6210\u529F");
1127
+ console.log(` id: ${d.id}`);
1128
+ console.log(` previewUrl: ${d.previewUrl}`);
1129
+ console.log("");
1130
+ console.log(d.markdownSnippet);
1131
+ });
1132
+ assetCmd.command("list").description("\u5217\u51FA\u7D20\u6750").option("-p, --page <num>", "\u9875\u7801", "1").option("-n, --per-page <num>", "\u6BCF\u9875\u6761\u6570", "50").action(async (opts, cmd) => {
1133
+ const { apiKey, client } = resolveApi(cmd);
1134
+ requireApiKey3(apiKey);
1135
+ const page = Number.parseInt(String(opts.page), 10) || 1;
1136
+ const perPage = Number.parseInt(String(opts.perPage), 10) || 50;
1137
+ const { data, meta } = await client.get("/assets", { page, per_page: perPage });
1138
+ const n = metaPerPage(meta);
1139
+ console.log(`\u5171 ${meta?.total ?? "?"} \u6761 \xB7 \u6BCF\u9875 ${n} \xB7 \u7B2C ${meta?.page ?? page} \u9875`);
1140
+ for (const row of data || []) {
1141
+ console.log(`- #${row.id} ${row.filename ?? ""} ${row.markdownSnippet ?? ""}`);
1142
+ }
1143
+ });
1144
+ assetCmd.command("update").description("\u66F4\u65B0\u7D20\u6750\u5728\u5E93\u4E2D\u7684\u5C55\u793A\u6587\u4EF6\u540D\uFF08\u4E0D\u66FF\u6362\u56FE\u7247\u5185\u5BB9\uFF1BJSON PATCH /assets/:id\uFF09").argument("<id>", "\u7D20\u6750 ID").requiredOption("--filename <name>", "\u65B0\u7684\u5C55\u793A\u6587\u4EF6\u540D\uFF0C\u5982 logo.webp").action(async (id, opts, cmd) => {
1145
+ const { apiKey, client } = resolveApi(cmd);
1146
+ requireApiKey3(apiKey);
1147
+ const { data } = await client.patch(`/assets/${id}`, { filename: opts.filename });
1148
+ console.log("\u2705 \u5DF2\u66F4\u65B0");
1149
+ console.log(` id: ${data.id}`);
1150
+ console.log(` filename: ${data.filename ?? ""}`);
1151
+ console.log("");
1152
+ console.log(data.markdownSnippet ?? "");
1153
+ });
1154
+ assetCmd.command("show").description("\u67E5\u770B\u5355\u6761\u7D20\u6750").argument("<id>", "\u7D20\u6750 ID").action(async (id, _opts, cmd) => {
1155
+ const { apiKey, client } = resolveApi(cmd);
1156
+ requireApiKey3(apiKey);
1157
+ const { data } = await client.get(`/assets/${id}`);
1158
+ console.log(JSON.stringify(data, null, 2));
1159
+ });
1160
+ assetCmd.command("delete").description("\u5220\u9664\u7D20\u6750\uFF08\u82E5\u4ECD\u88AB\u6B63\u6587\u5F15\u7528\u4F1A\u5931\u8D25\uFF09").argument("<id>", "\u7D20\u6750 ID").action(async (id, _opts, cmd) => {
1161
+ const { apiKey, client } = resolveApi(cmd);
1162
+ requireApiKey3(apiKey);
1163
+ await client.delete(`/assets/${id}`);
1164
+ console.log("\u2705 \u5DF2\u5220\u9664");
1165
+ });
1166
+ assetCmd.command("refresh-markdown").description("\u7EED\u671F\u6B63\u6587\u4E2D\u7684\u7D20\u6750\u9884\u89C8 URL\uFF08\u8BFB\u5165 Markdown\uFF0C\u8F93\u51FA\u66FF\u6362\u540E\u7684\u5168\u6587\u5230 stdout\uFF09").option("-b, --body <text>", "Markdown \u5B57\u7B26\u4E32").option("--body-file <path>", "Markdown \u6587\u4EF6\u8DEF\u5F84").action(async (opts, cmd) => {
1167
+ const { apiKey, client } = resolveApi(cmd);
1168
+ requireApiKey3(apiKey);
1169
+ if (opts.body && opts.bodyFile) {
1170
+ console.error("\u9519\u8BEF\uFF1A--body \u4E0E --body-file \u4E0D\u80FD\u540C\u65F6\u4F7F\u7528");
1171
+ process.exit(1);
1172
+ }
1173
+ const markdown = opts.bodyFile ? readTextFile(opts.bodyFile) : opts.body ?? "";
1174
+ if (!markdown) {
1175
+ console.error("\u9519\u8BEF\uFF1A\u8BF7\u63D0\u4F9B --body \u6216 --body-file");
1176
+ process.exit(1);
1177
+ }
1178
+ const { data } = await client.post("/assets/refresh_markdown", { markdown });
1179
+ process.stdout.write(String(data.markdown ?? ""));
1180
+ });
1181
+ assetCmd.command("fingerprint").description("\u5BF9\u6B63\u6587\u505A\u4E0E\u670D\u52A1\u5668\u4E00\u81F4\u7684\u89C4\u8303\u5316\u540E\u8F93\u51FA sha256 hex\uFF08\u4E0D\u8C03\u7528\u7F51\u7EDC\uFF09").option("-b, --body <text>", "Markdown \u5B57\u7B26\u4E32").option("--body-file <path>", "Markdown \u6587\u4EF6\u8DEF\u5F84").action(async (opts) => {
1182
+ if (opts.body && opts.bodyFile) {
1183
+ console.error("\u9519\u8BEF\uFF1A--body \u4E0E --body-file \u4E0D\u80FD\u540C\u65F6\u4F7F\u7528");
1184
+ process.exit(1);
1185
+ }
1186
+ const markdown = opts.bodyFile ? readTextFile(opts.bodyFile) : opts.body ?? "";
1187
+ if (!markdown) {
1188
+ console.error("\u9519\u8BEF\uFF1A\u8BF7\u63D0\u4F9B --body \u6216 --body-file");
1189
+ process.exit(1);
1190
+ }
1191
+ console.log(sha256HexUtf8(markdown));
1192
+ });
1193
+ var asset_default = assetCmd;
1194
+
894
1195
  // 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");
1196
+ import { Command as Command9 } from "commander";
1197
+ var configCmd = new Command9().name("config").description("\u914D\u7F6E\u7BA1\u7406 - \u8BBE\u7F6E API Key \u548C\u7CFB\u7EDF\u5730\u5740");
897
1198
  configCmd.command("set-key").description("\u8BBE\u7F6E API Key").argument("<token>", "API Key \u4EE4\u724C").action((token, cmd) => {
898
1199
  const config = loadConfig();
899
1200
  config.apiKey = token;
@@ -989,18 +1290,44 @@ ${body}
989
1290
  }
990
1291
 
991
1292
  // src/index.js
992
- var program = new Command7();
1293
+ var program = new Command10();
993
1294
  program.name("c456").description("C456 CLI - \u5FEB\u901F\u5185\u5BB9\u5F55\u5165\u4E0E\u6574\u7406\u5DE5\u5177").version(package_default.version);
994
- program.addHelpText("before", () => getHelpBanner());
1295
+ program.addHelpText("before", () => {
1296
+ const banner = getHelpBanner();
1297
+ const versionLine = `c456-cli ${package_default.version}`;
1298
+ if (!banner) {
1299
+ return `
1300
+ ${versionLine}
1301
+ `;
1302
+ }
1303
+ return `${banner}
1304
+ ${versionLine}
1305
+ `;
1306
+ });
1307
+ program.exitOverride((err) => {
1308
+ if (err.code === "commander.executeSubCommandAsync") {
1309
+ process.exit(err.exitCode ?? 1);
1310
+ return;
1311
+ }
1312
+ if (err.code === "commander.help" && err.exitCode === 1) {
1313
+ process.exit(0);
1314
+ return;
1315
+ }
1316
+ process.exit(err.exitCode ?? 1);
1317
+ });
995
1318
  program.option(
996
1319
  "-B, --base-url <url>",
997
1320
  "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
1321
  );
999
- program.addCommand(intake_default);
1322
+ program.addCommand(signal_default);
1323
+ program.addCommand(tool_default);
1324
+ program.addCommand(channel_default);
1000
1325
  program.addCommand(fetch_default);
1001
1326
  program.addCommand(search_default);
1002
1327
  program.addCommand(playbook_default);
1003
1328
  program.addCommand(walkthrough_default);
1329
+ program.addCommand(asset_default);
1330
+ program.addCommand(intake_default);
1004
1331
  program.addCommand(config_default);
1005
1332
  program.on("--help", () => {
1006
1333
  console.log("\n\u793A\u4F8B:");
@@ -1008,7 +1335,7 @@ program.on("--help", () => {
1008
1335
  console.log(" c456 config set-key your-api-token");
1009
1336
  console.log("");
1010
1337
  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"');
1338
+ console.log(' c456 -B https://c456.example.com tool new -u "https://github.com/owner/repo" --auto-resolve-url');
1012
1339
  console.log("");
1013
1340
  console.log(" # \u641C\u7D22\u6536\u5F55");
1014
1341
  console.log(' c456 search signals -q "AI agent"');