@actiondock/core 2.6.0 → 2.8.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 (268) hide show
  1. package/README.md +61 -68
  2. package/dist/catalog/action-catalog.d.ts +56 -0
  3. package/dist/catalog/action-catalog.js +202 -0
  4. package/dist/catalog/discovery.d.ts +60 -0
  5. package/dist/catalog/discovery.js +119 -0
  6. package/dist/catalog/graph.d.ts +190 -0
  7. package/dist/catalog/graph.js +589 -0
  8. package/dist/catalog/index.d.ts +5 -5
  9. package/dist/catalog/index.js +5 -5
  10. package/dist/catalog/resolve-action.d.ts +43 -0
  11. package/dist/catalog/resolve-action.js +119 -0
  12. package/dist/catalog/resolve-playbook.d.ts +26 -0
  13. package/dist/catalog/resolve-playbook.js +114 -0
  14. package/dist/doctor/checks/project.js +27 -8
  15. package/dist/doctor/checks/registry.js +2 -2
  16. package/dist/doctor/checks/runtime.js +34 -1
  17. package/dist/errors.d.ts +122 -10
  18. package/dist/errors.js +123 -10
  19. package/dist/execution/service.d.ts +18 -16
  20. package/dist/execution/service.js +183 -252
  21. package/dist/execution/types.d.ts +25 -69
  22. package/dist/execution/types.js +2 -1
  23. package/dist/filter/intent.d.ts +8 -9
  24. package/dist/filter/intent.js +49 -10
  25. package/dist/graph/index.d.ts +4 -0
  26. package/dist/graph/index.js +4 -0
  27. package/dist/host/host.d.ts +74 -32
  28. package/dist/host/host.js +585 -336
  29. package/dist/host/routing.d.ts +15 -48
  30. package/dist/host/routing.js +90 -153
  31. package/dist/host/types.d.ts +50 -17
  32. package/dist/index.d.ts +21 -22
  33. package/dist/index.js +19 -21
  34. package/dist/input/advice.d.ts +104 -0
  35. package/dist/input/advice.js +716 -0
  36. package/dist/input/describe.d.ts +106 -0
  37. package/dist/input/describe.js +176 -0
  38. package/dist/input/file-input.d.ts +54 -0
  39. package/dist/input/file-input.js +124 -0
  40. package/dist/input/flat-decode.d.ts +11 -0
  41. package/dist/input/flat-decode.js +13 -0
  42. package/dist/input/flat-errors.d.ts +71 -0
  43. package/dist/input/flat-errors.js +87 -0
  44. package/dist/input/flat-materializer.d.ts +29 -0
  45. package/dist/input/flat-materializer.js +177 -0
  46. package/dist/input/flat-parser.d.ts +50 -0
  47. package/dist/input/flat-parser.js +169 -0
  48. package/dist/input/flat-predicates.d.ts +34 -0
  49. package/dist/input/flat-predicates.js +50 -0
  50. package/dist/input/index.d.ts +14 -0
  51. package/dist/input/index.js +14 -0
  52. package/dist/input/input-resolver.d.ts +63 -0
  53. package/dist/input/input-resolver.js +254 -0
  54. package/dist/input/json-depth-scanner.d.ts +17 -0
  55. package/dist/input/json-depth-scanner.js +49 -0
  56. package/dist/input/metadata.d.ts +99 -0
  57. package/dist/input/metadata.js +99 -0
  58. package/dist/input/stdin-input.d.ts +26 -0
  59. package/dist/input/stdin-input.js +125 -0
  60. package/dist/input/utf8.d.ts +19 -0
  61. package/dist/input/utf8.js +36 -0
  62. package/dist/input/validation-mapper.d.ts +27 -0
  63. package/dist/input/validation-mapper.js +144 -0
  64. package/dist/invocation/index.d.ts +2 -0
  65. package/dist/invocation/index.js +2 -0
  66. package/dist/invocation/policy.d.ts +157 -0
  67. package/dist/invocation/policy.js +231 -0
  68. package/dist/invocation/types.d.ts +172 -0
  69. package/dist/invocation/types.js +97 -0
  70. package/dist/ipc/diagnostic.d.ts +0 -12
  71. package/dist/ipc/diagnostic.js +0 -21
  72. package/dist/ipc/host.d.ts +4 -4
  73. package/dist/ipc/host.js +44 -47
  74. package/dist/ipc/index.d.ts +1 -1
  75. package/dist/ipc/index.js +1 -1
  76. package/dist/ipc/service.d.ts +40 -0
  77. package/dist/ipc/service.js +349 -0
  78. package/dist/ipc/types.d.ts +21 -15
  79. package/dist/json/index.d.ts +1 -0
  80. package/dist/json/index.js +1 -0
  81. package/dist/json/value-validator.d.ts +88 -0
  82. package/dist/json/value-validator.js +330 -0
  83. package/dist/node/index.d.ts +1 -0
  84. package/dist/node/index.js +1 -0
  85. package/dist/node/module-loader.d.ts +63 -0
  86. package/dist/node/module-loader.js +112 -0
  87. package/dist/package/index.d.ts +23 -0
  88. package/dist/package/index.js +18 -0
  89. package/dist/{app/app.d.ts → package/runtime.d.ts} +41 -20
  90. package/dist/{app/app.js → package/runtime.js} +140 -95
  91. package/dist/{app → package}/static-index.js +58 -41
  92. package/dist/package/storage-view.d.ts +13 -0
  93. package/dist/package/storage-view.js +22 -0
  94. package/dist/{app → package}/types.d.ts +76 -57
  95. package/dist/package/types.js +22 -0
  96. package/dist/platform/index.d.ts +1 -1
  97. package/dist/platform/index.js +1 -1
  98. package/dist/platform/node.d.ts +48 -0
  99. package/dist/platform/node.js +96 -0
  100. package/dist/platform/types.d.ts +0 -9
  101. package/dist/process/control-arbiter.d.ts +2 -1
  102. package/dist/process/control-arbiter.js +1 -2
  103. package/dist/process/driver.d.ts +9 -8
  104. package/dist/process/driver.js +11 -22
  105. package/dist/process/index.d.ts +2 -0
  106. package/dist/process/index.js +2 -0
  107. package/dist/process/managed-record.d.ts +2 -2
  108. package/dist/process/process-driver.d.ts +109 -0
  109. package/dist/process/process-driver.js +650 -0
  110. package/dist/process/process-executor.d.ts +47 -0
  111. package/dist/process/process-executor.js +296 -0
  112. package/dist/process/process-manager.js +48 -26
  113. package/dist/process/run-executor.js +12 -12
  114. package/dist/profile/client-actions.js +2 -2
  115. package/dist/profile/client-health.js +3 -2
  116. package/dist/profile/client-query.js +5 -6
  117. package/dist/profile/client-transport.d.ts +19 -17
  118. package/dist/profile/client-transport.js +48 -80
  119. package/dist/profile/client.d.ts +2 -2
  120. package/dist/profile/client.js +1 -1
  121. package/dist/profile/index.d.ts +1 -0
  122. package/dist/profile/index.js +1 -0
  123. package/dist/profile/manager.d.ts +5 -0
  124. package/dist/profile/manager.js +41 -6
  125. package/dist/project/closure.js +2 -2
  126. package/dist/project/index.d.ts +8 -1
  127. package/dist/project/index.js +10 -1
  128. package/dist/project/init.js +2 -2
  129. package/dist/project/loader.d.ts +1 -1
  130. package/dist/project/loader.js +26 -29
  131. package/dist/project/transactions.js +5 -10
  132. package/dist/registry/index.d.ts +3 -1
  133. package/dist/registry/index.js +2 -1
  134. package/dist/registry/lock.d.ts +28 -7
  135. package/dist/registry/lock.js +136 -16
  136. package/dist/registry/registry.d.ts +1 -5
  137. package/dist/registry/registry.js +1 -53
  138. package/dist/registry/scan.d.ts +0 -15
  139. package/dist/registry/scan.js +0 -59
  140. package/dist/registry/store.d.ts +42 -0
  141. package/dist/registry/store.js +43 -0
  142. package/dist/registry/types.d.ts +0 -24
  143. package/dist/runtime/action-collection.d.ts +1 -1
  144. package/dist/runtime/action-registry.d.ts +0 -4
  145. package/dist/runtime/action-registry.js +0 -7
  146. package/dist/runtime/context.js +5 -11
  147. package/dist/runtime/events.js +3 -6
  148. package/dist/runtime/identity.d.ts +22 -0
  149. package/dist/runtime/identity.js +10 -0
  150. package/dist/runtime/index.d.ts +1 -2
  151. package/dist/runtime/index.js +1 -2
  152. package/dist/runtime/module-loader.d.ts +2 -34
  153. package/dist/runtime/module-loader.js +1 -16
  154. package/dist/runtime/process.d.ts +6 -24
  155. package/dist/runtime/process.js +1 -118
  156. package/dist/runtime/run-persistence.js +2 -5
  157. package/dist/runtime/runner.d.ts +33 -103
  158. package/dist/runtime/runner.js +142 -404
  159. package/dist/runtime/standalone.d.ts +37 -9
  160. package/dist/runtime/standalone.js +195 -136
  161. package/dist/schema/index.d.ts +1 -0
  162. package/dist/schema/index.js +1 -0
  163. package/dist/schema/validator.d.ts +10 -0
  164. package/dist/schema/validator.js +48 -54
  165. package/dist/server/body.d.ts +16 -8
  166. package/dist/server/body.js +33 -16
  167. package/dist/server/dispatcher.d.ts +6 -10
  168. package/dist/server/dispatcher.js +24 -32
  169. package/dist/server/http-server.d.ts +87 -0
  170. package/dist/server/http-server.js +304 -0
  171. package/dist/server/index.d.ts +11 -0
  172. package/dist/server/index.js +10 -0
  173. package/dist/server/mcp-endpoint.d.ts +61 -0
  174. package/dist/server/mcp-endpoint.js +118 -0
  175. package/dist/server/routes/actions.js +34 -28
  176. package/dist/server/routes/common.d.ts +10 -14
  177. package/dist/server/routes/common.js +32 -56
  178. package/dist/server/routes/config.js +54 -64
  179. package/dist/server/routes/doctor.d.ts +1 -1
  180. package/dist/server/routes/doctor.js +10 -18
  181. package/dist/server/routes/health.d.ts +1 -1
  182. package/dist/server/routes/health.js +2 -3
  183. package/dist/server/routes/info.d.ts +2 -2
  184. package/dist/server/routes/info.js +12 -13
  185. package/dist/server/routes/playbooks.js +16 -29
  186. package/dist/server/routes/runs.js +95 -117
  187. package/dist/server/routes/state.js +63 -62
  188. package/dist/server/server.d.ts +2 -2
  189. package/dist/server/server.js +43 -227
  190. package/dist/server/types.d.ts +8 -19
  191. package/dist/service/factory.d.ts +12 -0
  192. package/dist/service/factory.js +85 -0
  193. package/dist/{target → service}/index.d.ts +1 -1
  194. package/dist/{target → service}/index.js +1 -1
  195. package/dist/service/local.d.ts +27 -0
  196. package/dist/service/local.js +138 -0
  197. package/dist/{target → service}/remote-errors.d.ts +3 -6
  198. package/dist/service/remote-errors.js +38 -0
  199. package/dist/{target → service}/remote-polling.d.ts +2 -2
  200. package/dist/{target → service}/remote-polling.js +8 -8
  201. package/dist/service/remote.d.ts +34 -0
  202. package/dist/service/remote.js +634 -0
  203. package/dist/service/sse-stream.d.ts +24 -0
  204. package/dist/service/sse-stream.js +139 -0
  205. package/dist/service/types.d.ts +272 -0
  206. package/dist/service/types.js +32 -0
  207. package/dist/storage/data-dir-lock.js +10 -5
  208. package/dist/storage/driver.d.ts +2 -1
  209. package/dist/storage/driver.js +3 -52
  210. package/dist/storage/index.d.ts +1 -0
  211. package/dist/storage/index.js +1 -0
  212. package/dist/storage/lock-core.d.ts +2 -6
  213. package/dist/storage/lock-core.js +4 -17
  214. package/dist/storage/params.d.ts +2 -8
  215. package/dist/storage/params.js +2 -8
  216. package/dist/storage/sqlite-driver.d.ts +40 -0
  217. package/dist/storage/sqlite-driver.js +116 -0
  218. package/dist/storage/sqlite.js +21 -6
  219. package/dist/storage/types.d.ts +4 -4
  220. package/dist/storage/types.js +2 -2
  221. package/dist/utils/index.d.ts +53 -0
  222. package/dist/utils/index.js +99 -4
  223. package/dist/utils/process.d.ts +10 -0
  224. package/dist/utils/process.js +21 -0
  225. package/dist/version.d.ts +1 -1
  226. package/dist/version.js +1 -1
  227. package/package.json +41 -3
  228. package/dist/app/index.d.ts +0 -2
  229. package/dist/app/index.js +0 -2
  230. package/dist/app/types.js +0 -1
  231. package/dist/catalog/action-index.d.ts +0 -9
  232. package/dist/catalog/action-index.js +0 -95
  233. package/dist/catalog/action-resolver.d.ts +0 -20
  234. package/dist/catalog/action-resolver.js +0 -95
  235. package/dist/catalog/location-registry.d.ts +0 -15
  236. package/dist/catalog/location-registry.js +0 -138
  237. package/dist/catalog/package-catalog.d.ts +0 -7
  238. package/dist/catalog/package-catalog.js +0 -77
  239. package/dist/catalog/types.d.ts +0 -68
  240. package/dist/catalog/types.js +0 -1
  241. package/dist/export/index.d.ts +0 -1
  242. package/dist/export/index.js +0 -1
  243. package/dist/export/templates.d.ts +0 -71
  244. package/dist/export/templates.js +0 -623
  245. package/dist/ipc/target.d.ts +0 -74
  246. package/dist/ipc/target.js +0 -365
  247. package/dist/platform/default.d.ts +0 -38
  248. package/dist/platform/default.js +0 -78
  249. package/dist/project/resolver.d.ts +0 -116
  250. package/dist/project/resolver.js +0 -376
  251. package/dist/registry/resolve.d.ts +0 -62
  252. package/dist/registry/resolve.js +0 -195
  253. package/dist/runtime/execution-manager.d.ts +0 -48
  254. package/dist/runtime/execution-manager.js +0 -66
  255. package/dist/runtime/package-runner-factory.d.ts +0 -82
  256. package/dist/runtime/package-runner-factory.js +0 -186
  257. package/dist/target/local.d.ts +0 -53
  258. package/dist/target/local.js +0 -349
  259. package/dist/target/remote-errors.js +0 -51
  260. package/dist/target/remote.d.ts +0 -86
  261. package/dist/target/remote.js +0 -818
  262. package/dist/target/target.d.ts +0 -6
  263. package/dist/target/target.js +0 -37
  264. package/dist/target/types.d.ts +0 -261
  265. package/dist/target/types.js +0 -35
  266. /package/dist/{app → package}/static-index.d.ts +0 -0
  267. /package/dist/{target → service}/sse-parser.d.ts +0 -0
  268. /package/dist/{target → service}/sse-parser.js +0 -0
