@actiondock/core 2.19.0 → 2.21.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.
Files changed (108) hide show
  1. package/dist/client/config.d.ts +17 -14
  2. package/dist/client/config.js +112 -14
  3. package/dist/client/index.d.ts +1 -1
  4. package/dist/client/index.js +1 -1
  5. package/dist/errors.d.ts +13 -1
  6. package/dist/errors.js +25 -0
  7. package/dist/execution/service.js +44 -10
  8. package/dist/execution/types.d.ts +3 -3
  9. package/dist/host/host.d.ts +20 -1
  10. package/dist/host/host.js +430 -66
  11. package/dist/host/types.d.ts +13 -1
  12. package/dist/index.d.ts +11 -3
  13. package/dist/index.js +5 -1
  14. package/dist/input/config-override.d.ts +5 -0
  15. package/dist/input/config-override.js +23 -0
  16. package/dist/input/input-resolver.d.ts +24 -7
  17. package/dist/input/input-resolver.js +73 -5
  18. package/dist/invocation/bindings.d.ts +53 -0
  19. package/dist/invocation/bindings.js +248 -0
  20. package/dist/invocation/policy.d.ts +5 -1
  21. package/dist/invocation/policy.js +16 -9
  22. package/dist/invocation/remote.d.ts +40 -0
  23. package/dist/invocation/remote.js +489 -0
  24. package/dist/invocation/types.d.ts +33 -0
  25. package/dist/invocation/types.js +11 -1
  26. package/dist/package/index.d.ts +2 -2
  27. package/dist/package/runtime.js +48 -15
  28. package/dist/platform/node.d.ts +6 -0
  29. package/dist/platform/node.js +59 -16
  30. package/dist/platform/types.d.ts +59 -1
  31. package/dist/process/command-executor.d.ts +35 -0
  32. package/dist/process/command-executor.js +326 -0
  33. package/dist/process/index.d.ts +1 -0
  34. package/dist/process/index.js +1 -0
  35. package/dist/process/process-driver.d.ts +19 -6
  36. package/dist/process/process-driver.js +223 -54
  37. package/dist/process/run-executor.js +101 -47
  38. package/dist/project/config-declarations.d.ts +61 -0
  39. package/dist/project/config-declarations.js +297 -0
  40. package/dist/project/dependencies.d.ts +92 -0
  41. package/dist/project/dependencies.js +543 -0
  42. package/dist/project/index.d.ts +8 -2
  43. package/dist/project/index.js +8 -2
  44. package/dist/project/init.js +2 -2
  45. package/dist/project/loader.js +19 -30
  46. package/dist/project/manifest.js +10 -0
  47. package/dist/project/package-manager.d.ts +40 -0
  48. package/dist/project/package-manager.js +224 -0
  49. package/dist/project/preparation.d.ts +8 -0
  50. package/dist/project/preparation.js +130 -0
  51. package/dist/project/transactions.d.ts +5 -1
  52. package/dist/project/transactions.js +35 -75
  53. package/dist/project/types.d.ts +30 -0
  54. package/dist/runtime/context.d.ts +27 -5
  55. package/dist/runtime/context.js +98 -26
  56. package/dist/runtime/env.js +15 -1
  57. package/dist/runtime/run-persistence.d.ts +1 -1
  58. package/dist/runtime/run-persistence.js +4 -3
  59. package/dist/runtime/standalone-commands.d.ts +2 -2
  60. package/dist/runtime/standalone-commands.js +113 -47
  61. package/dist/runtime/standalone-help.d.ts +1 -0
  62. package/dist/runtime/standalone-help.js +15 -9
  63. package/dist/runtime/standalone.js +2 -2
  64. package/dist/security/config-cipher.d.ts +54 -0
  65. package/dist/security/config-cipher.js +190 -0
  66. package/dist/security/config-key.d.ts +35 -0
  67. package/dist/security/config-key.js +469 -0
  68. package/dist/server/policy.d.ts +24 -107
  69. package/dist/server/policy.js +134 -291
  70. package/dist/server/routes/actions.js +10 -8
  71. package/dist/server/routes/common.d.ts +5 -20
  72. package/dist/server/routes/common.js +22 -58
  73. package/dist/server/routes/config.js +84 -7
  74. package/dist/server/routes/doctor.d.ts +1 -0
  75. package/dist/server/routes/doctor.js +4 -3
  76. package/dist/server/routes/info.js +100 -13
  77. package/dist/server/routes/playbooks.js +1 -3
  78. package/dist/server/routes/runs.js +96 -18
  79. package/dist/server/server.js +25 -53
  80. package/dist/server/types.d.ts +6 -6
  81. package/dist/service/factory.js +4 -0
  82. package/dist/service/remote.js +14 -29
  83. package/dist/service/types.d.ts +28 -5
  84. package/dist/service/types.js +8 -0
  85. package/dist/storage/config-value.d.ts +33 -0
  86. package/dist/storage/config-value.js +102 -0
  87. package/dist/storage/file-lock.js +35 -21
  88. package/dist/storage/index.d.ts +24 -2
  89. package/dist/storage/index.js +65 -2
  90. package/dist/storage/mask.d.ts +33 -6
  91. package/dist/storage/mask.js +298 -16
  92. package/dist/storage/migrations/index.d.ts +40 -0
  93. package/dist/storage/migrations/index.js +96 -0
  94. package/dist/storage/migrations/v2-to-v3.d.ts +16 -0
  95. package/dist/storage/migrations/v2-to-v3.js +116 -0
  96. package/dist/storage/sqlite-config.d.ts +62 -3
  97. package/dist/storage/sqlite-config.js +163 -9
  98. package/dist/storage/sqlite-driver.d.ts +5 -2
  99. package/dist/storage/sqlite-driver.js +24 -3
  100. package/dist/storage/sqlite-schema.d.ts +20 -2
  101. package/dist/storage/sqlite-schema.js +129 -132
  102. package/dist/storage/sqlite.d.ts +7 -2
  103. package/dist/storage/sqlite.js +64 -13
  104. package/dist/storage/types.d.ts +72 -4
  105. package/dist/storage/types.js +7 -2
  106. package/dist/version.d.ts +1 -1
  107. package/dist/version.js +1 -1
  108. package/package.json +2 -2
@@ -1,20 +1,23 @@
1
+ import type { ConfigItemDefinition } from "../project/types.js";
1
2
  import type { RemoteClientRequestOptions } from "./transport.js";
