@hcmai/cli 0.3.4 → 0.3.6

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(path7) {
527
- const segs = path7.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";
@@ -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(path7) {
1710
- const segs = (path7 ?? "").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
  }
@@ -2286,9 +2286,9 @@ async function loginCommand(args) {
2286
2286
  } catch (e) {
2287
2287
  const err = e;
2288
2288
  if (err.isAxiosError) {
2289
- const { fromAxiosError: fromAxiosError18 } = await import("@hcmai/sdk");
2289
+ const { fromAxiosError: fromAxiosError19 } = await import("@hcmai/sdk");
2290
2290
  exitWithError(
2291
- fromAxiosError18(
2291
+ fromAxiosError19(
2292
2292
  e,
2293
2293
  envName
2294
2294
  )
@@ -3059,8 +3059,8 @@ import {
3059
3059
  formatObject as formatObject7,
3060
3060
  fromAxiosError as fromAxiosError8
3061
3061
  } from "@hcmai/sdk";
3062
- function collectYmlFiles(path7) {
3063
- if (statSync(path7).isFile()) return [path7];
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(path7) {
3069
3069
  else if (full.endsWith(".yml") || full.endsWith(".yaml")) out.push(full);
3070
3070
  }
3071
3071
  };
3072
- walk(path7);
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(path7, args) {
3080
+ async function importCommand(path9, args) {
3081
3081
  try {
3082
- const files = collectYmlFiles(path7);
3082
+ const files = collectYmlFiles(path9);
3083
3083
  const fixtures = files.map(
3084
3084
  (f) => parseFixture(readFileSync2(f, "utf8"), relative(process.cwd(), f))
3085
3085
  );
@@ -4278,10 +4278,10 @@ async function uploadCommand(filePath, args) {
4278
4278
 
4279
4279
  // src/commands/skills.ts
4280
4280
  init_exit();
4281
- import { promises as fsp } from "fs";
4281
+ import { promises as fsp2 } from "fs";
4282
4282
  import os2 from "os";
4283
- import path4 from "path";
4284
- import { createHash as createHash3 } from "crypto";
4283
+ import path6 from "path";
4284
+ import { createHash as createHash4 } from "crypto";
4285
4285
  import {
4286
4286
  createHttpClient as createHttpClient2,
4287
4287
  fetchSkillCatalog,
@@ -4290,31 +4290,316 @@ import {
4290
4290
  fetchSkillReference,
4291
4291
  resolveChironBase,
4292
4292
  assertSafeSkillId as assertSafeSkillId2,
4293
- assertSafeReferencePath,
4293
+ assertSafeReferencePath as assertSafeReferencePath2,
4294
4294
  normalizeReferences as normalizeReferences2,
4295
- parseSkillRequirements,
4296
- parseSkillFrontmatter,
4295
+ parseSkillRequirements as parseSkillRequirements2,
4296
+ parseSkillFrontmatter as parseSkillFrontmatter2,
4297
4297
  resolveSkillInstallOrder as resolveSkillInstallOrder2,
4298
4298
  resolveAllSkillsInstallOrder,
4299
- flattenSkills,
4300
4299
  matchSkills,
4301
4300
  filterByStage,
4302
- formatObject as formatObject13,
4301
+ formatObject as formatObject14,
4303
4302
  fromAxiosError as fromAxiosError13,
4304
4303
  loadEnv as loadEnv5,
4305
4304
  loadGlobalConfig as loadGlobalConfig6,
4306
4305
  resolveActiveEnv as resolveActiveEnv3,
4307
- CliError as CliError16,
4308
- CliErrorCode as CliErrorCode15
4306
+ CliError as CliError18,
4307
+ CliErrorCode as CliErrorCode17
4309
4308
  } from "@hcmai/sdk";
4310
4309
 
4311
- // src/commands/skills-sync.ts
4310
+ // src/commands/skills-catalog.ts
4311
+ import { flattenSkills, CliError as CliError14, CliErrorCode as CliErrorCode13 } from "@hcmai/sdk";
4312
+ var CLI_CATEGORY_KEY = "cli-operations";
4313
+ var CLI_CATEGORY_NAME = "CLI \u64CD\u4F5C";
4314
+ function chironEntry(skill) {
4315
+ return {
4316
+ meta: {
4317
+ id: skill.id,
4318
+ title: skill.title,
4319
+ description: skill.description,
4320
+ category: skill.category,
4321
+ stages: skill.stages ?? [],
4322
+ actionSurface: skill.actionSurface,
4323
+ requires: skill.requires,
4324
+ bytes: skill.bytes,
4325
+ files: skill.files
4326
+ },
4327
+ locator: { kind: "chiron", markdownUrl: skill.markdownUrl }
4328
+ };
4329
+ }
4330
+ function bundledEntry(entry, cliVersion) {
4331
+ return {
4332
+ meta: {
4333
+ id: entry.id,
4334
+ title: entry.title ?? entry.id,
4335
+ description: entry.description ?? "",
4336
+ category: entry.category ?? CLI_CATEGORY_KEY,
4337
+ stages: entry.stages ?? [],
4338
+ // 自带技能讲的就是本 CLI 的命令,恒为 cli。
4339
+ actionSurface: "cli",
4340
+ requires: entry.requires,
4341
+ bytes: entry.bytes,
4342
+ files: entry.files
4343
+ },
4344
+ locator: { kind: "cli", packagePath: `skills/${entry.id}`, cliVersion }
4345
+ };
4346
+ }
4347
+ function cliLocatorString(id, cliVersion) {
4348
+ return `@hcmai/cli@${cliVersion}:skills/${id}`;
4349
+ }
4350
+ var SOURCE_FILTERS = ["cli", "chiron", "all"];
4351
+ function parseSourceFilter(raw) {
4352
+ if (raw === void 0) return "all";
4353
+ if (SOURCE_FILTERS.includes(raw)) return raw;
4354
+ throw new CliError14({
4355
+ code: CliErrorCode13.INVALID_ARGUMENT,
4356
+ message: `--source \u53EA\u8BA4 ${SOURCE_FILTERS.join(" / ")}\uFF0C\u6536\u5230 "${raw}"\u3002\uFF08\`local\` \u4E0D\u662F\u53D6\u503C\uFF1A\u6CA1\u6709\u54EA\u4E00\u8D9F\u4F1A\u53BB\u300C\u626B local \u6765\u6E90\u300D\uFF0Cinstall --from \u88C5\u7684\u90A3\u4E9B\u5728\u4EFB\u4F55 --source \u4E0B\u90FD\u5355\u5217\u3001\u90FD\u4E0D\u53C2\u4E0E\u5347\u7EA7\u3002\uFF09`
4357
+ });
4358
+ }
4359
+ function emptyHalf() {
4360
+ return { status: "skipped", entries: /* @__PURE__ */ new Map() };
4361
+ }
4362
+ function buildUnifiedCatalog(input) {
4363
+ const chiron = emptyHalf();
4364
+ const cli = emptyHalf();
4365
+ if (input.source !== "cli" && input.chironManifest) {
4366
+ chiron.status = "fetched";
4367
+ for (const skill of flattenSkills(input.chironManifest)) chiron.entries.set(skill.id, chironEntry(skill));
4368
+ }
4369
+ if (input.source !== "chiron" && input.bundled) {
4370
+ cli.status = "fetched";
4371
+ for (const entry of input.bundled) cli.entries.set(entry.id, bundledEntry(entry, input.cliVersion));
4372
+ }
4373
+ return { chiron, cli };
4374
+ }
4375
+ function detectIdConflicts(catalog) {
4376
+ if (catalog.chiron.status !== "fetched" || catalog.cli.status !== "fetched") {
4377
+ return { checked: false, ids: [] };
4378
+ }
4379
+ const ids = [...catalog.cli.entries.keys()].filter((id) => catalog.chiron.entries.has(id)).sort();
4380
+ return { checked: true, ids };
4381
+ }
4382
+ function conflictMessage(ids, endpoint) {
4383
+ return `\u6280\u80FD id \`${ids.join("`\u3001`")}\` \u5728 CLI \u81EA\u5E26\u4E0E ${endpoint} \u7684\u777F\u620E\u76EE\u5F55\u91CC\u540C\u65F6\u5B58\u5728\u3002
4384
+ \u4E24\u8FB9\u5404\u81EA\u4E3B\u5F20\u7684\u4E1C\u897F\u4E0D\u540C\uFF0C\u53D6\u4EFB\u4F55\u4E00\u4EFD\u90FD\u4F1A\u8BA9\u53E6\u4E00\u4EFD\u7684\u8BFB\u8005\u62FF\u5230\u9519\u7684\u5408\u540C\u3002
4385
+ \u51FA\u8DEF\u53EA\u6709\u4E24\u6761\uFF1A\u2460 \u5347\u7EA7 CLI\uFF08\u4EA7\u54C1\u628A\u5B83\u6536\u7F16\u4E86\uFF0C\u65B0\u7248 CLI \u4F1A\u64A4\u6389\u81EA\u5E26\u7684\u90A3\u4EFD\uFF09\uFF1B
4386
+ \u2461 \u8FD9\u662F\u4E00\u6B21\u5F52\u5C5E\u672A\u5B9A\uFF0C\u628A id \u4E0E\u4E24\u5904\u51FA\u5904\u62A5\u7ED9\u4EA7\u54C1\u4FA7\u88C1\u51B3\u3002`;
4387
+ }
4388
+ function unconfirmedConflictNote(source) {
4389
+ return `\u672C\u8D9F\u53EA\u770B\u4E86${source === "cli" ? "CLI \u81EA\u5E26" : "\u777F\u620E"}\u6765\u6E90\uFF0C\u672A\u505A\u8DE8\u6765\u6E90\u51B2\u7A81\u68C0\u67E5`;
4390
+ }
4391
+ function classifyInstalledSource(id, record, catalog) {
4392
+ const kind = record.sourceKind ?? "chiron";
4393
+ if (kind === "local") return "local";
4394
+ const half = kind === "cli" ? catalog.cli : catalog.chiron;
4395
+ if (half.status !== "fetched") return "not-checked";
4396
+ if (half.entries.has(id)) return "present";
4397
+ return kind === "cli" ? "removed-in-cli" : "removed-upstream";
4398
+ }
4399
+ var SOURCE_STATUS_NOTE = {
4400
+ "removed-upstream": "\u4EA7\u54C1\u8FD9\u4E00\u7248\u7684\u6280\u80FD\u76EE\u5F55\u91CC\u5DF2\u7ECF\u6CA1\u6709\u5B83\u4E86\uFF1B\u672C\u5730\u6587\u4EF6\u4FDD\u7559\u4E0D\u52A8",
4401
+ "removed-in-cli": "\u8FD9\u4E00\u7248 CLI \u4E0D\u518D\u81EA\u5E26\u5B83\uFF08\u591A\u534A\u662F\u88AB\u4EA7\u54C1\u6536\u7F16\u4E86\uFF0C\u8DD1 hcm skills list \u770B\u770B\uFF09",
4402
+ "not-checked": "\u672C\u8F6E\u6CA1\u8FDE\u7F51\u6838\u5BF9\u5B83\u7684\u6765\u6E90\uFF08--source cli\uFF09\uFF0C\u5B83\u662F\u4E0D\u662F\u8FD8\u5728\u4EA7\u54C1\u76EE\u5F55\u91CC\u8FD9\u4E00\u8D9F\u4E0D\u77E5\u9053",
4403
+ local: "\u672C\u5730\u6765\u6E90\uFF08install --from \u88C5\u7684\uFF09\uFF0Cupdate \u4E0D\u7BA1\u5B83\uFF1B\u8981\u66F4\u65B0\u5C31\u518D install --from \u4E00\u6B21"
4404
+ };
4405
+ function checkCrossSourceRequires(catalog) {
4406
+ if (catalog.chiron.status !== "fetched" || catalog.cli.status !== "fetched") return [];
4407
+ const out = [];
4408
+ for (const [id, entry] of catalog.chiron.entries) {
4409
+ for (const need of entry.meta.requires ?? []) {
4410
+ if (catalog.chiron.entries.has(need)) continue;
4411
+ if (catalog.cli.entries.has(need)) {
4412
+ out.push({
4413
+ from: id,
4414
+ to: need,
4415
+ reason: "\u777F\u620E\u6280\u80FD\u4E0D\u5F97\u4F9D\u8D56 CLI \u81EA\u5E26\u6280\u80FD\uFF1A\u4EA7\u54C1\u77E5\u8BC6\u7684\u53EF\u8BFB\u6027\u4E0D\u80FD\u53D6\u51B3\u4E8E\u987E\u95EE\u88C5\u4E86\u54EA\u7248 CLI"
4416
+ });
4417
+ }
4418
+ }
4419
+ }
4420
+ return out;
4421
+ }
4422
+
4423
+ // src/commands/skills-bundled.ts
4424
+ import { promises as fsp } from "fs";
4425
+ import * as path3 from "path";
4426
+ import { CliError as CliError15, CliErrorCode as CliErrorCode14, assertSafeReferencePath, parseSkillRequirements } from "@hcmai/sdk";
4427
+
4428
+ // src/commands/skills-manifest.ts
4429
+ import { readFileSync as readFileSync3, readdirSync as readdirSync2, statSync as statSync3, existsSync } from "fs";
4312
4430
  import { createHash } from "crypto";
4431
+ import * as path2 from "path";
4432
+ import { fileURLToPath } from "url";
4433
+ import { formatObject as formatObject13, parseSkillFrontmatter } from "@hcmai/sdk";
4434
+ function collectCommandSurface(root) {
4435
+ const out = [];
4436
+ const walk = (cmd, prefix) => {
4437
+ for (const sub of cmd.commands) {
4438
+ const segs = [...prefix, sub.name()];
4439
+ const options = sub.options.map((o) => /(--[a-zA-Z0-9][\w-]*)/.exec(o.flags)?.[1] ?? "").filter((s) => s.length > 0);
4440
+ out.push({ path: segs.join(" "), options: [...new Set(options)].sort() });
4441
+ walk(sub, segs);
4442
+ }
4443
+ };
4444
+ walk(root, []);
4445
+ return out.sort((a, b) => a.path.localeCompare(b.path));
4446
+ }
4447
+ function bundledSkillsDir() {
4448
+ const here = path2.dirname(fileURLToPath(import.meta.url));
4449
+ return path2.join(here, "skills");
4450
+ }
4451
+ function sha256(buf) {
4452
+ return createHash("sha256").update(buf).digest("hex");
4453
+ }
4454
+ function listFiles(dir, rel = "") {
4455
+ const out = [];
4456
+ for (const name of readdirSync2(dir)) {
4457
+ const p = path2.join(dir, name);
4458
+ const r = rel ? `${rel}/${name}` : name;
4459
+ if (statSync3(p).isDirectory()) out.push(...listFiles(p, r));
4460
+ else out.push(r);
4461
+ }
4462
+ return out;
4463
+ }
4464
+ function collectBundledSkills(dir = bundledSkillsDir()) {
4465
+ if (!existsSync(dir)) return [];
4466
+ const out = [];
4467
+ for (const id of readdirSync2(dir).sort()) {
4468
+ const skillDir = path2.join(dir, id);
4469
+ if (!statSync3(skillDir).isDirectory()) continue;
4470
+ const files = listFiles(skillDir).sort();
4471
+ if (!files.includes("SKILL.md")) continue;
4472
+ let bytes = 0;
4473
+ const fileRows = files.map((rel) => {
4474
+ const buf = readFileSync3(path2.join(skillDir, rel));
4475
+ bytes += buf.byteLength;
4476
+ return { path: rel, bytes: buf.byteLength, sha256: sha256(buf) };
4477
+ });
4478
+ const body = readFileSync3(path2.join(skillDir, "SKILL.md"), "utf8");
4479
+ const fm = parseSkillFrontmatter(body, id);
4480
+ out.push({
4481
+ id,
4482
+ title: str(fm.title),
4483
+ description: str(fm.description),
4484
+ category: str(fm.category),
4485
+ stages: strArray(fm.stages),
4486
+ actionSurface: str(fm.actionSurface),
4487
+ requires: strArray(fm.requires),
4488
+ bytes,
4489
+ files: fileRows
4490
+ });
4491
+ }
4492
+ return out;
4493
+ }
4494
+ function buildManifest(root, skillsDir = bundledSkillsDir()) {
4495
+ return {
4496
+ schemaVersion: 1,
4497
+ cliVersion: CLI_VERSION,
4498
+ commands: collectCommandSurface(root),
4499
+ skills: collectBundledSkills(skillsDir)
4500
+ };
4501
+ }
4502
+ function skillsManifestCommand(root, args) {
4503
+ const manifest2 = buildManifest(root);
4504
+ process.stdout.write(formatObject13(manifest2, { format: args.output ?? "json" }) + "\n");
4505
+ }
4506
+ function str(v) {
4507
+ return typeof v === "string" && v ? v : void 0;
4508
+ }
4509
+ function strArray(v) {
4510
+ return Array.isArray(v) ? v.map(String) : void 0;
4511
+ }
4512
+
4513
+ // src/commands/skills-bundled.ts
4514
+ function listBundledSkills(dir = bundledSkillsDir()) {
4515
+ return collectBundledSkills(dir);
4516
+ }
4517
+ function unreachable(id, detail) {
4518
+ return new CliError15({
4519
+ code: CliErrorCode14.SKILL_SOURCE_UNREACHABLE,
4520
+ message: `\u88C5\u5728\u8FD9\u4EFD CLI \u91CC\u7684\u6280\u80FD\u8D44\u6E90\u8BFB\u4E0D\u5230\uFF08${detail}\uFF09\uFF0C\u91CD\u88C5 @hcmai/cli\u3002
4521
+ \u6280\u80FD id\uFF1A${id}\uFF1B\u627E\u7684\u4F4D\u7F6E\uFF1A${bundledSkillsDir()}`
4522
+ });
4523
+ }
4524
+ async function readBundledReferences(skillDir) {
4525
+ const root = path3.join(skillDir, "references");
4526
+ const out = [];
4527
+ const walk = async (dir, prefix) => {
4528
+ let items;
4529
+ try {
4530
+ items = await fsp.readdir(dir, { withFileTypes: true });
4531
+ } catch (cause) {
4532
+ if (cause?.code === "ENOENT") return;
4533
+ throw cause;
4534
+ }
4535
+ for (const item of items.sort((a, b) => a.name.localeCompare(b.name))) {
4536
+ const relative2 = prefix ? `${prefix}/${item.name}` : item.name;
4537
+ if (item.isDirectory()) {
4538
+ await walk(path3.join(dir, item.name), relative2);
4539
+ continue;
4540
+ }
4541
+ if (!item.isFile()) continue;
4542
+ assertSafeReferencePath(relative2);
4543
+ out.push({ path: relative2, content: await fsp.readFile(path3.join(dir, item.name), "utf8") });
4544
+ }
4545
+ };
4546
+ await walk(root, "");
4547
+ return out;
4548
+ }
4549
+ async function readBundledSkillDocument(id, dir = bundledSkillsDir()) {
4550
+ const skillDir = path3.join(dir, id);
4551
+ let markdown;
4552
+ try {
4553
+ markdown = await fsp.readFile(path3.join(skillDir, "SKILL.md"), "utf8");
4554
+ } catch (cause) {
4555
+ if (cause?.code === "ENOENT") throw unreachable(id, "SKILL.md \u4E0D\u5B58\u5728");
4556
+ throw cause;
4557
+ }
4558
+ if (!markdown.trim()) throw unreachable(id, "SKILL.md \u662F\u7A7A\u7684");
4559
+ return {
4560
+ id,
4561
+ markdown,
4562
+ source: cliLocatorString(id, CLI_VERSION),
4563
+ sourceKind: "cli",
4564
+ references: await readBundledReferences(skillDir)
4565
+ };
4566
+ }
4567
+ async function resolveBundledClosure(targetId, dir = bundledSkillsDir()) {
4568
+ const documents = [];
4569
+ const external = /* @__PURE__ */ new Set();
4570
+ const state = /* @__PURE__ */ new Map();
4571
+ const stack = [];
4572
+ const available = new Set(listBundledSkills(dir).map((s) => s.id));
4573
+ const visit = async (id) => {
4574
+ if (state.get(id) === "done") return;
4575
+ if (state.get(id) === "visiting") {
4576
+ throw new CliError15({
4577
+ code: CliErrorCode14.INVALID_ARGUMENT,
4578
+ message: `\u81EA\u5E26\u6280\u80FD\u4F9D\u8D56\u6210\u73AF\uFF1A${[...stack, id].join(" \u2192 ")}`
4579
+ });
4580
+ }
4581
+ state.set(id, "visiting");
4582
+ stack.push(id);
4583
+ const document = await readBundledSkillDocument(id, dir);
4584
+ for (const need of parseSkillRequirements(document.markdown, id)) {
4585
+ if (available.has(need)) await visit(need);
4586
+ else external.add(need);
4587
+ }
4588
+ stack.pop();
4589
+ state.set(id, "done");
4590
+ documents.push(document);
4591
+ };
4592
+ await visit(targetId);
4593
+ return { documents, external: [...external].sort() };
4594
+ }
4595
+
4596
+ // src/commands/skills-sync.ts
4597
+ import { createHash as createHash2 } from "crypto";
4313
4598
  import { promises as fs5 } from "fs";
4314
- import path2 from "path";
4599
+ import path4 from "path";
4315
4600
  import {
4316
- CliError as CliError14,
4317
- CliErrorCode as CliErrorCode13,
4601
+ CliError as CliError16,
4602
+ CliErrorCode as CliErrorCode15,
4318
4603
  assertSafeSkillFilePath,
4319
4604
  assertSafeSkillId,
4320
4605
  normalizeReferences,
@@ -4347,7 +4632,7 @@ async function prepareSkillDocuments(catalog, requestedSkill, fetchMarkdown, fet
4347
4632
  path: targetPath,
4348
4633
  content: referenceContent,
4349
4634
  bytes: referenceContent.length,
4350
- sha256: sha256(referenceContent)
4635
+ sha256: sha2562(referenceContent)
4351
4636
  };
4352
4637
  })
4353
4638
  );
@@ -4356,7 +4641,7 @@ async function prepareSkillDocuments(catalog, requestedSkill, fetchMarkdown, fet
4356
4641
  path: "SKILL.md",
4357
4642
  content,
4358
4643
  bytes: content.length,
4359
- sha256: sha256(content)
4644
+ sha256: sha2562(content)
4360
4645
  },
4361
4646
  ...referenceFiles
4362
4647
  ];
@@ -4384,7 +4669,7 @@ async function prepareSkillDocuments(catalog, requestedSkill, fetchMarkdown, fet
4384
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}`
4385
4670
  );
4386
4671
  }
4387
- const digest = sha256(content);
4672
+ const digest = sha2562(content);
4388
4673
  if (digest !== file.sha256) {
4389
4674
  throw invalid(`\u6280\u80FD ${skill.id}/${file.path} \u6458\u8981\u4E0E\u76EE\u5F55\u4E0D\u4E00\u81F4`);
4390
4675
  }
@@ -4406,10 +4691,10 @@ async function prepareSkillDocuments(catalog, requestedSkill, fetchMarkdown, fet
4406
4691
  );
4407
4692
  }
4408
4693
  async function syncWorkBuddyProject(input) {
4409
- const project = path2.resolve(input.project);
4410
- const metaDir = path2.join(project, ".hcm-delivery");
4411
- const skillsDir = path2.join(project, ".codebuddy", "skills");
4412
- const lockPath = path2.join(metaDir, "chiron.lock.json");
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");
4413
4698
  assertSafeSkillId(input.requestedSkill);
4414
4699
  validatePreparedDocuments(input.documents, input.requestedSkill);
4415
4700
  validatePreparedRuntime(input.runtime);
@@ -4429,27 +4714,27 @@ async function syncWorkBuddyProject(input) {
4429
4714
  const oldDigestByFile = lockDigests(oldLock);
4430
4715
  for (const file of oldOwned) validateOwnedFile(file);
4431
4716
  for (const file of desiredFiles) {
4432
- const absolute = path2.join(project, file);
4717
+ const absolute = path4.join(project, file);
4433
4718
  const current = await readOptionalBytes(absolute);
4434
4719
  if (current !== void 0 && !oldOwned.has(file)) {
4435
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}`);
4436
4721
  }
4437
4722
  }
4438
4723
  for (const file of oldOwned) {
4439
- const absolute = path2.join(project, file);
4724
+ const absolute = path4.join(project, file);
4440
4725
  const current = await readOptionalBytes(absolute);
4441
4726
  if (current === void 0) continue;
4442
4727
  const expected = oldDigestByFile.get(file);
4443
- if (!expected || sha256(current) !== expected.sha256 || !await fileModeMatches(absolute, expected.mode)) {
4728
+ if (!expected || sha2562(current) !== expected.sha256 || !await fileModeMatches(absolute, expected.mode)) {
4444
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}`);
4445
4730
  }
4446
4731
  }
4447
4732
  const newLock = {
4448
4733
  schemaVersion: 1,
4449
4734
  source: {
4450
- endpointOriginSha256: sha256(normalizeEndpoint(input.endpoint)),
4735
+ endpointOriginSha256: sha2562(normalizeEndpoint(input.endpoint)),
4451
4736
  catalogPath: "/skills.json",
4452
- catalogSha256: sha256(stableJson2(input.catalog))
4737
+ catalogSha256: sha2562(stableJson2(input.catalog))
4453
4738
  },
4454
4739
  selection: { requestedSkill: input.requestedSkill },
4455
4740
  resolvedSkills: input.documents.map(({ id, bytes, sha256: digest, files: skillFiles }) => ({
@@ -4481,16 +4766,16 @@ async function syncWorkBuddyProject(input) {
4481
4766
  }
4482
4767
  const obsolete = [...oldOwned].filter((file) => !desiredByFile.has(file));
4483
4768
  await fs5.mkdir(metaDir, { recursive: true });
4484
- const staging = await fs5.mkdtemp(path2.join(metaDir, ".staging-"));
4485
- const stagedFiles = path2.join(staging, "new");
4486
- const backups = path2.join(staging, "backup");
4487
- const stagedLock = path2.join(staging, "chiron.lock.json");
4488
- const journalPath = path2.join(staging, "journal.json");
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");
4489
4774
  let journalReady = false;
4490
4775
  try {
4491
4776
  for (const [file, preparedFile2] of desiredByFile) {
4492
- const staged = path2.join(stagedFiles, file);
4493
- await fs5.mkdir(path2.dirname(staged), { recursive: true });
4777
+ const staged = path4.join(stagedFiles, file);
4778
+ await fs5.mkdir(path4.dirname(staged), { recursive: true });
4494
4779
  await fs5.writeFile(
4495
4780
  staged,
4496
4781
  preparedFile2.content,
@@ -4501,16 +4786,16 @@ async function syncWorkBuddyProject(input) {
4501
4786
  `, "utf8");
4502
4787
  const affected = [.../* @__PURE__ */ new Set([...desiredFiles, ...obsolete])];
4503
4788
  for (const file of affected) {
4504
- const target = path2.join(project, file);
4789
+ const target = path4.join(project, file);
4505
4790
  if (!await exists(target)) continue;
4506
- const backup = path2.join(backups, file);
4507
- await fs5.mkdir(path2.dirname(backup), { recursive: true });
4791
+ const backup = path4.join(backups, file);
4792
+ await fs5.mkdir(path4.dirname(backup), { recursive: true });
4508
4793
  await fs5.copyFile(target, backup);
4509
4794
  }
4510
4795
  const oldLockExisted = await exists(lockPath);
4511
4796
  if (oldLockExisted) {
4512
- const backupLock = path2.join(backups, ".hcm-delivery", "chiron.lock.json");
4513
- await fs5.mkdir(path2.dirname(backupLock), { recursive: true });
4797
+ const backupLock = path4.join(backups, ".hcm-delivery", "chiron.lock.json");
4798
+ await fs5.mkdir(path4.dirname(backupLock), { recursive: true });
4514
4799
  await fs5.copyFile(lockPath, backupLock);
4515
4800
  }
4516
4801
  const journal = {
@@ -4523,12 +4808,12 @@ async function syncWorkBuddyProject(input) {
4523
4808
  `, "utf8");
4524
4809
  journalReady = true;
4525
4810
  for (const file of desiredFiles) {
4526
- const target = path2.join(project, file);
4527
- await fs5.mkdir(path2.dirname(target), { recursive: true });
4811
+ const target = path4.join(project, file);
4812
+ await fs5.mkdir(path4.dirname(target), { recursive: true });
4528
4813
  await fs5.rm(target, { force: true });
4529
- await fs5.rename(path2.join(stagedFiles, file), target);
4814
+ await fs5.rename(path4.join(stagedFiles, file), target);
4530
4815
  }
4531
- for (const file of obsolete) await fs5.unlink(path2.join(project, file)).catch(ignoreMissing);
4816
+ for (const file of obsolete) await fs5.unlink(path4.join(project, file)).catch(ignoreMissing);
4532
4817
  await fs5.rm(lockPath, { force: true });
4533
4818
  await fs5.rename(stagedLock, lockPath);
4534
4819
  await fs5.unlink(journalPath);
@@ -4559,32 +4844,32 @@ async function recoverInterruptedSyncs(project, metaDir, lockPath) {
4559
4844
  }
4560
4845
  for (const entry of entries) {
4561
4846
  if (!entry.isDirectory() || !entry.name.startsWith(".staging-")) continue;
4562
- const staging = path2.join(metaDir, entry.name);
4563
- if (await exists(path2.join(staging, "journal.json"))) {
4847
+ const staging = path4.join(metaDir, entry.name);
4848
+ if (await exists(path4.join(staging, "journal.json"))) {
4564
4849
  await recoverStaging(project, staging, lockPath);
4565
4850
  }
4566
4851
  await fs5.rm(staging, { recursive: true, force: true });
4567
4852
  }
4568
4853
  }
4569
4854
  async function recoverStaging(project, staging, lockPath) {
4570
- const journalPath = path2.join(staging, "journal.json");
4855
+ const journalPath = path4.join(staging, "journal.json");
4571
4856
  const journal = parseJournal(await fs5.readFile(journalPath, "utf8"), project);
4572
- const backups = path2.join(staging, "backup");
4857
+ const backups = path4.join(staging, "backup");
4573
4858
  for (const file of journal.affectedFiles) {
4574
- const target = path2.join(project, file);
4575
- const backup = path2.join(backups, file);
4859
+ const target = path4.join(project, file);
4860
+ const backup = path4.join(backups, file);
4576
4861
  if (await exists(backup)) {
4577
- await fs5.mkdir(path2.dirname(target), { recursive: true });
4862
+ await fs5.mkdir(path4.dirname(target), { recursive: true });
4578
4863
  await fs5.rm(target, { force: true });
4579
4864
  await fs5.rename(backup, target);
4580
4865
  } else {
4581
4866
  await fs5.rm(target, { force: true });
4582
4867
  }
4583
4868
  }
4584
- const backupLock = path2.join(backups, ".hcm-delivery", "chiron.lock.json");
4869
+ const backupLock = path4.join(backups, ".hcm-delivery", "chiron.lock.json");
4585
4870
  if (journal.oldLockExisted) {
4586
4871
  if (!await exists(backupLock)) throw invalid(`\u540C\u6B65\u6062\u590D\u7F3A\u5C11\u65E7\u9501\u5907\u4EFD\uFF1A${backupLock}`);
4587
- await fs5.mkdir(path2.dirname(lockPath), { recursive: true });
4872
+ await fs5.mkdir(path4.dirname(lockPath), { recursive: true });
4588
4873
  await fs5.rm(lockPath, { force: true });
4589
4874
  await fs5.rename(backupLock, lockPath);
4590
4875
  } else {
@@ -4596,8 +4881,8 @@ function parseJournal(content, project) {
4596
4881
  try {
4597
4882
  journal = JSON.parse(content);
4598
4883
  } catch (cause) {
4599
- throw new CliError14({
4600
- code: CliErrorCode13.CONFIG_PARSE_ERROR,
4884
+ throw new CliError16({
4885
+ code: CliErrorCode15.CONFIG_PARSE_ERROR,
4601
4886
  message: "Chiron \u540C\u6B65\u6062\u590D\u65E5\u5FD7\u635F\u574F",
4602
4887
  cause
4603
4888
  });
@@ -4620,7 +4905,7 @@ function validatePreparedDocuments(documents, requestedSkill) {
4620
4905
  assertSafeSkillFilePath(file.path);
4621
4906
  if (paths.has(file.path)) throw invalid(`\u6280\u80FD ${document.id} \u5305\u542B\u91CD\u590D\u6587\u4EF6: ${file.path}`);
4622
4907
  paths.add(file.path);
4623
- if (file.content.length !== file.bytes || sha256(file.content) !== file.sha256) {
4908
+ if (file.content.length !== file.bytes || sha2562(file.content) !== file.sha256) {
4624
4909
  throw invalid(`\u6280\u80FD ${document.id}/${file.path} \u7684\u5DF2\u51C6\u5907\u5185\u5BB9\u6458\u8981\u4E0D\u4E00\u81F4`);
4625
4910
  }
4626
4911
  }
@@ -4642,7 +4927,7 @@ function validatePreparedRuntime(runtime) {
4642
4927
  }
4643
4928
  capabilities.add(capability);
4644
4929
  }
4645
- if (!validDigest(runtime.capabilitiesSha256) || runtime.capabilitiesSha256 !== sha256(`${runtime.capabilities.join("\n")}
4930
+ if (!validDigest(runtime.capabilitiesSha256) || runtime.capabilitiesSha256 !== sha2562(`${runtime.capabilities.join("\n")}
4646
4931
  `)) {
4647
4932
  throw invalid("WorkBuddy CLI \u80FD\u529B\u6458\u8981\u4E0D\u4E00\u81F4");
4648
4933
  }
@@ -4667,7 +4952,7 @@ function validatePreparedRuntime(runtime) {
4667
4952
  }
4668
4953
  function validateRuntimeFile(file) {
4669
4954
  validateOwnedFile(file.path);
4670
- if (file.content.length !== file.bytes || sha256(file.content) !== file.sha256 || !Number.isInteger(file.mode) || file.mode < 0 || file.mode > 511) {
4955
+ if (file.content.length !== file.bytes || sha2562(file.content) !== file.sha256 || !Number.isInteger(file.mode) || file.mode < 0 || file.mode > 511) {
4671
4956
  throw invalid(`WorkBuddy \u8FD0\u884C\u5165\u53E3\u6458\u8981\u6216\u6743\u9650\u4E0D\u4E00\u81F4\uFF1A${file.path}`);
4672
4957
  }
4673
4958
  }
@@ -4712,15 +4997,15 @@ async function readLock(lockPath) {
4712
4997
  for (const file of lock.ownedFiles) validateOwnedFile(file);
4713
4998
  return lock;
4714
4999
  } catch (cause) {
4715
- throw new CliError14({
4716
- code: CliErrorCode13.CONFIG_PARSE_ERROR,
5000
+ throw new CliError16({
5001
+ code: CliErrorCode15.CONFIG_PARSE_ERROR,
4717
5002
  message: `Chiron \u9501\u6587\u4EF6\u635F\u574F\uFF0C\u62D2\u7EDD\u731C\u6D4B\u6587\u4EF6\u6240\u6709\u6743\uFF1A${lockPath}`,
4718
5003
  cause
4719
5004
  });
4720
5005
  }
4721
5006
  }
4722
5007
  function validateLockedRuntime(runtime) {
4723
- if (!Array.isArray(runtime.capabilities) || runtime.capabilities.length === 0 || !validDigest(runtime.capabilitiesSha256) || runtime.capabilitiesSha256 !== sha256(`${runtime.capabilities.join("\n")}
5008
+ if (!Array.isArray(runtime.capabilities) || runtime.capabilities.length === 0 || !validDigest(runtime.capabilitiesSha256) || runtime.capabilitiesSha256 !== sha2562(`${runtime.capabilities.join("\n")}
4724
5009
  `) || !runtime.launch || !validDigest(runtime.launch.executableSha256) || !Array.isArray(runtime.files) || runtime.files.length !== 2) {
4725
5010
  throw new Error("invalid runtime");
4726
5011
  }
@@ -4754,9 +5039,9 @@ function sameLockContent(left, right) {
4754
5039
  }
4755
5040
  async function desiredFilesMatch(project, desired) {
4756
5041
  for (const [file, preparedFile2] of desired) {
4757
- const absolute = path2.join(project, file);
5042
+ const absolute = path4.join(project, file);
4758
5043
  const current = await readOptionalBytes(absolute);
4759
- if (current === void 0 || sha256(current) !== preparedFile2.sha256 || !await fileModeMatches(absolute, preparedFile2.mode)) {
5044
+ if (current === void 0 || sha2562(current) !== preparedFile2.sha256 || !await fileModeMatches(absolute, preparedFile2.mode)) {
4760
5045
  return false;
4761
5046
  }
4762
5047
  }
@@ -4770,7 +5055,7 @@ function result(changed, input, project, skillsDir, lockPath, installed, removed
4770
5055
  project,
4771
5056
  skillsDir,
4772
5057
  lockPath,
4773
- runnerPath: path2.join(project, ".hcm-delivery", "bin", "hcm"),
5058
+ runnerPath: path4.join(project, ".hcm-delivery", "bin", "hcm"),
4774
5059
  capabilitiesSha256: input.runtime.capabilitiesSha256,
4775
5060
  installed,
4776
5061
  removed
@@ -4805,8 +5090,8 @@ function normalizeEndpoint(endpoint) {
4805
5090
  try {
4806
5091
  url = new URL(endpoint);
4807
5092
  } catch (cause) {
4808
- throw new CliError14({
4809
- code: CliErrorCode13.INVALID_ARGUMENT,
5093
+ throw new CliError16({
5094
+ code: CliErrorCode15.INVALID_ARGUMENT,
4810
5095
  message: `\u975E\u6CD5 endpoint\uFF1A${endpoint}`,
4811
5096
  cause
4812
5097
  });
@@ -4818,8 +5103,8 @@ function normalizeEndpoint(endpoint) {
4818
5103
  url.pathname = url.pathname.replace(/\/+$/, "");
4819
5104
  return url.toString().replace(/\/$/, "");
4820
5105
  }
4821
- function sha256(value) {
4822
- return createHash("sha256").update(value).digest("hex");
5106
+ function sha2562(value) {
5107
+ return createHash2("sha256").update(value).digest("hex");
4823
5108
  }
4824
5109
  function stableJson2(value) {
4825
5110
  if (Array.isArray(value)) return `[${value.map(stableJson2).join(",")}]`;
@@ -4882,16 +5167,16 @@ function ignoreMissing(cause) {
4882
5167
  if (cause.code !== "ENOENT") throw cause;
4883
5168
  }
4884
5169
  function invalid(message) {
4885
- return new CliError14({ code: CliErrorCode13.INVALID_ARGUMENT, message });
5170
+ return new CliError16({ code: CliErrorCode15.INVALID_ARGUMENT, message });
4886
5171
  }
4887
5172
 
4888
5173
  // src/commands/skills-runtime.ts
4889
5174
  import { execFile } from "child_process";
4890
- import { createHash as createHash2 } from "crypto";
5175
+ import { createHash as createHash3 } from "crypto";
4891
5176
  import { createReadStream, promises as fs6 } from "fs";
4892
- import path3 from "path";
5177
+ import path5 from "path";
4893
5178
  import { promisify } from "util";
4894
- import { CliError as CliError15, CliErrorCode as CliErrorCode14 } from "@hcmai/sdk";
5179
+ import { CliError as CliError17, CliErrorCode as CliErrorCode16 } from "@hcmai/sdk";
4895
5180
  var execFileAsync = promisify(execFile);
4896
5181
  var REQUIRED_CAPABILITIES = [
4897
5182
  "hcm.help.skills",
@@ -4928,7 +5213,7 @@ async function prepareWorkBuddyRuntime(input = {}) {
4928
5213
  }
4929
5214
  }
4930
5215
  const capabilities = [...REQUIRED_CAPABILITIES];
4931
- const capabilitiesSha256 = sha2562(`${capabilities.join("\n")}
5216
+ const capabilitiesSha256 = sha2563(`${capabilities.join("\n")}
4932
5217
  `);
4933
5218
  const executableSha256 = await sha256File(launch.executable);
4934
5219
  const launchRecord = launch.kind === "node-entry" ? {
@@ -4949,7 +5234,7 @@ async function prepareWorkBuddyRuntime(input = {}) {
4949
5234
  };
4950
5235
  }
4951
5236
  async function resolveLaunch(candidate, nodeExecutable) {
4952
- const requested = path3.resolve(candidate);
5237
+ const requested = path5.resolve(candidate);
4953
5238
  const resolvedCandidate = await realFile(requested, "\u5019\u9009 HCM CLI");
4954
5239
  const header = (await readPrefix(resolvedCandidate, 256)).toString("utf8");
4955
5240
  const nodeEntry = /^(?:#![^\r\n]*\bnode\b)|\.(?:c|m)?js$/i.test(
@@ -4958,7 +5243,7 @@ async function resolveLaunch(candidate, nodeExecutable) {
4958
5243
  if (nodeEntry) {
4959
5244
  return {
4960
5245
  kind: "node-entry",
4961
- executable: await realFile(path3.resolve(nodeExecutable), "Node \u53EF\u6267\u884C\u6587\u4EF6"),
5246
+ executable: await realFile(path5.resolve(nodeExecutable), "Node \u53EF\u6267\u884C\u6587\u4EF6"),
4962
5247
  entry: resolvedCandidate
4963
5248
  };
4964
5249
  }
@@ -4971,15 +5256,15 @@ async function realFile(file, label) {
4971
5256
  if (!stat.isFile()) throw new Error("not a regular file");
4972
5257
  return resolved;
4973
5258
  } catch (cause) {
4974
- throw new CliError15({
4975
- code: CliErrorCode14.INVALID_ARGUMENT,
5259
+ throw new CliError17({
5260
+ code: CliErrorCode16.INVALID_ARGUMENT,
4976
5261
  message: `${label}\u4E0D\u53EF\u7528\uFF1A${file}`,
4977
5262
  cause
4978
5263
  });
4979
5264
  }
4980
5265
  }
4981
5266
  async function comparablePath(file) {
4982
- const absolute = path3.resolve(file);
5267
+ const absolute = path5.resolve(file);
4983
5268
  return fs6.realpath(absolute).catch(() => absolute);
4984
5269
  }
4985
5270
  async function launchIdentity(launch) {
@@ -5025,8 +5310,8 @@ async function runProbe(launch, args, timeoutMs = 5e3) {
5025
5310
  return `${stdout}
5026
5311
  ${stderr}`;
5027
5312
  } catch (cause) {
5028
- throw new CliError15({
5029
- code: CliErrorCode14.INVALID_ARGUMENT,
5313
+ throw new CliError17({
5314
+ code: CliErrorCode16.INVALID_ARGUMENT,
5030
5315
  message: `\u5019\u9009 HCM CLI \u80FD\u529B\u63A2\u9488\u5931\u8D25\uFF1Ahcm ${args.join(" ")}`,
5031
5316
  cause
5032
5317
  });
@@ -5091,10 +5376,10 @@ function cmdQuote(value) {
5091
5376
  return `"${value.replace(/%/g, "%%")}"`;
5092
5377
  }
5093
5378
  function preparedFile(filePath, content, mode) {
5094
- return { path: filePath, content, bytes: content.length, sha256: sha2562(content), mode };
5379
+ return { path: filePath, content, bytes: content.length, sha256: sha2563(content), mode };
5095
5380
  }
5096
5381
  async function sha256File(file) {
5097
- const hash = createHash2("sha256");
5382
+ const hash = createHash3("sha256");
5098
5383
  await new Promise((resolve3, reject) => {
5099
5384
  const stream = createReadStream(file);
5100
5385
  stream.on("data", (chunk) => hash.update(chunk));
@@ -5103,17 +5388,29 @@ async function sha256File(file) {
5103
5388
  });
5104
5389
  return hash.digest("hex");
5105
5390
  }
5106
- function sha2562(value) {
5107
- return createHash2("sha256").update(value).digest("hex");
5391
+ function sha2563(value) {
5392
+ return createHash3("sha256").update(value).digest("hex");
5108
5393
  }
5109
5394
  function invalid2(message) {
5110
- return new CliError15({ code: CliErrorCode14.INVALID_ARGUMENT, message });
5395
+ return new CliError17({ code: CliErrorCode16.INVALID_ARGUMENT, message });
5111
5396
  }
5112
5397
 
5113
5398
  // src/commands/skills.ts
5114
5399
  var SKILLS_STATE_FILE = ".hcm-skills.json";
5115
- function sha2563(text) {
5116
- return createHash3("sha256").update(text, "utf8").digest("hex");
5400
+ function migrateSkillsState(state) {
5401
+ const skills2 = {};
5402
+ for (const [id, record] of Object.entries(state.skills ?? {})) {
5403
+ if (record.sourceKind) {
5404
+ skills2[id] = record;
5405
+ continue;
5406
+ }
5407
+ const kind = /^https?:\/\//i.test(record.source ?? "") ? "chiron" : "local";
5408
+ skills2[id] = { ...record, sourceKind: kind, sourceLocator: record.source };
5409
+ }
5410
+ return { ...state, skills: skills2 };
5411
+ }
5412
+ function sha2564(text) {
5413
+ return createHash4("sha256").update(text, "utf8").digest("hex");
5117
5414
  }
5118
5415
  async function resolveEndpoint(args) {
5119
5416
  if (args.endpoint) return args.endpoint.replace(/\/+$/, "");
@@ -5121,8 +5418,8 @@ async function resolveEndpoint(args) {
5121
5418
  const envName = resolveActiveEnv3({ envFlag: args.env }, process.env, g);
5122
5419
  const env2 = await loadEnv5(envName).catch(() => null);
5123
5420
  if (!env2?.endpoint) {
5124
- throw new CliError16({
5125
- code: CliErrorCode15.MISSING_FLAG,
5421
+ throw new CliError18({
5422
+ code: CliErrorCode17.MISSING_FLAG,
5126
5423
  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"
5127
5424
  });
5128
5425
  }
@@ -5141,8 +5438,8 @@ function decideTrackedEndpoint(options) {
5141
5438
  }
5142
5439
  if (!recorded) {
5143
5440
  if (!current) {
5144
- throw new CliError16({
5145
- code: CliErrorCode15.MISSING_FLAG,
5441
+ throw new CliError18({
5442
+ code: CliErrorCode17.MISSING_FLAG,
5146
5443
  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"
5147
5444
  });
5148
5445
  }
@@ -5159,32 +5456,32 @@ function decideTrackedEndpoint(options) {
5159
5456
  }
5160
5457
  async function exists2(target) {
5161
5458
  try {
5162
- await fsp.stat(target);
5459
+ await fsp2.stat(target);
5163
5460
  return true;
5164
5461
  } catch {
5165
5462
  return false;
5166
5463
  }
5167
5464
  }
5168
5465
  async function detectTarget(cwd) {
5169
- if (await exists2(path4.join(cwd, ".claude"))) return "claude";
5170
- if (await exists2(path4.join(cwd, "AGENTS.md"))) return "codex";
5171
- if (await exists2(path4.join(cwd, ".codex"))) return "codex";
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";
5172
5469
  return void 0;
5173
5470
  }
5174
5471
  async function resolveInstallLayout(args, cwd = process.cwd()) {
5175
5472
  const requested = args.target && args.target !== "auto" ? args.target : void 0;
5176
5473
  const target = requested ?? await detectTarget(cwd) ?? "claude";
5177
5474
  if (target === "codex") {
5178
- const root = args.global ? path4.join(os2.homedir(), ".codex") : cwd;
5475
+ const root = args.global ? path6.join(os2.homedir(), ".codex") : cwd;
5179
5476
  return {
5180
5477
  target,
5181
- baseDir: args.dir ? path4.resolve(args.dir) : path4.join(root, "hcm-skills"),
5182
- agentsFile: path4.join(root, "AGENTS.md")
5478
+ baseDir: args.dir ? path6.resolve(args.dir) : path6.join(root, "hcm-skills"),
5479
+ agentsFile: path6.join(root, "AGENTS.md")
5183
5480
  };
5184
5481
  }
5185
5482
  return {
5186
5483
  target,
5187
- baseDir: args.dir ? path4.resolve(args.dir) : args.global ? path4.join(os2.homedir(), ".claude", "skills") : path4.join(cwd, ".claude", "skills")
5484
+ baseDir: args.dir ? path6.resolve(args.dir) : args.global ? path6.join(os2.homedir(), ".claude", "skills") : path6.join(cwd, ".claude", "skills")
5188
5485
  };
5189
5486
  }
5190
5487
  async function chironClient(args) {
@@ -5209,10 +5506,41 @@ function fail3(e, args) {
5209
5506
  async function skillsListCommand(keyword, args) {
5210
5507
  try {
5211
5508
  if (args.installed) return await listInstalledSkills(keyword, args);
5212
- const { http, endpoint, base } = await chironClient(args);
5213
- const manifest2 = await fetchSkillCatalog(http, base);
5509
+ const source = parseSourceFilter(args.source);
5510
+ let manifest2;
5511
+ let endpoint;
5512
+ if (source !== "cli") {
5513
+ const client3 = await chironClient(args);
5514
+ endpoint = client3.endpoint;
5515
+ manifest2 = await fetchSkillCatalog(client3.http, client3.base);
5516
+ }
5517
+ const bundled = source === "chiron" ? void 0 : listBundledSkills();
5518
+ const catalog = buildUnifiedCatalog({ source, chironManifest: manifest2, bundled, cliVersion: CLI_VERSION });
5519
+ const conflicts = detectIdConflicts(catalog);
5520
+ if (conflicts.ids.length > 0) {
5521
+ throw new CliError18({
5522
+ code: CliErrorCode17.SKILL_ID_CONFLICT,
5523
+ message: conflictMessage(conflicts.ids, endpoint ?? "(\u672A\u77E5\u73AF\u5883)")
5524
+ });
5525
+ }
5214
5526
  const fmt = args.output ?? "table";
5215
- let cats = manifest2.categories ?? [];
5527
+ const cliCategory = catalog.cli.entries.size > 0 ? {
5528
+ key: CLI_CATEGORY_KEY,
5529
+ name: CLI_CATEGORY_NAME,
5530
+ description: "\u968F\u8FD9\u4EFD CLI \u53D1\u5E03\u7684\u6280\u80FD\uFF0C\u8BB2\u7684\u662F\u672C CLI \u7684\u547D\u4EE4\uFF1B\u5347\u7EA7 CLI \u5C31\u662F\u5347\u7EA7\u5B83\u4EEC",
5531
+ skills: [...catalog.cli.entries.values()].map((entry) => ({
5532
+ id: entry.meta.id,
5533
+ title: entry.meta.title,
5534
+ category: CLI_CATEGORY_KEY,
5535
+ actionSurface: "cli",
5536
+ description: entry.meta.description,
5537
+ stages: entry.meta.stages,
5538
+ requires: entry.meta.requires,
5539
+ bytes: entry.meta.bytes,
5540
+ markdownUrl: ""
5541
+ }))
5542
+ } : void 0;
5543
+ let cats = [...manifest2?.categories ?? [], ...cliCategory ? [cliCategory] : []];
5216
5544
  if (args.category) cats = cats.filter((c) => c.key === args.category);
5217
5545
  if (keyword) {
5218
5546
  cats = cats.map((c) => ({ ...c, skills: matchSkills(c.skills ?? [], keyword) })).filter((c) => c.skills.length > 0);
@@ -5221,21 +5549,41 @@ async function skillsListCommand(keyword, args) {
5221
5549
  cats = cats.map((c) => ({ ...c, skills: filterByStage(c.skills ?? [], args.stage) })).filter((c) => c.skills.length > 0);
5222
5550
  }
5223
5551
  if (fmt === "json" || fmt === "yaml") {
5224
- process.stdout.write(formatObject13({ ...manifest2, categories: cats }, { format: fmt }) + "\n");
5552
+ process.stdout.write(
5553
+ formatObject14(
5554
+ {
5555
+ ...manifest2 ?? {},
5556
+ categories: cats,
5557
+ sources: {
5558
+ cli: { status: catalog.cli.status, count: catalog.cli.entries.size },
5559
+ chiron: { status: catalog.chiron.status, count: catalog.chiron.entries.size }
5560
+ },
5561
+ conflictCheck: conflicts.checked ? { checked: true } : { checked: false, note: unconfirmedConflictNote(source) }
5562
+ },
5563
+ { format: fmt }
5564
+ ) + "\n"
5565
+ );
5225
5566
  process.exit(0);
5226
5567
  }
5227
5568
  const shown = cats.flatMap((c) => c.skills);
5569
+ const total = (manifest2?.skillCount ?? 0) + catalog.cli.entries.size;
5228
5570
  if (shown.length === 0) {
5229
- process.stdout.write(`\u6CA1\u6709\u5339\u914D\u7684\u6280\u80FD\uFF08${endpoint} \u5171 ${manifest2.skillCount} \u4E2A\uFF09
5571
+ process.stdout.write(`\u6CA1\u6709\u5339\u914D\u7684\u6280\u80FD\uFF08\u8FD9\u4E00\u8D9F\u770B\u7684\u6765\u6E90\u5171 ${total} \u4E2A\uFF09
5230
5572
  `);
5231
5573
  process.exit(0);
5232
5574
  }
5233
- process.stdout.write(`${manifest2.title ?? "Chiron"} \u2014 ${endpoint}
5575
+ process.stdout.write(`${manifest2?.title ?? "HCM \u6280\u80FD"} \u2014 ${endpoint ?? `@hcmai/cli@${CLI_VERSION}`}
5234
5576
 
5235
5577
  `);
5236
5578
  if (args.byStage) {
5237
5579
  const all = cats.flatMap((c) => c.skills);
5238
- for (const st of manifest2.stages ?? []) {
5580
+ const stageList = manifest2?.stages ?? [...new Set(all.flatMap((skill) => skill.stages ?? []))].sort().map((key) => ({
5581
+ key,
5582
+ name: key,
5583
+ description: "",
5584
+ skillCount: 0
5585
+ }));
5586
+ for (const st of stageList) {
5239
5587
  const inStage = filterByStage(all, st.key);
5240
5588
  if (inStage.length === 0 && !args.stage) {
5241
5589
  process.stdout.write(` ${st.name} (\u65E0\u6280\u80FD\u8986\u76D6)
@@ -5284,10 +5632,10 @@ async function listInstalledSkills(keyword, args) {
5284
5632
  const fmt = args.output ?? "table";
5285
5633
  if (!state || Object.keys(state.skills).length === 0) {
5286
5634
  if (fmt === "json" || fmt === "yaml") {
5287
- process.stdout.write(formatObject13({ baseDir: layout.baseDir, target: layout.target, all: false, skills: [] }, { format: fmt }) + "\n");
5635
+ process.stdout.write(formatObject14({ baseDir: layout.baseDir, target: layout.target, all: false, skills: [] }, { format: fmt }) + "\n");
5288
5636
  process.exit(0);
5289
5637
  }
5290
- 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
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
5291
5639
  `);
5292
5640
  process.stdout.write(" \u88C5\u5168\u90E8\uFF1Ahcm skills install --all\n");
5293
5641
  process.exit(0);
@@ -5297,31 +5645,43 @@ async function listInstalledSkills(keyword, args) {
5297
5645
  const markdown = await readInstalled(layout.baseDir, id);
5298
5646
  let title = id;
5299
5647
  if (markdown !== void 0) {
5300
- const raw = parseSkillFrontmatter(markdown, id).title;
5648
+ const raw = parseSkillFrontmatter2(markdown, id).title;
5301
5649
  if (typeof raw === "string" && raw.trim()) title = raw.trim();
5302
5650
  }
5303
5651
  rows.push({
5304
5652
  id,
5305
5653
  title,
5654
+ // 迁移保证它必然有值;`?? 'chiron'` 只是让类型闭合,不是业务缺省。
5655
+ sourceKind: record.sourceKind ?? "chiron",
5656
+ sourceLocator: record.sourceLocator ?? record.source,
5306
5657
  direct: record.direct,
5307
5658
  installedAt: record.installedAt,
5308
5659
  // 三种状态互斥:文件没了 / 本地改过 / 和装的时候一致
5309
- status: markdown === void 0 ? "missing" : sha2563(markdown) !== record.sha256 ? "locally-modified" : "installed"
5660
+ status: markdown === void 0 ? "missing" : sha2564(markdown) !== record.sha256 ? "locally-modified" : "installed"
5310
5661
  });
5311
5662
  }
5312
- const shown = keyword ? rows.filter((row) => row.id.includes(keyword) || row.title.includes(keyword)) : rows;
5663
+ const byKeyword = keyword ? rows.filter((row) => row.id.includes(keyword) || row.title.includes(keyword)) : rows;
5664
+ const sourceFilter = parseSourceFilter(args.source);
5665
+ const shown = sourceFilter === "all" ? byKeyword : byKeyword.filter((row) => row.sourceKind === sourceFilter);
5666
+ const groupOf = (kind) => kind === "cli" ? "CLI \u81EA\u5E26" : kind === "local" ? "\u672C\u5730\u76EE\u5F55\u88C5\u7684" : "\u777F\u620E\u6280\u80FD\u5E93";
5313
5667
  if (fmt === "json" || fmt === "yaml") {
5314
- process.stdout.write(formatObject13({
5668
+ process.stdout.write(formatObject14({
5315
5669
  baseDir: layout.baseDir,
5316
5670
  target: layout.target,
5317
5671
  endpoint: state.endpoint,
5318
5672
  all: Boolean(state.all),
5319
5673
  updatedAt: state.updatedAt,
5674
+ // 按来源分组的小计:顾问要能一眼看出「这份是跟着 CLI 走的还是跟着后端走的」
5675
+ bySource: {
5676
+ cli: shown.filter((r) => r.sourceKind === "cli").length,
5677
+ chiron: shown.filter((r) => r.sourceKind === "chiron").length,
5678
+ local: shown.filter((r) => r.sourceKind === "local").length
5679
+ },
5320
5680
  skills: shown
5321
5681
  }, { format: fmt }) + "\n");
5322
5682
  process.exit(0);
5323
5683
  }
5324
- process.stdout.write(`\u5DF2\u5B89\u88C5\u7684\u777F\u620E\u6280\u80FD \u2014 ${layout.baseDir}\uFF08${layout.target}\uFF09
5684
+ process.stdout.write(`\u5DF2\u5B89\u88C5\u7684\u6280\u80FD \u2014 ${layout.baseDir}\uFF08${layout.target}\uFF09
5325
5685
  `);
5326
5686
  process.stdout.write(`\u6765\u6E90 ${state.endpoint ?? "\uFF08\u672A\u8BB0\u5F55\uFF09"}` + (state.all ? " \u8DDF\u968F\u5168\u96C6\uFF1A\u662F\n\n" : "\n\n"));
5327
5687
  if (shown.length === 0) {
@@ -5329,11 +5689,18 @@ async function listInstalledSkills(keyword, args) {
5329
5689
  `);
5330
5690
  process.exit(0);
5331
5691
  }
5332
- for (const row of shown) {
5333
- const mark = row.status === "missing" ? "?" : row.status === "locally-modified" ? "!" : row.direct ? "\u25CF" : "\u25CB";
5334
- const note = row.status === "missing" ? "\u6587\u4EF6\u4E0D\u89C1\u4E86\uFF08update \u4F1A\u88C5\u56DE\uFF09" : row.status === "locally-modified" ? "\u672C\u5730\u6539\u8FC7" : row.direct ? "" : "\u4F9D\u8D56\u5E26\u5165";
5335
- process.stdout.write(` ${mark} ${row.id.padEnd(30)} ${row.title.padEnd(24)} ${note}
5692
+ for (const kind of ["chiron", "cli", "local"]) {
5693
+ const group = shown.filter((row) => row.sourceKind === kind);
5694
+ if (group.length === 0) continue;
5695
+ process.stdout.write(` ${groupOf(kind)}\uFF08${group.length}\uFF09
5336
5696
  `);
5697
+ for (const row of group) {
5698
+ const mark = row.status === "missing" ? "?" : row.status === "locally-modified" ? "!" : row.direct ? "\u25CF" : "\u25CB";
5699
+ const note = row.status === "missing" ? "\u6587\u4EF6\u4E0D\u89C1\u4E86\uFF08update \u4F1A\u88C5\u56DE\uFF09" : row.status === "locally-modified" ? "\u672C\u5730\u6539\u8FC7" : row.direct ? "" : "\u4F9D\u8D56\u5E26\u5165";
5700
+ process.stdout.write(` ${mark} ${row.id.padEnd(30)} ${row.title.padEnd(24)} ${note}
5701
+ `);
5702
+ }
5703
+ process.stdout.write("\n");
5337
5704
  }
5338
5705
  const modified = shown.filter((row) => row.status === "locally-modified").length;
5339
5706
  const missing = shown.filter((row) => row.status === "missing").length;
@@ -5352,6 +5719,16 @@ async function listInstalledSkills(keyword, args) {
5352
5719
  }
5353
5720
  async function skillsShowCommand(id, args) {
5354
5721
  try {
5722
+ assertSafeSkillId2(id);
5723
+ const source = parseSourceFilter(args.source);
5724
+ if (source !== "chiron" && listBundledSkills().some((s) => s.id === id)) {
5725
+ const document = await readBundledSkillDocument(id);
5726
+ process.stdout.write(document.markdown.endsWith("\n") ? document.markdown : document.markdown + "\n");
5727
+ process.exit(0);
5728
+ }
5729
+ 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`);
5731
+ }
5355
5732
  const { http, base } = await chironClient(args);
5356
5733
  const md = await fetchSkillMarkdown(http, id, base);
5357
5734
  process.stdout.write(md.endsWith("\n") ? md : md + "\n");
@@ -5367,13 +5744,19 @@ async function skillsSyncCommand(id, args) {
5367
5744
  throw invalid3(`sync --target \u5F53\u524D\u53EA\u652F\u6301 workbuddy\uFF0C\u6536\u5230 "${args.target ?? ""}"`);
5368
5745
  }
5369
5746
  if (!args.project?.trim()) throw invalid3("sync \u5FC5\u987B\u4F20 --project <path>");
5370
- const project = path4.resolve(args.project);
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);
5371
5754
  const runtime = await prepareWorkBuddyRuntime({
5372
5755
  candidate: args.cli,
5373
5756
  currentEntryHasRequiredCapabilities: !args.cli?.trim(),
5374
5757
  forbiddenCandidatePaths: [
5375
- path4.join(project, ".hcm-delivery", "bin", "hcm"),
5376
- path4.join(project, ".hcm-delivery", "bin", "hcm.cmd")
5758
+ path6.join(project, ".hcm-delivery", "bin", "hcm"),
5759
+ path6.join(project, ".hcm-delivery", "bin", "hcm.cmd")
5377
5760
  ]
5378
5761
  });
5379
5762
  const connectionArgs = { endpoint: args.endpoint, env: args.env };
@@ -5396,7 +5779,7 @@ async function skillsSyncCommand(id, args) {
5396
5779
  });
5397
5780
  const fmt = args.output ?? "table";
5398
5781
  if (fmt === "json" || fmt === "yaml") {
5399
- process.stdout.write(`${formatObject13(result2, { format: fmt })}
5782
+ process.stdout.write(`${formatObject14(result2, { format: fmt })}
5400
5783
  `);
5401
5784
  } else if (result2.changed) {
5402
5785
  process.stdout.write(`\u2705 ${id} \u2192 ${result2.skillsDir}
@@ -5434,8 +5817,9 @@ async function skillsInstallCommand(id, args) {
5434
5817
  let endpoint;
5435
5818
  let base;
5436
5819
  let manifest2;
5820
+ let conflictNote;
5437
5821
  if (args.from) {
5438
- const root = path4.resolve(args.from);
5822
+ const root = path6.resolve(args.from);
5439
5823
  requestedIds = all ? await listLocalSkillIds(root) : [id];
5440
5824
  const seen = /* @__PURE__ */ new Set();
5441
5825
  documents = [];
@@ -5447,23 +5831,97 @@ async function skillsInstallCommand(id, args) {
5447
5831
  }
5448
5832
  }
5449
5833
  } else {
5450
- const tracked = decideTrackedEndpoint({
5451
- explicit: Boolean(args.endpoint || args.env),
5452
- current: await resolveEndpoint(args).catch(() => void 0),
5453
- recorded: (await readSkillsState(layout.baseDir))?.endpoint
5454
- });
5455
- const client3 = await chironClient({ ...args, endpoint: tracked });
5456
- endpoint = client3.endpoint;
5457
- base = client3.base;
5458
- manifest2 = await fetchSkillCatalog(client3.http, base);
5459
- const order = all ? resolveAllSkillsInstallOrder(manifest2) : resolveSkillInstallOrder2(manifest2, id);
5460
- if (all && order.length === 0) throw invalid3(`${endpoint} \u7684\u6280\u80FD\u76EE\u5F55\u662F\u7A7A\u7684\uFF0C\u6CA1\u6709\u53EF\u88C5\u7684\u6280\u80FD`);
5461
- requestedIds = all ? order.map((skill) => skill.id) : [id];
5462
- documents = await mapWithConcurrency(
5463
- order,
5464
- FETCH_CONCURRENCY,
5465
- (skill) => fetchSkillDocument(client3.http, skill, endpoint, base)
5466
- );
5834
+ const source = parseSourceFilter(args.source);
5835
+ const bundled = source === "chiron" ? void 0 : listBundledSkills();
5836
+ let http;
5837
+ if (source !== "cli") {
5838
+ const tracked = decideTrackedEndpoint({
5839
+ explicit: Boolean(args.endpoint || args.env),
5840
+ current: await resolveEndpoint(args).catch(() => void 0),
5841
+ recorded: (await readSkillsState(layout.baseDir))?.endpoint
5842
+ });
5843
+ const client3 = await chironClient({ ...args, endpoint: tracked });
5844
+ endpoint = client3.endpoint;
5845
+ base = client3.base;
5846
+ http = client3.http;
5847
+ manifest2 = await fetchSkillCatalog(http, base);
5848
+ }
5849
+ const catalog = buildUnifiedCatalog({ source, chironManifest: manifest2, bundled, cliVersion: CLI_VERSION });
5850
+ const conflicts = detectIdConflicts(catalog);
5851
+ if (conflicts.ids.length > 0) {
5852
+ throw new CliError18({
5853
+ code: CliErrorCode17.SKILL_ID_CONFLICT,
5854
+ message: conflictMessage(conflicts.ids, endpoint ?? "(\u672A\u77E5\u73AF\u5883)")
5855
+ });
5856
+ }
5857
+ conflictNote = conflicts.checked ? void 0 : unconfirmedConflictNote(source);
5858
+ 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}`);
5860
+ }
5861
+ const wantBundled = (one) => catalog.cli.entries.has(one);
5862
+ const seen = /* @__PURE__ */ new Set();
5863
+ documents = [];
5864
+ const pushAll = (docs) => {
5865
+ for (const d of docs) {
5866
+ if (seen.has(d.id)) continue;
5867
+ seen.add(d.id);
5868
+ documents.push(d);
5869
+ }
5870
+ };
5871
+ const installBundled = async (one) => {
5872
+ const { documents: local, external } = await resolveBundledClosure(one);
5873
+ for (const need of external) {
5874
+ if (catalog.chiron.status !== "fetched") {
5875
+ throw invalid3(
5876
+ `\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
+ );
5878
+ }
5879
+ 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`);
5881
+ }
5882
+ pushAll(
5883
+ await mapWithConcurrency(
5884
+ resolveSkillInstallOrder2(manifest2, need),
5885
+ FETCH_CONCURRENCY,
5886
+ (skill) => fetchSkillDocument(http, skill, endpoint, base)
5887
+ )
5888
+ );
5889
+ }
5890
+ pushAll(local);
5891
+ };
5892
+ if (all) {
5893
+ const order = manifest2 ? resolveAllSkillsInstallOrder(manifest2) : [];
5894
+ const bundledIds = [...catalog.cli.entries.keys()].sort();
5895
+ 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`);
5897
+ }
5898
+ requestedIds = [...order.map((skill) => skill.id), ...bundledIds];
5899
+ if (order.length > 0) {
5900
+ pushAll(
5901
+ await mapWithConcurrency(
5902
+ order,
5903
+ FETCH_CONCURRENCY,
5904
+ (skill) => fetchSkillDocument(http, skill, endpoint, base)
5905
+ )
5906
+ );
5907
+ }
5908
+ for (const one of bundledIds) await installBundled(one);
5909
+ } else if (wantBundled(id)) {
5910
+ requestedIds = [id];
5911
+ await installBundled(id);
5912
+ } else {
5913
+ 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`);
5915
+ }
5916
+ requestedIds = [id];
5917
+ pushAll(
5918
+ await mapWithConcurrency(
5919
+ resolveSkillInstallOrder2(manifest2, id),
5920
+ FETCH_CONCURRENCY,
5921
+ (skill) => fetchSkillDocument(http, skill, endpoint, base)
5922
+ )
5923
+ );
5924
+ }
5467
5925
  }
5468
5926
  const result2 = await installSkillDocuments(documents, requestedIds, layout.baseDir, Boolean(args.force), {
5469
5927
  endpoint,
@@ -5474,9 +5932,9 @@ async function skillsInstallCommand(id, args) {
5474
5932
  const agents = layout.agentsFile ? await syncAgentsIndex(layout, manifest2) : void 0;
5475
5933
  const fmt = args.output ?? "table";
5476
5934
  if (fmt === "json" || fmt === "yaml") {
5477
- process.stdout.write(formatObject13({ ...result2, all, target_agent: layout.target, agentsFile: layout.agentsFile, agents }, { format: fmt }) + "\n");
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");
5478
5936
  } else {
5479
- const headline = all ? `\u2705 \u5168\u90E8 ${requestedIds.length} \u4E2A\u6280\u80FD \u2192 ${result2.baseDir}` : `\u2705 ${id} \u2192 ${path4.join(result2.baseDir, id, "SKILL.md")}`;
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")}`;
5480
5938
  process.stdout.write(`${headline}
5481
5939
  `);
5482
5940
  if (result2.installed.length > 0) {
@@ -5498,7 +5956,9 @@ async function skillsInstallCommand(id, args) {
5498
5956
  process.stdout.write(` \u5DF2${agents === "created" ? "\u521B\u5EFA" : "\u66F4\u65B0"} ${layout.agentsFile} \u91CC\u7684\u6280\u80FD\u7D22\u5F15\uFF08Codex \u8BFB\u8FD9\u91CC\uFF09
5499
5957
  `);
5500
5958
  }
5501
- process.stdout.write(` \u6765\u6E90 ${endpoint ?? path4.resolve(args.from)}
5959
+ process.stdout.write(` \u6765\u6E90 ${endpoint ?? (args.from ? path6.resolve(args.from) : `@hcmai/cli@${CLI_VERSION}`)}
5960
+ `);
5961
+ if (conflictNote) process.stdout.write(` \u26A0\uFE0F ${conflictNote}
5502
5962
  `);
5503
5963
  process.stdout.write(all ? " \u5DF2\u8BB0\u4E3A\u300C\u8DDF\u968F\u5168\u96C6\u300D\uFF1A\u4EE5\u540E\u8DD1 hcm skills update\uFF0C\u4EA7\u54C1\u65B0\u589E\u7684\u6280\u80FD\u4F1A\u81EA\u52A8\u8865\u4E0A\n" : " \u4EA7\u54C1\u66F4\u65B0\u540E\u8DD1 hcm skills update \u5347\u7EA7\n");
5504
5964
  }
@@ -5524,14 +5984,14 @@ async function mapWithConcurrency(items, limit, fn) {
5524
5984
  async function listLocalSkillIds(root) {
5525
5985
  let entries;
5526
5986
  try {
5527
- entries = await fsp.readdir(root, { withFileTypes: true });
5987
+ entries = await fsp2.readdir(root, { withFileTypes: true });
5528
5988
  } catch {
5529
5989
  throw invalid3(`\u8BFB\u4E0D\u5230\u672C\u5730\u6280\u80FD\u76EE\u5F55\uFF1A${root}`);
5530
5990
  }
5531
5991
  const ids = [];
5532
5992
  for (const entry of entries) {
5533
5993
  if (!entry.isDirectory()) continue;
5534
- if (await exists2(path4.join(root, entry.name, "SKILL.md"))) ids.push(entry.name);
5994
+ if (await exists2(path6.join(root, entry.name, "SKILL.md"))) ids.push(entry.name);
5535
5995
  }
5536
5996
  if (ids.length === 0) throw invalid3(`\u672C\u5730\u76EE\u5F55\u91CC\u6CA1\u6709\u4EFB\u4F55 <id>/SKILL.md\uFF1A${root}`);
5537
5997
  return ids.sort();
@@ -5546,6 +6006,7 @@ async function fetchSkillDocument(http, skill, endpoint, base) {
5546
6006
  id: skill.id,
5547
6007
  markdown: await fetchSkillMarkdown(http, skill.id, base),
5548
6008
  source: `${endpoint}${base}/skills/${skill.id}.md`,
6009
+ sourceKind: "chiron",
5549
6010
  references
5550
6011
  };
5551
6012
  }
@@ -5557,17 +6018,17 @@ async function syncAgentsIndex(layout, manifest2) {
5557
6018
  for (const category of manifest2?.categories ?? []) {
5558
6019
  for (const skill of category.skills ?? []) catalog.set(skill.id, skill);
5559
6020
  }
5560
- const agentsDir = path4.dirname(layout.agentsFile);
6021
+ const agentsDir = path6.dirname(layout.agentsFile);
5561
6022
  const entries = Object.keys(state.skills).sort().map((id) => {
5562
6023
  const known = catalog.get(id);
5563
- const absolute = path4.join(layout.baseDir, id, "SKILL.md");
5564
- let relative2 = path4.relative(agentsDir, absolute);
6024
+ const absolute = path6.join(layout.baseDir, id, "SKILL.md");
6025
+ let relative2 = path6.relative(agentsDir, absolute);
5565
6026
  if (!relative2.startsWith(".")) relative2 = `./${relative2}`;
5566
6027
  return {
5567
6028
  id,
5568
6029
  title: known?.title ?? id,
5569
6030
  description: known?.description ?? "",
5570
- relativePath: relative2.split(path4.sep).join("/")
6031
+ relativePath: relative2.split(path6.sep).join("/")
5571
6032
  };
5572
6033
  });
5573
6034
  return upsertAgentsBlock(layout.agentsFile, renderAgentsBlock(entries));
@@ -5585,13 +6046,13 @@ async function resolveLocalSkillDocuments(sourceRoot, targetId) {
5585
6046
  throw invalid3(`\u6280\u80FD\u4F9D\u8D56\u5B58\u5728\u73AF: ${[...pathStack.slice(Math.max(0, start)), id].join(" -> ")}`);
5586
6047
  }
5587
6048
  assertSafeSkillId2(id);
5588
- const local = path4.join(sourceRoot, id, "SKILL.md");
6049
+ const local = path6.join(sourceRoot, id, "SKILL.md");
5589
6050
  let markdown;
5590
6051
  try {
5591
- markdown = await fsp.readFile(local, "utf8");
6052
+ markdown = await fsp2.readFile(local, "utf8");
5592
6053
  } catch (cause) {
5593
6054
  if (cause?.code === "ENOENT") {
5594
- 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${path4.join(sourceRoot, id)}`);
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)}`);
5595
6056
  }
5596
6057
  throw cause;
5597
6058
  }
@@ -5602,9 +6063,10 @@ async function resolveLocalSkillDocuments(sourceRoot, targetId) {
5602
6063
  id,
5603
6064
  markdown,
5604
6065
  source: local,
5605
- references: await readLocalReferences(path4.join(sourceRoot, id))
6066
+ sourceKind: "local",
6067
+ references: await readLocalReferences(path6.join(sourceRoot, id))
5606
6068
  };
5607
- for (const required of parseSkillRequirements(markdown, id)) {
6069
+ for (const required of parseSkillRequirements2(markdown, id)) {
5608
6070
  await visit(required, id);
5609
6071
  }
5610
6072
  pathStack.pop();
@@ -5616,20 +6078,20 @@ async function resolveLocalSkillDocuments(sourceRoot, targetId) {
5616
6078
  }
5617
6079
  async function readSkillsState(baseDir) {
5618
6080
  try {
5619
- const raw = await fsp.readFile(path4.join(baseDir, SKILLS_STATE_FILE), "utf8");
6081
+ const raw = await fsp2.readFile(path6.join(baseDir, SKILLS_STATE_FILE), "utf8");
5620
6082
  const parsed = JSON.parse(raw);
5621
6083
  if (!parsed || typeof parsed !== "object" || !parsed.skills) return void 0;
5622
- return parsed;
6084
+ return migrateSkillsState(parsed);
5623
6085
  } catch {
5624
6086
  return void 0;
5625
6087
  }
5626
6088
  }
5627
6089
  async function writeSkillsState(baseDir, state) {
5628
- await fsp.mkdir(baseDir, { recursive: true });
5629
- const file = path4.join(baseDir, SKILLS_STATE_FILE);
6090
+ await fsp2.mkdir(baseDir, { recursive: true });
6091
+ const file = path6.join(baseDir, SKILLS_STATE_FILE);
5630
6092
  const temp = `${file}.${process.pid}.tmp`;
5631
- await fsp.writeFile(temp, JSON.stringify(state, null, 2) + "\n", "utf8");
5632
- await fsp.rename(temp, file);
6093
+ await fsp2.writeFile(temp, JSON.stringify(state, null, 2) + "\n", "utf8");
6094
+ await fsp2.rename(temp, file);
5633
6095
  }
5634
6096
  var AGENTS_BLOCK_BEGIN = "<!-- hcm-skills:begin -->";
5635
6097
  var AGENTS_BLOCK_END = "<!-- hcm-skills:end -->";
@@ -5652,22 +6114,22 @@ function renderAgentsBlock(entries) {
5652
6114
  async function upsertAgentsBlock(agentsFile, block) {
5653
6115
  let existing = "";
5654
6116
  try {
5655
- existing = await fsp.readFile(agentsFile, "utf8");
6117
+ existing = await fsp2.readFile(agentsFile, "utf8");
5656
6118
  } catch (cause) {
5657
6119
  if (cause?.code !== "ENOENT") throw cause;
5658
- await fsp.mkdir(path4.dirname(agentsFile), { recursive: true });
5659
- await fsp.writeFile(agentsFile, block + "\n", "utf8");
6120
+ await fsp2.mkdir(path6.dirname(agentsFile), { recursive: true });
6121
+ await fsp2.writeFile(agentsFile, block + "\n", "utf8");
5660
6122
  return "created";
5661
6123
  }
5662
6124
  const begin = existing.indexOf(AGENTS_BLOCK_BEGIN);
5663
6125
  const end = existing.indexOf(AGENTS_BLOCK_END);
5664
6126
  if (begin >= 0 && end > begin) {
5665
6127
  const next = existing.slice(0, begin) + block + existing.slice(end + AGENTS_BLOCK_END.length);
5666
- await fsp.writeFile(agentsFile, next, "utf8");
6128
+ await fsp2.writeFile(agentsFile, next, "utf8");
5667
6129
  return "replaced";
5668
6130
  }
5669
6131
  const separator = existing.endsWith("\n") ? "\n" : "\n\n";
5670
- await fsp.writeFile(agentsFile, existing + separator + block + "\n", "utf8");
6132
+ await fsp2.writeFile(agentsFile, existing + separator + block + "\n", "utf8");
5671
6133
  return "appended";
5672
6134
  }
5673
6135
  async function installSkillDocuments(documents, requestedIds, baseDir, force, meta2) {
@@ -5681,7 +6143,7 @@ async function installSkillDocuments(documents, requestedIds, baseDir, force, me
5681
6143
  if (!document.markdown.trim()) throw invalid3(`\u6280\u80FD ${document.id} \u5185\u5BB9\u4E3A\u7A7A`);
5682
6144
  return {
5683
6145
  ...document,
5684
- target: path4.join(baseDir, document.id, "SKILL.md"),
6146
+ target: path6.join(baseDir, document.id, "SKILL.md"),
5685
6147
  bytes: Buffer.byteLength(document.markdown)
5686
6148
  };
5687
6149
  });
@@ -5732,12 +6194,12 @@ async function sameOnDisk(baseDir, candidate) {
5732
6194
  return true;
5733
6195
  }
5734
6196
  async function readLocalReferences(skillDir) {
5735
- const root = path4.join(skillDir, "references");
6197
+ const root = path6.join(skillDir, "references");
5736
6198
  const out = [];
5737
6199
  const walk = async (dir, prefix) => {
5738
6200
  let items;
5739
6201
  try {
5740
- items = await fsp.readdir(dir, { withFileTypes: true });
6202
+ items = await fsp2.readdir(dir, { withFileTypes: true });
5741
6203
  } catch (cause) {
5742
6204
  if (cause?.code === "ENOENT") return;
5743
6205
  throw cause;
@@ -5745,49 +6207,79 @@ async function readLocalReferences(skillDir) {
5745
6207
  for (const item of items.sort((a, b) => a.name.localeCompare(b.name))) {
5746
6208
  const relative2 = prefix ? `${prefix}/${item.name}` : item.name;
5747
6209
  if (item.isDirectory()) {
5748
- await walk(path4.join(dir, item.name), relative2);
6210
+ await walk(path6.join(dir, item.name), relative2);
5749
6211
  continue;
5750
6212
  }
5751
6213
  if (!item.isFile()) continue;
5752
- assertSafeReferencePath(relative2);
5753
- out.push({ path: relative2, content: await fsp.readFile(path4.join(dir, item.name), "utf8") });
6214
+ assertSafeReferencePath2(relative2);
6215
+ out.push({ path: relative2, content: await fsp2.readFile(path6.join(dir, item.name), "utf8") });
5754
6216
  }
5755
6217
  };
5756
6218
  await walk(root, "");
5757
6219
  return out;
5758
6220
  }
5759
- async function writeSkillDocuments(documents, baseDir) {
6221
+ async function planStaleReferences(state, documents, baseDir) {
6222
+ const remove = [];
6223
+ const keptLocallyModified = [];
6224
+ for (const document of documents) {
6225
+ const recorded = state.skills[document.id]?.references ?? {};
6226
+ const fresh = new Set((document.references ?? []).map((r) => r.path));
6227
+ for (const [relative2, recordedSha] of Object.entries(recorded)) {
6228
+ if (fresh.has(relative2)) continue;
6229
+ const onDisk = await readInstalledReference(baseDir, document.id, relative2);
6230
+ if (onDisk === void 0) continue;
6231
+ if (sha2564(onDisk) !== recordedSha) {
6232
+ keptLocallyModified.push({ id: document.id, path: relative2 });
6233
+ continue;
6234
+ }
6235
+ remove.push({ id: document.id, path: relative2 });
6236
+ }
6237
+ }
6238
+ const byKey = (a, b) => `${a.id}/${a.path}`.localeCompare(`${b.id}/${b.path}`);
6239
+ return { remove: remove.sort(byKey), keptLocallyModified: keptLocallyModified.sort(byKey) };
6240
+ }
6241
+ async function writeSkillDocuments(documents, baseDir, removals = []) {
5760
6242
  const staged = [];
6243
+ const removed = [];
5761
6244
  try {
5762
6245
  for (const document of documents) {
5763
- const target = path4.join(baseDir, document.id, "SKILL.md");
5764
- await fsp.mkdir(path4.dirname(target), { recursive: true });
5765
- const temp = path4.join(path4.dirname(target), `.SKILL.md.${process.pid}.${Date.now()}.tmp`);
5766
- await fsp.writeFile(temp, document.markdown, "utf8");
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`);
6249
+ await fsp2.writeFile(temp, document.markdown, "utf8");
5767
6250
  staged.push({ temp, target });
5768
6251
  for (const reference of document.references ?? []) {
5769
- assertSafeReferencePath(reference.path);
5770
- const referenceTarget = path4.join(baseDir, document.id, "references", reference.path);
5771
- await fsp.mkdir(path4.dirname(referenceTarget), { recursive: true });
6252
+ assertSafeReferencePath2(reference.path);
6253
+ const referenceTarget = path6.join(baseDir, document.id, "references", reference.path);
6254
+ await fsp2.mkdir(path6.dirname(referenceTarget), { recursive: true });
5772
6255
  const referenceTemp = `${referenceTarget}.${process.pid}.${Date.now()}.tmp`;
5773
- await fsp.writeFile(referenceTemp, reference.content, "utf8");
6256
+ await fsp2.writeFile(referenceTemp, reference.content, "utf8");
5774
6257
  staged.push({ temp: referenceTemp, target: referenceTarget });
5775
6258
  }
5776
6259
  }
5777
- for (const file of staged) await fsp.rename(file.temp, file.target);
6260
+ for (const stale of removals) {
6261
+ assertSafeReferencePath2(stale.path);
6262
+ const original = path6.join(baseDir, stale.id, "references", stale.path);
6263
+ const parked = `${original}.${process.pid}.${Date.now()}.removed`;
6264
+ await fsp2.rename(original, parked);
6265
+ removed.push({ parked, original });
6266
+ }
6267
+ for (const file of staged) await fsp2.rename(file.temp, file.target);
6268
+ await Promise.all(removed.map((r) => fsp2.unlink(r.parked).catch(() => void 0)));
5778
6269
  } catch (cause) {
5779
- await Promise.all(staged.map((file) => fsp.unlink(file.temp).catch(() => void 0)));
6270
+ await Promise.all(staged.map((file) => fsp2.unlink(file.temp).catch(() => void 0)));
6271
+ await Promise.all(removed.map((r) => fsp2.rename(r.parked, r.original).catch(() => void 0)));
5780
6272
  throw cause;
5781
6273
  }
5782
6274
  }
5783
6275
  async function recordInstalled(baseDir, documents, meta2) {
5784
6276
  const state = await readSkillsState(baseDir) ?? {
5785
- version: 1,
6277
+ version: 2,
5786
6278
  target: meta2.target ?? "claude",
5787
6279
  updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
5788
6280
  skills: {}
5789
6281
  };
5790
- state.version = 1;
6282
+ state.version = 2;
5791
6283
  if (meta2.target) state.target = meta2.target;
5792
6284
  if (meta2.endpoint) state.endpoint = meta2.endpoint;
5793
6285
  if (meta2.base !== void 0) state.base = meta2.base;
@@ -5797,12 +6289,15 @@ async function recordInstalled(baseDir, documents, meta2) {
5797
6289
  const previous = state.skills[document.id];
5798
6290
  state.skills[document.id] = {
5799
6291
  source: document.source,
5800
- sha256: sha2563(document.markdown),
6292
+ // 🔴 两个键同值:`source` 留给旧 CLI 读(降级不炸),新代码只读 `sourceLocator`。
6293
+ sourceKind: document.sourceKind ?? previous?.sourceKind ?? "chiron",
6294
+ sourceLocator: document.source,
6295
+ sha256: sha2564(document.markdown),
5801
6296
  installedAt: meta2.keepInstalledAt?.has(document.id) && previous ? previous.installedAt : state.updatedAt,
5802
6297
  // 已经是直接安装的,不因为这次作为依赖被带进来就降级
5803
6298
  direct: meta2.directIds.has(document.id) || Boolean(previous?.direct),
5804
6299
  references: Object.fromEntries(
5805
- (document.references ?? []).map((reference) => [reference.path, sha2563(reference.content)])
6300
+ (document.references ?? []).map((reference) => [reference.path, sha2564(reference.content)])
5806
6301
  )
5807
6302
  };
5808
6303
  }
@@ -5810,11 +6305,11 @@ async function recordInstalled(baseDir, documents, meta2) {
5810
6305
  return state;
5811
6306
  }
5812
6307
  function invalid3(message) {
5813
- return new CliError16({ code: CliErrorCode15.INVALID_ARGUMENT, message });
6308
+ return new CliError18({ code: CliErrorCode17.INVALID_ARGUMENT, message });
5814
6309
  }
5815
6310
  async function readInstalled(baseDir, id) {
5816
6311
  try {
5817
- return await fsp.readFile(path4.join(baseDir, id, "SKILL.md"), "utf8");
6312
+ return await fsp2.readFile(path6.join(baseDir, id, "SKILL.md"), "utf8");
5818
6313
  } catch (cause) {
5819
6314
  if (cause?.code === "ENOENT") return void 0;
5820
6315
  throw cause;
@@ -5822,63 +6317,106 @@ async function readInstalled(baseDir, id) {
5822
6317
  }
5823
6318
  async function readInstalledReference(baseDir, id, relative2) {
5824
6319
  try {
5825
- return await fsp.readFile(path4.join(baseDir, id, "references", relative2), "utf8");
6320
+ return await fsp2.readFile(path6.join(baseDir, id, "references", relative2), "utf8");
5826
6321
  } catch (cause) {
5827
6322
  if (cause?.code === "ENOENT") return void 0;
5828
6323
  throw cause;
5829
6324
  }
5830
6325
  }
5831
6326
  async function planSkillUpdate(options) {
5832
- const { state, manifest: manifest2, baseDir, force, fetchDocument } = options;
6327
+ const { state, baseDir, force, fetchDocument } = options;
6328
+ const manifest2 = options.manifest;
6329
+ const catalog = options.catalog ?? buildUnifiedCatalog({ source: "chiron", chironManifest: manifest2, cliVersion: CLI_VERSION });
6330
+ const fetchBundled = options.fetchBundled ?? ((id) => readBundledSkillDocument(id));
5833
6331
  const all = options.all ?? Boolean(state.all);
5834
6332
  const recorded = Object.entries(state.skills);
5835
6333
  const directIds = recorded.some(([, r]) => r.direct) ? recorded.filter(([, r]) => r.direct).map(([id]) => id) : recorded.map(([id]) => id);
5836
- const wanted = all ? [.../* @__PURE__ */ new Set([...directIds, ...flattenSkills(manifest2).map((skill) => skill.id)])] : directIds;
5837
6334
  const entries = [];
6335
+ const live = [];
6336
+ for (const id of directIds.sort()) {
6337
+ const record = state.skills[id];
6338
+ const status = classifyInstalledSource(id, record, catalog);
6339
+ if (status === "present") {
6340
+ live.push({ id, kind: (record.sourceKind ?? "chiron") === "cli" ? "cli" : "chiron" });
6341
+ continue;
6342
+ }
6343
+ entries.push({ id, status, note: SOURCE_STATUS_NOTE[status] });
6344
+ }
6345
+ if (all) {
6346
+ const known = new Set(live.map((x) => x.id));
6347
+ for (const kind of ["chiron", "cli"]) {
6348
+ const half = kind === "chiron" ? catalog.chiron : catalog.cli;
6349
+ if (half.status !== "fetched") continue;
6350
+ for (const id of half.entries.keys()) {
6351
+ if (known.has(id)) continue;
6352
+ known.add(id);
6353
+ live.push({ id, kind });
6354
+ }
6355
+ }
6356
+ }
5838
6357
  const closure = /* @__PURE__ */ new Map();
5839
- for (const id of wanted.sort()) {
6358
+ const chironNeeded = /* @__PURE__ */ new Set();
6359
+ for (const item of live) {
6360
+ if (item.kind === "cli") {
6361
+ const queue = [item.id];
6362
+ while (queue.length > 0) {
6363
+ const id = queue.shift();
6364
+ if (closure.has(id)) continue;
6365
+ const entry = catalog.cli.entries.get(id);
6366
+ if (!entry) {
6367
+ chironNeeded.add(id);
6368
+ continue;
6369
+ }
6370
+ closure.set(id, { kind: "cli" });
6371
+ for (const need of entry.meta.requires ?? []) queue.push(need);
6372
+ }
6373
+ continue;
6374
+ }
6375
+ chironNeeded.add(item.id);
6376
+ }
6377
+ for (const id of chironNeeded) {
6378
+ if (!manifest2) continue;
5840
6379
  try {
5841
6380
  for (const skill of resolveSkillInstallOrder2(manifest2, id)) {
5842
- if (!closure.has(skill.id)) closure.set(skill.id, skill);
6381
+ if (!closure.has(skill.id)) closure.set(skill.id, { kind: "chiron", skill });
5843
6382
  }
5844
6383
  } catch {
5845
- entries.push({
5846
- id,
5847
- status: "removed-upstream",
5848
- note: "\u4EA7\u54C1\u8FD9\u4E00\u7248\u7684\u6280\u80FD\u76EE\u5F55\u91CC\u5DF2\u7ECF\u6CA1\u6709\u5B83\u4E86\uFF1B\u672C\u5730\u6587\u4EF6\u4FDD\u7559\u4E0D\u52A8"
5849
- });
6384
+ if (!entries.some((e) => e.id === id)) {
6385
+ entries.push({ id, status: "removed-upstream", note: SOURCE_STATUS_NOTE["removed-upstream"] });
6386
+ }
5850
6387
  }
5851
6388
  }
5852
6389
  const documents = [];
5853
- for (const skill of closure.values()) {
5854
- const record = state.skills[skill.id];
5855
- const onDisk = await readInstalled(baseDir, skill.id);
6390
+ for (const [id, item] of closure) {
6391
+ const record = state.skills[id];
6392
+ const onDisk = await readInstalled(baseDir, id);
6393
+ const fetch = async () => item.kind === "cli" ? await fetchBundled(id) : await fetchDocument(item.skill);
5856
6394
  if (onDisk === void 0) {
5857
- documents.push(await fetchDocument(skill));
6395
+ documents.push(await fetch());
5858
6396
  entries.push({
5859
- id: skill.id,
6397
+ id,
5860
6398
  status: "added",
5861
6399
  note: record ? "\u672C\u5730\u6587\u4EF6\u7F3A\u5931\uFF0C\u91CD\u65B0\u88C5\u56DE" : all ? "\u4EA7\u54C1\u8FD9\u4E00\u7248\u65B0\u589E\u7684\u6280\u80FD" : "\u4EA7\u54C1\u65B0\u589E\u7684\u524D\u7F6E\u6280\u80FD"
5862
6400
  });
5863
6401
  continue;
5864
6402
  }
5865
- const remote = await fetchDocument(skill);
6403
+ const remote = await fetch();
5866
6404
  const remoteReferences = remote.references ?? [];
5867
6405
  let differsFromRemote = remote.markdown !== onDisk;
5868
- let editedLocally = record !== void 0 && sha2563(onDisk) !== record.sha256;
6406
+ let editedLocally = record !== void 0 && sha2564(onDisk) !== record.sha256;
5869
6407
  for (const reference of remoteReferences) {
5870
- const installed = await readInstalledReference(baseDir, skill.id, reference.path);
6408
+ const installed = await readInstalledReference(baseDir, id, reference.path);
5871
6409
  if (installed !== reference.content) differsFromRemote = true;
5872
6410
  const recordedSha = record?.references?.[reference.path];
5873
- if (installed !== void 0 && recordedSha && sha2563(installed) !== recordedSha) editedLocally = true;
6411
+ if (installed !== void 0 && recordedSha && sha2564(installed) !== recordedSha) editedLocally = true;
5874
6412
  }
5875
6413
  if (!differsFromRemote) {
5876
- entries.push({ id: skill.id, status: "unchanged" });
6414
+ entries.push({ id, status: "unchanged" });
5877
6415
  continue;
5878
6416
  }
5879
6417
  if (editedLocally && !force) {
5880
6418
  entries.push({
5881
- id: skill.id,
6419
+ id,
5882
6420
  status: "locally-modified",
5883
6421
  note: "\u672C\u5730\u6539\u8FC7\uFF0C\u6CA1\u6709\u8986\u76D6\uFF1B\u786E\u5B9A\u8981\u7528\u4EA7\u54C1\u8FD9\u4E00\u7248\u5C31\u52A0 --force"
5884
6422
  });
@@ -5886,7 +6424,7 @@ async function planSkillUpdate(options) {
5886
6424
  }
5887
6425
  documents.push(remote);
5888
6426
  entries.push({
5889
- id: skill.id,
6427
+ id,
5890
6428
  status: "updated",
5891
6429
  note: editedLocally ? "\u672C\u5730\u6539\u8FC7\uFF0C--force \u5DF2\u8986\u76D6" : void 0
5892
6430
  });
@@ -5899,37 +6437,54 @@ var UPDATE_STATUS_LABEL = {
5899
6437
  added: "\u5DF2\u8865\u88C5",
5900
6438
  unchanged: "\u5DF2\u662F\u6700\u65B0",
5901
6439
  "locally-modified": "\u672C\u5730\u6539\u8FC7\xB7\u8DF3\u8FC7",
5902
- "removed-upstream": "\u4EA7\u54C1\u5DF2\u79FB\u9664"
6440
+ "removed-upstream": "\u4EA7\u54C1\u5DF2\u79FB\u9664",
6441
+ "removed-in-cli": "CLI \u4E0D\u518D\u81EA\u5E26",
6442
+ // 🔴 这一档不是结论,是「这一趟没核」。文案上必须看得出区别,
6443
+ // 否则顾问会把它读成「没问题」,而它可能正藏着一份真的被移除了的技能。
6444
+ "not-checked": "\u672C\u8F6E\u672A\u6838",
6445
+ local: "\u672C\u5730\u6765\u6E90\xB7\u4E0D\u7BA1"
5903
6446
  };
5904
6447
  async function skillsUpdateCommand(args) {
5905
6448
  try {
5906
6449
  const layout = await resolveInstallLayout(args);
5907
6450
  const state = await readSkillsState(layout.baseDir);
5908
6451
  if (!state || Object.keys(state.skills).length === 0) {
5909
- throw new CliError16({
5910
- code: CliErrorCode15.INVALID_ARGUMENT,
5911
- 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`
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`
5912
6455
  });
5913
6456
  }
6457
+ const source = parseSourceFilter(args.source);
5914
6458
  const endpoint = decideTrackedEndpoint({
5915
6459
  explicit: Boolean(args.endpoint || args.env),
5916
6460
  current: await resolveEndpoint(args).catch(() => void 0),
5917
6461
  recorded: state.endpoint
5918
6462
  });
5919
- const { http, base } = await chironClient({ ...args, endpoint });
5920
- const manifest2 = await fetchSkillCatalog(http, base);
6463
+ let manifest2;
6464
+ let base;
6465
+ let http;
6466
+ if (source !== "cli") {
6467
+ const client3 = await chironClient({ ...args, endpoint });
6468
+ http = client3.http;
6469
+ base = client3.base;
6470
+ manifest2 = await fetchSkillCatalog(http, base);
6471
+ }
6472
+ const bundled = source === "chiron" ? void 0 : listBundledSkills();
6473
+ const catalog = buildUnifiedCatalog({ source, chironManifest: manifest2, bundled, cliVersion: CLI_VERSION });
5921
6474
  const all = Boolean(args.all) || Boolean(state.all);
5922
6475
  const plan = await planSkillUpdate({
5923
6476
  state,
5924
6477
  manifest: manifest2,
6478
+ catalog,
5925
6479
  baseDir: layout.baseDir,
5926
6480
  force: Boolean(args.force),
5927
6481
  all,
5928
6482
  fetchDocument: (skill) => fetchSkillDocument(http, skill, endpoint, base)
5929
6483
  });
6484
+ const stale = await planStaleReferences(state, plan.documents, layout.baseDir);
5930
6485
  const subscriptionChanged = all && !state.all;
5931
6486
  if (!args.check && (plan.documents.length > 0 || subscriptionChanged)) {
5932
- await writeSkillDocuments(plan.documents, layout.baseDir);
6487
+ await writeSkillDocuments(plan.documents, layout.baseDir, stale.remove);
5933
6488
  await recordInstalled(layout.baseDir, plan.documents, {
5934
6489
  endpoint,
5935
6490
  base,
@@ -5942,18 +6497,24 @@ async function skillsUpdateCommand(args) {
5942
6497
  const changed = plan.entries.filter((e) => e.status === "updated" || e.status === "added");
5943
6498
  const fmt = args.output ?? "table";
5944
6499
  if (fmt === "json" || fmt === "yaml") {
5945
- process.stdout.write(formatObject13({
6500
+ process.stdout.write(formatObject14({
5946
6501
  endpoint,
5947
6502
  baseDir: layout.baseDir,
5948
6503
  target: layout.target,
5949
6504
  dryRun: Boolean(args.check),
5950
6505
  all,
5951
6506
  changed: changed.length,
6507
+ sources: {
6508
+ cli: { status: catalog.cli.status, count: catalog.cli.entries.size },
6509
+ chiron: { status: catalog.chiron.status, count: catalog.chiron.entries.size }
6510
+ },
6511
+ cliVersion: CLI_VERSION,
6512
+ staleReferences: stale,
5952
6513
  entries: plan.entries
5953
6514
  }, { format: fmt }) + "\n");
5954
6515
  process.exit(0);
5955
6516
  }
5956
- process.stdout.write(`\u777F\u620E\u6280\u80FD\u5347\u7EA7 \u2014 ${endpoint}
6517
+ process.stdout.write(`\u6280\u80FD\u5347\u7EA7 \u2014 ${source === "cli" ? `@hcmai/cli@${CLI_VERSION}\uFF08\u672A\u8FDE\u7F51\uFF09` : endpoint}
5957
6518
  `);
5958
6519
  process.stdout.write(`\u843D\u70B9 ${layout.baseDir}\uFF08${layout.target}\uFF09` + (all ? " \u8DDF\u968F\u5168\u96C6\uFF1A\u4EA7\u54C1\u65B0\u589E\u7684\u6280\u80FD\u4F1A\u81EA\u52A8\u8865\u4E0A\n\n" : "\n\n"));
5959
6520
  for (const entry of plan.entries) {
@@ -5966,10 +6527,38 @@ async function skillsUpdateCommand(args) {
5966
6527
  process.stdout.write("\n");
5967
6528
  const skipped = plan.entries.filter((e) => e.status === "locally-modified").length;
5968
6529
  const removed = plan.entries.filter((e) => e.status === "removed-upstream").length;
6530
+ const removedInCli = plan.entries.filter((e) => e.status === "removed-in-cli").length;
6531
+ const notChecked = plan.entries.filter((e) => e.status === "not-checked").length;
5969
6532
  const tail = [
5970
6533
  skipped > 0 ? `${skipped} \u4E2A\u672C\u5730\u6539\u8FC7\u88AB\u8DF3\u8FC7\uFF08--force \u8986\u76D6\uFF09` : "",
5971
- removed > 0 ? `${removed} \u4E2A\u4EA7\u54C1\u5DF2\u79FB\u9664\uFF08\u672C\u5730\u6587\u4EF6\u4FDD\u7559\uFF09` : ""
6534
+ removed > 0 ? `${removed} \u4E2A\u4EA7\u54C1\u5DF2\u79FB\u9664\uFF08\u672C\u5730\u6587\u4EF6\u4FDD\u7559\uFF09` : "",
6535
+ removedInCli > 0 ? `${removedInCli} \u4E2A\u8FD9\u4E00\u7248 CLI \u4E0D\u518D\u81EA\u5E26\uFF08\u672C\u5730\u6587\u4EF6\u4FDD\u7559\uFF09` : "",
6536
+ notChecked > 0 ? `${notChecked} \u4E2A\u672C\u8F6E\u672A\u6838\uFF08\u90A3\u4E00\u534A\u8FD9\u8D9F\u6CA1\u770B\uFF09` : ""
5972
6537
  ].filter(Boolean).join("\uFF0C");
6538
+ const cliCount = plan.entries.filter(
6539
+ (e) => (state.skills[e.id]?.sourceKind ?? "chiron") === "cli"
6540
+ ).length;
6541
+ if (cliCount > 0) {
6542
+ process.stdout.write(` \u81EA\u5E26\u6280\u80FD ${cliCount} \u4E2A\u5DF2\u8DDF\u968F\u5F53\u524D CLI ${CLI_VERSION}
6543
+ `);
6544
+ }
6545
+ if (source === "cli" && all) {
6546
+ process.stdout.write(
6547
+ " \u672C\u8D9F\u53EA\u770B\u4E86\u81EA\u5E26\u90A3\u4E00\u534A\uFF1B\u8FD9\u4E2A\u76EE\u5F55\u8BA2\u9605\u7684\u662F\u5168\u5E93\uFF0C\u8054\u7F51\u540E update \u4F1A\u8865\u9F50\u777F\u620E\u90A3\u4E00\u534A\n"
6548
+ );
6549
+ }
6550
+ if (stale.remove.length > 0) {
6551
+ process.stdout.write(
6552
+ ` ${args.check ? "\u4F1A\u5220\u6389" : "\u5DF2\u5220\u6389"} ${stale.remove.length} \u4E2A\u4EA7\u54C1\u8FD9\u4E00\u7248\u64A4\u6389\u7684\u53C2\u8003\u6587\u4EF6\uFF08${stale.remove.map((r) => `${r.id}/references/${r.path}`).join("\u3001")}\uFF09
6553
+ `
6554
+ );
6555
+ }
6556
+ if (stale.keptLocallyModified.length > 0) {
6557
+ process.stdout.write(
6558
+ ` ${stale.keptLocallyModified.length} \u4E2A\u4EA7\u54C1\u5DF2\u64A4\u6389\u4F46\u672C\u5730\u6539\u8FC7\u7684\u53C2\u8003\u6587\u4EF6\u4FDD\u7559\u4E86\uFF08${stale.keptLocallyModified.map((r) => `${r.id}/references/${r.path}`).join("\u3001")}\uFF09
6559
+ `
6560
+ );
6561
+ }
5973
6562
  if (changed.length === 0 && skipped === 0 && removed === 0) {
5974
6563
  process.stdout.write(args.check ? " \u5168\u90E8\u5DF2\u662F\u6700\u65B0\uFF08--check \u53EA\u770B\u4E0D\u52A8\uFF09\n" : " \u5168\u90E8\u5DF2\u662F\u6700\u65B0\uFF0C\u6CA1\u6709\u6539\u52A8\n");
5975
6564
  } else {
@@ -5987,13 +6576,13 @@ async function skillsUpdateCommand(args) {
5987
6576
  import {
5988
6577
  bootstrapTenant,
5989
6578
  createHttpClient as createHttpClient3,
5990
- formatObject as formatObject14,
6579
+ formatObject as formatObject15,
5991
6580
  fromAxiosError as fromAxiosError14,
5992
6581
  loadEnv as loadEnv6,
5993
6582
  loadGlobalConfig as loadGlobalConfig7,
5994
6583
  resolveActiveEnv as resolveActiveEnv4,
5995
- CliError as CliError17,
5996
- CliErrorCode as CliErrorCode16
6584
+ CliError as CliError19,
6585
+ CliErrorCode as CliErrorCode18
5997
6586
  } from "@hcmai/sdk";
5998
6587
  init_exit();
5999
6588
  async function resolveBootstrapKey(args, stdinTaken) {
@@ -6001,8 +6590,8 @@ async function resolveBootstrapKey(args, stdinTaken) {
6001
6590
  if (fromEnv) return fromEnv;
6002
6591
  if (args.bootstrapKeyStdin) {
6003
6592
  if (stdinTaken) {
6004
- throw new CliError17({
6005
- code: CliErrorCode16.INVALID_ARGUMENT,
6593
+ throw new CliError19({
6594
+ code: CliErrorCode18.INVALID_ARGUMENT,
6006
6595
  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"
6007
6596
  });
6008
6597
  }
@@ -6032,8 +6621,8 @@ async function resolveEndpoint2(args) {
6032
6621
  const envName = resolveActiveEnv4({ envFlag: args.env }, process.env, g);
6033
6622
  const env2 = await loadEnv6(envName).catch(() => null);
6034
6623
  if (!env2?.endpoint) {
6035
- throw new CliError17({
6036
- code: CliErrorCode16.MISSING_FLAG,
6624
+ throw new CliError19({
6625
+ code: CliErrorCode18.MISSING_FLAG,
6037
6626
  message: "\u672A\u89E3\u6790\u5230 endpoint \u2014\u2014 \u4F20 --endpoint <url>\uFF0C\u6216\u5148 `hcm env add <name> --endpoint <url>`"
6038
6627
  });
6039
6628
  }
@@ -6042,8 +6631,8 @@ async function resolveEndpoint2(args) {
6042
6631
  async function tenantBootstrapCommand(args) {
6043
6632
  try {
6044
6633
  if (!args.tenantId || !args.adminUsername) {
6045
- throw new CliError17({
6046
- code: CliErrorCode16.MISSING_FLAG,
6634
+ throw new CliError19({
6635
+ code: CliErrorCode18.MISSING_FLAG,
6047
6636
  message: "--tenant-id \u4E0E --admin-username \u5FC5\u586B"
6048
6637
  });
6049
6638
  }
@@ -6079,7 +6668,7 @@ async function tenantBootstrapCommand(args) {
6079
6668
  `
6080
6669
  );
6081
6670
  }
6082
- process.stdout.write(formatObject14(result2, { format: fmt }) + "\n");
6671
+ process.stdout.write(formatObject15(result2, { format: fmt }) + "\n");
6083
6672
  process.exit(0);
6084
6673
  } catch (e) {
6085
6674
  const err = e;
@@ -6094,17 +6683,17 @@ async function tenantBootstrapCommand(args) {
6094
6683
  }
6095
6684
 
6096
6685
  // src/commands/meta.ts
6097
- import { promises as fsp2 } from "fs";
6686
+ import { promises as fsp3 } from "fs";
6098
6687
  import {
6099
6688
  HcmClient as HcmClient15,
6100
- formatObject as formatObject15,
6689
+ formatObject as formatObject16,
6101
6690
  fromAxiosError as fromAxiosError15,
6102
6691
  listTenantMeta,
6103
6692
  getTenantMeta,
6104
6693
  saveTenantMeta,
6105
6694
  deleteTenantMeta,
6106
- CliError as CliError18,
6107
- CliErrorCode as CliErrorCode17
6695
+ CliError as CliError20,
6696
+ CliErrorCode as CliErrorCode19
6108
6697
  } from "@hcmai/sdk";
6109
6698
  init_exit();
6110
6699
  init_auth_guard();
@@ -6134,27 +6723,27 @@ async function metaListCommand(args) {
6134
6723
  const fmt = args.output ?? "json";
6135
6724
  if (fmt !== "json") process.stdout.write(`\u{1F4C4} ${items.length} \u4EFD${total ? ` / \u5171 ${total}` : ""}
6136
6725
  `);
6137
- process.stdout.write(formatObject15(items, { format: fmt }) + "\n");
6726
+ process.stdout.write(formatObject16(items, { format: fmt }) + "\n");
6138
6727
  process.exit(0);
6139
6728
  } catch (e) {
6140
6729
  fail4(e, args);
6141
6730
  }
6142
6731
  }
6143
- async function metaGetCommand(path7, args) {
6732
+ async function metaGetCommand(path9, args) {
6144
6733
  try {
6145
6734
  const c = await client2(args);
6146
- const content = await getTenantMeta(c.raw(), path7);
6735
+ const content = await getTenantMeta(c.raw(), path9);
6147
6736
  process.stdout.write(content.endsWith("\n") ? content : content + "\n");
6148
6737
  process.exit(0);
6149
6738
  } catch (e) {
6150
6739
  fail4(e, args);
6151
6740
  }
6152
6741
  }
6153
- async function metaSetCommand(path7, args) {
6742
+ async function metaSetCommand(path9, args) {
6154
6743
  try {
6155
6744
  if (!args.file) {
6156
- throw new CliError18({
6157
- code: CliErrorCode17.MISSING_FLAG,
6745
+ throw new CliError20({
6746
+ code: CliErrorCode19.MISSING_FLAG,
6158
6747
  message: "--file <path> \u5FC5\u586B\uFF08\u4ECE\u6587\u4EF6\u8BFB\u53D6 meta \u539F\u6587\uFF1B\u7528 - \u8868\u793A stdin\uFF09"
6159
6748
  });
6160
6749
  }
@@ -6164,10 +6753,10 @@ async function metaSetCommand(path7, args) {
6164
6753
  process.stdin.on("data", (d) => buf += d);
6165
6754
  process.stdin.on("end", () => resolve3(buf));
6166
6755
  process.stdin.on("error", reject);
6167
- }) : await fsp2.readFile(args.file, "utf8");
6756
+ }) : await fsp3.readFile(args.file, "utf8");
6168
6757
  if (args.dryRun) {
6169
6758
  process.stdout.write(
6170
- `[dry-run] \u5C06\u5199\u5165 ${path7}\uFF08${Buffer.byteLength(content)} B\uFF09\u2014\u2014\u672A\u5B9E\u9645\u5199\u5165
6759
+ `[dry-run] \u5C06\u5199\u5165 ${path9}\uFF08${Buffer.byteLength(content)} B\uFF09\u2014\u2014\u672A\u5B9E\u9645\u5199\u5165
6171
6760
  ---
6172
6761
  ${content}
6173
6762
  `
@@ -6175,35 +6764,35 @@ ${content}
6175
6764
  process.exit(0);
6176
6765
  }
6177
6766
  const c = await client2(args);
6178
- const result2 = await saveTenantMeta(c.raw(), path7, content);
6767
+ const result2 = await saveTenantMeta(c.raw(), path9, content);
6179
6768
  const fmt = args.output ?? "json";
6180
6769
  if (fmt !== "json") {
6181
- process.stdout.write(`\u2705 \u5DF2\u5199\u5165 ${path7}
6770
+ process.stdout.write(`\u2705 \u5DF2\u5199\u5165 ${path9}
6182
6771
  \u8BB0\u5F97\u6E05\u7F13\u5B58\uFF1Ahcm cache clear-meta <Model>
6183
6772
  `);
6184
6773
  }
6185
- process.stdout.write(formatObject15(result2, { format: fmt }) + "\n");
6774
+ process.stdout.write(formatObject16(result2, { format: fmt }) + "\n");
6186
6775
  process.exit(0);
6187
6776
  } catch (e) {
6188
6777
  if (e?.code === "ENOENT") exitWithError(new Error(`\u6587\u4EF6\u4E0D\u5B58\u5728\uFF1A${args.file}`));
6189
6778
  fail4(e, args);
6190
6779
  }
6191
6780
  }
6192
- async function metaDeleteCommand(path7, args) {
6781
+ async function metaDeleteCommand(path9, args) {
6193
6782
  try {
6194
6783
  if (!args.yes) {
6195
- const ok = await promptConfirm(`\u5C06\u5220\u9664\u5143\u6570\u636E ${path7}\uFF0C\u6B64\u64CD\u4F5C\u4E0D\u53EF\u9006\u3002\u7EE7\u7EED\uFF1F`);
6784
+ const ok = await promptConfirm(`\u5C06\u5220\u9664\u5143\u6570\u636E ${path9}\uFF0C\u6B64\u64CD\u4F5C\u4E0D\u53EF\u9006\u3002\u7EE7\u7EED\uFF1F`);
6196
6785
  if (!ok) {
6197
6786
  process.stderr.write("\u5DF2\u53D6\u6D88\n");
6198
6787
  process.exit(1);
6199
6788
  }
6200
6789
  }
6201
6790
  const c = await client2(args);
6202
- const result2 = await deleteTenantMeta(c.raw(), path7);
6791
+ const result2 = await deleteTenantMeta(c.raw(), path9);
6203
6792
  const fmt = args.output ?? "json";
6204
- if (fmt !== "json") process.stdout.write(`\u{1F5D1}\uFE0F \u5DF2\u5220\u9664 ${path7}
6793
+ if (fmt !== "json") process.stdout.write(`\u{1F5D1}\uFE0F \u5DF2\u5220\u9664 ${path9}
6205
6794
  `);
6206
- process.stdout.write(formatObject15(result2, { format: fmt }) + "\n");
6795
+ process.stdout.write(formatObject16(result2, { format: fmt }) + "\n");
6207
6796
  process.exit(0);
6208
6797
  } catch (e) {
6209
6798
  fail4(e, args);
@@ -6215,14 +6804,14 @@ init_exit();
6215
6804
  init_auth_guard();
6216
6805
  import * as crypto from "crypto";
6217
6806
  import * as fs7 from "fs/promises";
6218
- import * as path5 from "path";
6807
+ import * as path7 from "path";
6219
6808
  import {
6220
6809
  buildMiniPreviewTargets,
6221
6810
  buildMiniVerifyAgentReport,
6222
6811
  createWorkspaceFile,
6223
6812
  deleteWorkspaceFile,
6224
6813
  formatMiniVerifyReport,
6225
- formatObject as formatObject16,
6814
+ formatObject as formatObject17,
6226
6815
  formatRows as formatRows5,
6227
6816
  getMiniStatus,
6228
6817
  HcmClient as HcmClient16,
@@ -6432,7 +7021,7 @@ async function workspacePullCommand(args) {
6432
7021
  http: client3.raw(),
6433
7022
  appCode,
6434
7023
  workspaceKey,
6435
- targetDir: path5.join(rootDir, MINI_APPS_DIR, appCode),
7024
+ targetDir: path7.join(rootDir, MINI_APPS_DIR, appCode),
6436
7025
  tenantId: client3.tenantId,
6437
7026
  endpoint: client3.endpoint,
6438
7027
  profile: args.profile ?? client3.profile,
@@ -6447,7 +7036,7 @@ async function workspacePullCommand(args) {
6447
7036
  const rawRemoteByLocalPath = /* @__PURE__ */ new Map();
6448
7037
  for (const file of rawFiles) {
6449
7038
  const content = await loadWorkspaceFileContent(client3.raw(), file.id);
6450
- const target = path5.join(rootDir, content.relativePath);
7039
+ const target = path7.join(rootDir, content.relativePath);
6451
7040
  await writeTextFile(target, content.content, !!args.force);
6452
7041
  pulledRawFiles.push(content.relativePath);
6453
7042
  rawRemoteByLocalPath.set(content.relativePath, file);
@@ -6497,7 +7086,7 @@ async function workspaceAddMiniCommand(appCode, args) {
6497
7086
  const result2 = await initMiniAppProject({
6498
7087
  appCode,
6499
7088
  workspaceKey: context.workspaceKey,
6500
- targetDir: path5.join(rootDir, MINI_APPS_DIR, appCode),
7089
+ targetDir: path7.join(rootDir, MINI_APPS_DIR, appCode),
6501
7090
  name: args.name,
6502
7091
  defaultSurface: parseSurface(args.surface),
6503
7092
  templateKind,
@@ -6551,7 +7140,7 @@ async function workspaceStatusCommand(args) {
6551
7140
  }
6552
7141
  if (args.output === "json" || args.output === "yaml") {
6553
7142
  process.stdout.write(
6554
- formatObject16({ rootDir, miniApps: rows }, { format: args.output }) + "\n"
7143
+ formatObject17({ rootDir, miniApps: rows }, { format: args.output }) + "\n"
6555
7144
  );
6556
7145
  } else {
6557
7146
  process.stdout.write(formatRows5(rows, { format: "table" }) + "\n");
@@ -6627,7 +7216,7 @@ async function workspacePreviewCommand(args) {
6627
7216
  );
6628
7217
  }
6629
7218
  if (args.output === "json" || args.output === "yaml") {
6630
- process.stdout.write(formatObject16(rows, { format: args.output }) + "\n");
7219
+ process.stdout.write(formatObject17(rows, { format: args.output }) + "\n");
6631
7220
  } else {
6632
7221
  process.stdout.write(formatRows5(rows, { format: "table" }) + "\n");
6633
7222
  }
@@ -6738,7 +7327,7 @@ function removedMiniCommand() {
6738
7327
  );
6739
7328
  }
6740
7329
  function resolveRootDir(dir) {
6741
- return path5.resolve(dir ?? ".");
7330
+ return path7.resolve(dir ?? ".");
6742
7331
  }
6743
7332
  function buildWorkspaceContext(args) {
6744
7333
  return {
@@ -6754,7 +7343,7 @@ function buildWorkspaceContext(args) {
6754
7343
  async function readWorkspaceContext(rootDir) {
6755
7344
  try {
6756
7345
  const parsed = JSON.parse(
6757
- await fs7.readFile(path5.join(rootDir, WORKSPACE_CONTEXT_FILE), "utf-8")
7346
+ await fs7.readFile(path7.join(rootDir, WORKSPACE_CONTEXT_FILE), "utf-8")
6758
7347
  );
6759
7348
  if (parsed.kind !== WORKSPACE_CONTEXT_KIND || parsed.version !== WORKSPACE_CONTEXT_VERSION) {
6760
7349
  throw new Error(`${WORKSPACE_CONTEXT_FILE} is not an HCM workspace context`);
@@ -6784,7 +7373,7 @@ async function requireWorkspaceContext(rootDir) {
6784
7373
  }
6785
7374
  async function writeWorkspaceContext(rootDir, context) {
6786
7375
  await fs7.writeFile(
6787
- path5.join(rootDir, WORKSPACE_CONTEXT_FILE),
7376
+ path7.join(rootDir, WORKSPACE_CONTEXT_FILE),
6788
7377
  JSON.stringify(context, null, 2) + "\n"
6789
7378
  );
6790
7379
  }
@@ -6795,13 +7384,13 @@ async function writeTextFile(file, content, force) {
6795
7384
  } catch (e) {
6796
7385
  if (e.code !== "ENOENT") throw e;
6797
7386
  }
6798
- await fs7.mkdir(path5.dirname(file), { recursive: true });
7387
+ await fs7.mkdir(path7.dirname(file), { recursive: true });
6799
7388
  await fs7.writeFile(file, content);
6800
7389
  }
6801
7390
  async function readWorkspaceRawManifest(rootDir, context) {
6802
7391
  try {
6803
7392
  const parsed = JSON.parse(
6804
- await fs7.readFile(path5.join(rootDir, WORKSPACE_STATE_DIR, WORKSPACE_PULL_MANIFEST_FILE), "utf-8")
7393
+ await fs7.readFile(path7.join(rootDir, WORKSPACE_STATE_DIR, WORKSPACE_PULL_MANIFEST_FILE), "utf-8")
6805
7394
  );
6806
7395
  if (parsed.version !== WORKSPACE_CONTEXT_VERSION || parsed.workspaceKey !== context.workspaceKey) {
6807
7396
  throw new Error(`${WORKSPACE_PULL_MANIFEST_FILE} does not match workspace ${context.workspaceKey}`);
@@ -6819,7 +7408,7 @@ async function readWorkspaceRawManifest(rootDir, context) {
6819
7408
  }
6820
7409
  }
6821
7410
  async function writeWorkspaceRawState(rootDir, context, files, remoteByLocalPath) {
6822
- const stateDir = path5.join(rootDir, WORKSPACE_STATE_DIR);
7411
+ const stateDir = path7.join(rootDir, WORKSPACE_STATE_DIR);
6823
7412
  await fs7.mkdir(stateDir, { recursive: true });
6824
7413
  const snapshots = files.map((file) => ({
6825
7414
  localPath: file.localPath,
@@ -6830,7 +7419,7 @@ async function writeWorkspaceRawState(rootDir, context, files, remoteByLocalPath
6830
7419
  lastModified: remoteByLocalPath.get(file.localPath)?.lastModified
6831
7420
  }));
6832
7421
  await fs7.writeFile(
6833
- path5.join(stateDir, WORKSPACE_PULL_MANIFEST_FILE),
7422
+ path7.join(stateDir, WORKSPACE_PULL_MANIFEST_FILE),
6834
7423
  JSON.stringify(
6835
7424
  {
6836
7425
  version: WORKSPACE_CONTEXT_VERSION,
@@ -6852,7 +7441,7 @@ async function readWorkspaceRawLocalFiles(rootDir) {
6852
7441
  return files;
6853
7442
  }
6854
7443
  async function walkWorkspaceRawFiles(rootDir, relativeDir, files) {
6855
- const absoluteDir = path5.join(rootDir, relativeDir);
7444
+ const absoluteDir = path7.join(rootDir, relativeDir);
6856
7445
  let entries;
6857
7446
  try {
6858
7447
  entries = await fs7.readdir(absoluteDir, { withFileTypes: true });
@@ -6863,8 +7452,8 @@ async function walkWorkspaceRawFiles(rootDir, relativeDir, files) {
6863
7452
  for (const entry of entries) {
6864
7453
  if (entry.isDirectory() && RAW_WORKSPACE_EXCLUDED_DIRS.has(entry.name)) continue;
6865
7454
  if (entry.isFile() && RAW_WORKSPACE_EXCLUDED_FILES.has(entry.name)) continue;
6866
- const localPath = normalizeRelativePath(path5.posix.join(toPosix(relativeDir), entry.name));
6867
- const absolutePath = path5.join(rootDir, localPath);
7455
+ const localPath = normalizeRelativePath(path7.posix.join(toPosix(relativeDir), entry.name));
7456
+ const absolutePath = path7.join(rootDir, localPath);
6868
7457
  if (entry.isDirectory()) {
6869
7458
  await walkWorkspaceRawFiles(rootDir, localPath, files);
6870
7459
  continue;
@@ -6875,7 +7464,7 @@ async function walkWorkspaceRawFiles(rootDir, relativeDir, files) {
6875
7464
  localPath,
6876
7465
  absolutePath,
6877
7466
  content,
6878
- sha256: sha2564(content),
7467
+ sha256: sha2565(content),
6879
7468
  size: Buffer.byteLength(content, "utf-8")
6880
7469
  });
6881
7470
  }
@@ -6942,7 +7531,7 @@ function buildWorkspaceRawPushPlan(manifest2, localFiles, remoteFiles) {
6942
7531
  for (const entry of status) {
6943
7532
  const remote = remoteByLocal.get(entry.localPath);
6944
7533
  const base = baseByLocal.get(entry.localPath);
6945
- const remoteSha = remote ? sha2564(remote.content) : void 0;
7534
+ const remoteSha = remote ? sha2565(remote.content) : void 0;
6946
7535
  if (entry.status === "added") {
6947
7536
  if (remote) {
6948
7537
  conflicts.push(workspaceRawConflict(entry, "remote file already exists but was not in local snapshot"));
@@ -7044,7 +7633,7 @@ function workspaceRawConflict(entry, reason) {
7044
7633
  };
7045
7634
  }
7046
7635
  async function discoverMiniApps(rootDir) {
7047
- const appsRoot = path5.join(rootDir, MINI_APPS_DIR);
7636
+ const appsRoot = path7.join(rootDir, MINI_APPS_DIR);
7048
7637
  let entries;
7049
7638
  try {
7050
7639
  entries = await fs7.readdir(appsRoot, { withFileTypes: true });
@@ -7052,7 +7641,7 @@ async function discoverMiniApps(rootDir) {
7052
7641
  if (e.code === "ENOENT") return [];
7053
7642
  throw e;
7054
7643
  }
7055
- 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));
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));
7056
7645
  }
7057
7646
  function detectRemoteMiniApps(files) {
7058
7647
  const appCodes = /* @__PURE__ */ new Set();
@@ -7205,9 +7794,9 @@ function normalizeRelativePath(value) {
7205
7794
  return normalized;
7206
7795
  }
7207
7796
  function toPosix(value) {
7208
- return value.split(path5.sep).join("/");
7797
+ return value.split(path7.sep).join("/");
7209
7798
  }
7210
- function sha2564(content) {
7799
+ function sha2565(content) {
7211
7800
  return crypto.createHash("sha256").update(content, "utf-8").digest("hex");
7212
7801
  }
7213
7802
  function stringRequired(value, field) {
@@ -7233,7 +7822,7 @@ function optionalText(value) {
7233
7822
  }
7234
7823
  function writeWorkspaceListResult(rows, format, total) {
7235
7824
  if (format !== "table") {
7236
- process.stdout.write(formatObject16({ rows, total }, { format }) + "\n");
7825
+ process.stdout.write(formatObject17({ rows, total }, { format }) + "\n");
7237
7826
  return;
7238
7827
  }
7239
7828
  process.stdout.write(formatRows5(toWorkspaceListRows(rows), { format: "table" }) + "\n");
@@ -7244,7 +7833,7 @@ function writeWorkspaceListResult(rows, format, total) {
7244
7833
  }
7245
7834
  function writeWorkspaceActiveResult(view, format) {
7246
7835
  if (format !== "table") {
7247
- process.stdout.write(formatObject16(view, { format }) + "\n");
7836
+ process.stdout.write(formatObject17(view, { format }) + "\n");
7248
7837
  return;
7249
7838
  }
7250
7839
  const rows = [
@@ -7262,7 +7851,7 @@ function writeWorkspaceActiveResult(view, format) {
7262
7851
  }
7263
7852
  function writeWorkspaceBindResult(context, rootDir, format) {
7264
7853
  if (format !== "table") {
7265
- process.stdout.write(formatObject16({ ...context, rootDir }, { format }) + "\n");
7854
+ process.stdout.write(formatObject17({ ...context, rootDir }, { format }) + "\n");
7266
7855
  return;
7267
7856
  }
7268
7857
  process.stdout.write(
@@ -7276,7 +7865,7 @@ function writeWorkspaceBindResult(context, rootDir, format) {
7276
7865
  }
7277
7866
  function writeWorkspaceCreateResult(result2, format) {
7278
7867
  if (format !== "table") {
7279
- process.stdout.write(formatObject16(result2, { format }) + "\n");
7868
+ process.stdout.write(formatObject17(result2, { format }) + "\n");
7280
7869
  return;
7281
7870
  }
7282
7871
  process.stdout.write(
@@ -7292,7 +7881,7 @@ function writeWorkspaceCreateResult(result2, format) {
7292
7881
  }
7293
7882
  function writeWorkspacePullResult(result2, format) {
7294
7883
  if (format !== "table") {
7295
- process.stdout.write(formatObject16(result2, { format }) + "\n");
7884
+ process.stdout.write(formatObject17(result2, { format }) + "\n");
7296
7885
  return;
7297
7886
  }
7298
7887
  const lines = [
@@ -7310,7 +7899,7 @@ function writeWorkspacePullResult(result2, format) {
7310
7899
  }
7311
7900
  function writeWorkspaceAddMiniResult(result2, rootDir, format) {
7312
7901
  if (format !== "table") {
7313
- process.stdout.write(formatObject16({ ...result2, workspaceRoot: rootDir }, { format }) + "\n");
7902
+ process.stdout.write(formatObject17({ ...result2, workspaceRoot: rootDir }, { format }) + "\n");
7314
7903
  return;
7315
7904
  }
7316
7905
  process.stdout.write(
@@ -7326,7 +7915,7 @@ function writeWorkspaceAddMiniResult(result2, rootDir, format) {
7326
7915
  function writeWorkspaceValidateResult(results, format) {
7327
7916
  if (format !== "table") {
7328
7917
  process.stdout.write(
7329
- formatObject16(
7918
+ formatObject17(
7330
7919
  results.map((item) => ({ artifact: `mini:${item.app.appCode}`, ...item.result })),
7331
7920
  { format }
7332
7921
  ) + "\n"
@@ -7354,7 +7943,7 @@ mini:${item.app.appCode}
7354
7943
  function writeWorkspacePushResult(rawResult, results, format) {
7355
7944
  if (format !== "table") {
7356
7945
  process.stdout.write(
7357
- formatObject16(
7946
+ formatObject17(
7358
7947
  {
7359
7948
  workspaceFiles: { artifact: "workspace", ...rawResult },
7360
7949
  miniApps: results.map((item) => ({ artifact: `mini:${item.app.appCode}`, ...item.result }))
@@ -7410,7 +7999,7 @@ function writeWorkspaceVerifyResult(context, rootDir, raw, reports, format) {
7410
7999
  const ok = rawOk && reports.every((item) => item.report.ok);
7411
8000
  if (format === "json") {
7412
8001
  process.stdout.write(
7413
- formatObject16(
8002
+ formatObject17(
7414
8003
  {
7415
8004
  ok,
7416
8005
  workspaceKey: context.workspaceKey,
@@ -7437,7 +8026,7 @@ function writeWorkspaceVerifyResult(context, rootDir, raw, reports, format) {
7437
8026
  }
7438
8027
  if (format !== "table") {
7439
8028
  process.stdout.write(
7440
- formatObject16(
8029
+ formatObject17(
7441
8030
  {
7442
8031
  ok,
7443
8032
  workspaceKey: context.workspaceKey,
@@ -7504,8 +8093,8 @@ import {
7504
8093
  deleteIdentity as deleteIdentity2,
7505
8094
  loadGlobalConfig as loadGlobalConfig8,
7506
8095
  TokenStore as TokenStore3,
7507
- CliError as CliError19,
7508
- CliErrorCode as CliErrorCode18
8096
+ CliError as CliError21,
8097
+ CliErrorCode as CliErrorCode20
7509
8098
  } from "@hcmai/sdk";
7510
8099
  async function identityList(args) {
7511
8100
  try {
@@ -7533,8 +8122,8 @@ async function identityUse(name) {
7533
8122
  try {
7534
8123
  const meta2 = await loadIdentity4(name);
7535
8124
  const env2 = await loadEnv7(meta2.env).catch(() => {
7536
- throw new CliError19({
7537
- code: CliErrorCode18.IDENTITY_NOT_IN_ENV,
8125
+ throw new CliError21({
8126
+ code: CliErrorCode20.IDENTITY_NOT_IN_ENV,
7538
8127
  message: `identity '${name}' references env '${meta2.env}' which no longer exists. Re-create the env, or remove this orphan: hcm identity remove ${name}`
7539
8128
  });
7540
8129
  });
@@ -7572,11 +8161,11 @@ async function identityRemove(name) {
7572
8161
  init_auth_guard();
7573
8162
  import {
7574
8163
  HcmClient as HcmClient17,
7575
- formatObject as formatObject17
8164
+ formatObject as formatObject18
7576
8165
  } from "@hcmai/sdk";
7577
8166
 
7578
8167
  // src/commands/delivery.ts
7579
- import { createHash as createHash5 } from "crypto";
8168
+ import { createHash as createHash6 } from "crypto";
7580
8169
  var APPROVAL_BYPASS_FLAGS = /* @__PURE__ */ new Set(["-y", "--yes", "--force", "--auto-approve"]);
7581
8170
  var CREDENTIAL_FLAGS = /* @__PURE__ */ new Set([
7582
8171
  "--password",
@@ -7598,7 +8187,7 @@ var GUARDED_EXECUTOR_REASON_CODES = /* @__PURE__ */ new Set([
7598
8187
  ]);
7599
8188
  function assessDeliveryCommand(inputArgv, options = {}) {
7600
8189
  const argv = inputArgv[0] === "--" ? inputArgv.slice(1) : [...inputArgv];
7601
- const commandSha256 = sha2565(JSON.stringify(argv));
8190
+ const commandSha256 = sha2566(JSON.stringify(argv));
7602
8191
  const name = argv[0] ?? "";
7603
8192
  const subcommand = argv[1] && !argv[1].startsWith("-") ? argv[1] : void 0;
7604
8193
  const envAlias = flagValue(argv, "--env");
@@ -7629,7 +8218,7 @@ function assessDeliveryCommand(inputArgv, options = {}) {
7629
8218
  return {
7630
8219
  schemaVersion: 1,
7631
8220
  contractVersion: "2026-08-29",
7632
- assessmentId: sha2565(`2026-08-29
8221
+ assessmentId: sha2566(`2026-08-29
7633
8222
  ${commandSha256}`).slice(0, 24),
7634
8223
  commandSha256,
7635
8224
  command: { name: name || "(empty)", ...subcommand ? { subcommand } : {} },
@@ -7801,17 +8390,17 @@ function summarizeTarget(argv, actionResolution) {
7801
8390
  }
7802
8391
  const id = flagValue(argv, "--id");
7803
8392
  if (name === "user" && subcommand === "reset-password") {
7804
- if (id) target.userIdSha256 = sha2565(id);
8393
+ if (id) target.userIdSha256 = sha2566(id);
7805
8394
  const username = flagValue(argv, "--username");
7806
- if (username) target.usernameSha256 = sha2565(username);
8395
+ if (username) target.usernameSha256 = sha2566(username);
7807
8396
  target.forceChangeOnNextLogin = !hasFlag(argv, "--no-force-change");
7808
8397
  } else if (id) {
7809
- target.recordIdSha256 = sha2565(id);
8398
+ target.recordIdSha256 = sha2566(id);
7810
8399
  }
7811
8400
  for (const flag of PAYLOAD_FLAGS) {
7812
8401
  const raw = flagValue(argv, flag);
7813
8402
  if (!raw) continue;
7814
- target.payloadSha256 = sha2565(raw);
8403
+ target.payloadSha256 = sha2566(raw);
7815
8404
  try {
7816
8405
  const parsed = JSON.parse(raw);
7817
8406
  if (isPlainObject(parsed)) target.fieldNames = Object.keys(parsed).sort();
@@ -7908,8 +8497,8 @@ function valuesAfterFlag(argv, flag) {
7908
8497
  }
7909
8498
  return values;
7910
8499
  }
7911
- function sha2565(value) {
7912
- return createHash5("sha256").update(value).digest("hex");
8500
+ function sha2566(value) {
8501
+ return createHash6("sha256").update(value).digest("hex");
7913
8502
  }
7914
8503
  function isPlainObject(value) {
7915
8504
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -7928,7 +8517,7 @@ async function assessEffectiveDeliveryCommand(inputArgv, dependencies = {}) {
7928
8517
  }
7929
8518
  async function deliveryAssessCommand(argv, args) {
7930
8519
  const assessment = await assessEffectiveDeliveryCommand(argv);
7931
- process.stdout.write(formatObject17(assessment, { format: args.output ?? "json" }) + "\n");
8520
+ process.stdout.write(formatObject18(assessment, { format: args.output ?? "json" }) + "\n");
7932
8521
  }
7933
8522
  async function resolveCoreAction(request) {
7934
8523
  try {
@@ -8013,14 +8602,56 @@ function flagValue2(argv, flag) {
8013
8602
  return index >= 0 ? argv[index + 1] : void 0;
8014
8603
  }
8015
8604
 
8605
+ // src/commands/delivery-doctor.ts
8606
+ init_auth_guard();
8607
+ init_exit();
8608
+ import {
8609
+ HcmClient as HcmClient18,
8610
+ fetchReconIdentity,
8611
+ formatObject as formatObject19,
8612
+ fromAxiosError as fromAxiosError17,
8613
+ httpProbe,
8614
+ runDoctor
8615
+ } from "@hcmai/sdk";
8616
+ var DEFAULT_CAPABILITIES = "default";
8617
+ function render2(report) {
8618
+ const lines = [];
8619
+ for (const c of report.checks) {
8620
+ lines.push(`${c.ok ? "\u2705" : "\u274C"} ${c.anchor.padEnd(13)} ${c.detail}`);
8621
+ }
8622
+ lines.push("");
8623
+ lines.push(
8624
+ report.ok ? "\u56DB\u6761\u951A\u70B9\u5168\u7EFF\uFF1A\u53EF\u4EE5\u5F00\u59CB recon\u3002" : "\u6709\u951A\u70B9\u6CA1\u8FC7\u2014\u2014\u5148\u6309\u4E0A\u9762\u5404\u6761\u7684\u4E0B\u4E00\u6B65\u5904\u7406\uFF0C\u4E0D\u8981\u5728\u8FD9\u4E2A\u72B6\u6001\u4E0A\u722C\u57FA\u7EBF\u3002"
8625
+ );
8626
+ return lines.join("\n");
8627
+ }
8628
+ async function deliveryDoctorCommand(args) {
8629
+ try {
8630
+ const ctx = await getActiveAuthContextFromCli(args);
8631
+ const client3 = HcmClient18.fromAuthContext(ctx);
8632
+ const probe = httpProbe(client3.raw(), args.capabilities ?? DEFAULT_CAPABILITIES);
8633
+ const identity2 = await fetchReconIdentity(probe, ctx.tenantId);
8634
+ const report = await runDoctor(probe, identity2);
8635
+ const fmt = args.output ?? "json";
8636
+ if (fmt !== "json") process.stdout.write(render2(report) + "\n");
8637
+ process.stdout.write(formatObject19(report, { format: fmt }) + "\n");
8638
+ process.exit(report.ok ? 0 : 1);
8639
+ } catch (e) {
8640
+ const err = e;
8641
+ if (err?.isAxiosError) exitWithError(fromAxiosError17(err, args.env));
8642
+ exitWithError(e);
8643
+ process.exit(1);
8644
+ }
8645
+ }
8646
+
8016
8647
  // src/commands/delivery-execution.ts
8017
- import { createHash as createHash6, randomBytes as secureRandomBytes } from "crypto";
8648
+ import { createHash as createHash7, randomBytes as secureRandomBytes } from "crypto";
8018
8649
  import { spawn } from "child_process";
8019
8650
  import { createReadStream as createReadStream2, promises as fs8 } from "fs";
8020
- import path6 from "path";
8021
- import { CliError as CliError20, CliErrorCode as CliErrorCode19, formatObject as formatObject18 } from "@hcmai/sdk";
8651
+ import path8 from "path";
8652
+ import { CliError as CliError22, CliErrorCode as CliErrorCode21, formatObject as formatObject20 } from "@hcmai/sdk";
8022
8653
  init_exit();
8023
- var EXECUTION_CONTRACT_VERSION = "2026-08-28.controlled-v1";
8654
+ var EXECUTION_CONTRACT_VERSION = "2026-08-29.controlled-v2";
8024
8655
  var DEFAULT_TTL_SECONDS = 15 * 60;
8025
8656
  var MIN_TTL_SECONDS = 60;
8026
8657
  var MAX_TTL_SECONDS = 60 * 60;
@@ -8036,6 +8667,7 @@ async function prepareDeliveryExecution(input) {
8036
8667
  }
8037
8668
  const change = await bindDocument(project, input.changeRef, "\u53D8\u66F4\u8BF4\u660E");
8038
8669
  const rollback = await bindDocument(project, input.rollbackRef, "\u56DE\u6EDA\u8BF4\u660E");
8670
+ const payloads = await bindPayloadFiles(project, input.argv);
8039
8671
  const evidence = await bindEvidenceDirectory(project, input.evidenceDir);
8040
8672
  const { bytes: lockBytes, runtime: lockedRuntime } = await readChironLock(project);
8041
8673
  const runtime = await (input.runtimeIdentity ?? currentRuntimeIdentity)();
@@ -8045,20 +8677,21 @@ async function prepareDeliveryExecution(input) {
8045
8677
  const core = {
8046
8678
  schemaVersion: 1,
8047
8679
  contractVersion: EXECUTION_CONTRACT_VERSION,
8048
- nonceSha256: sha2566((input.randomBytes ?? secureRandomBytes)(12)),
8680
+ nonceSha256: sha2567((input.randomBytes ?? secureRandomBytes)(12)),
8049
8681
  createdAt: created.toISOString(),
8050
8682
  expiresAt: new Date(created.getTime() + ttlSeconds * 1e3).toISOString(),
8051
- chironLockSha256: sha2566(lockBytes),
8683
+ chironLockSha256: sha2567(lockBytes),
8052
8684
  runtime,
8053
8685
  assessment,
8054
8686
  documents: { change, rollback },
8687
+ payloads,
8055
8688
  evidenceDir: evidence.relative
8056
8689
  };
8057
- const planId = sha2566(canonicalJson(core)).slice(0, 24);
8690
+ const planId = sha2567(canonicalJson(core)).slice(0, 24);
8058
8691
  const plan = { ...core, planId };
8059
- const plansDir = path6.join(project, ".hcm-delivery", "execution-plans");
8692
+ const plansDir = path8.join(project, ".hcm-delivery", "execution-plans");
8060
8693
  await safeManagedDirectory(project, ".hcm-delivery/execution-plans", plansDir);
8061
- const planFile = path6.join(plansDir, `${planId}.json`);
8694
+ const planFile = path8.join(plansDir, `${planId}.json`);
8062
8695
  try {
8063
8696
  await fs8.writeFile(planFile, `${JSON.stringify(plan, null, 2)}
8064
8697
  `, {
@@ -8077,7 +8710,7 @@ async function executeDeliveryPlan(input) {
8077
8710
  if (await readProjectMode(project) !== "controlled") {
8078
8711
  throw invalid4("\u9879\u76EE\u4E0D\u662F controlled\uFF0C\u4E0D\u80FD\u6267\u884C R2 \u8BA1\u5212");
8079
8712
  }
8080
- const planFile = path6.join(project, ".hcm-delivery", "execution-plans", `${input.planId}.json`);
8713
+ const planFile = path8.join(project, ".hcm-delivery", "execution-plans", `${input.planId}.json`);
8081
8714
  const plan = await readPlan(project, planFile);
8082
8715
  if (plan.planId !== input.planId || computePlanId(plan) !== input.planId) {
8083
8716
  throw invalid4("\u6267\u884C\u8BA1\u5212\u5185\u5BB9\u4E0E planId \u6458\u8981\u4E0D\u4E00\u81F4");
@@ -8097,7 +8730,7 @@ async function executeDeliveryPlan(input) {
8097
8730
  throw invalid4("\u5B9E\u9645 argv \u4E0E\u6267\u884C\u8BA1\u5212\u7684\u547D\u4EE4\u6458\u8981\u6216\u98CE\u9669\u4E8B\u5B9E\u4E0D\u4E00\u81F4");
8098
8731
  }
8099
8732
  const { bytes: lockBytes, runtime: lockedRuntime } = await readChironLock(project);
8100
- if (sha2566(lockBytes) !== plan.chironLockSha256) {
8733
+ if (sha2567(lockBytes) !== plan.chironLockSha256) {
8101
8734
  throw invalid4("Chiron \u9501\u6458\u8981\u5DF2\u6F02\u79FB\uFF0C\u8BF7\u91CD\u65B0\u8BC4\u4F30\u5E76 prepare");
8102
8735
  }
8103
8736
  const runtime = await (input.runtimeIdentity ?? currentRuntimeIdentity)();
@@ -8107,12 +8740,13 @@ async function executeDeliveryPlan(input) {
8107
8740
  }
8108
8741
  await assertDocumentUnchanged(project, plan.documents.change, "\u53D8\u66F4\u8BF4\u660E");
8109
8742
  await assertDocumentUnchanged(project, plan.documents.rollback, "\u56DE\u6EDA\u8BF4\u660E");
8743
+ await assertPayloadsUnchanged(project, plan.payloads);
8110
8744
  const evidenceDir = await bindEvidenceDirectory(project, plan.evidenceDir);
8111
- const receiptFile = path6.join(evidenceDir.absolute, `${plan.planId}.receipt.json`);
8745
+ const receiptFile = path8.join(evidenceDir.absolute, `${plan.planId}.receipt.json`);
8112
8746
  if (await pathExists(receiptFile)) throw invalid4(`\u6267\u884C\u6536\u636E\u5DF2\u5B58\u5728\uFF0C\u62D2\u7EDD\u518D\u6B21\u6267\u884C\uFF1A${plan.planId}`);
8113
- const claimsDir = path6.join(project, ".hcm-delivery", "execution-claims");
8747
+ const claimsDir = path8.join(project, ".hcm-delivery", "execution-claims");
8114
8748
  await safeManagedDirectory(project, ".hcm-delivery/execution-claims", claimsDir);
8115
- const claimFile = path6.join(claimsDir, `${plan.planId}.json`);
8749
+ const claimFile = path8.join(claimsDir, `${plan.planId}.json`);
8116
8750
  try {
8117
8751
  await fs8.writeFile(
8118
8752
  claimFile,
@@ -8123,8 +8757,8 @@ async function executeDeliveryPlan(input) {
8123
8757
  } catch (cause) {
8124
8758
  throw invalid4(`\u6267\u884C\u8BA1\u5212\u5DF2\u6D88\u8D39\uFF0C\u62D2\u7EDD\u91CD\u590D\u6267\u884C\uFF1A${plan.planId}`, cause);
8125
8759
  }
8126
- const stdoutHash = createHash6("sha256");
8127
- const stderrHash = createHash6("sha256");
8760
+ const stdoutHash = createHash7("sha256");
8761
+ const stderrHash = createHash7("sha256");
8128
8762
  const run = input.runCommand ?? runCurrentCliCommand;
8129
8763
  let exitCode;
8130
8764
  try {
@@ -8171,7 +8805,7 @@ async function deliveryPrepareCommand(argv, args) {
8171
8805
  evidenceDir: args.evidenceDir,
8172
8806
  ...ttlSeconds === void 0 ? {} : { ttlSeconds }
8173
8807
  });
8174
- process.stdout.write(formatObject18(plan, { format: args.output ?? "json" }) + "\n");
8808
+ process.stdout.write(formatObject20(plan, { format: args.output ?? "json" }) + "\n");
8175
8809
  } catch (cause) {
8176
8810
  exitWithError(cause);
8177
8811
  }
@@ -8183,14 +8817,14 @@ async function deliveryExecuteCommand(planId, argv, args) {
8183
8817
  planId,
8184
8818
  argv
8185
8819
  });
8186
- process.stdout.write(formatObject18(receipt, { format: args.output ?? "json" }) + "\n");
8820
+ process.stdout.write(formatObject20(receipt, { format: args.output ?? "json" }) + "\n");
8187
8821
  process.exitCode = receipt.exitCode;
8188
8822
  } catch (cause) {
8189
8823
  exitWithError(cause);
8190
8824
  }
8191
8825
  }
8192
8826
  async function readProjectMode(project) {
8193
- const file = path6.join(project, ".hcm-delivery", "project.yml");
8827
+ const file = path8.join(project, ".hcm-delivery", "project.yml");
8194
8828
  const content = await readSafeFile(project, file, "\u9879\u76EE\u914D\u7F6E");
8195
8829
  const match = content.toString("utf8").match(
8196
8830
  /^deliveryMode:\s*(?:"(plan-only|controlled)"|'(plan-only|controlled)'|(plan-only|controlled))\s*$/m
@@ -8202,7 +8836,7 @@ async function readProjectMode(project) {
8202
8836
  return mode;
8203
8837
  }
8204
8838
  async function readChironLock(project) {
8205
- const file = path6.join(project, ".hcm-delivery", "chiron.lock.json");
8839
+ const file = path8.join(project, ".hcm-delivery", "chiron.lock.json");
8206
8840
  const bytes = await readSafeFile(project, file, "Chiron \u9501");
8207
8841
  let parsed;
8208
8842
  try {
@@ -8219,9 +8853,9 @@ async function bindDocument(project, reference, label) {
8219
8853
  if (!(relative2.startsWith("work/") || relative2.startsWith("decisions/"))) {
8220
8854
  throw invalid4(`${label}\u5FC5\u987B\u4F4D\u4E8E\u9879\u76EE work/ \u6216 decisions/ \u4E0B`);
8221
8855
  }
8222
- const file = path6.join(project, relative2);
8856
+ const file = path8.join(project, relative2);
8223
8857
  const bytes = await readSafeFile(project, file, label);
8224
- return { path: relative2, sha256: sha2566(bytes) };
8858
+ return { path: relative2, sha256: sha2567(bytes) };
8225
8859
  }
8226
8860
  async function assertDocumentUnchanged(project, document, label) {
8227
8861
  const current = await bindDocument(project, document.path, label);
@@ -8232,7 +8866,7 @@ async function bindEvidenceDirectory(project, reference) {
8232
8866
  if (!(relative2 === "evidence" || relative2.startsWith("evidence/"))) {
8233
8867
  throw invalid4("evidence \u76EE\u5F55\u5FC5\u987B\u4F4D\u4E8E\u9879\u76EE evidence/ \u4E0B");
8234
8868
  }
8235
- const absolute = path6.join(project, relative2);
8869
+ const absolute = path8.join(project, relative2);
8236
8870
  await assertNoSymlinkComponents(project, relative2);
8237
8871
  const stat = await fs8.stat(absolute).catch((cause) => {
8238
8872
  throw invalid4(`evidence \u76EE\u5F55\u4E0D\u53EF\u7528\uFF1A${relative2}`, cause);
@@ -8254,7 +8888,7 @@ async function readPlan(project, file) {
8254
8888
  function computePlanId(plan) {
8255
8889
  const core = { ...plan };
8256
8890
  delete core.planId;
8257
- return sha2566(canonicalJson(core)).slice(0, 24);
8891
+ return sha2567(canonicalJson(core)).slice(0, 24);
8258
8892
  }
8259
8893
  function assertGuardedAssessment(assessment, argv) {
8260
8894
  if (assessment.risk !== "R2") throw invalid4("\u53EA\u6709 R2 \u547D\u4EE4\u53EF\u4EE5\u8FDB\u5165\u53D7\u63A7\u6267\u884C\u8BA1\u5212");
@@ -8295,12 +8929,12 @@ function validateSupportedCommandShape(reasonCode, argv) {
8295
8929
  return;
8296
8930
  }
8297
8931
  if (reasonCode === "record-create") {
8298
- requireFlagValue(argv, "--data", "create \u5FC5\u987B\u5305\u542B --data <JSON>");
8932
+ requireExactlyOnePayload(argv, "create");
8299
8933
  return;
8300
8934
  }
8301
8935
  if (reasonCode === "record-update") {
8302
8936
  requireFlagValue(argv, "--id", "update \u5FC5\u987B\u5305\u542B --id <id>");
8303
- requireFlagValue(argv, "--data", "update \u5FC5\u987B\u5305\u542B --data <JSON>");
8937
+ requireExactlyOnePayload(argv, "update");
8304
8938
  return;
8305
8939
  }
8306
8940
  if (reasonCode === "cache-mutation") {
@@ -8331,6 +8965,40 @@ function optionalFlagValue(argv, flag) {
8331
8965
  }
8332
8966
  return void 0;
8333
8967
  }
8968
+ function requireExactlyOnePayload(argv, command) {
8969
+ const inline = optionalFlagValue(argv, "--data") !== void 0;
8970
+ const fromFile = optionalFlagValue(argv, "--data-file") !== void 0;
8971
+ if (inline && fromFile) {
8972
+ throw invalid4(`${command} \u7684 --data \u4E0E --data-file \u4E92\u65A5\uFF0C\u53EA\u80FD\u7ED9\u4E00\u4E2A`);
8973
+ }
8974
+ if (!inline && !fromFile) {
8975
+ throw invalid4(`${command} \u5FC5\u987B\u5305\u542B --data <JSON> \u6216 --data-file <\u6587\u4EF6>`);
8976
+ }
8977
+ }
8978
+ var PAYLOAD_FILE_FLAGS = ["--data-file", "--params-file"];
8979
+ async function bindPayloadFiles(project, argv) {
8980
+ const bound = [];
8981
+ for (const flag of PAYLOAD_FILE_FLAGS) {
8982
+ const reference = optionalFlagValue(argv, flag);
8983
+ if (reference === void 0) continue;
8984
+ bound.push(await bindPayloadFile(project, reference, `${flag} \u8F7D\u8377`));
8985
+ }
8986
+ return bound;
8987
+ }
8988
+ async function bindPayloadFile(project, reference, label) {
8989
+ const relative2 = safeRelative(reference, label);
8990
+ const file = path8.join(project, relative2);
8991
+ const bytes = await readSafeFile(project, file, label);
8992
+ return { path: relative2, sha256: sha2567(bytes) };
8993
+ }
8994
+ async function assertPayloadsUnchanged(project, payloads) {
8995
+ for (const payload of payloads) {
8996
+ const current = await bindPayloadFile(project, payload.path, `\u8F7D\u8377 ${payload.path}`);
8997
+ if (current.sha256 !== payload.sha256) {
8998
+ throw invalid4(`\u8F7D\u8377\u6587\u4EF6 ${payload.path} \u7684\u5185\u5BB9\u5DF2\u53D8\u66F4\uFF0C\u8BF7\u91CD\u65B0 prepare`);
8999
+ }
9000
+ }
9001
+ }
8334
9002
  function requireFlagValue(argv, flag, message) {
8335
9003
  for (let index = 0; index < argv.length; index += 1) {
8336
9004
  const value = argv[index];
@@ -8393,13 +9061,13 @@ async function writeReceiptExclusive(target, receipt) {
8393
9061
  });
8394
9062
  await fs8.link(temp, target);
8395
9063
  } catch (cause) {
8396
- throw invalid4(`\u6267\u884C\u6536\u636E\u5199\u5165\u5931\u8D25\u6216\u5DF2\u5B58\u5728\uFF1A${path6.basename(target)}`, cause);
9064
+ throw invalid4(`\u6267\u884C\u6536\u636E\u5199\u5165\u5931\u8D25\u6216\u5DF2\u5B58\u5728\uFF1A${path8.basename(target)}`, cause);
8397
9065
  } finally {
8398
9066
  await fs8.unlink(temp).catch(() => void 0);
8399
9067
  }
8400
9068
  }
8401
9069
  async function safeManagedDirectory(project, relative2, absolute) {
8402
- await assertNoSymlinkComponents(project, path6.dirname(relative2));
9070
+ await assertNoSymlinkComponents(project, path8.dirname(relative2));
8403
9071
  const existing = await fs8.lstat(absolute).catch(() => void 0);
8404
9072
  if (existing?.isSymbolicLink()) throw invalid4(`\u53D7\u7BA1\u76EE\u5F55\u4E0D\u80FD\u662F\u7B26\u53F7\u94FE\u63A5\uFF1A${relative2}`);
8405
9073
  if (existing && !existing.isDirectory()) throw invalid4(`\u53D7\u7BA1\u8DEF\u5F84\u4E0D\u662F\u76EE\u5F55\uFF1A${relative2}`);
@@ -8416,8 +9084,8 @@ async function pathExists(file) {
8416
9084
  );
8417
9085
  }
8418
9086
  async function readSafeFile(project, file, label) {
8419
- const relative2 = path6.relative(project, file).split(path6.sep).join("/");
8420
- if (relative2.startsWith("../") || path6.isAbsolute(relative2))
9087
+ const relative2 = path8.relative(project, file).split(path8.sep).join("/");
9088
+ if (relative2.startsWith("../") || path8.isAbsolute(relative2))
8421
9089
  throw invalid4(`${label}\u8DEF\u5F84\u9003\u9038\u9879\u76EE`);
8422
9090
  await assertNoSymlinkComponents(project, relative2);
8423
9091
  let stat;
@@ -8434,14 +9102,14 @@ async function assertNoSymlinkComponents(project, relative2) {
8434
9102
  const parts = relative2.split("/").filter(Boolean);
8435
9103
  let current = project;
8436
9104
  for (const part of parts) {
8437
- current = path6.join(current, part);
9105
+ current = path8.join(current, part);
8438
9106
  const stat = await fs8.lstat(current).catch(() => void 0);
8439
9107
  if (stat?.isSymbolicLink()) throw invalid4(`\u8DEF\u5F84\u5305\u542B\u7B26\u53F7\u94FE\u63A5\uFF1A${relative2}`);
8440
9108
  if (!stat) break;
8441
9109
  }
8442
9110
  }
8443
9111
  async function realProject(requested) {
8444
- const absolute = path6.resolve(requested);
9112
+ const absolute = path8.resolve(requested);
8445
9113
  let project;
8446
9114
  try {
8447
9115
  project = await fs8.realpath(absolute);
@@ -8453,10 +9121,10 @@ async function realProject(requested) {
8453
9121
  return project;
8454
9122
  }
8455
9123
  function safeRelative(reference, label) {
8456
- if (!reference || path6.isAbsolute(reference) || /[\r\n\0]/.test(reference)) {
9124
+ if (!reference || path8.isAbsolute(reference) || /[\r\n\0]/.test(reference)) {
8457
9125
  throw invalid4(`${label}\u5FC5\u987B\u662F\u9879\u76EE\u5185\u76F8\u5BF9\u8DEF\u5F84`);
8458
9126
  }
8459
- const normalized = path6.normalize(reference).split(path6.sep).join("/");
9127
+ const normalized = path8.normalize(reference).split(path8.sep).join("/");
8460
9128
  if (normalized === ".." || normalized.startsWith("../") || normalized === ".") {
8461
9129
  throw invalid4(`${label}\u8DEF\u5F84\u9003\u9038\u9879\u76EE`);
8462
9130
  }
@@ -8469,7 +9137,7 @@ function isRuntimeIdentity(value) {
8469
9137
  }
8470
9138
  function isExecutionPlan(value) {
8471
9139
  if (!isRecord(value)) return false;
8472
- 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) && typeof value.evidenceDir === "string";
9140
+ 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";
8473
9141
  }
8474
9142
  function isBoundDocument(value) {
8475
9143
  return isRecord(value) && typeof value.path === "string" && isSha(value.sha256);
@@ -8492,11 +9160,11 @@ function canonicalJson(value) {
8492
9160
  }
8493
9161
  return JSON.stringify(value) ?? "null";
8494
9162
  }
8495
- function sha2566(value) {
8496
- return createHash6("sha256").update(value).digest("hex");
9163
+ function sha2567(value) {
9164
+ return createHash7("sha256").update(value).digest("hex");
8497
9165
  }
8498
9166
  async function sha256File2(file) {
8499
- const hash = createHash6("sha256");
9167
+ const hash = createHash7("sha256");
8500
9168
  await new Promise((resolve3, reject) => {
8501
9169
  const stream = createReadStream2(file);
8502
9170
  stream.on("data", (chunk) => hash.update(chunk));
@@ -8506,32 +9174,32 @@ async function sha256File2(file) {
8506
9174
  return hash.digest("hex");
8507
9175
  }
8508
9176
  function invalid4(message, cause) {
8509
- return new CliError20({ code: CliErrorCode19.INVALID_ARGUMENT, message, cause });
9177
+ return new CliError22({ code: CliErrorCode21.INVALID_ARGUMENT, message, cause });
8510
9178
  }
8511
9179
 
8512
9180
  // src/commands/user.ts
8513
9181
  init_auth_guard();
8514
9182
  init_exit();
8515
9183
  import {
8516
- HcmClient as HcmClient18,
9184
+ HcmClient as HcmClient19,
8517
9185
  adminResetPassword,
8518
- formatObject as formatObject19,
8519
- fromAxiosError as fromAxiosError17,
8520
- CliError as CliError21,
8521
- CliErrorCode as CliErrorCode20
9186
+ formatObject as formatObject21,
9187
+ fromAxiosError as fromAxiosError18,
9188
+ CliError as CliError23,
9189
+ CliErrorCode as CliErrorCode22
8522
9190
  } from "@hcmai/sdk";
8523
9191
  function buildAdminResetPasswordRequest(args, password) {
8524
9192
  const hasId = Boolean(args.id);
8525
9193
  const hasUsername = Boolean(args.username);
8526
9194
  if (hasId === hasUsername) {
8527
- throw new CliError21({
8528
- code: CliErrorCode20.INVALID_ARGUMENT,
9195
+ throw new CliError23({
9196
+ code: CliErrorCode22.INVALID_ARGUMENT,
8529
9197
  message: "--id <uuid> \u4E0E --username <user> \u5FC5\u987B\u4E14\u53EA\u80FD\u63D0\u4F9B\u4E00\u4E2A"
8530
9198
  });
8531
9199
  }
8532
9200
  if (!password) {
8533
- throw new CliError21({
8534
- code: CliErrorCode20.INVALID_ARGUMENT,
9201
+ throw new CliError23({
9202
+ code: CliErrorCode22.INVALID_ARGUMENT,
8535
9203
  message: "\u65B0\u5BC6\u7801\u4E0D\u80FD\u4E3A\u7A7A"
8536
9204
  });
8537
9205
  }
@@ -8547,12 +9215,12 @@ async function userResetPasswordCommand(args) {
8547
9215
  try {
8548
9216
  const password = args.passwordStdin ? await readSecretFromStdin() : await promptPasswordTwice();
8549
9217
  const request = buildAdminResetPasswordRequest(args, password);
8550
- const client3 = HcmClient18.fromAuthContext(await getActiveAuthContextFromCli(args));
9218
+ const client3 = HcmClient19.fromAuthContext(await getActiveAuthContextFromCli(args));
8551
9219
  const result2 = await adminResetPassword(client3.raw(), request);
8552
- process.stdout.write(formatObject19(result2, { format: args.output ?? "json" }) + "\n");
9220
+ process.stdout.write(formatObject21(result2, { format: args.output ?? "json" }) + "\n");
8553
9221
  } catch (cause) {
8554
9222
  const err = cause;
8555
- if (err?.isAxiosError) exitWithError(fromAxiosError17(err, args.env));
9223
+ if (err?.isAxiosError) exitWithError(fromAxiosError18(err, args.env));
8556
9224
  exitWithError(cause);
8557
9225
  }
8558
9226
  }
@@ -8560,8 +9228,8 @@ async function promptPasswordTwice() {
8560
9228
  const password = await promptSecret("\u65B0\u5BC6\u7801: ");
8561
9229
  const confirmation = await promptSecret("\u518D\u6B21\u8F93\u5165\u65B0\u5BC6\u7801: ");
8562
9230
  if (password !== confirmation) {
8563
- throw new CliError21({
8564
- code: CliErrorCode20.INVALID_ARGUMENT,
9231
+ throw new CliError23({
9232
+ code: CliErrorCode22.INVALID_ARGUMENT,
8565
9233
  message: "\u4E24\u6B21\u8F93\u5165\u7684\u65B0\u5BC6\u7801\u4E0D\u4E00\u81F4"
8566
9234
  });
8567
9235
  }
@@ -8607,8 +9275,9 @@ identity.command("use <name>").description("\u628A identity \u8BBE\u4E3A\u5176 e
8607
9275
  identity.command("remove <name>").description("\u5220\u9664 identity\uFF08\u6E05 token + \u82E5\u662F env default \u5219\u6E05\u7A7A\uFF09").action((name) => identityRemove(name));
8608
9276
  var user = program.command("user").description("\u7BA1\u7406\u79DF\u6237\u7528\u6237\u7684\u4E13\u7528\u51ED\u636E\u6D41\u7A0B");
8609
9277
  user.command("reset-password").description("\u7531 admin.system \u5B89\u5168\u91CD\u7F6E\u7528\u6237\u5BC6\u7801\uFF0C\u5E76\u4F7F\u65E2\u6709\u4F1A\u8BDD\u5931\u6548").option("--id <uuid>", "\u76EE\u6807\u7528\u6237 ID\uFF08\u4E0E --username \u4E8C\u9009\u4E00\uFF09").option("--username <user>", "\u76EE\u6807\u7528\u6237\u540D\uFF08\u4E0E --id \u4E8C\u9009\u4E00\uFF09").option("--password-stdin", "\u4ECE\u6807\u51C6\u8F93\u5165\u8BFB\u53D6\u65B0\u5BC6\u7801\uFF08Agent/\u53D7\u63A7\u4EA4\u4ED8\u5FC5\u987B\u4F7F\u7528\uFF09").option("--no-force-change", "\u4E0B\u6B21\u767B\u5F55\u4E0D\u5F3A\u5236\u6539\u5BC6\uFF08\u4EC5\u9650\u5DF2\u6279\u51C6\u7684\u9694\u79BB\u6D4B\u8BD5\u73AF\u5883\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\u5FC5\u987B\u5177\u5907 admin.system\uFF09").option("--output <fmt>", "\u8F93\u51FA\u683C\u5F0F\uFF1Atable | json | yaml", "json").action((opts) => userResetPasswordCommand(opts));
8610
- var delivery = program.command("delivery").description("\u987E\u95EE\u4EA4\u4ED8\u547D\u4EE4\u7684\u98CE\u9669\u8BC4\u4F30\u4E0E\u4E00\u6B21\u6027\u53D7\u63A7\u6267\u884C\u5408\u540C");
9278
+ var delivery = program.command("delivery").description("\u987E\u95EE\u4EA4\u4ED8\uFF1A\u73B0\u573A\u63A2\u6D3B\u3001\u98CE\u9669\u8BC4\u4F30\u4E0E\u4E00\u6B21\u6027\u53D7\u63A7\u6267\u884C\u5408\u540C");
8611
9279
  delivery.command("assess").description("\u8BC4\u4F30\u4E00\u6B21 HCM CLI argv\uFF1BAction \u98CE\u63A7\u58F0\u660E\u8BFB\u53D6\u81EA\u76EE\u6807 Core\uFF0C\u7528 -- \u5206\u9694\u88AB\u8BC4\u4F30\u547D\u4EE4").option("--output <fmt>", "\u8F93\u51FA\u683C\u5F0F\uFF1Atable | json | yaml", "json").allowUnknownOption(true).argument("<command...>", "\u88AB\u8BC4\u4F30\u7684 HCM \u5B50\u547D\u4EE4\u4E0E\u53C2\u6570\uFF0C\u4E0D\u5305\u542B hcm \u672C\u8EAB").action((command, opts) => deliveryAssessCommand(command, opts));
9280
+ delivery.command("doctor").description("\u56DB\u6761\u951A\u70B9\u63A2\u6D3B\uFF1A\u8FDE\u901A / \u6211\u662F\u8C01 / configAdmin / \u7AD9\u5728\u54EA\u4E00\u5C42").option("--env <name>", "\u76EE\u6807\u73AF\u5883\u522B\u540D").option("--as <identity>", "\u4E34\u65F6\u6362\u8EAB\u4EFD").option("--capabilities <s>", "\u722C\u53D6\u65F6\u58F0\u660E\u7684 capability \u4E32\uFF08\u4F1A\u968F\u56DB\u5143\u7EC4\u7559\u6863\uFF09").option("--output <fmt>", "\u8F93\u51FA\u683C\u5F0F\uFF1Atable | json | yaml", "json").action((opts) => deliveryDoctorCommand(opts));
8612
9281
  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));
8613
9282
  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));
8614
9283
  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(
@@ -8670,12 +9339,13 @@ meta.command("list").description("\u5217\u51FA\u79DF\u6237\u5143\u6570\u636E\u65
8670
9339
  meta.command("get <path>").description("\u6253\u5370 meta \u539F\u6587\uFF08\u5982 metas/Employee.list.yml\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").action((p, opts) => metaGetCommand(p, opts));
8671
9340
  meta.command("set <path>").description("\u5199\u5165 meta \u539F\u6587\uFF1B\u5199\u5B8C\u987B hcm cache clear-meta <Model> \u624D\u751F\u6548").requiredOption("--file <file>", "\u4ECE\u6587\u4EF6\u8BFB\u53D6\u539F\u6587\uFF08- \u8868\u793A stdin\uFF09").option("--dry-run", "\u53EA\u663E\u793A\u5C06\u5199\u5165\u7684\u5185\u5BB9\uFF0C\u4E0D\u5B9E\u9645\u5199\u5165").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").option("--output <fmt>", "\u8F93\u51FA\u683C\u5F0F\uFF1Atable | json | yaml", "json").action((p, opts) => metaSetCommand(p, opts));
8672
9341
  meta.command("delete <path>").description("\u5220\u9664 meta\uFF08\u4E0D\u53EF\u9006\uFF0C\u9ED8\u8BA4\u8FC7\u786E\u8BA4\u95F8\uFF09").option("-y, --yes", "\u8DF3\u8FC7\u786E\u8BA4").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").option("--output <fmt>", "\u8F93\u51FA\u683C\u5F0F\uFF1Atable | json | yaml", "json").action((p, opts) => metaDeleteCommand(p, opts));
8673
- var skills = program.command("skills").description("\u777F\u620E Chiron \u4EA4\u4ED8\u6280\u80FD\u5E93\uFF1A\u5217\u51FA / \u67E5\u770B / \u5B89\u88C5\u4EA4\u4ED8\u6280\u80FD\uFF08\u514D\u8BA4\u8BC1\uFF0C\u65E0\u9700\u5148 login\uFF09");
8674
- skills.command("list [keyword]").description("\u5217\u51FA\u76EE\u6807\u73AF\u5883\u8FD9\u4E00\u7248\u7684\u4EA4\u4ED8\u6280\u80FD\uFF1B--installed \u6539\u770B\u672C\u5730\u88C5\u4E86\u54EA\u4E9B\uFF08\u4E0D\u8FDE\u7F51\uFF09").option("--installed", "\u53EA\u770B\u672C\u5730\u5DF2\u88C5\u7684\u6280\u80FD\uFF08\u8BFB .hcm-skills.json\uFF0C\u4E0D\u8FDE\u7F51\uFF09").option("--target <agent>", "\u914D\u5408 --installed\uFF1Aclaude | codex | auto", "auto").option("--global", "\u914D\u5408 --installed\uFF1A\u770B\u7528\u6237\u7EA7\u76EE\u5F55").option("--dir <path>", "\u914D\u5408 --installed\uFF1A\u770B\u6307\u5B9A\u76EE\u5F55").option("--category <key>", "\u53EA\u770B\u67D0\u4E2A\u5206\u7C7B").option("--stage <key>", "\u53EA\u770B\u67D0\u4E2A\u4EA4\u4ED8\u9636\u6BB5\uFF1Ahandover | baseline | configure | migrate | integrate | golive | operate").option("--by-stage", "\u6309\u4EA4\u4ED8\u751F\u547D\u5468\u671F\u5206\u7EC4\u5C55\u793A\uFF08\u9ED8\u8BA4\u6309\u529F\u80FD\u5206\u7C7B\uFF09").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((kw, opts) => skillsListCommand(kw, opts));
8675
- skills.command("show <id>").description("\u6253\u5370\u6280\u80FD\u539F\u6587\uFF08\u7BA1\u9053\u53CB\u597D\uFF09").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));
8676
- 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("--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));
9342
+ var skills = program.command("skills").description("\u4EA4\u4ED8\u6280\u80FD\uFF1A\u777F\u620E Chiron \u6280\u80FD\u5E93 + CLI \u81EA\u5E26\u6280\u80FD\uFF08\u514D\u8BA4\u8BC1\uFF0C\u65E0\u9700\u5148 login\uFF09");
9343
+ skills.command("list [keyword]").description("\u5217\u51FA\u76EE\u6807\u73AF\u5883\u8FD9\u4E00\u7248\u7684\u4EA4\u4ED8\u6280\u80FD\uFF1B--installed \u6539\u770B\u672C\u5730\u88C5\u4E86\u54EA\u4E9B\uFF08\u4E0D\u8FDE\u7F51\uFF09").option("--installed", "\u53EA\u770B\u672C\u5730\u5DF2\u88C5\u7684\u6280\u80FD\uFF08\u8BFB .hcm-skills.json\uFF0C\u4E0D\u8FDE\u7F51\uFF09").option("--target <agent>", "\u914D\u5408 --installed\uFF1Aclaude | codex | auto", "auto").option("--global", "\u914D\u5408 --installed\uFF1A\u770B\u7528\u6237\u7EA7\u76EE\u5F55").option("--dir <path>", "\u914D\u5408 --installed\uFF1A\u770B\u6307\u5B9A\u76EE\u5F55").option("--category <key>", "\u53EA\u770B\u67D0\u4E2A\u5206\u7C7B").option("--stage <key>", "\u53EA\u770B\u67D0\u4E2A\u4EA4\u4ED8\u9636\u6BB5\uFF1Ahandover | baseline | configure | migrate | integrate | golive | operate").option("--by-stage", "\u6309\u4EA4\u4ED8\u751F\u547D\u5468\u671F\u5206\u7EC4\u5C55\u793A\uFF08\u9ED8\u8BA4\u6309\u529F\u80FD\u5206\u7C7B\uFF09").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").option("--output <fmt>", "\u8F93\u51FA\u683C\u5F0F\uFF1Atable | json | yaml", "table").action((kw, opts) => skillsListCommand(kw, opts));
9344
+ 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));
9345
+ 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));
9346
+ 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));
8677
9347
  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));
8678
- 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("--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));
9348
+ 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));
8679
9349
  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));
8680
9350
  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));
8681
9351
  var setting = program.command("setting").description("\u79DF\u6237\u7CFB\u7EDF\u53C2\u6570\uFF08\u767B\u5F55\u7B56\u7565 / \u5BC6\u7801\u7B56\u7565 / \u529F\u80FD\u5F00\u5173 / \u96C6\u6210\u53C2\u6570\uFF09");
@@ -8695,9 +9365,14 @@ async function main() {
8695
9365
  }
8696
9366
  await program.parseAsync(process.argv);
8697
9367
  }
8698
- main().catch((e) => {
8699
- process.stderr.write(`[hcm] fatal: ${String(e.message)}
9368
+ if (process.env.HCM_CLI_IMPORT_ONLY !== "1") {
9369
+ main().catch((e) => {
9370
+ process.stderr.write(`[hcm] fatal: ${String(e.message)}
8700
9371
  `);
8701
- process.exit(1);
8702
- });
9372
+ process.exit(1);
9373
+ });
9374
+ }
9375
+ export {
9376
+ program
9377
+ };
8703
9378
  //# sourceMappingURL=index.js.map