@@ -0,0 +1,349 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { fork } from "node:child_process";
3
+ import { DiagnosticForwarder } from "./diagnostic.js";
4
+ import { ActionDockError, CAPABILITY_UNAVAILABLE, EXECUTION_ABORTED, HOST_PROCESS_EXITED, IPC_ERROR, SERVICE_CLOSED, } from "../errors.js";
5
+ /**
6
+ * 跨进程取消信号占位标记字段名。
7
+ * AbortSignal 不可序列化,序列化 options 时把 signal 字段替换为该标记,
8
+ * 宿主侧识别后重建 AbortController 并接入 abort 消息通知链路。
9
+ */
10
+ export const IPC_SIGNAL_MARKER = "__ipcSignal";
11
+ /**
12
+ * 判断执行选项中是否携带跨进程取消信号占位标记。
13
+ */
14
+ export function hasIpcSignalMarker(value) {
15
+ return (typeof value === "object" &&
16
+ value !== null &&
17
+ value[IPC_SIGNAL_MARKER] === true);
18
+ }
19
+ /**
20
+ * 序列化执行选项:剥离不可序列化的 AbortSignal 并写入占位标记。
21
+ */
22
+ function markIpcSignal(options) {
23
+ if (!options)
24
+ return undefined;
25
+ const clean = {};
26
+ if (options.timeoutMs !== undefined)
27
+ clean.timeoutMs = options.timeoutMs;
28
+ if (options.config !== undefined)
29
+ clean.config = options.config;
30
+ if (options.requestId !== undefined)
31
+ clean.requestId = options.requestId;
32
+ if (options.signal) {
33
+ clean[IPC_SIGNAL_MARKER] = true;
34
+ }
35
+ return clean;
36
+ }
37
+ /**
38
+ * 基于 Node IPC 监督进程通信通道的 ActionDockService 实现。
39
+ * 遵循标准 Service Ports 体系,隔离子进程生命周期并暴露结构化服务端口。
40
+ */
41
+ export class IpcActionDockService {
42
+ child;
43
+ forwarder;
44
+ pendingCalls = new Map();
45
+ isClosed = false;
46
+ exitError;
47
+ readyPromise;
48
+ discovery;
49
+ execution;
50
+ runs;
51
+ management;
52
+ constructor(options) {
53
+ this.forwarder = new DiagnosticForwarder({
54
+ maxBytes: options.maxDiagnosticBytes,
55
+ maxRateBytesPerSec: options.maxDiagnosticRate,
56
+ target: options.diagnosticTarget,
57
+ });
58
+ if (options.childProcess) {
59
+ this.child = options.childProcess;
60
+ }
61
+ else if (options.scriptPath) {
62
+ this.child = fork(options.scriptPath, options.scriptArgs || [], {
63
+ cwd: options.cwd || process.cwd(),
64
+ env: options.env || process.env,
65
+ stdio: ["pipe", "pipe", "pipe", "ipc"],
66
+ });
67
+ }
68
+ else {
69
+ throw new Error("IpcActionDockService requires either 'childProcess' or 'scriptPath'");
70
+ }
71
+ if (this.child.stdout) {
72
+ this.forwarder.attach(this.child.stdout, "stdout");
73
+ }
74
+ if (this.child.stderr) {
75
+ this.forwarder.attach(this.child.stderr, "stderr");
76
+ }
77
+ let resolveReady;
78
+ this.readyPromise = new Promise((r) => {
79
+ resolveReady = r;
80
+ });
81
+ this.child.on("message", (msg) => {
82
+ if (!msg || typeof msg !== "object")
83
+ return;
84
+ if (msg.type === "ready") {
85
+ resolveReady();
86
+ }
87
+ else if (msg.type === "response") {
88
+ const resp = msg;
89
+ const pending = this.pendingCalls.get(resp.id);
90
+ if (pending) {
91
+ this.pendingCalls.delete(resp.id);
92
+ if (resp.ok) {
93
+ pending.resolve(resp.data);
94
+ }
95
+ else {
96
+ const err = new ActionDockError(resp.error?.code || IPC_ERROR, resp.error?.message || "IPC Service call failed", resp.error?.details);
97
+ pending.reject(err);
98
+ }
99
+ }
100
+ }
101
+ });
102
+ this.child.on("exit", (code, signal) => {
103
+ const exitMsg = `Host process exited prematurely with code ${code ?? signal ?? "unknown"}`;
104
+ const err = new ActionDockError(HOST_PROCESS_EXITED, exitMsg);
105
+ this.exitError = err;
106
+ this.isClosed = true;
107
+ // 快速失败所有待处理调用
108
+ for (const pending of this.pendingCalls.values()) {
109
+ if (pending.method === "runAction") {
110
+ pending.resolve({
111
+ ok: false,
112
+ runId: randomUUID(),
113
+ error: {
114
+ code: HOST_PROCESS_EXITED,
115
+ message: exitMsg,
116
+ },
117
+ });
118
+ }
119
+ else {
120
+ pending.reject(err);
121
+ }
122
+ }
123
+ this.pendingCalls.clear();
124
+ this.forwarder.detachAll();
125
+ resolveReady();
126
+ });
127
+ const self = this;
128
+ /**
129
+ * 生成方法级端口转发器:把端口方法调用映射为 callRemote 远端调用。
130
+ * 方法名与参数列表的对应关系即唯一事实源,杜绝手写转发样板膨胀。
131
+ */
132
+ const forward = (method, args) => self.callRemote(method, args);
133
+ this.discovery = {
134
+ async listPackages() {
135
+ return forward("listPackages", []);
136
+ },
137
+ async listActions(opts) {
138
+ return forward("listActions", [opts]);
139
+ },
140
+ async describeAction(ref) {
141
+ return forward("describeAction", [ref]);
142
+ },
143
+ async listPlaybooks(opts) {
144
+ return forward("listPlaybooks", [opts]);
145
+ },
146
+ async describePlaybook(id) {
147
+ return forward("describePlaybook", [id]);
148
+ },
149
+ };
150
+ this.execution = {
151
+ async run(ref, input, opts) {
152
+ if (opts?.signal?.aborted) {
153
+ return {
154
+ ok: false,
155
+ runId: randomUUID(),
156
+ error: {
157
+ code: EXECUTION_ABORTED,
158
+ message: "Execution was aborted before starting",
159
+ },
160
+ };
161
+ }
162
+ const serializableOptions = markIpcSignal(opts);
163
+ return self.callRemote("runAction", [ref, input ?? {}, serializableOptions], opts?.signal);
164
+ },
165
+ async start(ref, input, opts) {
166
+ if (opts?.signal?.aborted) {
167
+ throw new ActionDockError(EXECUTION_ABORTED, "Execution was aborted before starting");
168
+ }
169
+ const serializableOptions = markIpcSignal(opts);
170
+ return self.callRemote("startAction", [ref, input ?? {}, serializableOptions], opts?.signal);
171
+ },
172
+ };
173
+ this.runs = {
174
+ async list(query) {
175
+ return forward("listRuns", [query]);
176
+ },
177
+ async get(runId) {
178
+ const res = await forward("getRun", [runId]);
179
+ return res ?? undefined;
180
+ },
181
+ async cancel(runId, reason) {
182
+ return forward("cancelRun", [runId, reason]);
183
+ },
184
+ async clear(opts) {
185
+ return forward("clearRuns", [opts]);
186
+ },
187
+ };
188
+ if (options.enableManagement !== false) {
189
+ this.management = {
190
+ config: {
191
+ async get(packageId, key) {
192
+ return forward("getConfig", [packageId, key]);
193
+ },
194
+ async set(packageId, key, value) {
195
+ return forward("setConfig", [packageId, key, value]);
196
+ },
197
+ async delete(packageId, key) {
198
+ return forward("deleteConfig", [packageId, key]);
199
+ },
200
+ async list(packageId) {
201
+ return forward("listConfig", [packageId]);
202
+ },
203
+ },
204
+ state: {
205
+ async get(packageId, actionId, key, opts) {
206
+ return forward("getState", [packageId, actionId, key, opts]);
207
+ },
208
+ async set(packageId, actionId, key, value, opts) {
209
+ return forward("setState", [packageId, actionId, key, value, opts]);
210
+ },
211
+ async delete(packageId, actionId, key, opts) {
212
+ return forward("deleteState", [packageId, actionId, key, opts]);
213
+ },
214
+ async list(packageId, actionId, opts) {
215
+ return forward("listStateKeys", [packageId, actionId, opts]);
216
+ },
217
+ async clear(packageId, actionId, opts) {
218
+ return forward("clearState", [packageId, actionId, opts]);
219
+ },
220
+ async listEntries(packageId, opts) {
221
+ return forward("listStateEntries", [packageId, opts]);
222
+ },
223
+ },
224
+ };
225
+ }
226
+ }
227
+ async callRemote(method, args, signal) {
228
+ if (this.isClosed || this.exitError) {
229
+ if (method === "runAction") {
230
+ return {
231
+ ok: false,
232
+ runId: randomUUID(),
233
+ error: {
234
+ code: HOST_PROCESS_EXITED,
235
+ message: this.exitError?.message || "Host process is already closed",
236
+ },
237
+ };
238
+ }
239
+ throw this.exitError || new ActionDockError(SERVICE_CLOSED, `IpcActionDockService is closed: cannot call '${method}'`);
240
+ }
241
+ await this.readyPromise;
242
+ if (signal?.aborted) {
243
+ const err = new Error(signal.reason ? String(signal.reason) : "Operation aborted");
244
+ err.name = "AbortError";
245
+ throw err;
246
+ }
247
+ const id = randomUUID();
248
+ const message = {
249
+ id,
250
+ type: "call",
251
+ method,
252
+ args,
253
+ };
254
+ let onAbort;
255
+ if (signal && !signal.aborted) {
256
+ onAbort = () => {
257
+ this.sendAbort(id);
258
+ };
259
+ signal.addEventListener("abort", onAbort, { once: true });
260
+ }
261
+ return new Promise((resolve, reject) => {
262
+ this.pendingCalls.set(id, { resolve, reject, method });
263
+ try {
264
+ if (!this.child.send) {
265
+ throw new ActionDockError(CAPABILITY_UNAVAILABLE, "ChildProcess IPC channel is not available");
266
+ }
267
+ this.child.send(message, (err) => {
268
+ if (err) {
269
+ this.pendingCalls.delete(id);
270
+ reject(err);
271
+ }
272
+ });
273
+ }
274
+ catch (err) {
275
+ this.pendingCalls.delete(id);
276
+ reject(err);
277
+ }
278
+ }).finally(() => {
279
+ if (onAbort && signal) {
280
+ signal.removeEventListener("abort", onAbort);
281
+ }
282
+ });
283
+ }
284
+ sendAbort(id) {
285
+ if (this.isClosed)
286
+ return;
287
+ try {
288
+ const abortMsg = { id, type: "abort" };
289
+ if (this.child.send) {
290
+ this.child.send(abortMsg);
291
+ }
292
+ }
293
+ catch (err) {
294
+ process.stderr.write(`[IPC Service] Failed to send abort for call '${id}': ${err instanceof Error ? err.message : String(err)}\n`);
295
+ }
296
+ }
297
+ async info() {
298
+ return this.discovery.listPackages();
299
+ }
300
+ get process() {
301
+ return this.child;
302
+ }
303
+ async waitReady() {
304
+ return this.readyPromise;
305
+ }
306
+ async close() {
307
+ if (this.isClosed)
308
+ return;
309
+ if (this.child.exitCode !== null) {
310
+ this.forwarder.detachAll();
311
+ return;
312
+ }
313
+ const exitPromise = new Promise((resolve) => {
314
+ this.child.once("exit", () => resolve());
315
+ });
316
+ try {
317
+ if (this.child.connected) {
318
+ this.child.send({ type: "close" });
319
+ }
320
+ }
321
+ catch {
322
+ // 忽略发送关闭消息异常
323
+ }
324
+ const termTimer = setTimeout(() => {
325
+ if (this.child.exitCode === null) {
326
+ try {
327
+ this.child.kill("SIGTERM");
328
+ }
329
+ catch { }
330
+ }
331
+ }, 1500);
332
+ const killTimer = setTimeout(() => {
333
+ if (this.child.exitCode === null) {
334
+ try {
335
+ this.child.kill("SIGKILL");
336
+ }
337
+ catch { }
338
+ }
339
+ }, 3000);
340
+ try {
341
+ await exitPromise;
342
+ }
343
+ finally {
344
+ clearTimeout(termTimer);
345
+ clearTimeout(killTimer);
346
+ this.forwarder.detachAll();
347
+ }
348
+ }
349
+ }
@@ -32,20 +32,26 @@ export interface IpcResponseMessage {
32
32
  };
