c456-cli 0.1.0 → 0.1.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.
Files changed (3) hide show
  1. package/README.md +2 -0
  2. package/dist/index.js +233 -11
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -129,6 +129,8 @@ bun run build
129
129
  node dist/index.js --help
130
130
  ```
131
131
 
132
+ 构建、发布与 **AI Agent 技能**(`npx skills add … --skill c456-cli`)见 [DEVELOPMENT.md](./DEVELOPMENT.md)。
133
+
132
134
  ## 许可证
133
135
 
134
136
  MIT
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 Command6 } from "commander";
4
+ import { Command as Command7 } from "commander";
5
5
 
6
6
  // package.json
7
7
  var package_default = {
8
8
  name: "c456-cli",
9
- version: "0.1.0",
9
+ version: "0.1.1",
10
10
  description: "C456 CLI - \u5185\u5BB9\u5F55\u5165\u4E0E\u6574\u7406\u5DE5\u5177",
11
11
  type: "module",
12
12
  bin: {
@@ -147,6 +147,36 @@ var ApiClient = class {
147
147
  });
148
148
  return this.handleResponse(res);
149
149
  }
150
+ /**
151
+ * POST multipart/form-data(用于上传文件)
152
+ * @param {string} path
153
+ * @param {Record<string, any>} fields
154
+ * @param {{ fieldName: string, filePath: string, filename?: string, contentType?: string } | null} file
155
+ */
156
+ async postMultipart(path, fields = {}, file = null) {
157
+ const url = `${this.baseUrl}/api/v1${path}`;
158
+ const form = new FormData();
159
+ Object.entries(fields || {}).forEach(([k, v]) => {
160
+ if (v === void 0 || v === null) return;
161
+ form.append(k, String(v));
162
+ });
163
+ if (file && file.filePath) {
164
+ const fs = await import("node:fs");
165
+ const pathMod = await import("node:path");
166
+ const bytes = fs.readFileSync(file.filePath);
167
+ const blob = new Blob([bytes], { type: file.contentType || "application/octet-stream" });
168
+ const name = file.filename || pathMod.basename(file.filePath);
169
+ form.append(file.fieldName, blob, name);
170
+ }
171
+ const headers = { ...this.headers() };
172
+ delete headers["Content-Type"];
173
+ const res = await fetch(url, {
174
+ method: "POST",
175
+ headers,
176
+ body: form
177
+ });
178
+ return this.handleResponse(res);
179
+ }
150
180
  /**
151
181
  * PATCH 请求
152
182
  */
@@ -159,6 +189,36 @@ var ApiClient = class {
159
189
  });
160
190
  return this.handleResponse(res);
161
191
  }
192
+ /**
193
+ * PATCH multipart/form-data(用于上传文件)
194
+ * @param {string} path
195
+ * @param {Record<string, any>} fields
196
+ * @param {{ fieldName: string, filePath: string, filename?: string, contentType?: string } | null} file
197
+ */
198
+ async patchMultipart(path, fields = {}, file = null) {
199
+ const url = `${this.baseUrl}/api/v1${path}`;
200
+ const form = new FormData();
201
+ Object.entries(fields || {}).forEach(([k, v]) => {
202
+ if (v === void 0 || v === null) return;
203
+ form.append(k, String(v));
204
+ });
205
+ if (file && file.filePath) {
206
+ const fs = await import("node:fs");
207
+ const pathMod = await import("node:path");
208
+ const bytes = fs.readFileSync(file.filePath);
209
+ const blob = new Blob([bytes], { type: file.contentType || "application/octet-stream" });
210
+ const name = file.filename || pathMod.basename(file.filePath);
211
+ form.append(file.fieldName, blob, name);
212
+ }
213
+ const headers = { ...this.headers() };
214
+ delete headers["Content-Type"];
215
+ const res = await fetch(url, {
216
+ method: "PATCH",
217
+ headers,
218
+ body: form
219
+ });
220
+ return this.handleResponse(res);
221
+ }
162
222
  /**
163
223
  * DELETE 请求
164
224
  */
@@ -212,7 +272,7 @@ function resolveApi(cmd) {
212
272
 
213
273
  // src/commands/intake.js
214
274
  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");
215
- intake.command("new").description("\u521B\u5EFA\u65B0\u6536\u5F55").option("-u, --url <url>", "\u76EE\u6807 URL\uFF08tool/channel \u65F6\u53EF\u9009\uFF0C\u7528\u4E8E\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").option("--profile-data-json <json>", "\u8D44\u6599\u6BB5 JSON\uFF08tool/channel\uFF09").action(async (opts, cmd) => {
275
+ intake.command("new").description("\u521B\u5EFA\u65B0\u6536\u5F55").option("-u, --url <url>", "\u76EE\u6807 URL\uFF08tool/channel \u65F6\u53EF\u9009\uFF0C\u7528\u4E8E\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\uFF08type: markdown_kramdown\uFF1B\u8BED\u6CD5\u89C1 references/content-syntax-kramdown.md\uFF09").option("--profile-data-json <json>", "\u8D44\u6599\u6BB5 JSON\uFF08tool/channel\uFF09").action(async (opts, cmd) => {
216
276
  const { apiKey, baseUrl, client } = resolveApi(cmd);
217
277
  if (!apiKey) {
218
278
  console.error("\u9519\u8BEF\uFF1A\u672A\u914D\u7F6E API Key");
@@ -271,7 +331,7 @@ intake.command("show").description("\u67E5\u770B\u6536\u5F55\u8BE6\u60C5").argum
271
331
  process.exit(1);
272
332
  }
273
333
  });
274
- 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").option("--favorited", "\u6807\u8BB0\u4E3A\u6536\u85CF").option("--unfavorited", "\u53D6\u6D88\u6536\u85CF").action(async (id, opts, cmd) => {
334
+ 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\uFF08type: markdown_kramdown\uFF1B\u8BED\u6CD5\u89C1 references/content-syntax-kramdown.md\uFF09").option("--favorited", "\u6807\u8BB0\u4E3A\u6536\u85CF").option("--unfavorited", "\u53D6\u6D88\u6536\u85CF").action(async (id, opts, cmd) => {
275
335
  const { apiKey, client } = resolveApi(cmd);
276
336
  if (!apiKey) {
277
337
  console.error("\u9519\u8BEF\uFF1A\u672A\u914D\u7F6E API Key");
@@ -318,7 +378,7 @@ intake.command("delete").description("\u5220\u9664\u6536\u5F55").argument("<id>"
318
378
  process.exit(1);
319
379
  }
320
380
  });
321
- intake.command("list").description("\u5217\u51FA\u6536\u5F55\uFF08\u5206\u9875\uFF09").option("-k, --kind <type>", "\u7C7B\u578B\u8FC7\u6EE4\uFF1Asignal/tool/channel").option("-q, --query <text>", "\u641C\u7D22\u5173\u952E\u8BCD").option("-p, --page <num>", "\u9875\u7801", "1").option("-n, --per-page <num>", "\u6BCF\u9875\u6570\u91CF", "20").action(async (opts, cmd) => {
381
+ intake.command("list").description("\u5217\u51FA\u6536\u5F55\uFF08\u5206\u9875\uFF09").option("-k, --kind <type>", "\u7C7B\u578B\u8FC7\u6EE4\uFF1Asignal/tool/channel").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) => {
322
382
  const { apiKey, client } = resolveApi(cmd);
323
383
  if (!apiKey) {
324
384
  console.error("\u9519\u8BEF\uFF1A\u672A\u914D\u7F6E API Key");
@@ -473,7 +533,7 @@ var search_default = searchCmd;
473
533
  // src/commands/playbook.js
474
534
  import { Command as Command4 } from "commander";
475
535
  var playbookCmd = new Command4().name("playbook").description("\u6253\u6CD5\u7BA1\u7406 - \u521B\u5EFA\u3001\u66F4\u65B0\u3001\u5220\u9664\u6253\u6CD5");
476
- 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\uFF08Markdown\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) => {
536
+ 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\uFF08type: markdown_kramdown\uFF1B\u8BED\u6CD5\u89C1 references/content-syntax-kramdown.md\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) => {
477
537
  const { apiKey, client } = resolveApi(cmd);
478
538
  if (!apiKey) {
479
539
  console.error("\u9519\u8BEF\uFF1A\u672A\u914D\u7F6E API Key");
@@ -539,7 +599,7 @@ ${data.body || "(\u65E0)"}`);
539
599
  process.exit(1);
