@actiondock/core 2.0.11 → 2.0.12

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 (119) hide show
  1. package/dist/build/templates.d.ts +19 -0
  2. package/dist/catalog/action-index.d.ts +9 -0
  3. package/dist/catalog/action-resolver.d.ts +20 -0
  4. package/dist/catalog/location-registry.d.ts +15 -0
  5. package/dist/catalog/package-catalog.d.ts +7 -0
  6. package/dist/catalog/types.d.ts +68 -0
  7. package/dist/doctor/doctor.d.ts +6 -0
  8. package/dist/doctor/types.d.ts +23 -0
  9. package/dist/execution/index.d.ts +2 -0
  10. package/dist/execution/service.d.ts +74 -0
  11. package/dist/execution/types.d.ts +74 -0
  12. package/dist/export/templates.d.ts +33 -0
  13. package/dist/filter/intent.d.ts +33 -0
  14. package/{src/index.ts → dist/index.d.ts} +1 -1
  15. package/dist/index.js +8458 -0
  16. package/dist/profile/client.d.ts +116 -0
  17. package/dist/profile/manager.d.ts +47 -0
  18. package/dist/profile/types.d.ts +61 -0
  19. package/dist/project/closure.d.ts +25 -0
  20. package/{src/project/index.ts → dist/project/index.d.ts} +1 -0
  21. package/dist/project/init.d.ts +27 -0
  22. package/dist/project/loader.d.ts +105 -0
  23. package/dist/project/manifest.d.ts +44 -0
  24. package/dist/project/types.d.ts +131 -0
  25. package/dist/registry/registry.d.ts +24 -0
  26. package/dist/registry/types.d.ts +117 -0
  27. package/dist/runtime/clock.d.ts +21 -0
  28. package/dist/runtime/context.d.ts +75 -0
  29. package/dist/runtime/env.d.ts +54 -0
  30. package/dist/runtime/events.d.ts +61 -0
  31. package/dist/runtime/execution-manager.d.ts +48 -0
  32. package/{src/runtime/index.ts → dist/runtime/index.d.ts} +0 -1
  33. package/dist/runtime/module-loader.d.ts +42 -0
  34. package/dist/runtime/process.d.ts +11 -0
  35. package/dist/runtime/runner.d.ts +186 -0
  36. package/dist/runtime/standalone.d.ts +40 -0
  37. package/dist/schema/validator.d.ts +28 -0
  38. package/dist/server/body.d.ts +40 -0
  39. package/{src/server/index.ts → dist/server/index.d.ts} +0 -1
  40. package/dist/server/routes/actions.d.ts +5 -0
  41. package/dist/server/routes/common.d.ts +36 -0
  42. package/dist/server/routes/config.d.ts +5 -0
  43. package/dist/server/routes/doctor.d.ts +5 -0
  44. package/dist/server/routes/health.d.ts +5 -0
  45. package/dist/server/routes/info.d.ts +5 -0
  46. package/dist/server/routes/playbooks.d.ts +5 -0
  47. package/dist/server/routes/runs.d.ts +5 -0
  48. package/dist/server/routes/state.d.ts +5 -0
  49. package/dist/server/runtime-registry.d.ts +78 -0
  50. package/dist/server/security.d.ts +37 -0
  51. package/dist/server/server.d.ts +15 -0
  52. package/dist/server/types.d.ts +59 -0
  53. package/dist/storage/driver.d.ts +15 -0
  54. package/dist/storage/index.d.ts +44 -0
  55. package/{src/storage/mask.ts → dist/storage/mask.d.ts} +5 -20
  56. package/dist/storage/sqlite.d.ts +66 -0
  57. package/dist/storage/types.d.ts +121 -0
  58. package/dist/utils/index.d.ts +29 -0
  59. package/dist/version.d.ts +4 -0
  60. package/package.json +11 -10
  61. package/src/build/templates.ts +0 -59
  62. package/src/catalog/action-index.ts +0 -92
  63. package/src/catalog/action-resolver.ts +0 -120
  64. package/src/catalog/location-registry.ts +0 -134
  65. package/src/catalog/package-catalog.ts +0 -87
  66. package/src/catalog/types.ts +0 -75
  67. package/src/doctor/doctor.ts +0 -419
  68. package/src/doctor/types.ts +0 -25
  69. package/src/execution/index.ts +0 -2
  70. package/src/execution/service.ts +0 -322
  71. package/src/execution/types.ts +0 -73
  72. package/src/export/templates.ts +0 -590
  73. package/src/filter/intent.ts +0 -154
  74. package/src/profile/client.ts +0 -552
  75. package/src/profile/manager.ts +0 -341
  76. package/src/profile/types.ts +0 -71
  77. package/src/project/init.ts +0 -242
  78. package/src/project/loader.ts +0 -479
  79. package/src/project/manifest.ts +0 -299
  80. package/src/project/types.ts +0 -141
  81. package/src/registry/registry.ts +0 -940
  82. package/src/registry/types.ts +0 -127
  83. package/src/runtime/clock.ts +0 -41
  84. package/src/runtime/context.ts +0 -259
  85. package/src/runtime/env.ts +0 -172
  86. package/src/runtime/events.ts +0 -142
  87. package/src/runtime/execution-manager.ts +0 -74
  88. package/src/runtime/module-loader.ts +0 -67
  89. package/src/runtime/process.ts +0 -245
  90. package/src/runtime/runner.ts +0 -527
  91. package/src/runtime/standalone.ts +0 -429
  92. package/src/schema/validator.ts +0 -61
  93. package/src/server/body.ts +0 -112
  94. package/src/server/routes/actions.ts +0 -262
  95. package/src/server/routes/common.ts +0 -126
  96. package/src/server/routes/config.ts +0 -147
  97. package/src/server/routes/doctor.ts +0 -29
  98. package/src/server/routes/health.ts +0 -40
  99. package/src/server/routes/info.ts +0 -221
  100. package/src/server/routes/playbooks.ts +0 -109
  101. package/src/server/routes/runs.ts +0 -301
  102. package/src/server/routes/state.ts +0 -133
  103. package/src/server/runtime-registry.ts +0 -115
  104. package/src/server/security.ts +0 -115
  105. package/src/server/server.ts +0 -251
  106. package/src/server/types.ts +0 -57
  107. package/src/storage/driver.ts +0 -126
  108. package/src/storage/index.ts +0 -81
  109. package/src/storage/sqlite.ts +0 -714
  110. package/src/storage/types.ts +0 -139
  111. package/src/utils/index.ts +0 -62
  112. /package/{src/build/index.ts → dist/build/index.d.ts} +0 -0
  113. /package/{src/catalog/index.ts → dist/catalog/index.d.ts} +0 -0
  114. /package/{src/doctor/index.ts → dist/doctor/index.d.ts} +0 -0
  115. /package/{src/export/index.ts → dist/export/index.d.ts} +0 -0
  116. /package/{src/filter/index.ts → dist/filter/index.d.ts} +0 -0
  117. /package/{src/profile/index.ts → dist/profile/index.d.ts} +0 -0
  118. /package/{src/registry/index.ts → dist/registry/index.d.ts} +0 -0
  119. /package/{src/server/routes/index.ts → dist/server/routes/index.d.ts} +0 -0
