@hcmai/cli 0.3.11 → 0.3.13

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
@@ -177,12 +177,12 @@ function wrapIndex(index, length) {
177
177
  if (length <= 0) return 0;
178
178
  return (index % length + length) % length;
179
179
  }
180
- function resolveSlashKey(key, selected) {
181
- if (key.upArrow) return { type: "move", delta: -1 };
182
- if (key.downArrow) return { type: "move", delta: 1 };
180
+ function resolveSlashKey(key2, selected) {
181
+ if (key2.upArrow) return { type: "move", delta: -1 };
182
+ if (key2.downArrow) return { type: "move", delta: 1 };
183
183
  if (!selected) return { type: "none" };
184
- if (key.tab) return { type: "complete", text: selected.cmd + (selected.takesArgs ? " " : "") };
185
- if (key.return) {
184
+ if (key2.tab) return { type: "complete", text: selected.cmd + (selected.takesArgs ? " " : "") };
185
+ if (key2.return) {
186
186
  return selected.takesArgs ? { type: "complete", text: selected.cmd + " " } : { type: "execute", text: selected.cmd };
187
187
  }
188
188
  return { type: "none" };
@@ -1181,41 +1181,41 @@ function MultilineInput(props) {
1181
1181
  setCursor(nextCursor);
1182
1182
  onChange(next);
1183
1183
  };
1184
- useInput((input, key) => {
1185
- if (captureKey?.(input, key)) return;
1186
- if (key.escape) {
1184
+ useInput((input, key2) => {
1185
+ if (captureKey?.(input, key2)) return;
1186
+ if (key2.escape) {
1187
1187
  if (value) edit("", 0);
1188
1188
  onEscapeClear?.();
1189
1189
  return;
1190
1190
  }
1191
- const modifiedEnter = classifyModifiedEnter(input, key);
1191
+ const modifiedEnter = classifyModifiedEnter(input, key2);
1192
1192
  if (modifiedEnter === "newline" || input === "\n") {
1193
1193
  edit(value.slice(0, cursor) + "\n" + value.slice(cursor), cursor + 1);
1194
1194
  return;
1195
1195
  }
1196
- if (key.return) {
1196
+ if (key2.return) {
1197
1197
  const sendDraft = draftFromSendCommandLine(value, cursor);
1198
1198
  const toSend = sendDraft !== null ? sendDraft : value;
1199
1199
  if (toSend.trim()) onSubmit(toSend);
1200
1200
  return;
1201
1201
  }
1202
1202
  if (/^(?:\x1b)?\[\d+(?:;\d+)*[~u]$/.test(input)) return;
1203
- if (key.backspace || key.delete) {
1203
+ if (key2.backspace || key2.delete) {
1204
1204
  if (cursor > 0) edit(value.slice(0, cursor - 1) + value.slice(cursor), cursor - 1);
1205
1205
  return;
1206
1206
  }
1207
- if (key.leftArrow) {
1207
+ if (key2.leftArrow) {
1208
1208
  setCursor((c) => Math.max(0, c - 1));
1209
1209
  return;
1210
1210
  }
1211
- if (key.rightArrow) {
1211
+ if (key2.rightArrow) {
1212
1212
  setCursor((c) => Math.min(value.length, c + 1));
1213
1213
  return;
1214
1214
  }
1215
- if (key.upArrow || key.downArrow) {
1215
+ if (key2.upArrow || key2.downArrow) {
1216
1216
  const lines2 = value.split("\n");
1217
1217
  const { row: row2, col: col2 } = locate(lines2, cursor);
1218
- if (key.upArrow) {
1218
+ if (key2.upArrow) {
1219
1219
  if (row2 === 0) {
1220
1220
  onHistoryUp?.();
1221
1221
  return;
@@ -1230,7 +1230,7 @@ function MultilineInput(props) {
1230
1230
  }
1231
1231
  return;
1232
1232
  }
1233
- if (key.ctrl || key.meta || key.tab) return;
1233
+ if (key2.ctrl || key2.meta || key2.tab) return;
1234
1234
  if (input) {
1235
1235
  const text = input.replace(/\r\n?/g, "\n");
1236
1236
  edit(value.slice(0, cursor) + text + value.slice(cursor), cursor + text.length);
@@ -1255,8 +1255,8 @@ function MultilineInput(props) {
1255
1255
  ] }) : /* @__PURE__ */ jsx2(Text2, { children: line.length ? line : " " })
1256
1256
  ] }, r)) });
1257
1257
  }
1258
- function classifyModifiedEnter(input, key) {
1259
- if (key.return && (key.ctrl || key.meta || key.shift)) return "newline";
1258
+ function classifyModifiedEnter(input, key2) {
1259
+ if (key2.return && (key2.ctrl || key2.meta || key2.shift)) return "newline";
1260
1260
  const match = /^(?:\x1b)?\[27;(\d+);13~$/.exec(input);
1261
1261
  if (!match) return null;
1262
1262
  return "newline";
@@ -1368,8 +1368,8 @@ function ReplApp(props) {
1368
1368
  (patch) => setStreaming((prev) => ({ ...prev, ...patch })),
1369
1369
  []
1370
1370
  );
1371
- useInput2((_input, key) => {
1372
- if (key.escape && cancelRef.current && !interaction) {
1371
+ useInput2((_input, key2) => {
1372
+ if (key2.escape && cancelRef.current && !interaction) {
1373
1373
  cancelRef.current("user-esc");
1374
1374
  return;
1375
1375
  }
@@ -1568,9 +1568,9 @@ function ReplApp(props) {
1568
1568
  const slashOpen = slashItems.length > 0;
1569
1569
  const slashSelected = slashOpen ? wrapIndex(slashIndex, slashItems.length) : 0;
1570
1570
  const slashColWidth = slashOpen ? Math.max(...slashItems.map((s) => s.cmd.length)) + 2 : 0;
1571
- const handleSlashKey = (_input, key) => {
1571
+ const handleSlashKey = (_input, key2) => {
1572
1572
  if (!slashOpen) return false;
1573
- const action = resolveSlashKey(key, slashItems[slashSelected]);
1573
+ const action = resolveSlashKey(key2, slashItems[slashSelected]);
1574
1574
  switch (action.type) {
1575
1575
  case "move":
1576
1576
  setSlashIndex(wrapIndex(slashSelected + action.delta, slashItems.length));
@@ -1723,9 +1723,9 @@ function InteractionView({ interaction }) {
1723
1723
  }));
1724
1724
  const askFreeText = req.kind === "ASK" && (choices.length === 0 || freeMode);
1725
1725
  const textInputActive = rejectMode || askFreeText;
1726
- useInput2((input, key) => {
1726
+ useInput2((input, key2) => {
1727
1727
  if (textInputActive) return;
1728
- if (key.escape) {
1728
+ if (key2.escape) {
1729
1729
  respond({ kind: "reject" });
1730
1730
  return;
1731
1731
  }
@@ -2286,9 +2286,9 @@ async function loginCommand(args) {
2286
2286
  } catch (e) {
2287
2287
  const err = e;
2288
2288
  if (err.isAxiosError) {
2289
- const { fromAxiosError: fromAxiosError20 } = await import("@hcmai/sdk");
2289
+ const { fromAxiosError: fromAxiosError21 } = await import("@hcmai/sdk");
2290
2290
  exitWithError(
2291
- fromAxiosError20(
2291
+ fromAxiosError21(
2292
2292
  e,
2293
2293
  envName
2294
2294
  )
@@ -2595,15 +2595,15 @@ async function configDeleteDeprecated(name) {
2595
2595
  warnDeprecated("hcm config delete", "hcm env remove --force");
2596
2596
  await envRemove(name, { force: true });
2597
2597
  }
2598
- async function configSet(key, value) {
2598
+ async function configSet(key2, value) {
2599
2599
  try {
2600
- if (!key.startsWith("defaults.")) {
2600
+ if (!key2.startsWith("defaults.")) {
2601
2601
  throw new CliError4({
2602
2602
  code: CliErrorCode3.INVALID_ARGUMENT,
2603
2603
  message: "hcm config set only accepts defaults.*. For env fields use 'hcm env edit <field> <value>'."
2604
2604
  });
2605
2605
  }
2606
- const sub = key.slice("defaults.".length);
2606
+ const sub = key2.slice("defaults.".length);
2607
2607
  const g = await loadGlobalConfig3();
2608
2608
  g.defaults = g.defaults ?? {};
2609
2609
  g.defaults[sub] = value;
@@ -2613,15 +2613,15 @@ async function configSet(key, value) {
2613
2613
  exitWithError(e);
2614
2614
  }
2615
2615
  }
2616
- async function configGet(key) {
2616
+ async function configGet(key2) {
2617
2617
  try {
2618
- if (!key.startsWith("defaults.")) {
2618
+ if (!key2.startsWith("defaults.")) {
2619
2619
  throw new CliError4({
2620
2620
  code: CliErrorCode3.INVALID_ARGUMENT,
2621
2621
  message: "hcm config get only accepts defaults.*. For env fields use 'hcm env show'."
2622
2622
  });
2623
2623
  }
2624
- const sub = key.slice("defaults.".length);
2624
+ const sub = key2.slice("defaults.".length);
2625
2625
  const g = await loadGlobalConfig3();
2626
2626
  exitOk(String(g.defaults?.[sub] ?? ""));
2627
2627
  } catch (e) {
@@ -2951,10 +2951,10 @@ async function settingSetCommand(domain, args) {
2951
2951
  fail(e, args);
2952
2952
  }
2953
2953
  }
2954
- async function settingResetCommand(domain, namespace, key, args) {
2954
+ async function settingResetCommand(domain, namespace, key2, args) {
2955
2955
  try {
2956
2956
  if (!args.yes) {
2957
- const ok = await promptConfirm(`\u5C06\u6E05\u9664 ${domain} / ${namespace}.${key} \u7684\u79DF\u6237\u8986\u76D6\uFF0C\u56DE\u843D\u5230\u9ED8\u8BA4\u503C\u3002\u7EE7\u7EED\uFF1F`);
2957
+ const ok = await promptConfirm(`\u5C06\u6E05\u9664 ${domain} / ${namespace}.${key2} \u7684\u79DF\u6237\u8986\u76D6\uFF0C\u56DE\u843D\u5230\u9ED8\u8BA4\u503C\u3002\u7EE7\u7EED\uFF1F`);
2958
2958
  if (!ok) {
2959
2959
  process.stderr.write("\u5DF2\u53D6\u6D88\n");
2960
2960
  process.exit(1);
@@ -2962,9 +2962,9 @@ async function settingResetCommand(domain, namespace, key, args) {
2962
2962
  }
2963
2963
  const c = await client(args);
2964
2964
  const revision = args.revision === void 0 ? void 0 : Number(args.revision);
2965
- const result = await resetSettingItem(c.raw(), domain, namespace, key, revision);
2965
+ const result = await resetSettingItem(c.raw(), domain, namespace, key2, revision);
2966
2966
  const fmt = args.output ?? "json";
2967
- if (fmt !== "json") process.stdout.write(`\u2705 ${namespace}.${key} \u5DF2\u56DE\u843D\u5230\u9ED8\u8BA4\u503C
2967
+ if (fmt !== "json") process.stdout.write(`\u2705 ${namespace}.${key2} \u5DF2\u56DE\u843D\u5230\u9ED8\u8BA4\u503C
2968
2968
  `);
2969
2969
  process.stdout.write(formatObject4(result, { format: fmt }) + "\n");
2970
2970
  process.exit(0);
@@ -3314,8 +3314,8 @@ function stableJson(value) {
3314
3314
  }
3315
3315
  }
3316
3316
  function eventPreview(value) {
3317
- for (const key of ["text", "content", "summary", "question", "detail", "message"]) {
3318
- if (typeof value[key] === "string" && value[key].trim()) return oneLine(value[key], 86);
3317
+ for (const key2 of ["text", "content", "summary", "question", "detail", "message"]) {
3318
+ if (typeof value[key2] === "string" && value[key2].trim()) return oneLine(value[key2], 86);
3319
3319
  }
3320
3320
  const tools = value.tools;
3321
3321
  if (Array.isArray(tools) && tools.length) {
@@ -4786,9 +4786,9 @@ async function skillsListCommand(keyword, args) {
4786
4786
  `);
4787
4787
  if (args.byStage) {
4788
4788
  const all = cats.flatMap((c) => c.skills);
4789
- const stageList = manifest2?.stages ?? [...new Set(all.flatMap((skill) => skill.stages ?? []))].sort().map((key) => ({
4790
- key,
4791
- name: key,
4789
+ const stageList = manifest2?.stages ?? [...new Set(all.flatMap((skill) => skill.stages ?? []))].sort().map((key2) => ({
4790
+ key: key2,
4791
+ name: key2,
4792
4792
  description: "",
4793
4793
  skillCount: 0
4794
4794
  }));
@@ -5780,7 +5780,7 @@ async function tenantBootstrapCommand(args) {
5780
5780
  }
5781
5781
  const endpoint = await resolveEndpoint2(args);
5782
5782
  const { pwd, stdinTaken } = await resolveAdminPassword(args);
5783
- const key = await resolveBootstrapKey(args, stdinTaken);
5783
+ const key2 = await resolveBootstrapKey(args, stdinTaken);
5784
5784
  if (!args.yes) {
5785
5785
  const ok = await promptConfirm(
5786
5786
  `\u5C06\u5728 ${endpoint} \u521B\u5EFA\u79DF\u6237 "${args.tenantId}"\uFF08admin: ${args.adminUsername}\uFF09\u3002\u6B64\u64CD\u4F5C\u4E0D\u53EF\u9006\uFF0C\u7EE7\u7EED\uFF1F`
@@ -5796,7 +5796,7 @@ async function tenantBootstrapCommand(args) {
5796
5796
  onRefresh: async () => {
5797
5797
  }
5798
5798
  });
5799
- const result = await bootstrapTenant(http, key, {
5799
+ const result = await bootstrapTenant(http, key2, {
5800
5800
  tenantId: args.tenantId,
5801
5801
  adminUsername: args.adminUsername,
5802
5802
  adminPassword: pwd,
@@ -6919,9 +6919,9 @@ function filterPreviewTargets(targets, surface) {
6919
6919
  throw new Error("--surface must be all, bare, standalone or embedded");
6920
6920
  }
6921
6921
  function normalizeWorkspaceKey(value) {
6922
- const key = value.trim();
6923
- if (!key) throw new Error("workspaceKey is required");
6924
- return key;
6922
+ const key2 = value.trim();
6923
+ if (!key2) throw new Error("workspaceKey is required");
6924
+ return key2;
6925
6925
  }
6926
6926
  function normalizeRelativePath(value) {
6927
6927
  const normalized = toPosix(value).replace(/^\/+/, "").replace(/\/+/g, "/");
@@ -7527,7 +7527,7 @@ function summarizeTarget(argv, actionResolution) {
7527
7527
  }
7528
7528
  if (name === "setting" && argv[2] && !argv[2].startsWith("-")) {
7529
7529
  target.domain = argv[2];
7530
- const settingKeys = valuesAfterFlag(argv, "--set").map((assignment) => assignment.split("=", 1)[0]).filter((key) => Boolean(key)).sort();
7530
+ const settingKeys = valuesAfterFlag(argv, "--set").map((assignment) => assignment.split("=", 1)[0]).filter((key2) => Boolean(key2)).sort();
7531
7531
  if (settingKeys.length > 0) target.settingKeys = settingKeys;
7532
7532
  }
7533
7533
  const id = flagValue(argv, "--id");
@@ -8227,10 +8227,21 @@ async function bindEvidenceDirectory(project, reference) {
8227
8227
  }
8228
8228
  const absolute = path8.join(project, relative2);
8229
8229
  await assertNoSymlinkComponents(project, relative2);
8230
- const stat = await fs6.stat(absolute).catch((cause) => {
8231
- throw invalid2(`evidence \u76EE\u5F55\u4E0D\u53EF\u7528\uFF1A${relative2}`, cause);
8232
- });
8233
- if (!stat.isDirectory()) throw invalid2(`evidence \u8DEF\u5F84\u4E0D\u662F\u76EE\u5F55\uFF1A${relative2}`);
8230
+ const stat = await fs6.stat(absolute).catch(() => null);
8231
+ if (stat === null) {
8232
+ await fs6.mkdir(absolute, { recursive: true, mode: 448 }).catch((cause) => {
8233
+ throw invalid2(
8234
+ `evidence \u76EE\u5F55\u5EFA\u4E0D\u51FA\u6765\uFF1A${relative2}\u3002next_step=\u68C0\u67E5\u4E0A\u7EA7\u76EE\u5F55\u6743\u9650\uFF0C\u6216\u6362\u4E00\u4E2A evidence/ \u4E0B\u7684\u8DEF\u5F84`,
8235
+ cause
8236
+ );
8237
+ });
8238
+ return { relative: relative2, absolute };
8239
+ }
8240
+ if (!stat.isDirectory()) {
8241
+ throw invalid2(
8242
+ `evidence \u8DEF\u5F84\u5DF2\u5B58\u5728\u4F46\u4E0D\u662F\u76EE\u5F55\uFF1A${relative2}\u3002next_step=\u6362\u4E00\u4E2A evidence/ \u4E0B\u7684\u76EE\u5F55\u540D`
8243
+ );
8244
+ }
8234
8245
  return { relative: relative2, absolute };
8235
8246
  }
8236
8247
  async function readPlan(project, file) {
@@ -8515,7 +8526,7 @@ function parseTtl(value) {
8515
8526
  function canonicalJson(value) {
8516
8527
  if (Array.isArray(value)) return `[${value.map(canonicalJson).join(",")}]`;
8517
8528
  if (isRecord(value)) {
8518
- return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${canonicalJson(value[key])}`).join(",")}}`;
8529
+ return `{${Object.keys(value).sort().map((key2) => `${JSON.stringify(key2)}:${canonicalJson(value[key2])}`).join(",")}}`;
8519
8530
  }
8520
8531
  return JSON.stringify(value) ?? "null";
8521
8532
  }
@@ -8595,6 +8606,54 @@ async function promptPasswordTwice() {
8595
8606
  return password;
8596
8607
  }
8597
8608
 
8609
+ // src/commands/models.ts
8610
+ init_exit();
8611
+ init_auth_guard();
8612
+ import {
8613
+ HcmClient as HcmClient22,
8614
+ formatObject as formatObject24,
8615
+ fromAxiosError as fromAxiosError20
8616
+ } from "@hcmai/sdk";
8617
+ async function modelsCommand(keyword, args) {
8618
+ try {
8619
+ const client3 = HcmClient22.fromAuthContext(await getActiveAuthContextFromCli(args));
8620
+ const all = await client3.listModels();
8621
+ const needle = keyword?.trim().toLowerCase();
8622
+ const rows = (needle ? all.filter((m) => JSON.stringify(m).toLowerCase().includes(needle)) : all).sort((a, b) => key(a).localeCompare(key(b)));
8623
+ const fmt = args.output ?? "table";
8624
+ if (fmt !== "table") {
8625
+ process.stdout.write(formatObject24({ total: rows.length, models: rows }, { format: fmt }) + "\n");
8626
+ process.exit(0);
8627
+ }
8628
+ if (rows.length === 0) {
8629
+ process.stdout.write(
8630
+ needle ? `\u6CA1\u6709\u5339\u914D "${keyword}" \u7684 Model\uFF08\u5171 ${all.length} \u4E2A\u53EF\u89C1\uFF09\u3002
8631
+ ` : "\u5F53\u524D\u8EAB\u4EFD\u5728\u8FD9\u4E2A\u73AF\u5883\u770B\u4E0D\u5230\u4EFB\u4F55 Model\u3002\n"
8632
+ );
8633
+ process.exit(0);
8634
+ }
8635
+ const width = Math.max(...rows.map((m) => key(m).length), 8);
8636
+ process.stdout.write(`${"MODEL".padEnd(width)} TYPE
8637
+ `);
8638
+ for (const m of rows) {
8639
+ process.stdout.write(`${key(m).padEnd(width)} ${typeof m.type === "string" ? m.type : "-"}
8640
+ `);
8641
+ }
8642
+ process.stdout.write(`
8643
+ \u5171 ${rows.length} \u4E2A${needle ? `\uFF08\u5168\u90E8 ${all.length} \u4E2A\u4E2D\u5339\u914D\uFF09` : ""}\u3002
8644
+ `);
8645
+ process.stdout.write("\u4E0B\u4E00\u6B65\uFF1Ahcm describe <Model> \u770B\u5B57\u6BB5\u3001\u5173\u7CFB\u4E0E Action\u3002\n");
8646
+ process.exit(0);
8647
+ } catch (e) {
8648
+ const err = e;
8649
+ if (err?.isAxiosError) exitWithError(fromAxiosError20(err, args.profile));
8650
+ exitWithError(e);
8651
+ }
8652
+ }
8653
+ function key(m) {
8654
+ return typeof m.modelKey === "string" && m.modelKey ? m.modelKey : "(\u672A\u547D\u540D)";
8655
+ }
8656
+
8598
8657
  // src/startup.ts
8599
8658
  function needsLegacyProfileMigration(argv) {
8600
8659
  const args = argv.slice(2);
@@ -8669,6 +8728,7 @@ program.command("action <Model.Action>").description("\u8C03\u7528 Model \u4E0A\
8669
8728
  program.command("create <Model>").description("\u521B\u5EFA\u4E00\u6761 Model \u8BB0\u5F55\uFF08\u8D70\u540E\u7AEF\u5B8C\u6574\u6821\u9A8C\uFF09").option("--data <JSON>", `\u8BB0\u5F55\u5B57\u6BB5 JSON\uFF0C\u4F8B\u5982 '{"code":"ORG_SALES","name":"\u9500\u552E\u90E8"}'`).option("--data-file <path>", "\u4ECE UTF-8 JSON \u6587\u4EF6\u8BFB\u53D6\u8BB0\u5F55\u5B57\u6BB5\uFF08\u4E0E --data \u4E92\u65A5\uFF09").option("--env <name>", "\u4E34\u65F6\u5207\u73AF\u5883\uFF08\u8986\u76D6 activeEnv\uFF0C\u672C\u6B21\u547D\u4EE4\uFF09").option("--as <identity>", "\u4E34\u65F6\u6362\u8EAB\u4EFD\uFF08\u8986\u76D6 env defaultIdentity\uFF0C\u672C\u6B21\u547D\u4EE4\uFF09").option("--profile <name>", "[deprecated] \u7528 --env \u66FF\u4EE3").option("--output <fmt>", "\u8F93\u51FA\u683C\u5F0F\uFF1Atable | json | yaml", "json").action((m, opts) => createCommand(m, opts));
8670
8729
  program.command("delete <Model>").description("\u5220\u9664\u4E00\u6761 Model \u8BB0\u5F55\uFF08\u8D70\u540E\u7AEF\u5B8C\u6574\u6821\u9A8C\uFF1B\u90E8\u5206 Model \u4F1A\u6267\u884C\u4E1A\u52A1\u64A4\u9500\uFF09").option("--id <id>", "\u76EE\u6807\u5B9E\u4F53 ID\uFF08\u5FC5\u586B\uFF09").option("--env <name>", "\u4E34\u65F6\u5207\u73AF\u5883\uFF08\u8986\u76D6 activeEnv\uFF0C\u672C\u6B21\u547D\u4EE4\uFF09").option("--as <identity>", "\u4E34\u65F6\u6362\u8EAB\u4EFD\uFF08\u8986\u76D6 env defaultIdentity\uFF0C\u672C\u6B21\u547D\u4EE4\uFF09").option("--profile <name>", "[deprecated] \u7528 --env \u66FF\u4EE3").option("--output <fmt>", "\u8F93\u51FA\u683C\u5F0F\uFF1Atable | json | yaml", "json").action((m, opts) => deleteCommand(m, opts));
8671
8730
  program.command("import <path>").description("\u6CE8\u5165 DataPackage YAML \u6570\u636E\u96C6\uFF08\u76EE\u5F55\u6216\u5355\u6587\u4EF6\uFF0C\u8D70\u540E\u7AEF\u5B8C\u6574\u6821\u9A8C\uFF09").option("--dry-run", "\u53EA\u8DD1\u5BA2\u6237\u7AEF\u9759\u6001\u6821\u9A8C\uFF0C\u4E0D\u843D\u5E93\uFF08\u89C1 spec \xA78 \u9650\u5236\uFF09").option("--update-only", "\u5DF2\u5B58\u5728\uFF08\u6309 key_field\uFF09\u5219 PUT \u66F4\u65B0\uFF0C\u5426\u5219 create").option("--on-error <mode>", "stop | continue\uFF08\u9ED8\u8BA4 continue\uFF09", "continue").option("--report <path>", "\u5199 JSON \u6CE8\u5165\u62A5\u544A\uFF08\u9010\u884C\u7ED3\u679C + key\u2192id \u6620\u5C04\uFF09").option("--env <name>", "\u4E34\u65F6\u5207\u73AF\u5883\uFF08\u8986\u76D6 activeEnv\uFF0C\u672C\u6B21\u547D\u4EE4\uFF09").option("--as <identity>", "\u4E34\u65F6\u6362\u8EAB\u4EFD\uFF08\u8986\u76D6 env defaultIdentity\uFF0C\u672C\u6B21\u547D\u4EE4\uFF09").option("--profile <name>", "[deprecated] \u7528 --env \u66FF\u4EE3").option("--output <fmt>", "\u8F93\u51FA\u683C\u5F0F\uFF1Atable | json | yaml", "json").action((p, opts) => importCommand(p, opts));
8731
+ program.command("models [keyword]").description("\u5217\u51FA\u76EE\u6807\u73AF\u5883\u6709\u54EA\u4E9B Model\uFF08describe \u7684\u4E0A\u4E00\u6B65\uFF09\uFF1B\u53EF\u5E26\u5173\u952E\u5B57\u8FC7\u6EE4").option("--env <name>", "\u4E34\u65F6\u5207\u73AF\u5883\uFF08\u8986\u76D6 activeEnv\uFF0C\u672C\u6B21\u547D\u4EE4\uFF09").option("--as <identity>", "\u4E34\u65F6\u6362\u8EAB\u4EFD\uFF08\u8986\u76D6 env defaultIdentity\uFF0C\u672C\u6B21\u547D\u4EE4\uFF09").option("--output <fmt>", "\u8F93\u51FA\u683C\u5F0F\uFF1Atable | json | yaml", "table").action((keyword, opts) => modelsCommand(keyword, opts));
8672
8732
  program.command("describe <Model>").description("\u67E5\u770B Model \u5143\u6570\u636E\uFF08\u5B57\u6BB5\u3001\u5173\u7CFB\u3001Action \u5217\u8868\uFF09").option("-v, --verbose", "\u663E\u793A\u5B57\u6BB5\u63CF\u8FF0\u4E0E enum \u53D6\u503C").option("--env <name>", "\u4E34\u65F6\u5207\u73AF\u5883\uFF08\u8986\u76D6 activeEnv\uFF0C\u672C\u6B21\u547D\u4EE4\uFF09").option("--as <identity>", "\u4E34\u65F6\u6362\u8EAB\u4EFD\uFF08\u8986\u76D6 env defaultIdentity\uFF0C\u672C\u6B21\u547D\u4EE4\uFF09").option("--profile <name>", "[deprecated] \u7528 --env \u66FF\u4EE3").option("--output <fmt>", "\u8F93\u51FA\u683C\u5F0F\uFF1Atable | json | yaml", "table").action((m, opts) => describeCommand(m, opts));
8673
8733
  program.command("chat [prompt]").description("\u4E0E\u6570\u5B57\u5458\u5DE5 Moirai \u5BF9\u8BDD\uFF1B\u6709 prompt \u5355\u53D1\u540E\u9000\u51FA\uFF0C\u4E0D\u5E26 prompt \u8FDB\u5165 REPL").option("--agent <key>", "\u6307\u5B9A agent UUID\uFF08\u9ED8\u8BA4\u4F7F\u7528 analyst \u5185\u7F6E agent\uFF09").option("--resume <id>", "\u7EED\u63A5\u6307\u5B9A conversation\uFF1B\u4E0D\u4F20\u5219\u9ED8\u8BA4\u5F00\u65B0\u4F1A\u8BDD").option("--conversation <id>", "[deprecated] \u7528 --resume \u66FF\u4EE3\uFF1B\u4F20 NEW \u7B49\u4EF7\u9ED8\u8BA4\u65B0\u4F1A\u8BDD").option("--list", "\u5217\u51FA\u6700\u8FD1\u4F1A\u8BDD\uFF0C\u4E0D\u8FDB\u5165\u804A\u5929").option("--events [conversationId]", "\u53EA\u8BFB\u67E5\u770B\u6307\u5B9A conversation \u7684 timeline/event \u6D41\uFF1B\u4E5F\u53EF\u914D --resume <id>").option("--limit <N>", "\u914D\u5408 --list\uFF1A\u663E\u793A\u6700\u8FD1 N \u6761\u4F1A\u8BDD", "10").option("--stream", "\u6D41\u5F0F\u8F93\u51FA\uFF08\u9ED8\u8BA4\u5F00\u542F\uFF0C\u9010 token \u6253\u5370 + thinking/tools \u5B9E\u65F6\u663E\u793A\uFF09", true).option("--no-stream", "\u5173\u95ED\u6D41\u5F0F\uFF0C\u7B49 LLM \u5168\u6587\u8FD4\u56DE\u540E\u4E00\u6B21\u6027\u663E\u793A\uFF08CI / \u811A\u672C\u7BA1\u9053\u573A\u666F\uFF09").option("--show-tool-calls", "\u5C55\u793A\u5DE5\u5177\u8C03\u7528\u8BE6\u7EC6\u53C2\u6570\uFF08\u9ED8\u8BA4\u663E\u793A\u5DE5\u5177\u540D + \u72B6\u6001\uFF0Cverbose \u65F6\u663E\u793A\u5B8C\u6574\u53C2\u6570\uFF09", true).option("--no-show-tool-calls", "\u5B8C\u5168\u9690\u85CF\u5DE5\u5177\u8C03\u7528").option("--prompt-file <path>", "\u4ECE\u6587\u4EF6\u8BFB\u53D6 prompt \u5185\u5BB9").option("--timeout <sec>", "\u8BF7\u6C42\u8D85\u65F6\u79D2\u6570", "60").option("--env <name>", "\u4E34\u65F6\u5207\u73AF\u5883\uFF08\u8986\u76D6 activeEnv\uFF0C\u672C\u6B21\u547D\u4EE4\uFF09").option("--as <identity>", "\u4E34\u65F6\u6362\u8EAB\u4EFD\uFF08\u8986\u76D6 env defaultIdentity\uFF0C\u672C\u6B21\u547D\u4EE4\uFF09").option("--profile <name>", "[deprecated] \u7528 --env \u66FF\u4EE3").option("--output <fmt>", "\u8F93\u51FA\u683C\u5F0F\uFF1Atext | json", "text").option("--no-markdown", "\u5173\u95ED\u6D41\u5F0F\u672B\u6001 markdown \u6E32\u67D3\uFF08CI / pipe \u53CB\u597D\uFF09").option("--no-thinking", "\u5173\u95ED thinking \u6BB5\u663E\u793A").option("--verbose-thinking", "\u5C55\u5F00 thinking \u5B8C\u6574\u5185\u5BB9\uFF08\u9ED8\u8BA4\u4EC5\u5355\u884C\u603B\u7ED3\uFF09").option("--verbose-tools", "\u5C55\u793A\u5DE5\u5177\u8C03\u7528\u5B8C\u6574\u53C2\u6570\uFF08\u9ED8\u8BA4\u4EC5\u5DE5\u5177\u540D + \u72B6\u6001\uFF09").option("--no-spinner", "\u5173\u95ED spinner\uFF08CI \u53CB\u597D\uFF09").option("--no-color", "\u5173\u95ED\u989C\u8272\uFF08CI / accessibility\uFF09").option("--raw", "\u9010\u884C\u6253\u5370\u539F\u59CB v4/control envelope\uFF08\u534F\u8BAE\u793A\u6CE2\u5668\uFF0C\u4E0D\u6E32\u67D3\uFF09").option("--auto-approve", "\u81EA\u52A8\u6279\u51C6\u9AD8\u98CE\u9669 confirm\uFF08\u4ECD\u6253\u5370\u5BA1\u8BA1\u884C\uFF1B\u6279\u91CF / \u975E\u4EA4\u4E92\u573A\u666F\uFF09").option("--on-confirm <decision>", "\u975E\u4EA4\u4E92 confirm \u51B3\u7B56\uFF1Aapprove | reject | reject:<reason>\uFF08\u4F18\u5148\u4E8E --auto-approve\uFF09").option("--on-ask <answer>", "\u975E\u4EA4\u4E92 ASK \u5E94\u7B54\u6587\u672C\uFF08\u547D\u4E2D choices \u65F6\u81EA\u52A8\u56DE\u586B choiceIndex\uFF09").option(
8674
8734
  "--inject-on <spec>",