@actiondock/core 2.19.0 → 2.20.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 (66) 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 +3 -1
  6. package/dist/errors.js +2 -0
  7. package/dist/execution/service.js +8 -5
  8. package/dist/execution/types.d.ts +3 -3
  9. package/dist/host/host.d.ts +9 -1
  10. package/dist/host/host.js +183 -38
  11. package/dist/host/types.d.ts +3 -0
  12. package/dist/index.d.ts +4 -3
  13. package/dist/index.js +1 -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 +2 -0
  25. package/dist/invocation/types.js +1 -0
  26. package/dist/package/index.d.ts +1 -1
  27. package/dist/package/runtime.js +31 -12
  28. package/dist/platform/types.d.ts +48 -1
  29. package/dist/project/config-declarations.d.ts +61 -0
  30. package/dist/project/config-declarations.js +297 -0
  31. package/dist/project/index.d.ts +5 -2
  32. package/dist/project/index.js +5 -2
  33. package/dist/project/init.js +2 -2
  34. package/dist/project/loader.js +4 -0
  35. package/dist/project/manifest.js +10 -0
  36. package/dist/project/types.d.ts +30 -0
  37. package/dist/runtime/context.d.ts +6 -3
  38. package/dist/runtime/context.js +60 -13
  39. package/dist/runtime/env.js +15 -1
  40. package/dist/runtime/standalone-commands.d.ts +2 -2
  41. package/dist/runtime/standalone-commands.js +113 -47
  42. package/dist/runtime/standalone-help.d.ts +1 -0
  43. package/dist/runtime/standalone-help.js +15 -9
  44. package/dist/runtime/standalone.js +2 -2
  45. package/dist/server/policy.d.ts +24 -107
  46. package/dist/server/policy.js +134 -291
  47. package/dist/server/routes/actions.js +10 -8
  48. package/dist/server/routes/common.d.ts +5 -20
  49. package/dist/server/routes/common.js +22 -58
  50. package/dist/server/routes/config.js +65 -7
  51. package/dist/server/routes/doctor.d.ts +1 -0
  52. package/dist/server/routes/doctor.js +4 -3
  53. package/dist/server/routes/info.js +100 -13
  54. package/dist/server/routes/playbooks.js +1 -3
  55. package/dist/server/routes/runs.js +96 -18
  56. package/dist/server/server.js +25 -53
  57. package/dist/server/types.d.ts +6 -6
  58. package/dist/service/factory.js +1 -0
  59. package/dist/service/remote.js +14 -29
  60. package/dist/service/types.d.ts +20 -5
  61. package/dist/service/types.js +8 -0
  62. package/dist/storage/mask.d.ts +33 -6
  63. package/dist/storage/mask.js +298 -16
  64. package/dist/version.d.ts +1 -1
  65. package/dist/version.js +1 -1
  66. 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
@@ -298,6 +298,8 @@ export declare const EXECUTION_CONCURRENCY_LIMIT = "EXECUTION_CONCURRENCY_LIMIT"
298
298
  export declare const PROJECT_CONFIG_NOT_FOUND = "PROJECT_CONFIG_NOT_FOUND";
299
299
  /** 项目清单加载失败 */
300
300
  export declare const MANIFEST_LOAD_FAILED = "MANIFEST_LOAD_FAILED";
301
+ /** 配置项数据值不符合声明的模式规范 */
302
+ export declare const CONFIG_VALUE_INVALID = "CONFIG_VALUE_INVALID";
301
303
  /** 动作标识符不符合命名规范 */
302
304
  export declare const INVALID_ACTION_ID = "INVALID_ACTION_ID";
303
305
  /** 规程标识符不符合命名规范 */
