@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
@@ -1,527 +0,0 @@
1
- import { existsSync } from "node:fs";
2
- import { randomUUID } from "node:crypto";
3
- import type {
4
- ActionContext,
5
- ActionDefinition,
6
- ActionRef,
7
- ExecutionResult,
8
- JsonValue,
9
- Logger,
10
- ProcessAPI,
11
- ProgressReporter,
12
- RuntimeError,
13
- RunRecord,
14
- } from "@actiondock/sdk";
15
- import { ActionResolver } from "../catalog/action-resolver";
16
- import { loadActions, loadProjectConfig } from "../project/loader";
17
- import type { ProjectConfig } from "../project/types";
18
- import { resolveActionProject } from "../registry/registry";
19
- import { validateSchema } from "../schema/validator";
20
- import type { RuntimeStorage, TerminalRunStatus } from "../storage/types";
21
- import { createActionContext, StderrLogger } from "./context";
22
-
23
- /**
24
- * ActionRunner 初始化配置选项。
25
- */
26
- export interface RunnerOptions {
27
- /** 运行所属的 Package ID */
28
- packageId: string;
29
- /** 持久化运行时存储实例(SQLite) */
30
- storage: RuntimeStorage;
31
- /** 项目元数据配置 */
32
- projectConfig?: ProjectConfig;
33
- /** CLI 或上层注入的临时配置覆盖项 */
34
- configOverrides?: Record<string, unknown>;
35
- /** 预加载的 Action 映射表 */
36
- actions?: Map<string, ActionDefinition>;
37
- /** 外部注入的进程执行器 */
38
- process?: ProcessAPI;
39
- /** 动态解析跨包或未注册 Action 的委托函数 */
40
- actionResolver?: (
41
- ref: ActionRef | string,
42
- currentPackageId?: string
43
- ) => ActionDefinition | undefined | Promise<ActionDefinition | undefined>;
44
- }
45
-
46
- /**
47
- * 启动 Action 执行时的可选控制参数。
48
- */
49
- export interface ExecutionStartOptions {
50
- /** 显式指定的运行 ID */
51
- runId?: string;
52
- /** 根运行 ID */
53
- rootRunId?: string;
54
- /** 父级运行 ID(嵌套调用场景下建立调用链树) */
55
- parentRunId?: string;
56
- /** 包物理实例标识 */
57
- packageInstanceId?: string;
58
- /** 快照代次标识 */
59
- generationId?: string;
60
- /** 执行所有者标识 */
61
- ownerId?: string;
62
- /** 调用栈数组(用于检测 A -> B -> A 环路死锁) */
63
- callStack?: string[];
64
- /** 外部传入的 AbortSignal 取消信号 */
65
- signal?: AbortSignal;
66
- /** 最大超时时间(毫秒),超时将自动中止执行并标记为 ACTION_TIMEOUT */
67
- timeoutMs?: number;
68
- /** 外部注入的进程执行器 */
69
- process?: ProcessAPI;
70
- /** 外部注入的进度报告器 */
71
- progress?: ProgressReporter;
72
- /** 外部注入的日志记录器 */
73
- logger?: Logger;
74
- }
75
-
76
- /**
77
- * 异步执行句柄,支持获取执行结果 Promise 与主动取消操作。
78
- */
79
- export interface ExecutionHandle {
80
- /** 本次执行生成的全局唯一运行 ID */
81
- runId: string;
82
- /** 最终执行结果信封 Promise */
83
- result: Promise<ExecutionResult>;
84
- /**
85
- * 取消当前正在执行的任务
86
- * @param reason 取消原因
87
- * @returns 是否成功触发取消
88
- */
89
- cancel(reason?: string): boolean;
90
- }
91
-
92
- /**
93
- * ActionDock 核心执行引擎(ActionRunner)。
94
- *
95
- * 职责:
96
- * 1. 负责 Action 执行的全生命周期管理(校验、隔离、跟踪、落库)。
97
- * 2. 入参 (inputSchema) 与出参 (outputSchema) 的 JSON Schema 严格校验。
98
- * 3. 嵌套 Action 相互调用的环路检测(Cycle Detection)。
99
- * 4. 超时 (Timeout) 与中断信号 (AbortSignal) 竞态控制。
100
- * 5. 自动记录并持久化 RunRecord 运行记录至 SQLite 存储。
101
- */
102
- export class ActionRunner {
103
- private packageId: string;
104
- private storage: RuntimeStorage;
105
- private projectConfig?: ProjectConfig;
106
- private configOverrides: Record<string, unknown>;
107
- private actions: Map<string, ActionDefinition>;
108
- private actionResolver?: (
109
- ref: ActionRef | string,
110
- currentPackageId?: string
111
- ) => ActionDefinition | undefined | Promise<ActionDefinition | undefined>;
112
-
113
- constructor(options: RunnerOptions) {
114
- this.packageId = options.packageId;
115
- this.storage = options.storage;
116
- this.projectConfig = options.projectConfig;
117
- this.configOverrides = options.configOverrides || {};
118
- this.actions = options.actions || new Map();
119
- this.actionResolver = options.actionResolver;
120
- }
121
-
122
- /**
123
- * 注册单个 Action 到当前 Runner。
124
- */
125
- public registerAction(action: ActionDefinition): void {
126
- this.actions.set(action.id, action);
127
- }
128
-
129
- /**
130
- * 根据 ID 检索注册的 Action。
131
- */
132
- public getAction(id: string): ActionDefinition | undefined {
133
- return this.actions.get(id);
134
- }
135
-
136
- /**
137
- * 动态解析 Action(支持本地注册表、自定义解析器委托与已链接包目录索引检索)。
138
- *
139
- * @param actionOrRef Action 定义对象、引用或标识符
140
- * @returns 解析出的 ActionDefinition,若未找到则返回 undefined
141
- */
142
- public async resolveAction(
143
- actionOrRef: ActionDefinition | ActionRef | string
144
- ): Promise<ActionDefinition | undefined> {
145
- if (
146
- typeof actionOrRef === "object" &&
147
- "run" in actionOrRef &&
148
- typeof (actionOrRef as any).run === "function"
149
- ) {
150
- return actionOrRef as ActionDefinition;
151
- }
152
-
153
- const ref = actionOrRef as ActionRef | string;
154
- const parsed = ActionResolver.parseRef(ref);
155
- const targetActionId = parsed.actionId;
156
- const targetPackageId = parsed.packageId;
157
-
158
- // 1. 本地 actions 映射表优先检索
159
- if (targetPackageId && targetPackageId !== this.packageId) {
160
- if (this.actions.has(`${targetPackageId}/${targetActionId}`)) {
161
- return this.actions.get(`${targetPackageId}/${targetActionId}`);
162
- }
163
- } else {
164
- if (this.actions.has(targetActionId)) {
165
- return this.actions.get(targetActionId);
166
- }
167
- if (this.packageId && this.actions.has(`${this.packageId}/${targetActionId}`)) {
168
- return this.actions.get(`${this.packageId}/${targetActionId}`);
169
- }
170
- }
171
-
172
- // 2. 外部注入的自定义 actionResolver 调度
173
- if (this.actionResolver) {
174
- const customResolved = await this.actionResolver(ref, this.packageId);
175
- if (customResolved) {
176
- if (targetPackageId && targetPackageId !== this.packageId) {
177
- this.actions.set(`${targetPackageId}/${targetActionId}`, customResolved);
178
- } else {
179
- this.actions.set(targetActionId, customResolved);
180
- if (this.packageId) {
181
- this.actions.set(`${this.packageId}/${targetActionId}`, customResolved);
182
- }
183
- }
184
- return customResolved;
185
- }
186
- }
187
-
188
- // 3. 基于全局链接注册表与目录索引的动态寻址与按需加载
189
- try {
190
- const identifier = targetPackageId
191
- ? `${targetPackageId}/${targetActionId}`
192
- : targetActionId;
193
- const resolved = await resolveActionProject(identifier);
194
- if (resolved && existsSync(resolved.projectRoot)) {
195
- const config = loadProjectConfig(resolved.projectRoot);
196
- const actionsMap = await loadActions(resolved.projectRoot, config.actionsDir, {
197
- autoInstall: false,
198
- });
199
- const matched = actionsMap.get(resolved.actionId);
200
- if (matched) {
201
- this.actions.set(`${resolved.packageId}/${resolved.actionId}`, matched);
202
- // 仅当目标包就是当前项目时才注册短标识符,避免跨包动态载入污染全局短标识符
203
- if (!targetPackageId || resolved.packageId === this.packageId) {
204
- this.actions.set(resolved.actionId, matched);
205
- }
206
- return matched;
207
- }
208
- }
209
- } catch {
210
- // 忽略寻址异常并返回 undefined
211
- }
212
-
213
- return undefined;
214
- }
215
-
216
- /**
217
- * 获取当前 Runner 已注册的所有 Action 列表。
218
- */
219
- public listActions(): ActionDefinition[] {
220
- return Array.from(this.actions.values());
221
- }
222
-
223
- /**
224
- * 异步启动 Action 的执行并立即返回 ExecutionHandle 句柄。
225
- *
226
- * @param actionOrId Action 定义对象、引用或标识符
227
- * @param input 传递给 Action 的输入数据
228
- * @param options 执行控制选项(超时、取消信号、父运行 ID 等)
229
- * @returns 包含 runId、result Promise 和 cancel 方法的执行句柄
230
- */
231
- start(
232
- actionOrId: ActionDefinition | ActionRef | string,
233
- input: unknown = {},
234
- options: ExecutionStartOptions = {}
235
- ): ExecutionHandle {
236
- const runId = options.runId || randomUUID();
237
- const startedAt = new Date().toISOString();
238
- const callStack = [...(options.callStack || [])];
239
-
240
- let action: ActionDefinition | undefined;
241
- let targetActionId: string;
242
- let targetPackageId: string = this.packageId;
243
-
244
- if (
245
- typeof actionOrId === "object" &&
246
- "run" in actionOrId &&
247
- typeof (actionOrId as any).run === "function"
248
- ) {
249
- action = actionOrId as ActionDefinition;
250
- targetActionId = action.id;
251
- } else {
252
- const parsed = ActionResolver.parseRef(actionOrId as ActionRef | string);
253
- targetActionId = parsed.actionId;
254
- if (parsed.packageId) {
255
- targetPackageId = parsed.packageId;
256
- }
257
-
258
- if (parsed.packageId && parsed.packageId !== this.packageId) {
259
- action = this.actions.get(`${parsed.packageId}/${targetActionId}`);
260
- } else {
261
- action =
262
- this.actions.get(targetActionId) ||
263
- (this.packageId ? this.actions.get(`${this.packageId}/${targetActionId}`) : undefined);
264
- }
265
- }
266
-
267
- // 1. 环路死锁检测 (Cycle Detection)
268
- const isExternal = Boolean(targetPackageId && targetPackageId !== this.packageId);
269
- const callKey = isExternal
270
- ? `${targetPackageId}/${targetActionId}`
271
- : targetActionId;
272
-
273
- const hasCycle = isExternal
274
- ? callStack.includes(callKey)
275
- : (callStack.includes(callKey) || (this.packageId ? callStack.includes(`${this.packageId}/${targetActionId}`) : false));
276
-
277
- if (hasCycle) {
278
- const error: RuntimeError = {
279
- code: "ACTION_CYCLE_DETECTED",
280
- message: `Cycle detected in action invocation: ${callStack.join(" -> ")} -> ${callKey}`,
281
- };
282
- return {
283
- runId,
284
- result: Promise.resolve({ ok: false, runId, error }),
285
- cancel: () => false,
286
- };
287
- }
288
- callStack.push(callKey);
289
-
290
- // 2. 输入参数 JSON Schema 校验(若 action 已就绪)
291
- if (action?.inputSchema) {
292
- const val = validateSchema(action.inputSchema, input);
293
- if (!val.valid) {
294
- const error: RuntimeError = {
295
- code: "INPUT_VALIDATION_FAILED",
296
- message: `Input schema validation failed for action '${action.id}'`,
297
- details: val.errors,
298
- };
299
- return {
300
- runId,
301
- result: Promise.resolve({ ok: false, runId, error }),
302
- cancel: () => false,
303
- };
304
- }
305
- }
306
-
307
- // 3. 插入初始运行记录 (状态: running)
308
- const initialRun: RunRecord = {
309
- id: runId,
310
- rootRunId: options.rootRunId || options.parentRunId || runId,
311
- parentRunId: options.parentRunId,
312
- packageId: targetPackageId,
313
- packageInstanceId: options.packageInstanceId || targetPackageId,
314
- actionId: targetActionId,
315
- generationId: options.generationId || "1",
316
- ownerId: options.ownerId || "local",
317
- status: "running",
318
- input: input as JsonValue | undefined,
319
- startedAt,
320
- };
321
- this.storage.createRun(initialRun);
322
-
323
- // 4. 初始化 AbortController 与超时定时器
324
- const controller = new AbortController();
325
- if (options.signal) {
326
- if (options.signal.aborted) {
327
- controller.abort(options.signal.reason);
328
- } else {
329
- options.signal.addEventListener(
330
- "abort",
331
- () => controller.abort(options.signal?.reason),
332
- { once: true }
333
- );
334
- }
335
- }
336
-
337
- let isTimeout = false;
338
- let timeoutTimer: ReturnType<typeof setTimeout> | undefined;
339
- if (typeof options.timeoutMs === "number" && options.timeoutMs > 0) {
340
- timeoutTimer = setTimeout(() => {
341
- isTimeout = true;
342
- controller.abort(new Error(`Action exceeded timeout of ${options.timeoutMs}ms`));
343
- }, options.timeoutMs);
344
- }
345
-
346
- let finalized = false;
347
- const finalizeRun = (
348
- status: TerminalRunStatus,
349
- output?: unknown,
350
- error?: RuntimeError
351
- ) => {
352
- if (timeoutTimer) {
353
- clearTimeout(timeoutTimer);
354
- timeoutTimer = undefined;
355
- }
356
- if (finalized) return;
357
- finalized = true;
358
- this.storage.updateRun(runId, status, output, error);
359
- };
360
-
361
- // 5. 构建 ActionContext 运行时上下文
362
- const ctx = createActionContext({
363
- storage: this.storage,
364
- overrides: this.configOverrides,
365
- projectConfig: this.projectConfig,
366
- runId,
367
- rootRunId: initialRun.rootRunId,
368
- parentRunId: options.parentRunId,
369
- signal: controller.signal,
370
- process: options.process,
371
- progress: options.progress,
372
- logger: options.logger || new StderrLogger(action?.id || targetActionId),
373
- onActionInvoke: async (childAction, childInput, parentRunId) => {
374
- const childResult = await this.execute(childAction, childInput, {
375
- rootRunId: initialRun.rootRunId,
376
- parentRunId,
377
- callStack,
378
- signal: controller.signal,
379
- process: options.process,
380
- progress: options.progress,
381
- logger: options.logger,
382
- });
383
- if (!childResult.ok) {
384
- const err = new Error(childResult.error.message);
385
- (err as any).code = childResult.error.code;
386
- (err as any).details = childResult.error.details;
387
- throw err;
388
- }
389
- return childResult.data;
390
- },
391
- });
392
-
393
- // 6. 执行 Action 业务逻辑并与取消/超时信号进行竞态
394
- const abortPromise = new Promise<never>((_, reject) => {
395
- if (controller.signal.aborted) {
396
- reject(controller.signal.reason || new Error("Action execution was cancelled"));
397
- } else {
398
- controller.signal.addEventListener(
399
- "abort",
400
- () => reject(controller.signal.reason || new Error("Action execution was cancelled")),
401
- { once: true }
402
- );
403
- }
404
- });
405
-
406
- const executionPromise = (async (): Promise<ExecutionResult> => {
407
- try {
408
- let currentAction = action;
409
- if (!currentAction) {
410
- currentAction = await this.resolveAction(actionOrId);
411
- if (!currentAction) {
412
- const error: RuntimeError = {
413
- code: "ACTION_NOT_FOUND",
414
- message: `Action '${targetActionId}' not found in registry or linked packages`,
415
- };
416
- finalizeRun("failed", undefined, error);
417
- return { ok: false, runId, error };
418
- }
419
-
420
- if (currentAction.inputSchema) {
421
- const val = validateSchema(currentAction.inputSchema, input);
422
- if (!val.valid) {
423
- const error: RuntimeError = {
424
- code: "INPUT_VALIDATION_FAILED",
425
- message: `Input schema validation failed for action '${currentAction.id}'`,
426
- details: val.errors,
427
- };
428
- finalizeRun("failed", undefined, error);
429
- return { ok: false, runId, error };
430
- }
431
- }
432
- }
433
-
434
- const rawOutput = await Promise.race([
435
- Promise.resolve().then(() => currentAction!.run(input, ctx)),
436
- abortPromise,
437
- ]);
438
-
439
- // 输出结果 Schema 校验
440
- if (currentAction.outputSchema) {
441
- const outVal = validateSchema(currentAction.outputSchema, rawOutput);
442
- if (!outVal.valid) {
443
- const error: RuntimeError = {
444
- code: "OUTPUT_VALIDATION_FAILED",
445
- message: `Output schema validation failed for action '${currentAction.id}'`,
446
- details: outVal.errors,
447
- };
448
- finalizeRun("failed", undefined, error);
449
- return { ok: false, runId, error };
450
- }
451
- }
452
-
453
- finalizeRun("success", rawOutput);
454
- return {
455
- ok: true,
456
- runId,
457
- data: rawOutput as JsonValue,
458
- };
459
- } catch (err: any) {
460
- if (isTimeout) {
461
- const error: RuntimeError = {
462
- code: "ACTION_TIMEOUT",
463
- message: `Action exceeded timeout of ${options.timeoutMs}ms`,
464
- };
465
- finalizeRun("failed", undefined, error);
466
- return { ok: false, runId, error };
467
- }
468
-
469
- if (controller.signal.aborted) {
470
- const reason = controller.signal.reason;
471
- const reasonMsg =
472
- reason instanceof Error
473
- ? reason.message
474
- : typeof reason === "string"
475
- ? reason
476
- : undefined;
477
- const error: RuntimeError = {
478
- code: "ACTION_CANCELLED",
479
- message: "Action execution was cancelled",
480
- details: reasonMsg ? { reason: reasonMsg } : undefined,
481
- };
482
- finalizeRun("cancelled", undefined, error);
483
- return { ok: false, runId, error };
484
- }
485
-
486
- const error: RuntimeError = {
487
- code: err?.code || "ACTION_FAILED",
488
- message: err?.message || String(err),
489
- details: err?.details,
490
- };
491
- finalizeRun("failed", undefined, error);
492
- return {
493
- ok: false,
494
- runId,
495
- error,
496
- };
497
- }
498
- })();
499
-
500
- return {
501
- runId,
502
- result: executionPromise,
503
- cancel: (reason?: string): boolean => {
504
- if (finalized || controller.signal.aborted) {
505
- return false;
506
- }
507
- controller.abort(new Error(reason || "Action execution was cancelled"));
508
- return true;
509
- },
510
- };
511
- }
512
-
513
- /**
514
- * 同步等待方式执行指定 Action,直接返回 ExecutionResult 信封结果。
515
- *
516
- * @param actionOrId Action 定义对象、引用或标识符
517
- * @param input 输入参数
518
- * @param options 执行控制选项
519
- */
520
- async execute(
521
- actionOrId: ActionDefinition | ActionRef | string,
522
- input: unknown = {},
523
- options: ExecutionStartOptions = {}
524
- ): Promise<ExecutionResult> {
525
- return this.start(actionOrId, input, options).result;
526
- }
527
- }