@actiondock/builder 2.16.0 → 2.18.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 +36 -15
- package/dist/build.js +16 -3
- package/dist/dependency-check.d.ts +1 -1
- package/dist/dependency-check.js +5 -0
- package/dist/export-composite.js +8 -3
- package/dist/export-source.d.ts +1 -1
- package/dist/export-source.js +16 -2
- package/dist/exporter.js +10 -3
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/skill/custom-parser.d.ts +8 -2
- package/dist/skill/custom-parser.js +3 -1
- package/dist/skill/templates.d.ts +8 -2
- package/dist/skill/templates.js +91 -44
- package/dist/skill-md.d.ts +9 -3
- package/dist/skill-md.js +59 -11
- package/dist/types.d.ts +9 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -40,21 +40,28 @@ ActionDock 2.x 构建规划、目录交付与技能导出包。
|
|
|
40
40
|
|
|
41
41
|
### SkillExporter 与技能导出
|
|
42
42
|
|
|
43
|
-
[SkillExporter](./src/exporter.ts)
|
|
43
|
+
[SkillExporter](./src/exporter.ts)、`exportSkill` 以及 `exportCompositeSkill` 导出函数将原子 Action 与操作规程 Playbook 打包导出为面向主流 AI 智能体生态的标准 Agent Skill 资产:
|
|
44
44
|
|
|
45
|
-
-
|
|
46
|
-
-
|
|
45
|
+
- 默认单包浅导出机制:默认采用单包源码浅闭包导出,仅复制当前包自身源码与规程,产物清单完整保留 `uses` 跨包逻辑契约,不物理拷贝外部包源码,单包结构纯粹透明,天然支持配合 `playbooks` 或 `actions` 执行规程驱动剪枝。
|
|
46
|
+
- 显式外部依赖物化:支持 `bundleDeps` 选项。当显式开启且依赖闭包跨越外部已链接包时,自顶向下递归解析依赖链并将外部依赖包物理物化进产物根目录的 `packages/*` 子目录,展开为自包含的微型工作区产物结构;展开为复合形态时与过滤参数严格互斥(抛出 `FILTERS_UNSUPPORTED_FOR_COMPOSITE` 错误)。
|
|
47
|
+
- 独立自包含 Node 目录型导出:支持 `standalone` 选项(等价于 `mode: "node"`),生成免全局 `ad` 命令行工具的自包含目录,内置独立运行脚本与说明书,配合 `vendorDeps` 可实现生产依赖完全内置。
|
|
47
48
|
- 本地依赖完整性强校验:严格断言 Action 源码中的相对路径导入。若引用了未在 `actions` 且未在 `files` 字段中声明的本地模块,直接中断构建并抛出 `BuilderError`(错误码 `UNMET_LOCAL_DEPENDENCY`),彻底杜绝缺失依赖的产物分发。
|
|
48
|
-
-
|
|
49
|
-
-
|
|
50
|
-
- 压缩归档:支持 `--archive` 选项将导出的技能目录打包为 `.zip` 或 `.tar.gz` 格式。
|
|
49
|
+
- 说明书定制与复合套件导出:支持单包与复合套件通过 `customMdPath` 注入插槽定制模板(或放置 `SKILL.custom.md` 自动发现);支持 `exportCompositeSkill` 函数将工作区内的多个包统一导出为复合工作区技能套件;支持通过 `skillMdOnly` 实现就地仅原位刷新说明书。
|
|
50
|
+
- 压缩归档:支持 `archive` 选项将导出的技能目录打包为 `.zip` 或 `.tar.gz` 格式。
|
|
51
51
|
|
|
52
52
|
---
|
|
53
53
|
|
|
54
54
|
## 编程调用示例
|
|
55
55
|
|
|
56
56
|
```ts
|
|
57
|
-
import {
|
|
57
|
+
import {
|
|
58
|
+
buildProject,
|
|
59
|
+
packProject,
|
|
60
|
+
SelectionPlanner,
|
|
61
|
+
SkillExporter,
|
|
62
|
+
exportSkill,
|
|
63
|
+
exportCompositeSkill,
|
|
64
|
+
} from "@actiondock/builder";
|
|
58
65
|
|
|
59
66
|
// 计算依赖规划闭包
|
|
60
67
|
const planner = new SelectionPlanner({ projectRoot: "/path/to/project" });
|
|
@@ -73,20 +80,34 @@ const packResult = await packProject({
|
|
|
73
80
|
outDir: "./dist/npm",
|
|
74
81
|
});
|
|
75
82
|
|
|
76
|
-
//
|
|
83
|
+
// 默认源码单包浅导出(支持规程定向裁剪)
|
|
77
84
|
const skillResult = await exportSkill({
|
|
78
85
|
projectRoot: "/path/to/project",
|
|
79
|
-
outDir: "./dist/skills",
|
|
86
|
+
outDir: "./dist/skills/review-pr",
|
|
80
87
|
playbooks: ["review-pr"],
|
|
81
|
-
mode: "source",
|
|
82
88
|
});
|
|
83
89
|
|
|
84
|
-
//
|
|
85
|
-
const
|
|
86
|
-
const customResult = await exporter.export({
|
|
90
|
+
// 显式物化外部依赖导出(展开为微型工作区)
|
|
91
|
+
const bundledResult = await exportSkill({
|
|
87
92
|
projectRoot: "/path/to/project",
|
|
88
|
-
outDir: "./dist/skills
|
|
89
|
-
|
|
93
|
+
outDir: "./dist/skills/bundled",
|
|
94
|
+
bundleDeps: true,
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// 独立自包含 Node.js 目录型导出(免全局 ad 命令行,物化生产依赖)
|
|
98
|
+
const standaloneResult = await exportSkill({
|
|
99
|
+
projectRoot: "/path/to/project",
|
|
100
|
+
outDir: "./dist/skills/standalone",
|
|
101
|
+
standalone: true,
|
|
102
|
+
vendorDeps: true,
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// 复合套件聚合导出与就地原位刷新说明书
|
|
106
|
+
const compositeResult = await exportCompositeSkill({
|
|
107
|
+
bundleName: "vip-agent-tools",
|
|
108
|
+
projectRoots: ["/path/to/pkg-a", "/path/to/pkg-b"],
|
|
109
|
+
outDir: "./dist/composite-skill",
|
|
110
|
+
customMdPath: "/path/to/SKILL.custom.md",
|
|
90
111
|
});
|
|
91
112
|
```
|
|
92
113
|
|
package/dist/build.js
CHANGED
|
@@ -12,7 +12,7 @@ import { generateNodeHostEntrySource, generateNodeSupervisorEntrySource } from "
|
|
|
12
12
|
import { vendorDependencies } from "./vendor.js";
|
|
13
13
|
import { generateStandaloneSkillMd } from "./skill/templates.js";
|
|
14
14
|
import { writeRuntimeReferenceFile } from "./export-source.js";
|
|
15
|
-
import { buildConfigForTemplates, writeSkillMd, } from "./skill-md.js";
|
|
15
|
+
import { buildConfigForTemplates, resolveCustomSkillDeclaration, writeSkillMd, } from "./skill-md.js";
|
|
16
16
|
import { createArchive, resolveArchiveFormat } from "./export-archive.js";
|
|
17
17
|
export { copyPlanEntries } from "./stage-sources.js";
|
|
18
18
|
/**
|
|
@@ -310,9 +310,22 @@ export async function exportNodeSkill(root, targetSkillDir, plan, options, pkgSl
|
|
|
310
310
|
allowInstallScripts: options.allowInstallScripts,
|
|
311
311
|
requireReproducible: options.requireReproducible,
|
|
312
312
|
});
|
|
313
|
-
const
|
|
313
|
+
const customDeclaration = resolveCustomSkillDeclaration({
|
|
314
|
+
projectRoot: root,
|
|
315
|
+
customMdPath: options.customMdPath,
|
|
316
|
+
workspaceRoot: options.workspaceRoot,
|
|
317
|
+
});
|
|
318
|
+
const usedExistingSkillMd = writeSkillMd(root, targetSkillDir, {
|
|
319
|
+
skipSkillMd: options.skipSkillMd,
|
|
320
|
+
skillMdPath: options.skillMdPath,
|
|
321
|
+
pkgSlug,
|
|
322
|
+
hasCustomDeclaration: Boolean(customDeclaration),
|
|
323
|
+
}, () => {
|
|
314
324
|
const configForTemplates = buildConfigForTemplates(plan, plan.actionsDir || "actions", plan.playbooksDir || "playbooks");
|
|
315
|
-
return generateStandaloneSkillMd(configForTemplates, plan.actions, plan.playbooks, "node ./entry.mjs"
|
|
325
|
+
return generateStandaloneSkillMd(configForTemplates, plan.actions, plan.playbooks, "node ./entry.mjs", {
|
|
326
|
+
customSections: customDeclaration?.sections,
|
|
327
|
+
description: customDeclaration?.description,
|
|
328
|
+
});
|
|
316
329
|
});
|
|
317
330
|
// 仅在使用自动模板时生成默认运行参考文件;Node 目录型使用自身入口,不要求全局安装 ad
|
|
318
331
|
if (usedExistingSkillMd === undefined && !options.skipSkillMd) {
|
package/dist/dependency-check.js
CHANGED
|
@@ -2,6 +2,7 @@ import { existsSync, readFileSync, realpathSync, statSync } from "node:fs";
|
|
|
2
2
|
import { dirname, join, relative, resolve } from "node:path";
|
|
3
3
|
import { isPathOutsideBoundary } from "@actiondock/core/project";
|
|
4
4
|
import { BuilderError } from "./errors.js";
|
|
5
|
+
import { isOwnAction } from "./types.js";
|
|
5
6
|
/**
|
|
6
7
|
* 移除源码中的单行与多行注释,防止注释内的相对路径字符串误触发依赖解析。
|
|
7
8
|
*/
|
|
@@ -130,6 +131,8 @@ export function assertRelativeDependenciesIntegrity(projectRoot, plan) {
|
|
|
130
131
|
// 收集已包含在构建规划中的全部文件物理绝对路径
|
|
131
132
|
const collectedPaths = new Set();
|
|
132
133
|
for (const act of plan.actions) {
|
|
134
|
+
if (!isOwnAction(act))
|
|
135
|
+
continue;
|
|
133
136
|
if (act.resolvedPath) {
|
|
134
137
|
collectedPaths.add(toRealPath(act.resolvedPath));
|
|
135
138
|
}
|
|
@@ -142,6 +145,8 @@ export function assertRelativeDependenciesIntegrity(projectRoot, plan) {
|
|
|
142
145
|
// 待校验文件队列(包括全部 Action 及其收集的 TS/JS 模块)
|
|
143
146
|
const queue = [];
|
|
144
147
|
for (const act of plan.actions) {
|
|
148
|
+
if (!isOwnAction(act))
|
|
149
|
+
continue;
|
|
145
150
|
if (act.resolvedPath && existsSync(act.resolvedPath)) {
|
|
146
151
|
queue.push({ file: toRealPath(act.resolvedPath), actionId: act.id });
|
|
147
152
|
}
|
package/dist/export-composite.js
CHANGED
|
@@ -20,6 +20,9 @@ export async function exportCompositeImpl(options, exportSubpackage) {
|
|
|
20
20
|
if (!options.bundleName || !options.bundleName.trim()) {
|
|
21
21
|
throw new BuilderError("bundleName is required for composite skill export.");
|
|
22
22
|
}
|
|
23
|
+
if (options.standalone) {
|
|
24
|
+
throw new BuilderError("Composite Skill export currently only supports source mode. Standalone mode is not supported for composite bundles.", "UNSUPPORTED_BUILD_MODE");
|
|
25
|
+
}
|
|
23
26
|
const skillMdOnly = options.skillMdOnly === true;
|
|
24
27
|
const customDeclaration = resolveCustomSkillDeclaration(options);
|
|
25
28
|
const bundleSlug = getPackageSlug(options.bundleName);
|
|
@@ -41,11 +44,11 @@ export async function exportCompositeImpl(options, exportSubpackage) {
|
|
|
41
44
|
const packageSummaries = [];
|
|
42
45
|
let existingSkillPath;
|
|
43
46
|
try {
|
|
44
|
-
//
|
|
47
|
+
// 收集项目根目录;仅在显式指定 bundleDeps 时展开依赖闭包中的外部项目根目录
|
|
45
48
|
const effectiveRoots = new Set();
|
|
46
49
|
for (const r of options.projectRoots) {
|
|
47
50
|
effectiveRoots.add(resolve(r));
|
|
48
|
-
if (!skillMdOnly) {
|
|
51
|
+
if (!skillMdOnly && options.bundleDeps === true) {
|
|
49
52
|
try {
|
|
50
53
|
const p = SelectionPlanner.plan({ projectRoot: r });
|
|
51
54
|
if (p.externalProjectRoots) {
|
|
@@ -111,7 +114,9 @@ export async function exportCompositeImpl(options, exportSubpackage) {
|
|
|
111
114
|
playbooks: playbookIds,
|
|
112
115
|
});
|
|
113
116
|
}
|
|
114
|
-
|
|
117
|
+
const shouldCheckExisting = !skillMdOnly &&
|
|
118
|
+
(Boolean(options.skillMdPath) || !customDeclaration);
|
|
119
|
+
existingSkillPath = shouldCheckExisting ? findExistingCompositeSkillMd(options) : undefined;
|
|
115
120
|
const description = options.description ||
|
|
116
121
|
customDeclaration?.description ||
|
|
117
122
|
`ActionDock 复合技能套件,聚合 ${packageInfos.map((p) => p.config.name).join("、")}`;
|
package/dist/export-source.d.ts
CHANGED
package/dist/export-source.js
CHANGED
|
@@ -7,7 +7,8 @@ import { BuilderError } from "./errors.js";
|
|
|
7
7
|
import { getInternalDependencyVersion } from "./fs-utils.js";
|
|
8
8
|
import { assertValidManifestActionIds, sanitizeExportDependencies, serializePlanManifest, } from "./manifest.js";
|
|
9
9
|
import { copyPlanEntries } from "./stage-sources.js";
|
|
10
|
-
import {
|
|
10
|
+
import { isOwnAction } from "./types.js";
|
|
11
|
+
import { buildConfigForTemplates, resolveCustomSkillDeclaration, writeSkillMd, } from "./skill-md.js";
|
|
11
12
|
/**
|
|
12
13
|
* 源码型 Skill 导出装配层。
|
|
13
14
|
*
|
|
@@ -20,8 +21,21 @@ import { buildConfigForTemplates, writeSkillMd, } from "./skill-md.js";
|
|
|
20
21
|
export function stageSourceSkill(root, skillDir, plan, options, pkgSlug) {
|
|
21
22
|
const actionsDir = plan.actionsDir || "actions";
|
|
22
23
|
const playbooksDir = plan.playbooksDir || "playbooks";
|
|
24
|
+
const customDeclaration = resolveCustomSkillDeclaration({
|
|
25
|
+
projectRoot: root,
|
|
26
|
+
customMdPath: options.customMdPath,
|
|
27
|
+
workspaceRoot: options.workspaceRoot,
|
|
28
|
+
});
|
|
23
29
|
const configForTemplates = buildConfigForTemplates(plan, actionsDir, playbooksDir);
|
|
24
|
-
const usedExistingSkillMd = writeSkillMd(root, skillDir, {
|
|
30
|
+
const usedExistingSkillMd = writeSkillMd(root, skillDir, {
|
|
31
|
+
skipSkillMd: options.skipSkillMd,
|
|
32
|
+
skillMdPath: options.skillMdPath,
|
|
33
|
+
pkgSlug,
|
|
34
|
+
hasCustomDeclaration: Boolean(customDeclaration),
|
|
35
|
+
}, () => generateSourceSkillMd(configForTemplates, plan.actions.filter((a) => isOwnAction(a)), plan.playbooks, {
|
|
36
|
+
customSections: customDeclaration?.sections,
|
|
37
|
+
description: customDeclaration?.description,
|
|
38
|
+
}));
|
|
25
39
|
// 导出精简后的 actiondock.json 项目配置(项目元数据与清单的单一事实源)
|
|
26
40
|
const exportedConfig = serializePlanManifest(plan, {
|
|
27
41
|
omitEmptyConfig: true,
|
package/dist/exporter.js
CHANGED
|
@@ -24,8 +24,11 @@ export class SkillExporter {
|
|
|
24
24
|
* @returns 导出产物详细描述
|
|
25
25
|
*/
|
|
26
26
|
async export(options) {
|
|
27
|
+
if (options.skillMdPath && options.customMdPath) {
|
|
28
|
+
throw new BuilderError("Options 'skillMdPath' and 'customMdPath' cannot be used together. Specify 'skillMdPath' to reuse an existing static document, or 'customMdPath' to customize template generation with custom slots.", "INVALID_EXPORT_OPTIONS");
|
|
29
|
+
}
|
|
27
30
|
const root = resolve(options.projectRoot);
|
|
28
|
-
const mode = options.mode === "node" ? "node" : "source";
|
|
31
|
+
const mode = options.standalone === true || options.mode === "node" ? "node" : "source";
|
|
29
32
|
// 调用 SelectionPlanner 执行声明式构建规划
|
|
30
33
|
const plan = SelectionPlanner.plan({
|
|
31
34
|
projectRoot: root,
|
|
@@ -40,12 +43,12 @@ export class SkillExporter {
|
|
|
40
43
|
const defaultSkillDir = join(root, "dist", defaultFolderName);
|
|
41
44
|
const targetSkillDir = resolve(options.outDir || defaultSkillDir);
|
|
42
45
|
const hasExternalDeps = Boolean(plan.externalProjectRoots && plan.externalProjectRoots.length > 0);
|
|
43
|
-
//
|
|
46
|
+
// 单包源码导出若开启 bundleDeps 且依赖闭包含外部包,导成 mini-workspace 形态(packages/ 下带齐依赖包),和 bundle 统一成一个交付形状
|
|
44
47
|
// 该复合分支会展开全部依赖包,无法保留调用方传入的 actions/playbooks 过滤选项;
|
|
45
48
|
// 静默丢弃过滤会导致产物全量导出,必须显式拒绝并给出调整指引(CLI 侧已有 roots>1 守卫,此处补齐 composite 分支守卫)
|
|
46
49
|
const hasFilters = Boolean((options.actions && options.actions.length > 0) ||
|
|
47
50
|
(options.playbooks && options.playbooks.length > 0));
|
|
48
|
-
const willUseComposite = mode === "source" && !options._isSubpackage && hasExternalDeps;
|
|
51
|
+
const willUseComposite = mode === "source" && !options._isSubpackage && hasExternalDeps && options.bundleDeps === true;
|
|
49
52
|
if (hasFilters && willUseComposite) {
|
|
50
53
|
throw new BuilderError("Filtering options (--actions, --playbook) cannot be combined with a source export whose dependency closure spans external linked packages (composite mini-workspace output). Remove the filtering options to export the full closure, or adjust the 'uses' declarations so the closure stays within a single package.", "FILTERS_UNSUPPORTED_FOR_COMPOSITE");
|
|
51
54
|
}
|
|
@@ -60,6 +63,7 @@ export class SkillExporter {
|
|
|
60
63
|
workspaceRoot: options.workspaceRoot,
|
|
61
64
|
skillMdPath: options.skillMdPath,
|
|
62
65
|
customMdPath: options.customMdPath,
|
|
66
|
+
bundleDeps: options.bundleDeps,
|
|
63
67
|
});
|
|
64
68
|
return {
|
|
65
69
|
packageId: plan.packageId,
|
|
@@ -121,6 +125,9 @@ export class SkillExporter {
|
|
|
121
125
|
* 复合模式导出:将多个包聚合为一个统一的复合技能目录。
|
|
122
126
|
*/
|
|
123
127
|
async exportComposite(options) {
|
|
128
|
+
if (options.skillMdPath && options.customMdPath) {
|
|
129
|
+
throw new BuilderError("Options 'skillMdPath' and 'customMdPath' cannot be used together. Specify 'skillMdPath' to reuse an existing static document, or 'customMdPath' to customize template generation with custom slots.", "INVALID_EXPORT_OPTIONS");
|
|
130
|
+
}
|
|
124
131
|
return exportCompositeImpl(options, (opts) => this.export(opts));
|
|
125
132
|
}
|
|
126
133
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -8,4 +8,6 @@ export { packProject } from "./pack.js";
|
|
|
8
8
|
export { exportCompositeSkill, exportSkill, SkillExporter, } from "./exporter.js";
|
|
9
9
|
export { allocatePackageDirName } from "./manifest.js";
|
|
10
10
|
export { SelectionPlanner } from "./planner.js";
|
|
11
|
+
export { COMPOSITE_CUSTOM_DECLARATION_FILE, COMPOSITE_CUSTOM_SLOTS, SKILL_CUSTOM_DECLARATION_FILE, SKILL_CUSTOM_SLOTS, parseCustomSections, parseCustomSkillDeclaration, } from "./skill/index.js";
|
|
12
|
+
export type { CompositeCustomDeclaration, CompositeCustomSection, CompositeCustomSlot, SkillCustomDeclaration, SkillCustomSection, SkillCustomSlot, } from "./skill/index.js";
|
|
11
13
|
export type { ArchiveFormat, BuildOptions, BuildPlan, BuildProjectWithPlanOptions, BuildResult, CompositeSkillExportOptions, CompositeSkillExportResult, ExportSkillOptions, ExportSkillResult, PackOptions, PackResult, SelectionPlan, SelectionPlannerOptions, SkillExporterOptions, SkillExportResult, } from "./types.js";
|
package/dist/index.js
CHANGED
|
@@ -11,3 +11,5 @@ export { exportCompositeSkill, exportSkill, SkillExporter, } from "./exporter.js
|
|
|
11
11
|
export { allocatePackageDirName } from "./manifest.js";
|
|
12
12
|
// 构建规划器
|
|
13
13
|
export { SelectionPlanner } from "./planner.js";
|
|
14
|
+
// 技能说明书自定义契约与解析
|
|
15
|
+
export { COMPOSITE_CUSTOM_DECLARATION_FILE, COMPOSITE_CUSTOM_SLOTS, SKILL_CUSTOM_DECLARATION_FILE, SKILL_CUSTOM_SLOTS, parseCustomSections, parseCustomSkillDeclaration, } from "./skill/index.js";
|
|
@@ -1,20 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* 自定义技能说明书(SKILL.custom.md)的槽位,
|
|
3
3
|
* 决定自定义段落插入到官方模板生成结果中的位置。
|
|
4
|
+
* 单包导出与复合套件导出共用同一套槽位体系。
|
|
4
5
|
*/
|
|
5
6
|
export type CompositeCustomSlot = "intro" | "after-init" | "after-describe" | "after-actions" | "after-playbooks" | "after-invoke" | "append";
|
|
7
|
+
export type SkillCustomSlot = CompositeCustomSlot;
|
|
6
8
|
export declare const COMPOSITE_CUSTOM_SLOTS: readonly CompositeCustomSlot[];
|
|
7
|
-
|
|
9
|
+
export declare const SKILL_CUSTOM_SLOTS: readonly CompositeCustomSlot[];
|
|
10
|
+
/** 约定俗成的自定义技能说明书文件名(单包与复合套件通用)。 */
|
|
8
11
|
export declare const COMPOSITE_CUSTOM_DECLARATION_FILE = "SKILL.custom.md";
|
|
12
|
+
export declare const SKILL_CUSTOM_DECLARATION_FILE = "SKILL.custom.md";
|
|
9
13
|
export interface CompositeCustomSection {
|
|
10
14
|
slot: CompositeCustomSlot;
|
|
11
15
|
content: string;
|
|
12
16
|
}
|
|
17
|
+
export type SkillCustomSection = CompositeCustomSection;
|
|
13
18
|
export interface CompositeCustomDeclaration {
|
|
14
19
|
/** 自定义说明书 frontmatter 中声明的 description 覆盖值 */
|
|
15
20
|
description?: string;
|
|
16
21
|
sections: CompositeCustomSection[];
|
|
17
22
|
}
|
|
23
|
+
export type SkillCustomDeclaration = CompositeCustomDeclaration;
|
|
18
24
|
export declare const CUSTOM_SLOT_MARKER_PATTERN: RegExp;
|
|
19
25
|
/**
|
|
20
26
|
* 解析自定义说明书正文:以 `<!-- actiondock:slot <name> -->` 标记行分段。
|
|
@@ -8,8 +8,10 @@ export const COMPOSITE_CUSTOM_SLOTS = [
|
|
|
8
8
|
"after-invoke",
|
|
9
9
|
"append",
|
|
10
10
|
];
|
|
11
|
-
|
|
11
|
+
export const SKILL_CUSTOM_SLOTS = COMPOSITE_CUSTOM_SLOTS;
|
|
12
|
+
/** 约定俗成的自定义技能说明书文件名(单包与复合套件通用)。 */
|
|
12
13
|
export const COMPOSITE_CUSTOM_DECLARATION_FILE = "SKILL.custom.md";
|
|
14
|
+
export const SKILL_CUSTOM_DECLARATION_FILE = COMPOSITE_CUSTOM_DECLARATION_FILE;
|
|
13
15
|
export const CUSTOM_SLOT_MARKER_PATTERN = /^\s*<!--\s*actiondock:slot\s+([a-zA-Z][a-zA-Z0-9-]*)\s*-->\s*$/;
|
|
14
16
|
/**
|
|
15
17
|
* 解析自定义说明书正文:以 `<!-- actiondock:slot <name> -->` 标记行分段。
|
|
@@ -33,8 +33,14 @@ export declare function renderRuntimeReferenceContent(options: {
|
|
|
33
33
|
}): string;
|
|
34
34
|
/** 运行时参考文件的导出目录内相对路径(单一事实源) */
|
|
35
35
|
export declare const RUNTIME_REFERENCE_REL_PATH = "references/actiondock-runtime.md";
|
|
36
|
-
export declare function generateSourceSkillMd(config: ProjectConfig, actions: SkillActionItem[], playbooks: SkillPlaybookItem[]
|
|
37
|
-
|
|
36
|
+
export declare function generateSourceSkillMd(config: ProjectConfig, actions: SkillActionItem[], playbooks: SkillPlaybookItem[], options?: {
|
|
37
|
+
customSections?: CompositeCustomSection[];
|
|
38
|
+
description?: string;
|
|
39
|
+
}): string;
|
|
40
|
+
export declare function generateStandaloneSkillMd(config: ProjectConfig, actions: SkillActionItem[], playbooks: SkillPlaybookItem[], binaryRelPath?: string, options?: {
|
|
41
|
+
customSections?: CompositeCustomSection[];
|
|
42
|
+
description?: string;
|
|
43
|
+
}): string;
|
|
38
44
|
export interface CompositeSkillPackageInfo {
|
|
39
45
|
config: ProjectConfig;
|
|
40
46
|
actions: Array<{
|
package/dist/skill/templates.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { basename } from "node:path";
|
|
2
|
-
function getCleanSkillMetadata(config) {
|
|
2
|
+
function getCleanSkillMetadata(config, descriptionOverride) {
|
|
3
3
|
const cleanName = config.id.replace(/[^a-zA-Z0-9-_]/g, "-").toLowerCase();
|
|
4
|
-
const desc = config.description || `AI Agent skill for ${config.name} (${config.id})`;
|
|
4
|
+
const desc = descriptionOverride || config.description || `AI Agent skill for ${config.name} (${config.id})`;
|
|
5
5
|
return { cleanName, desc };
|
|
6
6
|
}
|
|
7
7
|
/**
|
|
@@ -202,52 +202,53 @@ function renderTroubleshootingSection(referenceRelPath) {
|
|
|
202
202
|
}
|
|
203
203
|
/** 运行时参考文件的导出目录内相对路径(单一事实源) */
|
|
204
204
|
export const RUNTIME_REFERENCE_REL_PATH = "references/actiondock-runtime.md";
|
|
205
|
-
export function generateSourceSkillMd(config, actions, playbooks) {
|
|
206
|
-
const { cleanName, desc } = getCleanSkillMetadata(config);
|
|
205
|
+
export function generateSourceSkillMd(config, actions, playbooks, options) {
|
|
206
|
+
const { cleanName, desc } = getCleanSkillMetadata(config, options?.description);
|
|
207
207
|
const pkgId = config.id;
|
|
208
208
|
const firstAction = actions[0]?.id || "sample.greet";
|
|
209
209
|
const playbookSection = renderPlaybookSectionMarkdown(playbooks, config.playbooksDir || "playbooks");
|
|
210
210
|
const actionListMd = renderActionListMarkdown(actions, { packageId: pkgId });
|
|
211
|
-
|
|
211
|
+
const sIntro = `---
|
|
212
212
|
name: ${cleanName}
|
|
213
213
|
description: ${desc}
|
|
214
214
|
---
|
|
215
215
|
|
|
216
216
|
# ${config.name} (${config.id})
|
|
217
217
|
|
|
218
|
-
${desc}
|
|
219
|
-
|
|
220
|
-
## ActionDock 运行时
|
|
218
|
+
${desc}`;
|
|
219
|
+
const sInit = `## ActionDock 运行时
|
|
221
220
|
|
|
222
|
-
本技能为
|
|
221
|
+
本技能为 ActionDock 源码型技能包。智能体可直接通过宿主环境中已安装的 ActionDock 命令行工具 \`ad\` 执行其中的 Action。
|
|
223
222
|
|
|
224
|
-
###
|
|
223
|
+
### 安装依赖与注册链接
|
|
225
224
|
|
|
226
|
-
|
|
225
|
+
本技能面向全局挂载使用。在初次调用或初始化时,将包含本 \`SKILL.md\` 的目录解析为 \`<skill_root>\`。标准流程为先安装生产依赖,再执行注册链接,之后可在任意工作目录通过完全限定 ID 全局调用:
|
|
227
226
|
|
|
228
227
|
\`\`\`bash
|
|
228
|
+
# 安装生产依赖
|
|
229
|
+
cd "<skill_root>" && npm install --omit=dev
|
|
230
|
+
|
|
231
|
+
# 注册并链接到 ActionDock
|
|
229
232
|
ad link "<skill_root>"
|
|
230
233
|
\`\`\`
|
|
231
234
|
|
|
232
|
-
> \`ad link\` 天然具备幂等性,同一 Package
|
|
233
|
-
|
|
234
|
-
### 动作参数契约按需调阅
|
|
235
|
+
> \`ad link\` 天然具备幂等性,同一 Package 多次执行会直接更新路径,可安全重复调用。若后续依赖发生变更,可重新执行上述安装依赖与链接命令更新环境。`;
|
|
236
|
+
const sDescribe = `### 动作参数契约按需调阅
|
|
235
237
|
|
|
236
238
|
在调用未知参数的 Action 前,可在终端执行命令查阅该 Action 的输入输出模式与详细说明:
|
|
237
239
|
|
|
238
240
|
\`\`\`bash
|
|
239
241
|
ad describe ${pkgId}/${firstAction}
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
### 执行 Action
|
|
242
|
+
\`\`\``;
|
|
243
|
+
const sInvoke = `### 执行 Action
|
|
243
244
|
|
|
244
245
|
为避免多技能之间的 Action ID 命名冲突,建议统一使用带有 Package 前缀的完全限定 ID。
|
|
245
246
|
|
|
246
247
|
${renderInvocationGuidance(`ad describe ${pkgId}/${firstAction}`, `ad run ${pkgId}/${firstAction}`)}
|
|
247
248
|
|
|
248
|
-
${renderJsonEnvelopeSection("envelope")}
|
|
249
|
-
|
|
250
|
-
|
|
249
|
+
${renderJsonEnvelopeSection("envelope")}`;
|
|
250
|
+
const sPlaybooks = playbookSection.trim();
|
|
251
|
+
const sActions = `---
|
|
251
252
|
|
|
252
253
|
## Action 目录
|
|
253
254
|
|
|
@@ -267,41 +268,54 @@ ad config set KEY VALUE --package ${pkgId}
|
|
|
267
268
|
# 查看与检索状态数据
|
|
268
269
|
ad state list --package ${pkgId}
|
|
269
270
|
ad state get KEY --package ${pkgId}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
271
|
+
\`\`\``;
|
|
272
|
+
const sTroubleshooting = renderTroubleshootingSection(RUNTIME_REFERENCE_REL_PATH);
|
|
273
|
+
const parts = [
|
|
274
|
+
{ slot: "intro", text: sIntro },
|
|
275
|
+
{ slot: "after-init", text: sInit },
|
|
276
|
+
{ slot: "after-describe", text: sDescribe },
|
|
277
|
+
{ slot: "after-invoke", text: sInvoke },
|
|
278
|
+
{ slot: "after-playbooks", text: sPlaybooks },
|
|
279
|
+
{ slot: "after-actions", text: sActions },
|
|
280
|
+
{ slot: "append", text: sTroubleshooting },
|
|
281
|
+
];
|
|
282
|
+
const customSections = options?.customSections ?? [];
|
|
283
|
+
for (const section of [...customSections].reverse()) {
|
|
284
|
+
const anchorIndex = parts.findIndex((p) => p.slot === section.slot);
|
|
285
|
+
parts.splice(anchorIndex + 1, 0, { slot: section.slot, text: section.content });
|
|
286
|
+
}
|
|
287
|
+
return (parts
|
|
288
|
+
.filter((p) => p.text.trim().length > 0)
|
|
289
|
+
.map((p) => p.text.trim())
|
|
290
|
+
.join("\n\n") + "\n");
|
|
274
291
|
}
|
|
275
|
-
export function generateStandaloneSkillMd(config, actions, playbooks, binaryRelPath = "./bin/action-bin") {
|
|
276
|
-
const { cleanName, desc } = getCleanSkillMetadata(config);
|
|
292
|
+
export function generateStandaloneSkillMd(config, actions, playbooks, binaryRelPath = "./bin/action-bin", options) {
|
|
293
|
+
const { cleanName, desc } = getCleanSkillMetadata(config, options?.description);
|
|
277
294
|
const firstAction = actions[0]?.id || "sample.greet";
|
|
278
295
|
const playbookSection = renderPlaybookSectionMarkdown(playbooks, config.playbooksDir || "playbooks");
|
|
279
296
|
const actionListMd = renderActionListMarkdown(actions);
|
|
280
|
-
|
|
297
|
+
const sIntro = `---
|
|
281
298
|
name: ${cleanName}
|
|
282
299
|
description: ${desc}
|
|
283
300
|
---
|
|
284
301
|
|
|
285
302
|
# ${config.name} (${config.id})
|
|
286
303
|
|
|
287
|
-
${desc}
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
### 动作参数契约按需调阅
|
|
304
|
+
${desc}`;
|
|
305
|
+
const sDescribe = `### 动作参数契约按需调阅
|
|
291
306
|
|
|
292
307
|
在调用未知参数的 Action 前,可在终端执行命令查阅该 Action 的输入输出模式与详细说明:
|
|
293
308
|
|
|
294
309
|
\`\`\`bash
|
|
295
310
|
${binaryRelPath} describe ${firstAction}
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
### 执行 Action
|
|
311
|
+
\`\`\``;
|
|
312
|
+
const sInvoke = `### 执行 Action
|
|
299
313
|
|
|
300
314
|
${renderInvocationGuidance(`${binaryRelPath} describe ${firstAction}`, `${binaryRelPath} run ${firstAction}`)}
|
|
301
315
|
|
|
302
|
-
${renderJsonEnvelopeSection("result")}
|
|
303
|
-
|
|
304
|
-
|
|
316
|
+
${renderJsonEnvelopeSection("result")}`;
|
|
317
|
+
const sPlaybooks = playbookSection.trim();
|
|
318
|
+
const sActions = `---
|
|
305
319
|
|
|
306
320
|
## Action 目录
|
|
307
321
|
|
|
@@ -321,9 +335,8 @@ ${binaryRelPath} config set KEY VALUE
|
|
|
321
335
|
# 查看与检索状态数据
|
|
322
336
|
${binaryRelPath} state list
|
|
323
337
|
${binaryRelPath} state get KEY
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
---
|
|
338
|
+
\`\`\``;
|
|
339
|
+
const sTroubleshooting = `---
|
|
327
340
|
|
|
328
341
|
## 故障排查与依赖自愈指引(按需查阅)
|
|
329
342
|
|
|
@@ -334,8 +347,25 @@ ${binaryRelPath} state get KEY
|
|
|
334
347
|
npm install --omit=dev
|
|
335
348
|
\`\`\`
|
|
336
349
|
|
|
337
|
-
完整环境安装与自愈指引按需查阅:[${RUNTIME_REFERENCE_REL_PATH}](${RUNTIME_REFERENCE_REL_PATH})
|
|
338
|
-
|
|
350
|
+
完整环境安装与自愈指引按需查阅:[${RUNTIME_REFERENCE_REL_PATH}](${RUNTIME_REFERENCE_REL_PATH})`;
|
|
351
|
+
const parts = [
|
|
352
|
+
{ slot: "intro", text: sIntro },
|
|
353
|
+
{ slot: "after-init", text: "" },
|
|
354
|
+
{ slot: "after-describe", text: sDescribe },
|
|
355
|
+
{ slot: "after-invoke", text: sInvoke },
|
|
356
|
+
{ slot: "after-playbooks", text: sPlaybooks },
|
|
357
|
+
{ slot: "after-actions", text: sActions },
|
|
358
|
+
{ slot: "append", text: sTroubleshooting },
|
|
359
|
+
];
|
|
360
|
+
const customSections = options?.customSections ?? [];
|
|
361
|
+
for (const section of [...customSections].reverse()) {
|
|
362
|
+
const anchorIndex = parts.findIndex((p) => p.slot === section.slot);
|
|
363
|
+
parts.splice(anchorIndex + 1, 0, { slot: section.slot, text: section.content });
|
|
364
|
+
}
|
|
365
|
+
return (parts
|
|
366
|
+
.filter((p) => p.text.trim().length > 0)
|
|
367
|
+
.map((p) => p.text.trim())
|
|
368
|
+
.join("\n\n") + "\n");
|
|
339
369
|
}
|
|
340
370
|
/**
|
|
341
371
|
* 生成多包聚合的复合模式 SKILL.md 文档。
|
|
@@ -375,6 +405,23 @@ description: ${description}
|
|
|
375
405
|
# ${bundleName} 复合技能套件
|
|
376
406
|
|
|
377
407
|
${description}`;
|
|
408
|
+
const sInit = `## ActionDock 运行时
|
|
409
|
+
|
|
410
|
+
本技能为 ActionDock 复合技能套件,聚合了多个功能包。智能体可直接通过宿主环境中已安装的 ActionDock 命令行工具 \`ad\` 执行其中的 Action。
|
|
411
|
+
|
|
412
|
+
### 安装依赖与注册链接
|
|
413
|
+
|
|
414
|
+
本技能面向全局挂载使用。在初次调用或初始化时,将包含本 \`SKILL.md\` 的目录解析为 \`<skill_root>\`。标准流程为先安装复合套件聚合生产依赖,再执行注册链接,之后可在任意工作目录通过完全限定 ID 全局调用:
|
|
415
|
+
|
|
416
|
+
\`\`\`bash
|
|
417
|
+
# 安装复合套件聚合依赖
|
|
418
|
+
cd "<skill_root>" && npm install --omit=dev
|
|
419
|
+
|
|
420
|
+
# 注册并链接工作区子包到 ActionDock
|
|
421
|
+
ad link "<skill_root>"
|
|
422
|
+
\`\`\`
|
|
423
|
+
|
|
424
|
+
> \`ad link\` 会自动识别并注册工作区下的所有子包,使其中的 Action 随时可以通过完全限定标识调用。\`ad link\` 天然具备幂等性,可安全重复调用。若后续依赖发生变更,可重新执行上述安装依赖与链接命令更新环境。`;
|
|
378
425
|
const sDescribe = `## 动作参数契约按需调阅
|
|
379
426
|
|
|
380
427
|
为节省上下文开销,各 Action 的详细参数结构不静态内嵌在说明书中。在调用未知参数的 Action 前,可在终端执行命令查阅输入输出约束:
|
|
@@ -404,12 +451,12 @@ ${renderJsonEnvelopeSection("envelope", { withDescriptions: false })}`;
|
|
|
404
451
|
const sTroubleshooting = renderTroubleshootingSection(RUNTIME_REFERENCE_REL_PATH);
|
|
405
452
|
const parts = [
|
|
406
453
|
{ slot: "intro", text: sIntro },
|
|
454
|
+
{ slot: "after-init", text: sInit },
|
|
407
455
|
{ slot: "after-describe", text: sDescribe },
|
|
408
456
|
{ slot: "after-actions", text: sActions },
|
|
409
457
|
{ slot: "after-playbooks", text: sPlaybooks },
|
|
410
458
|
{ slot: "after-invoke", text: sInvoke },
|
|
411
|
-
{ slot: "
|
|
412
|
-
{ slot: "append", text: "" },
|
|
459
|
+
{ slot: "append", text: sTroubleshooting },
|
|
413
460
|
];
|
|
414
461
|
// 自定义段落按文件顺序插入到对应槽位(倒序插入保证同槽位多段保持先后)
|
|
415
462
|
const customSections = options?.customSections ?? [];
|
package/dist/skill-md.d.ts
CHANGED
|
@@ -16,10 +16,15 @@ export declare function findExistingSingleSkillMd(projectRoot: string, explicitP
|
|
|
16
16
|
*/
|
|
17
17
|
export declare function findExistingCompositeSkillMd(options: CompositeSkillExportOptions): string | undefined;
|
|
18
18
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
19
|
+
* 解析技能自定义说明书:显式 customMdPath 优先(缺失即报错),
|
|
20
|
+
* 否则单包导出按项目根目录,复合导出按工作区根目录与当前目录自动发现 `SKILL.custom.md`。
|
|
21
21
|
*/
|
|
22
|
-
export declare function resolveCustomSkillDeclaration(options:
|
|
22
|
+
export declare function resolveCustomSkillDeclaration(options: {
|
|
23
|
+
projectRoot?: string;
|
|
24
|
+
customMdPath?: string;
|
|
25
|
+
workspaceRoot?: string;
|
|
26
|
+
projectRoots?: string[];
|
|
27
|
+
}): (CompositeCustomDeclaration & {
|
|
23
28
|
file: string;
|
|
24
29
|
}) | undefined;
|
|
25
30
|
/**
|
|
@@ -30,6 +35,7 @@ export declare function writeSkillMd(root: string, destDir: string, options: {
|
|
|
30
35
|
skipSkillMd?: boolean;
|
|
31
36
|
skillMdPath?: string;
|
|
32
37
|
pkgSlug: string;
|
|
38
|
+
hasCustomDeclaration?: boolean;
|
|
33
39
|
}, generate: () => string): string | undefined;
|
|
34
40
|
/**
|
|
35
41
|
* 构造模板生成所需的 ProjectConfig 视图。
|
package/dist/skill-md.js
CHANGED
|
@@ -13,7 +13,10 @@ import { BuilderError } from "./errors.js";
|
|
|
13
13
|
* 检索单个 Action 项目目录中已存在的 SKILL.md 文件。
|
|
14
14
|
*/
|
|
15
15
|
export function findExistingSingleSkillMd(projectRoot, explicitPath, pkgSlug) {
|
|
16
|
-
if (explicitPath
|
|
16
|
+
if (explicitPath) {
|
|
17
|
+
if (!existsSync(explicitPath)) {
|
|
18
|
+
throw new BuilderError(`Skill document file not found: '${explicitPath}'`);
|
|
19
|
+
}
|
|
17
20
|
try {
|
|
18
21
|
if (statSync(explicitPath).isFile())
|
|
19
22
|
return resolve(explicitPath);
|
|
@@ -21,6 +24,7 @@ export function findExistingSingleSkillMd(projectRoot, explicitPath, pkgSlug) {
|
|
|
21
24
|
catch {
|
|
22
25
|
// 忽略文件属性读取异常
|
|
23
26
|
}
|
|
27
|
+
throw new BuilderError(`Skill document path is not a regular file: '${explicitPath}'`);
|
|
24
28
|
}
|
|
25
29
|
const candidates = [
|
|
26
30
|
join(projectRoot, "SKILL.md"),
|
|
@@ -48,7 +52,10 @@ export function findExistingSingleSkillMd(projectRoot, explicitPath, pkgSlug) {
|
|
|
48
52
|
* 检索复合套件工作区中已存在的 SKILL.md 文件。
|
|
49
53
|
*/
|
|
50
54
|
export function findExistingCompositeSkillMd(options) {
|
|
51
|
-
if (options.skillMdPath
|
|
55
|
+
if (options.skillMdPath) {
|
|
56
|
+
if (!existsSync(options.skillMdPath)) {
|
|
57
|
+
throw new BuilderError(`Skill document file not found: '${options.skillMdPath}'`);
|
|
58
|
+
}
|
|
52
59
|
try {
|
|
53
60
|
if (statSync(options.skillMdPath).isFile())
|
|
54
61
|
return resolve(options.skillMdPath);
|
|
@@ -56,6 +63,7 @@ export function findExistingCompositeSkillMd(options) {
|
|
|
56
63
|
catch {
|
|
57
64
|
// 忽略文件属性读取异常
|
|
58
65
|
}
|
|
66
|
+
throw new BuilderError(`Skill document path is not a regular file: '${options.skillMdPath}'`);
|
|
59
67
|
}
|
|
60
68
|
const bundleSlug = getPackageSlug(options.bundleName);
|
|
61
69
|
const searchDirs = new Set();
|
|
@@ -95,8 +103,8 @@ export function findExistingCompositeSkillMd(options) {
|
|
|
95
103
|
return undefined;
|
|
96
104
|
}
|
|
97
105
|
/**
|
|
98
|
-
*
|
|
99
|
-
*
|
|
106
|
+
* 解析技能自定义说明书:显式 customMdPath 优先(缺失即报错),
|
|
107
|
+
* 否则单包导出按项目根目录,复合导出按工作区根目录与当前目录自动发现 `SKILL.custom.md`。
|
|
100
108
|
*/
|
|
101
109
|
export function resolveCustomSkillDeclaration(options) {
|
|
102
110
|
let filePath;
|
|
@@ -106,14 +114,52 @@ export function resolveCustomSkillDeclaration(options) {
|
|
|
106
114
|
}
|
|
107
115
|
filePath = resolve(options.customMdPath);
|
|
108
116
|
}
|
|
117
|
+
else if (options.projectRoot) {
|
|
118
|
+
const root = resolve(options.projectRoot);
|
|
119
|
+
const candidates = [
|
|
120
|
+
join(root, COMPOSITE_CUSTOM_DECLARATION_FILE),
|
|
121
|
+
join(root, "skill.custom.md"),
|
|
122
|
+
join(root, "skills", COMPOSITE_CUSTOM_DECLARATION_FILE),
|
|
123
|
+
join(root, "skills", "skill.custom.md"),
|
|
124
|
+
];
|
|
125
|
+
for (const candidate of candidates) {
|
|
126
|
+
if (existsSync(candidate)) {
|
|
127
|
+
try {
|
|
128
|
+
if (statSync(candidate).isFile()) {
|
|
129
|
+
filePath = candidate;
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
// 忽略文件属性读取异常
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
109
139
|
else {
|
|
110
140
|
const searchDirs = [options.workspaceRoot, process.cwd()].filter(Boolean);
|
|
111
141
|
for (const dir of searchDirs) {
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
142
|
+
const candidates = [
|
|
143
|
+
join(resolve(dir), COMPOSITE_CUSTOM_DECLARATION_FILE),
|
|
144
|
+
join(resolve(dir), "skill.custom.md"),
|
|
145
|
+
join(resolve(dir), "skills", COMPOSITE_CUSTOM_DECLARATION_FILE),
|
|
146
|
+
join(resolve(dir), "skills", "skill.custom.md"),
|
|
147
|
+
];
|
|
148
|
+
for (const candidate of candidates) {
|
|
149
|
+
if (existsSync(candidate)) {
|
|
150
|
+
try {
|
|
151
|
+
if (statSync(candidate).isFile()) {
|
|
152
|
+
filePath = candidate;
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
// 忽略文件属性读取异常
|
|
158
|
+
}
|
|
159
|
+
}
|
|
116
160
|
}
|
|
161
|
+
if (filePath)
|
|
162
|
+
break;
|
|
117
163
|
}
|
|
118
164
|
}
|
|
119
165
|
if (!filePath) {
|
|
@@ -129,9 +175,11 @@ export function resolveCustomSkillDeclaration(options) {
|
|
|
129
175
|
* 返回实际复用的已有 SKILL.md 路径(若发生复用)。
|
|
130
176
|
*/
|
|
131
177
|
export function writeSkillMd(root, destDir, options, generate) {
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
|
|
178
|
+
const shouldCheckExisting = !options.skipSkillMd &&
|
|
179
|
+
(Boolean(options.skillMdPath) || !options.hasCustomDeclaration);
|
|
180
|
+
const existingSkill = shouldCheckExisting
|
|
181
|
+
? findExistingSingleSkillMd(root, options.skillMdPath, options.pkgSlug)
|
|
182
|
+
: undefined;
|
|
135
183
|
if (existingSkill) {
|
|
136
184
|
const destSkillMd = join(destDir, "SKILL.md");
|
|
137
185
|
if (resolve(existingSkill) !== resolve(destSkillMd)) {
|
package/dist/types.d.ts
CHANGED
|
@@ -308,6 +308,10 @@ export interface SkillExporterOptions {
|
|
|
308
308
|
projectRoot: string;
|
|
309
309
|
/** 导出模式:source 源码型 Skill 或 node 目录型 Skill(默认 source) */
|
|
310
310
|
mode?: "source" | "node";
|
|
311
|
+
/** 独立自包含模式(若为 true 则将导出模式设为 node 目录型) */
|
|
312
|
+
standalone?: boolean;
|
|
313
|
+
/** 是否将跨包依赖物理物化为微型工作区复合结构(默认 false) */
|
|
314
|
+
bundleDeps?: boolean;
|
|
311
315
|
/** 导出产物目标目录(默认输出至 dist 目录) */
|
|
312
316
|
outDir?: string;
|
|
313
317
|
/** 是否执行归档压缩,亦可直接指定归档格式 */
|
|
@@ -336,7 +340,7 @@ export interface SkillExporterOptions {
|
|
|
336
340
|
skipDependencyValidation?: boolean;
|
|
337
341
|
/** 内部标识:是否作为复合套件子包导出(避免闭包再次触发嵌套 mini-workspace) */
|
|
338
342
|
_isSubpackage?: boolean;
|
|
339
|
-
/**
|
|
343
|
+
/** 自定义技能说明书(SKILL.custom.md)文件路径;缺省时自动在项目或工作区根目录下发现同名文件 */
|
|
340
344
|
customMdPath?: string;
|
|
341
345
|
/** 所属 Workspace 根目录(可选) */
|
|
342
346
|
workspaceRoot?: string;
|
|
@@ -386,6 +390,10 @@ export interface CompositeSkillExportOptions {
|
|
|
386
390
|
projectRoots: string[];
|
|
387
391
|
/** 复合套件输出目标目录(默认输出至 dist 目录) */
|
|
388
392
|
outDir?: string;
|
|
393
|
+
/** 是否将外部依赖物理物化进复合产物(默认 false) */
|
|
394
|
+
bundleDeps?: boolean;
|
|
395
|
+
/** 独立自包含模式(复合导出暂不支持) */
|
|
396
|
+
standalone?: boolean;
|
|
389
397
|
/** 复合技能描述信息 */
|
|
390
398
|
description?: string;
|
|
391
399
|
/** 是否执行归档压缩,亦可直接指定归档格式 */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@actiondock/builder",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.18.0",
|
|
4
4
|
"description": "ActionDock Build Planner, distribution packaging, and Skill exporter",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"test": "node ../../scripts/run-tests.ts"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@actiondock/core": "^2.
|
|
33
|
-
"@actiondock/sdk": "^2.
|
|
32
|
+
"@actiondock/core": "^2.18.0",
|
|
33
|
+
"@actiondock/sdk": "^2.18.0"
|
|
34
34
|
},
|
|
35
35
|
"keywords": [
|
|
36
36
|
"actiondock",
|