@hcmai/cli 0.3.5 → 0.3.7

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
@@ -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: fromAxiosError19 } = await import("@hcmai/sdk");
2289
+ const { fromAxiosError: fromAxiosError20 } = await import("@hcmai/sdk");
2290
2290
  exitWithError(
2291
- fromAxiosError19(
2291
+ fromAxiosError20(
2292
2292
  e,
2293
2293
  envName
2294
2294
  )
@@ -8644,14 +8644,65 @@ async function deliveryDoctorCommand(args) {
8644
8644
  }
8645
8645
  }
8646
8646
 
8647
+ // src/commands/delivery-recon.ts
8648
+ init_auth_guard();
8649
+ init_exit();
8650
+ import {
8651
+ HcmClient as HcmClient19,
8652
+ ReconLayout,
8653
+ ROUND_EXIT_CODES,
8654
+ computeReconSourceKey,
8655
+ formatObject as formatObject20,
8656
+ fromAxiosError as fromAxiosError18,
8657
+ httpProbe as httpProbe2,
8658
+ inspectRound,
8659
+ renderRound,
8660
+ runRecon
8661
+ } from "@hcmai/sdk";
8662
+ var DEFAULT_CAPABILITIES2 = "default";
8663
+ async function deliveryReconCommand(args) {
8664
+ try {
8665
+ const ctx = await getActiveAuthContextFromCli(args);
8666
+ const client3 = HcmClient19.fromAuthContext(ctx);
8667
+ const probe = httpProbe2(client3.raw(), args.capabilities ?? DEFAULT_CAPABILITIES2);
8668
+ const sourceKey = await computeReconSourceKey(probe);
8669
+ const layout = new ReconLayout(args.out ?? ".", ctx.tenantId, sourceKey);
8670
+ const summary = await runRecon(probe, layout, {
8671
+ state: args.state ?? "",
8672
+ onlyModel: args.model ?? null,
8673
+ identity: ctx.tenantId ? { requestedTenantId: ctx.tenantId } : null
8674
+ });
8675
+ process.stdout.write(formatObject20(summary, { format: args.output ?? "json" }) + "\n");
8676
+ } catch (e) {
8677
+ const err = e;
8678
+ if (err?.isAxiosError) exitWithError(fromAxiosError18(err, args.env));
8679
+ exitWithError(e);
8680
+ process.exit(1);
8681
+ }
8682
+ }
8683
+ async function deliveryReconRoundCommand(args) {
8684
+ let code;
8685
+ try {
8686
+ const result2 = inspectRound(args.dir ?? ".");
8687
+ const fmt = args.output ?? "json";
8688
+ if (fmt !== "json") process.stdout.write(renderRound(result2));
8689
+ process.stdout.write(formatObject20(result2, { format: fmt }) + "\n");
8690
+ code = ROUND_EXIT_CODES[result2.state];
8691
+ } catch (e) {
8692
+ exitWithError(e);
8693
+ code = 1;
8694
+ }
8695
+ process.exit(code);
8696
+ }
8697
+
8647
8698
  // src/commands/delivery-execution.ts
8648
8699
  import { createHash as createHash7, randomBytes as secureRandomBytes } from "crypto";
8649
8700
  import { spawn } from "child_process";
8650
8701
  import { createReadStream as createReadStream2, promises as fs8 } from "fs";
8651
8702
  import path8 from "path";
8652
- import { CliError as CliError22, CliErrorCode as CliErrorCode21, formatObject as formatObject20 } from "@hcmai/sdk";
8703
+ import { CliError as CliError22, CliErrorCode as CliErrorCode21, formatObject as formatObject21 } from "@hcmai/sdk";
8653
8704
  init_exit();
8654
- var EXECUTION_CONTRACT_VERSION = "2026-08-28.controlled-v1";
8705
+ var EXECUTION_CONTRACT_VERSION = "2026-08-29.controlled-v2";
8655
8706
  var DEFAULT_TTL_SECONDS = 15 * 60;
8656
8707
  var MIN_TTL_SECONDS = 60;
8657
8708
  var MAX_TTL_SECONDS = 60 * 60;
@@ -8667,6 +8718,7 @@ async function prepareDeliveryExecution(input) {
8667
8718
  }
8668
8719
  const change = await bindDocument(project, input.changeRef, "\u53D8\u66F4\u8BF4\u660E");
8669
8720
  const rollback = await bindDocument(project, input.rollbackRef, "\u56DE\u6EDA\u8BF4\u660E");
8721
+ const payloads = await bindPayloadFiles(project, input.argv);
8670
8722
  const evidence = await bindEvidenceDirectory(project, input.evidenceDir);
8671
8723
  const { bytes: lockBytes, runtime: lockedRuntime } = await readChironLock(project);
8672
8724
  const runtime = await (input.runtimeIdentity ?? currentRuntimeIdentity)();
@@ -8683,6 +8735,7 @@ async function prepareDeliveryExecution(input) {
8683
8735
  runtime,
8684
8736
  assessment,
8685
8737
  documents: { change, rollback },
8738
+ payloads,
8686
8739
  evidenceDir: evidence.relative
8687
8740
  };
8688
8741
  const planId = sha2567(canonicalJson(core)).slice(0, 24);
@@ -8738,6 +8791,7 @@ async function executeDeliveryPlan(input) {
8738
8791
  }
8739
8792
  await assertDocumentUnchanged(project, plan.documents.change, "\u53D8\u66F4\u8BF4\u660E");
8740
8793
  await assertDocumentUnchanged(project, plan.documents.rollback, "\u56DE\u6EDA\u8BF4\u660E");
8794
+ await assertPayloadsUnchanged(project, plan.payloads);
8741
8795
  const evidenceDir = await bindEvidenceDirectory(project, plan.evidenceDir);
8742
8796
  const receiptFile = path8.join(evidenceDir.absolute, `${plan.planId}.receipt.json`);
8743
8797
  if (await pathExists(receiptFile)) throw invalid4(`\u6267\u884C\u6536\u636E\u5DF2\u5B58\u5728\uFF0C\u62D2\u7EDD\u518D\u6B21\u6267\u884C\uFF1A${plan.planId}`);
@@ -8802,7 +8856,7 @@ async function deliveryPrepareCommand(argv, args) {
8802
8856
  evidenceDir: args.evidenceDir,
8803
8857
  ...ttlSeconds === void 0 ? {} : { ttlSeconds }
8804
8858
  });