@@ -348,7 +350,7 @@ export declare function resolveExecutionHint(targetRef: string, error?: {
348
350
  /**
349
351
  * 集中定义的标准结构化错误码联合类型。
350
352
  */
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;
353
+ 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 CONFIG_VALUE_INVALID | typeof INVALID_ACTION_ID | typeof INVALID_PLAYBOOK_ID | typeof PROJECT_ROOT_NOT_FOUND;
352
354
  /** 全仓统一错误码类型别名 */
353
355
  export type ActionDockErrorCode = ErrorCode;
354
356
  /**
package/dist/errors.js CHANGED
@@ -299,6 +299,8 @@ export const EXECUTION_CONCURRENCY_LIMIT = "EXECUTION_CONCURRENCY_LIMIT";
299
299
  export const PROJECT_CONFIG_NOT_FOUND = "PROJECT_CONFIG_NOT_FOUND";
300
300
  /** 项目清单加载失败 */
301
301
  export const MANIFEST_LOAD_FAILED = "MANIFEST_LOAD_FAILED";
302
+ /** 配置项数据值不符合声明的模式规范 */
303
+ export const CONFIG_VALUE_INVALID = "CONFIG_VALUE_INVALID";
302
304
  /** 动作标识符不符合命名规范 */
303
305
  export const INVALID_ACTION_ID = "INVALID_ACTION_ID";
304
306
  /** 规程标识符不符合命名规范 */
@@ -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) ||
@@ -312,7 +313,7 @@ export class DefaultExecutionService {
312
313
  owner: effectiveOwner,
313
314
  progress: bridge.progressReporter,
314
315
  logger: bridge.executionLogger,
315
- onActionInvoke: (childAction, childInput, parentRunId) => this.invokeChildAction({
316
+ onActionInvoke: (childAction, childInput, parentRunId, options) => this.invokeChildAction({
316
317
  controller,
317
318
  rootRunId,
318
319
  childAction,
@@ -324,6 +325,8 @@ export class DefaultExecutionService {
324
325
  context,
325
326
  effectiveProcess,
326
327
  effectiveOwner,
328
+ logger: bridge.executionLogger,
329
+ options,
327
330
  }),
328
331
  });
329
332
  const executionPromise = this.raceExecution({
@@ -520,7 +523,7 @@ export class DefaultExecutionService {
520
523
  };
521
524
  }
522
525
  async invokeChildAction(args) {
523
- const { controller, rootRunId, childAction, childInput, parentRunId, currentActionId, currentAction, callStack, context, effectiveProcess, effectiveOwner, } = args;
526
+ const { controller, rootRunId, childAction, childInput, parentRunId, currentActionId, currentAction, callStack, context, effectiveProcess, effectiveOwner, logger, options, } = args;
524
527
  const invoker = this.actionInvoker;
525
528
  if (!invoker) {
526
529
  throw new ActionDockError(INVOCATION_UNSUPPORTED, "Nested action invocation requires a Host ActionInvoker");
@@ -546,13 +549,13 @@ export class DefaultExecutionService {
546
549
  tenantId: effectiveOwner.tenantId,
547
550
  principalId: effectiveOwner.principalId,
548
551
  hostSessionId: context.hostSessionId || this.hostSessionId,
549
- logger: context.logger,
552
+ logger: logger ?? context.logger,
550
553
  progress: context.progress,
551
554
  process: effectiveProcess,
552
555
  owner: effectiveOwner,
553
556
  origin: context.origin,
554
557
  };
555
- return await invoker(childAction, childInput, invocationContext);
558
+ return await invoker(childAction, childInput, invocationContext, options);
556
559
  }
557
560
  async checkIdempotencyGate(input, context, actionRef, effectiveClock) {
558
561
  if (!context.requestId) {
@@ -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
  */
@@ -10,6 +10,8 @@ export declare class DefaultActionDockHost implements ActionDockHost {
10
10
  readonly hostSessionId: string;
11
11
  readonly options: ActionDockHostOptions;
12
12
  private runtimes;
13
+ private extraRuntimes;
14
+ private extraRuntimeScopes;
13
15
  readonly policy: InvocationPolicy;
14
16
  private hostPublicPackageIds;
15
17
  private maxCallDepth;
@@ -26,6 +28,9 @@ export declare class DefaultActionDockHost implements ActionDockHost {
26
28
  private globalStorage?;
27
29
  private initPromise?;
28
30
  private isInitialized;
31
+ private readonly actionBindings;
32
+ private readonly remoteTargets;
33
+ private readonly remoteInvoker;
29
34
  readonly discovery: DiscoveryPort;
30
35
  readonly execution: ExecutionPort;
31
36
  readonly runs: RunsPort;
@@ -60,6 +65,8 @@ export declare class DefaultActionDockHost implements ActionDockHost {
60
65
  * 外部注入的 Runtime 保持既有生命周期约定,不在此预热。
61
66
  */
62
67
  private prewarmManagedRuntimes;
68
+ /** 返回的 Runtime 由 Host 统一接管,端口只清理自身缓存和附属资源。 */
69
+ private closeInvocationTargets;
63
70
  /**
64
71
  * 异步安全回滚初始化失败时所占用的资源。
65
72
  */
@@ -120,7 +127,8 @@ export declare class DefaultActionDockHost implements ActionDockHost {
120
127
  cancelRun(runId: string, reason?: string): Promise<CancelResult>;
121
128
  private subscribeEvents;
122
129
  private getGlobalStorage;
123
- private findDeclaredConfigItem;
130
+ private findAllDeclaredConfigItems;
131
+ private protectGlobalConfigView;
124
132
  private resolveRuntime;
125
133
  /**
126
134
  * 解析目标包运行时:未命中时抛出统一的包未找到错误。