@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/src/export/skill.ts
DELETED
|
@@ -1,350 +0,0 @@
|
|
|
1
|
-
import { spawnSync } from "node:child_process";
|
|
2
|
-
import { copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
-
import { basename, dirname, join, resolve } from "node:path";
|
|
4
|
-
import { buildProject } from "../build/builder";
|
|
5
|
-
import {
|
|
6
|
-
discoverPlaybookFiles,
|
|
7
|
-
loadActionFileMap,
|
|
8
|
-
loadActions,
|
|
9
|
-
loadPlaybooks,
|
|
10
|
-
loadProjectConfig,
|
|
11
|
-
} from "../project/loader";
|
|
12
|
-
import type { ProjectConfig } from "../project/types";
|
|
13
|
-
import { getPackageSlug } from "../utils";
|
|
14
|
-
import { generateSkillJson, generateSkillMd, generateSourceSkillMd, generateStandaloneSkillMd } from "./templates";
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* 导出 Agent Skill 产物时的配置选项。
|
|
18
|
-
*/
|
|
19
|
-
export interface ExportSkillOptions {
|
|
20
|
-
/** 源码项目根目录 */
|
|
21
|
-
projectRoot: string;
|
|
22
|
-
/** 导出模式:source (源码模式) 或 standalone (独立二进制模式) */
|
|
23
|
-
mode?: "source" | "standalone";
|
|
24
|
-
/** 是否强制独立二进制模式 */
|
|
25
|
-
standalone?: boolean;
|
|
26
|
-
/** 二进制编译目标架构(默认 host) */
|
|
27
|
-
target?: string;
|
|
28
|
-
/** 导出目录路径(默认 dist/skills/) */
|
|
29
|
-
outDir?: string;
|
|
30
|
-
/** 是否自动压缩打包为 .skill.tar.gz 归档包 */
|
|
31
|
-
archive?: boolean;
|
|
32
|
-
/** 按需挑选的 Playbook 列表(触发 Playbook-driven 最小化依赖 Tree-shaking 导出) */
|
|
33
|
-
playbooks?: string[];
|
|
34
|
-
/** 显式挑选导出的 Action ID 清单 */
|
|
35
|
-
actions?: string[];
|
|
36
|
-
/** 独立模式下是否开启代码混淆压缩 */
|
|
37
|
-
minify?: boolean;
|
|
38
|
-
/** 独立模式下是否编译为字节码 */
|
|
39
|
-
bytecode?: boolean;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Skill 导出完成后的产物描述结果。
|
|
44
|
-
*/
|
|
45
|
-
export interface ExportSkillResult {
|
|
46
|
-
/** 所属 Package ID */
|
|
47
|
-
packageId: string;
|
|
48
|
-
/** 版本号 */
|
|
49
|
-
version: string;
|
|
50
|
-
/** 导出模式 */
|
|
51
|
-
mode: "source" | "standalone";
|
|
52
|
-
/** 目标架构 */
|
|
53
|
-
target: string;
|
|
54
|
-
/** 生成的 Skill 目录绝对路径 */
|
|
55
|
-
skillDir: string;
|
|
56
|
-
/** 若开启了 archive,生成的 tar.gz 归档文件绝对路径 */
|
|
57
|
-
archivePath?: string;
|
|
58
|
-
/** 导出的 Action 数量 */
|
|
59
|
-
actionsCount: number;
|
|
60
|
-
/** 导出的 Playbook 数量 */
|
|
61
|
-
playbooksCount: number;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* 将 ActionDock 项目导出为兼容各大 AI Agent 平台(如 Claude Desktop / Antigravity / Open-Interpreter 等)的通用 Agent Skill 规范包。
|
|
66
|
-
*
|
|
67
|
-
* 支持两种模式:
|
|
68
|
-
* 1. source 源码模式:导出 SKILL.md + actiondock.json + 源码文件,配合 CLI 直接执行。
|
|
69
|
-
* 2. standalone 独立模式:导出 SKILL.md + 单文件独立二进制可执行文件,目标环境零依赖即跑。
|
|
70
|
-
*
|
|
71
|
-
* 支持 Playbook 驱动的最小化 Tree-shaking 依赖裁剪。
|
|
72
|
-
*
|
|
73
|
-
* @param options 导出配置选项
|
|
74
|
-
* @returns 导出产物详细结果
|
|
75
|
-
*/
|
|
76
|
-
export async function exportSkill(
|
|
77
|
-
options: ExportSkillOptions
|
|
78
|
-
): Promise<ExportSkillResult> {
|
|
79
|
-
const root = resolve(options.projectRoot);
|
|
80
|
-
const config = loadProjectConfig(root);
|
|
81
|
-
const mode: "source" | "standalone" =
|
|
82
|
-
options.standalone || options.mode === "standalone" ? "standalone" : "source";
|
|
83
|
-
const target = options.target || "host";
|
|
84
|
-
|
|
85
|
-
const actionsMap = await loadActions(root, config.actionsDir);
|
|
86
|
-
const playbooksMap = loadPlaybooks(root, config.playbooksDir);
|
|
87
|
-
|
|
88
|
-
// Map each action ID to its corresponding source file path
|
|
89
|
-
const actionFileMap = await loadActionFileMap(root, config.actionsDir);
|
|
90
|
-
|
|
91
|
-
let selectedPlaybooks = Array.from(playbooksMap.values());
|
|
92
|
-
let selectedActions = Array.from(actionsMap.values());
|
|
93
|
-
|
|
94
|
-
// 1. If playbooks are explicitly specified (Playbook-driven minimal export)
|
|
95
|
-
if (options.playbooks && options.playbooks.length > 0) {
|
|
96
|
-
const specifiedPlaybookIds = new Set(options.playbooks);
|
|
97
|
-
const pbList = [];
|
|
98
|
-
for (const id of specifiedPlaybookIds) {
|
|
99
|
-
const pb = playbooksMap.get(id);
|
|
100
|
-
if (!pb) {
|
|
101
|
-
throw new Error(
|
|
102
|
-
`Playbook '${id}' specified in export options not found in project`
|
|
103
|
-
);
|
|
104
|
-
}
|
|
105
|
-
pbList.push(pb);
|
|
106
|
-
}
|
|
107
|
-
selectedPlaybooks = pbList;
|
|
108
|
-
|
|
109
|
-
// If actions were not explicitly specified, derive required actions from selected playbooks
|
|
110
|
-
if (!options.actions || options.actions.length === 0) {
|
|
111
|
-
const requiredActions = new Set<string>();
|
|
112
|
-
for (const pb of selectedPlaybooks) {
|
|
113
|
-
if (pb.actions) {
|
|
114
|
-
for (const act of pb.actions) {
|
|
115
|
-
requiredActions.add(act);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
if (requiredActions.size > 0) {
|
|
120
|
-
for (const actId of requiredActions) {
|
|
121
|
-
if (!actionsMap.has(actId)) {
|
|
122
|
-
console.warn(
|
|
123
|
-
`[WARN] Action '${actId}' referenced in playbook is not found in project`
|
|
124
|
-
);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
selectedActions = Array.from(actionsMap.values()).filter((a) =>
|
|
128
|
-
requiredActions.has(a.id)
|
|
129
|
-
);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// 2. If actions are explicitly specified (Action-driven export)
|
|
135
|
-
if (options.actions && options.actions.length > 0) {
|
|
136
|
-
const specifiedActionIds = new Set(options.actions);
|
|
137
|
-
for (const actId of specifiedActionIds) {
|
|
138
|
-
if (!actionsMap.has(actId)) {
|
|
139
|
-
throw new Error(
|
|
140
|
-
`Action '${actId}' specified in export options not found in project`
|
|
141
|
-
);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
selectedActions = Array.from(actionsMap.values()).filter((a) =>
|
|
145
|
-
specifiedActionIds.has(a.id)
|
|
146
|
-
);
|
|
147
|
-
|
|
148
|
-
// If playbooks were not explicitly specified, tree-shake playbooks whose required actions are not included
|
|
149
|
-
if (!options.playbooks || options.playbooks.length === 0) {
|
|
150
|
-
selectedPlaybooks = selectedPlaybooks.filter((pb) => {
|
|
151
|
-
if (!pb.actions || pb.actions.length === 0) return true;
|
|
152
|
-
return pb.actions.every((a) => specifiedActionIds.has(a));
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
const pkgSlug = getPackageSlug(config.id);
|
|
158
|
-
|
|
159
|
-
const targetSuffix = mode === "standalone" && target !== "host" ? `-${target}` : "";
|
|
160
|
-
const skillFolderName = `${pkgSlug}-skill${targetSuffix}`;
|
|
161
|
-
const defaultSkillDir = join(root, "dist", skillFolderName);
|
|
162
|
-
const skillDir = resolve(options.outDir || defaultSkillDir);
|
|
163
|
-
|
|
164
|
-
const playbooksDestDir = join(skillDir, "playbooks");
|
|
165
|
-
|
|
166
|
-
if (mode === "source") {
|
|
167
|
-
// ----------------------------------------------------
|
|
168
|
-
// SOURCE SKILL EXPORT (Default)
|
|
169
|
-
// Structure: SKILL.md + actiondock.json + package.json + actions/* + playbooks/*
|
|
170
|
-
// ----------------------------------------------------
|
|
171
|
-
const actionsDestDir = join(skillDir, "actions");
|
|
172
|
-
mkdirSync(actionsDestDir, { recursive: true });
|
|
173
|
-
if (selectedPlaybooks.length > 0) {
|
|
174
|
-
mkdirSync(playbooksDestDir, { recursive: true });
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// 1. Generate SKILL.md for Source Package
|
|
178
|
-
const skillMd = generateSourceSkillMd(
|
|
179
|
-
config,
|
|
180
|
-
selectedActions,
|
|
181
|
-
selectedPlaybooks
|
|
182
|
-
);
|
|
183
|
-
writeFileSync(join(skillDir, "SKILL.md"), skillMd, "utf-8");
|
|
184
|
-
|
|
185
|
-
// 2. Export tailored actiondock.json
|
|
186
|
-
const exportedConfig: Partial<ProjectConfig> = {
|
|
187
|
-
id: config.id,
|
|
188
|
-
name: config.name,
|
|
189
|
-
version: config.version,
|
|
190
|
-
description: config.description,
|
|
191
|
-
actionsDir: "actions",
|
|
192
|
-
playbooksDir: "playbooks",
|
|
193
|
-
};
|
|
194
|
-
if (config.config) {
|
|
195
|
-
exportedConfig.config = config.config;
|
|
196
|
-
}
|
|
197
|
-
writeFileSync(
|
|
198
|
-
join(skillDir, "actiondock.json"),
|
|
199
|
-
JSON.stringify(exportedConfig, null, 2) + "\n",
|
|
200
|
-
"utf-8"
|
|
201
|
-
);
|
|
202
|
-
|
|
203
|
-
// 3. Export package.json
|
|
204
|
-
const projectPkgJsonPath = join(root, "package.json");
|
|
205
|
-
if (existsSync(projectPkgJsonPath)) {
|
|
206
|
-
try {
|
|
207
|
-
const rawPkg = readFileSync(projectPkgJsonPath, "utf-8");
|
|
208
|
-
const parsedPkg = JSON.parse(rawPkg);
|
|
209
|
-
const exportedPkg = {
|
|
210
|
-
name: parsedPkg.name || pkgSlug,
|
|
211
|
-
version: config.version || parsedPkg.version || "0.1.0",
|
|
212
|
-
description: config.description || parsedPkg.description,
|
|
213
|
-
type: "module",
|
|
214
|
-
dependencies: parsedPkg.dependencies || {
|
|
215
|
-
"@actiondock/sdk": "^2.0.0",
|
|
216
|
-
},
|
|
217
|
-
devDependencies: parsedPkg.devDependencies,
|
|
218
|
-
};
|
|
219
|
-
writeFileSync(
|
|
220
|
-
join(skillDir, "package.json"),
|
|
221
|
-
JSON.stringify(exportedPkg, null, 2) + "\n",
|
|
222
|
-
"utf-8"
|
|
223
|
-
);
|
|
224
|
-
} catch {
|
|
225
|
-
copyFileSync(projectPkgJsonPath, join(skillDir, "package.json"));
|
|
226
|
-
}
|
|
227
|
-
} else {
|
|
228
|
-
const minimalPkg = {
|
|
229
|
-
name: pkgSlug,
|
|
230
|
-
version: config.version,
|
|
231
|
-
description: config.description,
|
|
232
|
-
type: "module",
|
|
233
|
-
dependencies: {
|
|
234
|
-
"@actiondock/sdk": "^2.0.0",
|
|
235
|
-
},
|
|
236
|
-
};
|
|
237
|
-
writeFileSync(
|
|
238
|
-
join(skillDir, "package.json"),
|
|
239
|
-
JSON.stringify(minimalPkg, null, 2) + "\n",
|
|
240
|
-
"utf-8"
|
|
241
|
-
);
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
// 4. Copy tsconfig.json if available
|
|
245
|
-
const tsconfigPath = join(root, "tsconfig.json");
|
|
246
|
-
if (existsSync(tsconfigPath)) {
|
|
247
|
-
copyFileSync(tsconfigPath, join(skillDir, "tsconfig.json"));
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
// 5. Copy selected action source files
|
|
251
|
-
for (const act of selectedActions) {
|
|
252
|
-
const entry = actionFileMap.get(act.id);
|
|
253
|
-
const srcPath = entry?.filePath;
|
|
254
|
-
if (srcPath && existsSync(srcPath)) {
|
|
255
|
-
copyFileSync(srcPath, join(actionsDestDir, basename(srcPath)));
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
// 6. Copy selected playbooks
|
|
260
|
-
for (const pb of selectedPlaybooks) {
|
|
261
|
-
if (pb.filePath && existsSync(pb.filePath)) {
|
|
262
|
-
const filename = basename(pb.filePath);
|
|
263
|
-
copyFileSync(pb.filePath, join(playbooksDestDir, filename));
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
} else {
|
|
267
|
-
// ----------------------------------------------------
|
|
268
|
-
// STANDALONE SKILL EXPORT (--standalone)
|
|
269
|
-
// Structure: SKILL.md + actiondock.skill.json + bin/<binary> + playbooks/*
|
|
270
|
-
// ----------------------------------------------------
|
|
271
|
-
const binDir = join(skillDir, "bin");
|
|
272
|
-
mkdirSync(binDir, { recursive: true });
|
|
273
|
-
if (selectedPlaybooks.length > 0) {
|
|
274
|
-
mkdirSync(playbooksDestDir, { recursive: true });
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
const binaryName = pkgSlug;
|
|
278
|
-
const binaryPath = join(binDir, binaryName);
|
|
279
|
-
|
|
280
|
-
// Build standalone binary with selected actions
|
|
281
|
-
const buildRes = await buildProject({
|
|
282
|
-
projectRoot: root,
|
|
283
|
-
target: options.target,
|
|
284
|
-
outfile: binaryPath,
|
|
285
|
-
actions: selectedActions.map((a) => a.id),
|
|
286
|
-
minify: options.minify,
|
|
287
|
-
bytecode: options.bytecode,
|
|
288
|
-
});
|
|
289
|
-
|
|
290
|
-
const actualBinaryName = basename(buildRes.executablePath);
|
|
291
|
-
|
|
292
|
-
// Generate SKILL.md for Standalone Binary
|
|
293
|
-
const skillMd = generateStandaloneSkillMd(
|
|
294
|
-
config,
|
|
295
|
-
selectedActions,
|
|
296
|
-
selectedPlaybooks,
|
|
297
|
-
`./bin/${actualBinaryName}`
|
|
298
|
-
);
|
|
299
|
-
writeFileSync(join(skillDir, "SKILL.md"), skillMd, "utf-8");
|
|
300
|
-
|
|
301
|
-
// Generate actiondock.skill.json
|
|
302
|
-
const skillJson = generateSkillJson(
|
|
303
|
-
config,
|
|
304
|
-
selectedActions,
|
|
305
|
-
actualBinaryName,
|
|
306
|
-
target
|
|
307
|
-
);
|
|
308
|
-
writeFileSync(join(skillDir, "actiondock.skill.json"), skillJson, "utf-8");
|
|
309
|
-
|
|
310
|
-
// Copy selected playbooks
|
|
311
|
-
for (const pb of selectedPlaybooks) {
|
|
312
|
-
if (pb.filePath && existsSync(pb.filePath)) {
|
|
313
|
-
const filename = basename(pb.filePath);
|
|
314
|
-
copyFileSync(pb.filePath, join(playbooksDestDir, filename));
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
let archivePath: string | undefined;
|
|
320
|
-
if (options.archive) {
|
|
321
|
-
const zipName = `${skillFolderName}.zip`;
|
|
322
|
-
archivePath = join(dirname(skillDir), zipName);
|
|
323
|
-
const zipProc = spawnSync(
|
|
324
|
-
"zip",
|
|
325
|
-
["-r", archivePath, basename(skillDir)],
|
|
326
|
-
{
|
|
327
|
-
cwd: dirname(skillDir),
|
|
328
|
-
stdio: "pipe",
|
|
329
|
-
}
|
|
330
|
-
);
|
|
331
|
-
if (zipProc.status !== 0) {
|
|
332
|
-
console.warn(
|
|
333
|
-
`[WARN] Failed to create zip archive: ${zipProc.stderr?.toString() || "zip command failed"}`
|
|
334
|
-
);
|
|
335
|
-
archivePath = undefined;
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
return {
|
|
340
|
-
packageId: config.id,
|
|
341
|
-
version: config.version,
|
|
342
|
-
mode,
|
|
343
|
-
target,
|
|
344
|
-
skillDir,
|
|
345
|
-
archivePath,
|
|
346
|
-
actionsCount: selectedActions.length,
|
|
347
|
-
playbooksCount: selectedPlaybooks.length,
|
|
348
|
-
};
|
|
349
|
-
}
|
|
350
|
-
|