@hcmai/cli 0.3.9 → 0.3.11

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
@@ -523,8 +523,8 @@ var init_TerminalRenderer = __esm({
523
523
  }
524
524
  }
525
525
  /** 来源行(仅子代理触发,agentPath ≥2 段时显示 `↑ 来自 a › b`,对齐 Web)。 */
526
- originLine(path10) {
527
- const segs = path10.split(".").filter(Boolean);
526
+ originLine(path9) {
527
+ const segs = path9.split(".").filter(Boolean);
528
528
  if (segs.length < 2) return "";
529
529
  const names = segs.map((k) => agentDisplayName(k));
530
530
  return chalk.gray(` \u2191 \u6765\u81EA ${names.join(" \u203A ")}`) + "\n";
@@ -1458,10 +1458,10 @@ function ReplApp(props) {
1458
1458
  });
1459
1459
  const t0 = Date.now();
1460
1460
  try {
1461
- const result2 = await presenter.consume(handle.events);
1461
+ const result = await presenter.consume(handle.events);
1462
1462
  const stats = presenter.completionStats;
1463
- if (result2.status === "completed") {
1464
- bridge.showCompleted(Date.now() - t0, result2.traceId, convRef.current ?? "", presenter.tokenCount || void 0, stats);
1463
+ if (result.status === "completed") {
1464
+ bridge.showCompleted(Date.now() - t0, result.traceId, convRef.current ?? "", presenter.tokenCount || void 0, stats);
1465
1465
  }
1466
1466
  if (presenter.tokenCount) setSessionTokens((prev) => prev + presenter.tokenCount);
1467
1467
  if (convRef.current) {
@@ -1706,8 +1706,8 @@ function agentLabel(agentId) {
1706
1706
  if (/^[0-9a-f]{8}-[0-9a-f-]{27}$/i.test(agentId)) return `agent \u2026${agentId.slice(-4)}`;
1707
1707
  return agentDisplayName(agentId);
1708
1708
  }
1709
- function originLine(path10) {
1710
- const segs = (path10 ?? "").split(".").filter(Boolean);
1709
+ function originLine(path9) {
1710
+ const segs = (path9 ?? "").split(".").filter(Boolean);
1711
1711
  if (segs.length < 2) return null;
1712
1712
  return `\u6765\u81EA ${segs.map((k) => agentDisplayName(k)).join(" \u203A ")}`;
1713
1713
  }
@@ -2650,12 +2650,12 @@ async function queryCommand(model, args) {
2650
2650
  if (args.offset) dsl.offset = Number(args.offset);
2651
2651
  if (!dsl.limit) dsl.limit = 20;
2652
2652
  const client3 = HcmClient.fromAuthContext(await getActiveAuthContextFromCli(args));
2653
- const result2 = await client3.query(model, dsl);
2653
+ const result = await client3.query(model, dsl);
2654
2654
  const fmt = args.output ?? "table";
2655
- const out = formatRows(result2.rows, { format: fmt });
2655
+ const out = formatRows(result.rows, { format: fmt });
2656
2656
  process.stdout.write(out + "\n");
2657
- if (fmt === "table" && result2.total !== void 0) {
2658
- process.stdout.write(`Showing ${result2.rows.length} of ${result2.total} results.
2657
+ if (fmt === "table" && result.total !== void 0) {
2658
+ process.stdout.write(`Showing ${result.rows.length} of ${result.total} results.
2659
2659
  `);
2660
2660
  }
2661
2661
  process.exit(0);
@@ -2772,17 +2772,17 @@ async function actionCommand(spec, args) {
2772
2772
  });
2773
2773
  if (params) input.params = params;
2774
2774
  const client3 = HcmClient2.fromAuthContext(await getActiveAuthContextFromCli(args));
2775
- const result2 = await client3.action(model, action, input);
2775
+ const result = await client3.action(model, action, input);
2776
2776
  const fmt = args.output ?? "json";
2777
- if (fmt !== "json" && result2.taskId) {
2777
+ if (fmt !== "json" && result.taskId) {
2778
2778
  process.stdout.write(
2779
- `\u23F3 task created: ${result2.taskId} (use \`hcm task ${result2.taskId}\` to follow up \u2014 coming Phase 1)
2779
+ `\u23F3 task created: ${result.taskId} (use \`hcm task ${result.taskId}\` to follow up \u2014 coming Phase 1)
2780
2780
  `
2781
2781
  );
2782
2782
  } else if (fmt !== "json") {
2783
2783
  process.stdout.write("\u2705 action succeeded\n");
2784
2784
  }
2785
- process.stdout.write(formatObject(result2, { format: fmt }) + "\n");
2785
+ process.stdout.write(formatObject(result, { format: fmt }) + "\n");
2786
2786
  process.exit(0);
2787
2787
  } catch (e) {
2788
2788
  const err = e;
@@ -2856,11 +2856,11 @@ async function updateCommand(model, args) {
2856
2856
  fileFlag: "--data-file"
2857
2857
  });
2858
2858
  const client3 = HcmClient4.fromAuthContext(await getActiveAuthContextFromCli(args));
2859
- const result2 = await client3.update(model, args.id, data);
2859
+ const result = await client3.update(model, args.id, data);
2860
2860
  const fmt = args.output ?? "json";
2861
2861
  if (fmt !== "json") process.stdout.write(`\u2705 ${model}#${args.id} \u5DF2\u66F4\u65B0
2862
2862
  `);
2863
- process.stdout.write(formatObject3(result2, { format: fmt }) + "\n");
2863
+ process.stdout.write(formatObject3(result, { format: fmt }) + "\n");
2864
2864
  process.exit(0);
2865
2865
  } catch (e) {
2866
2866
  const err = e;
@@ -2941,11 +2941,11 @@ async function settingSetCommand(domain, args) {
2941
2941
  process.exit(0);
2942
2942
  }
2943
2943
  const c = await client(args);
2944
- const result2 = await patchSettingDomain(c.raw(), domain, items);
2944
+ const result = await patchSettingDomain(c.raw(), domain, items);
2945
2945
  const fmt = args.output ?? "json";
2946
2946
  if (fmt !== "json") process.stdout.write(`\u2705 ${domain} \u5DF2\u66F4\u65B0 ${items.length} \u9879
2947
2947
  `);
2948
- process.stdout.write(formatObject4(result2, { format: fmt }) + "\n");
2948
+ process.stdout.write(formatObject4(result, { format: fmt }) + "\n");
2949
2949
  process.exit(0);
2950
2950
  } catch (e) {
2951
2951
  fail(e, args);
@@ -2962,11 +2962,11 @@ 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 result2 = await resetSettingItem(c.raw(), domain, namespace, key, revision);
2965
+ const result = await resetSettingItem(c.raw(), domain, namespace, key, revision);
2966
2966
  const fmt = args.output ?? "json";
2967
2967
  if (fmt !== "json") process.stdout.write(`\u2705 ${namespace}.${key} \u5DF2\u56DE\u843D\u5230\u9ED8\u8BA4\u503C
2968
2968
  `);
2969
- process.stdout.write(formatObject4(result2, { format: fmt }) + "\n");
2969
+ process.stdout.write(formatObject4(result, { format: fmt }) + "\n");
2970
2970
  process.exit(0);
2971
2971
  } catch (e) {
2972
2972
  fail(e, args);
@@ -3059,8 +3059,8 @@ import {
3059
3059
  formatObject as formatObject7,
3060
3060
  fromAxiosError as fromAxiosError8
3061
3061
  } from "@hcmai/sdk";
3062
- function collectYmlFiles(path10) {
3063
- if (statSync(path10).isFile()) return [path10];
3062
+ function collectYmlFiles(path9) {
3063
+ if (statSync(path9).isFile()) return [path9];
3064
3064
  const out = [];
3065
3065
  const walk = (dir) => {
3066
3066
  for (const name of readdirSync(dir).sort()) {
@@ -3069,7 +3069,7 @@ function collectYmlFiles(path10) {
3069
3069
  else if (full.endsWith(".yml") || full.endsWith(".yaml")) out.push(full);
3070
3070
  }
3071
3071
  };
3072
- walk(path10);
3072
+ walk(path9);
3073
3073
  return out.sort();
3074
3074
  }
3075
3075
  var DRY_RUN_CLIENT = {
@@ -3077,9 +3077,9 @@ var DRY_RUN_CLIENT = {
3077
3077
  create: async () => ({ id: "" }),
3078
3078
  update: async () => ({})
3079
3079
  };
3080
- async function importCommand(path10, args) {
3080
+ async function importCommand(path9, args) {
3081
3081
  try {
3082
- const files = collectYmlFiles(path10);
3082
+ const files = collectYmlFiles(path9);
3083
3083
  const fixtures = files.map(
3084
3084
  (f) => parseFixture(readFileSync2(f, "utf8"), relative(process.cwd(), f))
3085
3085
  );
@@ -3089,16 +3089,16 @@ async function importCommand(path10, args) {
3089
3089
  onError: args.onError === "stop" ? "stop" : "continue"
3090
3090
  };
3091
3091
  const client3 = opts.dryRun ? DRY_RUN_CLIENT : HcmClient7.fromAuthContext(await getActiveAuthContextFromCli(args));
3092
- const result2 = await runImport(client3, fixtures, opts);
3093
- if (args.report) writeFileSync(args.report, JSON.stringify(result2, null, 2));
3092
+ const result = await runImport(client3, fixtures, opts);
3093
+ if (args.report) writeFileSync(args.report, JSON.stringify(result, null, 2));
3094
3094
  const fmt = args.output ?? "json";
3095
3095
  const tag = opts.dryRun ? "\u{1F50D} dry-run" : "\u{1F4E6} import";
3096
3096
  process.stdout.write(
3097
- `${tag}: created=${result2.created} updated=${result2.updated} skipped=${result2.skipped} failed=${result2.failed}
3097
+ `${tag}: created=${result.created} updated=${result.updated} skipped=${result.skipped} failed=${result.failed}
3098
3098
  `
3099
3099
  );
3100
- process.stdout.write(formatObject7(result2, { format: fmt }) + "\n");
3101
- process.exit(result2.failed > 0 ? 3 : 0);
3100
+ process.stdout.write(formatObject7(result, { format: fmt }) + "\n");
3101
+ process.exit(result.failed > 0 ? 3 : 0);
3102
3102
  } catch (e) {
3103
3103
  const err = e;
3104
3104
  if (err?.isAxiosError) exitWithError(fromAxiosError8(err, args.profile));
@@ -3389,13 +3389,13 @@ async function printConversationList(args) {
3389
3389
  const ctx = await getActiveAuthContextFromCli(args);
3390
3390
  const client3 = HcmClient10.fromAuthContext(ctx);
3391
3391
  const limit = parsePositiveInt(args.limit, 10, "--limit");
3392
- const result2 = await fetchRecentConversations(client3.raw(), limit);
3392
+ const result = await fetchRecentConversations(client3.raw(), limit);
3393
3393
  const fmt = args.output ?? "text";
3394
3394
  if (fmt === "json") {
3395
- process.stdout.write(formatObject9(result2, { format: "json" }) + "\n");
3395
+ process.stdout.write(formatObject9(result, { format: "json" }) + "\n");
3396
3396
  return;
3397
3397
  }
3398
- const rows = result2.rows.map((row) => ({
3398
+ const rows = result.rows.map((row) => ({
3399
3399
  UPDATED: formatShortDate(row.lastActiveAt ?? row.updateTime ?? row.createTime),
3400
3400
  MSGS: row.messageCount ?? 0,
3401
3401
  TOKENS: row.totalTokens ?? 0,
@@ -3403,8 +3403,8 @@ async function printConversationList(args) {
3403
3403
  CONVERSATION: row.id ?? "-"
3404
3404
  }));
3405
3405
  process.stdout.write(formatRows3(rows, { format: "table" }) + "\n");
3406
- if (result2.total !== void 0) {
3407
- process.stdout.write(`Showing ${result2.rows.length} of ${result2.total} conversations.
3406
+ if (result.total !== void 0) {
3407
+ process.stdout.write(`Showing ${result.rows.length} of ${result.total} conversations.
3408
3408
  `);
3409
3409
  }
3410
3410
  }
@@ -3676,9 +3676,9 @@ async function chatCommand(prompt, args) {
3676
3676
  process.once("SIGINT", sigintHandler);
3677
3677
  const t0 = Date.now();
3678
3678
  try {
3679
- const result2 = await presenter.consume(handle.events);
3679
+ const result = await presenter.consume(handle.events);
3680
3680
  const stats = presenter.completionStats;
3681
- renderer.showCompleted(Date.now() - t0, result2.traceId, handle.conversationId, presenter.tokenCount || void 0, {
3681
+ renderer.showCompleted(Date.now() - t0, result.traceId, handle.conversationId, presenter.tokenCount || void 0, {
3682
3682
  inputTokens: stats.inputTokens,
3683
3683
  outputTokens: stats.outputTokens,
3684
3684
  toolCount: stats.toolCount,
@@ -3687,8 +3687,8 @@ async function chatCommand(prompt, args) {
3687
3687
  await ws.close();
3688
3688
  await saveConversationState2(stateKey, {
3689
3689
  lastConversationId: handle.conversationId,
3690
- lastStreamId: result2.streamId,
3691
- lastTraceId: result2.traceId ?? void 0,
3690
+ lastStreamId: result.streamId,
3691
+ lastTraceId: result.traceId ?? void 0,
3692
3692
  lastAgentKey: args.agent,
3693
3693
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
3694
3694
  });
@@ -3700,7 +3700,7 @@ async function chatCommand(prompt, args) {
3700
3700
  resolve4();
3701
3701
  }
3702
3702
  });
3703
- process.exit(result2.status === "interrupted" ? 130 : 0);
3703
+ process.exit(result.status === "interrupted" ? 130 : 0);
3704
3704
  } catch (e) {
3705
3705
  process.removeListener("SIGINT", sigintHandler);
3706
3706
  await ws.close();
@@ -4192,10 +4192,10 @@ async function withClient(args, fn) {
4192
4192
  const client3 = HcmClient13.fromAuthContext(await getActiveAuthContextFromCli(args));
4193
4193
  return fn(client3);
4194
4194
  }
4195
- function emit(result2, args, human) {
4195
+ function emit(result, args, human) {
4196
4196
  const fmt = args.output ?? "json";
4197
4197
  if (fmt !== "json") process.stdout.write(human + "\n");
4198
- process.stdout.write(formatObject11(result2, { format: fmt }) + "\n");
4198
+ process.stdout.write(formatObject11(result, { format: fmt }) + "\n");
4199
4199
  process.exit(0);
4200
4200
  }
4201
4201
  function fail2(e, args) {
@@ -4214,20 +4214,20 @@ async function cacheStatsCommand(model, args) {
4214
4214
  }
4215
4215
  async function cacheClearCommand(model, args) {
4216
4216
  try {
4217
- const result2 = await withClient(args, (c) => clearModelCache(c.raw(), model, args.id));
4218
- emit(result2, args, args.id ? `\u{1F9F9} \u5DF2\u6E05 ${model}#${args.id} \u7F13\u5B58` : `\u{1F9F9} \u5DF2\u6E05 ${model} \u5168\u90E8\u5B9E\u4F53\u7F13\u5B58`);
4217
+ const result = await withClient(args, (c) => clearModelCache(c.raw(), model, args.id));
4218
+ emit(result, args, args.id ? `\u{1F9F9} \u5DF2\u6E05 ${model}#${args.id} \u7F13\u5B58` : `\u{1F9F9} \u5DF2\u6E05 ${model} \u5168\u90E8\u5B9E\u4F53\u7F13\u5B58`);
4219
4219
  } catch (e) {
4220
4220
  fail2(e, args);
4221
4221
  }
4222
4222
  }
4223
4223
  async function cacheClearMetaCommand(model, args) {
4224
4224
  try {
4225
- const result2 = await withClient(
4225
+ const result = await withClient(
4226
4226
  args,
4227
4227
  (c) => clearMetaCache(c.raw(), model, { type: args.type, state: args.state })
4228
4228
  );
4229
4229
  const scope = args.type ? `${args.type}${args.state ? `.${args.state}` : ""}` : "\u5168\u90E8";
4230
- emit(result2, args, `\u{1F9F9} \u5DF2\u6E05 ${model} \u5143\u6570\u636E\u7F13\u5B58\uFF08${scope}\uFF09`);
4230
+ emit(result, args, `\u{1F9F9} \u5DF2\u6E05 ${model} \u5143\u6570\u636E\u7F13\u5B58\uFF08${scope}\uFF09`);
4231
4231
  } catch (e) {
4232
4232
  fail2(e, args);
4233
4233
  }
@@ -4280,21 +4280,20 @@ async function uploadCommand(filePath, args) {
4280
4280
  init_exit();
4281
4281
  import { promises as fsp2 } from "fs";
4282
4282
  import os2 from "os";
4283
- import path6 from "path";
4284
- import { createHash as createHash4 } from "crypto";
4283
+ import path4 from "path";
4284
+ import { createHash as createHash2 } from "crypto";
4285
4285
  import {
4286
4286
  createHttpClient as createHttpClient2,
4287
4287
  fetchSkillCatalog,
4288
- fetchSkillFile,
4289
4288
  fetchSkillMarkdown,
4290
4289
  fetchSkillReference,
4291
4290
  resolveChironBase,
4292
- assertSafeSkillId as assertSafeSkillId2,
4291
+ assertSafeSkillId,
4293
4292
  assertSafeReferencePath as assertSafeReferencePath2,
4294
- normalizeReferences as normalizeReferences2,
4293
+ normalizeReferences,
4295
4294
  parseSkillRequirements as parseSkillRequirements2,
4296
4295
  parseSkillFrontmatter as parseSkillFrontmatter2,
4297
- resolveSkillInstallOrder as resolveSkillInstallOrder2,
4296
+ resolveSkillInstallOrder,
4298
4297
  resolveAllSkillsInstallOrder,
4299
4298
  matchSkills,
4300
4299
  filterByStage,
@@ -4303,8 +4302,8 @@ import {
4303
4302
  loadEnv as loadEnv5,
4304
4303
  loadGlobalConfig as loadGlobalConfig6,
4305
4304
  resolveActiveEnv as resolveActiveEnv3,
4306
- CliError as CliError18,
4307
- CliErrorCode as CliErrorCode17
4305
+ CliError as CliError16,
4306
+ CliErrorCode as CliErrorCode15
4308
4307
  } from "@hcmai/sdk";
4309
4308
 
4310
4309
  // src/commands/skills-catalog.ts
@@ -4593,810 +4592,20 @@ async function resolveBundledClosure(targetId, dir = bundledSkillsDir()) {
4593
4592
  return { documents, external: [...external].sort() };
4594
4593
  }
4595
4594
 
4596
- // src/commands/skills-sync.ts
4597
- import { createHash as createHash2 } from "crypto";
4598
- import { promises as fs5 } from "fs";
4599
- import path4 from "path";
4600
- import {
4601
- CliError as CliError16,
4602
- CliErrorCode as CliErrorCode15,
4603
- assertSafeSkillFilePath,
4604
- assertSafeSkillId,
4605
- normalizeReferences,
4606
- resolveSkillInstallOrder
4607
- } from "@hcmai/sdk";
4608
- async function prepareSkillDocuments(catalog, requestedSkill, fetchMarkdown, fetchFile, fetchReference) {
4609
- const order = resolveSkillInstallOrder(catalog, requestedSkill);
4610
- for (const skill of order) {
4611
- if (skill.actionSurface !== "cli") {
4612
- throw invalid(`\u6280\u80FD ${skill.id} \u5C1A\u672A\u6536\u655B\u5230 hcm CLI\uFF0C\u4E0D\u80FD\u540C\u6B65\u4E3A WorkBuddy \u6B63\u5F0F\u6267\u884C Skill`);
4613
- }
4614
- }
4615
- return Promise.all(
4616
- order.map(async (skill) => {
4617
- let files;
4618
- if (skill.files === void 0) {
4619
- const markdown2 = await fetchMarkdown(skill.id);
4620
- const content = Buffer.from(markdown2, "utf8");
4621
- const references = normalizeReferences(skill.references, skill.id);
4622
- if (references.length > 0 && !fetchReference) {
4623
- throw invalid(`\u6280\u80FD ${skill.id} \u58F0\u660E\u4E86 references\uFF0C\u4F46\u8C03\u7528\u65B9\u6CA1\u6709\u53C2\u8003\u6587\u4EF6\u4E0B\u8F7D\u80FD\u529B`);
4624
- }
4625
- const referenceFiles = await Promise.all(
4626
- references.map(async (relativePath) => {
4627
- const targetPath = `references/${relativePath}`;
4628
- assertSafeSkillFilePath(targetPath);
4629
- const fetched = await fetchReference(skill.id, relativePath);
4630
- const referenceContent = Buffer.isBuffer(fetched) ? Buffer.from(fetched) : Buffer.from(fetched, "utf8");
4631
- return {
4632
- path: targetPath,
4633
- content: referenceContent,
4634
- bytes: referenceContent.length,
4635
- sha256: sha2562(referenceContent)
4636
- };
4637
- })
4638
- );
4639
- files = [
4640
- {
4641
- path: "SKILL.md",
4642
- content,
4643
- bytes: content.length,
4644
- sha256: sha2562(content)
4645
- },
4646
- ...referenceFiles
4647
- ];
4648
- } else {
4649
- if (!Array.isArray(skill.files) || skill.files.length === 0) {
4650
- throw invalid(`\u6280\u80FD ${skill.id} \u7684 files \u76EE\u5F55\u4E3A\u7A7A`);
4651
- }
4652
- if (!fetchFile) throw invalid(`\u6280\u80FD ${skill.id} \u63D0\u4F9B\u5B8C\u6574\u76EE\u5F55\uFF0C\u4F46\u8C03\u7528\u65B9\u6CA1\u6709\u6587\u4EF6\u4E0B\u8F7D\u80FD\u529B`);
4653
- const seen = /* @__PURE__ */ new Set();
4654
- for (const file of skill.files) {
4655
- assertSafeSkillFilePath(file.path);
4656
- if (seen.has(file.path))
4657
- throw invalid(`\u6280\u80FD ${skill.id} \u7684 files \u5305\u542B\u91CD\u590D\u8DEF\u5F84: ${file.path}`);
4658
- seen.add(file.path);
4659
- if (!Number.isInteger(file.bytes) || file.bytes < 0 || !/^[a-f0-9]{64}$/.test(file.sha256)) {
4660
- throw invalid(`\u6280\u80FD ${skill.id} \u7684\u6587\u4EF6\u76EE\u5F55\u5143\u6570\u636E\u975E\u6CD5: ${file.path}`);
4661
- }
4662
- }
4663
- if (!seen.has("SKILL.md")) throw invalid(`\u6280\u80FD ${skill.id} \u7684\u5B8C\u6574\u76EE\u5F55\u7F3A\u5C11 SKILL.md`);
4664
- files = await Promise.all(
4665
- skill.files.map(async (file) => {
4666
- const content = Buffer.from(await fetchFile(skill.id, file.path));
4667
- if (content.length !== file.bytes) {
4668
- throw invalid(
4669
- `\u6280\u80FD ${skill.id}/${file.path} \u5B57\u8282\u6570\u4E0E\u76EE\u5F55\u4E0D\u4E00\u81F4\uFF1A\u76EE\u5F55=${file.bytes}\uFF0C\u5B9E\u9645=${content.length}`
4670
- );
4671
- }
4672
- const digest = sha2562(content);
4673
- if (digest !== file.sha256) {
4674
- throw invalid(`\u6280\u80FD ${skill.id}/${file.path} \u6458\u8981\u4E0E\u76EE\u5F55\u4E0D\u4E00\u81F4`);
4675
- }
4676
- return { path: file.path, content, bytes: content.length, sha256: digest };
4677
- })
4678
- );
4679
- }
4680
- const root = files.find((file) => file.path === "SKILL.md");
4681
- if (!root) throw invalid(`\u6280\u80FD ${skill.id} \u7684\u5B8C\u6574\u76EE\u5F55\u7F3A\u5C11 SKILL.md`);
4682
- const markdown = root.content.toString("utf8");
4683
- if (!markdown.trim()) throw invalid(`\u6280\u80FD ${skill.id} \u5185\u5BB9\u4E3A\u7A7A`);
4684
- validateWorkBuddyFrontmatter(markdown, skill.id);
4685
- const bytes = root.bytes;
4686
- if (Number.isFinite(skill.bytes) && skill.bytes > 0 && skill.bytes !== bytes) {
4687
- throw invalid(`\u6280\u80FD ${skill.id} \u5B57\u8282\u6570\u4E0E\u76EE\u5F55\u4E0D\u4E00\u81F4\uFF1A\u76EE\u5F55=${skill.bytes}\uFF0C\u5B9E\u9645=${bytes}`);
4688
- }
4689
- return { id: skill.id, markdown, bytes, sha256: root.sha256, files };
4690
- })
4691
- );
4692
- }
4693
- async function syncWorkBuddyProject(input) {
4694
- const project = path4.resolve(input.project);
4695
- const metaDir = path4.join(project, ".hcm-delivery");
4696
- const skillsDir = path4.join(project, ".codebuddy", "skills");
4697
- const lockPath = path4.join(metaDir, "chiron.lock.json");
4698
- assertSafeSkillId(input.requestedSkill);
4699
- validatePreparedDocuments(input.documents, input.requestedSkill);
4700
- validatePreparedRuntime(input.runtime);
4701
- await recoverInterruptedSyncs(project, metaDir, lockPath);
4702
- const oldLock = await readLock(lockPath);
4703
- const skillEntries = input.documents.flatMap(
4704
- (document) => document.files.map((file) => [ownedFile(document.id, file.path), file])
4705
- );
4706
- const runtimeEntries = input.runtime.files.map((file) => [file.path, file]);
4707
- const desiredEntries = [
4708
- ...skillEntries,
4709
- ...runtimeEntries
4710
- ];
4711
- const desiredFiles = desiredEntries.map(([file]) => file);
4712
- const desiredByFile = new Map(desiredEntries);
4713
- const oldOwned = new Set(oldLock?.ownedFiles ?? []);
4714
- const oldDigestByFile = lockDigests(oldLock);
4715
- for (const file of oldOwned) validateOwnedFile(file);
4716
- for (const file of desiredFiles) {
4717
- const absolute = path4.join(project, file);
4718
- const current = await readOptionalBytes(absolute);
4719
- if (current !== void 0 && !oldOwned.has(file)) {
4720
- throw invalid(`\u76EE\u6807\u6587\u4EF6\u4E0D\u5C5E\u4E8E\u4E0A\u4E00\u4EFD Chiron \u9501\uFF0C\u62D2\u7EDD\u8986\u76D6\u987E\u95EE\u6587\u4EF6\uFF1A${file}`);
4721
- }
4722
- }
4723
- for (const file of oldOwned) {
4724
- const absolute = path4.join(project, file);
4725
- const current = await readOptionalBytes(absolute);
4726
- if (current === void 0) continue;
4727
- const expected = oldDigestByFile.get(file);
4728
- if (!expected || sha2562(current) !== expected.sha256 || !await fileModeMatches(absolute, expected.mode)) {
4729
- throw invalid(`\u4E0A\u4E00\u4EFD\u9501\u62E5\u6709\u7684\u751F\u6210\u6587\u4EF6\u5DF2\u88AB\u4EBA\u5DE5\u4FEE\u6539\uFF0C\u62D2\u7EDD\u8986\u76D6\u6216\u6E05\u7406\uFF1A${file}`);
4730
- }
4731
- }
4732
- const newLock = {
4733
- schemaVersion: 1,
4734
- source: {
4735
- endpointOriginSha256: sha2562(normalizeEndpoint(input.endpoint)),
4736
- catalogPath: "/skills.json",
4737
- catalogSha256: sha2562(stableJson2(input.catalog))
4738
- },
4739
- selection: { requestedSkill: input.requestedSkill },
4740
- resolvedSkills: input.documents.map(({ id, bytes, sha256: digest, files: skillFiles }) => ({
4741
- id,
4742
- bytes,
4743
- sha256: digest,
4744
- files: skillFiles.map(({ path: filePath, bytes: fileBytes, sha256: fileSha256 }) => ({
4745
- path: filePath,
4746
- bytes: fileBytes,
4747
- sha256: fileSha256
4748
- }))
4749
- })),
4750
- runtime: {
4751
- capabilities: input.runtime.capabilities,
4752
- capabilitiesSha256: input.runtime.capabilitiesSha256,
4753
- launch: input.runtime.launch,
4754
- files: input.runtime.files.map(({ path: filePath, bytes, sha256: digest, mode }) => ({
4755
- path: filePath,
4756
- bytes,
4757
- sha256: digest,
4758
- mode
4759
- }))
4760
- },
4761
- ownedFiles: desiredFiles,
4762
- syncedAt: input.now ?? (/* @__PURE__ */ new Date()).toISOString()
4763
- };
4764
- if (oldLock && sameLockContent(oldLock, newLock) && await desiredFilesMatch(project, desiredByFile)) {
4765
- return result(false, input, project, skillsDir, lockPath, [], []);
4766
- }
4767
- const obsolete = [...oldOwned].filter((file) => !desiredByFile.has(file));
4768
- await fs5.mkdir(metaDir, { recursive: true });
4769
- const staging = await fs5.mkdtemp(path4.join(metaDir, ".staging-"));
4770
- const stagedFiles = path4.join(staging, "new");
4771
- const backups = path4.join(staging, "backup");
4772
- const stagedLock = path4.join(staging, "chiron.lock.json");
4773
- const journalPath = path4.join(staging, "journal.json");
4774
- let journalReady = false;
4775
- try {
4776
- for (const [file, preparedFile2] of desiredByFile) {
4777
- const staged = path4.join(stagedFiles, file);
4778
- await fs5.mkdir(path4.dirname(staged), { recursive: true });
4779
- await fs5.writeFile(
4780
- staged,
4781
- preparedFile2.content,
4782
- preparedFile2.mode === void 0 ? void 0 : { mode: preparedFile2.mode }
4783
- );
4784
- }
4785
- await fs5.writeFile(stagedLock, `${JSON.stringify(newLock, null, 2)}
4786
- `, "utf8");
4787
- const affected = [.../* @__PURE__ */ new Set([...desiredFiles, ...obsolete])];
4788
- for (const file of affected) {
4789
- const target = path4.join(project, file);
4790
- if (!await exists(target)) continue;
4791
- const backup = path4.join(backups, file);
4792
- await fs5.mkdir(path4.dirname(backup), { recursive: true });
4793
- await fs5.copyFile(target, backup);
4794
- }
4795
- const oldLockExisted = await exists(lockPath);
4796
- if (oldLockExisted) {
4797
- const backupLock = path4.join(backups, ".hcm-delivery", "chiron.lock.json");
4798
- await fs5.mkdir(path4.dirname(backupLock), { recursive: true });
4799
- await fs5.copyFile(lockPath, backupLock);
4800
- }
4801
- const journal = {
4802
- schemaVersion: 1,
4803
- project,
4804
- affectedFiles: affected,
4805
- oldLockExisted
4806
- };
4807
- await fs5.writeFile(journalPath, `${JSON.stringify(journal, null, 2)}
4808
- `, "utf8");
4809
- journalReady = true;
4810
- for (const file of desiredFiles) {
4811
- const target = path4.join(project, file);
4812
- await fs5.mkdir(path4.dirname(target), { recursive: true });
4813
- await fs5.rm(target, { force: true });
4814
- await fs5.rename(path4.join(stagedFiles, file), target);
4815
- }
4816
- for (const file of obsolete) await fs5.unlink(path4.join(project, file)).catch(ignoreMissing);
4817
- await fs5.rm(lockPath, { force: true });
4818
- await fs5.rename(stagedLock, lockPath);
4819
- await fs5.unlink(journalPath);
4820
- journalReady = false;
4821
- } catch (cause) {
4822
- if (journalReady) await recoverStaging(project, staging, lockPath);
4823
- throw cause;
4824
- } finally {
4825
- await fs5.rm(staging, { recursive: true, force: true });
4826
- }
4827
- return result(
4828
- true,
4829
- input,
4830
- project,
4831
- skillsDir,
4832
- lockPath,
4833
- input.documents.map((document) => document.id),
4834
- [...new Set(obsolete.map(idFromOwnedFile).filter((id) => id !== void 0))]
4835
- );
4836
- }
4837
- async function recoverInterruptedSyncs(project, metaDir, lockPath) {
4838
- let entries;
4839
- try {
4840
- entries = await fs5.readdir(metaDir, { withFileTypes: true });
4841
- } catch (cause) {
4842
- if (cause.code === "ENOENT") return;
4843
- throw cause;
4844
- }
4845
- for (const entry of entries) {
4846
- if (!entry.isDirectory() || !entry.name.startsWith(".staging-")) continue;
4847
- const staging = path4.join(metaDir, entry.name);
4848
- if (await exists(path4.join(staging, "journal.json"))) {
4849
- await recoverStaging(project, staging, lockPath);
4850
- }
4851
- await fs5.rm(staging, { recursive: true, force: true });
4852
- }
4853
- }
4854
- async function recoverStaging(project, staging, lockPath) {
4855
- const journalPath = path4.join(staging, "journal.json");
4856
- const journal = parseJournal(await fs5.readFile(journalPath, "utf8"), project);
4857
- const backups = path4.join(staging, "backup");
4858
- for (const file of journal.affectedFiles) {
4859
- const target = path4.join(project, file);
4860
- const backup = path4.join(backups, file);
4861
- if (await exists(backup)) {
4862
- await fs5.mkdir(path4.dirname(target), { recursive: true });
4863
- await fs5.rm(target, { force: true });
4864
- await fs5.rename(backup, target);
4865
- } else {
4866
- await fs5.rm(target, { force: true });
4867
- }
4868
- }
4869
- const backupLock = path4.join(backups, ".hcm-delivery", "chiron.lock.json");
4870
- if (journal.oldLockExisted) {
4871
- if (!await exists(backupLock)) throw invalid(`\u540C\u6B65\u6062\u590D\u7F3A\u5C11\u65E7\u9501\u5907\u4EFD\uFF1A${backupLock}`);
4872
- await fs5.mkdir(path4.dirname(lockPath), { recursive: true });
4873
- await fs5.rm(lockPath, { force: true });
4874
- await fs5.rename(backupLock, lockPath);
4875
- } else {
4876
- await fs5.rm(lockPath, { force: true });
4877
- }
4878
- }
4879
- function parseJournal(content, project) {
4880
- let journal;
4881
- try {
4882
- journal = JSON.parse(content);
4883
- } catch (cause) {
4884
- throw new CliError16({
4885
- code: CliErrorCode15.CONFIG_PARSE_ERROR,
4886
- message: "Chiron \u540C\u6B65\u6062\u590D\u65E5\u5FD7\u635F\u574F",
4887
- cause
4888
- });
4889
- }
4890
- if (journal.schemaVersion !== 1 || journal.project !== project || !Array.isArray(journal.affectedFiles) || typeof journal.oldLockExisted !== "boolean") {
4891
- throw invalid("Chiron \u540C\u6B65\u6062\u590D\u65E5\u5FD7\u5408\u540C\u4E0D\u5339\u914D\uFF0C\u62D2\u7EDD\u731C\u6D4B\u6062\u590D\u8303\u56F4");
4892
- }
4893
- for (const file of journal.affectedFiles) validateOwnedFile(file);
4894
- return journal;
4895
- }
4896
- function validatePreparedDocuments(documents, requestedSkill) {
4897
- const seen = /* @__PURE__ */ new Set();
4898
- for (const document of documents) {
4899
- assertSafeSkillId(document.id);
4900
- if (seen.has(document.id)) throw invalid(`\u540C\u6B65\u95ED\u5305\u5305\u542B\u91CD\u590D\u6280\u80FD: ${document.id}`);
4901
- seen.add(document.id);
4902
- if (!document.markdown.trim()) throw invalid(`\u6280\u80FD ${document.id} \u5185\u5BB9\u4E3A\u7A7A`);
4903
- const paths = /* @__PURE__ */ new Set();
4904
- for (const file of document.files) {
4905
- assertSafeSkillFilePath(file.path);
4906
- if (paths.has(file.path)) throw invalid(`\u6280\u80FD ${document.id} \u5305\u542B\u91CD\u590D\u6587\u4EF6: ${file.path}`);
4907
- paths.add(file.path);
4908
- if (file.content.length !== file.bytes || sha2562(file.content) !== file.sha256) {
4909
- throw invalid(`\u6280\u80FD ${document.id}/${file.path} \u7684\u5DF2\u51C6\u5907\u5185\u5BB9\u6458\u8981\u4E0D\u4E00\u81F4`);
4910
- }
4911
- }
4912
- const root = document.files.find((file) => file.path === "SKILL.md");
4913
- if (!root || !root.content.equals(Buffer.from(document.markdown, "utf8")) || root.bytes !== document.bytes || root.sha256 !== document.sha256) {
4914
- throw invalid(`\u6280\u80FD ${document.id} \u7684\u5DF2\u51C6\u5907\u5185\u5BB9\u6458\u8981\u4E0D\u4E00\u81F4`);
4915
- }
4916
- }
4917
- if (!seen.has(requestedSkill)) throw invalid(`\u540C\u6B65\u95ED\u5305\u4E0D\u5305\u542B\u76EE\u6807\u6280\u80FD: ${requestedSkill}`);
4918
- }
4919
- function validatePreparedRuntime(runtime) {
4920
- if (!Array.isArray(runtime.capabilities) || runtime.capabilities.length === 0) {
4921
- throw invalid("WorkBuddy CLI \u80FD\u529B\u96C6\u5408\u4E3A\u7A7A");
4922
- }
4923
- const capabilities = /* @__PURE__ */ new Set();
4924
- for (const capability of runtime.capabilities) {
4925
- if (!/^[a-z0-9]+(?:[.-][a-z0-9]+)*$/.test(capability) || capabilities.has(capability)) {
4926
- throw invalid(`WorkBuddy CLI \u80FD\u529B\u6807\u8BC6\u975E\u6CD5\u6216\u91CD\u590D\uFF1A${capability}`);
4927
- }
4928
- capabilities.add(capability);
4929
- }
4930
- if (!validDigest(runtime.capabilitiesSha256) || runtime.capabilitiesSha256 !== sha2562(`${runtime.capabilities.join("\n")}
4931
- `)) {
4932
- throw invalid("WorkBuddy CLI \u80FD\u529B\u6458\u8981\u4E0D\u4E00\u81F4");
4933
- }
4934
- if (!validDigest(runtime.launch.executableSha256)) {
4935
- throw invalid("WorkBuddy CLI \u53EF\u6267\u884C\u6587\u4EF6\u6458\u8981\u975E\u6CD5");
4936
- }
4937
- if (runtime.launch.kind === "node-entry" && !validDigest(runtime.launch.entrySha256)) {
4938
- throw invalid("WorkBuddy CLI \u5165\u53E3\u6458\u8981\u975E\u6CD5");
4939
- }
4940
- if (!Array.isArray(runtime.files) || runtime.files.length !== 2) {
4941
- throw invalid("WorkBuddy \u8FD0\u884C\u5165\u53E3\u5FC5\u987B\u540C\u65F6\u5305\u542B Unix \u4E0E Windows \u6587\u4EF6");
4942
- }
4943
- const files = /* @__PURE__ */ new Set();
4944
- for (const file of runtime.files) {
4945
- validateRuntimeFile(file);
4946
- if (files.has(file.path)) throw invalid(`WorkBuddy \u8FD0\u884C\u5165\u53E3\u91CD\u590D\uFF1A${file.path}`);
4947
- files.add(file.path);
4948
- }
4949
- if (!files.has(".hcm-delivery/bin/hcm") || !files.has(".hcm-delivery/bin/hcm.cmd")) {
4950
- throw invalid("WorkBuddy \u8FD0\u884C\u5165\u53E3\u5408\u540C\u4E0D\u5B8C\u6574");
4951
- }
4952
- }
4953
- function validateRuntimeFile(file) {
4954
- validateOwnedFile(file.path);
4955
- if (file.content.length !== file.bytes || sha2562(file.content) !== file.sha256 || !Number.isInteger(file.mode) || file.mode < 0 || file.mode > 511) {
4956
- throw invalid(`WorkBuddy \u8FD0\u884C\u5165\u53E3\u6458\u8981\u6216\u6743\u9650\u4E0D\u4E00\u81F4\uFF1A${file.path}`);
4957
- }
4958
- }
4959
- function validateWorkBuddyFrontmatter(markdown, skillId) {
4960
- const match = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/.exec(markdown);
4961
- if (!match) throw invalid(`\u6280\u80FD ${skillId} \u7F3A\u5C11 YAML frontmatter`);
4962
- const frontmatter = match[1] ?? "";
4963
- const name = /^name:\s*['"]?([^'"\s]+)['"]?\s*$/m.exec(frontmatter)?.[1];
4964
- const description = /^description:\s*(.+)$/m.exec(frontmatter)?.[1]?.trim();
4965
- if (name !== skillId) throw invalid(`\u6280\u80FD ${skillId} \u7684 frontmatter name \u4E0D\u4E00\u81F4`);
4966
- if (!description) throw invalid(`\u6280\u80FD ${skillId} \u7F3A\u5C11 description\uFF0CWorkBuddy \u65E0\u6CD5\u53D1\u73B0`);
4967
- }
4968
- async function readLock(lockPath) {
4969
- const content = await readOptional(lockPath);
4970
- if (content === void 0) return void 0;
4971
- try {
4972
- const lock = JSON.parse(content);
4973
- if (lock.schemaVersion !== 1 || !lock.source || !lock.selection?.requestedSkill || !Array.isArray(lock.resolvedSkills) || !Array.isArray(lock.ownedFiles)) {
4974
- throw new Error("schema mismatch");
4975
- }
4976
- assertSafeSkillId(lock.selection.requestedSkill);
4977
- for (const skill of lock.resolvedSkills) {
4978
- assertSafeSkillId(skill.id);
4979
- if (!Number.isInteger(skill.bytes) || skill.bytes < 0 || !/^[a-f0-9]{64}$/.test(skill.sha256)) {
4980
- throw new Error("invalid skill digest");
4981
- }
4982
- if (skill.files !== void 0) {
4983
- if (!Array.isArray(skill.files) || skill.files.length === 0)
4984
- throw new Error("invalid files");
4985
- const seen = /* @__PURE__ */ new Set();
4986
- for (const file of skill.files) {
4987
- assertSafeSkillFilePath(file.path);
4988
- if (seen.has(file.path) || !Number.isInteger(file.bytes) || file.bytes < 0 || !/^[a-f0-9]{64}$/.test(file.sha256)) {
4989
- throw new Error("invalid file digest");
4990
- }
4991
- seen.add(file.path);
4992
- }
4993
- if (!seen.has("SKILL.md")) throw new Error("missing SKILL.md");
4994
- }
4995
- }
4996
- if (lock.runtime !== void 0) validateLockedRuntime(lock.runtime);
4997
- for (const file of lock.ownedFiles) validateOwnedFile(file);
4998
- return lock;
4999
- } catch (cause) {
5000
- throw new CliError16({
5001
- code: CliErrorCode15.CONFIG_PARSE_ERROR,
5002
- message: `Chiron \u9501\u6587\u4EF6\u635F\u574F\uFF0C\u62D2\u7EDD\u731C\u6D4B\u6587\u4EF6\u6240\u6709\u6743\uFF1A${lockPath}`,
5003
- cause
5004
- });
5005
- }
5006
- }
5007
- function validateLockedRuntime(runtime) {
5008
- if (!Array.isArray(runtime.capabilities) || runtime.capabilities.length === 0 || !validDigest(runtime.capabilitiesSha256) || runtime.capabilitiesSha256 !== sha2562(`${runtime.capabilities.join("\n")}
5009
- `) || !runtime.launch || !validDigest(runtime.launch.executableSha256) || !Array.isArray(runtime.files) || runtime.files.length !== 2) {
5010
- throw new Error("invalid runtime");
5011
- }
5012
- if (runtime.launch.kind === "node-entry") {
5013
- if (!validDigest(runtime.launch.entrySha256)) throw new Error("invalid runtime entry");
5014
- } else if (runtime.launch.kind !== "executable") {
5015
- throw new Error("invalid runtime launch kind");
5016
- }
5017
- const capabilities = /* @__PURE__ */ new Set();
5018
- for (const capability of runtime.capabilities) {
5019
- if (!/^[a-z0-9]+(?:[.-][a-z0-9]+)*$/.test(capability) || capabilities.has(capability)) {
5020
- throw new Error("invalid runtime capability");
5021
- }
5022
- capabilities.add(capability);
5023
- }
5024
- const files = /* @__PURE__ */ new Set();
5025
- for (const file of runtime.files) {
5026
- validateOwnedFile(file.path);
5027
- if (files.has(file.path) || !Number.isInteger(file.bytes) || file.bytes < 0 || !validDigest(file.sha256) || !Number.isInteger(file.mode) || file.mode < 0 || file.mode > 511) {
5028
- throw new Error("invalid runtime file");
5029
- }
5030
- files.add(file.path);
5031
- }
5032
- if (!files.has(".hcm-delivery/bin/hcm") || !files.has(".hcm-delivery/bin/hcm.cmd")) {
5033
- throw new Error("missing runtime file");
5034
- }
5035
- }
5036
- function sameLockContent(left, right) {
5037
- const withoutTime = (lock) => ({ ...lock, syncedAt: void 0 });
5038
- return stableJson2(withoutTime(left)) === stableJson2(withoutTime(right));
5039
- }
5040
- async function desiredFilesMatch(project, desired) {
5041
- for (const [file, preparedFile2] of desired) {
5042
- const absolute = path4.join(project, file);
5043
- const current = await readOptionalBytes(absolute);
5044
- if (current === void 0 || sha2562(current) !== preparedFile2.sha256 || !await fileModeMatches(absolute, preparedFile2.mode)) {
5045
- return false;
5046
- }
5047
- }
5048
- return true;
4595
+ // src/commands/skills.ts
4596
+ var SKILLS_STATE_FILE = ".hcm-skills.json";
4597
+ async function sha256File(file) {
4598
+ return createHash2("sha256").update(await fsp2.readFile(file)).digest("hex");
5049
4599
  }
5050
- function result(changed, input, project, skillsDir, lockPath, installed, removed) {
4600
+ async function currentSkillsRuntimeLaunch() {
4601
+ const entry = process.argv[1];
4602
+ if (!entry) throw invalid("\u65E0\u6CD5\u89E3\u6790\u5F53\u524D CLI entry");
5051
4603
  return {
5052
- changed,
5053
- requestedSkill: input.requestedSkill,
5054
- resolvedSkills: input.documents.map((document) => document.id),
5055
- project,
5056
- skillsDir,
5057
- lockPath,
5058
- runnerPath: path4.join(project, ".hcm-delivery", "bin", "hcm"),
5059
- capabilitiesSha256: input.runtime.capabilitiesSha256,
5060
- installed,
5061
- removed
5062
- };
5063
- }
5064
- function ownedFile(id, relativePath = "SKILL.md") {
5065
- assertSafeSkillId(id);
5066
- assertSafeSkillFilePath(relativePath);
5067
- return `.codebuddy/skills/${id}/${relativePath}`;
5068
- }
5069
- function idFromOwnedFile(file) {
5070
- validateOwnedFile(file);
5071
- if (!file.startsWith(".codebuddy/skills/")) return void 0;
5072
- return file.split("/")[2] ?? "";
5073
- }
5074
- function validateOwnedFile(file) {
5075
- if (file === ".hcm-delivery/bin/hcm" || file === ".hcm-delivery/bin/hcm.cmd") return;
5076
- const match = /^\.codebuddy\/skills\/([a-z0-9][a-z0-9-]{0,63})\/(.+)$/.exec(file);
5077
- if (!match) throw invalid(`\u9501\u6587\u4EF6\u5305\u542B\u975E\u6CD5\u6240\u6709\u6743\u8DEF\u5F84\uFF1A${file}`);
5078
- const id = match[1];
5079
- const relativePath = match[2];
5080
- if (!id || !relativePath) throw invalid(`\u9501\u6587\u4EF6\u5305\u542B\u975E\u6CD5\u6240\u6709\u6743\u8DEF\u5F84\uFF1A${file}`);
5081
- assertSafeSkillId(id);
5082
- try {
5083
- assertSafeSkillFilePath(relativePath);
5084
- } catch {
5085
- throw invalid(`\u9501\u6587\u4EF6\u5305\u542B\u975E\u6CD5\u6240\u6709\u6743\u8DEF\u5F84\uFF1A${file}`);
5086
- }
5087
- }
5088
- function normalizeEndpoint(endpoint) {
5089
- let url;
5090
- try {
5091
- url = new URL(endpoint);
5092
- } catch (cause) {
5093
- throw new CliError16({
5094
- code: CliErrorCode15.INVALID_ARGUMENT,
5095
- message: `\u975E\u6CD5 endpoint\uFF1A${endpoint}`,
5096
- cause
5097
- });
5098
- }
5099
- url.username = "";
5100
- url.password = "";
5101
- url.search = "";
5102
- url.hash = "";
5103
- url.pathname = url.pathname.replace(/\/+$/, "");
5104
- return url.toString().replace(/\/$/, "");
5105
- }
5106
- function sha2562(value) {
5107
- return createHash2("sha256").update(value).digest("hex");
5108
- }
5109
- function stableJson2(value) {
5110
- if (Array.isArray(value)) return `[${value.map(stableJson2).join(",")}]`;
5111
- if (value && typeof value === "object") {
5112
- const entries = Object.entries(value).filter(([, item]) => item !== void 0).sort(([left], [right]) => left.localeCompare(right));
5113
- return `{${entries.map(([key, item]) => `${JSON.stringify(key)}:${stableJson2(item)}`).join(",")}}`;
5114
- }
5115
- return JSON.stringify(value);
5116
- }
5117
- async function readOptional(file) {
5118
- try {
5119
- return await fs5.readFile(file, "utf8");
5120
- } catch (cause) {
5121
- if (cause.code === "ENOENT") return void 0;
5122
- throw cause;
5123
- }
5124
- }
5125
- async function readOptionalBytes(file) {
5126
- try {
5127
- return await fs5.readFile(file);
5128
- } catch (cause) {
5129
- if (cause.code === "ENOENT") return void 0;
5130
- throw cause;
5131
- }
5132
- }
5133
- async function exists(file) {
5134
- try {
5135
- await fs5.access(file);
5136
- return true;
5137
- } catch (cause) {
5138
- if (cause.code === "ENOENT") return false;
5139
- throw cause;
5140
- }
5141
- }
5142
- function lockDigests(lock) {
5143
- const digests = /* @__PURE__ */ new Map();
5144
- for (const skill of lock?.resolvedSkills ?? []) {
5145
- if (skill.files === void 0) {
5146
- digests.set(ownedFile(skill.id), { sha256: skill.sha256 });
5147
- continue;
5148
- }
5149
- for (const file of skill.files) {
5150
- digests.set(ownedFile(skill.id, file.path), { sha256: file.sha256 });
5151
- }
5152
- }
5153
- for (const file of lock?.runtime?.files ?? []) {
5154
- digests.set(file.path, { sha256: file.sha256, mode: file.mode });
5155
- }
5156
- return digests;
5157
- }
5158
- async function fileModeMatches(file, expected) {
5159
- if (expected === void 0 || process.platform === "win32") return true;
5160
- const stat = await fs5.stat(file);
5161
- return (stat.mode & 511) === expected;
5162
- }
5163
- function validDigest(value) {
5164
- return typeof value === "string" && /^[a-f0-9]{64}$/.test(value);
5165
- }
5166
- function ignoreMissing(cause) {
5167
- if (cause.code !== "ENOENT") throw cause;
5168
- }
5169
- function invalid(message) {
5170
- return new CliError16({ code: CliErrorCode15.INVALID_ARGUMENT, message });
5171
- }
5172
-
5173
- // src/commands/skills-runtime.ts
5174
- import { execFile } from "child_process";
5175
- import { createHash as createHash3 } from "crypto";
5176
- import { createReadStream, promises as fs6 } from "fs";
5177
- import path5 from "path";
5178
- import { promisify } from "util";
5179
- import { CliError as CliError17, CliErrorCode as CliErrorCode16 } from "@hcmai/sdk";
5180
- var execFileAsync = promisify(execFile);
5181
- var REQUIRED_CAPABILITIES = [
5182
- "hcm.help.skills",
5183
- "hcm.skills.help.sync",
5184
- "hcm.skills.sync.option.project",
5185
- "hcm.skills.sync.option.target"
5186
- ];
5187
- async function prepareWorkBuddyRuntime(input = {}) {
5188
- const candidate = input.candidate?.trim() || input.currentEntry || process.argv[1];
5189
- if (!candidate) throw invalid2("\u65E0\u6CD5\u89E3\u6790\u5F53\u524D HCM CLI \u5165\u53E3\uFF1B\u8BF7\u4F20 --cli <path>");
5190
- const launch = await resolveLaunch(candidate, input.nodeExecutable ?? process.execPath);
5191
- const launchTarget = launch.kind === "node-entry" ? launch.entry : launch.executable;
5192
- for (const forbidden2 of input.forbiddenCandidatePaths ?? []) {
5193
- if (await comparablePath(forbidden2) === launchTarget) {
5194
- throw invalid2("\u5019\u9009 HCM CLI \u4E0D\u80FD\u6307\u5411\u5F85\u751F\u6210\u7684\u9879\u76EE\u7A33\u5B9A\u5165\u53E3");
5195
- }
5196
- }
5197
- if (!(input.currentEntryHasRequiredCapabilities && !input.candidate?.trim())) {
5198
- const beforeProbe = await launchIdentity(launch);
5199
- const syncHelp = await runProbe(launch, ["skills", "sync", "--help"], input.timeoutMs).catch(
5200
- () => ""
5201
- );
5202
- const missing = [];
5203
- if (!/\bhcm\s+skills\s+sync\b/.test(syncHelp)) {
5204
- missing.push(REQUIRED_CAPABILITIES[0], REQUIRED_CAPABILITIES[1]);
5205
- }
5206
- if (!/--project(?:\s|=|<|\[|$)/.test(syncHelp)) missing.push(REQUIRED_CAPABILITIES[2]);
5207
- if (!/--target(?:\s|=|<|\[|$)/.test(syncHelp)) missing.push(REQUIRED_CAPABILITIES[3]);
5208
- if (missing.length > 0) {
5209
- throw invalid2(`\u5019\u9009 HCM CLI \u7F3A\u5C11 WorkBuddy \u6240\u9700\u80FD\u529B\uFF1A${missing.join(", ")}`);
5210
- }
5211
- if (await launchIdentity(launch) !== beforeProbe) {
5212
- throw invalid2("\u5019\u9009 HCM CLI \u5728\u80FD\u529B\u63A2\u9488\u671F\u95F4\u53D1\u751F\u53D8\u5316\uFF0C\u8BF7\u91CD\u8BD5\u540C\u6B65");
5213
- }
5214
- }
5215
- const capabilities = [...REQUIRED_CAPABILITIES];
5216
- const capabilitiesSha256 = sha2563(`${capabilities.join("\n")}
5217
- `);
5218
- const executableSha256 = await sha256File(launch.executable);
5219
- const launchRecord = launch.kind === "node-entry" ? {
5220
4604
  kind: "node-entry",
5221
- executableSha256,
5222
- entrySha256: await sha256File(launch.entry)
5223
- } : { kind: "executable", executableSha256 };
5224
- const unixContent = Buffer.from(unixLauncher(launch), "utf8");
5225
- const windowsContent = Buffer.from(windowsLauncher(launch), "utf8");
5226
- return {
5227
- capabilities,
5228
- capabilitiesSha256,
5229
- launch: launchRecord,
5230
- files: [
5231
- preparedFile(".hcm-delivery/bin/hcm", unixContent, 493),
5232
- preparedFile(".hcm-delivery/bin/hcm.cmd", windowsContent, 420)
5233
- ]
5234
- };
5235
- }
5236
- async function resolveLaunch(candidate, nodeExecutable) {
5237
- const requested = path5.resolve(candidate);
5238
- const resolvedCandidate = await realFile(requested, "\u5019\u9009 HCM CLI");
5239
- const header = (await readPrefix(resolvedCandidate, 256)).toString("utf8");
5240
- const nodeEntry = /^(?:#![^\r\n]*\bnode\b)|\.(?:c|m)?js$/i.test(
5241
- header.startsWith("#!") ? header.split(/\r?\n/, 1)[0] ?? "" : resolvedCandidate
5242
- );
5243
- if (nodeEntry) {
5244
- return {
5245
- kind: "node-entry",
5246
- executable: await realFile(path5.resolve(nodeExecutable), "Node \u53EF\u6267\u884C\u6587\u4EF6"),
5247
- entry: resolvedCandidate
5248
- };
5249
- }
5250
- return { kind: "executable", executable: resolvedCandidate };
5251
- }
5252
- async function realFile(file, label) {
5253
- try {
5254
- const resolved = await fs6.realpath(file);
5255
- const stat = await fs6.stat(resolved);
5256
- if (!stat.isFile()) throw new Error("not a regular file");
5257
- return resolved;
5258
- } catch (cause) {
5259
- throw new CliError17({
5260
- code: CliErrorCode16.INVALID_ARGUMENT,
5261
- message: `${label}\u4E0D\u53EF\u7528\uFF1A${file}`,
5262
- cause
5263
- });
5264
- }
5265
- }
5266
- async function comparablePath(file) {
5267
- const absolute = path5.resolve(file);
5268
- return fs6.realpath(absolute).catch(() => absolute);
5269
- }
5270
- async function launchIdentity(launch) {
5271
- const files = launch.kind === "node-entry" ? [launch.executable, launch.entry] : [launch.executable];
5272
- const identities = await Promise.all(
5273
- files.map(async (file) => {
5274
- const stat = await fs6.stat(file, { bigint: true });
5275
- return [file, stat.dev, stat.ino, stat.size, stat.mtimeNs, stat.ctimeNs].map(String).join("\0");
5276
- })
5277
- );
5278
- return identities.join("\n");
5279
- }
5280
- async function readPrefix(file, bytes) {
5281
- const handle = await fs6.open(file, "r");
5282
- try {
5283
- const buffer = Buffer.alloc(bytes);
5284
- const result2 = await handle.read(buffer, 0, bytes, 0);
5285
- return buffer.subarray(0, result2.bytesRead);
5286
- } finally {
5287
- await handle.close();
5288
- }
5289
- }
5290
- async function runProbe(launch, args, timeoutMs = 5e3) {
5291
- const command = launch.executable;
5292
- const commandArgs = launch.kind === "node-entry" ? [launch.entry, ...args] : args;
5293
- const env2 = {
5294
- ...process.env,
5295
- CI: "1",
5296
- NO_COLOR: "1",
5297
- HCM_RUNTIME_PROBE: "1"
4605
+ executableSha256: await sha256File(process.execPath),
4606
+ entrySha256: await sha256File(entry)
5298
4607
  };
5299
- const nodeOptions = normalizeWorkBuddyNodeOptions(env2.NODE_OPTIONS);
5300
- if (nodeOptions === void 0) delete env2.NODE_OPTIONS;
5301
- else env2.NODE_OPTIONS = nodeOptions;
5302
- try {
5303
- const { stdout, stderr } = await execFileAsync(command, commandArgs, {
5304
- encoding: "utf8",
5305
- timeout: timeoutMs,
5306
- maxBuffer: 256 * 1024,
5307
- windowsHide: true,
5308
- env: env2
5309
- });
5310
- return `${stdout}
5311
- ${stderr}`;
5312
- } catch (cause) {
5313
- throw new CliError17({
5314
- code: CliErrorCode16.INVALID_ARGUMENT,
5315
- message: `\u5019\u9009 HCM CLI \u80FD\u529B\u63A2\u9488\u5931\u8D25\uFF1Ahcm ${args.join(" ")}`,
5316
- cause
5317
- });
5318
- }
5319
- }
5320
- function unixLauncher(launch) {
5321
- const command = shellQuote(launch.executable);
5322
- const entry = launch.kind === "node-entry" ? ` ${shellQuote(launch.entry)}` : "";
5323
- return `#!/bin/sh
5324
- set -eu
5325
-
5326
- # WorkBuddy on macOS may inject --use-system-ca. Node can then spend minutes
5327
- # evaluating the Keychain when a short-lived CLI process exits. Preserve every
5328
- # other host option (including safety --require hooks) and change only this CA mode.
5329
- wb_node_options="\${NODE_OPTIONS-}"
5330
- if [ "$(uname -s 2>/dev/null || printf '%s' unknown)" = 'Darwin' ] && printf '%s
5331
- ' "$wb_node_options" | grep -Eq '(^|[[:space:]])--use-system-ca([[:space:]]|$)'; then
5332
- while printf '%s
5333
- ' "$wb_node_options" | grep -Eq '(^|[[:space:]])--use-system-ca([[:space:]]|$)'; do
5334
- wb_next_options="$(printf '%s
5335
- ' "$wb_node_options" | sed -E 's/(^|[[:space:]])--use-system-ca([[:space:]]|$)/\\1\\2/g')"
5336
- [ "$wb_next_options" != "$wb_node_options" ] || break
5337
- wb_node_options="$wb_next_options"
5338
- done
5339
- if ! printf '%s
5340
- ' "$wb_node_options" | grep -Eq '(^|[[:space:]])--use-bundled-ca([[:space:]]|$)'; then
5341
- wb_node_options="\${wb_node_options:+$wb_node_options }--use-bundled-ca"
5342
- fi
5343
- NODE_OPTIONS="$wb_node_options"
5344
- export NODE_OPTIONS
5345
- fi
5346
-
5347
- exec ${command}${entry} "$@"
5348
- `;
5349
- }
5350
- function normalizeWorkBuddyNodeOptions(value, platform = process.platform) {
5351
- if (platform !== "darwin" || value === void 0) return value;
5352
- const systemCa = /(^|[\t\n\r ])--use-system-ca(?=$|[\t\n\r ])/;
5353
- if (!systemCa.test(value)) return value;
5354
- let normalized = value;
5355
- while (systemCa.test(normalized)) normalized = normalized.replace(systemCa, "$1");
5356
- normalized = normalized.trim();
5357
- const bundledCa = /(^|[\t\n\r ])--use-bundled-ca(?=$|[\t\n\r ])/;
5358
- if (!bundledCa.test(normalized)) {
5359
- normalized = `${normalized}${normalized ? " " : ""}--use-bundled-ca`;
5360
- }
5361
- return normalized;
5362
- }
5363
- function windowsLauncher(launch) {
5364
- const command = cmdQuote(launch.executable);
5365
- const entry = launch.kind === "node-entry" ? ` ${cmdQuote(launch.entry)}` : "";
5366
- return `@echo off\r
5367
- ${command}${entry} %*\r
5368
- `;
5369
- }
5370
- function shellQuote(value) {
5371
- if (/[\r\n\0]/.test(value)) throw invalid2("CLI \u542F\u52A8\u8DEF\u5F84\u5305\u542B\u975E\u6CD5\u63A7\u5236\u5B57\u7B26");
5372
- return `'${value.replace(/'/g, `'"'"'`)}'`;
5373
- }
5374
- function cmdQuote(value) {
5375
- if (/[\r\n\0"]/g.test(value)) throw invalid2("CLI \u542F\u52A8\u8DEF\u5F84\u5305\u542B\u975E\u6CD5\u63A7\u5236\u5B57\u7B26");
5376
- return `"${value.replace(/%/g, "%%")}"`;
5377
4608
  }
5378
- function preparedFile(filePath, content, mode) {
5379
- return { path: filePath, content, bytes: content.length, sha256: sha2563(content), mode };
5380
- }
5381
- async function sha256File(file) {
5382
- const hash = createHash3("sha256");
5383
- await new Promise((resolve4, reject) => {
5384
- const stream = createReadStream(file);
5385
- stream.on("data", (chunk) => hash.update(chunk));
5386
- stream.on("error", reject);
5387
- stream.on("end", resolve4);
5388
- });
5389
- return hash.digest("hex");
5390
- }
5391
- function sha2563(value) {
5392
- return createHash3("sha256").update(value).digest("hex");
5393
- }
5394
- function invalid2(message) {
5395
- return new CliError17({ code: CliErrorCode16.INVALID_ARGUMENT, message });
5396
- }
5397
-
5398
- // src/commands/skills.ts
5399
- var SKILLS_STATE_FILE = ".hcm-skills.json";
5400
4609
  function migrateSkillsState(state) {
5401
4610
  const skills2 = {};
5402
4611
  for (const [id, record] of Object.entries(state.skills ?? {})) {
@@ -5409,8 +4618,8 @@ function migrateSkillsState(state) {
5409
4618
  }
5410
4619
  return { ...state, skills: skills2 };
5411
4620
  }
5412
- function sha2564(text) {
5413
- return createHash4("sha256").update(text, "utf8").digest("hex");
4621
+ function sha2562(text) {
4622
+ return createHash2("sha256").update(text, "utf8").digest("hex");
5414
4623
  }
5415
4624
  async function resolveEndpoint(args) {
5416
4625
  if (args.endpoint) return args.endpoint.replace(/\/+$/, "");
@@ -5418,35 +4627,35 @@ async function resolveEndpoint(args) {
5418
4627
  const envName = resolveActiveEnv3({ envFlag: args.env }, process.env, g);
5419
4628
  const env2 = await loadEnv5(envName).catch(() => null);
5420
4629
  if (!env2?.endpoint) {
5421
- throw new CliError18({
5422
- code: CliErrorCode17.MISSING_FLAG,
4630
+ throw new CliError16({
4631
+ code: CliErrorCode15.MISSING_FLAG,
5423
4632
  message: "\u672A\u89E3\u6790\u5230 endpoint \u2014\u2014 \u4F20 --endpoint <url>\uFF0C\u6216\u5148 `hcm env add <name> --endpoint <url>`\u3002\uFF08\u6280\u80FD\u5E93\u514D\u8BA4\u8BC1\uFF0C\u4E0D\u9700\u8981\u5148 login\uFF09"
5424
4633
  });
5425
4634
  }
5426
4635
  return env2.endpoint.replace(/\/+$/, "");
5427
4636
  }
5428
- function normalizeEndpoint2(endpoint) {
4637
+ function normalizeEndpoint(endpoint) {
5429
4638
  return endpoint.replace(/\/+$/, "");
5430
4639
  }
5431
4640
  function decideTrackedEndpoint(options) {
5432
4641
  const { explicit } = options;
5433
- const current = options.current ? normalizeEndpoint2(options.current) : void 0;
5434
- const recorded = options.recorded ? normalizeEndpoint2(options.recorded) : void 0;
4642
+ const current = options.current ? normalizeEndpoint(options.current) : void 0;
4643
+ const recorded = options.recorded ? normalizeEndpoint(options.recorded) : void 0;
5435
4644
  if (explicit) {
5436
- if (!current) throw invalid3("\u672A\u89E3\u6790\u5230 endpoint \u2014\u2014 \u4F20 --endpoint <url>\uFF0C\u6216\u7528 --env <name> \u6307\u4E00\u4E2A\u914D\u597D\u7684\u73AF\u5883");
4645
+ if (!current) throw invalid("\u672A\u89E3\u6790\u5230 endpoint \u2014\u2014 \u4F20 --endpoint <url>\uFF0C\u6216\u7528 --env <name> \u6307\u4E00\u4E2A\u914D\u597D\u7684\u73AF\u5883");
5437
4646
  return current;
5438
4647
  }
5439
4648
  if (!recorded) {
5440
4649
  if (!current) {
5441
- throw new CliError18({
5442
- code: CliErrorCode17.MISSING_FLAG,
4650
+ throw new CliError16({
4651
+ code: CliErrorCode15.MISSING_FLAG,
5443
4652
  message: "\u672A\u89E3\u6790\u5230 endpoint \u2014\u2014 \u4F20 --endpoint <url>\uFF0C\u6216\u5148 `hcm env add <name> --endpoint <url>`\u3002\uFF08\u6280\u80FD\u5E93\u514D\u8BA4\u8BC1\uFF0C\u4E0D\u9700\u8981\u5148 login\uFF09"
5444
4653
  });
5445
4654
  }
5446
4655
  return current;
5447
4656
  }
5448
4657
  if (!current || current === recorded) return recorded;
5449
- throw invalid3(
4658
+ throw invalid(
5450
4659
  `\u8FD9\u4E2A\u76EE\u5F55\u7684\u6280\u80FD\u88C5\u81EA ${recorded}\uFF0C\u5F53\u524D env \u6307\u5411 ${current} \u2014\u2014 \u4E0D\u662F\u540C\u4E00\u4E2A\u73AF\u5883\u3002
5451
4660
  \u6280\u80FD\u968F\u4EA7\u54C1\u7248\u672C\u8D70\uFF0C\u8DE8\u73AF\u5883\u5347\u7EA7\u4F1A\u62FF\u53E6\u4E00\u4E2A\u73AF\u5883\u7684\u7248\u672C\u76D6\u6389\u73B0\u5728\u8FD9\u4EFD\uFF0C\u4E14\u4E0D\u4F1A\u6709\u4EFB\u4F55\u63D0\u793A\u3002
5452
4661
  \u660E\u8BF4\u8981\u54EA\u4E2A\uFF1A
@@ -5454,7 +4663,7 @@ function decideTrackedEndpoint(options) {
5454
4663
  \xB7 \u6539\u8DDF\u5F53\u524D\u8FD9\u4E2A \u2192 \u52A0 --endpoint ${current}\uFF08\u6765\u6E90\u4F1A\u6539\u6210\u5B83\uFF0C\u4E4B\u540E\u4E0D\u7528\u518D\u5E26\uFF09`
5455
4664
  );
5456
4665
  }
5457
- async function exists2(target) {
4666
+ async function exists(target) {
5458
4667
  try {
5459
4668
  await fsp2.stat(target);
5460
4669
  return true;
@@ -5463,25 +4672,25 @@ async function exists2(target) {
5463
4672
  }
5464
4673
  }
5465
4674
  async function detectTarget(cwd) {
5466
- if (await exists2(path6.join(cwd, ".claude"))) return "claude";
5467
- if (await exists2(path6.join(cwd, "AGENTS.md"))) return "codex";
5468
- if (await exists2(path6.join(cwd, ".codex"))) return "codex";
4675
+ if (await exists(path4.join(cwd, ".claude"))) return "claude";
4676
+ if (await exists(path4.join(cwd, "AGENTS.md"))) return "codex";
4677
+ if (await exists(path4.join(cwd, ".codex"))) return "codex";
5469
4678
  return void 0;
5470
4679
  }
5471
4680
  async function resolveInstallLayout(args, cwd = process.cwd()) {
5472
4681
  const requested = args.target && args.target !== "auto" ? args.target : void 0;
5473
4682
  const target = requested ?? await detectTarget(cwd) ?? "claude";
5474
4683
  if (target === "codex") {
5475
- const root = args.global ? path6.join(os2.homedir(), ".codex") : cwd;
4684
+ const root = args.global ? path4.join(os2.homedir(), ".codex") : cwd;
5476
4685
  return {
5477
4686
  target,
5478
- baseDir: args.dir ? path6.resolve(args.dir) : path6.join(root, "hcm-skills"),
5479
- agentsFile: path6.join(root, "AGENTS.md")
4687
+ baseDir: args.dir ? path4.resolve(args.dir) : path4.join(root, "hcm-skills"),
4688
+ agentsFile: path4.join(root, "AGENTS.md")
5480
4689
  };
5481
4690
  }
5482
4691
  return {
5483
4692
  target,
5484
- baseDir: args.dir ? path6.resolve(args.dir) : args.global ? path6.join(os2.homedir(), ".claude", "skills") : path6.join(cwd, ".claude", "skills")
4693
+ baseDir: args.dir ? path4.resolve(args.dir) : args.global ? path4.join(os2.homedir(), ".claude", "skills") : path4.join(cwd, ".claude", "skills")
5485
4694
  };
5486
4695
  }
5487
4696
  async function chironClient(args) {
@@ -5518,8 +4727,8 @@ async function skillsListCommand(keyword, args) {
5518
4727
  const catalog = buildUnifiedCatalog({ source, chironManifest: manifest2, bundled, cliVersion: CLI_VERSION });
5519
4728
  const conflicts = detectIdConflicts(catalog);
5520
4729
  if (conflicts.ids.length > 0) {
5521
- throw new CliError18({
5522
- code: CliErrorCode17.SKILL_ID_CONFLICT,
4730
+ throw new CliError16({
4731
+ code: CliErrorCode15.SKILL_ID_CONFLICT,
5523
4732
  message: conflictMessage(conflicts.ids, endpoint ?? "(\u672A\u77E5\u73AF\u5883)")
5524
4733
  });
5525
4734
  }
@@ -5635,7 +4844,7 @@ async function listInstalledSkills(keyword, args) {
5635
4844
  process.stdout.write(formatObject14({ baseDir: layout.baseDir, target: layout.target, all: false, skills: [] }, { format: fmt }) + "\n");
5636
4845
  process.exit(0);
5637
4846
  }
5638
- process.stdout.write(`${path6.join(layout.baseDir, SKILLS_STATE_FILE)} \u4E0D\u5B58\u5728\u6216\u4E3A\u7A7A \u2014\u2014 \u8FD9\u4E2A\u76EE\u5F55\u4E0B\u8FD8\u6CA1\u7528\u672C CLI \u88C5\u8FC7\u6280\u80FD\u3002
4847
+ process.stdout.write(`${path4.join(layout.baseDir, SKILLS_STATE_FILE)} \u4E0D\u5B58\u5728\u6216\u4E3A\u7A7A \u2014\u2014 \u8FD9\u4E2A\u76EE\u5F55\u4E0B\u8FD8\u6CA1\u7528\u672C CLI \u88C5\u8FC7\u6280\u80FD\u3002
5639
4848
  `);
5640
4849
  process.stdout.write(" \u88C5\u5168\u90E8\uFF1Ahcm skills install --all\n");
5641
4850
  process.exit(0);
@@ -5657,7 +4866,7 @@ async function listInstalledSkills(keyword, args) {
5657
4866
  direct: record.direct,
5658
4867
  installedAt: record.installedAt,
5659
4868
  // 三种状态互斥:文件没了 / 本地改过 / 和装的时候一致
5660
- status: markdown === void 0 ? "missing" : sha2564(markdown) !== record.sha256 ? "locally-modified" : "installed"
4869
+ status: markdown === void 0 ? "missing" : sha2562(markdown) !== record.sha256 ? "locally-modified" : "installed"
5661
4870
  });
5662
4871
  }
5663
4872
  const byKeyword = keyword ? rows.filter((row) => row.id.includes(keyword) || row.title.includes(keyword)) : rows;
@@ -5719,7 +4928,7 @@ async function listInstalledSkills(keyword, args) {
5719
4928
  }
5720
4929
  async function skillsShowCommand(id, args) {
5721
4930
  try {
5722
- assertSafeSkillId2(id);
4931
+ assertSafeSkillId(id);
5723
4932
  const source = parseSourceFilter(args.source);
5724
4933
  if (source !== "chiron" && listBundledSkills().some((s) => s.id === id)) {
5725
4934
  const document = await readBundledSkillDocument(id);
@@ -5727,7 +4936,7 @@ async function skillsShowCommand(id, args) {
5727
4936
  process.exit(0);
5728
4937
  }
5729
4938
  if (source === "cli") {
5730
- throw invalid3(`\u8FD9\u4E00\u7248 CLI \u6CA1\u6709\u81EA\u5E26 ${id} \u8FD9\u4E2A\u6280\u80FD\uFF08--source cli \u4E0D\u770B\u777F\u620E\u76EE\u5F55\uFF09`);
4939
+ throw invalid(`\u8FD9\u4E00\u7248 CLI \u6CA1\u6709\u81EA\u5E26 ${id} \u8FD9\u4E2A\u6280\u80FD\uFF08--source cli \u4E0D\u770B\u777F\u620E\u76EE\u5F55\uFF09`);
5731
4940
  }
5732
4941
  const { http, base } = await chironClient(args);
5733
4942
  const md = await fetchSkillMarkdown(http, id, base);
@@ -5737,80 +4946,12 @@ async function skillsShowCommand(id, args) {
5737
4946
  fail3(e, args);
5738
4947
  }
5739
4948
  }
5740
- async function skillsSyncCommand(id, args) {
5741
- try {
5742
- assertSafeSkillId2(id);
5743
- if (args.target !== "workbuddy") {
5744
- throw invalid3(`sync --target \u5F53\u524D\u53EA\u652F\u6301 workbuddy\uFF0C\u6536\u5230 "${args.target ?? ""}"`);
5745
- }
5746
- if (!args.project?.trim()) throw invalid3("sync \u5FC5\u987B\u4F20 --project <path>");
5747
- if (listBundledSkills().some((one) => one.id === id)) {
5748
- throw new CliError18({
5749
- code: CliErrorCode17.SYNC_SOURCE_UNSUPPORTED,
5750
- message: `\`${id}\` \u662F CLI \u81EA\u5E26\u6280\u80FD\uFF1Bskills sync \u7684\u9501\u6587\u4EF6\uFF08chiron.lock.json\uFF09\u6B64\u523B\u53EA\u80FD\u8BB0\u5F55\u777F\u620E\u6765\u6E90\u7684\u51FA\u5904\u3002\u88C5\u5230\u672C\u5730\u7528 \`hcm skills install ` + id + "`\u3002"
5751
- });
5752
- }
5753
- const project = path6.resolve(args.project);
5754
- const runtime = await prepareWorkBuddyRuntime({
5755
- candidate: args.cli,
5756
- currentEntryHasRequiredCapabilities: !args.cli?.trim(),
5757
- forbiddenCandidatePaths: [
5758
- path6.join(project, ".hcm-delivery", "bin", "hcm"),
5759
- path6.join(project, ".hcm-delivery", "bin", "hcm.cmd")
5760
- ]
5761
- });
5762
- const connectionArgs = { endpoint: args.endpoint, env: args.env };
5763
- const { http, endpoint, base } = await chironClient(connectionArgs);
5764
- const catalog = await fetchSkillCatalog(http, base);
5765
- const documents = await prepareSkillDocuments(
5766
- catalog,
5767
- id,
5768
- async (skillId) => fetchSkillMarkdown(http, skillId, base),
5769
- async (skillId, relativePath) => fetchSkillFile(http, skillId, relativePath, base),
5770
- async (skillId, relativePath) => fetchSkillReference(http, skillId, relativePath, base)
5771
- );
5772
- const result2 = await syncWorkBuddyProject({
5773
- project,
5774
- endpoint,
5775
- catalog,
5776
- requestedSkill: id,
5777
- documents,
5778
- runtime
5779
- });
5780
- const fmt = args.output ?? "table";
5781
- if (fmt === "json" || fmt === "yaml") {
5782
- process.stdout.write(`${formatObject14(result2, { format: fmt })}
5783
- `);
5784
- } else if (result2.changed) {
5785
- process.stdout.write(`\u2705 ${id} \u2192 ${result2.skillsDir}
5786
- `);
5787
- process.stdout.write(` \u95ED\u5305 ${result2.resolvedSkills.join(" \u2192 ")}
5788
- `);
5789
- process.stdout.write(` \u5165\u53E3 ${result2.runnerPath}
5790
- `);
5791
- process.stdout.write(` CLI \u80FD\u529B ${result2.capabilitiesSha256.slice(0, 12)}
5792
- `);
5793
- process.stdout.write(` \u9501 ${result2.lockPath}
5794
- `);
5795
- } else {
5796
- process.stdout.write(`\u2713 ${id} \u5DF2\u662F\u5F53\u524D\u76EE\u6807\u5B9E\u4F8B\u7248\u672C\uFF0C\u65E0\u9700\u66F4\u65B0
5797
- `);
5798
- process.stdout.write(` \u5165\u53E3 ${result2.runnerPath}
5799
- `);
5800
- process.stdout.write(` \u9501 ${result2.lockPath}
5801
- `);
5802
- }
5803
- process.exit(0);
5804
- } catch (e) {
5805
- fail3(e, { endpoint: args.endpoint, env: args.env });
5806
- }
5807
- }
5808
4949
  async function skillsInstallCommand(id, args) {
5809
4950
  try {
5810
4951
  const all = Boolean(args.all);
5811
- if (all && id) throw invalid3("`--all` \u662F\u88C5\u6574\u4E2A\u6280\u80FD\u5E93\uFF0C\u4E0D\u8981\u518D\u5E26\u6280\u80FD id\uFF1B\u53EA\u88C5\u4E00\u4E2A\u5C31\u53BB\u6389 --all");
5812
- if (!all && !id) throw invalid3("\u8981\u88C5\u54EA\u4E2A\u6280\u80FD\uFF1F\u7ED9\u4E2A id\uFF08`hcm skills list` \u770B\u76EE\u5F55\uFF09\uFF0C\u6216\u7528 `--all` \u88C5\u5168\u90E8");
5813
- if (id) assertSafeSkillId2(id);
4952
+ if (all && id) throw invalid("`--all` \u662F\u88C5\u6574\u4E2A\u6280\u80FD\u5E93\uFF0C\u4E0D\u8981\u518D\u5E26\u6280\u80FD id\uFF1B\u53EA\u88C5\u4E00\u4E2A\u5C31\u53BB\u6389 --all");
4953
+ if (!all && !id) throw invalid("\u8981\u88C5\u54EA\u4E2A\u6280\u80FD\uFF1F\u7ED9\u4E2A id\uFF08`hcm skills list` \u770B\u76EE\u5F55\uFF09\uFF0C\u6216\u7528 `--all` \u88C5\u5168\u90E8");
4954
+ if (id) assertSafeSkillId(id);
5814
4955
  const layout = await resolveInstallLayout(args);
5815
4956
  let documents;
5816
4957
  let requestedIds;
@@ -5819,7 +4960,7 @@ async function skillsInstallCommand(id, args) {
5819
4960
  let manifest2;
5820
4961
  let conflictNote;
5821
4962
  if (args.from) {
5822
- const root = path6.resolve(args.from);
4963
+ const root = path4.resolve(args.from);
5823
4964
  requestedIds = all ? await listLocalSkillIds(root) : [id];
5824
4965
  const seen = /* @__PURE__ */ new Set();
5825
4966
  documents = [];
@@ -5849,14 +4990,14 @@ async function skillsInstallCommand(id, args) {
5849
4990
  const catalog = buildUnifiedCatalog({ source, chironManifest: manifest2, bundled, cliVersion: CLI_VERSION });
5850
4991
  const conflicts = detectIdConflicts(catalog);
5851
4992
  if (conflicts.ids.length > 0) {
5852
- throw new CliError18({
5853
- code: CliErrorCode17.SKILL_ID_CONFLICT,
4993
+ throw new CliError16({
4994
+ code: CliErrorCode15.SKILL_ID_CONFLICT,
5854
4995
  message: conflictMessage(conflicts.ids, endpoint ?? "(\u672A\u77E5\u73AF\u5883)")
5855
4996
  });
5856
4997
  }
5857
4998
  conflictNote = conflicts.checked ? void 0 : unconfirmedConflictNote(source);
5858
4999
  for (const v of checkCrossSourceRequires(catalog)) {
5859
- throw invalid3(`${v.from} \u58F0\u660E\u4F9D\u8D56 ${v.to}\uFF0C\u4F46 ${v.to} \u662F CLI \u81EA\u5E26\u6280\u80FD\u3002${v.reason}`);
5000
+ throw invalid(`${v.from} \u58F0\u660E\u4F9D\u8D56 ${v.to}\uFF0C\u4F46 ${v.to} \u662F CLI \u81EA\u5E26\u6280\u80FD\u3002${v.reason}`);
5860
5001
  }
5861
5002
  const wantBundled = (one) => catalog.cli.entries.has(one);
5862
5003
  const seen = /* @__PURE__ */ new Set();
@@ -5872,16 +5013,16 @@ async function skillsInstallCommand(id, args) {
5872
5013
  const { documents: local, external } = await resolveBundledClosure(one);
5873
5014
  for (const need of external) {
5874
5015
  if (catalog.chiron.status !== "fetched") {
5875
- throw invalid3(
5016
+ throw invalid(
5876
5017
  `\u81EA\u5E26\u6280\u80FD ${one} \u4F9D\u8D56\u777F\u620E\u6280\u80FD ${need}\uFF0C\u4F46\u8FD9\u4E00\u8D9F\u6CA1\u8FDE\u7F51\u53D6\u777F\u620E\u76EE\u5F55\uFF08--source ${source}\uFF09\u3002\u8054\u7F51\u540E\u91CD\u8DD1\uFF0C\u6216\u5148\u5355\u72EC\u88C5\u4E0A\u5B83\u3002`
5877
5018
  );
5878
5019
  }
5879
5020
  if (!catalog.chiron.entries.has(need)) {
5880
- throw invalid3(`\u81EA\u5E26\u6280\u80FD ${one} \u4F9D\u8D56 ${need}\uFF0C\u4F46 ${endpoint} \u7684\u6280\u80FD\u76EE\u5F55\u91CC\u6CA1\u6709\u5B83`);
5021
+ throw invalid(`\u81EA\u5E26\u6280\u80FD ${one} \u4F9D\u8D56 ${need}\uFF0C\u4F46 ${endpoint} \u7684\u6280\u80FD\u76EE\u5F55\u91CC\u6CA1\u6709\u5B83`);
5881
5022
  }
5882
5023
  pushAll(
5883
5024
  await mapWithConcurrency(
5884
- resolveSkillInstallOrder2(manifest2, need),
5025
+ resolveSkillInstallOrder(manifest2, need),
5885
5026
  FETCH_CONCURRENCY,
5886
5027
  (skill) => fetchSkillDocument(http, skill, endpoint, base)
5887
5028
  )
@@ -5893,7 +5034,7 @@ async function skillsInstallCommand(id, args) {
5893
5034
  const order = manifest2 ? resolveAllSkillsInstallOrder(manifest2) : [];
5894
5035
  const bundledIds = [...catalog.cli.entries.keys()].sort();
5895
5036
  if (order.length === 0 && bundledIds.length === 0) {
5896
- throw invalid3(`${endpoint ?? "\u8FD9\u4E00\u8D9F\u770B\u7684\u6765\u6E90"} \u91CC\u6CA1\u6709\u53EF\u88C5\u7684\u6280\u80FD`);
5037
+ throw invalid(`${endpoint ?? "\u8FD9\u4E00\u8D9F\u770B\u7684\u6765\u6E90"} \u91CC\u6CA1\u6709\u53EF\u88C5\u7684\u6280\u80FD`);
5897
5038
  }
5898
5039
  requestedIds = [...order.map((skill) => skill.id), ...bundledIds];
5899
5040
  if (order.length > 0) {
@@ -5911,19 +5052,19 @@ async function skillsInstallCommand(id, args) {
5911
5052
  await installBundled(id);
5912
5053
  } else {
5913
5054
  if (source === "cli") {
5914
- throw invalid3(`\u8FD9\u4E00\u7248 CLI \u6CA1\u6709\u81EA\u5E26 ${id} \u8FD9\u4E2A\u6280\u80FD\uFF08--source cli \u4E0D\u770B\u777F\u620E\u76EE\u5F55\uFF09`);
5055
+ throw invalid(`\u8FD9\u4E00\u7248 CLI \u6CA1\u6709\u81EA\u5E26 ${id} \u8FD9\u4E2A\u6280\u80FD\uFF08--source cli \u4E0D\u770B\u777F\u620E\u76EE\u5F55\uFF09`);
5915
5056
  }
5916
5057
  requestedIds = [id];
5917
5058
  pushAll(
5918
5059
  await mapWithConcurrency(
5919
- resolveSkillInstallOrder2(manifest2, id),
5060
+ resolveSkillInstallOrder(manifest2, id),
5920
5061
  FETCH_CONCURRENCY,
5921
5062
  (skill) => fetchSkillDocument(http, skill, endpoint, base)
5922
5063
  )
5923
5064
  );
5924
5065
  }
5925
5066
  }
5926
- const result2 = await installSkillDocuments(documents, requestedIds, layout.baseDir, Boolean(args.force), {
5067
+ const result = await installSkillDocuments(documents, requestedIds, layout.baseDir, Boolean(args.force), {
5927
5068
  endpoint,
5928
5069
  base,
5929
5070
  target: layout.target,
@@ -5932,19 +5073,19 @@ async function skillsInstallCommand(id, args) {
5932
5073
  const agents = layout.agentsFile ? await syncAgentsIndex(layout, manifest2) : void 0;
5933
5074
  const fmt = args.output ?? "table";
5934
5075
  if (fmt === "json" || fmt === "yaml") {
5935
- process.stdout.write(formatObject14({ ...result2, all, target_agent: layout.target, agentsFile: layout.agentsFile, agents, conflictCheck: conflictNote ? { checked: false, note: conflictNote } : { checked: true } }, { format: fmt }) + "\n");
5076
+ process.stdout.write(formatObject14({ ...result, all, target_agent: layout.target, agentsFile: layout.agentsFile, agents, conflictCheck: conflictNote ? { checked: false, note: conflictNote } : { checked: true } }, { format: fmt }) + "\n");
5936
5077
  } else {
5937
- const headline = all ? `\u2705 \u5168\u90E8 ${requestedIds.length} \u4E2A\u6280\u80FD \u2192 ${result2.baseDir}` : `\u2705 ${id} \u2192 ${path6.join(result2.baseDir, id, "SKILL.md")}`;
5078
+ const headline = all ? `\u2705 \u5168\u90E8 ${requestedIds.length} \u4E2A\u6280\u80FD \u2192 ${result.baseDir}` : `\u2705 ${id} \u2192 ${path4.join(result.baseDir, id, "SKILL.md")}`;
5938
5079
  process.stdout.write(`${headline}
5939
5080
  `);
5940
- if (result2.installed.length > 0) {
5941
- process.stdout.write(all ? ` \u65B0\u5199\u5165 ${result2.installed.length} \u4E2A
5942
- ` : ` \u5DF2\u5B89\u88C5 ${result2.installed.join(" \u2192 ")}
5081
+ if (result.installed.length > 0) {
5082
+ process.stdout.write(all ? ` \u65B0\u5199\u5165 ${result.installed.length} \u4E2A
5083
+ ` : ` \u5DF2\u5B89\u88C5 ${result.installed.join(" \u2192 ")}
5943
5084
  `);
5944
5085
  }
5945
- if (result2.unchanged.length > 0) {
5946
- process.stdout.write(all ? ` \u5DF2\u662F\u8FD9\u4E00\u7248\u3001\u672A\u6539\u52A8 ${result2.unchanged.length} \u4E2A
5947
- ` : ` \u5DF2\u5B58\u5728\u4E14\u7248\u672C\u4E00\u81F4 ${result2.unchanged.join(", ")}
5086
+ if (result.unchanged.length > 0) {
5087
+ process.stdout.write(all ? ` \u5DF2\u662F\u8FD9\u4E00\u7248\u3001\u672A\u6539\u52A8 ${result.unchanged.length} \u4E2A
5088
+ ` : ` \u5DF2\u5B58\u5728\u4E14\u7248\u672C\u4E00\u81F4 ${result.unchanged.join(", ")}
5948
5089
  `);
5949
5090
  }
5950
5091
  const referenceCount = documents.reduce((n, d) => n + (d.references?.length ?? 0), 0);
@@ -5956,7 +5097,7 @@ async function skillsInstallCommand(id, args) {
5956
5097
  process.stdout.write(` \u5DF2${agents === "created" ? "\u521B\u5EFA" : "\u66F4\u65B0"} ${layout.agentsFile} \u91CC\u7684\u6280\u80FD\u7D22\u5F15\uFF08Codex \u8BFB\u8FD9\u91CC\uFF09
5957
5098
  `);
5958
5099
  }
5959
- process.stdout.write(` \u6765\u6E90 ${endpoint ?? (args.from ? path6.resolve(args.from) : `@hcmai/cli@${CLI_VERSION}`)}
5100
+ process.stdout.write(` \u6765\u6E90 ${endpoint ?? (args.from ? path4.resolve(args.from) : `@hcmai/cli@${CLI_VERSION}`)}
5960
5101
  `);
5961
5102
  if (conflictNote) process.stdout.write(` \u26A0\uFE0F ${conflictNote}
5962
5103
  `);
@@ -5986,18 +5127,18 @@ async function listLocalSkillIds(root) {
5986
5127
  try {
5987
5128
  entries = await fsp2.readdir(root, { withFileTypes: true });
5988
5129
  } catch {
5989
- throw invalid3(`\u8BFB\u4E0D\u5230\u672C\u5730\u6280\u80FD\u76EE\u5F55\uFF1A${root}`);
5130
+ throw invalid(`\u8BFB\u4E0D\u5230\u672C\u5730\u6280\u80FD\u76EE\u5F55\uFF1A${root}`);
5990
5131
  }
5991
5132
  const ids = [];
5992
5133
  for (const entry of entries) {
5993
5134
  if (!entry.isDirectory()) continue;
5994
- if (await exists2(path6.join(root, entry.name, "SKILL.md"))) ids.push(entry.name);
5135
+ if (await exists(path4.join(root, entry.name, "SKILL.md"))) ids.push(entry.name);
5995
5136
  }
5996
- if (ids.length === 0) throw invalid3(`\u672C\u5730\u76EE\u5F55\u91CC\u6CA1\u6709\u4EFB\u4F55 <id>/SKILL.md\uFF1A${root}`);
5137
+ if (ids.length === 0) throw invalid(`\u672C\u5730\u76EE\u5F55\u91CC\u6CA1\u6709\u4EFB\u4F55 <id>/SKILL.md\uFF1A${root}`);
5997
5138
  return ids.sort();
5998
5139
  }
5999
5140
  async function fetchSkillDocument(http, skill, endpoint, base) {
6000
- const relatives = normalizeReferences2(skill.references, skill.id);
5141
+ const relatives = normalizeReferences(skill.references, skill.id);
6001
5142
  const references = await Promise.all(relatives.map(async (relative2) => ({
6002
5143
  path: relative2,
6003
5144
  content: await fetchSkillReference(http, skill.id, relative2, base)
@@ -6018,23 +5159,23 @@ async function syncAgentsIndex(layout, manifest2) {
6018
5159
  for (const category of manifest2?.categories ?? []) {
6019
5160
  for (const skill of category.skills ?? []) catalog.set(skill.id, skill);
6020
5161
  }
6021
- const agentsDir = path6.dirname(layout.agentsFile);
5162
+ const agentsDir = path4.dirname(layout.agentsFile);
6022
5163
  const entries = Object.keys(state.skills).sort().map((id) => {
6023
5164
  const known = catalog.get(id);
6024
- const absolute = path6.join(layout.baseDir, id, "SKILL.md");
6025
- let relative2 = path6.relative(agentsDir, absolute);
5165
+ const absolute = path4.join(layout.baseDir, id, "SKILL.md");
5166
+ let relative2 = path4.relative(agentsDir, absolute);
6026
5167
  if (!relative2.startsWith(".")) relative2 = `./${relative2}`;
6027
5168
  return {
6028
5169
  id,
6029
5170
  title: known?.title ?? id,
6030
5171
  description: known?.description ?? "",
6031
- relativePath: relative2.split(path6.sep).join("/")
5172
+ relativePath: relative2.split(path4.sep).join("/")
6032
5173
  };
6033
5174
  });
6034
5175
  return upsertAgentsBlock(layout.agentsFile, renderAgentsBlock(entries));
6035
5176
  }
6036
5177
  async function resolveLocalSkillDocuments(sourceRoot, targetId) {
6037
- assertSafeSkillId2(targetId);
5178
+ assertSafeSkillId(targetId);
6038
5179
  const state = /* @__PURE__ */ new Map();
6039
5180
  const pathStack = [];
6040
5181
  const order = [];
@@ -6043,20 +5184,20 @@ async function resolveLocalSkillDocuments(sourceRoot, targetId) {
6043
5184
  if (current === "done") return;
6044
5185
  if (current === "visiting") {
6045
5186
  const start = pathStack.indexOf(id);
6046
- throw invalid3(`\u6280\u80FD\u4F9D\u8D56\u5B58\u5728\u73AF: ${[...pathStack.slice(Math.max(0, start)), id].join(" -> ")}`);
5187
+ throw invalid(`\u6280\u80FD\u4F9D\u8D56\u5B58\u5728\u73AF: ${[...pathStack.slice(Math.max(0, start)), id].join(" -> ")}`);
6047
5188
  }
6048
- assertSafeSkillId2(id);
6049
- const local = path6.join(sourceRoot, id, "SKILL.md");
5189
+ assertSafeSkillId(id);
5190
+ const local = path4.join(sourceRoot, id, "SKILL.md");
6050
5191
  let markdown;
6051
5192
  try {
6052
5193
  markdown = await fsp2.readFile(local, "utf8");
6053
5194
  } catch (cause) {
6054
5195
  if (cause?.code === "ENOENT") {
6055
- throw invalid3(requiredBy ? `\u672C\u5730\u6280\u80FD ${requiredBy} \u4F9D\u8D56\u4E0D\u5B58\u5728: ${id}\uFF08${local}\uFF09` : `\u672C\u5730\u76EE\u5F55\u91CC\u6CA1\u6709 ${id}/SKILL.md\uFF1A${path6.join(sourceRoot, id)}`);
5196
+ throw invalid(requiredBy ? `\u672C\u5730\u6280\u80FD ${requiredBy} \u4F9D\u8D56\u4E0D\u5B58\u5728: ${id}\uFF08${local}\uFF09` : `\u672C\u5730\u76EE\u5F55\u91CC\u6CA1\u6709 ${id}/SKILL.md\uFF1A${path4.join(sourceRoot, id)}`);
6056
5197
  }
6057
5198
  throw cause;
6058
5199
  }
6059
- if (!markdown.trim()) throw invalid3(`\u6280\u80FD ${id} \u5185\u5BB9\u4E3A\u7A7A`);
5200
+ if (!markdown.trim()) throw invalid(`\u6280\u80FD ${id} \u5185\u5BB9\u4E3A\u7A7A`);
6060
5201
  state.set(id, "visiting");
6061
5202
  pathStack.push(id);
6062
5203
  const document = {
@@ -6064,7 +5205,7 @@ async function resolveLocalSkillDocuments(sourceRoot, targetId) {
6064
5205
  markdown,
6065
5206
  source: local,
6066
5207
  sourceKind: "local",
6067
- references: await readLocalReferences(path6.join(sourceRoot, id))
5208
+ references: await readLocalReferences(path4.join(sourceRoot, id))
6068
5209
  };
6069
5210
  for (const required of parseSkillRequirements2(markdown, id)) {
6070
5211
  await visit(required, id);
@@ -6078,7 +5219,7 @@ async function resolveLocalSkillDocuments(sourceRoot, targetId) {
6078
5219
  }
6079
5220
  async function readSkillsState(baseDir) {
6080
5221
  try {
6081
- const raw = await fsp2.readFile(path6.join(baseDir, SKILLS_STATE_FILE), "utf8");
5222
+ const raw = await fsp2.readFile(path4.join(baseDir, SKILLS_STATE_FILE), "utf8");
6082
5223
  const parsed = JSON.parse(raw);
6083
5224
  if (!parsed || typeof parsed !== "object" || !parsed.skills) return void 0;
6084
5225
  return migrateSkillsState(parsed);
@@ -6088,7 +5229,7 @@ async function readSkillsState(baseDir) {
6088
5229
  }
6089
5230
  async function writeSkillsState(baseDir, state) {
6090
5231
  await fsp2.mkdir(baseDir, { recursive: true });
6091
- const file = path6.join(baseDir, SKILLS_STATE_FILE);
5232
+ const file = path4.join(baseDir, SKILLS_STATE_FILE);
6092
5233
  const temp = `${file}.${process.pid}.tmp`;
6093
5234
  await fsp2.writeFile(temp, JSON.stringify(state, null, 2) + "\n", "utf8");
6094
5235
  await fsp2.rename(temp, file);
@@ -6117,7 +5258,7 @@ async function upsertAgentsBlock(agentsFile, block) {
6117
5258
  existing = await fsp2.readFile(agentsFile, "utf8");
6118
5259
  } catch (cause) {
6119
5260
  if (cause?.code !== "ENOENT") throw cause;
6120
- await fsp2.mkdir(path6.dirname(agentsFile), { recursive: true });
5261
+ await fsp2.mkdir(path4.dirname(agentsFile), { recursive: true });
6121
5262
  await fsp2.writeFile(agentsFile, block + "\n", "utf8");
6122
5263
  return "created";
6123
5264
  }
@@ -6133,22 +5274,22 @@ async function upsertAgentsBlock(agentsFile, block) {
6133
5274
  return "appended";
6134
5275
  }
6135
5276
  async function installSkillDocuments(documents, requestedIds, baseDir, force, meta2) {
6136
- if (requestedIds.length === 0) throw invalid3("\u6CA1\u6709\u6307\u5B9A\u8981\u88C5\u7684\u6280\u80FD");
6137
- for (const id of requestedIds) assertSafeSkillId2(id);
5277
+ if (requestedIds.length === 0) throw invalid("\u6CA1\u6709\u6307\u5B9A\u8981\u88C5\u7684\u6280\u80FD");
5278
+ for (const id of requestedIds) assertSafeSkillId(id);
6138
5279
  const seen = /* @__PURE__ */ new Set();
6139
5280
  const candidates = documents.map((document) => {
6140
- assertSafeSkillId2(document.id);
6141
- if (seen.has(document.id)) throw invalid3(`\u5B89\u88C5\u95ED\u5305\u5305\u542B\u91CD\u590D\u6280\u80FD: ${document.id}`);
5281
+ assertSafeSkillId(document.id);
5282
+ if (seen.has(document.id)) throw invalid(`\u5B89\u88C5\u95ED\u5305\u5305\u542B\u91CD\u590D\u6280\u80FD: ${document.id}`);
6142
5283
  seen.add(document.id);
6143
- if (!document.markdown.trim()) throw invalid3(`\u6280\u80FD ${document.id} \u5185\u5BB9\u4E3A\u7A7A`);
5284
+ if (!document.markdown.trim()) throw invalid(`\u6280\u80FD ${document.id} \u5185\u5BB9\u4E3A\u7A7A`);
6144
5285
  return {
6145
5286
  ...document,
6146
- target: path6.join(baseDir, document.id, "SKILL.md"),
5287
+ target: path4.join(baseDir, document.id, "SKILL.md"),
6147
5288
  bytes: Buffer.byteLength(document.markdown)
6148
5289
  };
6149
5290
  });
6150
5291
  for (const id of requestedIds) {
6151
- if (!seen.has(id)) throw invalid3(`\u5B89\u88C5\u95ED\u5305\u4E0D\u5305\u542B\u76EE\u6807\u6280\u80FD: ${id}`);
5292
+ if (!seen.has(id)) throw invalid(`\u5B89\u88C5\u95ED\u5305\u4E0D\u5305\u542B\u76EE\u6807\u6280\u80FD: ${id}`);
6152
5293
  }
6153
5294
  const unchanged = /* @__PURE__ */ new Set();
6154
5295
  for (const candidate of candidates) {
@@ -6159,7 +5300,7 @@ async function installSkillDocuments(documents, requestedIds, baseDir, force, me
6159
5300
  unchanged.add(candidate.id);
6160
5301
  continue;
6161
5302
  }
6162
- throw invalid3(
5303
+ throw invalid(
6163
5304
  `${candidate.target} \u5DF2\u5B58\u5728\uFF0C\u4E14\u548C\u76EE\u6807\u73AF\u5883\u8FD9\u4E00\u7248\u4E0D\u4E00\u81F4\u3002\u7528 --force \u8986\u76D6\uFF08\u4F1A\u4E22\u6389\u672C\u5730\u6539\u52A8\uFF09\uFF0C\u6216 --dir <path> \u88C5\u5230\u522B\u5904\uFF1B\u53EA\u60F3\u8DDF\u4E0A\u4EA7\u54C1\u7248\u672C\u7528 hcm skills update`
6164
5305
  );
6165
5306
  }
@@ -6194,7 +5335,7 @@ async function sameOnDisk(baseDir, candidate) {
6194
5335
  return true;
6195
5336
  }
6196
5337
  async function readLocalReferences(skillDir) {
6197
- const root = path6.join(skillDir, "references");
5338
+ const root = path4.join(skillDir, "references");
6198
5339
  const out = [];
6199
5340
  const walk = async (dir, prefix) => {
6200
5341
  let items;
@@ -6207,12 +5348,12 @@ async function readLocalReferences(skillDir) {
6207
5348
  for (const item of items.sort((a, b) => a.name.localeCompare(b.name))) {
6208
5349
  const relative2 = prefix ? `${prefix}/${item.name}` : item.name;
6209
5350
  if (item.isDirectory()) {
6210
- await walk(path6.join(dir, item.name), relative2);
5351
+ await walk(path4.join(dir, item.name), relative2);
6211
5352
  continue;
6212
5353
  }
6213
5354
  if (!item.isFile()) continue;
6214
5355
  assertSafeReferencePath2(relative2);
6215
- out.push({ path: relative2, content: await fsp2.readFile(path6.join(dir, item.name), "utf8") });
5356
+ out.push({ path: relative2, content: await fsp2.readFile(path4.join(dir, item.name), "utf8") });
6216
5357
  }
6217
5358
  };
6218
5359
  await walk(root, "");
@@ -6228,7 +5369,7 @@ async function planStaleReferences(state, documents, baseDir) {
6228
5369
  if (fresh.has(relative2)) continue;
6229
5370
  const onDisk = await readInstalledReference(baseDir, document.id, relative2);
6230
5371
  if (onDisk === void 0) continue;
6231
- if (sha2564(onDisk) !== recordedSha) {
5372
+ if (sha2562(onDisk) !== recordedSha) {
6232
5373
  keptLocallyModified.push({ id: document.id, path: relative2 });
6233
5374
  continue;
6234
5375
  }
@@ -6243,15 +5384,15 @@ async function writeSkillDocuments(documents, baseDir, removals = []) {
6243
5384
  const removed = [];
6244
5385
  try {
6245
5386
  for (const document of documents) {
6246
- const target = path6.join(baseDir, document.id, "SKILL.md");
6247
- await fsp2.mkdir(path6.dirname(target), { recursive: true });
6248
- const temp = path6.join(path6.dirname(target), `.SKILL.md.${process.pid}.${Date.now()}.tmp`);
5387
+ const target = path4.join(baseDir, document.id, "SKILL.md");
5388
+ await fsp2.mkdir(path4.dirname(target), { recursive: true });
5389
+ const temp = path4.join(path4.dirname(target), `.SKILL.md.${process.pid}.${Date.now()}.tmp`);
6249
5390
  await fsp2.writeFile(temp, document.markdown, "utf8");
6250
5391
  staged.push({ temp, target });
6251
5392
  for (const reference of document.references ?? []) {
6252
5393
  assertSafeReferencePath2(reference.path);
6253
- const referenceTarget = path6.join(baseDir, document.id, "references", reference.path);
6254
- await fsp2.mkdir(path6.dirname(referenceTarget), { recursive: true });
5394
+ const referenceTarget = path4.join(baseDir, document.id, "references", reference.path);
5395
+ await fsp2.mkdir(path4.dirname(referenceTarget), { recursive: true });
6255
5396
  const referenceTemp = `${referenceTarget}.${process.pid}.${Date.now()}.tmp`;
6256
5397
  await fsp2.writeFile(referenceTemp, reference.content, "utf8");
6257
5398
  staged.push({ temp: referenceTemp, target: referenceTarget });
@@ -6259,7 +5400,7 @@ async function writeSkillDocuments(documents, baseDir, removals = []) {
6259
5400
  }
6260
5401
  for (const stale of removals) {
6261
5402
  assertSafeReferencePath2(stale.path);
6262
- const original = path6.join(baseDir, stale.id, "references", stale.path);
5403
+ const original = path4.join(baseDir, stale.id, "references", stale.path);
6263
5404
  const parked = `${original}.${process.pid}.${Date.now()}.removed`;
6264
5405
  await fsp2.rename(original, parked);
6265
5406
  removed.push({ parked, original });
@@ -6285,6 +5426,7 @@ async function recordInstalled(baseDir, documents, meta2) {
6285
5426
  if (meta2.base !== void 0) state.base = meta2.base;
6286
5427
  if (meta2.all) state.all = true;
6287
5428
  state.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
5429
+ state.runtime = { launch: await currentSkillsRuntimeLaunch() };
6288
5430
  for (const document of documents) {
6289
5431
  const previous = state.skills[document.id];
6290
5432
  state.skills[document.id] = {
@@ -6292,24 +5434,24 @@ async function recordInstalled(baseDir, documents, meta2) {
6292
5434
  // 🔴 两个键同值:`source` 留给旧 CLI 读(降级不炸),新代码只读 `sourceLocator`。
6293
5435
  sourceKind: document.sourceKind ?? previous?.sourceKind ?? "chiron",
6294
5436
  sourceLocator: document.source,
6295
- sha256: sha2564(document.markdown),
5437
+ sha256: sha2562(document.markdown),
6296
5438
  installedAt: meta2.keepInstalledAt?.has(document.id) && previous ? previous.installedAt : state.updatedAt,
6297
5439
  // 已经是直接安装的,不因为这次作为依赖被带进来就降级
6298
5440
  direct: meta2.directIds.has(document.id) || Boolean(previous?.direct),
6299
5441
  references: Object.fromEntries(
6300
- (document.references ?? []).map((reference) => [reference.path, sha2564(reference.content)])
5442
+ (document.references ?? []).map((reference) => [reference.path, sha2562(reference.content)])
6301
5443
  )
6302
5444
  };
6303
5445
  }
6304
5446
  await writeSkillsState(baseDir, state);
6305
5447
  return state;
6306
5448
  }
6307
- function invalid3(message) {
6308
- return new CliError18({ code: CliErrorCode17.INVALID_ARGUMENT, message });
5449
+ function invalid(message) {
5450
+ return new CliError16({ code: CliErrorCode15.INVALID_ARGUMENT, message });
6309
5451
  }
6310
5452
  async function readInstalled(baseDir, id) {
6311
5453
  try {
6312
- return await fsp2.readFile(path6.join(baseDir, id, "SKILL.md"), "utf8");
5454
+ return await fsp2.readFile(path4.join(baseDir, id, "SKILL.md"), "utf8");
6313
5455
  } catch (cause) {
6314
5456
  if (cause?.code === "ENOENT") return void 0;
6315
5457
  throw cause;
@@ -6317,7 +5459,7 @@ async function readInstalled(baseDir, id) {
6317
5459
  }
6318
5460
  async function readInstalledReference(baseDir, id, relative2) {
6319
5461
  try {
6320
- return await fsp2.readFile(path6.join(baseDir, id, "references", relative2), "utf8");
5462
+ return await fsp2.readFile(path4.join(baseDir, id, "references", relative2), "utf8");
6321
5463
  } catch (cause) {
6322
5464
  if (cause?.code === "ENOENT") return void 0;
6323
5465
  throw cause;
@@ -6377,7 +5519,7 @@ async function planSkillUpdate(options) {
6377
5519
  for (const id of chironNeeded) {
6378
5520
  if (!manifest2) continue;
6379
5521
  try {
6380
- for (const skill of resolveSkillInstallOrder2(manifest2, id)) {
5522
+ for (const skill of resolveSkillInstallOrder(manifest2, id)) {
6381
5523
  if (!closure.has(skill.id)) closure.set(skill.id, { kind: "chiron", skill });
6382
5524
  }
6383
5525
  } catch {
@@ -6403,12 +5545,12 @@ async function planSkillUpdate(options) {
6403
5545
  const remote = await fetch();
6404
5546
  const remoteReferences = remote.references ?? [];
6405
5547
  let differsFromRemote = remote.markdown !== onDisk;
6406
- let editedLocally = record !== void 0 && sha2564(onDisk) !== record.sha256;
5548
+ let editedLocally = record !== void 0 && sha2562(onDisk) !== record.sha256;
6407
5549
  for (const reference of remoteReferences) {
6408
5550
  const installed = await readInstalledReference(baseDir, id, reference.path);
6409
5551
  if (installed !== reference.content) differsFromRemote = true;
6410
5552
  const recordedSha = record?.references?.[reference.path];
6411
- if (installed !== void 0 && recordedSha && sha2564(installed) !== recordedSha) editedLocally = true;
5553
+ if (installed !== void 0 && recordedSha && sha2562(installed) !== recordedSha) editedLocally = true;
6412
5554
  }
6413
5555
  if (!differsFromRemote) {
6414
5556
  entries.push({ id, status: "unchanged" });
@@ -6449,9 +5591,9 @@ async function skillsUpdateCommand(args) {
6449
5591
  const layout = await resolveInstallLayout(args);
6450
5592
  const state = await readSkillsState(layout.baseDir);
6451
5593
  if (!state || Object.keys(state.skills).length === 0) {
6452
- throw new CliError18({
6453
- code: CliErrorCode17.INVALID_ARGUMENT,
6454
- message: `${path6.join(layout.baseDir, SKILLS_STATE_FILE)} \u4E0D\u5B58\u5728\u6216\u4E3A\u7A7A \u2014\u2014 \u8FD9\u4E2A\u76EE\u5F55\u4E0B\u8FD8\u6CA1\u6709\u7528\u672C CLI \u88C5\u8FC7\u6280\u80FD\u3002\u5148 \`hcm skills install <id>\`\uFF1B\u5982\u679C\u6280\u80FD\u662F\u624B\u5DE5\u62F7\u8FDB\u6765\u7684\uFF0C\u91CD\u88C5\u4E00\u6B21\u5373\u53EF\u63A5\u7BA1\u5347\u7EA7\u3002`
5594
+ throw new CliError16({
5595
+ code: CliErrorCode15.INVALID_ARGUMENT,
5596
+ message: `${path4.join(layout.baseDir, SKILLS_STATE_FILE)} \u4E0D\u5B58\u5728\u6216\u4E3A\u7A7A \u2014\u2014 \u8FD9\u4E2A\u76EE\u5F55\u4E0B\u8FD8\u6CA1\u6709\u7528\u672C CLI \u88C5\u8FC7\u6280\u80FD\u3002\u5148 \`hcm skills install <id>\`\uFF1B\u5982\u679C\u6280\u80FD\u662F\u624B\u5DE5\u62F7\u8FDB\u6765\u7684\uFF0C\u91CD\u88C5\u4E00\u6B21\u5373\u53EF\u63A5\u7BA1\u5347\u7EA7\u3002`
6455
5597
  });
6456
5598
  }
6457
5599
  const source = parseSourceFilter(args.source);
@@ -6581,8 +5723,8 @@ import {
6581
5723
  loadEnv as loadEnv6,
6582
5724
  loadGlobalConfig as loadGlobalConfig7,
6583
5725
  resolveActiveEnv as resolveActiveEnv4,
6584
- CliError as CliError19,
6585
- CliErrorCode as CliErrorCode18
5726
+ CliError as CliError17,
5727
+ CliErrorCode as CliErrorCode16
6586
5728
  } from "@hcmai/sdk";
6587
5729
  init_exit();
6588
5730
  async function resolveBootstrapKey(args, stdinTaken) {
@@ -6590,8 +5732,8 @@ async function resolveBootstrapKey(args, stdinTaken) {
6590
5732
  if (fromEnv) return fromEnv;
6591
5733
  if (args.bootstrapKeyStdin) {
6592
5734
  if (stdinTaken) {
6593
- throw new CliError19({
6594
- code: CliErrorCode18.INVALID_ARGUMENT,
5735
+ throw new CliError17({
5736
+ code: CliErrorCode16.INVALID_ARGUMENT,
6595
5737
  message: "--bootstrap-key-stdin \u4E0E --admin-password-stdin \u4E0D\u80FD\u540C\u65F6\u7528\uFF08stdin \u53EA\u6709\u4E00\u8DEF\uFF09\uFF1B\u628A\u5176\u4E2D\u4E00\u4E2A\u6539\u8D70 HCM_BOOTSTRAP_KEY \u73AF\u5883\u53D8\u91CF\u6216\u4EA4\u4E92\u8F93\u5165"
6596
5738
  });
6597
5739
  }
@@ -6621,8 +5763,8 @@ async function resolveEndpoint2(args) {
6621
5763
  const envName = resolveActiveEnv4({ envFlag: args.env }, process.env, g);
6622
5764
  const env2 = await loadEnv6(envName).catch(() => null);
6623
5765
  if (!env2?.endpoint) {
6624
- throw new CliError19({
6625
- code: CliErrorCode18.MISSING_FLAG,
5766
+ throw new CliError17({
5767
+ code: CliErrorCode16.MISSING_FLAG,
6626
5768
  message: "\u672A\u89E3\u6790\u5230 endpoint \u2014\u2014 \u4F20 --endpoint <url>\uFF0C\u6216\u5148 `hcm env add <name> --endpoint <url>`"
6627
5769
  });
6628
5770
  }
@@ -6631,8 +5773,8 @@ async function resolveEndpoint2(args) {
6631
5773
  async function tenantBootstrapCommand(args) {
6632
5774
  try {
6633
5775
  if (!args.tenantId || !args.adminUsername) {
6634
- throw new CliError19({
6635
- code: CliErrorCode18.MISSING_FLAG,
5776
+ throw new CliError17({
5777
+ code: CliErrorCode16.MISSING_FLAG,
6636
5778
  message: "--tenant-id \u4E0E --admin-username \u5FC5\u586B"
6637
5779
  });
6638
5780
  }
@@ -6654,7 +5796,7 @@ async function tenantBootstrapCommand(args) {
6654
5796
  onRefresh: async () => {
6655
5797
  }
6656
5798
  });
6657
- const result2 = await bootstrapTenant(http, key, {
5799
+ const result = await bootstrapTenant(http, key, {
6658
5800
  tenantId: args.tenantId,
6659
5801
  adminUsername: args.adminUsername,
6660
5802
  adminPassword: pwd,
@@ -6663,12 +5805,12 @@ async function tenantBootstrapCommand(args) {
6663
5805
  const fmt = args.output ?? "json";
6664
5806
  if (fmt !== "json") {
6665
5807
  process.stdout.write(
6666
- `\u2705 \u79DF\u6237 ${result2.tenantId} \u5DF2\u5F00\u901A\uFF08adminUserId ${result2.adminUserId ?? "-"}\uFF09
5808
+ `\u2705 \u79DF\u6237 ${result.tenantId} \u5DF2\u5F00\u901A\uFF08adminUserId ${result.adminUserId ?? "-"}\uFF09
6667
5809
  \u4E0B\u4E00\u6B65\uFF1Ahcm env add <name> --endpoint ${endpoint} && hcm login --env <name>
6668
5810
  `
6669
5811
  );
6670
5812
  }
6671
- process.stdout.write(formatObject15(result2, { format: fmt }) + "\n");
5813
+ process.stdout.write(formatObject15(result, { format: fmt }) + "\n");
6672
5814
  process.exit(0);
6673
5815
  } catch (e) {
6674
5816
  const err = e;
@@ -6692,8 +5834,8 @@ import {
6692
5834
  getTenantMeta,
6693
5835
  saveTenantMeta,
6694
5836
  deleteTenantMeta,
6695
- CliError as CliError20,
6696
- CliErrorCode as CliErrorCode19
5837
+ CliError as CliError18,
5838
+ CliErrorCode as CliErrorCode17
6697
5839
  } from "@hcmai/sdk";
6698
5840
  init_exit();
6699
5841
  init_auth_guard();
@@ -6729,21 +5871,21 @@ async function metaListCommand(args) {
6729
5871
  fail4(e, args);
6730
5872
  }
6731
5873
  }
6732
- async function metaGetCommand(path10, args) {
5874
+ async function metaGetCommand(path9, args) {
6733
5875
  try {
6734
5876
  const c = await client2(args);
6735
- const content = await getTenantMeta(c.raw(), path10);
5877
+ const content = await getTenantMeta(c.raw(), path9);
6736
5878
  process.stdout.write(content.endsWith("\n") ? content : content + "\n");
6737
5879
  process.exit(0);
6738
5880
  } catch (e) {
6739
5881
  fail4(e, args);
6740
5882
  }
6741
5883
  }
6742
- async function metaSetCommand(path10, args) {
5884
+ async function metaSetCommand(path9, args) {
6743
5885
  try {
6744
5886
  if (!args.file) {
6745
- throw new CliError20({
6746
- code: CliErrorCode19.MISSING_FLAG,
5887
+ throw new CliError18({
5888
+ code: CliErrorCode17.MISSING_FLAG,
6747
5889
  message: "--file <path> \u5FC5\u586B\uFF08\u4ECE\u6587\u4EF6\u8BFB\u53D6 meta \u539F\u6587\uFF1B\u7528 - \u8868\u793A stdin\uFF09"
6748
5890
  });
6749
5891
  }
@@ -6756,7 +5898,7 @@ async function metaSetCommand(path10, args) {
6756
5898
  }) : await fsp3.readFile(args.file, "utf8");
6757
5899
  if (args.dryRun) {
6758
5900
  process.stdout.write(
6759
- `[dry-run] \u5C06\u5199\u5165 ${path10}\uFF08${Buffer.byteLength(content)} B\uFF09\u2014\u2014\u672A\u5B9E\u9645\u5199\u5165
5901
+ `[dry-run] \u5C06\u5199\u5165 ${path9}\uFF08${Buffer.byteLength(content)} B\uFF09\u2014\u2014\u672A\u5B9E\u9645\u5199\u5165
6760
5902
  ---
6761
5903
  ${content}
6762
5904
  `
@@ -6764,35 +5906,35 @@ ${content}
6764
5906
  process.exit(0);
6765
5907
  }
6766
5908
  const c = await client2(args);
6767
- const result2 = await saveTenantMeta(c.raw(), path10, content);
5909
+ const result = await saveTenantMeta(c.raw(), path9, content);
6768
5910
  const fmt = args.output ?? "json";
6769
5911
  if (fmt !== "json") {
6770
- process.stdout.write(`\u2705 \u5DF2\u5199\u5165 ${path10}
5912
+ process.stdout.write(`\u2705 \u5DF2\u5199\u5165 ${path9}
6771
5913
  \u8BB0\u5F97\u6E05\u7F13\u5B58\uFF1Ahcm cache clear-meta <Model>
6772
5914
  `);
6773
5915
  }
6774
- process.stdout.write(formatObject16(result2, { format: fmt }) + "\n");
5916
+ process.stdout.write(formatObject16(result, { format: fmt }) + "\n");
6775
5917
  process.exit(0);
6776
5918
  } catch (e) {
6777
5919
  if (e?.code === "ENOENT") exitWithError(new Error(`\u6587\u4EF6\u4E0D\u5B58\u5728\uFF1A${args.file}`));
6778
5920
  fail4(e, args);
6779
5921
  }
6780
5922
  }
6781
- async function metaDeleteCommand(path10, args) {
5923
+ async function metaDeleteCommand(path9, args) {
6782
5924
  try {
6783
5925
  if (!args.yes) {
6784
- const ok = await promptConfirm(`\u5C06\u5220\u9664\u5143\u6570\u636E ${path10}\uFF0C\u6B64\u64CD\u4F5C\u4E0D\u53EF\u9006\u3002\u7EE7\u7EED\uFF1F`);
5926
+ const ok = await promptConfirm(`\u5C06\u5220\u9664\u5143\u6570\u636E ${path9}\uFF0C\u6B64\u64CD\u4F5C\u4E0D\u53EF\u9006\u3002\u7EE7\u7EED\uFF1F`);
6785
5927
  if (!ok) {
6786
5928
  process.stderr.write("\u5DF2\u53D6\u6D88\n");
6787
5929
  process.exit(1);
6788
5930
  }
6789
5931
  }
6790
5932
  const c = await client2(args);
6791
- const result2 = await deleteTenantMeta(c.raw(), path10);
5933
+ const result = await deleteTenantMeta(c.raw(), path9);
6792
5934
  const fmt = args.output ?? "json";
6793
- if (fmt !== "json") process.stdout.write(`\u{1F5D1}\uFE0F \u5DF2\u5220\u9664 ${path10}
5935
+ if (fmt !== "json") process.stdout.write(`\u{1F5D1}\uFE0F \u5DF2\u5220\u9664 ${path9}
6794
5936
  `);
6795
- process.stdout.write(formatObject16(result2, { format: fmt }) + "\n");
5937
+ process.stdout.write(formatObject16(result, { format: fmt }) + "\n");
6796
5938
  process.exit(0);
6797
5939
  } catch (e) {
6798
5940
  fail4(e, args);
@@ -6803,8 +5945,8 @@ async function metaDeleteCommand(path10, args) {
6803
5945
  init_exit();
6804
5946
  init_auth_guard();
6805
5947
  import * as crypto from "crypto";
6806
- import * as fs7 from "fs/promises";
6807
- import * as path7 from "path";
5948
+ import * as fs5 from "fs/promises";
5949
+ import * as path5 from "path";
6808
5950
  import {
6809
5951
  buildMiniPreviewTargets,
6810
5952
  buildMiniVerifyAgentReport,
@@ -6873,7 +6015,7 @@ async function workspaceListCommand(args) {
6873
6015
  try {
6874
6016
  const client3 = HcmClient16.fromAuthContext(await getActiveAuthContextFromCli(args));
6875
6017
  const limit = parsePositiveInt3(args.limit, 50, "--limit");
6876
- const result2 = await client3.query("TenantExtensionWorkspace", {
6018
+ const result = await client3.query("TenantExtensionWorkspace", {
6877
6019
  keyword: args.keyword,
6878
6020
  fields: [
6879
6021
  "workspaceKey",
@@ -6888,7 +6030,7 @@ async function workspaceListCommand(args) {
6888
6030
  sort: [{ field: "devModeEnabled", desc: true }, { field: "updateTime", desc: true }],
6889
6031
  limit
6890
6032
  });
6891
- writeWorkspaceListResult(result2.rows, args.output ?? "table", result2.total);
6033
+ writeWorkspaceListResult(result.rows, args.output ?? "table", result.total);
6892
6034
  process.exit(0);
6893
6035
  } catch (e) {
6894
6036
  exitWorkspaceError(e, args.env ?? args.profile);
@@ -6902,12 +6044,12 @@ async function workspaceActiveCommand(args) {
6902
6044
  fallbackEnv: localContext?.profile
6903
6045
  });
6904
6046
  const client3 = HcmClient16.fromAuthContext(ctx);
6905
- const result2 = await client3.query("TenantExtensionWorkspace", {
6047
+ const result = await client3.query("TenantExtensionWorkspace", {
6906
6048
  filter: { devModeEnabled: true },
6907
6049
  fields: ["workspaceKey", "devModeEnabled"],
6908
6050
  limit: 1
6909
6051
  });
6910
- const activeWorkspaceKey = optionalText(result2.rows[0]?.workspaceKey) ?? null;
6052
+ const activeWorkspaceKey = optionalText(result.rows[0]?.workspaceKey) ?? null;
6911
6053
  const view = {
6912
6054
  activeWorkspaceKey,
6913
6055
  localWorkspaceKey: localContext?.workspaceKey ?? null,
@@ -6939,7 +6081,7 @@ async function workspaceBindCommand(workspaceKey, args) {
6939
6081
  tenantId: args.tenant ?? client3?.tenantId,
6940
6082
  endpoint: args.endpoint ?? client3?.endpoint
6941
6083
  });
6942
- await fs7.mkdir(rootDir, { recursive: true });
6084
+ await fs5.mkdir(rootDir, { recursive: true });
6943
6085
  await writeWorkspaceContext(rootDir, context);
6944
6086
  writeWorkspaceBindResult(context, rootDir, args.output ?? "table");
6945
6087
  process.exit(0);
@@ -6974,7 +6116,7 @@ async function workspaceCreateCommand(workspaceKey, args) {
6974
6116
  tenantId: client3.tenantId,
6975
6117
  endpoint: client3.endpoint
6976
6118
  });
6977
- await fs7.mkdir(rootDir, { recursive: true });
6119
+ await fs5.mkdir(rootDir, { recursive: true });
6978
6120
  await writeWorkspaceContext(rootDir, context);
6979
6121
  writeWorkspaceCreateResult(
6980
6122
  {
@@ -7011,23 +6153,23 @@ async function workspacePullCommand(args) {
7011
6153
  tenantId: client3.tenantId ?? existing?.tenantId,
7012
6154
  endpoint: client3.endpoint ?? existing?.endpoint
7013
6155
  });
7014
- await fs7.mkdir(rootDir, { recursive: true });
6156
+ await fs5.mkdir(rootDir, { recursive: true });
7015
6157
  await writeWorkspaceContext(rootDir, context);
7016
6158
  const files = await listWorkspaceFiles(client3.raw(), workspaceKey, { pageSize: 5e3 });
7017
6159
  const miniApps = detectRemoteMiniApps(files.data);
7018
6160
  const pulledMiniApps = [];
7019
6161
  for (const appCode of miniApps) {
7020
- const result2 = await pullMiniAppProject({
6162
+ const result = await pullMiniAppProject({
7021
6163
  http: client3.raw(),
7022
6164
  appCode,
7023
6165
  workspaceKey,
7024
- targetDir: path7.join(rootDir, MINI_APPS_DIR, appCode),
6166
+ targetDir: path5.join(rootDir, MINI_APPS_DIR, appCode),
7025
6167
  tenantId: client3.tenantId,
7026
6168
  endpoint: client3.endpoint,
7027
6169
  profile: args.profile ?? client3.profile,
7028
6170
  force: !!args.force
7029
6171
  });
7030
- pulledMiniApps.push(result2);
6172
+ pulledMiniApps.push(result);
7031
6173
  }
7032
6174
  const rawFiles = files.data.filter(
7033
6175
  (file) => !isDirectoryMarker(file.relativePath) && !isMiniAppPath(file.relativePath)
@@ -7036,7 +6178,7 @@ async function workspacePullCommand(args) {
7036
6178
  const rawRemoteByLocalPath = /* @__PURE__ */ new Map();
7037
6179
  for (const file of rawFiles) {
7038
6180
  const content = await loadWorkspaceFileContent(client3.raw(), file.id);
7039
- const target = path7.join(rootDir, content.relativePath);
6181
+ const target = path5.join(rootDir, content.relativePath);
7040
6182
  await writeTextFile(target, content.content, !!args.force);
7041
6183
  pulledRawFiles.push(content.relativePath);
7042
6184
  rawRemoteByLocalPath.set(content.relativePath, file);
@@ -7083,10 +6225,10 @@ async function workspaceAddMiniCommand(appCode, args) {
7083
6225
  fields: args.fields,
7084
6226
  defaults: args.defaults
7085
6227
  });
7086
- const result2 = await initMiniAppProject({
6228
+ const result = await initMiniAppProject({
7087
6229
  appCode,
7088
6230
  workspaceKey: context.workspaceKey,
7089
- targetDir: path7.join(rootDir, MINI_APPS_DIR, appCode),
6231
+ targetDir: path5.join(rootDir, MINI_APPS_DIR, appCode),
7090
6232
  name: args.name,
7091
6233
  defaultSurface: parseSurface(args.surface),
7092
6234
  templateKind,
@@ -7100,7 +6242,7 @@ async function workspaceAddMiniCommand(appCode, args) {
7100
6242
  profile: args.env ?? args.profile ?? client3?.profile ?? context.profile,
7101
6243
  force: !!args.force
7102
6244
  });
7103
- writeWorkspaceAddMiniResult(result2, rootDir, args.output ?? "table");
6245
+ writeWorkspaceAddMiniResult(result, rootDir, args.output ?? "table");
7104
6246
  process.exit(0);
7105
6247
  } catch (e) {
7106
6248
  exitWorkspaceError(e, args.env ?? args.profile);
@@ -7180,12 +6322,12 @@ async function workspacePushCommand(args) {
7180
6322
  });
7181
6323
  const results = [];
7182
6324
  for (const app of miniApps) {
7183
- const result2 = await pushMiniAppProject({
6325
+ const result = await pushMiniAppProject({
7184
6326
  http: client3.raw(),
7185
6327
  rootDir: app.dir,
7186
6328
  dryRun: !!args.dryRun
7187
6329
  });
7188
- results.push({ app, result: result2 });
6330
+ results.push({ app, result });
7189
6331
  }
7190
6332
  writeWorkspacePushResult(rawResult, results, args.output ?? "table");
7191
6333
  process.exit(
@@ -7327,7 +6469,7 @@ function removedMiniCommand() {
7327
6469
  );
7328
6470
  }
7329
6471
  function resolveRootDir(dir) {
7330
- return path7.resolve(dir ?? ".");
6472
+ return path5.resolve(dir ?? ".");
7331
6473
  }
7332
6474
  function buildWorkspaceContext(args) {
7333
6475
  return {
@@ -7343,7 +6485,7 @@ function buildWorkspaceContext(args) {
7343
6485
  async function readWorkspaceContext(rootDir) {
7344
6486
  try {
7345
6487
  const parsed = JSON.parse(
7346
- await fs7.readFile(path7.join(rootDir, WORKSPACE_CONTEXT_FILE), "utf-8")
6488
+ await fs5.readFile(path5.join(rootDir, WORKSPACE_CONTEXT_FILE), "utf-8")
7347
6489
  );
7348
6490
  if (parsed.kind !== WORKSPACE_CONTEXT_KIND || parsed.version !== WORKSPACE_CONTEXT_VERSION) {
7349
6491
  throw new Error(`${WORKSPACE_CONTEXT_FILE} is not an HCM workspace context`);
@@ -7372,25 +6514,25 @@ async function requireWorkspaceContext(rootDir) {
7372
6514
  return context;
7373
6515
  }
7374
6516
  async function writeWorkspaceContext(rootDir, context) {
7375
- await fs7.writeFile(
7376
- path7.join(rootDir, WORKSPACE_CONTEXT_FILE),
6517
+ await fs5.writeFile(
6518
+ path5.join(rootDir, WORKSPACE_CONTEXT_FILE),
7377
6519
  JSON.stringify(context, null, 2) + "\n"
7378
6520
  );
7379
6521
  }
7380
6522
  async function writeTextFile(file, content, force) {
7381
6523
  try {
7382
- await fs7.access(file);
6524
+ await fs5.access(file);
7383
6525
  if (!force) throw new Error(`${file} already exists; use --force to overwrite`);
7384
6526
  } catch (e) {
7385
6527
  if (e.code !== "ENOENT") throw e;
7386
6528
  }
7387
- await fs7.mkdir(path7.dirname(file), { recursive: true });
7388
- await fs7.writeFile(file, content);
6529
+ await fs5.mkdir(path5.dirname(file), { recursive: true });
6530
+ await fs5.writeFile(file, content);
7389
6531
  }
7390
6532
  async function readWorkspaceRawManifest(rootDir, context) {
7391
6533
  try {
7392
6534
  const parsed = JSON.parse(
7393
- await fs7.readFile(path7.join(rootDir, WORKSPACE_STATE_DIR, WORKSPACE_PULL_MANIFEST_FILE), "utf-8")
6535
+ await fs5.readFile(path5.join(rootDir, WORKSPACE_STATE_DIR, WORKSPACE_PULL_MANIFEST_FILE), "utf-8")
7394
6536
  );
7395
6537
  if (parsed.version !== WORKSPACE_CONTEXT_VERSION || parsed.workspaceKey !== context.workspaceKey) {
7396
6538
  throw new Error(`${WORKSPACE_PULL_MANIFEST_FILE} does not match workspace ${context.workspaceKey}`);
@@ -7408,8 +6550,8 @@ async function readWorkspaceRawManifest(rootDir, context) {
7408
6550
  }
7409
6551
  }
7410
6552
  async function writeWorkspaceRawState(rootDir, context, files, remoteByLocalPath) {
7411
- const stateDir = path7.join(rootDir, WORKSPACE_STATE_DIR);
7412
- await fs7.mkdir(stateDir, { recursive: true });
6553
+ const stateDir = path5.join(rootDir, WORKSPACE_STATE_DIR);
6554
+ await fs5.mkdir(stateDir, { recursive: true });
7413
6555
  const snapshots = files.map((file) => ({
7414
6556
  localPath: file.localPath,
7415
6557
  remotePath: file.localPath,
@@ -7418,8 +6560,8 @@ async function writeWorkspaceRawState(rootDir, context, files, remoteByLocalPath
7418
6560
  size: file.size,
7419
6561
  lastModified: remoteByLocalPath.get(file.localPath)?.lastModified
7420
6562
  }));
7421
- await fs7.writeFile(
7422
- path7.join(stateDir, WORKSPACE_PULL_MANIFEST_FILE),
6563
+ await fs5.writeFile(
6564
+ path5.join(stateDir, WORKSPACE_PULL_MANIFEST_FILE),
7423
6565
  JSON.stringify(
7424
6566
  {
7425
6567
  version: WORKSPACE_CONTEXT_VERSION,
@@ -7441,10 +6583,10 @@ async function readWorkspaceRawLocalFiles(rootDir) {
7441
6583
  return files;
7442
6584
  }
7443
6585
  async function walkWorkspaceRawFiles(rootDir, relativeDir, files) {
7444
- const absoluteDir = path7.join(rootDir, relativeDir);
6586
+ const absoluteDir = path5.join(rootDir, relativeDir);
7445
6587
  let entries;
7446
6588
  try {
7447
- entries = await fs7.readdir(absoluteDir, { withFileTypes: true });
6589
+ entries = await fs5.readdir(absoluteDir, { withFileTypes: true });
7448
6590
  } catch (e) {
7449
6591
  if (e.code === "ENOENT") return;
7450
6592
  throw e;
@@ -7452,19 +6594,19 @@ async function walkWorkspaceRawFiles(rootDir, relativeDir, files) {
7452
6594
  for (const entry of entries) {
7453
6595
  if (entry.isDirectory() && RAW_WORKSPACE_EXCLUDED_DIRS.has(entry.name)) continue;
7454
6596
  if (entry.isFile() && RAW_WORKSPACE_EXCLUDED_FILES.has(entry.name)) continue;
7455
- const localPath = normalizeRelativePath(path7.posix.join(toPosix(relativeDir), entry.name));
7456
- const absolutePath = path7.join(rootDir, localPath);
6597
+ const localPath = normalizeRelativePath(path5.posix.join(toPosix(relativeDir), entry.name));
6598
+ const absolutePath = path5.join(rootDir, localPath);
7457
6599
  if (entry.isDirectory()) {
7458
6600
  await walkWorkspaceRawFiles(rootDir, localPath, files);
7459
6601
  continue;
7460
6602
  }
7461
6603
  if (!entry.isFile()) continue;
7462
- const content = await fs7.readFile(absolutePath, "utf-8");
6604
+ const content = await fs5.readFile(absolutePath, "utf-8");
7463
6605
  files.push({
7464
6606
  localPath,
7465
6607
  absolutePath,
7466
6608
  content,
7467
- sha256: sha2565(content),
6609
+ sha256: sha2563(content),
7468
6610
  size: Buffer.byteLength(content, "utf-8")
7469
6611
  });
7470
6612
  }
@@ -7478,13 +6620,13 @@ async function pushWorkspaceRawFiles(args) {
7478
6620
  const localFiles = await readWorkspaceRawLocalFiles(args.rootDir);
7479
6621
  const remoteFiles = await loadWorkspaceRawRemoteFiles(args.http, args.context.workspaceKey);
7480
6622
  const plan = buildWorkspaceRawPushPlan(manifest2, localFiles, remoteFiles);
7481
- const result2 = {
6623
+ const result = {
7482
6624
  workspaceKey: args.context.workspaceKey,
7483
6625
  dryRun: args.dryRun,
7484
6626
  operations: plan.operations,
7485
6627
  conflicts: plan.conflicts
7486
6628
  };
7487
- if (args.dryRun || plan.conflicts.length) return result2;
6629
+ if (args.dryRun || plan.conflicts.length) return result;
7488
6630
  const localByPath = new Map(localFiles.map((file) => [file.localPath, file]));
7489
6631
  for (const operation of plan.operations) {
7490
6632
  if (operation.operation === "skip") continue;
@@ -7510,17 +6652,17 @@ async function pushWorkspaceRawFiles(args) {
7510
6652
  const latestRemoteFiles = await loadWorkspaceRawRemoteFiles(args.http, args.context.workspaceKey);
7511
6653
  const latestRemoteByLocalPath = new Map(latestRemoteFiles.map((file) => [file.item.relativePath, file.item]));
7512
6654
  await writeWorkspaceRawState(args.rootDir, args.context, localFiles, latestRemoteByLocalPath);
7513
- return result2;
6655
+ return result;
7514
6656
  }
7515
6657
  async function loadWorkspaceRawRemoteFiles(http, workspaceKey) {
7516
6658
  const list = await listWorkspaceFiles(http, workspaceKey, { pageSize: 5e3 });
7517
- const result2 = [];
6659
+ const result = [];
7518
6660
  for (const item of list.data) {
7519
6661
  if (isDirectoryMarker(item.relativePath) || isMiniAppPath(item.relativePath)) continue;
7520
6662
  const content = await loadWorkspaceFileContent(http, item.id);
7521
- result2.push({ item, content: content.content });
6663
+ result.push({ item, content: content.content });
7522
6664
  }
7523
- return result2;
6665
+ return result;
7524
6666
  }
7525
6667
  function buildWorkspaceRawPushPlan(manifest2, localFiles, remoteFiles) {
7526
6668
  const status = computeWorkspaceRawStatus(manifest2, localFiles);
@@ -7531,7 +6673,7 @@ function buildWorkspaceRawPushPlan(manifest2, localFiles, remoteFiles) {
7531
6673
  for (const entry of status) {
7532
6674
  const remote = remoteByLocal.get(entry.localPath);
7533
6675
  const base = baseByLocal.get(entry.localPath);
7534
- const remoteSha = remote ? sha2565(remote.content) : void 0;
6676
+ const remoteSha = remote ? sha2563(remote.content) : void 0;
7535
6677
  if (entry.status === "added") {
7536
6678
  if (remote) {
7537
6679
  conflicts.push(workspaceRawConflict(entry, "remote file already exists but was not in local snapshot"));
@@ -7633,15 +6775,15 @@ function workspaceRawConflict(entry, reason) {
7633
6775
  };
7634
6776
  }
7635
6777
  async function discoverMiniApps(rootDir) {
7636
- const appsRoot = path7.join(rootDir, MINI_APPS_DIR);
6778
+ const appsRoot = path5.join(rootDir, MINI_APPS_DIR);
7637
6779
  let entries;
7638
6780
  try {
7639
- entries = await fs7.readdir(appsRoot, { withFileTypes: true });
6781
+ entries = await fs5.readdir(appsRoot, { withFileTypes: true });
7640
6782
  } catch (e) {
7641
6783
  if (e.code === "ENOENT") return [];
7642
6784
  throw e;
7643
6785
  }
7644
- return entries.filter((entry) => entry.isDirectory()).map((entry) => ({ appCode: entry.name, dir: path7.join(appsRoot, entry.name) })).sort((a, b) => a.appCode.localeCompare(b.appCode));
6786
+ return entries.filter((entry) => entry.isDirectory()).map((entry) => ({ appCode: entry.name, dir: path5.join(appsRoot, entry.name) })).sort((a, b) => a.appCode.localeCompare(b.appCode));
7645
6787
  }
7646
6788
  function detectRemoteMiniApps(files) {
7647
6789
  const appCodes = /* @__PURE__ */ new Set();
@@ -7794,9 +6936,9 @@ function normalizeRelativePath(value) {
7794
6936
  return normalized;
7795
6937
  }
7796
6938
  function toPosix(value) {
7797
- return value.split(path7.sep).join("/");
6939
+ return value.split(path5.sep).join("/");
7798
6940
  }
7799
- function sha2565(content) {
6941
+ function sha2563(content) {
7800
6942
  return crypto.createHash("sha256").update(content, "utf-8").digest("hex");
7801
6943
  }
7802
6944
  function stringRequired(value, field) {
@@ -7863,52 +7005,52 @@ function writeWorkspaceBindResult(context, rootDir, format) {
7863
7005
  ].join("\n") + "\n"
7864
7006
  );
7865
7007
  }
7866
- function writeWorkspaceCreateResult(result2, format) {
7008
+ function writeWorkspaceCreateResult(result, format) {
7867
7009
  if (format !== "table") {
7868
- process.stdout.write(formatObject17(result2, { format }) + "\n");
7010
+ process.stdout.write(formatObject17(result, { format }) + "\n");
7869
7011
  return;
7870
7012
  }
7871
7013
  process.stdout.write(
7872
7014
  [
7873
- `workspace created: ${result2.workspaceKey}`,
7874
- `id: ${result2.id}`,
7875
- `directory: ${result2.rootDir}`,
7876
- `profile: ${result2.profile}`,
7877
- `tenant: ${result2.tenantId}`,
7878
- `activated: ${result2.activated ? "yes" : "no"}`
7015
+ `workspace created: ${result.workspaceKey}`,
7016
+ `id: ${result.id}`,
7017
+ `directory: ${result.rootDir}`,
7018
+ `profile: ${result.profile}`,
7019
+ `tenant: ${result.tenantId}`,
7020
+ `activated: ${result.activated ? "yes" : "no"}`
7879
7021
  ].join("\n") + "\n"
7880
7022
  );
7881
7023
  }
7882
- function writeWorkspacePullResult(result2, format) {
7024
+ function writeWorkspacePullResult(result, format) {
7883
7025
  if (format !== "table") {
7884
- process.stdout.write(formatObject17(result2, { format }) + "\n");
7026
+ process.stdout.write(formatObject17(result, { format }) + "\n");
7885
7027
  return;
7886
7028
  }
7887
7029
  const lines = [
7888
- `workspace pulled: ${result2.workspaceKey}`,
7889
- `directory: ${result2.rootDir}`,
7890
- `remote files: ${result2.totalRemoteFiles}`,
7891
- `mini apps: ${result2.miniApps.length}`,
7892
- `raw files: ${result2.rawFiles.length}`
7030
+ `workspace pulled: ${result.workspaceKey}`,
7031
+ `directory: ${result.rootDir}`,
7032
+ `remote files: ${result.totalRemoteFiles}`,
7033
+ `mini apps: ${result.miniApps.length}`,
7034
+ `raw files: ${result.rawFiles.length}`
7893
7035
  ];
7894
- if (result2.miniApps.length) {
7036
+ if (result.miniApps.length) {
7895
7037
  lines.push("mini artifacts:");
7896
- for (const app of result2.miniApps) lines.push(` - ${app.appCode}: ${app.files} files`);
7038
+ for (const app of result.miniApps) lines.push(` - ${app.appCode}: ${app.files} files`);
7897
7039
  }
7898
7040
  process.stdout.write(lines.join("\n") + "\n");
7899
7041
  }
7900
- function writeWorkspaceAddMiniResult(result2, rootDir, format) {
7042
+ function writeWorkspaceAddMiniResult(result, rootDir, format) {
7901
7043
  if (format !== "table") {
7902
- process.stdout.write(formatObject17({ ...result2, workspaceRoot: rootDir }, { format }) + "\n");
7044
+ process.stdout.write(formatObject17({ ...result, workspaceRoot: rootDir }, { format }) + "\n");
7903
7045
  return;
7904
7046
  }
7905
7047
  process.stdout.write(
7906
7048
  [
7907
- `workspace artifact added: mini:${result2.appCode}`,
7908
- `workspace: ${result2.workspaceKey}`,
7049
+ `workspace artifact added: mini:${result.appCode}`,
7050
+ `workspace: ${result.workspaceKey}`,
7909
7051
  `workspace root: ${rootDir}`,
7910
- `directory: ${result2.targetDir}`,
7911
- `files: ${result2.files.length}`
7052
+ `directory: ${result.targetDir}`,
7053
+ `files: ${result.files.length}`
7912
7054
  ].join("\n") + "\n"
7913
7055
  );
7914
7056
  }
@@ -8093,8 +7235,8 @@ import {
8093
7235
  deleteIdentity as deleteIdentity2,
8094
7236
  loadGlobalConfig as loadGlobalConfig8,
8095
7237
  TokenStore as TokenStore3,
8096
- CliError as CliError21,
8097
- CliErrorCode as CliErrorCode20
7238
+ CliError as CliError19,
7239
+ CliErrorCode as CliErrorCode18
8098
7240
  } from "@hcmai/sdk";
8099
7241
  async function identityList(args) {
8100
7242
  try {
@@ -8122,8 +7264,8 @@ async function identityUse(name) {
8122
7264
  try {
8123
7265
  const meta2 = await loadIdentity4(name);
8124
7266
  const env2 = await loadEnv7(meta2.env).catch(() => {
8125
- throw new CliError21({
8126
- code: CliErrorCode20.IDENTITY_NOT_IN_ENV,
7267
+ throw new CliError19({
7268
+ code: CliErrorCode18.IDENTITY_NOT_IN_ENV,
8127
7269
  message: `identity '${name}' references env '${meta2.env}' which no longer exists. Re-create the env, or remove this orphan: hcm identity remove ${name}`
8128
7270
  });
8129
7271
  });
@@ -8165,7 +7307,7 @@ import {
8165
7307
  } from "@hcmai/sdk";
8166
7308
 
8167
7309
  // src/commands/delivery.ts
8168
- import { createHash as createHash6 } from "crypto";
7310
+ import { createHash as createHash4 } from "crypto";
8169
7311
  var APPROVAL_BYPASS_FLAGS = /* @__PURE__ */ new Set(["-y", "--yes", "--force", "--auto-approve"]);
8170
7312
  var CREDENTIAL_FLAGS = /* @__PURE__ */ new Set([
8171
7313
  "--password",
@@ -8187,7 +7329,7 @@ var GUARDED_EXECUTOR_REASON_CODES = /* @__PURE__ */ new Set([
8187
7329
  ]);
8188
7330
  function assessDeliveryCommand(inputArgv, options = {}) {
8189
7331
  const argv = inputArgv[0] === "--" ? inputArgv.slice(1) : [...inputArgv];
8190
- const commandSha256 = sha2566(JSON.stringify(argv));
7332
+ const commandSha256 = sha2564(JSON.stringify(argv));
8191
7333
  const name = argv[0] ?? "";
8192
7334
  const subcommand = argv[1] && !argv[1].startsWith("-") ? argv[1] : void 0;
8193
7335
  const envAlias = flagValue(argv, "--env");
@@ -8218,7 +7360,7 @@ function assessDeliveryCommand(inputArgv, options = {}) {
8218
7360
  return {
8219
7361
  schemaVersion: 1,
8220
7362
  contractVersion: "2026-08-29",
8221
- assessmentId: sha2566(`2026-08-29
7363
+ assessmentId: sha2564(`2026-08-29
8222
7364
  ${commandSha256}`).slice(0, 24),
8223
7365
  commandSha256,
8224
7366
  command: { name: name || "(empty)", ...subcommand ? { subcommand } : {} },
@@ -8390,17 +7532,17 @@ function summarizeTarget(argv, actionResolution) {
8390
7532
  }
8391
7533
  const id = flagValue(argv, "--id");
8392
7534
  if (name === "user" && subcommand === "reset-password") {
8393
- if (id) target.userIdSha256 = sha2566(id);
7535
+ if (id) target.userIdSha256 = sha2564(id);
8394
7536
  const username = flagValue(argv, "--username");
8395
- if (username) target.usernameSha256 = sha2566(username);
7537
+ if (username) target.usernameSha256 = sha2564(username);
8396
7538
  target.forceChangeOnNextLogin = !hasFlag(argv, "--no-force-change");
8397
7539
  } else if (id) {
8398
- target.recordIdSha256 = sha2566(id);
7540
+ target.recordIdSha256 = sha2564(id);
8399
7541
  }
8400
7542
  for (const flag of PAYLOAD_FLAGS) {
8401
7543
  const raw = flagValue(argv, flag);
8402
7544
  if (!raw) continue;
8403
- target.payloadSha256 = sha2566(raw);
7545
+ target.payloadSha256 = sha2564(raw);
8404
7546
  try {
8405
7547
  const parsed = JSON.parse(raw);
8406
7548
  if (isPlainObject(parsed)) target.fieldNames = Object.keys(parsed).sort();
@@ -8497,8 +7639,8 @@ function valuesAfterFlag(argv, flag) {
8497
7639
  }
8498
7640
  return values;
8499
7641
  }
8500
- function sha2566(value) {
8501
- return createHash6("sha256").update(value).digest("hex");
7642
+ function sha2564(value) {
7643
+ return createHash4("sha256").update(value).digest("hex");
8502
7644
  }
8503
7645
  function isPlainObject(value) {
8504
7646
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -8683,11 +7825,11 @@ async function deliveryReconCommand(args) {
8683
7825
  async function deliveryReconRoundCommand(args) {
8684
7826
  let code;
8685
7827
  try {
8686
- const result2 = inspectRound(args.dir ?? ".");
7828
+ const result = inspectRound(args.dir ?? ".");
8687
7829
  const fmt = args.output ?? "json";
8688
- if (fmt !== "json") process.stdout.write(renderRound(result2));
8689
- process.stdout.write(formatObject20(result2, { format: fmt }) + "\n");
8690
- code = ROUND_EXIT_CODES[result2.state];
7830
+ if (fmt !== "json") process.stdout.write(renderRound(result));
7831
+ process.stdout.write(formatObject20(result, { format: fmt }) + "\n");
7832
+ code = ROUND_EXIT_CODES[result.state];
8691
7833
  } catch (e) {
8692
7834
  exitWithError(e);
8693
7835
  code = 1;
@@ -8708,20 +7850,20 @@ import {
8708
7850
  loadProtocolFacts,
8709
7851
  scan
8710
7852
  } from "@hcmai/sdk";
8711
- import * as path8 from "path";
8712
- function renderGate0(result2, skillRoot) {
8713
- const where = skillRoot ? `\uFF08${path8.resolve(skillRoot)}\uFF09` : "";
7853
+ import * as path6 from "path";
7854
+ function renderGate0(result, skillRoot) {
7855
+ const where = skillRoot ? `\uFF08${path6.resolve(skillRoot)}\uFF09` : "";
8714
7856
  const lines = [
8715
- `\u626B\u63CF\u9762${where}\uFF1A${result2.scanned.length} \u4E2A\u6587\u4EF6\uFF1B\u5224\u7EA2 ${result2.red.length} \u6761\uFF1B\u7F3A\u53E3\u653E\u884C ${result2.gaps.length} \u6761\u3002`
7857
+ `\u626B\u63CF\u9762${where}\uFF1A${result.scanned.length} \u4E2A\u6587\u4EF6\uFF1B\u5224\u7EA2 ${result.red.length} \u6761\uFF1B\u7F3A\u53E3\u653E\u884C ${result.gaps.length} \u6761\u3002`
8716
7858
  ];
8717
7859
  for (const channel of CHANNELS) {
8718
- const rows = result2.channels[channel];
7860
+ const rows = result.channels[channel];
8719
7861
  lines.push(` [${channel}] ${rows.length} \u6761`);
8720
7862
  for (const red of rows) lines.push(` - (${red.reason}) ${red.message}`);
8721
7863
  }
8722
- if (result2.gaps.length > 0) {
8723
- lines.push(` [gaps] ${result2.gaps.length} \u6761\uFF08\u4E0D\u9876 rc\uFF0C\u8BF7\u81EA\u5DF1\u770B\u4E00\u773C\uFF09`);
8724
- for (const gap of result2.gaps) lines.push(` - (${gap.reason}) ${gap.why}`);
7864
+ if (result.gaps.length > 0) {
7865
+ lines.push(` [gaps] ${result.gaps.length} \u6761\uFF08\u4E0D\u9876 rc\uFF0C\u8BF7\u81EA\u5DF1\u770B\u4E00\u773C\uFF09`);
7866
+ for (const gap of result.gaps) lines.push(` - (${gap.reason}) ${gap.why}`);
8725
7867
  }
8726
7868
  return `${lines.join("\n")}
8727
7869
  `;
@@ -8733,17 +7875,17 @@ async function deliveryGate0Command(args) {
8733
7875
  const reconDir = args.recon ?? ".";
8734
7876
  const { aclass, problems: aclassProblems } = deriveAclass(reconDir, args.mapping ?? null);
8735
7877
  const { facts, problems: factsProblems } = loadProtocolFacts();
8736
- const result2 = scan(skillRoot, aclass, facts, { aclassProblems, factsProblems });
8737
- const premise = checkPremise([
8738
- ...result2.premise,
7878
+ const result = scan(skillRoot, aclass, facts, { aclassProblems, factsProblems });
7879
+ const premise2 = checkPremise([
7880
+ ...result.premise,
8739
7881
  ...baselineRoundPremise(inspectRound2(reconDir))
8740
7882
  ]);
8741
- const merged = { ...result2, premise };
7883
+ const merged = { ...result, premise: premise2 };
8742
7884
  const fmt = args.output ?? "json";
8743
7885
  if (fmt !== "json") process.stdout.write(renderGate0(merged, skillRoot));
8744
7886
  process.stdout.write(`${formatObject21(merged, { format: fmt })}
8745
7887
  `);
8746
- for (const problem of premise) {
7888
+ for (const problem of premise2) {
8747
7889
  process.stderr.write(`\u{1F534} \u524D\u63D0\u4E0D\u6210\u7ACB\uFF08${problem.reason}\uFF09\uFF1A${problem.message}
8748
7890
  `);
8749
7891
  }
@@ -8755,14 +7897,99 @@ async function deliveryGate0Command(args) {
8755
7897
  process.exit(code);
8756
7898
  }
8757
7899
 
7900
+ // src/commands/delivery-triage.ts
7901
+ init_auth_guard();
7902
+ init_exit();
7903
+ import {
7904
+ computeReconSourceKey as computeReconSourceKey2,
7905
+ HcmClient as HcmClient20,
7906
+ httpProbe as httpProbe3,
7907
+ ReconLayout as ReconLayout2,
7908
+ runTriageRound
7909
+ } from "@hcmai/sdk";
7910
+ import { mkdirSync, readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "fs";
7911
+ import * as path7 from "path";
7912
+ var DEFAULT_CAPABILITIES3 = "default";
7913
+ function premise(message, hint) {
7914
+ process.stderr.write(`\u{1F534} \u524D\u63D0\u4E0D\u6210\u7ACB\uFF1A${message}
7915
+ `);
7916
+ process.stderr.write(` ${hint}
7917
+ `);
7918
+ return 1;
7919
+ }
7920
+ var REQUESTS_SHAPE = "`--requests` \u6536\u7684\u662F\u4E00\u4E2A JSON \u6570\u7EC4\uFF0C\u6BCF\u6761\u81F3\u5C11\u8981\u6709 `request` / `verdict` / `evidence` \u4E09\u683C\u3002\u516D\u683C\u6838\u67E5\u8868\u7531\u672C\u547D\u4EE4\u81EA\u5DF1\u586B\uFF0C\u522B\u624B\u5199\u3002";
7921
+ function readRequests(file) {
7922
+ let raw;
7923
+ try {
7924
+ raw = JSON.parse(readFileSync4(file, "utf8"));
7925
+ } catch (e) {
7926
+ throw new Error(`\u9700\u6C42\u6E05\u5355\u8BFB\u4E0D\u51FA\u6765\uFF08${file}\uFF09\uFF1A${e instanceof Error ? e.message : String(e)}`);
7927
+ }
7928
+ if (!Array.isArray(raw)) {
7929
+ throw new Error(`\u9700\u6C42\u6E05\u5355\u4E0D\u662F\u4E00\u4E2A JSON \u6570\u7EC4\uFF08${file}\uFF09\uFF0C\u5B9E\u9645\u662F ${typeof raw}`);
7930
+ }
7931
+ raw.forEach((row, i) => {
7932
+ if (!row || typeof row !== "object" || Array.isArray(row)) {
7933
+ throw new Error(`\u9700\u6C42\u6E05\u5355\u7B2C ${i + 1} \u6761\u4E0D\u662F\u4E00\u4E2A JSON \u5BF9\u8C61\uFF0C\u800C\u662F ${typeof row}`);
7934
+ }
7935
+ });
7936
+ return raw;
7937
+ }
7938
+ function renderProblems(rows) {
7939
+ const lines = ["\u5206\u8BCA\u7ED3\u8BBA\u4E0E\u8BC1\u636E\u6253\u67B6\uFF0C\u8FD9\u4EFD\u4EA7\u51FA\u6CA1\u6709\u843D\u76D8\uFF1A"];
7940
+ for (const row of rows) {
7941
+ lines.push(` [${row.idx}] ${row.request.slice(0, 30)} \xB7 ${row.rule}\uFF1A${row.note}`);
7942
+ }
7943
+ return `${lines.join("\n")}
7944
+ `;
7945
+ }
7946
+ function writeTriageArtifact(outDir, body) {
7947
+ const out = path7.join(outDir, "work", "triage.md");
7948
+ mkdirSync(path7.dirname(out), { recursive: true });
7949
+ writeFileSync2(out, body, "utf8");
7950
+ return out;
7951
+ }
7952
+ async function runTriage(args) {
7953
+ if (!args.requests) return premise("\u6CA1\u7ED9 `--requests`", REQUESTS_SHAPE);
7954
+ let entriesIn;
7955
+ try {
7956
+ entriesIn = readRequests(args.requests);
7957
+ } catch (e) {
7958
+ return premise(e instanceof Error ? e.message : String(e), REQUESTS_SHAPE);
7959
+ }
7960
+ const ctx = await getActiveAuthContextFromCli(args);
7961
+ const client3 = HcmClient20.fromAuthContext(ctx);
7962
+ const probe = httpProbe3(client3.raw(), args.capabilities ?? DEFAULT_CAPABILITIES3);
7963
+ const artifactsDir = args.recon ?? new ReconLayout2(args.out ?? ".", ctx.tenantId, await computeReconSourceKey2(probe)).dir;
7964
+ const result = await runTriageRound(probe, artifactsDir, entriesIn);
7965
+ if (result.body === null) {
7966
+ process.stdout.write(renderProblems(result.problems));
7967
+ return 1;
7968
+ }
7969
+ const out = writeTriageArtifact(args.out ?? ".", result.body);
7970
+ process.stdout.write(`\u5206\u8BCA\u81EA\u6D3D\uFF0C\u5DF2\u5199 ${out}\uFF08${result.entries.length} \u6761\uFF09
7971
+ `);
7972
+ return 0;
7973
+ }
7974
+ async function deliveryTriageCommand(args) {
7975
+ let code;
7976
+ try {
7977
+ code = await runTriage(args);
7978
+ } catch (e) {
7979
+ exitWithError(e);
7980
+ code = 1;
7981
+ }
7982
+ process.exit(code);
7983
+ }
7984
+
8758
7985
  // src/commands/delivery-execution.ts
8759
- import { createHash as createHash7, randomBytes as secureRandomBytes } from "crypto";
7986
+ import { createHash as createHash5, randomBytes as secureRandomBytes } from "crypto";
8760
7987
  import { spawn } from "child_process";
8761
- import { createReadStream as createReadStream2, promises as fs8 } from "fs";
8762
- import path9 from "path";
8763
- import { CliError as CliError22, CliErrorCode as CliErrorCode21, formatObject as formatObject22 } from "@hcmai/sdk";
7988
+ import { createReadStream, promises as fs6 } from "fs";
7989
+ import path8 from "path";
7990
+ import { CliError as CliError20, CliErrorCode as CliErrorCode19, formatObject as formatObject22 } from "@hcmai/sdk";
8764
7991
  init_exit();
8765
- var EXECUTION_CONTRACT_VERSION = "2026-08-29.controlled-v2";
7992
+ var EXECUTION_CONTRACT_VERSION = "2026-08-29.controlled-v3";
8766
7993
  var DEFAULT_TTL_SECONDS = 15 * 60;
8767
7994
  var MIN_TTL_SECONDS = 60;
8768
7995
  var MAX_TTL_SECONDS = 60 * 60;
@@ -8774,102 +8001,102 @@ async function prepareDeliveryExecution(input) {
8774
8001
  assertGuardedAssessment(assessment, input.argv);
8775
8002
  const ttlSeconds = input.ttlSeconds ?? DEFAULT_TTL_SECONDS;
8776
8003
  if (!Number.isInteger(ttlSeconds) || ttlSeconds < MIN_TTL_SECONDS || ttlSeconds > MAX_TTL_SECONDS) {
8777
- throw invalid4(`--ttl-seconds \u5FC5\u987B\u662F ${MIN_TTL_SECONDS} \u5230 ${MAX_TTL_SECONDS} \u7684\u6574\u6570`);
8004
+ throw invalid2(`--ttl-seconds \u5FC5\u987B\u662F ${MIN_TTL_SECONDS} \u5230 ${MAX_TTL_SECONDS} \u7684\u6574\u6570`);
8778
8005
  }
8779
8006
  const change = await bindDocument(project, input.changeRef, "\u53D8\u66F4\u8BF4\u660E");
8780
8007
  const rollback = await bindDocument(project, input.rollbackRef, "\u56DE\u6EDA\u8BF4\u660E");
8781
8008
  const payloads = await bindPayloadFiles(project, input.argv);
8782
8009
  const evidence = await bindEvidenceDirectory(project, input.evidenceDir);
8783
- const { bytes: lockBytes, runtime: lockedRuntime } = await readChironLock(project);
8010
+ const { bytes: lockBytes, runtime: lockedRuntime } = await readSkillsLock(project);
8784
8011
  const runtime = await (input.runtimeIdentity ?? currentRuntimeIdentity)();
8785
8012
  assertRuntimeMatches(runtime, lockedRuntime);
8786
8013
  const created = (input.now ?? (() => /* @__PURE__ */ new Date()))();
8787
- if (Number.isNaN(created.getTime())) throw invalid4("\u5F53\u524D\u65F6\u95F4\u65E0\u6548");
8014
+ if (Number.isNaN(created.getTime())) throw invalid2("\u5F53\u524D\u65F6\u95F4\u65E0\u6548");
8788
8015
  const core = {
8789
8016
  schemaVersion: 1,
8790
8017
  contractVersion: EXECUTION_CONTRACT_VERSION,
8791
- nonceSha256: sha2567((input.randomBytes ?? secureRandomBytes)(12)),
8018
+ nonceSha256: sha2565((input.randomBytes ?? secureRandomBytes)(12)),
8792
8019
  createdAt: created.toISOString(),
8793
8020
  expiresAt: new Date(created.getTime() + ttlSeconds * 1e3).toISOString(),
8794
- chironLockSha256: sha2567(lockBytes),
8021
+ skillsLockSha256: sha2565(lockBytes),
8795
8022
  runtime,
8796
8023
  assessment,
8797
8024
  documents: { change, rollback },
8798
8025
  payloads,
8799
8026
  evidenceDir: evidence.relative
8800
8027
  };
8801
- const planId = sha2567(canonicalJson(core)).slice(0, 24);
8028
+ const planId = sha2565(canonicalJson(core)).slice(0, 24);
8802
8029
  const plan = { ...core, planId };
8803
- const plansDir = path9.join(project, ".hcm-delivery", "execution-plans");
8030
+ const plansDir = path8.join(project, ".hcm-delivery", "execution-plans");
8804
8031
  await safeManagedDirectory(project, ".hcm-delivery/execution-plans", plansDir);
8805
- const planFile = path9.join(plansDir, `${planId}.json`);
8032
+ const planFile = path8.join(plansDir, `${planId}.json`);
8806
8033
  try {
8807
- await fs8.writeFile(planFile, `${JSON.stringify(plan, null, 2)}
8034
+ await fs6.writeFile(planFile, `${JSON.stringify(plan, null, 2)}
8808
8035
  `, {
8809
8036
  encoding: "utf8",
8810
8037
  mode: 384,
8811
8038
  flag: "wx"
8812
8039
  });
8813
8040
  } catch (cause) {
8814
- throw invalid4(`\u6267\u884C\u8BA1\u5212\u5199\u5165\u5931\u8D25\u6216 planId \u5DF2\u5B58\u5728\uFF1A${planId}`, cause);
8041
+ throw invalid2(`\u6267\u884C\u8BA1\u5212\u5199\u5165\u5931\u8D25\u6216 planId \u5DF2\u5B58\u5728\uFF1A${planId}`, cause);
8815
8042
  }
8816
8043
  return plan;
8817
8044
  }
8818
8045
  async function executeDeliveryPlan(input) {
8819
- if (!PLAN_ID_PATTERN.test(input.planId)) throw invalid4("planId \u5FC5\u987B\u662F 24 \u4F4D\u5C0F\u5199\u5341\u516D\u8FDB\u5236");
8046
+ if (!PLAN_ID_PATTERN.test(input.planId)) throw invalid2("planId \u5FC5\u987B\u662F 24 \u4F4D\u5C0F\u5199\u5341\u516D\u8FDB\u5236");
8820
8047
  const project = await realProject(input.project);
8821
8048
  if (await readProjectMode(project) !== "controlled") {
8822
- throw invalid4("\u9879\u76EE\u4E0D\u662F controlled\uFF0C\u4E0D\u80FD\u6267\u884C R2 \u8BA1\u5212");
8049
+ throw invalid2("\u9879\u76EE\u4E0D\u662F controlled\uFF0C\u4E0D\u80FD\u6267\u884C R2 \u8BA1\u5212");
8823
8050
  }
8824
- const planFile = path9.join(project, ".hcm-delivery", "execution-plans", `${input.planId}.json`);
8051
+ const planFile = path8.join(project, ".hcm-delivery", "execution-plans", `${input.planId}.json`);
8825
8052
  const plan = await readPlan(project, planFile);
8826
8053
  if (plan.planId !== input.planId || computePlanId(plan) !== input.planId) {
8827
- throw invalid4("\u6267\u884C\u8BA1\u5212\u5185\u5BB9\u4E0E planId \u6458\u8981\u4E0D\u4E00\u81F4");
8054
+ throw invalid2("\u6267\u884C\u8BA1\u5212\u5185\u5BB9\u4E0E planId \u6458\u8981\u4E0D\u4E00\u81F4");
8828
8055
  }
8829
8056
  const now = (input.now ?? (() => /* @__PURE__ */ new Date()))();
8830
- if (Number.isNaN(now.getTime())) throw invalid4("\u5F53\u524D\u65F6\u95F4\u65E0\u6548");
8057
+ if (Number.isNaN(now.getTime())) throw invalid2("\u5F53\u524D\u65F6\u95F4\u65E0\u6548");
8831
8058
  const expiresAt = Date.parse(plan.expiresAt);
8832
8059
  const createdAt = Date.parse(plan.createdAt);
8833
8060
  if (!Number.isFinite(createdAt) || !Number.isFinite(expiresAt) || expiresAt - createdAt < MIN_TTL_SECONDS * 1e3 || expiresAt - createdAt > MAX_TTL_SECONDS * 1e3) {
8834
- throw invalid4("\u6267\u884C\u8BA1\u5212\u65F6\u95F4\u7A97\u53E3\u65E0\u6548");
8061
+ throw invalid2("\u6267\u884C\u8BA1\u5212\u65F6\u95F4\u7A97\u53E3\u65E0\u6548");
8835
8062
  }
8836
- if (now.getTime() < createdAt - 5e3) throw invalid4("\u5F53\u524D\u65F6\u95F4\u65E9\u4E8E\u8BA1\u5212\u521B\u5EFA\u65F6\u95F4");
8837
- if (now.getTime() > expiresAt) throw invalid4("\u6267\u884C\u8BA1\u5212\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0 prepare");
8063
+ if (now.getTime() < createdAt - 5e3) throw invalid2("\u5F53\u524D\u65F6\u95F4\u65E9\u4E8E\u8BA1\u5212\u521B\u5EFA\u65F6\u95F4");
8064
+ if (now.getTime() > expiresAt) throw invalid2("\u6267\u884C\u8BA1\u5212\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0 prepare");
8838
8065
  const assessment = await (input.assessCommand ?? assessEffectiveDeliveryCommand)(input.argv);
8839
8066
  assertGuardedAssessment(assessment, input.argv);
8840
8067
  if (canonicalJson(assessment) !== canonicalJson(plan.assessment)) {
8841
- throw invalid4("\u5B9E\u9645 argv \u4E0E\u6267\u884C\u8BA1\u5212\u7684\u547D\u4EE4\u6458\u8981\u6216\u98CE\u9669\u4E8B\u5B9E\u4E0D\u4E00\u81F4");
8068
+ throw invalid2("\u5B9E\u9645 argv \u4E0E\u6267\u884C\u8BA1\u5212\u7684\u547D\u4EE4\u6458\u8981\u6216\u98CE\u9669\u4E8B\u5B9E\u4E0D\u4E00\u81F4");
8842
8069
  }
8843
- const { bytes: lockBytes, runtime: lockedRuntime } = await readChironLock(project);
8844
- if (sha2567(lockBytes) !== plan.chironLockSha256) {
8845
- throw invalid4("Chiron \u9501\u6458\u8981\u5DF2\u6F02\u79FB\uFF0C\u8BF7\u91CD\u65B0\u8BC4\u4F30\u5E76 prepare");
8070
+ const { bytes: lockBytes, runtime: lockedRuntime } = await readSkillsLock(project);
8071
+ if (sha2565(lockBytes) !== plan.skillsLockSha256) {
8072
+ throw invalid2("\u6280\u80FD\u9501\u6458\u8981\u5DF2\u6F02\u79FB\uFF0C\u8BF7\u91CD\u65B0\u8BC4\u4F30\u5E76 prepare");
8846
8073
  }
8847
8074
  const runtime = await (input.runtimeIdentity ?? currentRuntimeIdentity)();
8848
8075
  assertRuntimeMatches(runtime, lockedRuntime);
8849
8076
  if (canonicalJson(runtime) !== canonicalJson(plan.runtime)) {
8850
- throw invalid4("CLI \u8FD0\u884C\u65F6\u6458\u8981\u4E0E\u6267\u884C\u8BA1\u5212\u4E0D\u4E00\u81F4");
8077
+ throw invalid2("CLI \u8FD0\u884C\u65F6\u6458\u8981\u4E0E\u6267\u884C\u8BA1\u5212\u4E0D\u4E00\u81F4");
8851
8078
  }
8852
8079
  await assertDocumentUnchanged(project, plan.documents.change, "\u53D8\u66F4\u8BF4\u660E");
8853
8080
  await assertDocumentUnchanged(project, plan.documents.rollback, "\u56DE\u6EDA\u8BF4\u660E");
8854
8081
  await assertPayloadsUnchanged(project, plan.payloads);
8855
8082
  const evidenceDir = await bindEvidenceDirectory(project, plan.evidenceDir);
8856
- const receiptFile = path9.join(evidenceDir.absolute, `${plan.planId}.receipt.json`);
8857
- if (await pathExists(receiptFile)) throw invalid4(`\u6267\u884C\u6536\u636E\u5DF2\u5B58\u5728\uFF0C\u62D2\u7EDD\u518D\u6B21\u6267\u884C\uFF1A${plan.planId}`);
8858
- const claimsDir = path9.join(project, ".hcm-delivery", "execution-claims");
8083
+ const receiptFile = path8.join(evidenceDir.absolute, `${plan.planId}.receipt.json`);
8084
+ if (await pathExists(receiptFile)) throw invalid2(`\u6267\u884C\u6536\u636E\u5DF2\u5B58\u5728\uFF0C\u62D2\u7EDD\u518D\u6B21\u6267\u884C\uFF1A${plan.planId}`);
8085
+ const claimsDir = path8.join(project, ".hcm-delivery", "execution-claims");
8859
8086
  await safeManagedDirectory(project, ".hcm-delivery/execution-claims", claimsDir);
8860
- const claimFile = path9.join(claimsDir, `${plan.planId}.json`);
8087
+ const claimFile = path8.join(claimsDir, `${plan.planId}.json`);
8861
8088
  try {
8862
- await fs8.writeFile(
8089
+ await fs6.writeFile(
8863
8090
  claimFile,
8864
8091
  `${JSON.stringify({ schemaVersion: 1, planId: plan.planId, claimedAt: now.toISOString() }, null, 2)}
8865
8092
  `,
8866
8093
  { encoding: "utf8", mode: 384, flag: "wx" }
8867
8094
  );
8868
8095
  } catch (cause) {
8869
- throw invalid4(`\u6267\u884C\u8BA1\u5212\u5DF2\u6D88\u8D39\uFF0C\u62D2\u7EDD\u91CD\u590D\u6267\u884C\uFF1A${plan.planId}`, cause);
8096
+ throw invalid2(`\u6267\u884C\u8BA1\u5212\u5DF2\u6D88\u8D39\uFF0C\u62D2\u7EDD\u91CD\u590D\u6267\u884C\uFF1A${plan.planId}`, cause);
8870
8097
  }
8871
- const stdoutHash = createHash7("sha256");
8872
- const stderrHash = createHash7("sha256");
8098
+ const stdoutHash = createHash5("sha256");
8099
+ const stderrHash = createHash5("sha256");
8873
8100
  const run = input.runCommand ?? runCurrentCliCommand;
8874
8101
  let exitCode;
8875
8102
  try {
@@ -8885,7 +8112,7 @@ async function executeDeliveryPlan(input) {
8885
8112
  exitCode = 1;
8886
8113
  }
8887
8114
  const completed = (input.now ?? (() => /* @__PURE__ */ new Date()))();
8888
- if (Number.isNaN(completed.getTime())) throw invalid4("\u5B8C\u6210\u65F6\u95F4\u65E0\u6548");
8115
+ if (Number.isNaN(completed.getTime())) throw invalid2("\u5B8C\u6210\u65F6\u95F4\u65E0\u6548");
8889
8116
  if (!Number.isInteger(exitCode) || exitCode < 0) exitCode = 1;
8890
8117
  const receipt = {
8891
8118
  schemaVersion: 1,
@@ -8904,9 +8131,9 @@ async function executeDeliveryPlan(input) {
8904
8131
  }
8905
8132
  async function deliveryPrepareCommand(argv, args) {
8906
8133
  try {
8907
- if (!args.changeRef) throw invalid4("--change-ref <file> \u5FC5\u586B");
8908
- if (!args.rollbackRef) throw invalid4("--rollback-ref <file> \u5FC5\u586B");
8909
- if (!args.evidenceDir) throw invalid4("--evidence-dir <dir> \u5FC5\u586B");
8134
+ if (!args.changeRef) throw invalid2("--change-ref <file> \u5FC5\u586B");
8135
+ if (!args.rollbackRef) throw invalid2("--rollback-ref <file> \u5FC5\u586B");
8136
+ if (!args.evidenceDir) throw invalid2("--evidence-dir <dir> \u5FC5\u586B");
8910
8137
  const ttlSeconds = parseTtl(args.ttlSeconds);
8911
8138
  const plan = await prepareDeliveryExecution({
8912
8139
  project: args.project ?? process.cwd(),
@@ -8935,54 +8162,75 @@ async function deliveryExecuteCommand(planId, argv, args) {
8935
8162
  }
8936
8163
  }
8937
8164
  async function readProjectMode(project) {
8938
- const file = path9.join(project, ".hcm-delivery", "project.yml");
8165
+ const file = path8.join(project, ".hcm-delivery", "project.yml");
8939
8166
  const content = await readSafeFile(project, file, "\u9879\u76EE\u914D\u7F6E");
8940
8167
  const match = content.toString("utf8").match(
8941
8168
  /^deliveryMode:\s*(?:"(plan-only|controlled)"|'(plan-only|controlled)'|(plan-only|controlled))\s*$/m
8942
8169
  );
8943
8170
  const mode = match?.[1] ?? match?.[2] ?? match?.[3];
8944
8171
  if (mode !== "plan-only" && mode !== "controlled") {
8945
- throw invalid4("project.yml \u7F3A\u5C11\u5408\u6CD5 deliveryMode");
8172
+ throw invalid2("project.yml \u7F3A\u5C11\u5408\u6CD5 deliveryMode");
8946
8173
  }
8947
8174
  return mode;
8948
8175
  }
8949
- async function readChironLock(project) {
8950
- const file = path9.join(project, ".hcm-delivery", "chiron.lock.json");
8951
- const bytes = await readSafeFile(project, file, "Chiron \u9501");
8176
+ var SKILLS_LOCK_CANDIDATES = [
8177
+ path8.join("hcm-skills", ".hcm-skills.json"),
8178
+ path8.join(".claude", "skills", ".hcm-skills.json")
8179
+ ];
8180
+ async function readSkillsLock(project) {
8181
+ const found = [];
8182
+ for (const candidate of SKILLS_LOCK_CANDIDATES) {
8183
+ if (await pathExists(path8.join(project, candidate))) found.push(candidate);
8184
+ }
8185
+ if (found.length === 0) {
8186
+ throw invalid2(
8187
+ "\u627E\u4E0D\u5230\u6280\u80FD\u9501\uFF08hcm-skills/.hcm-skills.json \u6216 .claude/skills/.hcm-skills.json\uFF09\u3002next_step=\u5148\u5728\u9879\u76EE\u91CC\u8DD1\u4E00\u6B21 `hcm skills install <id>`\uFF0C\u518D\u91CD\u65B0 prepare"
8188
+ );
8189
+ }
8190
+ if (found.length > 1) {
8191
+ throw invalid2(
8192
+ `\u9879\u76EE\u91CC\u6709\u591A\u4EFD\u6280\u80FD\u9501\uFF08${found.join("\u3001")}\uFF09\uFF0C\u65E0\u6CD5\u552F\u4E00\u5224\u5B9A\u53D7\u63A7\u6267\u884C\u7ED1\u5B9A\u54EA\u4E00\u4EFD\u3002next_step=\u53EA\u4FDD\u7559\u5B9E\u9645\u5728\u7528\u7684\u90A3\u4E2A\u6280\u80FD\u76EE\u5F55`
8193
+ );
8194
+ }
8195
+ const bytes = await readSafeFile(project, path8.join(project, found[0]), "\u6280\u80FD\u9501");
8952
8196
  let parsed;
8953
8197
  try {
8954
8198
  parsed = JSON.parse(bytes.toString("utf8"));
8955
8199
  } catch (cause) {
8956
- throw invalid4("Chiron \u9501\u4E0D\u662F\u5408\u6CD5 JSON", cause);
8200
+ throw invalid2("\u6280\u80FD\u9501\u4E0D\u662F\u5408\u6CD5 JSON", cause);
8957
8201
  }
8958
8202
  const launch = parsed?.runtime?.launch;
8959
- if (!isRuntimeIdentity(launch)) throw invalid4("Chiron \u9501\u7F3A\u5C11\u5408\u6CD5 runtime.launch \u6458\u8981");
8203
+ if (!isRuntimeIdentity(launch)) {
8204
+ throw invalid2(
8205
+ "\u6280\u80FD\u9501\u6CA1\u6709\u8BB0\u5F55 runtime.launch\uFF0C\u65E0\u6CD5\u786E\u8BA4\u300C\u73B0\u5728\u8FD9\u4EFD CLI \u5C31\u662F\u5F53\u521D\u88C5\u6280\u80FD\u7684\u90A3\u4EFD\u300D\u3002next_step=\u7528\u5F53\u524D CLI \u91CD\u8DD1\u4E00\u6B21 `hcm skills install`\uFF08\u6216 `hcm skills update`\uFF09\u5237\u65B0\u6280\u80FD\u9501"
8206
+ );
8207
+ }
8960
8208
  return { bytes, runtime: launch };
8961
8209
  }
8962
8210
  async function bindDocument(project, reference, label) {
8963
8211
  const relative2 = safeRelative(reference, label);
8964
8212
  if (!(relative2.startsWith("work/") || relative2.startsWith("decisions/"))) {
8965
- throw invalid4(`${label}\u5FC5\u987B\u4F4D\u4E8E\u9879\u76EE work/ \u6216 decisions/ \u4E0B`);
8213
+ throw invalid2(`${label}\u5FC5\u987B\u4F4D\u4E8E\u9879\u76EE work/ \u6216 decisions/ \u4E0B`);
8966
8214
  }
8967
- const file = path9.join(project, relative2);
8215
+ const file = path8.join(project, relative2);
8968
8216
  const bytes = await readSafeFile(project, file, label);
8969
- return { path: relative2, sha256: sha2567(bytes) };
8217
+ return { path: relative2, sha256: sha2565(bytes) };
8970
8218
  }
8971
8219
  async function assertDocumentUnchanged(project, document, label) {
8972
8220
  const current = await bindDocument(project, document.path, label);
8973
- if (current.sha256 !== document.sha256) throw invalid4(`${label}\u6458\u8981\u5DF2\u6F02\u79FB\uFF0C\u8BF7\u91CD\u65B0 prepare`);
8221
+ if (current.sha256 !== document.sha256) throw invalid2(`${label}\u6458\u8981\u5DF2\u6F02\u79FB\uFF0C\u8BF7\u91CD\u65B0 prepare`);
8974
8222
  }
8975
8223
  async function bindEvidenceDirectory(project, reference) {
8976
8224
  const relative2 = safeRelative(reference, "evidence \u76EE\u5F55");
8977
8225
  if (!(relative2 === "evidence" || relative2.startsWith("evidence/"))) {
8978
- throw invalid4("evidence \u76EE\u5F55\u5FC5\u987B\u4F4D\u4E8E\u9879\u76EE evidence/ \u4E0B");
8226
+ throw invalid2("evidence \u76EE\u5F55\u5FC5\u987B\u4F4D\u4E8E\u9879\u76EE evidence/ \u4E0B");
8979
8227
  }
8980
- const absolute = path9.join(project, relative2);
8228
+ const absolute = path8.join(project, relative2);
8981
8229
  await assertNoSymlinkComponents(project, relative2);
8982
- const stat = await fs8.stat(absolute).catch((cause) => {
8983
- throw invalid4(`evidence \u76EE\u5F55\u4E0D\u53EF\u7528\uFF1A${relative2}`, cause);
8230
+ const stat = await fs6.stat(absolute).catch((cause) => {
8231
+ throw invalid2(`evidence \u76EE\u5F55\u4E0D\u53EF\u7528\uFF1A${relative2}`, cause);
8984
8232
  });
8985
- if (!stat.isDirectory()) throw invalid4(`evidence \u8DEF\u5F84\u4E0D\u662F\u76EE\u5F55\uFF1A${relative2}`);
8233
+ if (!stat.isDirectory()) throw invalid2(`evidence \u8DEF\u5F84\u4E0D\u662F\u76EE\u5F55\uFF1A${relative2}`);
8986
8234
  return { relative: relative2, absolute };
8987
8235
  }
8988
8236
  async function readPlan(project, file) {
@@ -8991,39 +8239,39 @@ async function readPlan(project, file) {
8991
8239
  try {
8992
8240
  plan = JSON.parse(bytes.toString("utf8"));
8993
8241
  } catch (cause) {
8994
- throw invalid4("\u6267\u884C\u8BA1\u5212\u4E0D\u662F\u5408\u6CD5 JSON", cause);
8242
+ throw invalid2("\u6267\u884C\u8BA1\u5212\u4E0D\u662F\u5408\u6CD5 JSON", cause);
8995
8243
  }
8996
- if (!isExecutionPlan(plan)) throw invalid4("\u6267\u884C\u8BA1\u5212 schema \u65E0\u6548");
8244
+ if (!isExecutionPlan(plan)) throw invalid2("\u6267\u884C\u8BA1\u5212 schema \u65E0\u6548");
8997
8245
  return plan;
8998
8246
  }
8999
8247
  function computePlanId(plan) {
9000
8248
  const core = { ...plan };
9001
8249
  delete core.planId;
9002
- return sha2567(canonicalJson(core)).slice(0, 24);
8250
+ return sha2565(canonicalJson(core)).slice(0, 24);
9003
8251
  }
9004
8252
  function assertGuardedAssessment(assessment, argv) {
9005
- if (assessment.risk !== "R2") throw invalid4("\u53EA\u6709 R2 \u547D\u4EE4\u53EF\u4EE5\u8FDB\u5165\u53D7\u63A7\u6267\u884C\u8BA1\u5212");
8253
+ if (assessment.risk !== "R2") throw invalid2("\u53EA\u6709 R2 \u547D\u4EE4\u53EF\u4EE5\u8FDB\u5165\u53D7\u63A7\u6267\u884C\u8BA1\u5212");
9006
8254
  if (!assessment.guardedExecutionAvailable) {
9007
- throw invalid4("\u8BE5 R2 \u547D\u4EE4\u4E0D\u5728\u9996\u6279\u53D7\u63A7\u6267\u884C\u5668\u652F\u6301\u9762");
8255
+ throw invalid2("\u8BE5 R2 \u547D\u4EE4\u4E0D\u5728\u9996\u6279\u53D7\u63A7\u6267\u884C\u5668\u652F\u6301\u9762");
9008
8256
  }
9009
- if (!assessment.environment.envAlias) throw invalid4("R2 argv \u5FC5\u987B\u663E\u5F0F\u5305\u542B --env \u73AF\u5883\u522B\u540D");
8257
+ if (!assessment.environment.envAlias) throw invalid2("R2 argv \u5FC5\u987B\u663E\u5F0F\u5305\u542B --env \u73AF\u5883\u522B\u540D");
9010
8258
  if (!assessment.environment.identityAlias) {
9011
- throw invalid4("R2 argv \u5FC5\u987B\u663E\u5F0F\u5305\u542B --as \u8EAB\u4EFD\u522B\u540D");
8259
+ throw invalid2("R2 argv \u5FC5\u987B\u663E\u5F0F\u5305\u542B --as \u8EAB\u4EFD\u522B\u540D");
9012
8260
  }
9013
8261
  validateSupportedCommandShape(assessment.reasonCode, argv);
9014
8262
  }
9015
8263
  function validateSupportedCommandShape(reasonCode, argv) {
9016
8264
  if (reasonCode === "credential-reset") {
9017
8265
  if (argv[0] !== "user" || argv[1] !== "reset-password") {
9018
- throw invalid4("credential-reset \u53EA\u652F\u6301 user reset-password");
8266
+ throw invalid2("credential-reset \u53EA\u652F\u6301 user reset-password");
9019
8267
  }
9020
8268
  const userId = optionalFlagValue(argv, "--id");
9021
8269
  const username = optionalFlagValue(argv, "--username");
9022
8270
  if (Boolean(userId) === Boolean(username)) {
9023
- throw invalid4("user reset-password \u5FC5\u987B\u4E14\u53EA\u80FD\u5305\u542B --id \u6216 --username");
8271
+ throw invalid2("user reset-password \u5FC5\u987B\u4E14\u53EA\u80FD\u5305\u542B --id \u6216 --username");
9024
8272
  }
9025
8273
  if (!argv.includes("--password-stdin")) {
9026
- throw invalid4("user reset-password \u5FC5\u987B\u5305\u542B\u72EC\u7ACB\u7684 --password-stdin");
8274
+ throw invalid2("user reset-password \u5FC5\u987B\u5305\u542B\u72EC\u7ACB\u7684 --password-stdin");
9027
8275
  }
9028
8276
  if (argv.some(
9029
8277
  (value) => [
@@ -9035,7 +8283,7 @@ function validateSupportedCommandShape(reasonCode, argv) {
9035
8283
  "--pat-stdin"
9036
8284
  ].includes(value.split("=", 1)[0] ?? "")
9037
8285
  ) || argv.some((value) => value.startsWith("--password-stdin="))) {
9038
- throw invalid4("user reset-password \u4E0D\u5141\u8BB8\u5728 argv \u4E2D\u643A\u5E26\u660E\u6587\u51ED\u636E");
8286
+ throw invalid2("user reset-password \u4E0D\u5141\u8BB8\u5728 argv \u4E2D\u643A\u5E26\u660E\u6587\u51ED\u636E");
9039
8287
  }
9040
8288
  return;
9041
8289
  }
@@ -9049,17 +8297,17 @@ function validateSupportedCommandShape(reasonCode, argv) {
9049
8297
  return;
9050
8298
  }
9051
8299
  if (reasonCode === "cache-mutation") {
9052
- if (!argv[2] || argv[2].startsWith("-")) throw invalid4("cache clear \u5FC5\u987B\u5305\u542B Model");
8300
+ if (!argv[2] || argv[2].startsWith("-")) throw invalid2("cache clear \u5FC5\u987B\u5305\u542B Model");
9053
8301
  return;
9054
8302
  }
9055
8303
  if (reasonCode === "setting-write") {
9056
- if (!argv[2] || argv[2].startsWith("-")) throw invalid4("setting \u5199\u547D\u4EE4\u5FC5\u987B\u5305\u542B domain");
8304
+ if (!argv[2] || argv[2].startsWith("-")) throw invalid2("setting \u5199\u547D\u4EE4\u5FC5\u987B\u5305\u542B domain");
9057
8305
  if (argv[1] === "set") {
9058
8306
  requireFlagValue(argv, "--set", "setting set \u5FC5\u987B\u5305\u542B --set <assignment>");
9059
8307
  return;
9060
8308
  }
9061
8309
  if (argv[1] === "reset" && (!argv[3] || !argv[4])) {
9062
- throw invalid4("setting reset \u5FC5\u987B\u5305\u542B domain\u3001namespace \u4E0E key");
8310
+ throw invalid2("setting reset \u5FC5\u987B\u5305\u542B domain\u3001namespace \u4E0E key");
9063
8311
  }
9064
8312
  }
9065
8313
  }
@@ -9080,10 +8328,10 @@ function requireExactlyOnePayload(argv, command) {
9080
8328
  const inline = optionalFlagValue(argv, "--data") !== void 0;
9081
8329
  const fromFile = optionalFlagValue(argv, "--data-file") !== void 0;
9082
8330
  if (inline && fromFile) {
9083
- throw invalid4(`${command} \u7684 --data \u4E0E --data-file \u4E92\u65A5\uFF0C\u53EA\u80FD\u7ED9\u4E00\u4E2A`);
8331
+ throw invalid2(`${command} \u7684 --data \u4E0E --data-file \u4E92\u65A5\uFF0C\u53EA\u80FD\u7ED9\u4E00\u4E2A`);
9084
8332
  }
9085
8333
  if (!inline && !fromFile) {
9086
- throw invalid4(`${command} \u5FC5\u987B\u5305\u542B --data <JSON> \u6216 --data-file <\u6587\u4EF6>`);
8334
+ throw invalid2(`${command} \u5FC5\u987B\u5305\u542B --data <JSON> \u6216 --data-file <\u6587\u4EF6>`);
9087
8335
  }
9088
8336
  }
9089
8337
  var PAYLOAD_FILE_FLAGS = ["--data-file", "--params-file"];
@@ -9098,15 +8346,15 @@ async function bindPayloadFiles(project, argv) {
9098
8346
  }
9099
8347
  async function bindPayloadFile(project, reference, label) {
9100
8348
  const relative2 = safeRelative(reference, label);
9101
- const file = path9.join(project, relative2);
8349
+ const file = path8.join(project, relative2);
9102
8350
  const bytes = await readSafeFile(project, file, label);
9103
- return { path: relative2, sha256: sha2567(bytes) };
8351
+ return { path: relative2, sha256: sha2565(bytes) };
9104
8352
  }
9105
8353
  async function assertPayloadsUnchanged(project, payloads) {
9106
8354
  for (const payload of payloads) {
9107
8355
  const current = await bindPayloadFile(project, payload.path, `\u8F7D\u8377 ${payload.path}`);
9108
8356
  if (current.sha256 !== payload.sha256) {
9109
- throw invalid4(`\u8F7D\u8377\u6587\u4EF6 ${payload.path} \u7684\u5185\u5BB9\u5DF2\u53D8\u66F4\uFF0C\u8BF7\u91CD\u65B0 prepare`);
8357
+ throw invalid2(`\u8F7D\u8377\u6587\u4EF6 ${payload.path} \u7684\u5185\u5BB9\u5DF2\u53D8\u66F4\uFF0C\u8BF7\u91CD\u65B0 prepare`);
9110
8358
  }
9111
8359
  }
9112
8360
  }
@@ -9116,22 +8364,22 @@ function requireFlagValue(argv, flag, message) {
9116
8364
  if (value === flag) {
9117
8365
  const next = argv[index + 1];
9118
8366
  if (next && !next.startsWith("-")) return next;
9119
- throw invalid4(message);
8367
+ throw invalid2(message);
9120
8368
  }
9121
8369
  if (value?.startsWith(`${flag}=`) && value.length > flag.length + 1) {
9122
8370
  return value.slice(flag.length + 1);
9123
8371
  }
9124
8372
  }
9125
- throw invalid4(message);
8373
+ throw invalid2(message);
9126
8374
  }
9127
8375
  function assertRuntimeMatches(actual, expected) {
9128
8376
  if (canonicalJson(actual) !== canonicalJson(expected)) {
9129
- throw invalid4("\u5F53\u524D CLI \u8FD0\u884C\u65F6\u6458\u8981\u4E0E Chiron \u9501\u4E0D\u4E00\u81F4\uFF0C\u8BF7\u91CD\u65B0 skills sync");
8377
+ throw invalid2("\u5F53\u524D CLI \u8FD0\u884C\u65F6\u6458\u8981\u4E0E\u6280\u80FD\u9501\u4E0D\u4E00\u81F4\u3002next_step=\u7528\u5F53\u524D CLI \u91CD\u8DD1\u4E00\u6B21 `hcm skills install` \u5237\u65B0\u6280\u80FD\u9501\uFF0C\u518D prepare");
9130
8378
  }
9131
8379
  }
9132
8380
  async function currentRuntimeIdentity() {
9133
8381
  const entry = process.argv[1];
9134
- if (!entry) throw invalid4("\u65E0\u6CD5\u89E3\u6790\u5F53\u524D CLI entry");
8382
+ if (!entry) throw invalid2("\u65E0\u6CD5\u89E3\u6790\u5F53\u524D CLI entry");
9135
8383
  return {
9136
8384
  kind: "node-entry",
9137
8385
  executableSha256: await sha256File2(process.execPath),
@@ -9140,7 +8388,7 @@ async function currentRuntimeIdentity() {
9140
8388
  }
9141
8389
  async function runCurrentCliCommand(argv, cwd, streams) {
9142
8390
  const entry = process.argv[1];
9143
- if (!entry) throw invalid4("\u65E0\u6CD5\u89E3\u6790\u5F53\u524D CLI entry");
8391
+ if (!entry) throw invalid2("\u65E0\u6CD5\u89E3\u6790\u5F53\u524D CLI entry");
9144
8392
  return new Promise((resolve4, reject) => {
9145
8393
  const child = spawn(process.execPath, [entry, ...argv], {
9146
8394
  cwd,
@@ -9164,29 +8412,29 @@ async function runCurrentCliCommand(argv, cwd, streams) {
9164
8412
  async function writeReceiptExclusive(target, receipt) {
9165
8413
  const temp = `${target}.${process.pid}.${Date.now()}.tmp`;
9166
8414
  try {
9167
- await fs8.writeFile(temp, `${JSON.stringify(receipt, null, 2)}
8415
+ await fs6.writeFile(temp, `${JSON.stringify(receipt, null, 2)}
9168
8416
  `, {
9169
8417
  encoding: "utf8",
9170
8418
  mode: 384,
9171
8419
  flag: "wx"
9172
8420
  });
9173
- await fs8.link(temp, target);
8421
+ await fs6.link(temp, target);
9174
8422
  } catch (cause) {
9175
- throw invalid4(`\u6267\u884C\u6536\u636E\u5199\u5165\u5931\u8D25\u6216\u5DF2\u5B58\u5728\uFF1A${path9.basename(target)}`, cause);
8423
+ throw invalid2(`\u6267\u884C\u6536\u636E\u5199\u5165\u5931\u8D25\u6216\u5DF2\u5B58\u5728\uFF1A${path8.basename(target)}`, cause);
9176
8424
  } finally {
9177
- await fs8.unlink(temp).catch(() => void 0);
8425
+ await fs6.unlink(temp).catch(() => void 0);
9178
8426
  }
9179
8427
  }
9180
8428
  async function safeManagedDirectory(project, relative2, absolute) {
9181
- await assertNoSymlinkComponents(project, path9.dirname(relative2));
9182
- const existing = await fs8.lstat(absolute).catch(() => void 0);
9183
- if (existing?.isSymbolicLink()) throw invalid4(`\u53D7\u7BA1\u76EE\u5F55\u4E0D\u80FD\u662F\u7B26\u53F7\u94FE\u63A5\uFF1A${relative2}`);
9184
- if (existing && !existing.isDirectory()) throw invalid4(`\u53D7\u7BA1\u8DEF\u5F84\u4E0D\u662F\u76EE\u5F55\uFF1A${relative2}`);
9185
- if (!existing) await fs8.mkdir(absolute, { mode: 448 });
9186
- await fs8.chmod(absolute, 448);
8429
+ await assertNoSymlinkComponents(project, path8.dirname(relative2));
8430
+ const existing = await fs6.lstat(absolute).catch(() => void 0);
8431
+ if (existing?.isSymbolicLink()) throw invalid2(`\u53D7\u7BA1\u76EE\u5F55\u4E0D\u80FD\u662F\u7B26\u53F7\u94FE\u63A5\uFF1A${relative2}`);
8432
+ if (existing && !existing.isDirectory()) throw invalid2(`\u53D7\u7BA1\u8DEF\u5F84\u4E0D\u662F\u76EE\u5F55\uFF1A${relative2}`);
8433
+ if (!existing) await fs6.mkdir(absolute, { mode: 448 });
8434
+ await fs6.chmod(absolute, 448);
9187
8435
  }
9188
8436
  async function pathExists(file) {
9189
- return fs8.lstat(file).then(
8437
+ return fs6.lstat(file).then(
9190
8438
  () => true,
9191
8439
  (cause) => {
9192
8440
  if (cause.code === "ENOENT") return false;
@@ -9195,49 +8443,49 @@ async function pathExists(file) {
9195
8443
  );
9196
8444
  }
9197
8445
  async function readSafeFile(project, file, label) {
9198
- const relative2 = path9.relative(project, file).split(path9.sep).join("/");
9199
- if (relative2.startsWith("../") || path9.isAbsolute(relative2))
9200
- throw invalid4(`${label}\u8DEF\u5F84\u9003\u9038\u9879\u76EE`);
8446
+ const relative2 = path8.relative(project, file).split(path8.sep).join("/");
8447
+ if (relative2.startsWith("../") || path8.isAbsolute(relative2))
8448
+ throw invalid2(`${label}\u8DEF\u5F84\u9003\u9038\u9879\u76EE`);
9201
8449
  await assertNoSymlinkComponents(project, relative2);
9202
8450
  let stat;
9203
8451
  try {
9204
- stat = await fs8.lstat(file);
8452
+ stat = await fs6.lstat(file);
9205
8453
  } catch (cause) {
9206
- throw invalid4(`${label}\u4E0D\u53EF\u7528\uFF1A${relative2}`, cause);
8454
+ throw invalid2(`${label}\u4E0D\u53EF\u7528\uFF1A${relative2}`, cause);
9207
8455
  }
9208
- if (stat.isSymbolicLink()) throw invalid4(`${label}\u4E0D\u80FD\u662F\u7B26\u53F7\u94FE\u63A5\uFF1A${relative2}`);
9209
- if (!stat.isFile()) throw invalid4(`${label}\u4E0D\u662F\u666E\u901A\u6587\u4EF6\uFF1A${relative2}`);
9210
- return fs8.readFile(file);
8456
+ if (stat.isSymbolicLink()) throw invalid2(`${label}\u4E0D\u80FD\u662F\u7B26\u53F7\u94FE\u63A5\uFF1A${relative2}`);
8457
+ if (!stat.isFile()) throw invalid2(`${label}\u4E0D\u662F\u666E\u901A\u6587\u4EF6\uFF1A${relative2}`);
8458
+ return fs6.readFile(file);
9211
8459
  }
9212
8460
  async function assertNoSymlinkComponents(project, relative2) {
9213
8461
  const parts = relative2.split("/").filter(Boolean);
9214
8462
  let current = project;
9215
8463
  for (const part of parts) {
9216
- current = path9.join(current, part);
9217
- const stat = await fs8.lstat(current).catch(() => void 0);
9218
- if (stat?.isSymbolicLink()) throw invalid4(`\u8DEF\u5F84\u5305\u542B\u7B26\u53F7\u94FE\u63A5\uFF1A${relative2}`);
8464
+ current = path8.join(current, part);
8465
+ const stat = await fs6.lstat(current).catch(() => void 0);
8466
+ if (stat?.isSymbolicLink()) throw invalid2(`\u8DEF\u5F84\u5305\u542B\u7B26\u53F7\u94FE\u63A5\uFF1A${relative2}`);
9219
8467
  if (!stat) break;
9220
8468
  }
9221
8469
  }
9222
8470
  async function realProject(requested) {
9223
- const absolute = path9.resolve(requested);
8471
+ const absolute = path8.resolve(requested);
9224
8472
  let project;
9225
8473
  try {
9226
- project = await fs8.realpath(absolute);
8474
+ project = await fs6.realpath(absolute);
9227
8475
  } catch (cause) {
9228
- throw invalid4(`\u9879\u76EE\u76EE\u5F55\u4E0D\u53EF\u7528\uFF1A${absolute}`, cause);
8476
+ throw invalid2(`\u9879\u76EE\u76EE\u5F55\u4E0D\u53EF\u7528\uFF1A${absolute}`, cause);
9229
8477
  }
9230
- const stat = await fs8.stat(project);
9231
- if (!stat.isDirectory()) throw invalid4(`\u9879\u76EE\u8DEF\u5F84\u4E0D\u662F\u76EE\u5F55\uFF1A${absolute}`);
8478
+ const stat = await fs6.stat(project);
8479
+ if (!stat.isDirectory()) throw invalid2(`\u9879\u76EE\u8DEF\u5F84\u4E0D\u662F\u76EE\u5F55\uFF1A${absolute}`);
9232
8480
  return project;
9233
8481
  }
9234
8482
  function safeRelative(reference, label) {
9235
- if (!reference || path9.isAbsolute(reference) || /[\r\n\0]/.test(reference)) {
9236
- throw invalid4(`${label}\u5FC5\u987B\u662F\u9879\u76EE\u5185\u76F8\u5BF9\u8DEF\u5F84`);
8483
+ if (!reference || path8.isAbsolute(reference) || /[\r\n\0]/.test(reference)) {
8484
+ throw invalid2(`${label}\u5FC5\u987B\u662F\u9879\u76EE\u5185\u76F8\u5BF9\u8DEF\u5F84`);
9237
8485
  }
9238
- const normalized = path9.normalize(reference).split(path9.sep).join("/");
8486
+ const normalized = path8.normalize(reference).split(path8.sep).join("/");
9239
8487
  if (normalized === ".." || normalized.startsWith("../") || normalized === ".") {
9240
- throw invalid4(`${label}\u8DEF\u5F84\u9003\u9038\u9879\u76EE`);
8488
+ throw invalid2(`${label}\u8DEF\u5F84\u9003\u9038\u9879\u76EE`);
9241
8489
  }
9242
8490
  return normalized.replace(/^\.\//, "");
9243
8491
  }
@@ -9248,7 +8496,7 @@ function isRuntimeIdentity(value) {
9248
8496
  }
9249
8497
  function isExecutionPlan(value) {
9250
8498
  if (!isRecord(value)) return false;
9251
- return value.schemaVersion === 1 && value.contractVersion === EXECUTION_CONTRACT_VERSION && typeof value.planId === "string" && PLAN_ID_PATTERN.test(value.planId) && typeof value.createdAt === "string" && typeof value.expiresAt === "string" && isSha(value.nonceSha256) && isSha(value.chironLockSha256) && isRuntimeIdentity(value.runtime) && isRecord(value.assessment) && isRecord(value.documents) && isBoundDocument(value.documents.change) && isBoundDocument(value.documents.rollback) && Array.isArray(value.payloads) && value.payloads.every(isBoundDocument) && typeof value.evidenceDir === "string";
8499
+ return value.schemaVersion === 1 && value.contractVersion === EXECUTION_CONTRACT_VERSION && typeof value.planId === "string" && PLAN_ID_PATTERN.test(value.planId) && typeof value.createdAt === "string" && typeof value.expiresAt === "string" && isSha(value.nonceSha256) && isSha(value.skillsLockSha256) && isRuntimeIdentity(value.runtime) && isRecord(value.assessment) && isRecord(value.documents) && isBoundDocument(value.documents.change) && isBoundDocument(value.documents.rollback) && Array.isArray(value.payloads) && value.payloads.every(isBoundDocument) && typeof value.evidenceDir === "string";
9252
8500
  }
9253
8501
  function isBoundDocument(value) {
9254
8502
  return isRecord(value) && typeof value.path === "string" && isSha(value.sha256);
@@ -9261,7 +8509,7 @@ function isSha(value) {
9261
8509
  }
9262
8510
  function parseTtl(value) {
9263
8511
  if (value === void 0) return void 0;
9264
- if (!/^\d+$/.test(value)) throw invalid4("--ttl-seconds \u5FC5\u987B\u662F\u6574\u6570");
8512
+ if (!/^\d+$/.test(value)) throw invalid2("--ttl-seconds \u5FC5\u987B\u662F\u6574\u6570");
9265
8513
  return Number(value);
9266
8514
  }
9267
8515
  function canonicalJson(value) {
@@ -9271,46 +8519,46 @@ function canonicalJson(value) {
9271
8519
  }
9272
8520
  return JSON.stringify(value) ?? "null";
9273
8521
  }
9274
- function sha2567(value) {
9275
- return createHash7("sha256").update(value).digest("hex");
8522
+ function sha2565(value) {
8523
+ return createHash5("sha256").update(value).digest("hex");
9276
8524
  }
9277
8525
  async function sha256File2(file) {
9278
- const hash = createHash7("sha256");
8526
+ const hash = createHash5("sha256");
9279
8527
  await new Promise((resolve4, reject) => {
9280
- const stream = createReadStream2(file);
8528
+ const stream = createReadStream(file);
9281
8529
  stream.on("data", (chunk) => hash.update(chunk));
9282
8530
  stream.on("error", reject);
9283
8531
  stream.on("end", resolve4);
9284
8532
  });
9285
8533
  return hash.digest("hex");
9286
8534
  }
9287
- function invalid4(message, cause) {
9288
- return new CliError22({ code: CliErrorCode21.INVALID_ARGUMENT, message, cause });
8535
+ function invalid2(message, cause) {
8536
+ return new CliError20({ code: CliErrorCode19.INVALID_ARGUMENT, message, cause });
9289
8537
  }
9290
8538
 
9291
8539
  // src/commands/user.ts
9292
8540
  init_auth_guard();
9293
8541
  init_exit();
9294
8542
  import {
9295
- HcmClient as HcmClient20,
8543
+ HcmClient as HcmClient21,
9296
8544
  adminResetPassword,
9297
8545
  formatObject as formatObject23,
9298
8546
  fromAxiosError as fromAxiosError19,
9299
- CliError as CliError23,
9300
- CliErrorCode as CliErrorCode22
8547
+ CliError as CliError21,
8548
+ CliErrorCode as CliErrorCode20
9301
8549
  } from "@hcmai/sdk";
9302
8550
  function buildAdminResetPasswordRequest(args, password) {
9303
8551
  const hasId = Boolean(args.id);
9304
8552
  const hasUsername = Boolean(args.username);
9305
8553
  if (hasId === hasUsername) {
9306
- throw new CliError23({
9307
- code: CliErrorCode22.INVALID_ARGUMENT,
8554
+ throw new CliError21({
8555
+ code: CliErrorCode20.INVALID_ARGUMENT,
9308
8556
  message: "--id <uuid> \u4E0E --username <user> \u5FC5\u987B\u4E14\u53EA\u80FD\u63D0\u4F9B\u4E00\u4E2A"
9309
8557
  });
9310
8558
  }
9311
8559
  if (!password) {
9312
- throw new CliError23({
9313
- code: CliErrorCode22.INVALID_ARGUMENT,
8560
+ throw new CliError21({
8561
+ code: CliErrorCode20.INVALID_ARGUMENT,
9314
8562
  message: "\u65B0\u5BC6\u7801\u4E0D\u80FD\u4E3A\u7A7A"
9315
8563
  });
9316
8564
  }
@@ -9326,9 +8574,9 @@ async function userResetPasswordCommand(args) {
9326
8574
  try {
9327
8575
  const password = args.passwordStdin ? await readSecretFromStdin() : await promptPasswordTwice();
9328
8576
  const request = buildAdminResetPasswordRequest(args, password);
9329
- const client3 = HcmClient20.fromAuthContext(await getActiveAuthContextFromCli(args));
9330
- const result2 = await adminResetPassword(client3.raw(), request);
9331
- process.stdout.write(formatObject23(result2, { format: args.output ?? "json" }) + "\n");
8577
+ const client3 = HcmClient21.fromAuthContext(await getActiveAuthContextFromCli(args));
8578
+ const result = await adminResetPassword(client3.raw(), request);
8579
+ process.stdout.write(formatObject23(result, { format: args.output ?? "json" }) + "\n");
9332
8580
  } catch (cause) {
9333
8581
  const err = cause;
9334
8582
  if (err?.isAxiosError) exitWithError(fromAxiosError19(err, args.env));
@@ -9339,8 +8587,8 @@ async function promptPasswordTwice() {
9339
8587
  const password = await promptSecret("\u65B0\u5BC6\u7801: ");
9340
8588
  const confirmation = await promptSecret("\u518D\u6B21\u8F93\u5165\u65B0\u5BC6\u7801: ");
9341
8589
  if (password !== confirmation) {
9342
- throw new CliError23({
9343
- code: CliErrorCode22.INVALID_ARGUMENT,
8590
+ throw new CliError21({
8591
+ code: CliErrorCode20.INVALID_ARGUMENT,
9344
8592
  message: "\u4E24\u6B21\u8F93\u5165\u7684\u65B0\u5BC6\u7801\u4E0D\u4E00\u81F4"
9345
8593
  });
9346
8594
  }
@@ -9402,6 +8650,15 @@ delivery.command("gate0").description(
9402
8650
  "--mapping <file>",
9403
8651
  "\u987E\u95EE\u624B\u5199\u7684\u6620\u5C04\u5DE5\u4EF6\uFF08naturalKey \u8FD9\u4E00\u7C7B\u7684\u552F\u4E00\u6765\u6E90\uFF09\uFF1B\u4E0D\u7ED9 \u21D2 \u90A3\u4E00\u7C7B\u6052\u7EFF \u21D2 rc=2"
9404
8652
  ).option("--output <fmt>", "\u8F93\u51FA\u683C\u5F0F\uFF1Atable | json | yaml", "json").action((opts) => deliveryGate0Command(opts));
8653
+ delivery.command("triage").description(
8654
+ "\u9700\u6C42\u5206\u8BCA\uFF1A\u516D\u7C7B\u627F\u8F7D\u7269\u7531\u672C\u547D\u4EE4\u73B0\u63A2\u73B0\u586B\uFF08\u987E\u95EE\u8DF3\u4E0D\u4E86\u6B65\uFF09\uFF0C\u7ED3\u8BBA\u4E0E\u8BC1\u636E\u7531\u4F60\u7ED9\uFF0C\u5B83\u53EA\u5224\u4E24\u8005\u6253\u4E0D\u6253\u67B6"
8655
+ ).requiredOption(
8656
+ "--requests <file>",
8657
+ '\u5F85\u5206\u8BCA\u7684\u9700\u6C42\u6E05\u5355\uFF08**\u8FD9\u53F0\u673A\u5668\u4E0A**\u7684\u4E00\u4EFD JSON \u6570\u7EC4\uFF09\uFF1A\u6BCF\u6761 `{"request":\u5BA2\u6237\u539F\u8BDD, "verdict":REUSE|CONFIG|EXTEND|GAP, "evidence":\u51ED\u4EC0\u4E48\u8FD9\u4E48\u5224, "debtAction":\u7F3A\u54EA\u4E2A Action\uFF08GAP \u65F6\uFF09, "blindAcknowledged":true\uFF08\u5224 GAP \u4E14\u6709\u76F2\u533A\u65F6\u5FC5\u987B\u663E\u5F0F\u627F\u8BA4\uFF09}`'
8658
+ ).option(
8659
+ "--recon <dir>",
8660
+ "\u57FA\u7EBF\u4EA7\u7269\u76EE\u5F55\uFF08<out>/recon/<\u79DF\u6237\u6BB5>/<\u6765\u6E90\u6BB5>\uFF09\uFF1B\u4E0D\u7ED9\u5219\u6309\u722C\u53D6\u8EAB\u4EFD\u73B0\u7B97\u4E00\u4EFD"
8661
+ ).option("--out <dir>", "\u4EA7\u7269\u6839\uFF08\u5199 work/triage.md\uFF09", ".").option("--capabilities <caps>", "\u672C\u6B21\u63A2\u6D4B\u58F0\u660E\u7684 capability \u4E32", "default").action((opts) => deliveryTriageCommand(opts));
9405
8662
  delivery.command("prepare").description("\u628A\u53D7\u652F\u6301\u7684 R2 argv \u4E0E\u9501\u3001\u8FD0\u884C\u65F6\u548C\u53D8\u66F4/\u56DE\u6EDA\u8BF4\u660E\u7ED1\u5B9A\u4E3A\u77ED\u65F6\u6267\u884C\u8BA1\u5212").requiredOption("--change-ref <file>", "\u9879\u76EE work/ \u6216 decisions/ \u4E0B\u7684\u53D8\u66F4\u8BF4\u660E").requiredOption("--rollback-ref <file>", "\u9879\u76EE work/ \u6216 decisions/ \u4E0B\u7684\u56DE\u6EDA\u8BF4\u660E").requiredOption("--evidence-dir <dir>", "\u9879\u76EE evidence/ \u4E0B\u7684\u6536\u636E\u76EE\u5F55").option("--project <dir>", "HCM \u987E\u95EE\u9879\u76EE\u6839\u76EE\u5F55", ".").option("--ttl-seconds <n>", "\u6709\u6548\u671F\u79D2\u6570\uFF0860-3600\uFF09", "900").option("--output <fmt>", "\u8F93\u51FA\u683C\u5F0F\uFF1Atable | json | yaml", "json").allowUnknownOption(true).argument("<command...>", "\u88AB\u7ED1\u5B9A\u7684 R2 HCM \u5B50\u547D\u4EE4\u4E0E\u53C2\u6570\uFF0C\u4E0D\u5305\u542B hcm \u672C\u8EAB").action((command, opts) => deliveryPrepareCommand(command, opts));
9406
8663
  delivery.command("execute <planId>").description("\u9010\u6B21\u6279\u51C6\u540E\u6D88\u8D39\u77ED\u65F6\u8BA1\u5212\uFF0C\u5E76\u6267\u884C\u4E00\u6B21\u4E0E\u8BA1\u5212\u5B8C\u5168\u76F8\u540C\u7684 R2 argv").option("--project <dir>", "HCM \u987E\u95EE\u9879\u76EE\u6839\u76EE\u5F55", ".").option("--output <fmt>", "\u6536\u636E\u8F93\u51FA\u683C\u5F0F\uFF1Atable | json | yaml", "json").allowUnknownOption(true).argument("<command...>", "\u4E0E prepare \u5B8C\u5168\u76F8\u540C\u7684 R2 HCM \u5B50\u547D\u4EE4\u4E0E\u53C2\u6570").action((planId, command, opts) => deliveryExecuteCommand(planId, command, opts));
9407
8664
  program.command("query <Model>").description("\u67E5\u8BE2 Model \u5217\u8868\u6570\u636E\uFF08\u901A\u8FC7 ModelQueryDsl JSON \u8868\u8FBE\u8FC7\u6EE4/\u6392\u5E8F/\u5206\u9875\uFF09").option(
@@ -9468,7 +8725,6 @@ skills.command("list [keyword]").description("\u5217\u51FA\u76EE\u6807\u73AF\u58
9468
8725
  skills.command("manifest").description("\u6253\u5370\u672C CLI \u7684\u547D\u4EE4\u9762\u4E0E\u81EA\u5E26\u6280\u80FD\u6E05\u5355\uFF08\u4E0D\u8FDE\u7F51\uFF0C\u4F9B\u5B88\u536B\u4E0E\u5916\u90E8\u5DE5\u5177\u6BD4\u5BF9\uFF09").option("--output <fmt>", "\u8F93\u51FA\u683C\u5F0F\uFF1Atable | json | yaml", "json").action((opts) => skillsManifestCommand(program, opts));
9469
8726
  skills.command("show <id>").description("\u6253\u5370\u6280\u80FD\u539F\u6587\uFF08\u7BA1\u9053\u53CB\u597D\uFF09\uFF1B\u81EA\u5E26\u6280\u80FD\u76F4\u63A5\u8BFB\u672C\u5730\uFF0C\u4E0D\u8FDE\u7F51").option("--source <kind>", "\u8FD9\u4E00\u8D9F\u770B\u54EA\u4E9B\u6765\u6E90\uFF1Acli\uFF08\u53EA\u770B\u81EA\u5E26\uFF0C\u4E0D\u8FDE\u7F51\uFF09| chiron | all", "all").option("--endpoint <url>", "\u6280\u80FD\u5E93\u5730\u5740\uFF08\u9ED8\u8BA4\u53D6 activeEnv \u7684 endpoint\uFF09").option("--env <name>", "\u4ECE\u8BE5 env \u89E3\u6790 endpoint").action((id, opts) => skillsShowCommand(id, opts));
9470
8727
  skills.command("install [id]").description("\u8FDE\u540C requires \u524D\u7F6E\u6280\u80FD\u4E0E\u53C2\u8003\u6587\u4EF6\u88C5\u5230 agent \u6280\u80FD\u76EE\u5F55\uFF1B--all \u88C5\u6574\u4E2A\u6280\u80FD\u5E93").option("--all", "\u88C5\u6574\u4E2A\u6280\u80FD\u5E93\uFF0C\u5E76\u8BB0\u4E3A\u300C\u8DDF\u968F\u5168\u96C6\u300D\uFF08\u5F80\u540E update \u4F1A\u81EA\u52A8\u8865\u4E0A\u4EA7\u54C1\u65B0\u589E\u7684\u6280\u80FD\uFF09").option("--target <agent>", "\u88C5\u7ED9\u54EA\u4E2A agent\uFF1Aclaude\uFF08.claude/skills/\uFF09| codex\uFF08hcm-skills/ + AGENTS.md\uFF09| auto", "auto").option("--global", "\u88C5\u5230\u7528\u6237\u7EA7\u76EE\u5F55\u800C\u975E\u5F53\u524D\u9879\u76EE").option("--dir <path>", "\u88C5\u5230\u6307\u5B9A\u76EE\u5F55").option("--from <dir>", "\u4ECE\u672C\u5730\u76EE\u5F55\u88C5\uFF08\u73B0\u573A\u6539\u8FC7\u7684\u7248\u672C\uFF09\uFF0C\u4E0D\u8D70\u7F51\u7EDC").option("--source <kind>", "\u8FD9\u4E00\u8D9F\u770B\u54EA\u4E9B\u6765\u6E90\uFF1Acli\uFF08\u53EA\u770B\u81EA\u5E26\uFF0C\u4E0D\u8FDE\u7F51\uFF09| chiron | all", "all").option("--force", "\u8986\u76D6\u5DF2\u5B58\u5728\u7684\u540C\u540D\u6280\u80FD").option("--endpoint <url>", "\u6280\u80FD\u5E93\u5730\u5740\uFF08\u9ED8\u8BA4\u53D6 activeEnv \u7684 endpoint\uFF09").option("--env <name>", "\u4ECE\u8BE5 env \u89E3\u6790 endpoint").option("--output <fmt>", "\u8F93\u51FA\u683C\u5F0F\uFF1Atable | json | yaml", "table").action((id, opts) => skillsInstallCommand(id, opts));
9471
- skills.command("sync <id>").description("\u4ECE\u76EE\u6807\u5B9E\u4F8B\u540C\u6B65 Skill \u95ED\u5305\u5230 WorkBuddy \u9879\u76EE\u5E76\u5199 chiron.lock").requiredOption("--target <agent>", "\u76EE\u6807 Agent \u5BBF\u4E3B\uFF1B\u5F53\u524D\u652F\u6301 workbuddy").requiredOption("--project <path>", "WorkBuddy \u9879\u76EE\u6839\u76EE\u5F55").option("--cli <path>", "\u663E\u5F0F\u6307\u5B9A\u8981\u9501\u5B9A\u5230\u9879\u76EE\u7684 HCM CLI\uFF1B\u9ED8\u8BA4\u4F7F\u7528\u5F53\u524D\u8FD9\u4EFD CLI").option("--endpoint <url>", "\u6280\u80FD\u5E93\u5730\u5740\uFF08\u9ED8\u8BA4\u53D6 activeEnv \u7684 endpoint\uFF09").option("--env <name>", "\u4ECE\u8BE5 env \u89E3\u6790 endpoint").option("--output <fmt>", "\u8F93\u51FA\u683C\u5F0F\uFF1Atable | json | yaml", "table").action((id, opts) => skillsSyncCommand(id, opts));
9472
8728
  skills.command("update").description("\u628A\u88C5\u8FC7\u7684\u6280\u80FD\u5347\u5230\u76EE\u6807\u73AF\u5883\u8FD9\u4E00\u7248\uFF08\u4EA7\u54C1\u5347\u7EA7\u540E\u8DD1\u5B83\uFF09").option("--all", "\u8FDE\u4EA7\u54C1\u65B0\u589E\u7684\u6280\u80FD\u4E00\u8D77\u88C5\u4E0A\uFF0C\u5E76\u8BB0\u4E3A\u300C\u8DDF\u968F\u5168\u96C6\u300D").option("--check", "\u53EA\u770B\u4F1A\u53D8\u4EC0\u4E48\uFF0C\u4E0D\u5199\u76D8").option("--target <agent>", "claude | codex | auto\uFF08\u9ED8\u8BA4\u6309\u5DF2\u5B89\u88C5\u76EE\u5F55\u63A2\uFF09", "auto").option("--global", "\u5347\u7EA7\u7528\u6237\u7EA7\u76EE\u5F55\u91CC\u7684\u6280\u80FD").option("--dir <path>", "\u5347\u7EA7\u6307\u5B9A\u76EE\u5F55\u91CC\u7684\u6280\u80FD").option("--force", "\u8FDE\u672C\u5730\u6539\u8FC7\u7684\u6280\u80FD\u4E00\u8D77\u8986\u76D6\u6210\u4EA7\u54C1\u8FD9\u4E00\u7248").option("--source <kind>", "\u8FD9\u4E00\u8D9F\u770B\u54EA\u4E9B\u6765\u6E90\uFF1Acli\uFF08\u53EA\u770B\u81EA\u5E26\uFF0C\u4E0D\u8FDE\u7F51\uFF09| chiron | all", "all").option("--endpoint <url>", "\u6280\u80FD\u5E93\u5730\u5740\uFF08\u9ED8\u8BA4\u53D6\u5B89\u88C5\u65F6\u8BB0\u5F55\u7684\u5730\u5740\uFF09").option("--env <name>", "\u4ECE\u8BE5 env \u89E3\u6790 endpoint").option("--output <fmt>", "\u8F93\u51FA\u683C\u5F0F\uFF1Atable | json | yaml", "table").action((opts) => skillsUpdateCommand(opts));
9473
8729
  program.command("update <Model>").description("\u66F4\u65B0\u4E00\u6761 Model \u8BB0\u5F55\uFF08\u8D70\u540E\u7AEF\u5B8C\u6574\u6821\u9A8C\uFF09").requiredOption("--id <id>", "\u8BB0\u5F55 ID").option("--data <JSON>", `\u8981\u66F4\u65B0\u7684\u5B57\u6BB5 JSON\uFF0C\u4F8B\u5982 '{"name":"\u65B0\u540D\u79F0"}'`).option("--data-file <path>", "\u4ECE UTF-8 JSON \u6587\u4EF6\u8BFB\u53D6\u66F4\u65B0\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("--output <fmt>", "\u8F93\u51FA\u683C\u5F0F\uFF1Atable | json | yaml", "json").action((model, opts) => updateCommand(model, opts));
9474
8730
  program.command("version").description("\u67E5\u540E\u7AEF\u7248\u672C\uFF08commit / tag / \u6784\u5EFA\u65F6\u95F4\uFF09\u2014\u2014\u514D\u8BA4\u8BC1\uFF0C\u65E0\u9700\u5148 login").option("--endpoint <url>", "\u540E\u7AEF\u5730\u5740\uFF08\u9ED8\u8BA4\u53D6 activeEnv \u7684 endpoint\uFF09").option("--env <name>", "\u4ECE\u8BE5 env \u89E3\u6790 endpoint").option("--output <fmt>", "\u8F93\u51FA\u683C\u5F0F\uFF1Atable | json | yaml", "json").action((opts) => versionCommand(opts));