3
+ export interface FetchRemoteConfigOptions extends RemoteClientRequestOptions {
4
+ /** 本地声明只可加强远端保护,不能撤销服务端标记。 */
5
+ localDeclarations?: Record<string, ConfigItemDefinition>;
6
+ /** 提供当前目录声明时,仅在响应包标识匹配后启用。 */
7
+ localPackageId?: string;
8
+ }
2
9
  /**
3
- * 远端配置域端点。
4
- */
5
- /**
6
- * 拉取远端配置视图(可定向指定包)。
7
- */
8
- export declare function fetchRemoteConfig(serverUrl: string, token?: string, packageId?: string, options?: RemoteClientRequestOptions): Promise<any>;
9
- /**
10
- * 写入单个远端配置键值。
10
+ * 在核心边界归一化配置安全视图;仅接受 configViewVersion:1 新协议。
11
+ * 旧协议无法证明来源与元数据真实性,统一抛出协议不支持错误,不猜测来源。
11
12
  */
13
+ export declare function normalizeRemoteConfigResponse(rawResponse: any, options?: Pick<FetchRemoteConfigOptions, "localDeclarations" | "localPackageId"> & {
14
+ packageId?: string;
15
+ }): any;
16
+ /** 拉取远端配置;返回值与元数据均已完成安全归一化。 */
17
+ export declare function fetchRemoteConfig(serverUrl: string, token?: string, packageId?: string, options?: FetchRemoteConfigOptions): Promise<any>;
18
+ /** 单键查询可解析仅由环境变量提供的模板实例;服务端必须返回同键完整单项视图。 */
19
+ export declare function fetchRemoteConfigItem(serverUrl: string, key: string, token?: string, packageId?: string, options?: FetchRemoteConfigOptions): Promise<any>;
20
+ /** 写入仍为整键替换;服务端在持久化之前校验。 */
12
21
  export declare function setRemoteConfig(serverUrl: string, key: string, value: unknown, token?: string, packageId?: string, options?: RemoteClientRequestOptions): Promise<any>;
13
- /**
14
- * 删除单个远端配置键。
15
- */
16
22
  export declare function deleteRemoteConfig(serverUrl: string, key: string, token?: string, packageId?: string, options?: RemoteClientRequestOptions): Promise<any>;
17
- /**
18
- * 拉取远端配置环境变量检查结果(可定向指定包)。
19
- */
20
23
  export declare function fetchRemoteConfigEnv(serverUrl: string, token?: string, packageId?: string, options?: RemoteClientRequestOptions): Promise<any>;
@@ -1,22 +1,125 @@
1
+ import { CONFIG_SOURCES } from "../service/types.js";
2
+ import { ActionDockError, PROTOCOL_UNSUPPORTED } from "../errors.js";
3
+ import { assertConcreteConfigKey, assertValidConfigDeclarations, resolveConfigDeclaration, } from "../project/config-declarations.js";
4
+ import { redactConfigValueAtPaths, redactConfigValueForDeclarations, sanitizeConfigDefinitions, } from "../storage/mask.js";
1
5
  import { buildQueryString, fetchRemoteJson } from "./transport.js";
6
+ function isRecord(value) {
7
+ return value !== null && typeof value === "object" && !Array.isArray(value);
8
+ }
9
+ /** 判定远端响应中的 source 是否为合法 ConfigSource(含 null);合法值单一事实源为 CONFIG_SOURCES 元组。 */
10
+ function isValidConfigSource(source) {
11
+ return source === null || (typeof source === "string" && CONFIG_SOURCES.includes(source));
12
+ }
13
+ /** 在核心边界校验配置安全视图契约:来源合法、状态与值自洽,不满足即拒绝;诊断不携带配置原文。 */
14
+ function assertValidConfigValueView(item) {
15
+ if (!isRecord(item) || typeof item.key !== "string" || typeof item.configured !== "boolean" || typeof item.secret !== "boolean" ||
16
+ !isValidConfigSource(item.source) || !Array.isArray(item.redactedPaths) ||
17
+ item.redactedPaths.some((path) => typeof path !== "string")) {
18
+ throw new ActionDockError(PROTOCOL_UNSUPPORTED, "Remote configuration view violates the config view protocol: source must be one of override/package/global/env/default/null and metadata must be complete");
19
+ }
20
+ // source null 仅代表未命中:不得携带生效值或隐藏路径,也不得宣称已配置。
21
+ if (item.source === null) {
22
+ if (item.configured !== false || item.value !== undefined || item.redactedPaths.length > 0) {
23
+ throw new ActionDockError(PROTOCOL_UNSUPPORTED, `Remote configuration view for '${item.key}' declares no effective source but carries configured state, a value, or redaction paths`);
24
+ }
25
+ return;
26
+ }
27
+ // default 与未命中同样不是显式配置;显式来源必须宣称已配置。
28
+ if (item.source === "default") {
29
+ if (item.configured !== false) {
30
+ throw new ActionDockError(PROTOCOL_UNSUPPORTED, `Remote configuration view for '${item.key}' declares a default source but claims configured state`);
31
+ }
32
+ }
33
+ else if (item.configured !== true) {
34
+ throw new ActionDockError(PROTOCOL_UNSUPPORTED, `Remote configuration view for '${item.key}' declares an explicit source but claims unconfigured state`);
35
+ }
36
+ // 声明有来源就必须有实际生效值;整项隐藏可省略 value 但必须携带根隐藏路径。
37
+ if (item.value === undefined && !item.redactedPaths.includes("")) {
38
+ throw new ActionDockError(PROTOCOL_UNSUPPORTED, `Remote configuration view for '${item.key}' declares an effective source but omits both the value and the root redaction path`);
39
+ }
40
+ }
2
41
  /**
3
- * 远端配置域端点。
4
- */
5
- /**
6
- * 拉取远端配置视图(可定向指定包)。
42
+ * 在核心边界归一化配置安全视图;仅接受 configViewVersion:1 新协议。
43
+ * 旧协议无法证明来源与元数据真实性,统一抛出协议不支持错误,不猜测来源。
7
44
  */