540
600
  }
541
601
  });
542
- playbookCmd.command("update").description("\u66F4\u65B0\u6253\u6CD5").argument("<id>", "\u6253\u6CD5 ID").option("-t, --title <title>", "\u65B0\u6807\u9898").option("-b, --body <text>", "\u65B0\u6B63\u6587").action(async (id, opts, cmd) => {
602
+ playbookCmd.command("update").description("\u66F4\u65B0\u6253\u6CD5").argument("<id>", "\u6253\u6CD5 ID").option("-t, --title <title>", "\u65B0\u6807\u9898").option("-b, --body <text>", "\u65B0\u6B63\u6587\uFF08type: markdown_kramdown\uFF1B\u8BED\u6CD5\u89C1 references/content-syntax-kramdown.md\uFF09").action(async (id, opts, cmd) => {
543
603
  const { apiKey, client } = resolveApi(cmd);
544
604
  if (!apiKey) {
545
605
  console.error("\u9519\u8BEF\uFF1A\u672A\u914D\u7F6E API Key");
@@ -584,7 +644,7 @@ playbookCmd.command("delete").description("\u5220\u9664\u6253\u6CD5").argument("
584
644
  process.exit(1);
585
645
  }
586
646
  });
587
- playbookCmd.command("list").description("\u5217\u51FA\u6253\u6CD5\uFF08\u5206\u9875\uFF09").option("-q, --query <text>", "\u641C\u7D22\u5173\u952E\u8BCD").option("-p, --page <num>", "\u9875\u7801", "1").option("-n, --per-page <num>", "\u6BCF\u9875\u6570\u91CF", "20").action(async (opts, cmd) => {
647
+ playbookCmd.command("list").description("\u5217\u51FA\u6253\u6CD5\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) => {
588
648
  const { apiKey, client } = resolveApi(cmd);
589
649
  if (!apiKey) {
590
650
  console.error("\u9519\u8BEF\uFF1A\u672A\u914D\u7F6E API Key");
@@ -614,9 +674,170 @@ playbookCmd.command("list").description("\u5217\u51FA\u6253\u6CD5\uFF08\u5206\u9
614
674
  });
615
675
  var playbook_default = playbookCmd;
616
676
 
617
- // src/commands/config.js
677
+ // src/commands/walkthrough.js
618
678
  import { Command as Command5 } from "commander";
619
- var configCmd = new Command5().name("config").description("\u914D\u7F6E\u7BA1\u7406 - \u8BBE\u7F6E API Key \u548C\u7CFB\u7EDF\u5730\u5740");
679
+ var walkthroughCmd = new Command5().name("walkthrough").description("\u8BB2\u89E3\uFF08Walkthrough\uFF09\u7BA1\u7406 - \u521B\u5EFA\u3001\u66F4\u65B0\u3001\u5220\u9664\u8BB2\u89E3");
680
+ function requireApiKey(apiKey) {
681
+ if (!apiKey) {
682
+ console.error("\u9519\u8BEF\uFF1A\u672A\u914D\u7F6E API Key");
683
+ process.exit(1);
684
+ }
685
+ }
686
+ function ensureSourceKind(kind) {
687
+ const k = String(kind || "").trim() || "upload";
688
+ if (!["upload", "external_url"].includes(k)) {
689
+ console.error("\u9519\u8BEF\uFF1A--source-kind \u4EC5\u652F\u6301 upload \u6216 external_url");
690
+ process.exit(1);
691
+ }
692
+ return k;
693
+ }
694
+ function buildWalkthroughFields(opts) {
695
+ const w = {};
696
+ if (opts.title !== void 0) w.title = opts.title;
697
+ if (opts.summary !== void 0) w.summary = opts.summary;
698
+ if (opts.body !== void 0) w.body = opts.body;
699
+ if (opts.sourceKind !== void 0) w.source_kind = opts.sourceKind;
700
+ if (opts.externalUrl !== void 0) w.external_url = opts.externalUrl;
701
+ if (opts.posterAt !== void 0) w.poster_preview_at_seconds = opts.posterAt;
702
+ if (opts.publicationStatus !== void 0) w.publication_status = opts.publicationStatus;
703
+ return w;
704
+ }
705
+ walkthroughCmd.command("new").description("\u521B\u5EFA\u65B0\u8BB2\u89E3").requiredOption("-t, --title <title>", "\u6807\u9898").option("-s, --summary <text>", "\u6458\u8981").option("-b, --body <text>", "\u6B63\u6587\uFF08type: markdown_kramdown\uFF1B\u8BED\u6CD5\u89C1 references/content-syntax-kramdown.md\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) => {
706
+ const { apiKey, client } = resolveApi(cmd);
707
+ requireApiKey(apiKey);
708
+ const sourceKind = ensureSourceKind(opts.sourceKind);
709
+ const posterAt = opts.posterAt !== void 0 ? Number.parseInt(String(opts.posterAt), 10) : void 0;
710
+ const w = {
711
+ title: opts.title,
712
+ summary: opts.summary || "",
713
+ body: opts.body || "",
714
+ source_kind: sourceKind,
715
+ external_url: opts.externalUrl || "",
716
+ poster_preview_at_seconds: Number.isFinite(posterAt) ? posterAt : void 0
717
+ };
718
+ if (sourceKind === "external_url") {
719
+ if (!w.external_url) {
720
+ console.error("\u9519\u8BEF\uFF1Asource-kind=external_url \u65F6\u5FC5\u987B\u63D0\u4F9B --external-url");
721
+ process.exit(1);
722
+ }
723
+ const result2 = await client.post("/walkthroughs", { walkthrough: w });
724
+ console.log("\u2705 \u8BB2\u89E3\u521B\u5EFA\u6210\u529F");
725
+ console.log(` ID: ${result2.data.id}`);
726
+ console.log(` \u6807\u9898\uFF1A${result2.data.title}`);
727
+ return;
728
+ }
729
+ if (!opts.castFile) {
730
+ console.error("\u9519\u8BEF\uFF1Asource-kind=upload \u65F6\u5FC5\u987B\u63D0\u4F9B --cast-file");
731
+ process.exit(1);
732
+ }
733
+ const fields = {
734
+ "walkthrough[title]": w.title,
735
+ "walkthrough[summary]": w.summary,
736
+ "walkthrough[body]": w.body,
737
+ "walkthrough[source_kind]": "upload"
738
+ };
739
+ if (w.poster_preview_at_seconds !== void 0) {
740
+ fields["walkthrough[poster_preview_at_seconds]"] = w.poster_preview_at_seconds;
741
+ }
742
+ const result = await client.postMultipart(
743
+ "/walkthroughs",
744
+ fields,
745
+ { fieldName: "walkthrough[cast_file]", filePath: opts.castFile, filename: "upload.cast" }
746
+ );
747
+ console.log("\u2705 \u8BB2\u89E3\u521B\u5EFA\u6210\u529F");
748
+ console.log(` ID: ${result.data.id}`);
749
+ console.log(` \u6807\u9898\uFF1A${result.data.title}`);
750
+ });
751
+ 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) => {
752
+ const { apiKey, client } = resolveApi(cmd);
753
+ requireApiKey(apiKey);
754
+ const result = await client.get("/walkthroughs", {
755
+ q: opts.query,
756
+ page: opts.page,
757
+ per_page: opts.perPage
758
+ });
759
+ const { data, meta } = result;
760
+ const perPage = metaPerPage(meta);
761
+ const totalPages = Math.max(1, Math.ceil(meta.total / perPage));
762
+ console.log(`\u5171 ${meta.total} \u6761\u8BB2\u89E3\uFF08\u7B2C ${meta.page}/${totalPages} \u9875\uFF09
763
+ `);
764
+ data.forEach((w) => {
765
+ console.log(`\u{1F3AC} [${w.id}] ${w.title}`);
766
+ if (w.durationLabel) console.log(` \u65F6\u957F\uFF1A${w.durationLabel}`);
767
+ if (w.summary) console.log(` ${w.summary}`);
768
+ });
769
+ });
770
+ walkthroughCmd.command("show").description("\u67E5\u770B\u8BB2\u89E3\u8BE6\u60C5").argument("<id>", "\u8BB2\u89E3 ID").action(async (id, opts, cmd) => {
771
+ const { apiKey, client } = resolveApi(cmd);
772
+ requireApiKey(apiKey);
773
+ const result = await client.get(`/walkthroughs/${id}`);
774
+ const w = result.data;
775
+ console.log(`ID: ${w.id}`);
776
+ console.log(`\u6807\u9898\uFF1A${w.title}`);
777
+ console.log(`\u72B6\u6001\uFF1A${w.publicationStatus}`);
778
+ if (w.summary) console.log(`\u6458\u8981\uFF1A${w.summary}`);
779
+ console.log(`\u6B63\u6587\uFF1A
780
+ ${w.body || "(\u65E0)"}`);
781
+ console.log(`\u6765\u6E90\uFF1A${w.sourceKind}`);
782
+ if (w.src) console.log(`\u5A92\u4F53\uFF1A${w.src}`);
783
+ });
784
+ 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").option("-b, --body <text>", "\u65B0\u6B63\u6587\uFF08type: markdown_kramdown\uFF1B\u8BED\u6CD5\u89C1 references/content-syntax-kramdown.md\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) => {
785
+ const { apiKey, client } = resolveApi(cmd);
786
+ requireApiKey(apiKey);
787
+ const posterAt = opts.posterAt !== void 0 ? Number.parseInt(String(opts.posterAt), 10) : void 0;
788
+ const w = buildWalkthroughFields({
789
+ title: opts.title,
790
+ summary: opts.summary,
791
+ body: opts.body,
792
+ sourceKind: opts.sourceKind ? ensureSourceKind(opts.sourceKind) : void 0,
793
+ externalUrl: opts.externalUrl,
794
+ posterAt: Number.isFinite(posterAt) ? posterAt : void 0,
795
+ publicationStatus: opts.publicationStatus
796
+ });
797
+ const hasFile = Boolean(opts.castFile);
798
+ if (!hasFile) {
799
+ const result2 = await client.patch(`/walkthroughs/${id}`, { walkthrough: w });
800
+ console.log("\u2705 \u8BB2\u89E3\u66F4\u65B0\u6210\u529F");
801
+ console.log(` \u6807\u9898\uFF1A${result2.data.title}`);
802
+ return;
803
+ }
804
+ const fields = {};
805
+ Object.entries(w).forEach(([k, v]) => {
806
+ fields[`walkthrough[${k}]`] = v;
807
+ });
808
+ const result = await client.patchMultipart(
809
+ `/walkthroughs/${id}`,
810
+ fields,
811
+ { fieldName: "walkthrough[cast_file]", filePath: opts.castFile, filename: "upload.cast" }
812
+ );
813
+ console.log("\u2705 \u8BB2\u89E3\u66F4\u65B0\u6210\u529F");
814
+ console.log(` \u6807\u9898\uFF1A${result.data.title}`);
815
+ });
816
+ 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) => {
817
+ const { apiKey, client } = resolveApi(cmd);
818
+ requireApiKey(apiKey);
819
+ if (!opts.force) {
820
+ const readline = await import("node:readline");
821
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
822
+ const answer = await new Promise((resolve) => {
823
+ rl.question("\u786E\u8BA4\u5220\u9664\uFF1F(y/N): ", (ans) => {
824
+ rl.close();
825
+ resolve(ans.toLowerCase());
826
+ });
827
+ });
828
+ if (answer !== "y" && answer !== "yes") {
829
+ console.log("\u5DF2\u53D6\u6D88");
830
+ return;
831
+ }
832
+ }
833
+ await client.delete(`/walkthroughs/${id}`);
834
+ console.log("\u2705 \u8BB2\u89E3\u5DF2\u5220\u9664");
835
+ });
836
+ var walkthrough_default = walkthroughCmd;
837
+
838
+ // src/commands/config.js
839
+ import { Command as Command6 } from "commander";
840
+ var configCmd = new Command6().name("config").description("\u914D\u7F6E\u7BA1\u7406 - \u8BBE\u7F6E API Key \u548C\u7CFB\u7EDF\u5730\u5740");
620
841
  configCmd.command("set-key").description("\u8BBE\u7F6E API Key").argument("<token>", "API Key \u4EE4\u724C").action((token, cmd) => {
621
842
  const config = loadConfig();
622
843
  config.apiKey = token;
@@ -712,7 +933,7 @@ ${body}
712
933
  }
713
934
 
714
935
  // src/index.js
715
- var program = new Command6();
936
+ var program = new Command7();
716
937
  program.name("c456").description("C456 CLI - \u5FEB\u901F\u5185\u5BB9\u5F55\u5165\u4E0E\u6574\u7406\u5DE5\u5177").version(package_default.version);
717
938
  program.addHelpText("before", () => getHelpBanner());
718
939
  program.option(
@@ -723,6 +944,7 @@ program.addCommand(intake_default);
723
944
  program.addCommand(fetch_default);
724
945
  program.addCommand(search_default);
725
946
  program.addCommand(playbook_default);
947
+ program.addCommand(walkthrough_default);
726
948
  program.addCommand(config_default);
727
949
  program.on("--help", () => {
728
950
  console.log("\n\u793A\u4F8B:");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "c456-cli",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "C456 CLI - 内容录入与整理工具",
5
5
  "type": "module",
6
6
  "bin": {