@actiondock/core 2.7.0 → 2.9.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 +77 -64
- package/dist/catalog/action-catalog.d.ts +56 -0
- package/dist/catalog/action-catalog.js +202 -0
- package/dist/catalog/discovery.d.ts +60 -0
- package/dist/catalog/discovery.js +119 -0
- package/dist/catalog/graph.d.ts +190 -0
- package/dist/catalog/graph.js +589 -0
- package/dist/catalog/index.d.ts +5 -5
- package/dist/catalog/index.js +5 -5
- package/dist/catalog/resolve-action.d.ts +43 -0
- package/dist/catalog/resolve-action.js +119 -0
- package/dist/catalog/resolve-playbook.d.ts +26 -0
- package/dist/catalog/resolve-playbook.js +114 -0
- package/dist/doctor/checks/project.js +27 -8
- package/dist/doctor/checks/registry.js +2 -2
- package/dist/doctor/checks/runtime.js +34 -1
- package/dist/errors.d.ts +106 -10
- package/dist/errors.js +105 -10
- package/dist/execution/service.d.ts +18 -16
- package/dist/execution/service.js +183 -252
- package/dist/execution/types.d.ts +25 -69
- package/dist/execution/types.js +2 -1
- package/dist/filter/intent.d.ts +8 -9
- package/dist/filter/intent.js +49 -10
- package/dist/graph/index.d.ts +4 -0
- package/dist/graph/index.js +4 -0
- package/dist/host/host.d.ts +74 -32
- package/dist/host/host.js +585 -336
- package/dist/host/routing.d.ts +15 -48
- package/dist/host/routing.js +90 -153
- package/dist/host/types.d.ts +50 -17
- package/dist/index.d.ts +21 -24
- package/dist/index.js +19 -23
- package/dist/input/advice.d.ts +5 -1
- package/dist/input/advice.js +163 -214
- package/dist/input/describe.d.ts +1 -1
- package/dist/input/flat-errors.d.ts +5 -6
- package/dist/input/flat-errors.js +6 -6
- package/dist/input/flat-materializer.js +42 -44
- package/dist/invocation/index.d.ts +2 -0
- package/dist/invocation/index.js +2 -0
- package/dist/invocation/policy.d.ts +157 -0
- package/dist/invocation/policy.js +231 -0
- package/dist/invocation/types.d.ts +172 -0
- package/dist/invocation/types.js +97 -0
- package/dist/ipc/diagnostic.d.ts +0 -12
- package/dist/ipc/diagnostic.js +0 -21
- package/dist/ipc/host.d.ts +4 -4
- package/dist/ipc/host.js +44 -47
- package/dist/ipc/index.d.ts +1 -1
- package/dist/ipc/index.js +1 -1
- package/dist/ipc/service.d.ts +40 -0
- package/dist/ipc/service.js +349 -0
- package/dist/ipc/types.d.ts +21 -15
- package/dist/node/index.d.ts +1 -0
- package/dist/node/index.js +1 -0
- package/dist/node/module-loader.d.ts +63 -0
- package/dist/node/module-loader.js +112 -0
- package/dist/package/index.d.ts +23 -0
- package/dist/package/index.js +18 -0
- package/dist/{app/app.d.ts → package/runtime.d.ts} +41 -20
- package/dist/{app/app.js → package/runtime.js} +140 -95
- package/dist/{app → package}/static-index.js +58 -41
- package/dist/package/storage-view.d.ts +13 -0
- package/dist/package/storage-view.js +22 -0
- package/dist/{app → package}/types.d.ts +76 -57
- package/dist/package/types.js +22 -0
- package/dist/platform/index.d.ts +1 -1
- package/dist/platform/index.js +1 -1
- package/dist/platform/node.d.ts +48 -0
- package/dist/platform/node.js +96 -0
- package/dist/platform/types.d.ts +0 -9
- package/dist/process/control-arbiter.d.ts +2 -1
- package/dist/process/control-arbiter.js +1 -2
- package/dist/process/driver.d.ts +9 -8
- package/dist/process/driver.js +11 -22
- package/dist/process/index.d.ts +2 -0
- package/dist/process/index.js +2 -0
- package/dist/process/managed-record.d.ts +2 -2
- package/dist/process/process-driver.d.ts +109 -0
- package/dist/process/process-driver.js +650 -0
- package/dist/process/process-executor.d.ts +47 -0
- package/dist/process/process-executor.js +296 -0
- package/dist/process/process-manager.js +48 -26
- package/dist/process/run-executor.js +12 -12
- package/dist/profile/client-actions.js +2 -2
- package/dist/profile/client-health.js +2 -2
- package/dist/profile/client-query.js +5 -6
- package/dist/profile/client-transport.d.ts +19 -17
- package/dist/profile/client-transport.js +47 -80
- package/dist/profile/client.d.ts +2 -2
- package/dist/profile/client.js +1 -1
- package/dist/profile/index.d.ts +1 -0
- package/dist/profile/index.js +1 -0
- package/dist/profile/manager.d.ts +5 -0
- package/dist/profile/manager.js +41 -6
- package/dist/project/closure.js +2 -2
- package/dist/project/index.d.ts +8 -1
- package/dist/project/index.js +10 -1
- package/dist/project/init.js +2 -2
- package/dist/project/loader.d.ts +1 -1
- package/dist/project/loader.js +26 -29
- package/dist/project/transactions.js +5 -10
- package/dist/project/types.d.ts +5 -0
- package/dist/registry/index.d.ts +3 -1
- package/dist/registry/index.js +2 -1
- package/dist/registry/lock.d.ts +28 -7
- package/dist/registry/lock.js +136 -16
- package/dist/registry/registry.d.ts +1 -5
- package/dist/registry/registry.js +1 -53
- package/dist/registry/scan.d.ts +0 -15
- package/dist/registry/scan.js +0 -59
- package/dist/registry/store.d.ts +42 -0
- package/dist/registry/store.js +43 -0
- package/dist/registry/types.d.ts +0 -24
- package/dist/runtime/action-collection.d.ts +1 -1
- package/dist/runtime/action-registry.d.ts +0 -4
- package/dist/runtime/action-registry.js +0 -7
- package/dist/runtime/context.js +5 -11
- package/dist/runtime/events.js +3 -6
- package/dist/runtime/identity.d.ts +22 -0
- package/dist/runtime/identity.js +10 -0
- package/dist/runtime/index.d.ts +1 -2
- package/dist/runtime/index.js +1 -2
- package/dist/runtime/module-loader.d.ts +2 -34
- package/dist/runtime/module-loader.js +1 -16
- package/dist/runtime/process.d.ts +6 -24
- package/dist/runtime/process.js +1 -118
- package/dist/runtime/run-persistence.js +2 -5
- package/dist/runtime/runner.d.ts +33 -93
- package/dist/runtime/runner.js +132 -364
- package/dist/runtime/standalone.d.ts +23 -8
- package/dist/runtime/standalone.js +100 -147
- package/dist/server/body.d.ts +16 -8
- package/dist/server/body.js +33 -16
- package/dist/server/dispatcher.d.ts +6 -10
- package/dist/server/dispatcher.js +24 -32
- package/dist/server/http-server.d.ts +87 -0
- package/dist/server/http-server.js +304 -0
- package/dist/server/index.d.ts +12 -0
- package/dist/server/index.js +11 -0
- package/dist/server/mcp-endpoint.d.ts +61 -0
- package/dist/server/mcp-endpoint.js +118 -0
- package/dist/server/policy.d.ts +138 -0
- package/dist/server/policy.js +368 -0
- package/dist/server/routes/actions.js +114 -64
- package/dist/server/routes/common.d.ts +18 -33
- package/dist/server/routes/common.js +45 -65
- package/dist/server/routes/config.d.ts +1 -1
- package/dist/server/routes/config.js +55 -65
- package/dist/server/routes/doctor.d.ts +1 -1
- package/dist/server/routes/doctor.js +13 -21
- package/dist/server/routes/health.d.ts +1 -1
- package/dist/server/routes/health.js +4 -5
- package/dist/server/routes/info.d.ts +2 -2
- package/dist/server/routes/info.js +17 -24
- package/dist/server/routes/playbooks.js +23 -36
- package/dist/server/routes/runs.js +151 -141
- package/dist/server/routes/state.d.ts +1 -1
- package/dist/server/routes/state.js +64 -63
- package/dist/server/security.d.ts +11 -0
- package/dist/server/security.js +36 -19
- package/dist/server/server.d.ts +2 -2
- package/dist/server/server.js +224 -238
- package/dist/server/types.d.ts +68 -21
- package/dist/service/factory.d.ts +12 -0
- package/dist/service/factory.js +85 -0
- package/dist/{target → service}/index.d.ts +1 -1
- package/dist/{target → service}/index.js +1 -1
- package/dist/service/local.d.ts +27 -0
- package/dist/service/local.js +138 -0
- package/dist/{target → service}/remote-errors.d.ts +3 -6
- package/dist/service/remote-errors.js +38 -0
- package/dist/{target → service}/remote-polling.d.ts +2 -2
- package/dist/{target → service}/remote-polling.js +8 -8
- package/dist/service/remote.d.ts +34 -0
- package/dist/service/remote.js +634 -0
- package/dist/service/sse-stream.d.ts +24 -0
- package/dist/service/sse-stream.js +139 -0
- package/dist/service/types.d.ts +272 -0
- package/dist/service/types.js +32 -0
- package/dist/storage/data-dir-lock.js +10 -5
- package/dist/storage/driver.d.ts +2 -1
- package/dist/storage/driver.js +3 -52
- package/dist/storage/index.d.ts +1 -0
- package/dist/storage/index.js +1 -0
- package/dist/storage/lock-core.d.ts +2 -6
- package/dist/storage/lock-core.js +4 -17
- package/dist/storage/params.d.ts +2 -8
- package/dist/storage/params.js +2 -8
- package/dist/storage/sqlite-driver.d.ts +40 -0
- package/dist/storage/sqlite-driver.js +116 -0
- package/dist/storage/sqlite.js +21 -6
- package/dist/storage/types.d.ts +4 -4
- package/dist/storage/types.js +2 -2
- package/dist/utils/index.d.ts +53 -0
- package/dist/utils/index.js +99 -4
- package/dist/utils/process.d.ts +10 -0
- package/dist/utils/process.js +21 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +41 -3
- package/dist/app/index.d.ts +0 -2
- package/dist/app/index.js +0 -2
- package/dist/app/types.js +0 -1
- package/dist/catalog/action-index.d.ts +0 -9
- package/dist/catalog/action-index.js +0 -95
- package/dist/catalog/action-resolver.d.ts +0 -20
- package/dist/catalog/action-resolver.js +0 -95
- package/dist/catalog/location-registry.d.ts +0 -15
- package/dist/catalog/location-registry.js +0 -138
- package/dist/catalog/package-catalog.d.ts +0 -7
- package/dist/catalog/package-catalog.js +0 -77
- package/dist/catalog/types.d.ts +0 -68
- package/dist/catalog/types.js +0 -1
- package/dist/export/index.d.ts +0 -1
- package/dist/export/index.js +0 -1
- package/dist/export/templates.d.ts +0 -71
- package/dist/export/templates.js +0 -635
- package/dist/ipc/target.d.ts +0 -74
- package/dist/ipc/target.js +0 -365
- package/dist/platform/default.d.ts +0 -38
- package/dist/platform/default.js +0 -78
- package/dist/project/resolver.d.ts +0 -116
- package/dist/project/resolver.js +0 -376
- package/dist/registry/resolve.d.ts +0 -62
- package/dist/registry/resolve.js +0 -195
- package/dist/runtime/execution-manager.d.ts +0 -48
- package/dist/runtime/execution-manager.js +0 -66
- package/dist/runtime/package-runner-factory.d.ts +0 -82
- package/dist/runtime/package-runner-factory.js +0 -186
- package/dist/target/local.d.ts +0 -53
- package/dist/target/local.js +0 -349
- package/dist/target/remote-errors.js +0 -51
- package/dist/target/remote.d.ts +0 -86
- package/dist/target/remote.js +0 -818
- package/dist/target/target.d.ts +0 -6
- package/dist/target/target.js +0 -37
- package/dist/target/types.d.ts +0 -261
- package/dist/target/types.js +0 -35
- /package/dist/{app → package}/static-index.d.ts +0 -0
- /package/dist/{target → service}/sse-parser.d.ts +0 -0
- /package/dist/{target → service}/sse-parser.js +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type ActionDefinition } from "@actiondock/sdk";
|
|
2
|
-
import type { ActionSpec } from "../
|
|
2
|
+
import type { ActionSpec } from "../package/types.js";
|
|
3
3
|
import type { ConfigItemDefinition } from "../project/types.js";
|
|
4
|
-
import type {
|
|
4
|
+
import type { ActionDockService } from "../service/types.js";
|
|
5
5
|
/**
|
|
6
6
|
* 退出状态码常量。
|
|
7
7
|
*/
|
|
@@ -28,8 +28,8 @@ export interface StandaloneDispatcherOptions {
|
|
|
28
28
|
version: string;
|
|
29
29
|
/** 描述信息 */
|
|
30
30
|
description?: string;
|
|
31
|
-
/** 已构造的
|
|
32
|
-
|
|
31
|
+
/** 已构造的 ActionDockService 服务(若未传入则依据 actions/config 自动创建) */
|
|
32
|
+
service?: ActionDockService;
|
|
33
33
|
/** 声明的配置依赖定义(兼容选项) */
|
|
34
34
|
configDefs?: Record<string, ConfigItemDefinition>;
|
|
35
35
|
config?: Record<string, ConfigItemDefinition>;
|
|
@@ -56,7 +56,7 @@ export interface StandaloneDispatcherOptions {
|
|
|
56
56
|
*
|
|
57
57
|
* 职责:
|
|
58
58
|
* 1. 负责轻量参数解析、诊断输出渲染与统一退出码管理。
|
|
59
|
-
* 2. 统一面向
|
|
59
|
+
* 2. 统一面向 ActionDockService 服务调用能力。
|
|
60
60
|
* 3. 严格遵循 ActionDock 2.0 输出协议约定:结果数据专走 stdout,日志与错误专走 stderr。
|
|
61
61
|
* 4. 独立入口拒绝异步启动语义,显式拦截并返回 STANDALONE_ASYNC_UNSUPPORTED。
|
|
62
62
|
*/
|
|
@@ -65,7 +65,22 @@ export declare class StandaloneDispatcher {
|
|
|
65
65
|
constructor(options: StandaloneDispatcherOptions);
|
|
66
66
|
private writeOut;
|
|
67
67
|
private writeErr;
|
|
68
|
-
|
|
68
|
+
/**
|
|
69
|
+
* 统一错误输出辅助方法。
|
|
70
|
+
*
|
|
71
|
+
* JSON 模式向 stdout 输出两空格缩进的标准错误结构;
|
|
72
|
+
* 纯文本模式向 stderr 输出单行错误消息(默认携带 Error: 前缀)。
|
|
73
|
+
* 消息文本与退出码由调用方逐字给定,输出字节严格保持不变。
|
|
74
|
+
*
|
|
75
|
+
* @param isJson 是否处于 JSON 输出模式
|
|
76
|
+
* @param code 错误码
|
|
77
|
+
* @param message JSON 模式错误消息(兼作纯文本默认消息主体)
|
|
78
|
+
* @param exitCode 调用方应返回的退出状态码
|
|
79
|
+
* @param options 可选项:textMessage 覆盖纯文本消息全文;details 为 JSON 模式可选结构化详情
|
|
80
|
+
* @returns 透传 exitCode 供调用方直接返回
|
|
81
|
+
*/
|
|
82
|
+
private emitError;
|
|
83
|
+
private createLocalService;
|
|
69
84
|
/**
|
|
70
85
|
* 解析命令行参数并分发执行对应子命令。
|
|
71
86
|
*
|
|
@@ -80,9 +95,9 @@ export declare class StandaloneDispatcher {
|
|
|
80
95
|
private handleConfig;
|
|
81
96
|
private handleState;
|
|
82
97
|
/**
|
|
83
|
-
*
|
|
98
|
+
* 判定配置读取异常是否为服务能力缺失(键未配置语义)而非内部故障。
|
|
84
99
|
*/
|
|
85
|
-
private
|
|
100
|
+
private isServiceCapabilityError;
|
|
86
101
|
/**
|
|
87
102
|
* 解析携带命名空间前缀的状态键参数:委托 sdk 单一事实源 decodeStateKey。
|
|
88
103
|
*
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { decodeStateKey } from "@actiondock/sdk";
|
|
2
2
|
import { filterWithFallbackInfo } from "../filter/index.js";
|
|
3
|
-
import {
|
|
3
|
+
import { createActionDock } from "../service/factory.js";
|
|
4
4
|
import { STANDALONE_ASYNC_UNSUPPORTED } from "../errors.js";
|
|
5
5
|
import { resolveActionInput, formatActionDetail, buildActionDescribePayload, mapInputValidationFailure, } from "../input/index.js";
|
|
6
6
|
import { validateActionInputValue } from "../json/value-validator.js";
|
|
@@ -20,7 +20,7 @@ export const ExitCode = {
|
|
|
20
20
|
*
|
|
21
21
|
* 职责:
|
|
22
22
|
* 1. 负责轻量参数解析、诊断输出渲染与统一退出码管理。
|
|
23
|
-
* 2. 统一面向
|
|
23
|
+
* 2. 统一面向 ActionDockService 服务调用能力。
|
|
24
24
|
* 3. 严格遵循 ActionDock 2.0 输出协议约定:结果数据专走 stdout,日志与错误专走 stderr。
|
|
25
25
|
* 4. 独立入口拒绝异步启动语义,显式拦截并返回 STANDALONE_ASYNC_UNSUPPORTED。
|
|
26
26
|
*/
|
|
@@ -45,18 +45,49 @@ export class StandaloneDispatcher {
|
|
|
45
45
|
console.error(msg);
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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
|
+
emitError(isJson, code, message, exitCode, options) {
|
|
63
|
+
if (isJson) {
|
|
64
|
+
const details = options?.details;
|
|
65
|
+
this.writeOut(JSON.stringify({
|
|
66
|
+
ok: false,
|
|
67
|
+
error: {
|
|
68
|
+
code,
|
|
69
|
+
message,
|
|
70
|
+
...(details !== undefined ? { details } : {}),
|
|
71
|
+
},
|
|
72
|
+
}, null, 2));
|
|
51
73
|
}
|
|
52
|
-
|
|
53
|
-
|
|
74
|
+
else {
|
|
75
|
+
this.writeErr(options?.textMessage ?? `Error: ${message}`);
|
|
76
|
+
}
|
|
77
|
+
return exitCode;
|
|
78
|
+
}
|
|
79
|
+
async createLocalService(dataDir, configOverrides = {}) {
|
|
80
|
+
if (this.options.service) {
|
|
81
|
+
return { service: this.options.service, ownsService: false };
|
|
82
|
+
}
|
|
83
|
+
if (this.options.inMemory && this.options._sharedService) {
|
|
84
|
+
return { service: this.options._sharedService, ownsService: false };
|
|
54
85
|
}
|
|
55
86
|
// 归一化 Action 集合:单一入口统一三形态输入
|
|
56
87
|
const { actionsMap, actionSpecs } = normalizeActionCollection(this.options.actions);
|
|
57
88
|
// projectConfig.actions 要求 manifest 形态,字段语义兼容,此处显式收敛类型
|
|
58
89
|
const manifestActions = actionSpecs;
|
|
59
|
-
const
|
|
90
|
+
const runtimeOptions = {
|
|
60
91
|
projectConfig: {
|
|
61
92
|
id: this.options.packageId,
|
|
62
93
|
name: this.options.packageId,
|
|
@@ -71,15 +102,14 @@ export class StandaloneDispatcher {
|
|
|
71
102
|
customHome: this.options.customHome,
|
|
72
103
|
inMemory: this.options.inMemory,
|
|
73
104
|
};
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
appOptions,
|
|
105
|
+
const service = await createActionDock({
|
|
106
|
+
runtimeOptions,
|
|
77
107
|
});
|
|
78
108
|
if (this.options.inMemory) {
|
|
79
|
-
this.options.
|
|
80
|
-
return {
|
|
109
|
+
this.options._sharedService = service;
|
|
110
|
+
return { service, ownsService: false };
|
|
81
111
|
}
|
|
82
|
-
return {
|
|
112
|
+
return { service, ownsService: true };
|
|
83
113
|
}
|
|
84
114
|
/**
|
|
85
115
|
* 解析命令行参数并分发执行对应子命令。
|
|
@@ -124,20 +154,9 @@ export class StandaloneDispatcher {
|
|
|
124
154
|
const subArgs = filteredArgs.slice(1);
|
|
125
155
|
// 2. 独立入口拒绝异步启动语义
|
|
126
156
|
if (controlArgs.includes("--async")) {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
ok: false,
|
|
131
|
-
error: {
|
|
132
|
-
code: STANDALONE_ASYNC_UNSUPPORTED,
|
|
133
|
-
message: "Async execution is not supported in standalone single-execution binaries. Use 'ad serve' or remote target.",
|
|
134
|
-
},
|
|
135
|
-
}, null, 2));
|
|
136
|
-
}
|
|
137
|
-
else {
|
|
138
|
-
this.writeErr(`Error [${STANDALONE_ASYNC_UNSUPPORTED}]: Async execution is not supported in standalone single-execution binaries.`);
|
|
139
|
-
}
|
|
140
|
-
return ExitCode.FAILURE;
|
|
157
|
+
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, {
|
|
158
|
+
textMessage: `Error [${STANDALONE_ASYNC_UNSUPPORTED}]: Async execution is not supported in standalone single-execution binaries.`,
|
|
159
|
+
});
|
|
141
160
|
}
|
|
142
161
|
// 3. 版本与帮助快速处理(无需初始化 Host / Storage)
|
|
143
162
|
if (command === "-v" || command === "-V" || command === "--version" || command === "version") {
|
|
@@ -148,35 +167,35 @@ export class StandaloneDispatcher {
|
|
|
148
167
|
this.printHelp();
|
|
149
168
|
return ExitCode.SUCCESS;
|
|
150
169
|
}
|
|
151
|
-
let
|
|
152
|
-
let
|
|
170
|
+
let service;
|
|
171
|
+
let ownsService = false;
|
|
153
172
|
try {
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
|
|
173
|
+
const serviceRes = await this.createLocalService(dataDir, configOverrides);
|
|
174
|
+
service = serviceRes.service;
|
|
175
|
+
ownsService = serviceRes.ownsService;
|
|
157
176
|
}
|
|
158
177
|
catch (err) {
|
|
159
|
-
this.writeErr(`Error initializing standalone
|
|
178
|
+
this.writeErr(`Error initializing standalone service: ${err?.message || err}`);
|
|
160
179
|
return ExitCode.FAILURE;
|
|
161
180
|
}
|
|
162
181
|
try {
|
|
163
182
|
let code;
|
|
164
183
|
switch (command) {
|
|
165
184
|
case "list":
|
|
166
|
-
code = await this.handleList(
|
|
185
|
+
code = await this.handleList(service, subArgs);
|
|
167
186
|
break;
|
|
168
187
|
case "describe":
|
|
169
188
|
case "show":
|
|
170
|
-
code = await this.handleDescribe(
|
|
189
|
+
code = await this.handleDescribe(service, subArgs);
|
|
171
190
|
break;
|
|
172
191
|
case "run":
|
|
173
|
-
code = await this.handleRun(
|
|
192
|
+
code = await this.handleRun(service, subArgs, actionArgs, control?.signal);
|
|
174
193
|
break;
|
|
175
194
|
case "config":
|
|
176
|
-
code = await this.handleConfig(
|
|
195
|
+
code = await this.handleConfig(service, subArgs);
|
|
177
196
|
break;
|
|
178
197
|
case "state":
|
|
179
|
-
code = await this.handleState(
|
|
198
|
+
code = await this.handleState(service, subArgs);
|
|
180
199
|
break;
|
|
181
200
|
default:
|
|
182
201
|
this.writeErr(`Unknown command: '${command}'`);
|
|
@@ -190,19 +209,19 @@ export class StandaloneDispatcher {
|
|
|
190
209
|
}
|
|
191
210
|
catch (err) {
|
|
192
211
|
if (control?.cancellationSource === "sigint" &&
|
|
193
|
-
(control?.signal?.aborted || err?.name === "AbortError" || err?.
|
|
212
|
+
(control?.signal?.aborted || err?.name === "AbortError" || err?.code === "SIGINT_INTERRUPTED")) {
|
|
194
213
|
return ExitCode.SIGINT;
|
|
195
214
|
}
|
|
196
215
|
this.writeErr(`Error: ${err?.message || err}`);
|
|
197
216
|
return ExitCode.FAILURE;
|
|
198
217
|
}
|
|
199
218
|
finally {
|
|
200
|
-
if (
|
|
201
|
-
await
|
|
219
|
+
if (ownsService) {
|
|
220
|
+
await service.close();
|
|
202
221
|
}
|
|
203
222
|
}
|
|
204
223
|
}
|
|
205
|
-
async handleList(
|
|
224
|
+
async handleList(service, subArgs) {
|
|
206
225
|
const isJson = subArgs.includes("--json");
|
|
207
226
|
const noFallback = subArgs.includes("--no-fallback");
|
|
208
227
|
let intent;
|
|
@@ -224,7 +243,7 @@ export class StandaloneDispatcher {
|
|
|
224
243
|
}
|
|
225
244
|
}
|
|
226
245
|
const effectiveIntent = intent || (positionalPatterns.length > 0 ? positionalPatterns.join("|") : undefined);
|
|
227
|
-
const actions = await
|
|
246
|
+
const actions = await service.discovery.listActions();
|
|
228
247
|
const list = actions.map((a) => ({
|
|
229
248
|
id: a.id,
|
|
230
249
|
description: a.description || "",
|
|
@@ -242,42 +261,18 @@ export class StandaloneDispatcher {
|
|
|
242
261
|
}
|
|
243
262
|
return ExitCode.SUCCESS;
|
|
244
263
|
}
|
|
245
|
-
async handleDescribe(
|
|
264
|
+
async handleDescribe(service, subArgs) {
|
|
246
265
|
const id = subArgs.find((a) => !a.startsWith("-"));
|
|
247
266
|
const isJson = subArgs.includes("--json");
|
|
248
267
|
if (!id) {
|
|
249
|
-
|
|
250
|
-
this.writeOut(JSON.stringify({
|
|
251
|
-
ok: false,
|
|
252
|
-
error: {
|
|
253
|
-
code: "INVALID_ARGUMENT",
|
|
254
|
-
message: "Action ID is required for describe",
|
|
255
|
-
},
|
|
256
|
-
}, null, 2));
|
|
257
|
-
}
|
|
258
|
-
else {
|
|
259
|
-
this.writeErr("Error: Action ID is required for describe");
|
|
260
|
-
}
|
|
261
|
-
return ExitCode.INVALID_ARGUMENT;
|
|
268
|
+
return this.emitError(isJson, "INVALID_ARGUMENT", "Action ID is required for describe", ExitCode.INVALID_ARGUMENT);
|
|
262
269
|
}
|
|
263
270
|
let action;
|
|
264
271
|
try {
|
|
265
|
-
action = await
|
|
272
|
+
action = await service.discovery.describeAction(id);
|
|
266
273
|
}
|
|
267
274
|
catch {
|
|
268
|
-
|
|
269
|
-
this.writeOut(JSON.stringify({
|
|
270
|
-
ok: false,
|
|
271
|
-
error: {
|
|
272
|
-
code: "INVALID_ARGUMENT",
|
|
273
|
-
message: `Action '${id}' not found`,
|
|
274
|
-
},
|
|
275
|
-
}, null, 2));
|
|
276
|
-
}
|
|
277
|
-
else {
|
|
278
|
-
this.writeErr(`Error: Action '${id}' not found`);
|
|
279
|
-
}
|
|
280
|
-
return ExitCode.INVALID_ARGUMENT;
|
|
275
|
+
return this.emitError(isJson, "INVALID_ARGUMENT", `Action '${id}' not found`, ExitCode.INVALID_ARGUMENT);
|
|
281
276
|
}
|
|
282
277
|
const payload = buildActionDescribePayload(action, {
|
|
283
278
|
packageId: this.options.packageId,
|
|
@@ -290,23 +285,11 @@ export class StandaloneDispatcher {
|
|
|
290
285
|
}
|
|
291
286
|
return ExitCode.SUCCESS;
|
|
292
287
|
}
|
|
293
|
-
async handleRun(
|
|
288
|
+
async handleRun(service, subArgs, actionArgs, signal) {
|
|
294
289
|
const isJson = subArgs.includes("--json");
|
|
295
290
|
const id = subArgs.find((a) => !a.startsWith("-"));
|
|
296
291
|
if (!id) {
|
|
297
|
-
|
|
298
|
-
this.writeOut(JSON.stringify({
|
|
299
|
-
ok: false,
|
|
300
|
-
error: {
|
|
301
|
-
code: "INVALID_ARGUMENT",
|
|
302
|
-
message: "Error: Action ID is required for run",
|
|
303
|
-
},
|
|
304
|
-
}, null, 2));
|
|
305
|
-
}
|
|
306
|
-
else {
|
|
307
|
-
this.writeErr("Error: Action ID is required for run");
|
|
308
|
-
}
|
|
309
|
-
return ExitCode.INVALID_ARGUMENT;
|
|
292
|
+
return this.emitError(isJson, "INVALID_ARGUMENT", "Error: Action ID is required for run", ExitCode.INVALID_ARGUMENT, { textMessage: "Error: Action ID is required for run" });
|
|
310
293
|
}
|
|
311
294
|
let inputStr;
|
|
312
295
|
let inputFile;
|
|
@@ -318,19 +301,7 @@ export class StandaloneDispatcher {
|
|
|
318
301
|
timeoutMs = parseDuration(subArgs[++i]);
|
|
319
302
|
}
|
|
320
303
|
catch (err) {
|
|
321
|
-
|
|
322
|
-
this.writeOut(JSON.stringify({
|
|
323
|
-
ok: false,
|
|
324
|
-
error: {
|
|
325
|
-
code: "INVALID_ARGUMENT",
|
|
326
|
-
message: `Invalid timeout format: ${err?.message || err}`,
|
|
327
|
-
},
|
|
328
|
-
}, null, 2));
|
|
329
|
-
}
|
|
330
|
-
else {
|
|
331
|
-
this.writeErr(`Error: Invalid timeout format: ${err?.message || err}`);
|
|
332
|
-
}
|
|
333
|
-
return ExitCode.INVALID_ARGUMENT;
|
|
304
|
+
return this.emitError(isJson, "INVALID_ARGUMENT", `Invalid timeout format: ${err?.message || err}`, ExitCode.INVALID_ARGUMENT);
|
|
334
305
|
}
|
|
335
306
|
}
|
|
336
307
|
else if (arg.startsWith("--timeout=")) {
|
|
@@ -338,19 +309,7 @@ export class StandaloneDispatcher {
|
|
|
338
309
|
timeoutMs = parseDuration(arg.slice(10));
|
|
339
310
|
}
|
|
340
311
|
catch (err) {
|
|
341
|
-
|
|
342
|
-
this.writeOut(JSON.stringify({
|
|
343
|
-
ok: false,
|
|
344
|
-
error: {
|
|
345
|
-
code: "INVALID_ARGUMENT",
|
|
346
|
-
message: `Invalid timeout format: ${err?.message || err}`,
|
|
347
|
-
},
|
|
348
|
-
}, null, 2));
|
|
349
|
-
}
|
|
350
|
-
else {
|
|
351
|
-
this.writeErr(`Error: Invalid timeout format: ${err?.message || err}`);
|
|
352
|
-
}
|
|
353
|
-
return ExitCode.INVALID_ARGUMENT;
|
|
312
|
+
return this.emitError(isJson, "INVALID_ARGUMENT", `Invalid timeout format: ${err?.message || err}`, ExitCode.INVALID_ARGUMENT);
|
|
354
313
|
}
|
|
355
314
|
}
|
|
356
315
|
else if (arg === "--input" && i + 1 < subArgs.length) {
|
|
@@ -380,22 +339,11 @@ export class StandaloneDispatcher {
|
|
|
380
339
|
}
|
|
381
340
|
}
|
|
382
341
|
catch (err) {
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
error: {
|
|
387
|
-
code: err?.code || "INVALID_ARGUMENT",
|
|
388
|
-
message: err?.message || String(err),
|
|
389
|
-
...(err?.details !== undefined ? { details: err.details } : {}),
|
|
390
|
-
},
|
|
391
|
-
}, null, 2));
|
|
392
|
-
}
|
|
393
|
-
else {
|
|
394
|
-
this.writeErr(`Error: ${err?.message || String(err)}`);
|
|
395
|
-
}
|
|
396
|
-
return ExitCode.INVALID_ARGUMENT;
|
|
342
|
+
return this.emitError(isJson, err?.code || "INVALID_ARGUMENT", err?.message || String(err), ExitCode.INVALID_ARGUMENT, {
|
|
343
|
+
details: err?.details,
|
|
344
|
+
});
|
|
397
345
|
}
|
|
398
|
-
const result = await
|
|
346
|
+
const result = await service.execution.run(id, input, {
|
|
399
347
|
signal,
|
|
400
348
|
timeoutMs,
|
|
401
349
|
});
|
|
@@ -484,10 +432,14 @@ export class StandaloneDispatcher {
|
|
|
484
432
|
}
|
|
485
433
|
return result.ok ? ExitCode.SUCCESS : ExitCode.FAILURE;
|
|
486
434
|
}
|
|
487
|
-
async handleConfig(
|
|
435
|
+
async handleConfig(service, subArgs) {
|
|
488
436
|
const sub = subArgs[0] || "list";
|
|
437
|
+
if (!service.management) {
|
|
438
|
+
this.writeErr("Error: management port is not enabled on this service");
|
|
439
|
+
return ExitCode.FAILURE;
|
|
440
|
+
}
|
|
489
441
|
if (sub === "list") {
|
|
490
|
-
const views = await
|
|
442
|
+
const views = await service.management.config.list(this.options.packageId);
|
|
491
443
|
const dict = {};
|
|
492
444
|
for (const v of views) {
|
|
493
445
|
if (v.configured && v.value !== undefined) {
|
|
@@ -504,13 +456,13 @@ export class StandaloneDispatcher {
|
|
|
504
456
|
return ExitCode.INVALID_ARGUMENT;
|
|
505
457
|
}
|
|
506
458
|
try {
|
|
507
|
-
const item = await
|
|
459
|
+
const item = await service.management.config.get(this.options.packageId, key);
|
|
508
460
|
this.writeOut(item.configured ? JSON.stringify(item.value) : "undefined");
|
|
509
461
|
return ExitCode.SUCCESS;
|
|
510
462
|
}
|
|
511
463
|
catch (err) {
|
|
512
|
-
//
|
|
513
|
-
if (this.
|
|
464
|
+
// 服务能力缺失(如远端未开启管理接口)视为键未配置,输出 undefined
|
|
465
|
+
if (this.isServiceCapabilityError(err)) {
|
|
514
466
|
this.writeOut("undefined");
|
|
515
467
|
return ExitCode.SUCCESS;
|
|
516
468
|
}
|
|
@@ -533,7 +485,7 @@ export class StandaloneDispatcher {
|
|
|
533
485
|
catch {
|
|
534
486
|
parsed = rawVal;
|
|
535
487
|
}
|
|
536
|
-
await
|
|
488
|
+
await service.management.config.set(this.options.packageId, key, parsed);
|
|
537
489
|
this.writeOut(`Config '${key}' updated`);
|
|
538
490
|
return ExitCode.SUCCESS;
|
|
539
491
|
}
|
|
@@ -543,18 +495,22 @@ export class StandaloneDispatcher {
|
|
|
543
495
|
this.writeErr("Error: config key required");
|
|
544
496
|
return ExitCode.INVALID_ARGUMENT;
|
|
545
497
|
}
|
|
546
|
-
await
|
|
498
|
+
await service.management.config.delete(this.options.packageId, key);
|
|
547
499
|
this.writeOut(`Config '${key}' deleted`);
|
|
548
500
|
return ExitCode.SUCCESS;
|
|
549
501
|
}
|
|
550
502
|
this.writeErr(`Unknown config subcommand: '${sub}'`);
|
|
551
503
|
return ExitCode.INVALID_ARGUMENT;
|
|
552
504
|
}
|
|
553
|
-
async handleState(
|
|
505
|
+
async handleState(service, subArgs) {
|
|
554
506
|
const sub = subArgs[0] || "list";
|
|
555
507
|
let namespace;
|
|
556
508
|
let isAll = false;
|
|
557
509
|
let isJson = false;
|
|
510
|
+
if (!service.management) {
|
|
511
|
+
this.writeErr("Error: management port is not enabled on this service");
|
|
512
|
+
return ExitCode.FAILURE;
|
|
513
|
+
}
|
|
558
514
|
for (let i = 1; i < subArgs.length; i++) {
|
|
559
515
|
if ((subArgs[i] === "-n" || subArgs[i] === "--namespace") && i + 1 < subArgs.length) {
|
|
560
516
|
namespace = subArgs[++i];
|
|
@@ -571,7 +527,7 @@ export class StandaloneDispatcher {
|
|
|
571
527
|
}
|
|
572
528
|
if (sub === "list") {
|
|
573
529
|
const prefix = subArgs[1] && !subArgs[1].startsWith("-") ? subArgs[1] : "";
|
|
574
|
-
const keys = await
|
|
530
|
+
const keys = await service.management.state.list(this.options.packageId, "", {
|
|
575
531
|
namespace,
|
|
576
532
|
prefix: prefix || undefined,
|
|
577
533
|
all: isAll,
|
|
@@ -592,7 +548,7 @@ export class StandaloneDispatcher {
|
|
|
592
548
|
ns = decoded.namespace || undefined;
|
|
593
549
|
actualKey = decoded.key;
|
|
594
550
|
}
|
|
595
|
-
const val = await
|
|
551
|
+
const val = await service.management.state.get(this.options.packageId, "", actualKey, { namespace: ns });
|
|
596
552
|
if (isJson) {
|
|
597
553
|
this.writeOut(JSON.stringify({ key, value: val }, null, 2));
|
|
598
554
|
}
|
|
@@ -631,7 +587,7 @@ export class StandaloneDispatcher {
|
|
|
631
587
|
ttl = parseInt(subArgs[i].slice(6), 10);
|
|
632
588
|
}
|
|
633
589
|
}
|
|
634
|
-
await
|
|
590
|
+
await service.management.state.set(this.options.packageId, "", actualKey, parsed, { namespace: ns, ttl });
|
|
635
591
|
const displayKey = ns ? `${ns}:${actualKey}` : actualKey;
|
|
636
592
|
this.writeOut(`State '${displayKey}' updated`);
|
|
637
593
|
return ExitCode.SUCCESS;
|
|
@@ -642,7 +598,7 @@ export class StandaloneDispatcher {
|
|
|
642
598
|
this.writeErr("Error: state key required");
|
|
643
599
|
return ExitCode.INVALID_ARGUMENT;
|
|
644
600
|
}
|
|
645
|
-
const deleted = await
|
|
601
|
+
const deleted = await service.management.state.delete(this.options.packageId, "", key, { namespace });
|
|
646
602
|
if (deleted) {
|
|
647
603
|
this.writeOut(`State '${key}' deleted`);
|
|
648
604
|
return ExitCode.SUCCESS;
|
|
@@ -652,7 +608,7 @@ export class StandaloneDispatcher {
|
|
|
652
608
|
}
|
|
653
609
|
if (sub === "clear" || sub === "clean") {
|
|
654
610
|
const prefix = subArgs[1] && !subArgs[1].startsWith("-") ? subArgs[1] : "";
|
|
655
|
-
const count = await
|
|
611
|
+
const count = await service.management.state.clear(this.options.packageId, "", {
|
|
656
612
|
namespace,
|
|
657
613
|
all: isAll,
|
|
658
614
|
prefix: prefix || undefined,
|
|
@@ -664,15 +620,12 @@ export class StandaloneDispatcher {
|
|
|
664
620
|
return ExitCode.INVALID_ARGUMENT;
|
|
665
621
|
}
|
|
666
622
|
/**
|
|
667
|
-
*
|
|
623
|
+
* 判定配置读取异常是否为服务能力缺失(键未配置语义)而非内部故障。
|
|
668
624
|
*/
|
|
669
|
-
|
|
625
|
+
isServiceCapabilityError(err) {
|
|
670
626
|
const code = String(err?.code || "");
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
code === "CAPABILITY_UNAVAILABLE" ||
|
|
674
|
-
msg.includes("TARGET_CAPABILITY_UNAVAILABLE") ||
|
|
675
|
-
msg.includes("Management APIs are not enabled"));
|
|
627
|
+
return (code === "CAPABILITY_UNAVAILABLE" ||
|
|
628
|
+
code === "TARGET_CAPABILITY_UNAVAILABLE");
|
|
676
629
|
}
|
|
677
630
|
/**
|
|
678
631
|
* 解析携带命名空间前缀的状态键参数:委托 sdk 单一事实源 decodeStateKey。
|
package/dist/server/body.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ActionDockError } from "../errors.js";
|
|
1
2
|
/**
|
|
2
3
|
* 默认单次 HTTP 请求体最大字节上限(1 MiB)。
|
|
3
4
|
*/
|
|
@@ -5,15 +6,13 @@ export declare const DEFAULT_MAX_BODY_BYTES: number;
|
|
|
5
6
|
/**
|
|
6
7
|
* 请求体超出最大允许体积时抛出的异常(对应 HTTP 413 Payload Too Large)。
|
|
7
8
|
*/
|
|
8
|
-
export declare class RequestTooLargeError extends
|
|
9
|
-
code: string;
|
|
9
|
+
export declare class RequestTooLargeError extends ActionDockError {
|
|
10
10
|
constructor(message?: string);
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
13
13
|
* 请求体非合法 JSON 格式时抛出的异常(对应 HTTP 400 Bad Request)。
|
|
14
14
|
*/
|
|
15
|
-
export declare class InvalidJsonError extends
|
|
16
|
-
code: string;
|
|
15
|
+
export declare class InvalidJsonError extends ActionDockError {
|
|
17
16
|
constructor(message?: string);
|
|
18
17
|
}
|
|
19
18
|
/**
|
|
@@ -24,12 +23,21 @@ export interface ReadJsonBodyOptions {
|
|
|
24
23
|
maxBytes?: number;
|
|
25
24
|
}
|
|
26
25
|
/**
|
|
27
|
-
* 流式安全地读取 HTTP
|
|
26
|
+
* 流式安全地读取 HTTP 请求体为原始字节数组(有界读取单一事实源)。
|
|
28
27
|
*
|
|
29
28
|
* 防护机制:
|
|
30
|
-
* 1. 快速拒绝(Fast-path):若请求头中存在
|
|
31
|
-
* 2. 流式计数器(Chunk Streaming
|
|
32
|
-
*
|
|
29
|
+
* 1. 快速拒绝(Fast-path):若请求头中存在 Content-Length 且超过 maxBytes,立即抛出 RequestTooLargeError,不进行内存分配。
|
|
30
|
+
* 2. 流式计数器(Chunk Streaming):读取 ReadableStream 过程中实时累计字节数,中途超出上限即刻截断并释放流锁,防止大文件 DoS 与内存耗尽(OOM)。
|
|
31
|
+
*
|
|
32
|
+
* @param req 传入的 Request 对象
|
|
33
|
+
* @param options 读取配置选项
|
|
34
|
+
* @returns 原始字节数组(空请求体返回空数组)
|
|
35
|
+
* @throws {RequestTooLargeError} 若请求体体积超限
|
|
36
|
+
*/
|
|
37
|
+
export declare function readBodyWithLimit(req: Request, options?: ReadJsonBodyOptions): Promise<Uint8Array>;
|
|
38
|
+
/**
|
|
39
|
+
* 流式安全地读取 HTTP 请求体并解析为 JSON 对象。
|
|
40
|
+
* 防护机制见 readBodyWithLimit;此外处理空请求体与 UTF-8 字符集解码。
|
|
33
41
|
*
|
|
34
42
|
* @param req 传入的 Request 对象
|
|
35
43
|
* @param options 读取配置选项
|