8805
- process.stdout.write(formatObject20(plan, { format: args.output ?? "json" }) + "\n");
8859
+ process.stdout.write(formatObject21(plan, { format: args.output ?? "json" }) + "\n");
8806
8860
  } catch (cause) {
8807
8861
  exitWithError(cause);
8808
8862
  }
@@ -8814,7 +8868,7 @@ async function deliveryExecuteCommand(planId, argv, args) {
8814
8868
  planId,
8815
8869
  argv
8816
8870
  });
8817
- process.stdout.write(formatObject20(receipt, { format: args.output ?? "json" }) + "\n");
8871
+ process.stdout.write(formatObject21(receipt, { format: args.output ?? "json" }) + "\n");
8818
8872
  process.exitCode = receipt.exitCode;
8819
8873
  } catch (cause) {
8820
8874
  exitWithError(cause);
@@ -8926,12 +8980,12 @@ function validateSupportedCommandShape(reasonCode, argv) {
8926
8980
  return;
8927
8981
  }
8928
8982
  if (reasonCode === "record-create") {
8929
- requireFlagValue(argv, "--data", "create \u5FC5\u987B\u5305\u542B --data <JSON>");
8983
+ requireExactlyOnePayload(argv, "create");
8930
8984
  return;
8931
8985
  }
8932
8986
  if (reasonCode === "record-update") {
8933
8987
  requireFlagValue(argv, "--id", "update \u5FC5\u987B\u5305\u542B --id <id>");
8934
- requireFlagValue(argv, "--data", "update \u5FC5\u987B\u5305\u542B --data <JSON>");
8988
+ requireExactlyOnePayload(argv, "update");
8935
8989
  return;
8936
8990
  }
8937
8991
  if (reasonCode === "cache-mutation") {
@@ -8962,6 +9016,40 @@ function optionalFlagValue(argv, flag) {
8962
9016
  }
8963
9017
  return void 0;
8964
9018
  }
9019
+ function requireExactlyOnePayload(argv, command) {
9020
+ const inline = optionalFlagValue(argv, "--data") !== void 0;
9021
+ const fromFile = optionalFlagValue(argv, "--data-file") !== void 0;
9022
+ if (inline && fromFile) {
9023
+ throw invalid4(`${command} \u7684 --data \u4E0E --data-file \u4E92\u65A5\uFF0C\u53EA\u80FD\u7ED9\u4E00\u4E2A`);
9024
+ }
9025
+ if (!inline && !fromFile) {
9026
+ throw invalid4(`${command} \u5FC5\u987B\u5305\u542B --data <JSON> \u6216 --data-file <\u6587\u4EF6>`);
9027
+ }
9028
+ }
9029
+ var PAYLOAD_FILE_FLAGS = ["--data-file", "--params-file"];
9030
+ async function bindPayloadFiles(project, argv) {
9031
+ const bound = [];
9032
+ for (const flag of PAYLOAD_FILE_FLAGS) {
9033
+ const reference = optionalFlagValue(argv, flag);
9034
+ if (reference === void 0) continue;
9035
+ bound.push(await bindPayloadFile(project, reference, `${flag} \u8F7D\u8377`));
9036
+ }
9037
+ return bound;
9038
+ }
9039
+ async function bindPayloadFile(project, reference, label) {
9040
+ const relative2 = safeRelative(reference, label);
9041
+ const file = path8.join(project, relative2);
9042
+ const bytes = await readSafeFile(project, file, label);
9043
+ return { path: relative2, sha256: sha2567(bytes) };
9044
+ }
9045
+ async function assertPayloadsUnchanged(project, payloads) {
9046
+ for (const payload of payloads) {
9047
+ const current = await bindPayloadFile(project, payload.path, `\u8F7D\u8377 ${payload.path}`);
9048
+ if (current.sha256 !== payload.sha256) {
9049
+ throw invalid4(`\u8F7D\u8377\u6587\u4EF6 ${payload.path} \u7684\u5185\u5BB9\u5DF2\u53D8\u66F4\uFF0C\u8BF7\u91CD\u65B0 prepare`);
9050
+ }
9051
+ }
9052
+ }
8965
9053
  function requireFlagValue(argv, flag, message) {
8966
9054
  for (let index = 0; index < argv.length; index += 1) {
8967
9055
  const value = argv[index];
@@ -9100,7 +9188,7 @@ function isRuntimeIdentity(value) {
9100
9188
  }
9101
9189
  function isExecutionPlan(value) {
9102
9190
  if (!isRecord(value)) return false;
9103
- 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";
9191
+ 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";
9104
9192
  }
9105
9193
  function isBoundDocument(value) {
9106
9194
  return isRecord(value) && typeof value.path === "string" && isSha(value.sha256);
@@ -9144,10 +9232,10 @@ function invalid4(message, cause) {
9144
9232
  init_auth_guard();
9145
9233
  init_exit();
9146
9234
  import {
9147
- HcmClient as HcmClient19,
9235
+ HcmClient as HcmClient20,
9148
9236
  adminResetPassword,
9149
- formatObject as formatObject21,
9150
- fromAxiosError as fromAxiosError18,
9237
+ formatObject as formatObject22,
9238
+ fromAxiosError as fromAxiosError19,
9151
9239
  CliError as CliError23,
9152
9240
  CliErrorCode as CliErrorCode22
9153
9241
  } from "@hcmai/sdk";
@@ -9178,12 +9266,12 @@ async function userResetPasswordCommand(args) {
9178
9266
  try {
9179
9267
  const password = args.passwordStdin ? await readSecretFromStdin() : await promptPasswordTwice();
9180
9268
  const request = buildAdminResetPasswordRequest(args, password);
9181
- const client3 = HcmClient19.fromAuthContext(await getActiveAuthContextFromCli(args));
9269
+ const client3 = HcmClient20.fromAuthContext(await getActiveAuthContextFromCli(args));
9182
9270
  const result2 = await adminResetPassword(client3.raw(), request);
9183
- process.stdout.write(formatObject21(result2, { format: args.output ?? "json" }) + "\n");
9271
+ process.stdout.write(formatObject22(result2, { format: args.output ?? "json" }) + "\n");
9184
9272
  } catch (cause) {
9185
9273
  const err = cause;
9186
- if (err?.isAxiosError) exitWithError(fromAxiosError18(err, args.env));
9274
+ if (err?.isAxiosError) exitWithError(fromAxiosError19(err, args.env));
9187
9275
  exitWithError(cause);
9188
9276
  }
9189
9277
  }
@@ -9241,6 +9329,13 @@ user.command("reset-password").description("\u7531 admin.system \u5B89\u5168\u91
9241
9329
  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");
9242
9330
  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));
9243
9331
  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));
9332
+ var recon = delivery.command("recon").description("\u722C\u4E00\u4EFD\u53EF\u5E26\u8D70\u7684\u57FA\u7EBF\uFF1A\u6A21\u578B / \u5B57\u6BB5 / \u53EA\u8BFB\u95F8 / \u4F9D\u8D56\u56FE / \u7801\u8868 / \u53EF\u5199\u6027\u753B\u50CF").option("--env <name>", "\u76EE\u6807\u73AF\u5883\u522B\u540D").option("--as <identity>", "\u4E34\u65F6\u6362\u8EAB\u4EFD").option("--out <dir>", "\u4EA7\u7269\u6839\u76EE\u5F55\uFF08\u4EA7\u7269\u843D\u5728 <out>/recon/<\u79DF\u6237\u6BB5>/<\u6765\u6E90\u6BB5>\uFF09", ".").option("--state <s>", "\u53EA\u8BFB\u95F8\u7684 state\uFF08\u4EA7\u54C1\u91CC state \u4E0D\u53EF\u679A\u4E3E\uFF0C\u95F8\u7684\u8986\u76D6\u9762\u6C38\u8FDC\u662F state-scoped\uFF09").option("--model <key>", "\u5B9A\u5411\u91CD\u722C\uFF1A\u53EA\u91CD\u722C\u8FD9\u4E00\u4E2A\u6A21\u578B\uFF0C\u5176\u4F59\u6CBF\u7528\u4E0A\u4E00\u8F6E\u4EA7\u7269").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) => deliveryReconCommand(opts));
9333
+ recon.command("round").description("\u96F6\u7F51\u7EDC\uFF1A\u8BFB\u4E00\u4EFD\u5DF2\u843D\u76D8\u7684\u57FA\u7EBF\uFF0C\u5224\u65AD\u5B83\u662F\u4E0D\u662F\u4E00\u8F6E\u5B8C\u6574\u8DD1\u51FA\u6765\u7684\uFF08complete/mixed/unknown\uFF09").option("--dir <dir>", "\u4EA7\u7269\u76EE\u5F55\uFF08<out>/recon/<\u79DF\u6237\u6BB5>/<\u6765\u6E90\u6BB5>\uFF09", ".").action(
9334
+ (opts, cmd) => deliveryReconRoundCommand({
9335
+ ...opts,
9336
+ output: cmd.parent?.opts()?.output
9337
+ })
9338
+ );
9244
9339
  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));
9245
9340
  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));
9246
9341
  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(