@actiondock/core 2.0.9 → 2.0.11-beta.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.
- package/package.json +2 -2
- package/src/build/index.ts +0 -1
- package/src/build/templates.ts +1 -1
- package/src/catalog/types.ts +1 -9
- package/src/doctor/doctor.ts +99 -38
- package/src/execution/service.ts +47 -7
- package/src/export/index.ts +0 -1
- package/src/export/templates.ts +348 -59
- package/src/index.ts +1 -0
- package/src/project/init.ts +3 -2
- package/src/project/loader.ts +46 -7
- package/src/project/manifest.ts +205 -2
- package/src/project/types.ts +49 -0
- package/src/registry/registry.ts +271 -34
- package/src/runtime/context.ts +8 -3
- package/src/runtime/index.ts +1 -0
- package/src/runtime/module-loader.ts +67 -0
- package/src/runtime/process.ts +12 -11
- package/src/runtime/runner.ts +193 -68
- package/src/server/index.ts +1 -0
- package/src/server/routes/actions.ts +262 -0
- package/src/server/routes/common.ts +126 -0
- package/src/server/routes/config.ts +147 -0
- package/src/server/routes/doctor.ts +29 -0
- package/src/server/routes/health.ts +40 -0
- package/src/server/routes/index.ts +9 -0
- package/src/server/routes/info.ts +221 -0
- package/src/server/routes/playbooks.ts +109 -0
- package/src/server/routes/runs.ts +301 -0
- package/src/server/routes/state.ts +133 -0
- package/src/server/server.ts +82 -1323
- package/src/storage/index.ts +20 -4
- package/src/storage/sqlite.ts +60 -31
- package/src/storage/types.ts +8 -0
- package/src/utils/index.ts +2 -0
- package/src/build/builder.ts +0 -218
- package/src/export/skill.ts +0 -350
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@actiondock/core",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.11-beta.0",
|
|
4
4
|
"description": "ActionDock Core Engine - Project loader, runtime execution, SQLite storage, standalone builder, and skill exporter",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.ts",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"test": "bun test"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@actiondock/sdk": "
|
|
30
|
+
"@actiondock/sdk": "2.0.11-beta.0",
|
|
31
31
|
"ajv": "^8.17.1",
|
|
32
32
|
"ajv-formats": "^3.0.1",
|
|
33
33
|
"yaml": "^2.7.0"
|
package/src/build/index.ts
CHANGED
package/src/build/templates.ts
CHANGED
|
@@ -27,7 +27,7 @@ export function generateStandaloneEntrypoint(
|
|
|
27
27
|
configDefs?: Record<string, unknown>
|
|
28
28
|
): string {
|
|
29
29
|
// Resolve path to standalone runtime inside @actiondock/cli
|
|
30
|
-
const standaloneRuntimePath = resolve(
|
|
30
|
+
const standaloneRuntimePath = resolve(import.meta.dirname, "../runtime/standalone");
|
|
31
31
|
|
|
32
32
|
const imports = actions
|
|
33
33
|
.map((a, idx) => `import action_${idx} from ${JSON.stringify(a.filePath)};`)
|
package/src/catalog/types.ts
CHANGED
|
@@ -72,12 +72,4 @@ export interface IndexedAction {
|
|
|
72
72
|
projectRoot: string;
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
|
|
76
|
-
* 模块加载器接口。
|
|
77
|
-
*/
|
|
78
|
-
export interface ModuleLoader {
|
|
79
|
-
load<T>(file: string, options: {
|
|
80
|
-
projectRoot: string;
|
|
81
|
-
tsconfigPath?: string;
|
|
82
|
-
}): Promise<T>;
|
|
83
|
-
}
|
|
75
|
+
export type { ModuleLoader } from "../runtime/module-loader";
|
package/src/doctor/doctor.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { existsSync } from "node:fs";
|
|
2
|
-
import { delimiter, join } from "node:path";
|
|
3
|
-
import { findProjectRoot, loadActions, loadPlaybooks, loadProjectConfig } from "../project/loader";
|
|
1
|
+
import { existsSync, statSync } from "node:fs";
|
|
2
|
+
import { delimiter, join, relative } from "node:path";
|
|
3
|
+
import { discoverActionFiles, findProjectRoot, loadActions, loadPlaybooks, loadProjectConfig } from "../project/loader";
|
|
4
|
+
import { loadManifest, MANIFEST_FILE_NAME } from "../project/manifest";
|
|
4
5
|
import { getRegistryStatus } from "../registry/registry";
|
|
5
6
|
import { createGlobalStorage, createStorage } from "../storage";
|
|
6
|
-
import { getActionDockHome } from "../utils";
|
|
7
|
+
import { findExecutable, getActionDockHome } from "../utils";
|
|
7
8
|
import type { DoctorCheckItem, DoctorReport } from "./types";
|
|
8
9
|
|
|
9
10
|
function compareSemver(v1: string, v2: string): number {
|
|
@@ -18,36 +19,6 @@ function compareSemver(v1: string, v2: string): number {
|
|
|
18
19
|
return 0;
|
|
19
20
|
}
|
|
20
21
|
|
|
21
|
-
function findExecutable(command: string): string | null {
|
|
22
|
-
if (typeof (globalThis as any).Bun !== "undefined" && typeof (globalThis as any).Bun.which === "function") {
|
|
23
|
-
try {
|
|
24
|
-
const bPath = (globalThis as any).Bun.which(command);
|
|
25
|
-
if (bPath) return bPath;
|
|
26
|
-
} catch {}
|
|
27
|
-
}
|
|
28
|
-
const hasPathSep = command.includes("/") || command.includes("\\");
|
|
29
|
-
if (hasPathSep) {
|
|
30
|
-
return existsSync(command) ? command : null;
|
|
31
|
-
}
|
|
32
|
-
const pathEnv = process.env.PATH || "";
|
|
33
|
-
const dirs = pathEnv.split(delimiter);
|
|
34
|
-
const isWindows = process.platform === "win32";
|
|
35
|
-
const pathext = isWindows
|
|
36
|
-
? (process.env.PATHEXT || ".COM;.EXE;.BAT;.CMD").split(";")
|
|
37
|
-
: [""];
|
|
38
|
-
|
|
39
|
-
for (const dir of dirs) {
|
|
40
|
-
if (!dir) continue;
|
|
41
|
-
for (const ext of pathext) {
|
|
42
|
-
const candidate = join(dir, isWindows && !command.includes(".") ? command + ext : command);
|
|
43
|
-
if (existsSync(candidate)) {
|
|
44
|
-
return candidate;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
return null;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
22
|
export async function runDoctorChecks(options?: {
|
|
52
23
|
cwd?: string;
|
|
53
24
|
packageIdOrPath?: string;
|
|
@@ -244,15 +215,23 @@ export async function runDoctorChecks(options?: {
|
|
|
244
215
|
|
|
245
216
|
// Actions Check
|
|
246
217
|
try {
|
|
247
|
-
const
|
|
248
|
-
|
|
218
|
+
const manifest = loadManifest(projectRoot);
|
|
219
|
+
let actionsCount = 0;
|
|
220
|
+
if (manifest?.actions) {
|
|
221
|
+
actionsCount = Object.keys(manifest.actions).length;
|
|
222
|
+
} else {
|
|
223
|
+
const actions = await loadActions(projectRoot, config.actionsDir, { autoInstall: false });
|
|
224
|
+
actionsCount = actions.size;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (actionsCount === 0) {
|
|
249
228
|
checks.push({
|
|
250
229
|
id: "project.actions",
|
|
251
230
|
category: "project",
|
|
252
231
|
name: "Actions",
|
|
253
232
|
status: "warn",
|
|
254
233
|
message: `No actions found in '${config.actionsDir || "actions"}'`,
|
|
255
|
-
fix: "Run 'ad action
|
|
234
|
+
fix: "Run 'ad action new <id>' to create your first action",
|
|
256
235
|
});
|
|
257
236
|
} else {
|
|
258
237
|
checks.push({
|
|
@@ -260,7 +239,7 @@ export async function runDoctorChecks(options?: {
|
|
|
260
239
|
category: "project",
|
|
261
240
|
name: "Actions",
|
|
262
241
|
status: "ok",
|
|
263
|
-
message: `${
|
|
242
|
+
message: `${actionsCount} action(s) valid and loaded`,
|
|
264
243
|
});
|
|
265
244
|
}
|
|
266
245
|
} catch (err: any) {
|
|
@@ -273,6 +252,88 @@ export async function runDoctorChecks(options?: {
|
|
|
273
252
|
});
|
|
274
253
|
}
|
|
275
254
|
|
|
255
|
+
// Project Manifest Check (Lightweight Static Detection)
|
|
256
|
+
try {
|
|
257
|
+
const manifestPath = join(projectRoot, MANIFEST_FILE_NAME);
|
|
258
|
+
const manifest = loadManifest(projectRoot);
|
|
259
|
+
const actionFiles = discoverActionFiles(projectRoot, config.actionsDir || "actions");
|
|
260
|
+
|
|
261
|
+
if (!existsSync(manifestPath)) {
|
|
262
|
+
if (actionFiles.length > 0) {
|
|
263
|
+
checks.push({
|
|
264
|
+
id: "project.manifest",
|
|
265
|
+
category: "project",
|
|
266
|
+
name: "Action Manifest",
|
|
267
|
+
status: "warn",
|
|
268
|
+
message: `${MANIFEST_FILE_NAME} not found (${actionFiles.length} action source file(s) exist)`,
|
|
269
|
+
fix: "Run 'ad action sync' to generate manifest",
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
} else if (manifest && manifest.actions) {
|
|
273
|
+
const missingFiles = Object.entries(manifest.actions)
|
|
274
|
+
.filter(([_, item]) => !existsSync(join(projectRoot, item.entry)))
|
|
275
|
+
.map(([id, item]) => `${id} (${item.entry})`);
|
|
276
|
+
|
|
277
|
+
const manifestEntries = new Set(
|
|
278
|
+
Object.values(manifest.actions).map((a) => a.entry.replace(/\\/g, "/"))
|
|
279
|
+
);
|
|
280
|
+
const untracked = actionFiles
|
|
281
|
+
.map((f) => relative(projectRoot, f).replace(/\\/g, "/"))
|
|
282
|
+
.filter((rel) => !manifestEntries.has(rel));
|
|
283
|
+
|
|
284
|
+
if (missingFiles.length > 0) {
|
|
285
|
+
checks.push({
|
|
286
|
+
id: "project.manifest",
|
|
287
|
+
category: "project",
|
|
288
|
+
name: "Action Manifest",
|
|
289
|
+
status: "warn",
|
|
290
|
+
message: `${missingFiles.length} action(s) in manifest point to missing files: ${missingFiles.join(", ")}`,
|
|
291
|
+
fix: "Run 'ad action sync' to synchronize manifest",
|
|
292
|
+
});
|
|
293
|
+
} else if (untracked.length > 0) {
|
|
294
|
+
checks.push({
|
|
295
|
+
id: "project.manifest",
|
|
296
|
+
category: "project",
|
|
297
|
+
name: "Action Manifest",
|
|
298
|
+
status: "warn",
|
|
299
|
+
message: `${untracked.length} action file(s) not declared in manifest: ${untracked.join(", ")}`,
|
|
300
|
+
fix: "Run 'ad action sync' to synchronize manifest",
|
|
301
|
+
});
|
|
302
|
+
} else {
|
|
303
|
+
const manifestStat = statSync(manifestPath);
|
|
304
|
+
const newerFiles = actionFiles.filter(
|
|
305
|
+
(f) => statSync(f).mtimeMs > manifestStat.mtimeMs + 2000
|
|
306
|
+
);
|
|
307
|
+
if (newerFiles.length > 0) {
|
|
308
|
+
checks.push({
|
|
309
|
+
id: "project.manifest",
|
|
310
|
+
category: "project",
|
|
311
|
+
name: "Action Manifest",
|
|
312
|
+
status: "ok",
|
|
313
|
+
message: `Manifest valid (Note: ${newerFiles.length} action file(s) modified after manifest; run 'ad action sync' if definitions changed)`,
|
|
314
|
+
});
|
|
315
|
+
} else {
|
|
316
|
+
checks.push({
|
|
317
|
+
id: "project.manifest",
|
|
318
|
+
category: "project",
|
|
319
|
+
name: "Action Manifest",
|
|
320
|
+
status: "ok",
|
|
321
|
+
message: "Manifest synchronized with action files",
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
} catch (err: any) {
|
|
327
|
+
checks.push({
|
|
328
|
+
id: "project.manifest",
|
|
329
|
+
category: "project",
|
|
330
|
+
name: "Action Manifest",
|
|
331
|
+
status: "error",
|
|
332
|
+
message: `Failed to inspect manifest: ${err.message}`,
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
|
|
276
337
|
// Playbooks Check
|
|
277
338
|
try {
|
|
278
339
|
const playbooks = loadPlaybooks(projectRoot, config.playbooksDir);
|
package/src/execution/service.ts
CHANGED
|
@@ -5,6 +5,7 @@ import type {
|
|
|
5
5
|
ExecutionEvent,
|
|
6
6
|
ExecutionResult,
|
|
7
7
|
JsonValue,
|
|
8
|
+
Logger,
|
|
8
9
|
ProgressReporter,
|
|
9
10
|
RunRecord,
|
|
10
11
|
RunStatus,
|
|
@@ -159,6 +160,7 @@ export class DefaultExecutionService implements ExecutionService {
|
|
|
159
160
|
}
|
|
160
161
|
}
|
|
161
162
|
|
|
163
|
+
const runId = randomUUID();
|
|
162
164
|
let sequence = 0;
|
|
163
165
|
type EventPayload =
|
|
164
166
|
| { type: "log"; level: "debug" | "info" | "warn" | "error"; message: string; data?: JsonValue }
|
|
@@ -166,16 +168,11 @@ export class DefaultExecutionService implements ExecutionService {
|
|
|
166
168
|
| { type: "status"; status: RunStatus }
|
|
167
169
|
| { type: "finish"; result: ExecutionResult };
|
|
168
170
|
|
|
169
|
-
const handle = this.runner.start(action, input, {
|
|
170
|
-
signal: controller.signal,
|
|
171
|
-
timeoutMs: options.timeoutMs,
|
|
172
|
-
});
|
|
173
|
-
|
|
174
171
|
const emitEvent = (payload: EventPayload) => {
|
|
175
172
|
const evt: ExecutionEvent = {
|
|
176
173
|
...payload,
|
|
177
|
-
runId
|
|
178
|
-
rootRunId:
|
|
174
|
+
runId,
|
|
175
|
+
rootRunId: runId,
|
|
179
176
|
sequence: sequence++,
|
|
180
177
|
timestamp: new Date().toISOString(),
|
|
181
178
|
};
|
|
@@ -193,6 +190,49 @@ export class DefaultExecutionService implements ExecutionService {
|
|
|
193
190
|
},
|
|
194
191
|
};
|
|
195
192
|
|
|
193
|
+
const executionLogger: Logger = {
|
|
194
|
+
debug(message: string, data?: unknown) {
|
|
195
|
+
emitEvent({
|
|
196
|
+
type: "log",
|
|
197
|
+
level: "debug",
|
|
198
|
+
message,
|
|
199
|
+
data: data as JsonValue | undefined,
|
|
200
|
+
});
|
|
201
|
+
},
|
|
202
|
+
info(message: string, data?: unknown) {
|
|
203
|
+
emitEvent({
|
|
204
|
+
type: "log",
|
|
205
|
+
level: "info",
|
|
206
|
+
message,
|
|
207
|
+
data: data as JsonValue | undefined,
|
|
208
|
+
});
|
|
209
|
+
},
|
|
210
|
+
warn(message: string, data?: unknown) {
|
|
211
|
+
emitEvent({
|
|
212
|
+
type: "log",
|
|
213
|
+
level: "warn",
|
|
214
|
+
message,
|
|
215
|
+
data: data as JsonValue | undefined,
|
|
216
|
+
});
|
|
217
|
+
},
|
|
218
|
+
error(message: string, data?: unknown) {
|
|
219
|
+
emitEvent({
|
|
220
|
+
type: "log",
|
|
221
|
+
level: "error",
|
|
222
|
+
message,
|
|
223
|
+
data: data as JsonValue | undefined,
|
|
224
|
+
});
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
const handle = this.runner.start(action, input, {
|
|
229
|
+
runId,
|
|
230
|
+
signal: controller.signal,
|
|
231
|
+
timeoutMs: options.timeoutMs,
|
|
232
|
+
progress: progressReporter,
|
|
233
|
+
logger: executionLogger,
|
|
234
|
+
});
|
|
235
|
+
|
|
196
236
|
const activeItem: ActiveRun = {
|
|
197
237
|
runId: handle.runId,
|
|
198
238
|
handle,
|
package/src/export/index.ts
CHANGED