@actiondock/core 2.0.11 → 2.2.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 (258) hide show
  1. package/README.md +61 -30
  2. package/dist/app/app.d.ts +73 -0
  3. package/dist/app/app.js +700 -0
  4. package/dist/app/index.d.ts +2 -0
  5. package/dist/app/index.js +2 -0
  6. package/dist/app/types.d.ts +283 -0
  7. package/dist/app/types.js +1 -0
  8. package/dist/catalog/action-index.d.ts +9 -0
  9. package/dist/catalog/action-index.js +93 -0
  10. package/dist/catalog/action-resolver.d.ts +20 -0
  11. package/dist/catalog/action-resolver.js +95 -0
  12. package/dist/catalog/index.d.ts +5 -0
  13. package/dist/catalog/index.js +5 -0
  14. package/dist/catalog/location-registry.d.ts +15 -0
  15. package/dist/catalog/location-registry.js +138 -0
  16. package/dist/catalog/package-catalog.d.ts +7 -0
  17. package/dist/catalog/package-catalog.js +76 -0
  18. package/dist/catalog/types.d.ts +68 -0
  19. package/dist/catalog/types.js +1 -0
  20. package/dist/doctor/doctor.d.ts +7 -0
  21. package/dist/doctor/doctor.js +613 -0
  22. package/dist/doctor/index.d.ts +2 -0
  23. package/dist/doctor/index.js +2 -0
  24. package/dist/doctor/types.d.ts +23 -0
  25. package/dist/doctor/types.js +1 -0
  26. package/dist/errors.d.ts +122 -0
  27. package/dist/errors.js +123 -0
  28. package/dist/execution/index.d.ts +2 -0
  29. package/dist/execution/index.js +2 -0
  30. package/dist/execution/service.d.ts +79 -0
  31. package/dist/execution/service.js +633 -0
  32. package/dist/execution/types.d.ts +131 -0
  33. package/dist/execution/types.js +1 -0
  34. package/dist/export/index.d.ts +1 -0
  35. package/dist/export/index.js +1 -0
  36. package/dist/export/templates.d.ts +71 -0
  37. package/dist/export/templates.js +621 -0
  38. package/dist/filter/index.d.ts +1 -0
  39. package/dist/filter/index.js +1 -0
  40. package/dist/filter/intent.d.ts +33 -0
  41. package/dist/filter/intent.js +123 -0
  42. package/dist/host/host.d.ts +55 -0
  43. package/dist/host/host.js +740 -0
  44. package/dist/host/index.d.ts +2 -0
  45. package/dist/host/index.js +2 -0
  46. package/dist/host/types.d.ts +81 -0
  47. package/dist/host/types.js +1 -0
  48. package/dist/index.d.ts +21 -0
  49. package/dist/index.js +20 -0
  50. package/dist/ipc/diagnostic.d.ts +65 -0
  51. package/dist/ipc/diagnostic.js +129 -0
  52. package/dist/ipc/host.d.ts +7 -0
  53. package/dist/ipc/host.js +93 -0
  54. package/dist/ipc/index.d.ts +4 -0
  55. package/dist/ipc/index.js +4 -0
  56. package/dist/ipc/target.d.ts +56 -0
  57. package/dist/ipc/target.js +297 -0
  58. package/dist/ipc/types.d.ts +42 -0
  59. package/dist/ipc/types.js +1 -0
  60. package/dist/platform/default.d.ts +32 -0
  61. package/dist/platform/default.js +40 -0
  62. package/dist/platform/index.d.ts +3 -0
  63. package/dist/platform/index.js +3 -0
  64. package/dist/platform/node-fs.d.ts +37 -0
  65. package/dist/platform/node-fs.js +81 -0
  66. package/dist/platform/types.d.ts +104 -0
  67. package/dist/platform/types.js +1 -0
  68. package/dist/profile/client.d.ts +162 -0
  69. package/dist/profile/client.js +467 -0
  70. package/dist/profile/index.d.ts +3 -0
  71. package/dist/profile/index.js +3 -0
  72. package/dist/profile/manager.d.ts +47 -0
  73. package/dist/profile/manager.js +294 -0
  74. package/dist/profile/types.d.ts +61 -0
  75. package/dist/profile/types.js +1 -0
  76. package/dist/project/closure.d.ts +25 -0
  77. package/dist/project/closure.js +68 -0
  78. package/dist/project/digest.d.ts +29 -0
  79. package/dist/project/digest.js +324 -0
  80. package/dist/project/index.d.ts +10 -0
  81. package/dist/project/index.js +10 -0
  82. package/dist/project/init.d.ts +26 -0
  83. package/dist/project/init.js +175 -0
  84. package/dist/project/loader.d.ts +99 -0
  85. package/dist/project/loader.js +484 -0
  86. package/dist/project/lockfile.d.ts +55 -0
  87. package/dist/project/lockfile.js +175 -0
  88. package/dist/project/manifest.d.ts +22 -0
  89. package/dist/project/manifest.js +220 -0
  90. package/dist/project/resolver.d.ts +116 -0
  91. package/dist/project/resolver.js +376 -0
  92. package/dist/project/transactions.d.ts +103 -0
  93. package/dist/project/transactions.js +1203 -0
  94. package/dist/project/types-generator.d.ts +33 -0
  95. package/dist/project/types-generator.js +168 -0
  96. package/dist/project/types.d.ts +107 -0
  97. package/dist/project/types.js +1 -0
  98. package/dist/registry/index.d.ts +5 -0
  99. package/dist/registry/index.js +5 -0
  100. package/dist/registry/lock.d.ts +27 -0
  101. package/dist/registry/lock.js +93 -0
  102. package/dist/registry/registry.d.ts +45 -0
  103. package/dist/registry/registry.js +611 -0
  104. package/dist/registry/resolve.d.ts +62 -0
  105. package/dist/registry/resolve.js +195 -0
  106. package/dist/registry/scan.d.ts +38 -0
  107. package/dist/registry/scan.js +135 -0
  108. package/dist/registry/types.d.ts +117 -0
  109. package/dist/registry/types.js +1 -0
  110. package/dist/runtime/action-collection.d.ts +27 -0
  111. package/dist/runtime/action-collection.js +57 -0
  112. package/dist/runtime/clock.d.ts +19 -0
  113. package/dist/runtime/clock.js +17 -0
  114. package/dist/runtime/context.d.ts +86 -0
  115. package/dist/runtime/context.js +242 -0
  116. package/dist/runtime/env.d.ts +56 -0
  117. package/dist/runtime/env.js +159 -0
  118. package/dist/runtime/events.d.ts +93 -0
  119. package/dist/runtime/events.js +604 -0
  120. package/dist/runtime/execution-manager.d.ts +48 -0
  121. package/dist/runtime/execution-manager.js +66 -0
  122. package/dist/runtime/index.d.ts +10 -0
  123. package/dist/runtime/index.js +10 -0
  124. package/dist/runtime/module-loader.d.ts +34 -0
  125. package/dist/runtime/module-loader.js +16 -0
  126. package/dist/runtime/process.d.ts +9 -0
  127. package/dist/runtime/process.js +146 -0
  128. package/dist/runtime/runner.d.ts +293 -0
  129. package/dist/runtime/runner.js +984 -0
  130. package/dist/runtime/standalone.d.ts +89 -0
  131. package/dist/runtime/standalone.js +536 -0
  132. package/dist/schema/validator.d.ts +28 -0
  133. package/dist/schema/validator.js +116 -0
  134. package/dist/server/body.d.ts +40 -0
  135. package/dist/server/body.js +93 -0
  136. package/dist/server/index.d.ts +5 -0
  137. package/dist/server/index.js +5 -0
  138. package/dist/server/routes/actions.d.ts +5 -0
  139. package/dist/server/routes/actions.js +298 -0
  140. package/dist/server/routes/common.d.ts +47 -0
  141. package/dist/server/routes/common.js +104 -0
  142. package/dist/server/routes/config.d.ts +6 -0
  143. package/dist/server/routes/config.js +173 -0
  144. package/dist/server/routes/doctor.d.ts +5 -0
  145. package/dist/server/routes/doctor.js +63 -0
  146. package/dist/server/routes/health.d.ts +5 -0
  147. package/dist/server/routes/health.js +35 -0
  148. package/dist/server/routes/index.d.ts +9 -0
  149. package/dist/server/routes/index.js +9 -0
  150. package/dist/server/routes/info.d.ts +7 -0
  151. package/dist/server/routes/info.js +158 -0
  152. package/dist/server/routes/playbooks.d.ts +5 -0
  153. package/dist/server/routes/playbooks.js +134 -0
  154. package/dist/server/routes/runs.d.ts +5 -0
  155. package/dist/server/routes/runs.js +343 -0
  156. package/dist/server/routes/state.d.ts +6 -0
  157. package/dist/server/routes/state.js +169 -0
  158. package/dist/server/security.d.ts +44 -0
  159. package/dist/server/security.js +101 -0
  160. package/dist/server/server.d.ts +15 -0
  161. package/dist/server/server.js +355 -0
  162. package/dist/server/types.d.ts +78 -0
  163. package/dist/server/types.js +1 -0
  164. package/dist/storage/data-dir-lock.d.ts +119 -0
  165. package/dist/storage/data-dir-lock.js +1016 -0
  166. package/dist/storage/driver.d.ts +9 -0
  167. package/dist/storage/driver.js +59 -0
  168. package/dist/storage/index.d.ts +64 -0
  169. package/dist/storage/index.js +98 -0
  170. package/dist/storage/lazy.d.ts +8 -0
  171. package/dist/storage/lazy.js +44 -0
  172. package/dist/storage/mask.d.ts +26 -0
  173. package/dist/storage/mask.js +48 -0
  174. package/dist/storage/params.d.ts +13 -0
  175. package/dist/storage/params.js +32 -0
  176. package/dist/storage/sqlite.d.ts +79 -0
  177. package/dist/storage/sqlite.js +689 -0
  178. package/dist/storage/types.d.ts +172 -0
  179. package/dist/storage/types.js +14 -0
  180. package/dist/target/index.d.ts +4 -0
  181. package/dist/target/index.js +4 -0
  182. package/dist/target/local.d.ts +52 -0
  183. package/dist/target/local.js +343 -0
  184. package/dist/target/remote.d.ts +76 -0
  185. package/dist/target/remote.js +839 -0
  186. package/dist/target/target.d.ts +6 -0
  187. package/dist/target/target.js +35 -0
  188. package/dist/target/types.d.ts +246 -0
  189. package/dist/target/types.js +34 -0
  190. package/dist/utils/index.d.ts +49 -0
  191. package/dist/utils/index.js +180 -0
  192. package/dist/version.d.ts +4 -0
  193. package/dist/version.js +4 -0
  194. package/package.json +13 -13
  195. package/src/build/index.ts +0 -1
  196. package/src/build/templates.ts +0 -59
  197. package/src/catalog/action-index.ts +0 -92
  198. package/src/catalog/action-resolver.ts +0 -120
  199. package/src/catalog/index.ts +0 -5
  200. package/src/catalog/location-registry.ts +0 -134
  201. package/src/catalog/package-catalog.ts +0 -87
  202. package/src/catalog/types.ts +0 -75
  203. package/src/doctor/doctor.ts +0 -419
  204. package/src/doctor/index.ts +0 -2
  205. package/src/doctor/types.ts +0 -25
  206. package/src/execution/index.ts +0 -2
  207. package/src/execution/service.ts +0 -322
  208. package/src/execution/types.ts +0 -73
  209. package/src/export/index.ts +0 -1
  210. package/src/export/templates.ts +0 -590
  211. package/src/filter/index.ts +0 -1
  212. package/src/filter/intent.ts +0 -154
  213. package/src/index.ts +0 -16
  214. package/src/profile/client.ts +0 -552
  215. package/src/profile/index.ts +0 -3
  216. package/src/profile/manager.ts +0 -341
  217. package/src/profile/types.ts +0 -71
  218. package/src/project/index.ts +0 -4
  219. package/src/project/init.ts +0 -242
  220. package/src/project/loader.ts +0 -479
  221. package/src/project/manifest.ts +0 -299
  222. package/src/project/types.ts +0 -141
  223. package/src/registry/index.ts +0 -2
  224. package/src/registry/registry.ts +0 -940
  225. package/src/registry/types.ts +0 -127
  226. package/src/runtime/clock.ts +0 -41
  227. package/src/runtime/context.ts +0 -259
  228. package/src/runtime/env.ts +0 -172
  229. package/src/runtime/events.ts +0 -142
  230. package/src/runtime/execution-manager.ts +0 -74
  231. package/src/runtime/index.ts +0 -10
  232. package/src/runtime/module-loader.ts +0 -67
  233. package/src/runtime/process.ts +0 -245
  234. package/src/runtime/runner.ts +0 -527
  235. package/src/runtime/standalone.ts +0 -429
  236. package/src/schema/validator.ts +0 -61
  237. package/src/server/body.ts +0 -112
  238. package/src/server/index.ts +0 -7
  239. package/src/server/routes/actions.ts +0 -262
  240. package/src/server/routes/common.ts +0 -126
  241. package/src/server/routes/config.ts +0 -147
  242. package/src/server/routes/doctor.ts +0 -29
  243. package/src/server/routes/health.ts +0 -40
  244. package/src/server/routes/index.ts +0 -9
  245. package/src/server/routes/info.ts +0 -221
  246. package/src/server/routes/playbooks.ts +0 -109
  247. package/src/server/routes/runs.ts +0 -301
  248. package/src/server/routes/state.ts +0 -133
  249. package/src/server/runtime-registry.ts +0 -115
  250. package/src/server/security.ts +0 -115
  251. package/src/server/server.ts +0 -251
  252. package/src/server/types.ts +0 -57
  253. package/src/storage/driver.ts +0 -126
  254. package/src/storage/index.ts +0 -81
  255. package/src/storage/mask.ts +0 -34
  256. package/src/storage/sqlite.ts +0 -714
  257. package/src/storage/types.ts +0 -139
  258. package/src/utils/index.ts +0 -62