@@ -1,142 +0,0 @@
1
- import type { ExecutionEvent } from "@actiondock/sdk";
2
-
3
- export interface EventSink {
4
- emit(event: ExecutionEvent): void;
5
- subscribe(
6
- runId: string,
7
- options?: { after?: number; signal?: AbortSignal }
8
- ): AsyncIterable<ExecutionEvent>;
9
- clear(runId: string): void;
10
- }
11
-
12
- /**
13
- * 进程内有界事件缓冲区实现。
14
- * 遵循设计文档:每个运行最多保留 1024 条或 1MB 事件,支持单调序号。
15
- */
16
- export class InMemoryEventSink implements EventSink {
17
- private eventsByRun = new Map<string, ExecutionEvent[]>();
18
- private listeners = new Map<string, Set<(event: ExecutionEvent) => void>>();
19
- private maxEventsPerRun = 1024;
20
-
21
- emit(event: ExecutionEvent): void {
22
- let list = this.eventsByRun.get(event.runId);
23
- if (!list) {
24
- list = [];
25
- this.eventsByRun.set(event.runId, list);
26
- }
27
-
28
- if (list.length >= this.maxEventsPerRun) {
29
- // 淘汰旧日志和进度事件,保留状态和结果
30
- const nonEssentialIndex = list.findIndex((e) => e.type === "log" || e.type === "progress");
31
- if (nonEssentialIndex >= 0) {
32
- list.splice(nonEssentialIndex, 1);
33
- } else {
34
- list.shift();
35
- }
36
- }
37
- list.push(event);
38
-
39
- const subs = this.listeners.get(event.runId);
40
- if (subs) {
41
- for (const listener of subs) {
42
- try {
43
- listener(event);
44
- } catch {
45
- // 忽略单个监听器内部异常
46
- }
47
- }
48
- }
49
- }
50
-
51
- async *subscribe(
52
- runId: string,
53
- options: { after?: number; signal?: AbortSignal } = {}
54
- ): AsyncIterable<ExecutionEvent> {
55
- const after = options.after ?? -1;
56
- const history = this.eventsByRun.get(runId) || [];
57
-
58
- for (const evt of history) {
59
- if (evt.sequence > after) {
60
- yield evt;
61
- }
62
- }
63
-
64
- const lastEvt = history[history.length - 1];
65
- if (lastEvt && (lastEvt.type === "finish" || lastEvt.type === "status" && lastEvt.status !== "running")) {
66
- return;
67
- }
68
-
69
- const queue: ExecutionEvent[] = [];
70
- let notify: (() => void) | null = null;
71
- let done = false;
72
-
73
- const listener = (evt: ExecutionEvent) => {
74
- if (evt.sequence > after) {
75
- queue.push(evt);
76
- if (notify) {
77
- notify();
78
- notify = null;
79
- }
80
- if (evt.type === "finish") {
81
- done = true;
82
- }
83
- }
84
- };
85
-
86
- let subs = this.listeners.get(runId);
87
- if (!subs) {
88
- subs = new Set();
89
- this.listeners.set(runId, subs);
90
- }
91
- subs.add(listener);
92
-
93
- const cleanup = () => {
94
- subs?.delete(listener);
95
- if (subs && subs.size === 0) {
96
- this.listeners.delete(runId);
97
- }
98
- };
99
-
100
- if (options.signal) {
101
- options.signal.addEventListener("abort", () => {
102
- done = true;
103
- if (notify) {
104
- notify();
105
- notify = null;
106
- }
107
- }, { once: true });
108
- }
109
-
110
- try {
111
- while (!done && !options.signal?.aborted) {
112
- if (queue.length > 0) {
113
- yield queue.shift()!;
114
- } else {
115
- await new Promise<void>((resolve) => {
116
- notify = resolve;
117
- });
118
- }
119
- }
120
- while (queue.length > 0) {
121
- yield queue.shift()!;
122
- }
123
- } finally {
124
- cleanup();
125
- }
126
- }
127
-
128
- clear(runId: string): void {
129
- this.eventsByRun.delete(runId);
130
- this.listeners.delete(runId);
131
- }
132
- }
133
-
134
- let defaultEventSink: EventSink = new InMemoryEventSink();
135
-
136
- export function getDefaultEventSink(): EventSink {
137
- return defaultEventSink;
138
- }
139
-
140
- export function setDefaultEventSink(sink: EventSink): void {
141
- defaultEventSink = sink;
142
- }
@@ -1,74 +0,0 @@
1
- import type { ExecutionHandle } from "./runner";
2
-
3
- /**
4
- * 内存中活跃执行句柄(In-flight Execution Handles)生命周期管理器。
5
- *
6
- * 职责:
7
- * 1. 集中追踪正在执行的异步 Action 任务句柄。
8
- * 2. 任务完成(无论成功或失败)后通过 Promise.finally 自动注销,防止内存泄漏。
9
- * 3. 支持依据 runId 查询、遍历或主动发送取消信号(cancel)。
10
- */
11
- export class ExecutionManager {
12
- private active = new Map<string, ExecutionHandle>();
13
-
14
- /**
15
- * 注册一个活跃的执行句柄。
16
- * 当底层 Promise 完成结算(resolve/reject)时,自动从活跃映射表中移除。
17
- *
18
- * @param handle 执行句柄对象
19
- */
20
- public register(handle: ExecutionHandle): void {
21
- this.active.set(handle.runId, handle);
22
- handle.result.finally(() => {
23
- this.active.delete(handle.runId);
24
- });
25
- }
26
-
27
- /**
28
- * 根据 runId 检索正在执行的任务句柄。
29
- *
30
- * @param runId 运行 ID
31
- * @returns 匹配的 ExecutionHandle 或 undefined
32
- */
33
- public get(runId: string): ExecutionHandle | undefined {
34
- return this.active.get(runId);
35
- }
36
-
37
- /**
38
- * 向指定 runId 的在途执行任务发送取消信号。
39
- *
40
- * @param runId 目标运行 ID
41
- * @param reason 取消原因描述
42
- * @returns 若句柄存在且成功触发中断返回 true;若任务不存在或已完成返回 false
43
- */
44
- public cancel(runId: string, reason?: string): boolean {
45
- const handle = this.active.get(runId);
46
- if (!handle) {
47
- return false;
48
- }
49
- return handle.cancel(reason);
50
- }
51
-
52
- /**
53
- * 手动从活跃集合中移除执行句柄。
54
- *
55
- * @param runId 运行 ID
56
- */
57
- public remove(runId: string): void {
58
- this.active.delete(runId);
59
- }
60
-
61
- /**
62
- * 获取当前系统中所有正在执行的活跃句柄列表。
63
- */
64
- public list(): ExecutionHandle[] {
65
- return Array.from(this.active.values());
66
- }
67
-
68
- /**
69
- * 清空所有活跃执行句柄。
70
- */
71
- public clear(): void {
72
- this.active.clear();
73
- }
74
- }
@@ -1,67 +0,0 @@
1
- import { pathToFileURL } from "node:url";
2
-
3
- /**
4
- * 统一源码模块加载器接口。
5
- * 解耦 Action 与各类扩展模块的具体加载机制(如 ECMAScript 原生 import、tsx 动态转译加载等)。
6
- */
7
- export interface ModuleLoader {
8
- /**
9
- * 解析模块标识符为绝对路径或完整 URL。
10
- *
11
- * @param specifier 模块规范说明符或物理路径
12
- * @param parentPath 发起解析的父级文件或目录路径
13
- */
14
- resolve?(specifier: string, parentPath?: string): string;
15
-
16
- /**
17
- * 动态加载模块并返回命名空间全量导出对象。
18
- *
19
- * @param specifier 模块规范说明符或物理路径
20
- * @param parentPath 发起加载的父级文件或目录路径
21
- */
22
- load<T = any>(specifier: string, parentPath?: string): Promise<T>;
23
-
24
- /**
25
- * 加载模块并解包其默认导出(default 或 action 属性)。
26
- *
27
- * @param specifier 模块规范说明符或物理路径
28
- * @param parentPath 发起加载的父级文件或目录路径
29
- */
30
- loadDefault?<T = any>(specifier: string, parentPath?: string): Promise<T>;
31
- }
32
-
33
- /**
34
- * 基于标准 ECMAScript 动态 import 的默认模块加载器。
35
- */
36
- export class DefaultModuleLoader implements ModuleLoader {
37
- async load<T = any>(specifier: string, _parentPath?: string): Promise<T> {
38
- const importSpecifier = specifier.startsWith("file://")
39
- ? specifier
40
- : pathToFileURL(specifier).href;
41
- return (await import(importSpecifier)) as T;
42
- }
43
-
44
- async loadDefault<T = any>(specifier: string, parentPath?: string): Promise<T> {
45
- const mod = await this.load<any>(specifier, parentPath);
46
- return (mod?.default !== undefined ? mod.default : mod?.action !== undefined ? mod.action : mod) as T;
47
- }
48
- }
49
-
50
- let globalModuleLoader: ModuleLoader | undefined;
51
-
52
- /**
53
- * 注册全局模块加载器实现。
54
- */
55
- export function setModuleLoader(loader: ModuleLoader): void {
56
- globalModuleLoader = loader;
57
- }
58
-
59
- /**
60
- * 获取当前全局模块加载器,若未显式注册则回退使用 DefaultModuleLoader。
61
- */
62
- export function getModuleLoader(): ModuleLoader {
63
- if (!globalModuleLoader) {
64
- globalModuleLoader = new DefaultModuleLoader();
65
- }
66
- return globalModuleLoader;
67
- }
@@ -1,245 +0,0 @@
1
- import { spawn } from "node:child_process";
2
- import type {
3
- DetachedProcessOptions,
4
- DetachedProcessResult,
5
- ProcessAPI,
6
- ProcessExecOptions,
7
- ProcessResult,
8
- RuntimeError,
9
- } from "@actiondock/sdk";
10
-
11
- export type ProcessExecutor = ProcessAPI;
12
-
13
- let globalProcessExecutor: ProcessExecutor | undefined;
14
-
15
- export function setProcessExecutor(executor: ProcessExecutor): void {
16
- globalProcessExecutor = executor;
17
- }
18
-
19
- export function getProcessExecutor(): ProcessExecutor {
20
- if (!globalProcessExecutor) {
21
- globalProcessExecutor = new DefaultProcessExecutor();
22
- }
23
- return globalProcessExecutor;
24
- }
25
-
26
- /**
27
- * 基于 Node.js 标准 child_process 实现的基础进程执行器。
28
- */
29
- export class DefaultProcessExecutor implements ProcessExecutor {
30
- async exec(
31
- command: string,
32
- args: string[] = [],
33
- options: ProcessExecOptions = {}
34
- ): Promise<ProcessResult> {
35
- const startTime = Date.now();
36
- const maxOutputBytes = options.maxOutputBytes ?? 10 * 1024 * 1024;
37
-
38
- return new Promise<ProcessResult>((resolve, reject) => {
39
- let stdoutBuf = "";
40
- let stderrBuf = "";
41
- let totalBytes = 0;
42
- let timedOut = false;
43
- let cancelled = false;
44
- let error: RuntimeError | undefined;
45
-
46
- const cp = spawn(command, args, {
47
- cwd: options.cwd,
48
- env: options.env ? { ...process.env, ...options.env } : process.env,
49
- stdio: ["pipe", "pipe", "pipe"],
50
- });
51
-
52
- if (options.input) {
53
- cp.stdin.write(options.input);
54
- cp.stdin.end();
55
- } else {
56
- cp.stdin.end();
57
- }
58
-
59
- let timer: ReturnType<typeof setTimeout> | undefined;
60
- if (options.timeoutMs && options.timeoutMs > 0) {
61
- timer = setTimeout(() => {
62
- timedOut = true;
63
- cp.kill("SIGTERM");
64
- setTimeout(() => {
65
- if (!cp.killed) cp.kill("SIGKILL");
66
- }, 1000);
67
- }, options.timeoutMs);
68
- }
69
-
70
- const onAbort = () => {
71
- cancelled = true;
72
- cp.kill("SIGTERM");
73
- setTimeout(() => {
74
- if (!cp.killed) cp.kill("SIGKILL");
75
- }, 1000);
76
- };
77
-
78
- if (options.signal) {
79
- if (options.signal.aborted) {
80
- onAbort();
81
- } else {
82
- options.signal.addEventListener("abort", onAbort, { once: true });
83
- }
84
- }
85
-
86
- cp.stdout?.on("data", (chunk: Buffer) => {
87
- totalBytes += chunk.length;
88
- if (totalBytes > maxOutputBytes) {
89
- error = {
90
- code: "PROCESS_OUTPUT_LIMIT",
91
- message: `Process output exceeded limit of ${maxOutputBytes} bytes`,
92
- };
93
- cp.kill("SIGKILL");
94
- return;
95
- }
96
- stdoutBuf += chunk.toString("utf-8");
97
- });
98
-
99
- cp.stderr?.on("data", (chunk: Buffer) => {
100
- totalBytes += chunk.length;
101
- if (totalBytes > maxOutputBytes) {
102
- error = {
103
- code: "PROCESS_OUTPUT_LIMIT",
104
- message: `Process output exceeded limit of ${maxOutputBytes} bytes`,
105
- };
106
- cp.kill("SIGKILL");
107
- return;
108
- }
109
- stderrBuf += chunk.toString("utf-8");
110
- });
111
-
112
- cp.on("error", (err) => {
113
- if (timer) clearTimeout(timer);
114
- const durationMs = Date.now() - startTime;
115
- const res: ProcessResult = {
116
- ok: false,
117
- exitCode: null,
118
- stdout: stdoutBuf.trim(),
119
- stderr: stderrBuf.trim() || err.message,
120
- raw: new TextEncoder().encode(stdoutBuf),
121
- timedOut,
122
- cancelled,
123
- durationMs,
124
- error: error || {
125
- code: "PROCESS_SPAWN_ERROR",
126
- message: err.message,
127
- },
128
- };
129
- if (options.throwOnError) {
130
- reject(new Error(err.message));
131
- } else {
132
- resolve(res);
133
- }
134
- });
135
-
136
- cp.on("close", (exitCode, signal) => {
137
- if (timer) clearTimeout(timer);
138
- const durationMs = Date.now() - startTime;
139
- const ok = exitCode === 0 && !timedOut && !cancelled && !error;
140
-
141
- const res: ProcessResult = {
142
- ok,
143
- exitCode,
144
- signal: signal || undefined,
145
- stdout: stdoutBuf.trim(),
146
- stderr: stderrBuf.trim(),
147
- raw: new TextEncoder().encode(stdoutBuf),
148
- timedOut,
149
- cancelled,
150
- durationMs,
151
- error,
152
- };
153
-
154
- if (!ok && options.throwOnError) {
155
- reject(new Error(stderrBuf.trim() || `Process exited with code ${exitCode}`));
156
- } else {
157
- resolve(res);
158
- }
159
- });
160
- });
161
- }
162
-
163
- async spawnDetached(options: DetachedProcessOptions): Promise<DetachedProcessResult> {
164
- const startTime = Date.now();
165
- try {
166
- const child = spawn(options.command, options.args || [], {
167
- cwd: options.cwd,
168
- env: options.env ? { ...process.env, ...options.env } : process.env,
169
- detached: true,
170
- stdio: "ignore",
171
- });
172
-
173
- child.unref();
174
-
175
- if (!options.probe) {
176
- return {
177
- ok: true,
178
- pid: child.pid,
179
- ready: true,
180
- durationMs: Date.now() - startTime,
181
- };
182
- }
183
-
184
- const probeInterval = options.probeIntervalMs ?? 200;
185
- const probeTimeout = options.probeTimeoutMs ?? 5000;
186
- const deadline = Date.now() + probeTimeout;
187
-
188
- while (Date.now() < deadline) {
189
- if (options.signal?.aborted) {
190
- return {
191
- ok: false,
192
- pid: child.pid,
193
- ready: false,
194
- durationMs: Date.now() - startTime,
195
- error: {
196
- code: "PROCESS_CANCELLED",
197
- message: "Probe was cancelled by AbortSignal",
198
- },
199
- };
200
- }
201
-
202
- try {
203
- const res: DetachedProcessResult = {
204
- ok: true,
205
- pid: child.pid,
206
- ready: true,
207
- durationMs: Date.now() - startTime,
208
- };
209
- const isReady = await options.probe(res as any);
210
- if (isReady) {
211
- return res;
212
- }
213
- } catch {
214
- // 探测失败继续轮询
215
- }
216
-
217
- const remaining = deadline - Date.now();
218
- if (remaining <= 0) break;
219
- const sleepTime = Math.min(probeInterval, remaining);
220
- await new Promise((r) => setTimeout(r, sleepTime));
221
- }
222
-
223
- return {
224
- ok: false,
225
- pid: child.pid,
226
- ready: false,
227
- durationMs: Date.now() - startTime,
228
- error: {
229
- code: "PROCESS_PROBE_TIMEOUT",
230
- message: `Process probe timed out after ${probeTimeout}ms`,
231
- },
232
- };
233
- } catch (err: any) {
234
- return {
235
- ok: false,
236
- ready: false,
237
- durationMs: Date.now() - startTime,
238
- error: {
239
- code: "PROCESS_DETACHED_FAILED",
240
- message: err.message,
241
- },
242
- };
243
- }
244
- }
245
- }