45
+ export function normalizeRemoteConfigResponse(rawResponse, options) {
46
+ if (!rawResponse || typeof rawResponse !== "object") {
47
+ throw new ActionDockError(PROTOCOL_UNSUPPORTED, "Remote configuration response violates the config view protocol: response must be an object");
48
+ }
49
+ // 新协议门槛提前到一切声明解析之前:缺失 configViewVersion:1 视为旧服务端,
50
+ // 直接拒绝,避免旧协议因其他字段错误先报清单/参数错误。
51
+ if (rawResponse.configViewVersion !== 1) {
52
+ throw new ActionDockError(PROTOCOL_UNSUPPORTED, "Remote server did not declare configViewVersion: 1; legacy configuration responses without safe view metadata are no longer supported");
53
+ }
54
+ if (!Array.isArray(rawResponse.items)) {
55
+ throw new ActionDockError(PROTOCOL_UNSUPPORTED, "Remote configuration response is missing safe views");
56
+ }
57
+ const remoteDeclared = isRecord(rawResponse.declared) ? rawResponse.declared : {};
58
+ const matchesLocalPackage = !options?.localPackageId ||
59
+ rawResponse.packageId === options.localPackageId || options.packageId === options.localPackageId;
60
+ const localDeclared = matchesLocalPackage ? options?.localDeclarations ?? {} : {};
61
+ assertValidConfigDeclarations(remoteDeclared);
62
+ assertValidConfigDeclarations(localDeclared);
63
+ const declarationsFor = (key) => [
64
+ resolveConfigDeclaration(remoteDeclared, key)?.item,
65
+ resolveConfigDeclaration(localDeclared, key)?.item,
66
+ ].filter((item) => item !== undefined);
67
+ const items = rawResponse.items.map((item) => {
68
+ assertValidConfigValueView(item);
69
+ assertConcreteConfigKey(item.key);
70
+ // 路径只是保护策略,不是原值已经被替换的证据;先实际应用服务端路径。
71
+ const remoteSafe = redactConfigValueAtPaths(item.value, item.redactedPaths);
72
+ const declaredSafe = redactConfigValueForDeclarations(remoteSafe.value, declarationsFor(item.key));
73
+ const safe = redactConfigValueAtPaths(declaredSafe.value, [
74
+ ...remoteSafe.redactedPaths, ...declaredSafe.redactedPaths,
75
+ ]);
76
+ return {
77
+ key: item.key,
78
+ configured: item.configured,
79
+ secret: item.secret || remoteSafe.secret || declaredSafe.secret,
80
+ source: item.source,
81
+ value: safe.value,
82
+ redactedPaths: safe.redactedPaths,
83
+ };
84
+ });
85
+ // 只返回已知安全字段,避免 spread 原响应把原始别名重新带出边界。
86
+ return {
87
+ ok: rawResponse.ok ?? true,
88
+ configViewVersion: 1,
89
+ packageId: rawResponse.packageId ?? options?.packageId,
90
+ declared: sanitizeConfigDefinitions({ ...localDeclared, ...remoteDeclared }) ?? {},
91
+ items,
92
+ values: Object.fromEntries(items.map((item) => [item.key,
93
+ item.value === undefined && item.redactedPaths.includes("") ? "********" : item.value,
94
+ ])),
95
+ masked: Object.fromEntries(items.map((item) => [item.key, item.redactedPaths])),
96
+ };
97
+ }
98
+ /** 拉取远端配置;返回值与元数据均已完成安全归一化。 */
8
99
  export async function fetchRemoteConfig(serverUrl, token, packageId, options) {
9
- return fetchRemoteJson(serverUrl, `/api/v2/config${buildQueryString({ package: packageId })}`, token, {
100
+ const raw = await fetchRemoteJson(serverUrl, `/api/v2/config${buildQueryString({ package: packageId })}`, token, {
10
101
  errorPrefix: "Failed to fetch remote config",
11
102
  allowInsecureHttp: options?.allowInsecureHttp,
12
103
  insecure: options?.insecure,
13
104
  dispatcher: options?.dispatcher,
14
105
  });
106
+ return normalizeRemoteConfigResponse(raw, { ...options, packageId });
15
107
  }
16
- /**
17
- * 写入单个远端配置键值。
18
- */
108
+ /** 单键查询可解析仅由环境变量提供的模板实例;服务端必须返回同键完整单项视图。 */
109
+ export async function fetchRemoteConfigItem(serverUrl, key, token, packageId, options) {
110
+ assertConcreteConfigKey(key);
111
+ const raw = await fetchRemoteJson(serverUrl, `/api/v2/config${buildQueryString({ package: packageId, key })}`, token, { ...options, errorPrefix: "Failed to fetch remote configuration item" });
112
+ // 严格单项契约:新协议必须提供与请求键一致的完整 item;
113
+ // 真正未命中由服务端返回同键 source null 视图,不接受列表或空 items 伪装单项。
114
+ if (!raw || typeof raw !== "object" || raw.configViewVersion !== 1 ||
115
+ !isRecord(raw.item) || raw.item.key !== key) {
116
+ throw new ActionDockError(PROTOCOL_UNSUPPORTED, `Remote server did not return a complete single-item config view for key '${key}'; servers that ignore the key query parameter are no longer supported`);
117
+ }
118
+ return normalizeRemoteConfigResponse({ ...raw, items: [raw.item] }, { ...options, packageId });
119
+ }
120
+ /** 写入仍为整键替换;服务端在持久化之前校验。 */
19
121
  export async function setRemoteConfig(serverUrl, key, value, token, packageId, options) {
122
+ assertConcreteConfigKey(key);
20
123
  return fetchRemoteJson(serverUrl, "/api/v2/config", token, {
21
124
  method: "PUT",
22
125
  body: { key, value, package: packageId },
@@ -26,10 +129,8 @@ export async function setRemoteConfig(serverUrl, key, value, token, packageId, o
26
129
  dispatcher: options?.dispatcher,
27
130
  });
28
131
  }
29
- /**
30
- * 删除单个远端配置键。
31
- */
32
132
  export async function deleteRemoteConfig(serverUrl, key, token, packageId, options) {
133
+ assertConcreteConfigKey(key);
33
134
  return fetchRemoteJson(serverUrl, `/api/v2/config/${encodeURIComponent(key)}${buildQueryString({ package: packageId })}`, token, {
34
135
  method: "DELETE",
35
136
  errorPrefix: `Failed to delete remote config '${key}'`,
@@ -38,9 +139,6 @@ export async function deleteRemoteConfig(serverUrl, key, token, packageId, optio
38
139
  dispatcher: options?.dispatcher,
39
140
  });
40
141
  }
41
- /**
42
- * 拉取远端配置环境变量检查结果(可定向指定包)。
43
- */
44
142
  export async function fetchRemoteConfigEnv(serverUrl, token, packageId, options) {
45
143
  return fetchRemoteJson(serverUrl, `/api/v2/config/env${buildQueryString({ package: packageId })}`, token, {
46
144
  errorPrefix: "Failed to fetch remote config env checks",
@@ -13,4 +13,4 @@ export type { RemoteExecuteOptions, RemoteExecutionResult } from "./actions.js";
13
13
  export { fetchRemotePlaybookShow, fetchRemotePlaybooks } from "./playbooks.js";
14
14
  export { cancelRemoteRun, cleanExpiredRemoteRuns, clearRemoteRuns, fetchRemoteRun, fetchRemoteRuns, } from "./runs.js";
15
15
  export { clearRemoteState, deleteRemoteStateKey, fetchRemoteStateList, getRemoteStateKey, setRemoteStateKey, } from "./state.js";
16
- export { deleteRemoteConfig, fetchRemoteConfig, fetchRemoteConfigEnv, setRemoteConfig, } from "./config.js";
16
+ export { deleteRemoteConfig, fetchRemoteConfig, fetchRemoteConfigItem, fetchRemoteConfigEnv, setRemoteConfig, normalizeRemoteConfigResponse, type FetchRemoteConfigOptions, } from "./config.js";
@@ -17,4 +17,4 @@ export { cancelRemoteRun, cleanExpiredRemoteRuns, clearRemoteRuns, fetchRemoteRu
17
17
  // 6. 状态存储管理域
18
18
  export { clearRemoteState, deleteRemoteStateKey, fetchRemoteStateList, getRemoteStateKey, setRemoteStateKey, } from "./state.js";
19
19
  // 7. 配置管理域
20
- export { deleteRemoteConfig, fetchRemoteConfig, fetchRemoteConfigEnv, setRemoteConfig, } from "./config.js";
20
+ export { deleteRemoteConfig, fetchRemoteConfig, fetchRemoteConfigItem, fetchRemoteConfigEnv, setRemoteConfig, normalizeRemoteConfigResponse, } from "./config.js";
package/dist/errors.d.ts CHANGED
@@ -71,6 +71,10 @@ export declare const CAPABILITY_UNAVAILABLE = "CAPABILITY_UNAVAILABLE";
71
71
  export declare const STATE_KEY_NOT_FOUND = "STATE_KEY_NOT_FOUND";
72
72
  /** SQLite 数据库忙或锁定 */
73
73
  export declare const STORAGE_BUSY = "STORAGE_BUSY";
74
+ /** 所需生产依赖未就绪且当前环境不允许或不满足自动首装条件 */
75
+ export declare const DEPENDENCIES_NOT_READY = "DEPENDENCIES_NOT_READY";
76
+ /** 自动依赖安装进程启动失败、超时或非零退出 */
77
+ export declare const DEPENDENCY_INSTALL_FAILED = "DEPENDENCY_INSTALL_FAILED";
74
78
  /** 工程事务锁被其他活跃进程持有 */
75
79
  export declare const PROJECT_BUSY = "PROJECT_BUSY";
76
80
  /** 工程存在未恢复的崩溃事务,需要执行恢复流程 */
@@ -298,6 +302,14 @@ export declare const EXECUTION_CONCURRENCY_LIMIT = "EXECUTION_CONCURRENCY_LIMIT"
298
302
  export declare const PROJECT_CONFIG_NOT_FOUND = "PROJECT_CONFIG_NOT_FOUND";
299
303
  /** 项目清单加载失败 */
300
304
  export declare const MANIFEST_LOAD_FAILED = "MANIFEST_LOAD_FAILED";
305
+ /** 配置项数据值不符合声明的模式规范 */
306
+ export declare const CONFIG_VALUE_INVALID = "CONFIG_VALUE_INVALID";
307
+ /** 配置加密密钥缺失、无效或与存储域身份不符等加密配置错误 */
308
+ export declare const CONFIG_ENCRYPTION_ERROR = "CONFIG_ENCRYPTION_ERROR";
309
+ /** 配置密文解密失败(信封格式非法、版本未知、密钥身份不符或认证校验失败) */
310
+ export declare const CONFIG_DECRYPT_FAILED = "CONFIG_DECRYPT_FAILED";
311
+ /** 配置加密与解密错误按结构化错误码识别,跨模块副本也不得吞没或覆盖。 */
312
+ export declare function isConfigEncryptionError(error: unknown): boolean;
301
313
  /** 动作标识符不符合命名规范 */
302
314
  export declare const INVALID_ACTION_ID = "INVALID_ACTION_ID";
303
315
  /** 规程标识符不符合命名规范 */
@@ -348,7 +360,7 @@ export declare function resolveExecutionHint(targetRef: string, error?: {
348
360
  /**
349
361
  * 集中定义的标准结构化错误码联合类型。
350
362
  */
351
- export type ErrorCode = typeof PACKAGE_NOT_FOUND | typeof ACTION_PACKAGE_VERSION_CONFLICT | typeof ACTION_NOT_FOUND | typeof ACTION_LOAD_FAILED | typeof ACTION_FAILED | typeof ACTION_TIMEOUT | typeof ACTION_CANCELLED | typeof INPUT_VALIDATION_FAILED | typeof OUTPUT_VALIDATION_FAILED | typeof INPUT_NOT_JSON | typeof OUTPUT_NOT_JSON | typeof ACTION_SUBRUN_LIMIT | typeof ACTION_CALL_CYCLE | typeof UNDECLARED_ACTION_DEPENDENCY | typeof INVALID_ACTION_REF | typeof IDEMPOTENCY_CONFLICT | typeof EXECUTION_FAILED | typeof UNHANDLED_EXECUTION_ERROR | typeof RUN_REPOSITORY_UNAVAILABLE | typeof RUN_PERSISTENCE_FAILED | typeof STANDALONE_ASYNC_UNSUPPORTED | typeof INVOCATION_UNSUPPORTED | typeof HOST_PROCESS_EXITED | typeof EXECUTION_ABORTED | typeof TIMEOUT | typeof SERVICE_CLOSED | typeof NETWORK_ERROR | typeof INSECURE_TRANSPORT | typeof REMOTE_REQUEST_FAILED | typeof REMOTE_STREAM_UNAVAILABLE | typeof CAPABILITY_UNAVAILABLE | typeof STATE_KEY_NOT_FOUND | typeof STORAGE_BUSY | typeof PROJECT_BUSY | typeof PROJECT_RECOVERY_REQUIRED | typeof EVENT_BACKPRESSURE_LIMIT | typeof EVENT_CURSOR_EXPIRED | typeof PROCESS_OUTPUT_LIMIT | typeof PROCESS_SPAWN_ERROR | typeof PROCESS_CANCELLED | typeof PROCESS_TIMEOUT | typeof UNAUTHORIZED | typeof NOT_FOUND | typeof SERVER_ERROR | typeof BAD_REQUEST | typeof PACKAGE_FORBIDDEN | typeof ACTION_FORBIDDEN | typeof PLAYBOOK_NOT_FOUND | typeof REQUEST_TOO_LARGE | typeof ACTION_START_FAILED | typeof ACTION_EXECUTION_ERROR | typeof ACTIONS_LIST_ERROR | typeof PLAYBOOKS_LIST_ERROR | typeof RUNS_LIST_ERROR | typeof RUNS_CLEAR_ERROR | typeof INFO_ERROR | typeof PACKAGES_INFO_ERROR | typeof DOCTOR_ERROR | typeof RUN_INTERRUPTED | typeof CONFIG_ENV_ERROR | typeof CONFIG_LIST_ERROR | typeof CONFIG_SET_ERROR | typeof CONFIG_DELETE_ERROR | typeof STATE_LIST_ERROR | typeof STATE_CLEAR_ERROR | typeof STATE_KEY_ERROR | typeof DATA_DIR_IN_USE | typeof DATA_DIR_RECOVERY_REQUIRED | typeof UNSUPPORTED_STORAGE_SCHEMA | typeof STORED_ERROR_DECODE_FAILED | typeof PROCESS_FAILED | typeof GENERATED_TYPES_OUTDATED | typeof PROTOCOL_UNSUPPORTED | typeof SERVICE_RESULT_UNKNOWN | typeof MCP_TOOL_NAME_COLLISION | typeof ACCESS_DENIED | typeof UNSUPPORTED_CAPABILITY | typeof CONTROL_BUSY | typeof CONTROL_EXPIRED | typeof CONTROL_REVOKED | typeof PROCESS_QUARANTINED | typeof PROCESS_LOST | typeof REQUEST_CONFLICT | typeof INPUT_OUTCOME_UNKNOWN | typeof OUTPUT_GAP | typeof OUTPUT_UNAVAILABLE | typeof INVALID_CURSOR | typeof QUEUE_FULL | typeof QUOTA_EXCEEDED | typeof INPUT_CLOSED | typeof INVALID_FLAT_ARGUMENT | typeof INVALID_JSON | typeof INVALID_JSON_LITERAL | typeof INPUT_PATH_CONFLICT | typeof FLAT_INPUT_LIMIT_EXCEEDED | typeof INPUT_LIMIT_EXCEEDED | typeof INPUT_POLICY_VIOLATION | typeof INPUT_CONFLICT | typeof INPUT_FILE_NOT_FOUND | typeof INPUT_FILE_READ_FAILED | typeof INVALID_ARGUMENT | typeof PACKAGE_NOT_ALLOWED | typeof INVALID_PACKAGE_ID | typeof PATH_TRAVERSAL | typeof AMBIGUOUS_STATE_KEY | typeof RUN_NOT_FOUND | typeof RUN_ALREADY_FINISHED | typeof IPC_ERROR | typeof SERVICE_ERROR | typeof PROFILE_NOT_FOUND | typeof LOCKFILE_READ_FAILED | typeof LOCKFILE_CORRUPTED | typeof LOCKFILE_INVALID | typeof UNSUPPORTED_LOCKFILE_VERSION | typeof MANIFEST_READ_FAILED | typeof MANIFEST_CORRUPTED | typeof MANIFEST_INVALID | typeof UNSUPPORTED_MANIFEST_SCHEMA | typeof MANIFEST_NOT_FOUND | typeof MANIFEST_DIGEST_MISMATCH | typeof REGISTRY_CORRUPTED | typeof ASYNC_TRANSACTION_UNSUPPORTED | typeof STORAGE_CLOSED | typeof PACKAGE_ID_CONFLICT | typeof INVALID_PATH | typeof STORAGE_INIT_FAILED | typeof INVALID_STATE | typeof PROCESS_NOT_FOUND | typeof MODULE_RESOLVE_FAILED | typeof EXECUTION_CONCURRENCY_LIMIT | typeof PROJECT_CONFIG_NOT_FOUND | typeof MANIFEST_LOAD_FAILED | typeof INVALID_ACTION_ID | typeof INVALID_PLAYBOOK_ID | typeof PROJECT_ROOT_NOT_FOUND;
363
+ export type ErrorCode = typeof PACKAGE_NOT_FOUND | typeof ACTION_PACKAGE_VERSION_CONFLICT | typeof ACTION_NOT_FOUND | typeof ACTION_LOAD_FAILED | typeof ACTION_FAILED | typeof ACTION_TIMEOUT | typeof ACTION_CANCELLED | typeof INPUT_VALIDATION_FAILED | typeof OUTPUT_VALIDATION_FAILED | typeof INPUT_NOT_JSON | typeof OUTPUT_NOT_JSON | typeof ACTION_SUBRUN_LIMIT | typeof ACTION_CALL_CYCLE | typeof UNDECLARED_ACTION_DEPENDENCY | typeof INVALID_ACTION_REF | typeof IDEMPOTENCY_CONFLICT | typeof EXECUTION_FAILED | typeof UNHANDLED_EXECUTION_ERROR | typeof RUN_REPOSITORY_UNAVAILABLE | typeof RUN_PERSISTENCE_FAILED | typeof STANDALONE_ASYNC_UNSUPPORTED | typeof INVOCATION_UNSUPPORTED | typeof HOST_PROCESS_EXITED | typeof EXECUTION_ABORTED | typeof TIMEOUT | typeof SERVICE_CLOSED | typeof NETWORK_ERROR | typeof INSECURE_TRANSPORT | typeof REMOTE_REQUEST_FAILED | typeof REMOTE_STREAM_UNAVAILABLE | typeof CAPABILITY_UNAVAILABLE | typeof STATE_KEY_NOT_FOUND | typeof STORAGE_BUSY | typeof DEPENDENCIES_NOT_READY | typeof DEPENDENCY_INSTALL_FAILED | typeof PROJECT_BUSY | typeof PROJECT_RECOVERY_REQUIRED | typeof EVENT_BACKPRESSURE_LIMIT | typeof EVENT_CURSOR_EXPIRED | typeof PROCESS_OUTPUT_LIMIT | typeof PROCESS_SPAWN_ERROR | typeof PROCESS_CANCELLED | typeof PROCESS_TIMEOUT | typeof UNAUTHORIZED | typeof NOT_FOUND | typeof SERVER_ERROR | typeof BAD_REQUEST | typeof PACKAGE_FORBIDDEN | typeof ACTION_FORBIDDEN | typeof PLAYBOOK_NOT_FOUND | typeof REQUEST_TOO_LARGE | typeof ACTION_START_FAILED | typeof ACTION_EXECUTION_ERROR | typeof ACTIONS_LIST_ERROR | typeof PLAYBOOKS_LIST_ERROR | typeof RUNS_LIST_ERROR | typeof RUNS_CLEAR_ERROR | typeof INFO_ERROR | typeof PACKAGES_INFO_ERROR | typeof DOCTOR_ERROR | typeof RUN_INTERRUPTED | typeof CONFIG_ENV_ERROR | typeof CONFIG_LIST_ERROR | typeof CONFIG_SET_ERROR | typeof CONFIG_DELETE_ERROR | typeof STATE_LIST_ERROR | typeof STATE_CLEAR_ERROR | typeof STATE_KEY_ERROR | typeof DATA_DIR_IN_USE | typeof DATA_DIR_RECOVERY_REQUIRED | typeof UNSUPPORTED_STORAGE_SCHEMA | typeof STORED_ERROR_DECODE_FAILED | typeof PROCESS_FAILED | typeof GENERATED_TYPES_OUTDATED | typeof PROTOCOL_UNSUPPORTED | typeof SERVICE_RESULT_UNKNOWN | typeof MCP_TOOL_NAME_COLLISION | typeof ACCESS_DENIED | typeof UNSUPPORTED_CAPABILITY | typeof CONTROL_BUSY | typeof CONTROL_EXPIRED | typeof CONTROL_REVOKED | typeof PROCESS_QUARANTINED | typeof PROCESS_LOST | typeof REQUEST_CONFLICT | typeof INPUT_OUTCOME_UNKNOWN | typeof OUTPUT_GAP | typeof OUTPUT_UNAVAILABLE | typeof INVALID_CURSOR | typeof QUEUE_FULL | typeof QUOTA_EXCEEDED | typeof INPUT_CLOSED | typeof INVALID_FLAT_ARGUMENT | typeof INVALID_JSON | typeof INVALID_JSON_LITERAL | typeof INPUT_PATH_CONFLICT | typeof FLAT_INPUT_LIMIT_EXCEEDED | typeof INPUT_LIMIT_EXCEEDED | typeof INPUT_POLICY_VIOLATION | typeof INPUT_CONFLICT | typeof INPUT_FILE_NOT_FOUND | typeof INPUT_FILE_READ_FAILED | typeof INVALID_ARGUMENT | typeof PACKAGE_NOT_ALLOWED | typeof INVALID_PACKAGE_ID | typeof PATH_TRAVERSAL | typeof AMBIGUOUS_STATE_KEY | typeof RUN_NOT_FOUND | typeof RUN_ALREADY_FINISHED | typeof IPC_ERROR | typeof SERVICE_ERROR | typeof PROFILE_NOT_FOUND | typeof LOCKFILE_READ_FAILED | typeof LOCKFILE_CORRUPTED | typeof LOCKFILE_INVALID | typeof UNSUPPORTED_LOCKFILE_VERSION | typeof MANIFEST_READ_FAILED | typeof MANIFEST_CORRUPTED | typeof MANIFEST_INVALID | typeof UNSUPPORTED_MANIFEST_SCHEMA | typeof MANIFEST_NOT_FOUND | typeof MANIFEST_DIGEST_MISMATCH | typeof REGISTRY_CORRUPTED | typeof ASYNC_TRANSACTION_UNSUPPORTED | typeof STORAGE_CLOSED | typeof PACKAGE_ID_CONFLICT | typeof INVALID_PATH | typeof STORAGE_INIT_FAILED | typeof INVALID_STATE | typeof PROCESS_NOT_FOUND | typeof MODULE_RESOLVE_FAILED | typeof EXECUTION_CONCURRENCY_LIMIT | typeof PROJECT_CONFIG_NOT_FOUND | typeof MANIFEST_LOAD_FAILED | typeof CONFIG_VALUE_INVALID | typeof CONFIG_ENCRYPTION_ERROR | typeof CONFIG_DECRYPT_FAILED | typeof INVALID_ACTION_ID | typeof INVALID_PLAYBOOK_ID | typeof PROJECT_ROOT_NOT_FOUND;
352
364
  /** 全仓统一错误码类型别名 */
353
365
  export type ActionDockErrorCode = ErrorCode;
354
366
  /**
package/dist/errors.js CHANGED
@@ -71,6 +71,10 @@ export const CAPABILITY_UNAVAILABLE = "CAPABILITY_UNAVAILABLE";
71
71
  export const STATE_KEY_NOT_FOUND = "STATE_KEY_NOT_FOUND";
72
72
  /** SQLite 数据库忙或锁定 */
73
73
  export const STORAGE_BUSY = "STORAGE_BUSY";
74
+ /** 所需生产依赖未就绪且当前环境不允许或不满足自动首装条件 */
75
+ export const DEPENDENCIES_NOT_READY = "DEPENDENCIES_NOT_READY";
76
+ /** 自动依赖安装进程启动失败、超时或非零退出 */
77
+ export const DEPENDENCY_INSTALL_FAILED = "DEPENDENCY_INSTALL_FAILED";
74
78
  /** 工程事务锁被其他活跃进程持有 */
75
79
  export const PROJECT_BUSY = "PROJECT_BUSY";
76
80
  /** 工程存在未恢复的崩溃事务,需要执行恢复流程 */
@@ -299,6 +303,21 @@ export const EXECUTION_CONCURRENCY_LIMIT = "EXECUTION_CONCURRENCY_LIMIT";
299
303
  export const PROJECT_CONFIG_NOT_FOUND = "PROJECT_CONFIG_NOT_FOUND";
300
304
  /** 项目清单加载失败 */
301
305
  export const MANIFEST_LOAD_FAILED = "MANIFEST_LOAD_FAILED";
306
+ /** 配置项数据值不符合声明的模式规范 */
307
+ export const CONFIG_VALUE_INVALID = "CONFIG_VALUE_INVALID";
308
+ /** 配置加密密钥缺失、无效或与存储域身份不符等加密配置错误 */
309
+ export const CONFIG_ENCRYPTION_ERROR = "CONFIG_ENCRYPTION_ERROR";
310
+ /** 配置密文解密失败(信封格式非法、版本未知、密钥身份不符或认证校验失败) */
311
+ export const CONFIG_DECRYPT_FAILED = "CONFIG_DECRYPT_FAILED";
312
+ const CONFIG_ENCRYPTION_ERROR_CODES = new Set([
313
+ CONFIG_ENCRYPTION_ERROR,
314
+ CONFIG_DECRYPT_FAILED,
315
+ ]);
316
+ /** 配置加密与解密错误按结构化错误码识别,跨模块副本也不得吞没或覆盖。 */
317
+ export function isConfigEncryptionError(error) {
318
+ const code = error?.code;
319
+ return typeof code === "string" && CONFIG_ENCRYPTION_ERROR_CODES.has(code);
320
+ }
302
321
  /** 动作标识符不符合命名规范 */
303
322
  export const INVALID_ACTION_ID = "INVALID_ACTION_ID";
304
323
  /** 规程标识符不符合命名规范 */
@@ -372,6 +391,12 @@ export function resolveExecutionHint(targetRef, error) {
372
391
  if (error.code === ACTION_TIMEOUT) {
373
392
  return "Tip: Increase timeout via '--timeout <duration>', or run in background via '--async' and track with 'ad runs show <runId>'.";
374
393
  }
394
+ if (error.code === DEPENDENCIES_NOT_READY) {
395
+ return error.hint || error.details?.hint || "Tip: Install missing dependencies using 'npm install' or 'bun install'.";
396
+ }
397
+ if (error.code === DEPENDENCY_INSTALL_FAILED) {
398
+ return error.hint || error.details?.hint || "Tip: Check error output above and try running the package manager manually.";
399
+ }
375
400
  if (error.hint && typeof error.hint === "string") {
376
401
  return error.hint;
377
402
  }
@@ -1,4 +1,5 @@
1
1
  import { existsSync } from "node:fs";
2
+ import { createActionCallKey } from "../invocation/policy.js";
2
3
  import { parseActionRef } from "../catalog/resolve-action.js";
3
4
  import { computeDigest } from "../project/digest.js";
4
5
  import { loadActions, loadProjectConfig } from "../project/loader.js";
@@ -265,7 +266,7 @@ export class DefaultExecutionService {
265
266
  const finalizer = createRunFinalizer(this.storage, runId);
266
267
  // 调用栈快照跟踪
267
268
  const callStack = context.callStack ? [...context.callStack] : [];
268
- const callKey = targetPackageId ? `${targetPackageId}/${targetActionId}` : targetActionId;
269
+ const callKey = createActionCallKey(targetActionId, targetPackageId, context.targetScope);
269
270
  const lastStackItem = callStack[callStack.length - 1];
270
271
  const isAlreadyAtTop = lastStackItem === callKey ||
271
272
  (targetActionId && lastStackItem === targetActionId) ||
@@ -288,7 +289,18 @@ export class DefaultExecutionService {
288
289
  }
289
290
  }
290
291
  if (typeof context.timeoutMs === "number" && context.timeoutMs > 0) {
291
- finalizer.startTimeout(controller, context.timeoutMs);
292
+ if (context.deadline !== undefined) {
293
+ const remainingMs = Math.max(0, context.deadline - Date.now());
294
+ if (remainingMs <= 0) {
295
+ controller.abort(new ActionDockError(ACTION_TIMEOUT, `Action exceeded timeout of ${context.initialTimeoutMs ?? context.timeoutMs}ms`, { timeoutMs: context.initialTimeoutMs ?? context.timeoutMs }));
296
+ }
297
+ else {
298
+ finalizer.startTimeout(controller, remainingMs, context.initialTimeoutMs ?? context.timeoutMs);
299
+ }
300
+ }
301
+ else {
302
+ finalizer.startTimeout(controller, context.timeoutMs, context.initialTimeoutMs);
303
+ }
292
304
  }
293
305
  const effectiveOwner = context.owner ||
294
306
  createDefaultProcessOwner({
@@ -312,7 +324,7 @@ export class DefaultExecutionService {
312
324
  owner: effectiveOwner,
313
325
  progress: bridge.progressReporter,
314
326
  logger: bridge.executionLogger,
315
- onActionInvoke: (childAction, childInput, parentRunId) => this.invokeChildAction({
327
+ onActionInvoke: (childAction, childInput, parentRunId, options) => this.invokeChildAction({
316
328
  controller,
317
329
  rootRunId,
318
330
  childAction,
@@ -324,6 +336,8 @@ export class DefaultExecutionService {
324
336
  context,
325
337
  effectiveProcess,
326
338
  effectiveOwner,
339
+ logger: bridge.executionLogger,
340
+ options,
327
341
  }),
328
342
  });
329
343
  const executionPromise = this.raceExecution({
@@ -423,6 +437,8 @@ export class DefaultExecutionService {
423
437
  package: opts.package || this.identity,
424
438
  signal: opts.signal,
425
439
  timeoutMs: opts.timeoutMs,
440
+ initialTimeoutMs: opts.initialTimeoutMs,
441
+ deadline: opts.deadline,
426
442
  maxCallDepth: opts.maxCallDepth,
427
443
  config: opts.config || opts.configOverrides,
428
444
  tenantId: opts.tenantId || opts.owner?.tenantId,
@@ -480,20 +496,36 @@ export class DefaultExecutionService {
480
496
  };
481
497
  }
482
498
  catch (err) {
483
- return this.classifyExecutionError(err, runId, context.timeoutMs, controller, finalizer);
499
+ return this.classifyExecutionError(err, runId, context, controller, finalizer);
484
500
  }
485
501
  }
486
- classifyExecutionError(err, runId, timeoutMs, controller, finalizer) {
502
+ classifyExecutionError(err, runId, context, controller, finalizer) {
503
+ const timeoutBudget = context.initialTimeoutMs ?? context.timeoutMs;
487
504
  if (finalizer.isTimeout) {
488
505
  const error = {
489
506
  code: ACTION_TIMEOUT,
490
- message: `Action exceeded timeout of ${timeoutMs}ms`,
507
+ message: `Action exceeded timeout of ${timeoutBudget}ms`,
491
508
  };
492
509
  finalizer.finalize("timed_out", undefined, error);
493
510
  return { ok: false, runId, error: finalizer.persistError || error };
494
511
  }
495
512
  if (controller.signal.aborted) {
496
513
  const reason = controller.signal.reason;
514
+ const reasonCode = reason?.code;
515
+ const isTimeoutReason = reasonCode === ACTION_TIMEOUT ||
516
+ (reason?.details && reason.details.code === ACTION_TIMEOUT) ||
517
+ (reason instanceof Error && reason.message?.includes("exceeded timeout")) ||
518
+ (typeof reason === "string" && reason.includes("exceeded timeout"));
519
+ if (isTimeoutReason) {
520
+ const error = {
521
+ code: ACTION_TIMEOUT,
522
+ message: (reason instanceof Error && reason.message?.includes("exceeded timeout"))
523
+ ? reason.message
524
+ : `Action exceeded timeout of ${timeoutBudget}ms`,
525
+ };
526
+ finalizer.finalize("timed_out", undefined, error);
527
+ return { ok: false, runId, error: finalizer.persistError || error };
528
+ }
497
529
  const reasonMsg = reason instanceof Error
498
530
  ? reason.message
499
531
  : typeof reason === "string"
@@ -520,7 +552,7 @@ export class DefaultExecutionService {
520
552
  };
521
553
  }
522
554
  async invokeChildAction(args) {
523
- const { controller, rootRunId, childAction, childInput, parentRunId, currentActionId, currentAction, callStack, context, effectiveProcess, effectiveOwner, } = args;
555
+ const { controller, rootRunId, childAction, childInput, parentRunId, currentActionId, currentAction, callStack, context, effectiveProcess, effectiveOwner, logger, options, } = args;
524
556
  const invoker = this.actionInvoker;
525
557
  if (!invoker) {
526
558
  throw new ActionDockError(INVOCATION_UNSUPPORTED, "Nested action invocation requires a Host ActionInvoker");
@@ -541,18 +573,20 @@ export class DefaultExecutionService {
541
573
  package: this.identity,
542
574
  signal: controller.signal,
543
575
  timeoutMs: context.timeoutMs,
576
+ initialTimeoutMs: context.initialTimeoutMs,
577
+ deadline: context.deadline,
544
578
  maxCallDepth: context.maxCallDepth,
545
579
  config: context.config,
546
580
  tenantId: effectiveOwner.tenantId,
547
581
  principalId: effectiveOwner.principalId,
548
582
  hostSessionId: context.hostSessionId || this.hostSessionId,
549
- logger: context.logger,
583
+ logger: logger ?? context.logger,
550
584
  progress: context.progress,
551
585
  process: effectiveProcess,
552
586
  owner: effectiveOwner,
553
587
  origin: context.origin,
554
588
  };
555
- return await invoker(childAction, childInput, invocationContext);
589
+ return await invoker(childAction, childInput, invocationContext, options);
556
590
  }
557
591
  async checkIdempotencyGate(input, context, actionRef, effectiveClock) {
558
592
  if (!context.requestId) {
@@ -561,7 +595,7 @@ export class DefaultExecutionService {
561
595
  const digestPayload = {
562
596
  input,
563
597
  config: context.config,
564
- timeoutMs: context.timeoutMs,
598
+ timeoutMs: context.initialTimeoutMs ?? context.timeoutMs,
565
599
  };
566
600
  const inputDigest = computeDigest(digestPayload);
567
601
  const provisionalRunId = crypto.randomUUID();
@@ -1,4 +1,4 @@
1
- import type { ActionDefinition, ActionRef, ExecutionEvent, ExecutionResult, JsonValue, Logger, ProcessAPI, RunRecord, RunStatus } from "@actiondock/sdk";
1
+ import type { ActionDefinition, ActionInvokeOptions, ActionRef, ExecutionEvent, ExecutionResult, JsonValue, Logger, ProcessAPI, RunRecord, RunStatus } from "@actiondock/sdk";
2
2
  import type { ProjectConfig } from "../project/types.js";
3
3
  import type { Clock } from "../storage/clock.js";
4
4
  import type { EventSink } from "../runtime/events.js";
@@ -6,7 +6,7 @@ import type { RuntimeStorage } from "../storage/types.js";
6
6
  import type { ModuleLoader } from "../platform/module-loader.js";
7
7
  import { type PackageIdentity, type RunOptions, type InvocationContext, createInvocationContext, createRootInvocationContext } from "../invocation/types.js";
8
8
  export { createInvocationContext, createRootInvocationContext };
9
- export type { PackageIdentity, RunOptions, InvocationContext };
9
+ export type { PackageIdentity, RunOptions, InvocationContext, ActionInvokeOptions };
10
10
  /**
11
11
  * 局部动作解析器委托函数契约(仅限当前包内部动作)。
12
12
  */
@@ -29,7 +29,7 @@ export interface ExecutionHandle {
29
29
  /**
30
30
  * 跨包动作调用委托函数。
31
31
  */
32
- export type ActionInvoker = (childAction: ActionRef | string, childInput: unknown, context: InvocationContext) => Promise<unknown>;
32
+ export type ActionInvoker = (childAction: ActionRef | string, childInput: unknown, context: InvocationContext, options?: ActionInvokeOptions) => Promise<unknown>;
33
33
  /**
34
34
  * 统一执行协调服务配置选项。
35
35
  */
@@ -9,13 +9,20 @@ import type { StateEntry } from "../storage/types.js";
9
9
  export declare class DefaultActionDockHost implements ActionDockHost {
10
10
  readonly hostSessionId: string;
11
11
  readonly options: ActionDockHostOptions;
12
+ readonly allowInstall?: boolean;
12
13
  private runtimes;
14
+ private extraRuntimes;
15
+ private extraRuntimeScopes;
13
16
  readonly policy: InvocationPolicy;
14
17
  private hostPublicPackageIds;
15
18
  private maxCallDepth;
16
19
  private maxSubRuns;
17
20
  private eventSink;
18
21
  private isClosed;
22
+ private readonly prepareLocalPackage?;
23
+ private readonly closeController;
24
+ private readonly activePreparations;
25
+ private closePromise?;
19
26
  private dataDirLock?;
20
27
  private failedLinkedPackages;
21
28
  private failedAutoLoad?;
@@ -26,6 +33,9 @@ export declare class DefaultActionDockHost implements ActionDockHost {
26
33
  private globalStorage?;
27
34
  private initPromise?;
28
35
  private isInitialized;
36
+ private readonly actionBindings;
37
+ private readonly remoteTargets;
38
+ private readonly remoteInvoker;
29
39
  readonly discovery: DiscoveryPort;
30
40
  readonly execution: ExecutionPort;
31
41
  readonly runs: RunsPort;
@@ -60,6 +70,8 @@ export declare class DefaultActionDockHost implements ActionDockHost {
60
70
  * 外部注入的 Runtime 保持既有生命周期约定,不在此预热。
61
71
  */
62
72
  private prewarmManagedRuntimes;
73
+ /** 返回的 Runtime 由 Host 统一接管,端口只清理自身缓存和附属资源。 */
74
+ private closeInvocationTargets;
63
75
  /**
64
76
  * 异步安全回滚初始化失败时所占用的资源。
65
77
  */
@@ -106,6 +118,12 @@ export declare class DefaultActionDockHost implements ActionDockHost {
106
118
  describePlaybook(id: string): Promise<PlaybookSpec>;
107
119
  runAction(ref: ActionRef | string, input: JsonValue, options?: RunOptions): Promise<ExecutionResult>;
108
120
  startAction(ref: ActionRef | string, input: JsonValue, options?: RunOptions): Promise<ExecutionTicket>;
121
+ /**
122
+ * 私有本地 Action 调度中枢。
123
+ * 统一处理本地已授权目标的准备(若已注入 prepareLocalPackage 且存在物理包根路径)、
124
+ * 中断与关闭复核,并分发至目标 Runtime 的 startInvocation。
125
+ */
126
+ private dispatchLocalInvocation;
109
127
  getRun(runId: string, signal?: AbortSignal): Promise<RunRecord | undefined>;
110
128
  listRuns(query?: ListRunsOptions, signal?: AbortSignal): Promise<RunRecord[]>;
111
129
  countRuns(query?: ListRunsOptions, signal?: AbortSignal): Promise<number>;
@@ -120,7 +138,8 @@ export declare class DefaultActionDockHost implements ActionDockHost {
120
138
  cancelRun(runId: string, reason?: string): Promise<CancelResult>;
121
139
  private subscribeEvents;
122
140
  private getGlobalStorage;
123
- private findDeclaredConfigItem;
141
+ private findAllDeclaredConfigItems;
142
+ private protectGlobalConfigView;
124
143
  private resolveRuntime;
125
144
  /**
126
145
  * 解析目标包运行时:未命中时抛出统一的包未找到错误。