@@ -0,0 +1,297 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { fork } from "node:child_process";
3
+ import { DiagnosticForwarder } from "./diagnostic.js";
4
+ import { EXECUTION_ABORTED, HOST_PROCESS_EXITED } from "../errors.js";
5
+ /**
6
+ * 基于 Node IPC 监督进程通信通道的 ActionDockTarget 实现。
7
+ *
8
+ * 职责:
9
+ * 1. 监督并隔离子进程的生命周期与标准输出,保证父进程标准输入输出通道 100% 纯净。
10
+ * 2. 将子进程标准输出/错误通过 DiagnosticForwarder 进行受控排空与诊断流限流转发。
11
+ * 3. 当子进程异常终止时,立即将当前活跃调用转换为结构化 HOST_PROCESS_EXITED 错误,防止调用方死锁。
12
+ */
13
+ export class IpcActionDockTarget {
14
+ child;
15
+ forwarder;
16
+ pendingCalls = new Map();
17
+ isClosed = false;
18
+ exitError;
19
+ readyPromise;
20
+ constructor(options) {
21
+ this.forwarder = new DiagnosticForwarder({
22
+ maxBytes: options.maxDiagnosticBytes,
23
+ maxRateBytesPerSec: options.maxDiagnosticRate,
24
+ target: options.diagnosticTarget,
25
+ });
26
+ if (options.childProcess) {
27
+ this.child = options.childProcess;
28
+ }
29
+ else if (options.scriptPath) {
30
+ this.child = fork(options.scriptPath, options.scriptArgs || [], {
31
+ cwd: options.cwd || process.cwd(),
32
+ env: options.env || process.env,
33
+ stdio: ["pipe", "pipe", "pipe", "ipc"],
34
+ });
35
+ }
36
+ else {
37
+ throw new Error("IpcActionDockTarget requires either 'childProcess' or 'scriptPath'");
38
+ }
39
+ // 绑定子进程输出至受控限流排空器,绝不泄露至 process.stdout
40
+ if (this.child.stdout) {
41
+ this.forwarder.attach(this.child.stdout, "stdout");
42
+ }
43
+ if (this.child.stderr) {
44
+ this.forwarder.attach(this.child.stderr, "stderr");
45
+ }
46
+ let resolveReady;
47
+ this.readyPromise = new Promise((r) => {
48
+ resolveReady = r;
49
+ });
50
+ this.child.on("message", (msg) => {
51
+ if (!msg || typeof msg !== "object")
52
+ return;
53
+ if (msg.type === "ready") {
54
+ resolveReady();
55
+ }
56
+ else if (msg.type === "response") {
57
+ const resp = msg;
58
+ const pending = this.pendingCalls.get(resp.id);
59
+ if (pending) {
60
+ this.pendingCalls.delete(resp.id);
61
+ if (resp.ok) {
62
+ pending.resolve(resp.data);
63
+ }
64
+ else {
65
+ const err = new Error(resp.error?.message || "IPC Target call failed");
66
+ if (resp.error?.code)
67
+ err.code = resp.error.code;
68
+ if (resp.error?.details)
69
+ err.details = resp.error.details;
70
+ pending.reject(err);
71
+ }
72
+ }
73
+ }
74
+ });
75
+ this.child.on("exit", (code, signal) => {
76
+ const exitMsg = `Host process exited prematurely with code ${code ?? signal ?? "unknown"}`;
77
+ const err = new Error(exitMsg);
78
+ err.code = "HOST_PROCESS_EXITED";
79
+ this.exitError = err;
80
+ this.isClosed = true;
81
+ // 快速失败所有待处理调用
82
+ for (const pending of this.pendingCalls.values()) {
83
+ if (pending.method === "runAction") {
84
+ pending.resolve({
85
+ ok: false,
86
+ runId: randomUUID(),
87
+ error: {
88
+ code: HOST_PROCESS_EXITED,
89
+ message: exitMsg,
90
+ },
91
+ });
92
+ }
93
+ else {
94
+ pending.reject(err);
95
+ }
96
+ }
97
+ this.pendingCalls.clear();
98
+ resolveReady(); // 避免就绪死锁
99
+ });
100
+ this.child.on("error", (err) => {
101
+ this.exitError = err;
102
+ });
103
+ }
104
+ /**
105
+ * 等待宿主子进程初始化就绪。
106
+ */
107
+ async waitReady(timeoutMs = 5000) {
108
+ if (this.exitError)
109
+ throw this.exitError;
110
+ let timer;
111
+ const timeout = new Promise((_, reject) => {
112
+ timer = setTimeout(() => reject(new Error(`Timeout waiting for host process ready after ${timeoutMs}ms`)), timeoutMs);
113
+ });
114
+ try {
115
+ await Promise.race([this.readyPromise, timeout]);
116
+ }
117
+ finally {
118
+ if (timer !== undefined) {
119
+ clearTimeout(timer);
120
+ }
121
+ }
122
+ }
123
+ /**
124
+ * 获取底层子进程实例。
125
+ */
126
+ get process() {
127
+ return this.child;
128
+ }
129
+ async callRemote(method, args) {
130
+ if (this.isClosed || this.exitError) {
131
+ if (method === "runAction") {
132
+ return {
133
+ ok: false,
134
+ runId: randomUUID(),
135
+ error: {
136
+ code: HOST_PROCESS_EXITED,
137
+ message: this.exitError?.message || "Host process is already closed",
138
+ },
139
+ };
140
+ }
141
+ throw this.exitError || new Error("Host process is already closed");
142
+ }
143
+ const id = randomUUID();
144
+ const msg = {
145
+ id,
146
+ type: "call",
147
+ method,
148
+ args,
149
+ };
150
+ return new Promise((resolve, reject) => {
151
+ this.pendingCalls.set(id, { resolve, reject, method });
152
+ try {
153
+ if (this.child.send) {
154
+ this.child.send(msg);
155
+ }
156
+ else {
157
+ this.pendingCalls.delete(id);
158
+ reject(new Error("IPC channel unavailable on child process"));
159
+ }
160
+ }
161
+ catch (err) {
162
+ this.pendingCalls.delete(id);
163
+ reject(err);
164
+ }
165
+ });
166
+ }
167
+ async info() {
168
+ return this.callRemote("info", []);
169
+ }
170
+ async listPackages() {
171
+ return this.callRemote("listPackages", []);
172
+ }
173
+ async listActions(options) {
174
+ return this.callRemote("listActions", [options]);
175
+ }
176
+ async describeAction(ref) {
177
+ return this.callRemote("describeAction", [ref]);
178
+ }
179
+ async listPlaybooks(options) {
180
+ return this.callRemote("listPlaybooks", [options]);
181
+ }
182
+ async describePlaybook(id) {
183
+ return this.callRemote("describePlaybook", [id]);
184
+ }
185
+ async runAction(ref, input, options) {
186
+ const { signal, ...serializableOptions } = options || {};
187
+ if (signal?.aborted) {
188
+ return {
189
+ ok: false,
190
+ runId: randomUUID(),
191
+ error: {
192
+ code: EXECUTION_ABORTED,
193
+ message: "Execution was aborted before starting",
194
+ },
195
+ };
196
+ }
197
+ return this.callRemote("runAction", [ref, input, serializableOptions]);
198
+ }
199
+ async startAction(ref, input, options) {
200
+ const { signal, ...serializableOptions } = options || {};
201
+ return this.callRemote("startAction", [ref, input, serializableOptions]);
202
+ }
203
+ async getRun(runId) {
204
+ const res = await this.callRemote("getRun", [runId]);
205
+ return res ?? undefined;
206
+ }
207
+ async cancelRun(runId) {
208
+ return this.callRemote("cancelRun", [runId]);
209
+ }
210
+ async listRuns(options) {
211
+ return this.callRemote("listRuns", [options]);
212
+ }
213
+ async *events(_runId, _options) {
214
+ // 基础 IPC 通道暂不流式下发历史事件
215
+ }
216
+ async listConfig(packageId) {
217
+ return this.callRemote("listConfig", [packageId]);
218
+ }
219
+ async getConfig(packageId, key) {
220
+ return this.callRemote("getConfig", [packageId, key]);
221
+ }
222
+ async setConfig(packageId, key, value) {
223
+ return this.callRemote("setConfig", [packageId, key, value]);
224
+ }
225
+ async deleteConfig(packageId, key) {
226
+ return this.callRemote("deleteConfig", [packageId, key]);
227
+ }
228
+ async getState(packageId, actionId, key, options) {
229
+ return this.callRemote("getState", [
230
+ packageId,
231
+ actionId,
232
+ key,
233
+ options,
234
+ ]);
235
+ }
236
+ async setState(packageId, actionId, key, value, options) {
237
+ return this.callRemote("setState", [packageId, actionId, key, value, options]);
238
+ }
239
+ async deleteState(packageId, actionId, key, options) {
240
+ return this.callRemote("deleteState", [packageId, actionId, key, options]);
241
+ }
242
+ async listStateKeys(packageId, actionId, options) {
243
+ return this.callRemote("listStateKeys", [packageId, actionId, options]);
244
+ }
245
+ async clearState(packageId, actionId, options) {
246
+ return this.callRemote("clearState", [packageId, actionId, options]);
247
+ }
248
+ async close() {
249
+ if (this.isClosed)
250
+ return;
251
+ if (this.child.exitCode !== null) {
252
+ this.forwarder.detachAll();
253
+ return;
254
+ }
255
+ const exitPromise = new Promise((resolve) => {
256
+ if (this.child.exitCode !== null) {
257
+ resolve();
258
+ }
259
+ else {
260
+ this.child.once("exit", () => resolve());
261
+ }
262
+ });
263
+ try {
264
+ if (this.child.connected) {
265
+ this.child.send({ type: "close" });
266
+ }
267
+ }
268
+ catch {
269
+ // 忽略发送关闭消息异常
270
+ }
271
+ // 若子进程超时未退出,先 SIGTERM 再 SIGKILL
272
+ const termTimer = setTimeout(() => {
273
+ if (this.child.exitCode === null) {
274
+ try {
275
+ this.child.kill("SIGTERM");
276
+ }
277
+ catch { }
278
+ }
279
+ }, 1500);
280
+ const killTimer = setTimeout(() => {
281
+ if (this.child.exitCode === null) {
282
+ try {
283
+ this.child.kill("SIGKILL");
284
+ }
285
+ catch { }
286
+ }
287
+ }, 3000);
288
+ try {
289
+ await exitPromise;
290
+ }
291
+ finally {
292
+ clearTimeout(termTimer);
293
+ clearTimeout(killTimer);
294
+ this.forwarder.detachAll();
295
+ }
296
+ }
297
+ }
@@ -0,0 +1,42 @@
1
+ /**
2
+ * 监督进程与宿主子进程间调用的 IPC 请求消息。
3
+ */
4
+ export interface IpcCallMessage {
5
+ id: string;
6
+ type: "call";
7
+ method: string;
8
+ args: unknown[];
9
+ }
10
+ /**
11
+ * 宿主子进程回复给监督进程的 IPC 响应消息。
12
+ */
13
+ export interface IpcResponseMessage {
14
+ id: string;
15
+ type: "response";
16
+ ok: boolean;
17
+ data?: unknown;
18
+ error?: {
19
+ code?: string;
20
+ message: string;
21
+ stack?: string;
22
+ details?: unknown;
23
+ };
24
+ }
25
+ /**
26
+ * 宿主子进程向监督进程流式推送的执行事件。
27
+ */
28
+ export interface IpcEventMessage {
29
+ type: "event";
30
+ runId: string;
31
+ event: unknown;
32
+ }
33
+ /**
34
+ * 宿主子进程初始化就绪通知。
35
+ */
36
+ export interface IpcReadyMessage {
37
+ type: "ready";
38
+ }
39
+ /**
40
+ * 联合 IPC 消息类型。
41
+ */
42
+ export type IpcMessage = IpcCallMessage | IpcResponseMessage | IpcEventMessage | IpcReadyMessage;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,32 @@
1
+ import type { ProcessAPI } from "@actiondock/sdk";
2
+ import { type Clock } from "../runtime/clock.js";
3
+ import { type ModuleLoader } from "../runtime/module-loader.js";
4
+ import type { FileSystem, RuntimePlatform, StorageFactory } from "./types.js";
5
+ /**
6
+ * 默认运行时平台构建选项。
7
+ */
8
+ export interface DefaultPlatformOptions {
9
+ /** 平台名称覆盖(默认使用 node) */
10
+ name?: "node" | "test";
11
+ /** 自定义文件系统实现(默认使用 NodeFileSystem) */
12
+ files?: FileSystem;
13
+ /** 自定义时间与时钟驱动(默认使用 SystemClock) */
14
+ clock?: Clock;
15
+ /** 自定义进程执行驱动(默认使用 DefaultProcessExecutor) */
16
+ process?: ProcessAPI;
17
+ /** 自定义源码加载驱动(默认使用 DefaultModuleLoader) */
18
+ modules?: ModuleLoader;
19
+ /** 自定义存储工厂(默认基于 core/storage 构造) */
20
+ storage?: StorageFactory;
21
+ /** 自定义 ActionDock 家目录 */
22
+ customHome?: string;
23
+ /** 自定义全局数据存储目录 */
24
+ dataDir?: string;
25
+ /** 文件系统沙箱根目录 */
26
+ rootDir?: string;
27
+ }
28
+ /**
29
+ * 创建默认 RuntimePlatform 平台实例。
30
+ * 直接基于 Node 原生与 Core 内核能力组装平台,禁止任何全局单例状态。
31
+ */
32
+ export declare function createDefaultPlatform(options?: DefaultPlatformOptions): RuntimePlatform;
@@ -0,0 +1,40 @@
1
+ import { SystemClock } from "../runtime/clock.js";
2
+ import { DefaultModuleLoader } from "../runtime/module-loader.js";
3
+ import { DefaultProcessExecutor } from "../runtime/process.js";
4
+ import { createGlobalStorage as coreCreateGlobalStorage, createStorage as coreCreateStorage, } from "../storage/index.js";
5
+ import { NodeFileSystem } from "./node-fs.js";
6
+ /**
7
+ * 创建默认 RuntimePlatform 平台实例。
8
+ * 直接基于 Node 原生与 Core 内核能力组装平台,禁止任何全局单例状态。
9
+ */
10
+ export function createDefaultPlatform(options = {}) {
11
+ const platformName = options.name ?? "node";
12
+ const clock = options.clock ?? new SystemClock();
13
+ const files = options.files ?? new NodeFileSystem({ rootDir: options.rootDir });
14
+ const modules = options.modules ?? new DefaultModuleLoader();
15
+ const process = options.process ?? new DefaultProcessExecutor();
16
+ const storage = options.storage ?? {
17
+ createStorage(packageId, opts) {
18
+ return coreCreateStorage(packageId, {
19
+ customHome: options.customHome,
20
+ dataDir: options.dataDir,
21
+ ...opts,
22
+ });
23
+ },
24
+ createGlobalStorage(opts) {
25
+ return coreCreateGlobalStorage({
26
+ customHome: options.customHome,
27
+ dataDir: options.dataDir,
28
+ ...opts,
29
+ });
30
+ },
31
+ };
32
+ return {
33
+ name: platformName,
34
+ clock,
35
+ files,
36
+ modules,
37
+ process,
38
+ storage,
39
+ };
40
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./types.js";
2
+ export * from "./node-fs.js";
3
+ export * from "./default.js";
@@ -0,0 +1,3 @@
1
+ export * from "./types.js";
2
+ export * from "./node-fs.js";
3
+ export * from "./default.js";
@@ -0,0 +1,37 @@
1
+ import type { FileStat, FileSystem } from "./types.js";
2
+ /**
3
+ * NodeFileSystem 配置选项。
4
+ */
5
+ export interface NodeFileSystemOptions {
6
+ /**
7
+ * 安全沙箱根路径。
8
+ * 若指定,则所有文件系统操作将被强制约束在 rootDir 边界内,防止路径遍历逃逸。
9
+ */
10
+ rootDir?: string;
11
+ }
12
+ /**
13
+ * 基于 node:fs 和 node:path 的安全受限文件系统实现。
14
+ */
15
+ export declare class NodeFileSystem implements FileSystem {
16
+ private readonly rootDir?;
17
+ constructor(options?: NodeFileSystemOptions);
18
+ /**
19
+ * 安全解析并校验路径边界。
20
+ */
21
+ private resolvePath;
22
+ readFile(path: string, encoding?: string): Promise<string>;
23
+ writeFile(path: string, content: string | Uint8Array): Promise<void>;
24
+ readdir(dir: string): Promise<string[]>;
25
+ stat(path: string): Promise<FileStat>;
26
+ exists(path: string): Promise<boolean>;
27
+ mkdir(dir: string, options?: {
28
+ recursive?: boolean;
29
+ }): Promise<void>;
30
+ rm(path: string, options?: {
31
+ recursive?: boolean;
32
+ force?: boolean;
33
+ }): Promise<void>;
34
+ copy(src: string, dest: string, options?: {
35
+ recursive?: boolean;
36
+ }): Promise<void>;
37
+ }
@@ -0,0 +1,81 @@
1
+ import { promises as fs } from "node:fs";
2
+ import { dirname, isAbsolute, resolve } from "node:path";
3
+ import { assertPathWithinRoot } from "../utils/index.js";
4
+ /**
5
+ * 基于 node:fs 和 node:path 的安全受限文件系统实现。
6
+ */
7
+ export class NodeFileSystem {
8
+ rootDir;
9
+ constructor(options = {}) {
10
+ if (options.rootDir) {
11
+ this.rootDir = resolve(options.rootDir);
12
+ }
13
+ }
14
+ /**
15
+ * 安全解析并校验路径边界。
16
+ */
17
+ resolvePath(targetPath) {
18
+ if (typeof targetPath !== "string" || targetPath.includes("\0")) {
19
+ throw new Error("Invalid path: contains null byte or non-string argument");
20
+ }
21
+ if (this.rootDir) {
22
+ const resolved = isAbsolute(targetPath)
23
+ ? resolve(targetPath)
24
+ : resolve(this.rootDir, targetPath);
25
+ assertPathWithinRoot(this.rootDir, resolved);
26
+ return resolved;
27
+ }
28
+ return resolve(targetPath);
29
+ }
30
+ async readFile(path, encoding = "utf-8") {
31
+ const resolved = this.resolvePath(path);
32
+ return await fs.readFile(resolved, { encoding: (encoding || "utf-8") });
33
+ }
34
+ async writeFile(path, content) {
35
+ const resolved = this.resolvePath(path);
36
+ const parentDir = dirname(resolved);
37
+ await fs.mkdir(parentDir, { recursive: true });
38
+ await fs.writeFile(resolved, content);
39
+ }
40
+ async readdir(dir) {
41
+ const resolved = this.resolvePath(dir);
42
+ return await fs.readdir(resolved);
43
+ }
44
+ async stat(path) {
45
+ const resolved = this.resolvePath(path);
46
+ const s = await fs.stat(resolved);
47
+ return {
48
+ isDirectory: () => s.isDirectory(),
49
+ isFile: () => s.isFile(),
50
+ size: s.size,
51
+ };
52
+ }
53
+ async exists(path) {
54
+ try {
55
+ const resolved = this.resolvePath(path);
56
+ await fs.access(resolved);
57
+ return true;
58
+ }
59
+ catch {
60
+ return false;
61
+ }
62
+ }
63
+ async mkdir(dir, options) {
64
+ const resolved = this.resolvePath(dir);
65
+ await fs.mkdir(resolved, { recursive: options?.recursive ?? true });
66
+ }
67
+ async rm(path, options) {
68
+ const resolved = this.resolvePath(path);
69
+ await fs.rm(resolved, {
70
+ recursive: options?.recursive ?? true,
71
+ force: options?.force ?? true,
72
+ });
73
+ }
74
+ async copy(src, dest, options) {
75
+ const resolvedSrc = this.resolvePath(src);
76
+ const resolvedDest = this.resolvePath(dest);
77
+ const parentDir = dirname(resolvedDest);
78
+ await fs.mkdir(parentDir, { recursive: true });
79
+ await fs.cp(resolvedSrc, resolvedDest, { recursive: options?.recursive ?? true });
80
+ }
81
+ }
@@ -0,0 +1,104 @@
1
+ import type { ProcessAPI } from "@actiondock/sdk";
2
+ import type { Clock } from "../runtime/clock.js";
3
+ import type { ModuleLoader } from "../runtime/module-loader.js";
4
+ import type { RuntimeStorage } from "../storage/types.js";
5
+ /**
6
+ * 文件元数据信息契约。
7
+ */
8
+ export interface FileStat {
9
+ /** 是否为目录 */
10
+ isDirectory(): boolean;
11
+ /** 是否为普通文件 */
12
+ isFile(): boolean;
13
+ /** 文件字节大小 */
14
+ size: number;
15
+ }
16
+ /**
17
+ * 跨运行时统一文件系统抽象契约。
18
+ */
19
+ export interface FileSystem {
20
+ /** 读取文件内容 */
21
+ readFile(path: string, encoding?: string): Promise<string> | string;
22
+ /** 写入文件内容 */
23
+ writeFile(path: string, content: string | Uint8Array): Promise<void> | void;
24
+ /** 读取目录下的所有条目名称 */
25
+ readdir(dir: string): Promise<string[]> | string[];
26
+ /** 获取路径对应条目的元数据状态 */
27
+ stat(path: string): Promise<{
28
+ isDirectory(): boolean;
29
+ isFile(): boolean;
30
+ size: number;
31
+ }>;
32
+ /** 检查路径是否存在 */
33
+ exists(path: string): Promise<boolean> | boolean;
34
+ /** 创建目录 */
35
+ mkdir(dir: string, options?: {
36
+ recursive?: boolean;
37
+ }): Promise<void> | void;
38
+ /** 删除文件或目录 */
39
+ rm(path: string, options?: {
40
+ recursive?: boolean;
41
+ force?: boolean;
42
+ }): Promise<void> | void;
43
+ /** 拷贝文件或目录 */
44
+ copy(src: string, dest: string, options?: {
45
+ recursive?: boolean;
46
+ }): Promise<void> | void;
47
+ }
48
+ /**
49
+ * 跨运行时持久化存储工厂配置选项。
50
+ */
51
+ export interface StorageFactoryOptions {
52
+ projectRoot?: string;
53
+ dataDir?: string;
54
+ inMemory?: boolean;
55
+ customHome?: string;
56
+ }
57
+ /**
58
+ * 跨运行时全局存储工厂配置选项。
59
+ */
60
+ export interface GlobalStorageFactoryOptions {
61
+ dataDir?: string;
62
+ inMemory?: boolean;
63
+ customHome?: string;
64
+ }
65
+ /**
66
+ * 跨运行时持久化存储工厂契约。
67
+ */
68
+ export interface StorageFactory {
69
+ /**
70
+ * 为指定 Package 创建或连接运行时存储。
71
+ */
72
+ createStorage(packageId: string, options?: StorageFactoryOptions): RuntimeStorage;
73
+ /**
74
+ * 创建或连接跨 Package 共享的全局存储。
75
+ */
76
+ createGlobalStorage(options?: GlobalStorageFactoryOptions): RuntimeStorage;
77
+ }
78
+ /**
79
+ * 跨运行时 HTTP 服务启动工厂契约。
80
+ */
81
+ export interface HttpServerFactory {
82
+ /**
83
+ * 启动 HTTP 服务端实例。
84
+ */
85
+ launchHttpServer(options: any): Promise<any>;
86
+ }
87
+ /**
88
+ * 运行时底层环境核心标准契约。
89
+ * 提供统一的运行时契约,屏蔽宿主平台与测试沙箱环境的实现差异。
90
+ */
91
+ export interface RuntimePlatform {
92
+ /** 运行时平台名称标识 */
93
+ readonly name: "node" | "test";
94
+ /** 统一时间与时钟驱动 */
95
+ readonly clock: Clock;
96
+ /** 统一文件系统操作驱动 */
97
+ readonly files: FileSystem;
98
+ /** 动态源码模块加载驱动 */
99
+ readonly modules: ModuleLoader;
100
+ /** 子进程衍生与执行驱动 */
101
+ readonly process: ProcessAPI;
102
+ /** 持久化数据库存储驱动工厂 */
103
+ readonly storage: StorageFactory;
104
+ }
@@ -0,0 +1 @@
1
+ export {};