@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 +110 -15
- package/dist/index.js.map +1 -1
- package/dist/skills/manifest.json +19 -1
- package/package.json +2 -2
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:
|
|
2289
|
+
const { fromAxiosError: fromAxiosError20 } = await import("@hcmai/sdk");
|
|
2290
2290
|
exitWithError(
|
|
2291
|
-
|
|
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
|
|
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-
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
9235
|
+
HcmClient as HcmClient20,
|
|
9148
9236
|
adminResetPassword,
|
|
9149
|
-
formatObject as
|
|
9150
|
-
fromAxiosError as
|
|
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 =
|
|
9269
|
+
const client3 = HcmClient20.fromAuthContext(await getActiveAuthContextFromCli(args));
|
|
9182
9270
|
const result2 = await adminResetPassword(client3.raw(), request);
|
|
9183
|
-
process.stdout.write(
|
|
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(
|
|
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(
|