@actiondock/builder 2.7.0 → 2.9.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/README.md +4 -5
- package/dist/archive.d.ts +0 -16
- package/dist/archive.js +35 -202
- package/dist/build.d.ts +1 -0
- package/dist/build.js +26 -61
- package/dist/dependency-check.js +36 -89
- package/dist/export-batch.js +4 -6
- package/dist/export-composite.js +8 -22
- package/dist/export-node.js +1 -1
- package/dist/export-source.js +11 -61
- package/dist/exporter.js +3 -9
- package/dist/fs-utils.d.ts +3 -2
- package/dist/fs-utils.js +9 -66
- package/dist/index.d.ts +3 -10
- package/dist/index.js +5 -16
- package/dist/manifest.d.ts +26 -0
- package/dist/manifest.js +67 -2
- package/dist/pack.js +37 -47
- package/dist/planner.js +73 -102
- package/dist/skill/index.d.ts +1 -0
- package/dist/skill/index.js +1 -0
- package/dist/skill/templates.d.ts +60 -0
- package/dist/skill/templates.js +507 -0
- package/dist/skill-md.d.ts +2 -1
- package/dist/skill-md.js +2 -1
- package/dist/stage-sources.d.ts +25 -0
- package/dist/stage-sources.js +51 -0
- package/dist/types.d.ts +18 -23
- package/dist/types.js +10 -1
- package/package.json +3 -4
package/dist/dependency-check.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync, readFileSync, realpathSync, statSync } from "node:fs";
|
|
2
2
|
import { dirname, join, relative, resolve } from "node:path";
|
|
3
|
-
import { isPathOutsideBoundary } from "@actiondock/core";
|
|
3
|
+
import { isPathOutsideBoundary } from "@actiondock/core/project";
|
|
4
4
|
import { BuilderError } from "./errors.js";
|
|
5
5
|
/**
|
|
6
6
|
* 移除源码中的单行与多行注释,防止注释内的相对路径字符串误触发依赖解析。
|
|
@@ -53,73 +53,60 @@ const RESOLUTION_EXTENSIONS = [
|
|
|
53
53
|
".cts",
|
|
54
54
|
".json",
|
|
55
55
|
];
|
|
56
|
+
/**
|
|
57
|
+
* 将路径解析为物理真实路径:不存在时回退到逻辑绝对路径,realpath 失败时同样回退。
|
|
58
|
+
*/
|
|
59
|
+
function toRealPath(p) {
|
|
60
|
+
try {
|
|
61
|
+
return existsSync(p) ? realpathSync(p) : resolve(p);
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return resolve(p);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* 判断候选路径是否为磁盘上真实存在的文件。
|
|
69
|
+
*/
|
|
70
|
+
function isFileReal(cand) {
|
|
71
|
+
return existsSync(cand) && statSync(cand).isFile();
|
|
72
|
+
}
|
|
56
73
|
/**
|
|
57
74
|
* 将相对模块说明符解析为磁盘上的物理真实文件路径。
|
|
58
75
|
*/
|
|
59
76
|
export function resolveRelativeModule(fromDir, specifier) {
|
|
60
77
|
const basePath = resolve(fromDir, specifier);
|
|
61
78
|
// 1. 精确匹配文件
|
|
62
|
-
if (
|
|
63
|
-
|
|
64
|
-
return realpathSync(basePath);
|
|
65
|
-
}
|
|
66
|
-
catch {
|
|
67
|
-
return basePath;
|
|
68
|
-
}
|
|
79
|
+
if (isFileReal(basePath)) {
|
|
80
|
+
return toRealPath(basePath);
|
|
69
81
|
}
|
|
70
82
|
// 2. ESM TypeScript 映射:导入写了 .js / .mjs / .cjs,但在源码中真实文件为 .ts / .mts / .cts
|
|
71
83
|
if (specifier.endsWith(".js")) {
|
|
72
84
|
const tsCandidate = basePath.slice(0, -3) + ".ts";
|
|
73
|
-
if (
|
|
74
|
-
|
|
75
|
-
return realpathSync(tsCandidate);
|
|
76
|
-
}
|
|
77
|
-
catch {
|
|
78
|
-
return tsCandidate;
|
|
79
|
-
}
|
|
85
|
+
if (isFileReal(tsCandidate)) {
|
|
86
|
+
return toRealPath(tsCandidate);
|
|
80
87
|
}
|
|
81
88
|
const tsxCandidate = basePath.slice(0, -3) + ".tsx";
|
|
82
|
-
if (
|
|
83
|
-
|
|
84
|
-
return realpathSync(tsxCandidate);
|
|
85
|
-
}
|
|
86
|
-
catch {
|
|
87
|
-
return tsxCandidate;
|
|
88
|
-
}
|
|
89
|
+
if (isFileReal(tsxCandidate)) {
|
|
90
|
+
return toRealPath(tsxCandidate);
|
|
89
91
|
}
|
|
90
92
|
}
|
|
91
93
|
else if (specifier.endsWith(".mjs")) {
|
|
92
94
|
const mtsCandidate = basePath.slice(0, -4) + ".mts";
|
|
93
|
-
if (
|
|
94
|
-
|
|
95
|
-
return realpathSync(mtsCandidate);
|
|
96
|
-
}
|
|
97
|
-
catch {
|
|
98
|
-
return mtsCandidate;
|
|
99
|
-
}
|
|
95
|
+
if (isFileReal(mtsCandidate)) {
|
|
96
|
+
return toRealPath(mtsCandidate);
|
|
100
97
|
}
|
|
101
98
|
}
|
|
102
99
|
else if (specifier.endsWith(".cjs")) {
|
|
103
100
|
const ctsCandidate = basePath.slice(0, -4) + ".cts";
|
|
104
|
-
if (
|
|
105
|
-
|
|
106
|
-
return realpathSync(ctsCandidate);
|
|
107
|
-
}
|
|
108
|
-
catch {
|
|
109
|
-
return ctsCandidate;
|
|
110
|
-
}
|
|
101
|
+
if (isFileReal(ctsCandidate)) {
|
|
102
|
+
return toRealPath(ctsCandidate);
|
|
111
103
|
}
|
|
112
104
|
}
|
|
113
105
|
// 3. 补充扩展名尝试
|
|
114
106
|
for (const ext of RESOLUTION_EXTENSIONS) {
|
|
115
107
|
const cand = basePath + ext;
|
|
116
|
-
if (
|
|
117
|
-
|
|
118
|
-
return realpathSync(cand);
|
|
119
|
-
}
|
|
120
|
-
catch {
|
|
121
|
-
return cand;
|
|
122
|
-
}
|
|
108
|
+
if (isFileReal(cand)) {
|
|
109
|
+
return toRealPath(cand);
|
|
123
110
|
}
|
|
124
111
|
}
|
|
125
112
|
// 4. 目录默认 index 尝试
|
|
@@ -127,13 +114,8 @@ export function resolveRelativeModule(fromDir, specifier) {
|
|
|
127
114
|
if (ext === "")
|
|
128
115
|
continue;
|
|
129
116
|
const cand = join(basePath, `index${ext}`);
|
|
130
|
-
if (
|
|
131
|
-
|
|
132
|
-
return realpathSync(cand);
|
|
133
|
-
}
|
|
134
|
-
catch {
|
|
135
|
-
return cand;
|
|
136
|
-
}
|
|
117
|
+
if (isFileReal(cand)) {
|
|
118
|
+
return toRealPath(cand);
|
|
137
119
|
}
|
|
138
120
|
}
|
|
139
121
|
return undefined;
|
|
@@ -144,59 +126,24 @@ export function resolveRelativeModule(fromDir, specifier) {
|
|
|
144
126
|
*/
|
|
145
127
|
export function assertRelativeDependenciesIntegrity(projectRoot, plan) {
|
|
146
128
|
const root = resolve(projectRoot);
|
|
147
|
-
|
|
148
|
-
try {
|
|
149
|
-
realRoot = existsSync(root) ? realpathSync(root) : root;
|
|
150
|
-
}
|
|
151
|
-
catch {
|
|
152
|
-
realRoot = root;
|
|
153
|
-
}
|
|
129
|
+
const realRoot = toRealPath(root);
|
|
154
130
|
// 收集已包含在构建规划中的全部文件物理绝对路径
|
|
155
131
|
const collectedPaths = new Set();
|
|
156
132
|
for (const act of plan.actions) {
|
|
157
133
|
if (act.resolvedPath) {
|
|
158
|
-
|
|
159
|
-
const real = existsSync(act.resolvedPath)
|
|
160
|
-
? realpathSync(act.resolvedPath)
|
|
161
|
-
: resolve(act.resolvedPath);
|
|
162
|
-
collectedPaths.add(real);
|
|
163
|
-
}
|
|
164
|
-
catch {
|
|
165
|
-
collectedPaths.add(resolve(act.resolvedPath));
|
|
166
|
-
}
|
|
134
|
+
collectedPaths.add(toRealPath(act.resolvedPath));
|
|
167
135
|
}
|
|
168
136
|
}
|
|
169
137
|
for (const dep of plan.dependencies.modulesAndAssets) {
|
|
170
138
|
if (dep.resolvedPath) {
|
|
171
|
-
|
|
172
|
-
const real = existsSync(dep.resolvedPath)
|
|
173
|
-
? realpathSync(dep.resolvedPath)
|
|
174
|
-
: resolve(dep.resolvedPath);
|
|
175
|
-
collectedPaths.add(real);
|
|
176
|
-
}
|
|
177
|
-
catch {
|
|
178
|
-
collectedPaths.add(resolve(dep.resolvedPath));
|
|
179
|
-
}
|
|
139
|
+
collectedPaths.add(toRealPath(dep.resolvedPath));
|
|
180
140
|
}
|
|
181
141
|
}
|
|
182
142
|
// 待校验文件队列(包括全部 Action 及其收集的 TS/JS 模块)
|
|
183
143
|
const queue = [];
|
|
184
144
|
for (const act of plan.actions) {
|
|
185
145
|
if (act.resolvedPath && existsSync(act.resolvedPath)) {
|
|
186
|
-
|
|
187
|
-
queue.push({
|
|
188
|
-
file: existsSync(act.resolvedPath)
|
|
189
|
-
? realpathSync(act.resolvedPath)
|
|
190
|
-
: resolve(act.resolvedPath),
|
|
191
|
-
actionId: act.id,
|
|
192
|
-
});
|
|
193
|
-
}
|
|
194
|
-
catch {
|
|
195
|
-
queue.push({
|
|
196
|
-
file: resolve(act.resolvedPath),
|
|
197
|
-
actionId: act.id,
|
|
198
|
-
});
|
|
199
|
-
}
|
|
146
|
+
queue.push({ file: toRealPath(act.resolvedPath), actionId: act.id });
|
|
200
147
|
}
|
|
201
148
|
}
|
|
202
149
|
const visited = new Set();
|
package/dist/export-batch.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { mkdirSync } from "node:fs";
|
|
2
2
|
import { join, resolve } from "node:path";
|
|
3
|
-
import {
|
|
3
|
+
import { loadProjectConfig } from "@actiondock/core";
|
|
4
4
|
import { BuilderError } from "./errors.js";
|
|
5
|
+
import { allocatePackageDirName } from "./manifest.js";
|
|
5
6
|
/**
|
|
6
7
|
* 执行批量导出多个 Skill。
|
|
7
8
|
*/
|
|
@@ -15,11 +16,8 @@ export async function exportBatchImpl(options, exportSingle) {
|
|
|
15
16
|
const usedDirNames = new Set();
|
|
16
17
|
for (const projectRoot of options.projectRoots) {
|
|
17
18
|
const config = loadProjectConfig(projectRoot);
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
pkgSlug = config.id.replace(/[^a-zA-Z0-9-_]/g, "-").replace(/^-+|-+$/g, "");
|
|
21
|
-
}
|
|
22
|
-
usedDirNames.add(pkgSlug);
|
|
19
|
+
// 目录名分配统一复用 manifest 的 allocatePackageDirName,回退后仍冲突会追加数字后缀
|
|
20
|
+
const pkgSlug = allocatePackageDirName(usedDirNames, config.id);
|
|
23
21
|
const pkgOutDir = join(baseOutDir, `${pkgSlug}-skill`);
|
|
24
22
|
const res = await exportSingle({
|
|
25
23
|
...options,
|
package/dist/export-composite.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { copyFileSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync, } from "node:fs";
|
|
2
2
|
import { basename, dirname, join, resolve } from "node:path";
|
|
3
|
-
import {
|
|
3
|
+
import { loadProjectConfig, } from "@actiondock/core";
|
|
4
|
+
import { getPackageSlug, loadManifest, loadPlaybooks, } from "@actiondock/core/project";
|
|
5
|
+
import { generateCompositeSkillMd } from "./skill/index.js";
|
|
4
6
|
import { BuilderError } from "./errors.js";
|
|
5
7
|
import { collectRelativeFiles, getInternalDependencyVersion, replaceDirAtomic } from "./fs-utils.js";
|
|
6
|
-
import {
|
|
8
|
+
import { allocatePackageDirName, sanitizeExportDependencies } from "./manifest.js";
|
|
7
9
|
import { SelectionPlanner } from "./planner.js";
|
|
8
10
|
import { findExistingCompositeSkillMd, resolveCustomSkillDeclaration, } from "./skill-md.js";
|
|
9
11
|
import { createArchive, resolveArchiveFormat } from "./export-archive.js";
|
|
@@ -65,11 +67,8 @@ export async function exportCompositeImpl(options, exportSubpackage) {
|
|
|
65
67
|
pkgSlug = basename(resolve(projectRoot));
|
|
66
68
|
}
|
|
67
69
|
else {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
pkgSlug = config.id.replace(/[^a-zA-Z0-9-_]/g, "-").replace(/^-+|-+$/g, "");
|
|
71
|
-
}
|
|
72
|
-
usedDirNames.add(pkgSlug);
|
|
70
|
+
// 目录名分配统一复用 manifest 的 allocatePackageDirName,回退后仍冲突会追加数字后缀
|
|
71
|
+
pkgSlug = allocatePackageDirName(usedDirNames, config.id);
|
|
73
72
|
}
|
|
74
73
|
let actionIds;
|
|
75
74
|
let playbookIds;
|
|
@@ -179,6 +178,7 @@ export async function exportCompositeImpl(options, exportSubpackage) {
|
|
|
179
178
|
}
|
|
180
179
|
/**
|
|
181
180
|
* 复合套件聚合各子包依赖并生成复合根目录 package.json。
|
|
181
|
+
* 依赖清洗统一复用 manifest 的 sanitizeExportDependencies 单一入口,与单包导出口径一致。
|
|
182
182
|
*/
|
|
183
183
|
function writeCompositePkgJson(stagingDir, packagesDestDir, packageInfos, bundleSlug, options) {
|
|
184
184
|
const aggregatedDeps = {
|
|
@@ -189,21 +189,7 @@ function writeCompositePkgJson(stagingDir, packagesDestDir, packageInfos, bundle
|
|
|
189
189
|
if (existsSync(pkgJsonPath)) {
|
|
190
190
|
try {
|
|
191
191
|
const parsed = JSON.parse(readFileSync(pkgJsonPath, "utf-8"));
|
|
192
|
-
|
|
193
|
-
assertNoFileProtocolDeps(parsed.dependencies, "exported skill packages");
|
|
194
|
-
for (const [dep, ver] of Object.entries(parsed.dependencies)) {
|
|
195
|
-
const verStr = String(ver);
|
|
196
|
-
if (dep.startsWith("@actiondock/")) {
|
|
197
|
-
aggregatedDeps[dep] = getInternalDependencyVersion();
|
|
198
|
-
}
|
|
199
|
-
else if (verStr.startsWith("workspace:")) {
|
|
200
|
-
aggregatedDeps[dep] = resolveWorkspaceDepVersion(join(packagesDestDir, info.packageDir), dep, verStr);
|
|
201
|
-
}
|
|
202
|
-
else {
|
|
203
|
-
aggregatedDeps[dep] = verStr;
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
}
|
|
192
|
+
Object.assign(aggregatedDeps, sanitizeExportDependencies(join(packagesDestDir, info.packageDir), parsed.dependencies, "exported skill packages", false));
|
|
207
193
|
}
|
|
208
194
|
catch (err) {
|
|
209
195
|
if (err instanceof BuilderError)
|
package/dist/export-node.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { generateStandaloneSkillMd } from "
|
|
1
|
+
import { generateStandaloneSkillMd } from "./skill/index.js";
|
|
2
2
|
import { buildProject } from "./build.js";
|
|
3
3
|
import { collectRelativeFiles } from "./fs-utils.js";
|
|
4
4
|
import { buildConfigForTemplates, toPlaybookDefinitions, toSkillActionItems, writeSkillMd, } from "./skill-md.js";
|
package/dist/export-source.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { copyFileSync, existsSync,
|
|
2
|
-
import { basename,
|
|
3
|
-
import { generateSourceSkillMd } from "
|
|
1
|
+
import { copyFileSync, existsSync, readFileSync, writeFileSync, } from "node:fs";
|
|
2
|
+
import { basename, join } from "node:path";
|
|
3
|
+
import { generateSourceSkillMd } from "./skill/index.js";
|
|
4
4
|
import { BuilderError } from "./errors.js";
|
|
5
5
|
import { getInternalDependencyVersion } from "./fs-utils.js";
|
|
6
|
-
import { assertValidManifestActionIds,
|
|
6
|
+
import { assertValidManifestActionIds, sanitizeExportDependencies, serializePlanManifest, } from "./manifest.js";
|
|
7
|
+
import { copyPlanEntries } from "./stage-sources.js";
|
|
7
8
|
import { buildConfigForTemplates, toPlaybookDefinitions, toSkillActionItems, writeSkillMd, } from "./skill-md.js";
|
|
8
9
|
/**
|
|
9
10
|
* 源码型 Skill 导出装配层。
|
|
@@ -17,10 +18,6 @@ import { buildConfigForTemplates, toPlaybookDefinitions, toSkillActionItems, wri
|
|
|
17
18
|
export function stageSourceSkill(root, skillDir, plan, options, pkgSlug) {
|
|
18
19
|
const actionsDir = plan.actionsDir || "actions";
|
|
19
20
|
const playbooksDir = plan.playbooksDir || "playbooks";
|
|
20
|
-
const playbooksDestDir = join(skillDir, playbooksDir);
|
|
21
|
-
if (plan.playbooks.length > 0) {
|
|
22
|
-
mkdirSync(playbooksDestDir, { recursive: true });
|
|
23
|
-
}
|
|
24
21
|
const configForTemplates = buildConfigForTemplates(plan, actionsDir, playbooksDir);
|
|
25
22
|
const usedExistingSkillMd = writeSkillMd(root, skillDir, plan, { skipSkillMd: options.skipSkillMd, skillMdPath: options.skillMdPath, pkgSlug }, () => generateSourceSkillMd(configForTemplates, toSkillActionItems(plan.actions), toPlaybookDefinitions(plan.playbooks)));
|
|
26
23
|
// 导出精简后的 actiondock.json 项目配置(项目元数据与清单的单一事实源)
|
|
@@ -39,63 +36,16 @@ export function stageSourceSkill(root, skillDir, plan, options, pkgSlug) {
|
|
|
39
36
|
if (existsSync(tsconfigPath)) {
|
|
40
37
|
copyFileSync(tsconfigPath, join(skillDir, "tsconfig.json"));
|
|
41
38
|
}
|
|
42
|
-
// 拷贝 Action
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
47
|
-
if (existsSync(act.resolvedPath)) {
|
|
48
|
-
const destFile = join(skillDir, act.entry);
|
|
49
|
-
mkdirSync(dirname(destFile), { recursive: true });
|
|
50
|
-
copyFileSync(act.resolvedPath, destFile);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
// 拷贝静态资产与代码模块文件,保留相对路径
|
|
54
|
-
for (const dep of plan.dependencies.modulesAndAssets) {
|
|
55
|
-
if ((dep.type === "asset" || dep.type === "module" || dep.type === "file") &&
|
|
56
|
-
existsSync(dep.resolvedPath)) {
|
|
57
|
-
const destAsset = join(skillDir, dep.path);
|
|
58
|
-
mkdirSync(dirname(destAsset), { recursive: true });
|
|
59
|
-
copyFileSync(dep.resolvedPath, destAsset);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
// 拷贝 Playbook 规程文件
|
|
63
|
-
for (const pb of plan.playbooks) {
|
|
64
|
-
if (existsSync(pb.filePath)) {
|
|
65
|
-
const destPb = join(playbooksDestDir, basename(pb.filePath));
|
|
66
|
-
copyFileSync(pb.filePath, destPb);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
39
|
+
// 拷贝 Action 源码、静态资产与 Playbook 规程文件(共享拷贝内核,行为与 stage-sources 单一事实源对齐)
|
|
40
|
+
copyPlanEntries(skillDir, plan, {
|
|
41
|
+
playbookRelPath: (pb) => join(playbooksDir, basename(pb.filePath)),
|
|
42
|
+
});
|
|
69
43
|
return usedExistingSkillMd;
|
|
70
44
|
}
|
|
71
45
|
/**
|
|
72
|
-
* 生成源码型 Skill 的 package.json
|
|
46
|
+
* 生成源码型 Skill 的 package.json(依赖清洗统一复用 manifest 的 sanitizeExportDependencies 单一入口)。
|
|
73
47
|
*/
|
|
74
48
|
function writeSourceSkillPkgJson(root, skillDir, plan, pkgSlug) {
|
|
75
|
-
const sanitizeDependencies = (deps) => {
|
|
76
|
-
const result = {};
|
|
77
|
-
if (deps && typeof deps === "object") {
|
|
78
|
-
for (const [k, v] of Object.entries(deps)) {
|
|
79
|
-
const verStr = String(v);
|
|
80
|
-
if (verStr.startsWith("file:")) {
|
|
81
|
-
throw new BuilderError(`Unsupported file: dependency for '${k}'. Runtime dependencies must not use file: protocol in exported skill packages.`);
|
|
82
|
-
}
|
|
83
|
-
if (k.startsWith("@actiondock/")) {
|
|
84
|
-
result[k] = getInternalDependencyVersion();
|
|
85
|
-
}
|
|
86
|
-
else if (verStr.startsWith("workspace:")) {
|
|
87
|
-
result[k] = resolveWorkspaceDepVersion(root, k, verStr);
|
|
88
|
-
}
|
|
89
|
-
else {
|
|
90
|
-
result[k] = verStr;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
if (!result["@actiondock/sdk"]) {
|
|
95
|
-
result["@actiondock/sdk"] = getInternalDependencyVersion();
|
|
96
|
-
}
|
|
97
|
-
return result;
|
|
98
|
-
};
|
|
99
49
|
let exportedPkg;
|
|
100
50
|
const projectPkgPath = join(root, "package.json");
|
|
101
51
|
if (existsSync(projectPkgPath)) {
|
|
@@ -107,7 +57,7 @@ function writeSourceSkillPkgJson(root, skillDir, plan, pkgSlug) {
|
|
|
107
57
|
version: plan.version || parsed.version || "0.1.0",
|
|
108
58
|
description: plan.description || parsed.description,
|
|
109
59
|
type: "module",
|
|
110
|
-
dependencies:
|
|
60
|
+
dependencies: sanitizeExportDependencies(root, parsed.dependencies, "exported skill packages"),
|
|
111
61
|
};
|
|
112
62
|
}
|
|
113
63
|
catch (err) {
|
package/dist/exporter.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, rmSync } from "node:fs";
|
|
2
2
|
import { basename, dirname, join, resolve } from "node:path";
|
|
3
|
-
import { getPackageSlug } from "@actiondock/core";
|
|
3
|
+
import { getPackageSlug } from "@actiondock/core/project";
|
|
4
4
|
import { BuilderError } from "./errors.js";
|
|
5
5
|
import { replaceDirAtomic } from "./fs-utils.js";
|
|
6
6
|
import { collectRelativeFiles } from "./fs-utils.js";
|
|
7
7
|
import { SelectionPlanner } from "./planner.js";
|
|
8
|
+
import { isOwnAction } from "./types.js";
|
|
8
9
|
import { createArchive, resolveArchiveFormat } from "./export-archive.js";
|
|
9
10
|
import { stageSourceSkill } from "./export-source.js";
|
|
10
11
|
import { exportNodeSkill } from "./export-node.js";
|
|
@@ -24,13 +25,6 @@ export class SkillExporter {
|
|
|
24
25
|
* @returns 导出产物详细描述
|
|
25
26
|
*/
|
|
26
27
|
async export(options) {
|
|
27
|
-
// 彻底废弃旧的独立二进制编译分支与参数
|
|
28
|
-
if (options.standalone ||
|
|
29
|
-
options.mode === "standalone" ||
|
|
30
|
-
options.target !== undefined ||
|
|
31
|
-
options.bytecode !== undefined) {
|
|
32
|
-
throw new BuilderError("The '--standalone' mode has been removed in ActionDock 2.0. Please use '--mode node' for self-contained Node.js directory skills, or '--mode source' for source-based skills.", "UNSUPPORTED_BUILD_MODE");
|
|
33
|
-
}
|
|
34
28
|
const root = resolve(options.projectRoot);
|
|
35
29
|
const mode = options.mode === "node" ? "node" : "source";
|
|
36
30
|
// 调用 SelectionPlanner 执行声明式构建规划
|
|
@@ -109,7 +103,7 @@ export class SkillExporter {
|
|
|
109
103
|
if (options.archive) {
|
|
110
104
|
archivePath = await createArchive(targetSkillDir, resolveArchiveFormat(options));
|
|
111
105
|
}
|
|
112
|
-
const ownActions = plan.actions.filter((a) =>
|
|
106
|
+
const ownActions = plan.actions.filter((a) => isOwnAction(a));
|
|
113
107
|
return {
|
|
114
108
|
packageId: plan.packageId,
|
|
115
109
|
version: plan.version,
|
package/dist/fs-utils.d.ts
CHANGED
|
@@ -2,9 +2,10 @@ export declare function moveDirAtomic(src: string, dest: string): Promise<void>;
|
|
|
2
2
|
/**
|
|
3
3
|
* 递归收集目录内全部文件的相对路径(正斜杠分隔)。
|
|
4
4
|
* 收集完成后对最终 POSIX 相对路径统一排序,保证跨平台 digest 一致性;
|
|
5
|
-
*
|
|
5
|
+
* 目录遍历统一复用 core 的 traverseDirectory 单一事实源,
|
|
6
|
+
* 自带软链接越界跳过与循环拦截防护。
|
|
6
7
|
*/
|
|
7
|
-
export declare function collectRelativeFiles(dir: string
|
|
8
|
+
export declare function collectRelativeFiles(dir: string): string[];
|
|
8
9
|
/**
|
|
9
10
|
* 获取内部 @actiondock/* 依赖的版本号规则。
|
|
10
11
|
* 预发布版本采用精确锁定,正式版本采用 ^ 语义范围。
|
package/dist/fs-utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { cpSync, existsSync,
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { cpSync, existsSync, renameSync, rmSync } from "node:fs";
|
|
2
|
+
import { ACTIONDOCK_VERSION } from "@actiondock/core";
|
|
3
|
+
import { traverseDirectory } from "@actiondock/core/project";
|
|
4
4
|
/**
|
|
5
5
|
* builder 包内共享的文件系统基础设施。
|
|
6
6
|
* 消除 pack / build / exporter 三个业务模块中成体系的重复实现,
|
|
@@ -67,72 +67,15 @@ export async function moveDirAtomic(src, dest) {
|
|
|
67
67
|
/**
|
|
68
68
|
* 递归收集目录内全部文件的相对路径(正斜杠分隔)。
|
|
69
69
|
* 收集完成后对最终 POSIX 相对路径统一排序,保证跨平台 digest 一致性;
|
|
70
|
-
*
|
|
70
|
+
* 目录遍历统一复用 core 的 traverseDirectory 单一事实源,
|
|
71
|
+
* 自带软链接越界跳过与循环拦截防护。
|
|
71
72
|
*/
|
|
72
|
-
export function collectRelativeFiles(dir
|
|
73
|
-
const results = collectRelativeFilesUnsorted(dir, baseDir, new Set());
|
|
74
|
-
return results.sort();
|
|
75
|
-
}
|
|
76
|
-
function collectRelativeFilesUnsorted(dir, baseDir, visited) {
|
|
73
|
+
export function collectRelativeFiles(dir) {
|
|
77
74
|
if (!existsSync(dir))
|
|
78
75
|
return [];
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
catch {
|
|
84
|
-
// 忽略根目录真实路径解析异常,退化为不携带根真实路径的循环拦截
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
const results = [];
|
|
88
|
-
let entries;
|
|
89
|
-
try {
|
|
90
|
-
entries = readdirSync(dir).sort();
|
|
91
|
-
}
|
|
92
|
-
catch {
|
|
93
|
-
return [];
|
|
94
|
-
}
|
|
95
|
-
for (const entry of entries) {
|
|
96
|
-
const fullPath = join(dir, entry);
|
|
97
|
-
try {
|
|
98
|
-
assertPathWithinRoot(baseDir, fullPath, "collect files path");
|
|
99
|
-
}
|
|
100
|
-
catch {
|
|
101
|
-
continue;
|
|
102
|
-
}
|
|
103
|
-
let real;
|
|
104
|
-
try {
|
|
105
|
-
real = existsSync(fullPath) ? realpathSync(fullPath) : fullPath;
|
|
106
|
-
}
|
|
107
|
-
catch {
|
|
108
|
-
continue;
|
|
109
|
-
}
|
|
110
|
-
try {
|
|
111
|
-
assertPathWithinRoot(baseDir, real, "collect files path");
|
|
112
|
-
}
|
|
113
|
-
catch {
|
|
114
|
-
// 忽略并跳过指向 baseDir 外部的软链接,与归档防护策略保持一致
|
|
115
|
-
continue;
|
|
116
|
-
}
|
|
117
|
-
if (visited.has(real)) {
|
|
118
|
-
continue;
|
|
119
|
-
}
|
|
120
|
-
visited.add(real);
|
|
121
|
-
try {
|
|
122
|
-
const stat = statSync(fullPath);
|
|
123
|
-
if (stat.isDirectory()) {
|
|
124
|
-
results.push(...collectRelativeFilesUnsorted(fullPath, baseDir, visited));
|
|
125
|
-
}
|
|
126
|
-
else if (stat.isFile()) {
|
|
127
|
-
results.push(relative(baseDir, fullPath).split(sep).join("/"));
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
catch {
|
|
131
|
-
// 忽略无法访问或损坏的文件/符号链接
|
|
132
|
-
continue;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
return results;
|
|
76
|
+
return traverseDirectory(dir)
|
|
77
|
+
.map((entry) => entry.relPath)
|
|
78
|
+
.sort();
|
|
136
79
|
}
|
|
137
80
|
/**
|
|
138
81
|
* 获取内部 @actiondock/* 依赖的版本号规则。
|
package/dist/index.d.ts
CHANGED
|
@@ -1,17 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @actiondock/builder 公共导出面。
|
|
3
|
-
*
|
|
3
|
+
* 专注于暴露核心构建主接口与必要契约,低层内部工具作为包内模块封装。
|
|
4
4
|
*/
|
|
5
5
|
export { BuilderError, PlannerError } from "./errors.js";
|
|
6
|
-
export { collectRelativeFiles, getInternalDependencyVersion, moveDirAtomic, replaceDirAtomic, } from "./fs-utils.js";
|
|
7
|
-
export { assertNoFileProtocolDeps, assertValidManifestActionIds, serializeManifestAction, serializeManifestPlaybooks, serializePlanManifest, } from "./manifest.js";
|
|
8
|
-
export type { SerializePlanManifestOptions } from "./manifest.js";
|
|
9
|
-
export { createTarGzArchive, createTarGzArchiveAsync, createZipArchive, createZipArchiveAsync, dosDateTime, writeToStream, } from "./archive.js";
|
|
10
|
-
export type { TarGzArchiveOptions } from "./archive.js";
|
|
11
|
-
export { SelectionPlanner } from "./planner.js";
|
|
12
|
-
export { assertRelativeDependenciesIntegrity, extractRelativeSpecifiers, resolveRelativeModule, } from "./dependency-check.js";
|
|
13
6
|
export { buildProject } from "./build.js";
|
|
14
7
|
export { packProject } from "./pack.js";
|
|
15
8
|
export { exportCompositeSkill, exportSkill, exportSkillBatch, SkillExporter, } from "./exporter.js";
|
|
16
|
-
export {
|
|
17
|
-
export type {
|
|
9
|
+
export { SelectionPlanner } from "./planner.js";
|
|
10
|
+
export type { ArchiveFormat, BatchSkillExportOptions, BatchSkillExportResult, BuildOptions, BuildPlan, BuildResult, CompositeSkillExportOptions, CompositeSkillExportResult, ExportSkillOptions, ExportSkillResult, PackOptions, PackResult, SelectionPlan, SelectionPlannerOptions, SkillExporterOptions, SkillExportResult, } from "./types.js";
|
package/dist/index.js
CHANGED
|
@@ -1,23 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @actiondock/builder 公共导出面。
|
|
3
|
-
*
|
|
3
|
+
* 专注于暴露核心构建主接口与必要契约,低层内部工具作为包内模块封装。
|
|
4
4
|
*/
|
|
5
|
-
//
|
|
5
|
+
// 错误模型
|
|
6
6
|
export { BuilderError, PlannerError } from "./errors.js";
|
|
7
|
-
//
|
|
8
|
-
export { collectRelativeFiles, getInternalDependencyVersion, moveDirAtomic, replaceDirAtomic, } from "./fs-utils.js";
|
|
9
|
-
// 清单组装与依赖协议校验
|
|
10
|
-
export { assertNoFileProtocolDeps, assertValidManifestActionIds, serializeManifestAction, serializeManifestPlaybooks, serializePlanManifest, } from "./manifest.js";
|
|
11
|
-
// 归档压缩
|
|
12
|
-
export { createTarGzArchive, createTarGzArchiveAsync, createZipArchive, createZipArchiveAsync, dosDateTime, writeToStream, } from "./archive.js";
|
|
13
|
-
// 构建规划
|
|
14
|
-
export { SelectionPlanner } from "./planner.js";
|
|
15
|
-
// 相对依赖完整性校验
|
|
16
|
-
export { assertRelativeDependenciesIntegrity, extractRelativeSpecifiers, resolveRelativeModule, } from "./dependency-check.js";
|
|
17
|
-
// 目录型构建与 npm 打包
|
|
7
|
+
// 构建、打包与导出主接口
|
|
18
8
|
export { buildProject } from "./build.js";
|
|
19
9
|
export { packProject } from "./pack.js";
|
|
20
|
-
// Skill 导出
|
|
21
|
-
// 入口函数与导出器门面位于 ./exporter;SKILL.md 发现能力单一事实源位于 ./skill-md
|
|
22
10
|
export { exportCompositeSkill, exportSkill, exportSkillBatch, SkillExporter, } from "./exporter.js";
|
|
23
|
-
|
|
11
|
+
// 构建规划器
|
|
12
|
+
export { SelectionPlanner } from "./planner.js";
|
package/dist/manifest.d.ts
CHANGED
|
@@ -64,6 +64,32 @@ export declare function assertNoFileProtocolDeps(dependencies: Record<string, un
|
|
|
64
64
|
* workspace:* 则在本地 node_modules 与 monorepo packages 目录中搜索目标包版本。
|
|
65
65
|
*/
|
|
66
66
|
export declare function resolveWorkspaceDepVersion(root: string, depName: string, ver: string): string;
|
|
67
|
+
/**
|
|
68
|
+
* 为导出子包分配互不冲突的目录名。
|
|
69
|
+
*
|
|
70
|
+
* 首选 Package ID 尾段(getPackageSlug);冲突时回退为 ID 全量的安全形式,
|
|
71
|
+
* 回退后仍冲突(如两个同尾段 ID 回退值相同)则追加数字后缀直至唯一,
|
|
72
|
+
* 严禁仅加入 used 集合而不二次消歧导致目录互相覆盖。
|
|
73
|
+
*
|
|
74
|
+
* @param used 已占用的目录名集合(函数内部会登记分配结果)
|
|
75
|
+
* @param configId 待分配目录名的 Package ID
|
|
76
|
+
*/
|
|
77
|
+
export declare function allocatePackageDirName(used: Set<string>, configId: string): string;
|
|
78
|
+
/**
|
|
79
|
+
* 导出产物依赖清洗单一入口。
|
|
80
|
+
*
|
|
81
|
+
* 清洗规则(单包源码导出与复合套件聚合导出共用同一事实源):
|
|
82
|
+
* - file: 本地协议拒绝(经 assertNoFileProtocolDeps);
|
|
83
|
+
* - @actiondock/* 内部依赖覆写为内部版本规则;
|
|
84
|
+
* - workspace: 前缀解析为真实版本(经 resolveWorkspaceDepVersion);
|
|
85
|
+
* - 其余依赖原样保留。
|
|
86
|
+
*
|
|
87
|
+
* @param root 解析 workspace 依赖时的参照根目录
|
|
88
|
+
* @param deps 待清洗的依赖字典(可选)
|
|
89
|
+
* @param context 错误消息中的场景描述
|
|
90
|
+
* @param ensureSdk 是否保证 @actiondock/sdk 依赖存在(单包导出需要,复合根目录已预置)
|
|
91
|
+
*/
|
|
92
|
+
export declare function sanitizeExportDependencies(root: string, deps: Record<string, unknown> | undefined, context: string, ensureSdk?: boolean): Record<string, string>;
|
|
67
93
|
/**
|
|
68
94
|
* 读取并解析 package.json,解析失败抛出 BuilderError。
|
|
69
95
|
*/
|