33
33
  }
34
34
  /**
35
- * 宿主子进程向监督进程流式推送的执行事件。
35
+ * 监督进程 IPC 服务初始化选项。
36
36
  */
37
- export interface IpcEventMessage {
38
- type: "event";
39
- runId: string;
40
- event: unknown;
37
+ export interface IpcServiceOptions {
38
+ type?: "ipc";
39
+ /** 已启动的子进程实例(需具备 IPC 通道) */
40
+ childProcess?: any;
41
+ /** 待启动的脚本物理路径 */
42
+ scriptPath?: string;
43
+ /** 启动参数 */
44
+ scriptArgs?: string[];
45
+ /** 工作目录 */
46
+ cwd?: string;
47
+ /** 环境变量 */
48
+ env?: NodeJS.ProcessEnv;
49
+ /** 诊断流最大缓冲字节数 */
50
+ maxDiagnosticBytes?: number;
51
+ /** 诊断流每秒最大字节速率 */
52
+ maxDiagnosticRate?: number;
53
+ /** 诊断流目标输出 */
54
+ diagnosticTarget?: any;
55
+ /** 是否启用管理端口(默认 true) */
56
+ enableManagement?: boolean;
41
57
  }
42
- /**
43
- * 宿主子进程初始化就绪通知。
44
- */
45
- export interface IpcReadyMessage {
46
- type: "ready";
47
- }
48
- /**
49
- * 联合 IPC 消息类型。
50
- */
51
- export type IpcMessage = IpcCallMessage | IpcResponseMessage | IpcAbortMessage | IpcEventMessage | IpcReadyMessage;
@@ -0,0 +1 @@
1
+ export * from "./value-validator.js";
@@ -0,0 +1 @@
1
+ export * from "./value-validator.js";
@@ -0,0 +1,88 @@
1
+ import type { JsonValue } from "@actiondock/sdk";
2
+ /** 默认 JSON 最大嵌套深度限制(防止恶意超深结构) */
3
+ export declare const DEFAULT_MAX_JSON_DEPTH = 256;
4
+ /**
5
+ * JSON 结构校验选项。
6
+ */
7
+ export interface ValidateJsonOptions {
8
+ /** 最大允许嵌套深度(默认 256) */
9
+ maxDepth?: number;
10
+ }
11
+ /**
12
+ * Action 输入校验选项。
13
+ */
14
+ export interface ValidateActionInputOptions extends ValidateJsonOptions {
15
+ }
16
+ /**
17
+ * JSON 值校验错误码类型。
18
+ */
19
+ export type JsonValueValidationErrorCode = "NON_FINITE_NUMBER" | "MAX_JSON_DEPTH" | "CIRCULAR_REFERENCE" | "UNSUPPORTED_JSON_TYPE" | "INVALID_JSON_OBJECT" | "UNDEFINED_JSON_VALUE";
20
+ /**
21
+ * Canonical JsonValue 校验结果。
22
+ */
23
+ export type JsonValueValidationResult = {
24
+ valid: true;
25
+ } | {
26
+ valid: false;
27
+ code: JsonValueValidationErrorCode;
28
+ reason: string;
29
+ path?: string;
30
+ };
31
+ /**
32
+ * Action 输入值校验结果(包含策略违规分支)。
33
+ */
34
+ export type ActionInputValidationResult = {
35
+ valid: true;
36
+ } | {
37
+ valid: false;
38
+ kind: "json-value";
39
+ code: JsonValueValidationErrorCode;
40
+ reason: string;
41
+ path?: string;
42
+ } | {
43
+ valid: false;
44
+ kind: "input-policy";
45
+ code: "FORBIDDEN_PROPERTY";
46
+ property: string;
47
+ path: string;
48
+ reason: string;
49
+ };
50
+ /**
51
+ * 按照 RFC 6901 转义单个 JSON Pointer 路径段。
52
+ *
53
+ * @param segment 路径段(属性名或数组索引)
54
+ * @returns 转义后的路径段
55
+ */
56
+ export declare function escapeJsonPointerSegment(segment: string | number): string;
57
+ /**
58
+ * 将路径段追加到基础 RFC 6901 JSON Pointer 路径后。
59
+ *
60
+ * @param basePath 基础路径
61
+ * @param segment 待追加的路径段
62
+ * @returns 拼接后的 JSON Pointer
63
+ */
64
+ export declare function appendJsonPointer(basePath: string, segment: string | number): string;
65
+ /**
66
+ * 校验值是否为合法的 Canonical JSON 兼容结构。
67
+ *
68
+ * @param value 待校验的目标值
69
+ * @param options 校验配置选项
70
+ * @returns 校验结果对象
71
+ */
72
+ export declare function validateJsonValue(value: unknown, options?: ValidateJsonOptions): JsonValueValidationResult;
73
+ /**
74
+ * 校验 Action 输入值是否满足 Canonical JsonValue 规范且符合 ActionDock 安全策略。
75
+ * 在遍历过程中递归检查是否存在禁止属性(__proto__、constructor、prototype)。
76
+ *
77
+ * @param value 待校验的 Action 输入值
78
+ * @param options 校验配置选项
79
+ * @returns 校验结果对象
80
+ */
81
+ export declare function validateActionInputValue(value: unknown, options?: ValidateActionInputOptions): ActionInputValidationResult;
82
+ /**
83
+ * 断言值必须为合法的 Canonical JSON 兼容结构,若非法则抛出 TypeError。
84
+ *
85
+ * @param value 待断言的目标值
86
+ * @param options 校验配置选项
87
+ */
88
+ export declare function assertJsonValue(value: unknown, options?: ValidateJsonOptions): asserts value is JsonValue;