@actiondock/core 2.10.0 → 2.12.0
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/README.md +1 -2
- package/dist/catalog/action-catalog.js +3 -33
- package/dist/catalog/discovery.d.ts +0 -3
- package/dist/catalog/discovery.js +4 -4
- package/dist/catalog/graph.d.ts +0 -4
- package/dist/catalog/graph.js +8 -14
- package/dist/{profile/client-actions.d.ts → client/actions.d.ts} +1 -1
- package/dist/{profile/client-actions.js → client/actions.js} +2 -8
- package/dist/{profile/client-config.d.ts → client/config.d.ts} +1 -1
- package/dist/{profile/client-config.js → client/config.js} +1 -1
- package/dist/client/dispatcher.d.ts +4 -0
- package/dist/client/dispatcher.js +21 -0
- package/dist/client/health.d.ts +38 -0
- package/dist/{profile/client-health.js → client/health.js} +9 -6
- package/dist/client/index.d.ts +16 -0
- package/dist/client/index.js +20 -0
- package/dist/{profile/client-playbooks.d.ts → client/playbooks.d.ts} +1 -1
- package/dist/{profile/client-playbooks.js → client/playbooks.js} +1 -1
- package/dist/{profile/client-runs.d.ts → client/runs.d.ts} +4 -2
- package/dist/{profile/client-runs.js → client/runs.js} +7 -1
- package/dist/{profile/client-state.d.ts → client/state.d.ts} +1 -1
- package/dist/{profile/client-state.js → client/state.js} +1 -1
- package/dist/{profile/client-transport.d.ts → client/transport.d.ts} +29 -10
- package/dist/{profile/client-transport.js → client/transport.js} +125 -35
- package/dist/doctor/checks/index.d.ts +1 -1
- package/dist/doctor/checks/index.js +1 -1
- package/dist/doctor/checks/project.js +20 -88
- package/dist/doctor/checks/runtime.d.ts +0 -4
- package/dist/doctor/checks/runtime.js +0 -28
- package/dist/doctor/doctor.js +1 -2
- package/dist/errors.d.ts +53 -3
- package/dist/errors.js +53 -3
- package/dist/execution/service.d.ts +55 -37
- package/dist/execution/service.js +601 -212
- package/dist/execution/types.d.ts +24 -5
- package/dist/host/host.d.ts +42 -22
- package/dist/host/host.js +562 -149
- package/dist/host/routing.js +6 -6
- package/dist/host/types.d.ts +25 -13
- package/dist/index.d.ts +9 -4
- package/dist/index.js +5 -2
- package/dist/input/advice.d.ts +0 -44
- package/dist/input/advice.js +7 -141
- package/dist/input/flat-materializer.js +1 -1
- package/dist/input/flat-parser.js +1 -1
- package/dist/input/index.d.ts +0 -1
- package/dist/input/index.js +0 -1
- package/dist/input/input-resolver.js +1 -1
- package/dist/input/validation-mapper.d.ts +1 -1
- package/dist/ipc/diagnostic.d.ts +8 -21
- package/dist/ipc/diagnostic.js +24 -57
- package/dist/ipc/host.js +21 -7
- package/dist/ipc/service.d.ts +14 -0
- package/dist/ipc/service.js +132 -26
- package/dist/ipc/types.d.ts +0 -4
- package/dist/package/index.d.ts +4 -5
- package/dist/package/index.js +1 -2
- package/dist/package/runtime.d.ts +94 -23
- package/dist/package/runtime.js +628 -274
- package/dist/package/static-index.d.ts +3 -6
- package/dist/package/static-index.js +11 -40
- package/dist/package/types.d.ts +19 -4
- package/dist/platform/index.d.ts +2 -1
- package/dist/platform/index.js +2 -1
- package/dist/platform/loader-hook.d.ts +32 -0
- package/dist/platform/loader-hook.js +90 -0
- package/dist/{node → platform}/module-loader.d.ts +13 -0
- package/dist/{node → platform}/module-loader.js +51 -4
- package/dist/platform/node.d.ts +19 -8
- package/dist/platform/node.js +50 -20
- package/dist/platform/types.d.ts +7 -47
- package/dist/process/context-process.d.ts +3 -18
- package/dist/process/context-process.js +3 -44
- package/dist/process/control.d.ts +21 -0
- package/dist/process/control.js +34 -0
- package/dist/process/converters.d.ts +23 -0
- package/dist/process/converters.js +92 -0
- package/dist/process/cursor.js +2 -22
- package/dist/process/{diagnostics-sink.d.ts → diagnostics.d.ts} +0 -7
- package/dist/process/{diagnostics-sink.js → diagnostics.js} +6 -8
- package/dist/process/index.d.ts +1 -3
- package/dist/process/index.js +1 -3
- package/dist/process/input-dispatcher.d.ts +4 -13
- package/dist/process/input-dispatcher.js +48 -69
- package/dist/process/managed-record.d.ts +3 -31
- package/dist/process/metadata-store.d.ts +0 -41
- package/dist/process/metadata-store.js +2 -341
- package/dist/process/process-driver.js +2 -2
- package/dist/process/process-manager.d.ts +8 -50
- package/dist/process/process-manager.js +28 -417
- package/dist/process/quotas.d.ts +14 -0
- package/dist/process/quotas.js +29 -0
- package/dist/process/run-executor.js +0 -1
- package/dist/process/terminal-output-cache.d.ts +20 -34
- package/dist/process/terminal-output-cache.js +43 -64
- package/dist/profile/index.d.ts +1 -2
- package/dist/profile/index.js +1 -2
- package/dist/profile/manager.d.ts +2 -4
- package/dist/profile/manager.js +10 -40
- package/dist/profile/types.d.ts +1 -17
- package/dist/project/digest.d.ts +5 -1
- package/dist/project/digest.js +81 -219
- package/dist/project/index.d.ts +4 -5
- package/dist/project/index.js +4 -5
- package/dist/project/init.js +2 -2
- package/dist/project/loader.d.ts +3 -3
- package/dist/project/loader.js +72 -50
- package/dist/project/lockfile.js +6 -5
- package/dist/project/manifest.js +5 -4
- package/dist/project/transactions.d.ts +4 -42
- package/dist/project/transactions.js +83 -138
- package/dist/project/types-generator.js +2 -1
- package/dist/project/types.d.ts +2 -0
- package/dist/registry/index.d.ts +0 -1
- package/dist/registry/index.js +0 -1
- package/dist/registry/lock.d.ts +2 -11
- package/dist/registry/lock.js +14 -183
- package/dist/registry/registry.d.ts +1 -6
- package/dist/registry/registry.js +5 -17
- package/dist/runtime/action-registry.d.ts +1 -5
- package/dist/runtime/action-registry.js +0 -12
- package/dist/runtime/context.js +2 -2
- package/dist/runtime/events.d.ts +11 -50
- package/dist/runtime/events.js +88 -368
- package/dist/runtime/index.d.ts +0 -4
- package/dist/runtime/index.js +0 -4
- package/dist/runtime/run-persistence.d.ts +2 -0
- package/dist/runtime/run-persistence.js +2 -1
- package/dist/runtime/standalone-commands.d.ts +18 -0
- package/dist/runtime/standalone-commands.js +466 -0
- package/dist/runtime/standalone-help.d.ts +20 -0
- package/dist/runtime/standalone-help.js +72 -0
- package/dist/runtime/standalone.d.ts +1 -44
- package/dist/runtime/standalone.js +32 -573
- package/dist/schema/validator.d.ts +2 -2
- package/dist/schema/validator.js +2 -9
- package/dist/server/index.d.ts +0 -2
- package/dist/server/index.js +0 -2
- package/dist/server/routes/actions.js +1 -1
- package/dist/server/routes/info.js +1 -1
- package/dist/server/routes/playbooks.js +1 -1
- package/dist/server/routes/runs.js +123 -16
- package/dist/server/routes/state.js +43 -18
- package/dist/server/security.d.ts +1 -1
- package/dist/server/security.js +2 -2
- package/dist/server/server.js +3 -7
- package/dist/service/factory.js +4 -3
- package/dist/service/index.d.ts +1 -1
- package/dist/service/index.js +1 -1
- package/dist/service/remote-errors.d.ts +1 -1
- package/dist/service/remote-errors.js +6 -6
- package/dist/service/remote-polling.d.ts +3 -0
- package/dist/service/remote-polling.js +10 -5
- package/dist/service/remote.d.ts +5 -1
- package/dist/service/remote.js +108 -17
- package/dist/service/sse-stream.js +2 -2
- package/dist/service/types.d.ts +22 -19
- package/dist/service/types.js +1 -24
- package/dist/storage/clock.d.ts +1 -1
- package/dist/storage/clock.js +1 -1
- package/dist/storage/data-dir-lock.d.ts +10 -22
- package/dist/storage/data-dir-lock.js +28 -56
- package/dist/storage/file-lock.d.ts +64 -0
- package/dist/storage/file-lock.js +447 -0
- package/dist/storage/index.d.ts +2 -2
- package/dist/storage/index.js +5 -4
- package/dist/storage/run-liveness.d.ts +48 -0
- package/dist/storage/run-liveness.js +44 -0
- package/dist/storage/sqlite-config.d.ts +16 -0
- package/dist/storage/sqlite-config.js +59 -0
- package/dist/storage/sqlite-driver.d.ts +3 -1
- package/dist/storage/sqlite-driver.js +14 -4
- package/dist/storage/sqlite-events.d.ts +13 -0
- package/dist/storage/sqlite-events.js +48 -0
- package/dist/storage/sqlite-runs.d.ts +107 -0
- package/dist/storage/sqlite-runs.js +622 -0
- package/dist/storage/sqlite-schema.d.ts +5 -0
- package/dist/storage/sqlite-schema.js +143 -0
- package/dist/storage/sqlite-state.d.ts +33 -0
- package/dist/storage/sqlite-state.js +270 -0
- package/dist/storage/sqlite.d.ts +30 -57
- package/dist/storage/sqlite.js +84 -741
- package/dist/storage/types.d.ts +35 -2
- package/dist/utils/index.d.ts +18 -14
- package/dist/utils/index.js +37 -29
- package/dist/utils/semver.d.ts +18 -0
- package/dist/utils/semver.js +19 -0
- package/dist/utils/warning.d.ts +1 -0
- package/dist/utils/warning.js +52 -0
- package/dist/{json/value-validator.d.ts → value-validator.d.ts} +9 -0
- package/dist/value-validator.js +330 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +10 -12
- package/dist/execution/index.d.ts +0 -2
- package/dist/execution/index.js +0 -2
- package/dist/filter/index.d.ts +0 -1
- package/dist/filter/index.js +0 -1
- package/dist/graph/index.d.ts +0 -4
- package/dist/graph/index.js +0 -4
- package/dist/input/metadata.d.ts +0 -99
- package/dist/input/metadata.js +0 -99
- package/dist/invocation/index.d.ts +0 -2
- package/dist/invocation/index.js +0 -2
- package/dist/ipc/index.d.ts +0 -4
- package/dist/ipc/index.js +0 -4
- package/dist/json/index.d.ts +0 -1
- package/dist/json/index.js +0 -1
- package/dist/json/value-validator.js +0 -330
- package/dist/node/index.d.ts +0 -1
- package/dist/node/index.js +0 -1
- package/dist/platform/node-fs.d.ts +0 -37
- package/dist/platform/node-fs.js +0 -81
- package/dist/process/control-arbiter.d.ts +0 -108
- package/dist/process/control-arbiter.js +0 -250
- package/dist/process/process-executor.d.ts +0 -47
- package/dist/process/process-executor.js +0 -296
- package/dist/profile/client-health.d.ts +0 -14
- package/dist/profile/client-query.d.ts +0 -30
- package/dist/profile/client-query.js +0 -69
- package/dist/profile/client.d.ts +0 -26
- package/dist/profile/client.js +0 -31
- package/dist/project/closure.d.ts +0 -25
- package/dist/project/closure.js +0 -74
- package/dist/registry/store.d.ts +0 -42
- package/dist/registry/store.js +0 -43
- package/dist/runtime/clock.d.ts +0 -7
- package/dist/runtime/clock.js +0 -7
- package/dist/runtime/module-loader.d.ts +0 -2
- package/dist/runtime/module-loader.js +0 -1
- package/dist/runtime/process.d.ts +0 -8
- package/dist/runtime/process.js +0 -1
- package/dist/runtime/runner.d.ts +0 -234
- package/dist/runtime/runner.js +0 -609
- package/dist/schema/index.d.ts +0 -1
- package/dist/schema/index.js +0 -1
- package/dist/server/dispatcher.d.ts +0 -25
- package/dist/server/dispatcher.js +0 -54
- package/dist/service/local.d.ts +0 -27
- package/dist/service/local.js +0 -141
- package/dist/storage/driver.d.ts +0 -10
- package/dist/storage/driver.js +0 -10
- package/dist/storage/lazy.d.ts +0 -8
- package/dist/storage/lazy.js +0 -45
- package/dist/storage/lock-core.d.ts +0 -158
- package/dist/storage/lock-core.js +0 -872
- package/dist/utils/net.d.ts +0 -10
- package/dist/utils/net.js +0 -16
- package/dist/utils/process.d.ts +0 -10
- package/dist/utils/process.js +0 -21
- /package/dist/{filter → utils}/intent.d.ts +0 -0
- /package/dist/{filter → utils}/intent.js +0 -0
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
import { decodeStateKey } from "@actiondock/sdk";
|
|
2
|
-
import { filterWithFallbackInfo } from "../filter/index.js";
|
|
3
1
|
import { createActionDock } from "../service/factory.js";
|
|
4
|
-
import { STANDALONE_ASYNC_UNSUPPORTED
|
|
5
|
-
import { resolveActionInput, formatActionDetail, buildActionDescribePayload, mapInputValidationFailure, } from "../input/index.js";
|
|
6
|
-
import { validateActionInputValue } from "../json/value-validator.js";
|
|
2
|
+
import { STANDALONE_ASYNC_UNSUPPORTED } from "../errors.js";
|
|
7
3
|
import { normalizeActionCollection } from "./action-collection.js";
|
|
8
|
-
import {
|
|
4
|
+
import { parseStandaloneArgs, printHelp, emitError } from "./standalone-help.js";
|
|
5
|
+
import { handleList, handleDescribe, handleRun, handleConfig, handleState, } from "./standalone-commands.js";
|
|
9
6
|
/**
|
|
10
7
|
* 退出状态码常量。
|
|
11
8
|
*/
|
|
@@ -45,43 +42,10 @@ export class StandaloneDispatcher {
|
|
|
45
42
|
console.error(msg);
|
|
46
43
|
}
|
|
47
44
|
}
|
|
48
|
-
/**
|
|
49
|
-
* 统一错误输出辅助方法。
|
|
50
|
-
*
|
|
51
|
-
* JSON 模式向 stdout 输出两空格缩进的标准错误结构;
|
|
52
|
-
* 纯文本模式向 stderr 输出单行错误消息(默认携带 Error: 前缀)。
|
|
53
|
-
* 消息文本与退出码由调用方逐字给定,输出字节严格保持不变。
|
|
54
|
-
*
|
|
55
|
-
* @param isJson 是否处于 JSON 输出模式
|
|
56
|
-
* @param code 错误码
|
|
57
|
-
* @param message JSON 模式错误消息(兼作纯文本默认消息主体)
|
|
58
|
-
* @param exitCode 调用方应返回的退出状态码
|
|
59
|
-
* @param options 可选项:textMessage 覆盖纯文本消息全文;details 为 JSON 模式可选结构化详情
|
|
60
|
-
* @returns 透传 exitCode 供调用方直接返回
|
|
61
|
-
*/
|
|
62
45
|
emitError(isJson, code, message, exitCode, options) {
|
|
63
|
-
|
|
64
|
-
const details = options?.details;
|
|
65
|
-
const hint = options?.hint ??
|
|
66
|
-
(details && typeof details === "object" && typeof details.hint === "string"
|
|
67
|
-
? details.hint
|
|
68
|
-
: undefined);
|
|
69
|
-
this.writeOut(JSON.stringify({
|
|
70
|
-
ok: false,
|
|
71
|
-
error: {
|
|
72
|
-
code,
|
|
73
|
-
message,
|
|
74
|
-
...(details !== undefined ? { details } : {}),
|
|
75
|
-
},
|
|
76
|
-
...(hint !== undefined ? { hint } : {}),
|
|
77
|
-
}, null, 2));
|
|
78
|
-
}
|
|
79
|
-
else {
|
|
80
|
-
this.writeErr(options?.textMessage ?? `Error: ${message}`);
|
|
81
|
-
}
|
|
82
|
-
return exitCode;
|
|
46
|
+
return emitError(this.writeOut.bind(this), this.writeErr.bind(this), isJson, code, message, exitCode, options);
|
|
83
47
|
}
|
|
84
|
-
async createLocalService(dataDir, configOverrides = {}) {
|
|
48
|
+
async createLocalService(dataDir, configOverrides = {}, accessMode = "owner") {
|
|
85
49
|
if (this.options.service) {
|
|
86
50
|
return { service: this.options.service, ownsService: false };
|
|
87
51
|
}
|
|
@@ -109,6 +73,9 @@ export class StandaloneDispatcher {
|
|
|
109
73
|
};
|
|
110
74
|
const service = await createActionDock({
|
|
111
75
|
runtimeOptions,
|
|
76
|
+
// 发现入口使用旁观初始化:不创建数据库、不取目录锁、不收割遗留运行记录;
|
|
77
|
+
// 执行与写入入口继续持有者初始化(默认 recoverOrphans 语义)
|
|
78
|
+
...(accessMode === "observer" ? { recoverOrphans: false } : {}),
|
|
112
79
|
});
|
|
113
80
|
if (this.options.inMemory) {
|
|
114
81
|
this.options._sharedService = service;
|
|
@@ -116,6 +83,13 @@ export class StandaloneDispatcher {
|
|
|
116
83
|
}
|
|
117
84
|
return { service, ownsService: true };
|
|
118
85
|
}
|
|
86
|
+
printHelp() {
|
|
87
|
+
printHelp(this.writeOut.bind(this), {
|
|
88
|
+
packageId: this.options.packageId,
|
|
89
|
+
version: this.options.version,
|
|
90
|
+
description: this.options.description,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
119
93
|
/**
|
|
120
94
|
* 解析命令行参数并分发执行对应子命令。
|
|
121
95
|
*
|
|
@@ -124,39 +98,7 @@ export class StandaloneDispatcher {
|
|
|
124
98
|
* @returns 退出状态码(0: 成功, 1: 失败, 2: 参数错误, 130: 中断)
|
|
125
99
|
*/
|
|
126
100
|
async dispatch(argv, control) {
|
|
127
|
-
const
|
|
128
|
-
const controlArgs = separator >= 0 ? argv.slice(0, separator) : argv;
|
|
129
|
-
const actionArgs = separator >= 0 ? argv.slice(separator + 1) : [];
|
|
130
|
-
let dataDir;
|
|
131
|
-
const configOverrides = {};
|
|
132
|
-
// 1. 提取全局参数(--data-dir, --config)仅从 controlArgs 中解析
|
|
133
|
-
const filteredArgs = [];
|
|
134
|
-
for (let i = 0; i < controlArgs.length; i++) {
|
|
135
|
-
const arg = controlArgs[i];
|
|
136
|
-
if (arg === "--data-dir" && i + 1 < controlArgs.length) {
|
|
137
|
-
dataDir = controlArgs[++i];
|
|
138
|
-
}
|
|
139
|
-
else if (arg.startsWith("--data-dir=")) {
|
|
140
|
-
dataDir = arg.slice(11);
|
|
141
|
-
}
|
|
142
|
-
else if (arg === "--config" && i + 1 < controlArgs.length) {
|
|
143
|
-
const pair = controlArgs[++i];
|
|
144
|
-
const [k, ...v] = pair.split("=");
|
|
145
|
-
if (k)
|
|
146
|
-
configOverrides[k] = v.join("=");
|
|
147
|
-
}
|
|
148
|
-
else if (arg.startsWith("--config=")) {
|
|
149
|
-
const pair = arg.slice(9);
|
|
150
|
-
const [k, ...v] = pair.split("=");
|
|
151
|
-
if (k)
|
|
152
|
-
configOverrides[k] = v.join("=");
|
|
153
|
-
}
|
|
154
|
-
else {
|
|
155
|
-
filteredArgs.push(arg);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
const command = filteredArgs[0] || "help";
|
|
159
|
-
const subArgs = filteredArgs.slice(1);
|
|
101
|
+
const { controlArgs, actionArgs, dataDir, configOverrides, command, subArgs, } = parseStandaloneArgs(argv);
|
|
160
102
|
// 2. 独立入口拒绝异步启动语义
|
|
161
103
|
if (controlArgs.includes("--async")) {
|
|
162
104
|
return this.emitError(controlArgs.includes("--json"), STANDALONE_ASYNC_UNSUPPORTED, "Async execution is not supported in standalone single-execution binaries. Use 'ad serve' or remote target.", ExitCode.FAILURE, {
|
|
@@ -175,7 +117,10 @@ export class StandaloneDispatcher {
|
|
|
175
117
|
let service;
|
|
176
118
|
let ownsService = false;
|
|
177
119
|
try {
|
|
178
|
-
|
|
120
|
+
// 复用既有命令分发结果确定访问性质:发现命令(list/describe)为旁观;
|
|
121
|
+
// 执行与写入命令(run/config/state)为持有者
|
|
122
|
+
const accessMode = command === "list" || command === "describe" || command === "show" ? "observer" : "owner";
|
|
123
|
+
const serviceRes = await this.createLocalService(dataDir, configOverrides, accessMode);
|
|
179
124
|
service = serviceRes.service;
|
|
180
125
|
ownsService = serviceRes.ownsService;
|
|
181
126
|
}
|
|
@@ -183,24 +128,31 @@ export class StandaloneDispatcher {
|
|
|
183
128
|
this.writeErr(`Error initializing standalone service: ${err?.message || err}`);
|
|
184
129
|
return ExitCode.FAILURE;
|
|
185
130
|
}
|
|
131
|
+
const ctx = {
|
|
132
|
+
service,
|
|
133
|
+
options: this.options,
|
|
134
|
+
writeOut: this.writeOut.bind(this),
|
|
135
|
+
writeErr: this.writeErr.bind(this),
|
|
136
|
+
emitError: this.emitError.bind(this),
|
|
137
|
+
};
|
|
186
138
|
try {
|
|
187
139
|
let code;
|
|
188
140
|
switch (command) {
|
|
189
141
|
case "list":
|
|
190
|
-
code = await
|
|
142
|
+
code = await handleList(ctx, subArgs);
|
|
191
143
|
break;
|
|
192
144
|
case "describe":
|
|
193
145
|
case "show":
|
|
194
|
-
code = await
|
|
146
|
+
code = await handleDescribe(ctx, subArgs);
|
|
195
147
|
break;
|
|
196
148
|
case "run":
|
|
197
|
-
code = await
|
|
149
|
+
code = await handleRun(ctx, subArgs, actionArgs, control?.signal);
|
|
198
150
|
break;
|
|
199
151
|
case "config":
|
|
200
|
-
code = await
|
|
152
|
+
code = await handleConfig(ctx, subArgs);
|
|
201
153
|
break;
|
|
202
154
|
case "state":
|
|
203
|
-
code = await
|
|
155
|
+
code = await handleState(ctx, subArgs);
|
|
204
156
|
break;
|
|
205
157
|
default:
|
|
206
158
|
this.writeErr(`Unknown command: '${command}'`);
|
|
@@ -226,499 +178,6 @@ export class StandaloneDispatcher {
|
|
|
226
178
|
}
|
|
227
179
|
}
|
|
228
180
|
}
|
|
229
|
-
async handleList(service, subArgs) {
|
|
230
|
-
const isJson = subArgs.includes("--json");
|
|
231
|
-
const noFallback = subArgs.includes("--no-fallback");
|
|
232
|
-
let intent;
|
|
233
|
-
const positionalPatterns = [];
|
|
234
|
-
for (let i = 0; i < subArgs.length; i++) {
|
|
235
|
-
const arg = subArgs[i];
|
|
236
|
-
if (arg === "--intent" || arg === "-i") {
|
|
237
|
-
if (i + 1 < subArgs.length)
|
|
238
|
-
intent = subArgs[++i];
|
|
239
|
-
}
|
|
240
|
-
else if (arg.startsWith("--intent=")) {
|
|
241
|
-
intent = arg.slice(9);
|
|
242
|
-
}
|
|
243
|
-
else if (arg.startsWith("-i=")) {
|
|
244
|
-
intent = arg.slice(3);
|
|
245
|
-
}
|
|
246
|
-
else if (!arg.startsWith("-")) {
|
|
247
|
-
positionalPatterns.push(arg);
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
const effectiveIntent = intent || (positionalPatterns.length > 0 ? positionalPatterns.join("|") : undefined);
|
|
251
|
-
const actions = await service.discovery.listActions();
|
|
252
|
-
const list = actions.map((a) => ({
|
|
253
|
-
id: a.id,
|
|
254
|
-
description: a.description || "",
|
|
255
|
-
}));
|
|
256
|
-
const filterRes = filterWithFallbackInfo(list, effectiveIntent, [(a) => a.id, (a) => a.description], !noFallback);
|
|
257
|
-
const hints = [
|
|
258
|
-
"Tip: For composite or multi-step tasks, check 'ad playbook list' for standard operating procedures.",
|
|
259
|
-
];
|
|
260
|
-
if (isJson) {
|
|
261
|
-
this.writeOut(JSON.stringify({ items: filterRes.items, hints }, null, 2));
|
|
262
|
-
}
|
|
263
|
-
else {
|
|
264
|
-
let text = `Actions in ${this.options.packageId} (v${this.options.version}):\n\n`;
|
|
265
|
-
for (const a of filterRes.items) {
|
|
266
|
-
text += ` ${a.id.padEnd(28)} ${a.description}\n`;
|
|
267
|
-
}
|
|
268
|
-
this.writeOut(text.trimEnd());
|
|
269
|
-
}
|
|
270
|
-
return ExitCode.SUCCESS;
|
|
271
|
-
}
|
|
272
|
-
async handleDescribe(service, subArgs) {
|
|
273
|
-
const id = subArgs.find((a) => !a.startsWith("-"));
|
|
274
|
-
const isJson = subArgs.includes("--json");
|
|
275
|
-
if (!id) {
|
|
276
|
-
return this.emitError(isJson, "INVALID_ARGUMENT", "Action ID is required for describe", ExitCode.INVALID_ARGUMENT);
|
|
277
|
-
}
|
|
278
|
-
let action;
|
|
279
|
-
try {
|
|
280
|
-
action = await service.discovery.describeAction(id);
|
|
281
|
-
}
|
|
282
|
-
catch {
|
|
283
|
-
const hint = "Tip: Run 'ad list' to discover available actions.";
|
|
284
|
-
return this.emitError(isJson, "INVALID_ARGUMENT", `Action '${id}' not found`, ExitCode.INVALID_ARGUMENT, {
|
|
285
|
-
textMessage: `Error: Action '${id}' not found\n${hint}`,
|
|
286
|
-
hint,
|
|
287
|
-
});
|
|
288
|
-
}
|
|
289
|
-
const payload = buildActionDescribePayload(action, {
|
|
290
|
-
packageId: this.options.packageId,
|
|
291
|
-
});
|
|
292
|
-
if (isJson) {
|
|
293
|
-
this.writeOut(JSON.stringify(payload, null, 2));
|
|
294
|
-
}
|
|
295
|
-
else {
|
|
296
|
-
this.writeOut(formatActionDetail(payload));
|
|
297
|
-
}
|
|
298
|
-
return ExitCode.SUCCESS;
|
|
299
|
-
}
|
|
300
|
-
async handleRun(service, subArgs, actionArgs, signal) {
|
|
301
|
-
const isJson = subArgs.includes("--json");
|
|
302
|
-
const id = subArgs.find((a) => !a.startsWith("-"));
|
|
303
|
-
if (!id) {
|
|
304
|
-
return this.emitError(isJson, "INVALID_ARGUMENT", "Error: Action ID is required for run", ExitCode.INVALID_ARGUMENT, { textMessage: "Error: Action ID is required for run" });
|
|
305
|
-
}
|
|
306
|
-
let inputStr;
|
|
307
|
-
let inputFile;
|
|
308
|
-
let timeoutMs;
|
|
309
|
-
const recognizedFlags = new Set(["--json", "--async"]);
|
|
310
|
-
for (let i = 0; i < subArgs.length; i++) {
|
|
311
|
-
const arg = subArgs[i];
|
|
312
|
-
if (arg === id || recognizedFlags.has(arg)) {
|
|
313
|
-
continue;
|
|
314
|
-
}
|
|
315
|
-
if (arg === "--timeout" && i + 1 < subArgs.length) {
|
|
316
|
-
try {
|
|
317
|
-
timeoutMs = parseDuration(subArgs[++i]);
|
|
318
|
-
}
|
|
319
|
-
catch (err) {
|
|
320
|
-
return this.emitError(isJson, "INVALID_ARGUMENT", `Invalid timeout format: ${err?.message || err}`, ExitCode.INVALID_ARGUMENT);
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
else if (arg.startsWith("--timeout=")) {
|
|
324
|
-
try {
|
|
325
|
-
timeoutMs = parseDuration(arg.slice(10));
|
|
326
|
-
}
|
|
327
|
-
catch (err) {
|
|
328
|
-
return this.emitError(isJson, "INVALID_ARGUMENT", `Invalid timeout format: ${err?.message || err}`, ExitCode.INVALID_ARGUMENT);
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
else if (arg === "--input" && i + 1 < subArgs.length) {
|
|
332
|
-
inputStr = subArgs[++i];
|
|
333
|
-
}
|
|
334
|
-
else if (arg.startsWith("--input=")) {
|
|
335
|
-
inputStr = arg.slice(8);
|
|
336
|
-
}
|
|
337
|
-
else if (arg === "-i" && i + 1 < subArgs.length) {
|
|
338
|
-
inputStr = subArgs[++i];
|
|
339
|
-
}
|
|
340
|
-
else if (arg.startsWith("-i=")) {
|
|
341
|
-
inputStr = arg.slice(3);
|
|
342
|
-
}
|
|
343
|
-
else if (arg === "--input-file" && i + 1 < subArgs.length) {
|
|
344
|
-
inputFile = subArgs[++i];
|
|
345
|
-
}
|
|
346
|
-
else if (arg.startsWith("--input-file=")) {
|
|
347
|
-
inputFile = arg.slice(13);
|
|
348
|
-
}
|
|
349
|
-
else if (arg === "-f" && i + 1 < subArgs.length) {
|
|
350
|
-
inputFile = subArgs[++i];
|
|
351
|
-
}
|
|
352
|
-
else if (arg.startsWith("-f=")) {
|
|
353
|
-
inputFile = arg.slice(3);
|
|
354
|
-
}
|
|
355
|
-
else if (arg.startsWith("-")) {
|
|
356
|
-
const hint = "Hint: Separate action inputs from CLI options using '--', e.g.: ad run <id> [options] -- <param>=<val> or <param>:=<json>.";
|
|
357
|
-
return this.emitError(isJson, "INVALID_ARGUMENT", `error: unknown option '${arg}'`, ExitCode.INVALID_ARGUMENT, {
|
|
358
|
-
textMessage: `error: unknown option '${arg}'\n${hint}`,
|
|
359
|
-
hint,
|
|
360
|
-
});
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
let input;
|
|
364
|
-
try {
|
|
365
|
-
input = await resolveActionInput({
|
|
366
|
-
input: inputStr,
|
|
367
|
-
inputFile,
|
|
368
|
-
flatArgs: actionArgs.length > 0 ? actionArgs : undefined,
|
|
369
|
-
stdin: process.stdin,
|
|
370
|
-
});
|
|
371
|
-
const check = validateActionInputValue(input);
|
|
372
|
-
if (!check.valid) {
|
|
373
|
-
throw mapInputValidationFailure("cli-pre-target", check);
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
catch (err) {
|
|
377
|
-
return this.emitError(isJson, err?.code || "INVALID_ARGUMENT", err?.message || String(err), ExitCode.INVALID_ARGUMENT, {
|
|
378
|
-
details: err?.details,
|
|
379
|
-
});
|
|
380
|
-
}
|
|
381
|
-
const result = await service.execution.run(id, input, {
|
|
382
|
-
signal,
|
|
383
|
-
timeoutMs,
|
|
384
|
-
});
|
|
385
|
-
if (isJson) {
|
|
386
|
-
if (!result.ok) {
|
|
387
|
-
const hint = resolveExecutionHint(id, result.error);
|
|
388
|
-
const machineOutput = hint !== undefined ? { ...result, hint } : result;
|
|
389
|
-
this.writeOut(JSON.stringify(machineOutput, null, 2));
|
|
390
|
-
}
|
|
391
|
-
else {
|
|
392
|
-
this.writeOut(JSON.stringify(result, null, 2));
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
else {
|
|
396
|
-
if (result.ok) {
|
|
397
|
-
const data = result.data;
|
|
398
|
-
let rawText;
|
|
399
|
-
let metaInfo;
|
|
400
|
-
if (typeof data === "string") {
|
|
401
|
-
rawText = data;
|
|
402
|
-
}
|
|
403
|
-
else if (data !== null && typeof data === "object") {
|
|
404
|
-
if ("content" in data && data.content !== undefined) {
|
|
405
|
-
rawText =
|
|
406
|
-
typeof data.content === "object" && data.content !== null
|
|
407
|
-
? JSON.stringify(data.content, null, 2)
|
|
408
|
-
: String(data.content);
|
|
409
|
-
const { content, ...rest } = data;
|
|
410
|
-
if (Object.keys(rest).length > 0) {
|
|
411
|
-
metaInfo = rest;
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
else if ("text" in data && typeof data.text === "string") {
|
|
415
|
-
rawText = data.text;
|
|
416
|
-
const { text, ...rest } = data;
|
|
417
|
-
if (Object.keys(rest).length > 0) {
|
|
418
|
-
metaInfo = rest;
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
else if ("message" in data && typeof data.message === "string") {
|
|
422
|
-
rawText = data.message;
|
|
423
|
-
const { message, ...rest } = data;
|
|
424
|
-
if (Object.keys(rest).length > 0) {
|
|
425
|
-
metaInfo = rest;
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
else {
|
|
429
|
-
rawText = JSON.stringify(data, null, 2);
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
else if (data !== undefined) {
|
|
433
|
-
rawText = String(data);
|
|
434
|
-
}
|
|
435
|
-
else {
|
|
436
|
-
rawText = "";
|
|
437
|
-
}
|
|
438
|
-
if (metaInfo) {
|
|
439
|
-
const parts = [];
|
|
440
|
-
const title = metaInfo.path ? String(metaInfo.path) : id;
|
|
441
|
-
parts.push(title);
|
|
442
|
-
if (metaInfo.startLine !== undefined && metaInfo.endLine !== undefined) {
|
|
443
|
-
parts.push(`lines ${metaInfo.startLine}-${metaInfo.endLine}`);
|
|
444
|
-
}
|
|
445
|
-
else if (metaInfo.line !== undefined) {
|
|
446
|
-
parts.push(`line ${metaInfo.line}`);
|
|
447
|
-
}
|
|
448
|
-
if (metaInfo.hasMore !== undefined) {
|
|
449
|
-
parts.push(`hasMore: ${metaInfo.hasMore}`);
|
|
450
|
-
}
|
|
451
|
-
if (metaInfo.truncated) {
|
|
452
|
-
parts.push("truncated: true");
|
|
453
|
-
}
|
|
454
|
-
const handled = new Set(["path", "startLine", "endLine", "line", "hasMore", "truncated"]);
|
|
455
|
-
for (const [k, v] of Object.entries(metaInfo)) {
|
|
456
|
-
if (!handled.has(k) && v !== undefined) {
|
|
457
|
-
parts.push(`${k}: ${typeof v === "object" ? JSON.stringify(v) : v}`);
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
if (parts.length > 0) {
|
|
461
|
-
this.writeErr(`[${parts.join(" | ")}]`);
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
this.writeOut(rawText);
|
|
465
|
-
}
|
|
466
|
-
else {
|
|
467
|
-
this.writeErr(`Error [${result.error.code}]: ${result.error.message}`);
|
|
468
|
-
if (result.error.details) {
|
|
469
|
-
this.writeErr(typeof result.error.details === "string"
|
|
470
|
-
? result.error.details
|
|
471
|
-
: JSON.stringify(result.error.details, null, 2));
|
|
472
|
-
}
|
|
473
|
-
const hint = resolveExecutionHint(id, result.error);
|
|
474
|
-
if (hint) {
|
|
475
|
-
this.writeErr(hint);
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
return result.ok ? ExitCode.SUCCESS : ExitCode.FAILURE;
|
|
480
|
-
}
|
|
481
|
-
async handleConfig(service, subArgs) {
|
|
482
|
-
const sub = subArgs[0] || "list";
|
|
483
|
-
if (!service.management) {
|
|
484
|
-
this.writeErr("Error: management port is not enabled on this service");
|
|
485
|
-
return ExitCode.FAILURE;
|
|
486
|
-
}
|
|
487
|
-
if (sub === "list") {
|
|
488
|
-
const views = await service.management.config.list(this.options.packageId);
|
|
489
|
-
const dict = {};
|
|
490
|
-
for (const v of views) {
|
|
491
|
-
if (v.configured && v.value !== undefined) {
|
|
492
|
-
dict[v.key] = v.value;
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
this.writeOut(JSON.stringify(dict, null, 2));
|
|
496
|
-
return ExitCode.SUCCESS;
|
|
497
|
-
}
|
|
498
|
-
if (sub === "get") {
|
|
499
|
-
const key = subArgs[1];
|
|
500
|
-
if (!key) {
|
|
501
|
-
this.writeErr("Error: config key required");
|
|
502
|
-
return ExitCode.INVALID_ARGUMENT;
|
|
503
|
-
}
|
|
504
|
-
try {
|
|
505
|
-
const item = await service.management.config.get(this.options.packageId, key);
|
|
506
|
-
this.writeOut(item.configured ? JSON.stringify(item.value) : "undefined");
|
|
507
|
-
return ExitCode.SUCCESS;
|
|
508
|
-
}
|
|
509
|
-
catch (err) {
|
|
510
|
-
// 服务能力缺失(如远端未开启管理接口)视为键未配置,输出 undefined
|
|
511
|
-
if (this.isServiceCapabilityError(err)) {
|
|
512
|
-
this.writeOut("undefined");
|
|
513
|
-
return ExitCode.SUCCESS;
|
|
514
|
-
}
|
|
515
|
-
// 内部异常严禁吞没:透传 stderr 并以 FAILURE 退出码暴露
|
|
516
|
-
this.writeErr(`Error reading config '${key}': ${err?.message || String(err)}`);
|
|
517
|
-
return ExitCode.FAILURE;
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
if (sub === "set") {
|
|
521
|
-
const key = subArgs[1];
|
|
522
|
-
const rawVal = subArgs[2];
|
|
523
|
-
if (!key || rawVal === undefined) {
|
|
524
|
-
this.writeErr("Error: key and value required");
|
|
525
|
-
return ExitCode.INVALID_ARGUMENT;
|
|
526
|
-
}
|
|
527
|
-
let parsed = rawVal;
|
|
528
|
-
try {
|
|
529
|
-
parsed = JSON.parse(rawVal);
|
|
530
|
-
}
|
|
531
|
-
catch {
|
|
532
|
-
parsed = rawVal;
|
|
533
|
-
}
|
|
534
|
-
await service.management.config.set(this.options.packageId, key, parsed);
|
|
535
|
-
this.writeOut(`Config '${key}' updated`);
|
|
536
|
-
return ExitCode.SUCCESS;
|
|
537
|
-
}
|
|
538
|
-
if (sub === "delete") {
|
|
539
|
-
const key = subArgs[1];
|
|
540
|
-
if (!key) {
|
|
541
|
-
this.writeErr("Error: config key required");
|
|
542
|
-
return ExitCode.INVALID_ARGUMENT;
|
|
543
|
-
}
|
|
544
|
-
await service.management.config.delete(this.options.packageId, key);
|
|
545
|
-
this.writeOut(`Config '${key}' deleted`);
|
|
546
|
-
return ExitCode.SUCCESS;
|
|
547
|
-
}
|
|
548
|
-
this.writeErr(`Unknown config subcommand: '${sub}'`);
|
|
549
|
-
return ExitCode.INVALID_ARGUMENT;
|
|
550
|
-
}
|
|
551
|
-
async handleState(service, subArgs) {
|
|
552
|
-
const sub = subArgs[0] || "list";
|
|
553
|
-
let namespace;
|
|
554
|
-
let isAll = false;
|
|
555
|
-
let isJson = false;
|
|
556
|
-
if (!service.management) {
|
|
557
|
-
this.writeErr("Error: management port is not enabled on this service");
|
|
558
|
-
return ExitCode.FAILURE;
|
|
559
|
-
}
|
|
560
|
-
for (let i = 1; i < subArgs.length; i++) {
|
|
561
|
-
if ((subArgs[i] === "-n" || subArgs[i] === "--namespace") && i + 1 < subArgs.length) {
|
|
562
|
-
namespace = subArgs[++i];
|
|
563
|
-
}
|
|
564
|
-
else if (subArgs[i].startsWith("--namespace=")) {
|
|
565
|
-
namespace = subArgs[i].slice(12);
|
|
566
|
-
}
|
|
567
|
-
else if (subArgs[i] === "-a" || subArgs[i] === "--all") {
|
|
568
|
-
isAll = true;
|
|
569
|
-
}
|
|
570
|
-
else if (subArgs[i] === "--json") {
|
|
571
|
-
isJson = true;
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
if (sub === "list") {
|
|
575
|
-
const prefix = subArgs[1] && !subArgs[1].startsWith("-") ? subArgs[1] : "";
|
|
576
|
-
const keys = await service.management.state.list(this.options.packageId, "", {
|
|
577
|
-
namespace,
|
|
578
|
-
prefix: prefix || undefined,
|
|
579
|
-
all: isAll,
|
|
580
|
-
});
|
|
581
|
-
this.writeOut(JSON.stringify(keys, null, 2));
|
|
582
|
-
return ExitCode.SUCCESS;
|
|
583
|
-
}
|
|
584
|
-
if (sub === "get") {
|
|
585
|
-
const key = subArgs[1] && !subArgs[1].startsWith("-") ? subArgs[1] : subArgs[2];
|
|
586
|
-
if (!key) {
|
|
587
|
-
this.writeErr("Error: state key required");
|
|
588
|
-
return ExitCode.INVALID_ARGUMENT;
|
|
589
|
-
}
|
|
590
|
-
let ns = namespace;
|
|
591
|
-
let actualKey = key;
|
|
592
|
-
if (ns === undefined) {
|
|
593
|
-
const decoded = this.decodeStateKeyArg(key);
|
|
594
|
-
ns = decoded.namespace || undefined;
|
|
595
|
-
actualKey = decoded.key;
|
|
596
|
-
}
|
|
597
|
-
const val = await service.management.state.get(this.options.packageId, "", actualKey, { namespace: ns });
|
|
598
|
-
if (isJson) {
|
|
599
|
-
this.writeOut(JSON.stringify({ key, value: val }, null, 2));
|
|
600
|
-
}
|
|
601
|
-
else {
|
|
602
|
-
this.writeOut(val !== undefined ? JSON.stringify(val) : "undefined");
|
|
603
|
-
}
|
|
604
|
-
return ExitCode.SUCCESS;
|
|
605
|
-
}
|
|
606
|
-
if (sub === "set") {
|
|
607
|
-
const key = subArgs[1];
|
|
608
|
-
const rawVal = subArgs[2];
|
|
609
|
-
if (!key || rawVal === undefined) {
|
|
610
|
-
this.writeErr("Error: key and value required");
|
|
611
|
-
return ExitCode.INVALID_ARGUMENT;
|
|
612
|
-
}
|
|
613
|
-
let ns = namespace || "";
|
|
614
|
-
let actualKey = key;
|
|
615
|
-
if (namespace === undefined) {
|
|
616
|
-
const decoded = this.decodeStateKeyArg(key);
|
|
617
|
-
ns = decoded.namespace;
|
|
618
|
-
actualKey = decoded.key;
|
|
619
|
-
}
|
|
620
|
-
let parsed = rawVal;
|
|
621
|
-
try {
|
|
622
|
-
parsed = JSON.parse(rawVal);
|
|
623
|
-
}
|
|
624
|
-
catch {
|
|
625
|
-
parsed = rawVal;
|
|
626
|
-
}
|
|
627
|
-
let ttl;
|
|
628
|
-
for (let i = 3; i < subArgs.length; i++) {
|
|
629
|
-
if (subArgs[i] === "--ttl" && i + 1 < subArgs.length) {
|
|
630
|
-
ttl = parseInt(subArgs[++i], 10);
|
|
631
|
-
}
|
|
632
|
-
else if (subArgs[i].startsWith("--ttl=")) {
|
|
633
|
-
ttl = parseInt(subArgs[i].slice(6), 10);
|
|
634
|
-
}
|
|
635
|
-
}
|
|
636
|
-
await service.management.state.set(this.options.packageId, "", actualKey, parsed, { namespace: ns, ttl });
|
|
637
|
-
const displayKey = ns ? `${ns}:${actualKey}` : actualKey;
|
|
638
|
-
this.writeOut(`State '${displayKey}' updated`);
|
|
639
|
-
return ExitCode.SUCCESS;
|
|
640
|
-
}
|
|
641
|
-
if (sub === "delete" || sub === "rm") {
|
|
642
|
-
const key = subArgs[1] && !subArgs[1].startsWith("-") ? subArgs[1] : subArgs[2];
|
|
643
|
-
if (!key) {
|
|
644
|
-
this.writeErr("Error: state key required");
|
|
645
|
-
return ExitCode.INVALID_ARGUMENT;
|
|
646
|
-
}
|
|
647
|
-
const deleted = await service.management.state.delete(this.options.packageId, "", key, { namespace });
|
|
648
|
-
if (deleted) {
|
|
649
|
-
this.writeOut(`State '${key}' deleted`);
|
|
650
|
-
return ExitCode.SUCCESS;
|
|
651
|
-
}
|
|
652
|
-
this.writeErr(`Error: State key '${key}' not found`);
|
|
653
|
-
return ExitCode.FAILURE;
|
|
654
|
-
}
|
|
655
|
-
if (sub === "clear" || sub === "clean") {
|
|
656
|
-
const prefix = subArgs[1] && !subArgs[1].startsWith("-") ? subArgs[1] : "";
|
|
657
|
-
const count = await service.management.state.clear(this.options.packageId, "", {
|
|
658
|
-
namespace,
|
|
659
|
-
all: isAll,
|
|
660
|
-
prefix: prefix || undefined,
|
|
661
|
-
});
|
|
662
|
-
this.writeOut(`Cleared ${count} state entry(s)`);
|
|
663
|
-
return ExitCode.SUCCESS;
|
|
664
|
-
}
|
|
665
|
-
this.writeErr(`Unknown state subcommand: '${sub}'`);
|
|
666
|
-
return ExitCode.INVALID_ARGUMENT;
|
|
667
|
-
}
|
|
668
|
-
/**
|
|
669
|
-
* 判定配置读取异常是否为服务能力缺失(键未配置语义)而非内部故障。
|
|
670
|
-
*/
|
|
671
|
-
isServiceCapabilityError(err) {
|
|
672
|
-
const code = String(err?.code || "");
|
|
673
|
-
return (code === "CAPABILITY_UNAVAILABLE" ||
|
|
674
|
-
code === "TARGET_CAPABILITY_UNAVAILABLE");
|
|
675
|
-
}
|
|
676
|
-
/**
|
|
677
|
-
* 解析携带命名空间前缀的状态键参数:委托 sdk 单一事实源 decodeStateKey。
|
|
678
|
-
*
|
|
679
|
-
* 解析失败(如存在多个未转义冒号的歧义键)时按纯键处理,交由存储层兜底。
|
|
680
|
-
*/
|
|
681
|
-
decodeStateKeyArg(key) {
|
|
682
|
-
try {
|
|
683
|
-
return decodeStateKey(key);
|
|
684
|
-
}
|
|
685
|
-
catch {
|
|
686
|
-
return { namespace: "", key };
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
|
-
printHelp() {
|
|
690
|
-
this.writeOut(`${this.options.packageId} (v${this.options.version})`);
|
|
691
|
-
if (this.options.description)
|
|
692
|
-
this.writeOut(`${this.options.description}\n`);
|
|
693
|
-
this.writeOut("Usage:");
|
|
694
|
-
this.writeOut(" <cmd> list [--json] List available actions");
|
|
695
|
-
this.writeOut(" <cmd> describe <id> [--json] Show action details and schemas");
|
|
696
|
-
this.writeOut(" <cmd> run <id> [--input '<json>'] Execute action (raw text output by default)");
|
|
697
|
-
this.writeOut(" <cmd> run <id> [--json] Output standard execution result in JSON format");
|
|
698
|
-
this.writeOut(" <cmd> config list/get/set/delete Manage package configuration");
|
|
699
|
-
this.writeOut(" <cmd> state list/get/set/delete Manage shared state store");
|
|
700
|
-
this.writeOut("\nGlobal options:");
|
|
701
|
-
this.writeOut(" --data-dir <path> Custom runtime database directory");
|
|
702
|
-
this.writeOut(" --config <KEY=val> Temporary config override");
|
|
703
|
-
}
|
|
704
|
-
}
|
|
705
|
-
export class StandaloneRuntime {
|
|
706
|
-
dispatcher;
|
|
707
|
-
constructor(options) {
|
|
708
|
-
this.dispatcher = new StandaloneDispatcher(options);
|
|
709
|
-
}
|
|
710
|
-
async run(argv) {
|
|
711
|
-
const code = await this.dispatcher.dispatch(argv);
|
|
712
|
-
if (code !== ExitCode.SUCCESS && code !== ExitCode.FAILURE) {
|
|
713
|
-
process.exit(code);
|
|
714
|
-
}
|
|
715
|
-
}
|
|
716
|
-
}
|
|
717
|
-
/**
|
|
718
|
-
* 工厂函数:创建独立运行时实例。
|
|
719
|
-
*/
|
|
720
|
-
export function createStandaloneRuntime(options) {
|
|
721
|
-
return new StandaloneRuntime(options);
|
|
722
181
|
}
|
|
723
182
|
/**
|
|
724
183
|
* 独立二进制进程入口适配器。
|
|
@@ -10,9 +10,9 @@ export interface ValidationResult {
|
|
|
10
10
|
}
|
|
11
11
|
/**
|
|
12
12
|
* 递归检查数据中是否包含危险的原型污染属性键名(__proto__、constructor、prototype)。
|
|
13
|
-
* 内部委托 validateActionInputValue 执行迭代遍历,确保环路安全、有向无环图安全且无调用栈溢出风险。
|
|
14
13
|
*/
|
|
15
|
-
|
|
14
|
+
import { hasDangerousKeys } from "../value-validator.js";
|
|
15
|
+
export { hasDangerousKeys };
|
|
16
16
|
/**
|
|
17
17
|
* 内部纯 Schema 校验器。
|
|
18
18
|
* 仅处理布尔 Schema 与 Ajv 规则校验,严禁执行 dangerous-key 遍历。
|