@actiondock/cli 2.0.12 → 2.2.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 +41 -34
- package/bin/ad.js +28 -41
- package/dist/commands/action/create.d.ts +9 -1
- package/dist/commands/action/create.js +120 -0
- package/dist/commands/add.d.ts +7 -0
- package/dist/commands/add.js +144 -0
- package/dist/commands/build.d.ts +2 -1
- package/dist/commands/build.js +83 -0
- package/dist/commands/config/delete.d.ts +9 -0
- package/dist/commands/config/delete.js +52 -0
- package/dist/commands/config/env.d.ts +9 -0
- package/dist/commands/config/env.js +85 -0
- package/dist/commands/config/get.d.ts +9 -0
- package/dist/commands/config/get.js +120 -0
- package/dist/commands/config/index.d.ts +9 -0
- package/dist/commands/config/index.js +23 -0
- package/dist/commands/config/list.d.ts +9 -0
- package/dist/commands/config/list.js +137 -0
- package/dist/commands/config/schema.d.ts +9 -0
- package/dist/commands/config/schema.js +121 -0
- package/dist/commands/config/set.d.ts +9 -0
- package/dist/commands/config/set.js +85 -0
- package/dist/commands/describe.d.ts +9 -0
- package/dist/commands/describe.js +68 -0
- package/dist/commands/doctor.d.ts +2 -1
- package/dist/commands/doctor.js +82 -0
- package/dist/commands/export.d.ts +2 -1
- package/dist/commands/export.js +212 -0
- package/dist/commands/generate.d.ts +9 -0
- package/dist/commands/generate.js +44 -0
- package/dist/commands/index.d.ts +31 -1
- package/dist/commands/index.js +111 -0
- package/dist/commands/info.d.ts +9 -2
- package/dist/commands/info.js +210 -0
- package/dist/commands/init.js +24 -0
- package/dist/commands/link.js +71 -0
- package/dist/commands/list.d.ts +9 -0
- package/dist/commands/list.js +77 -0
- package/dist/commands/mcp.d.ts +9 -2
- package/dist/commands/mcp.js +172 -0
- package/dist/commands/new.d.ts +9 -0
- package/dist/commands/new.js +33 -0
- package/dist/commands/pack.d.ts +3 -0
- package/dist/commands/pack.js +63 -0
- package/dist/commands/playbook.d.ts +7 -3
- package/dist/commands/playbook.js +433 -0
- package/dist/commands/profile.js +253 -0
- package/dist/commands/remove.d.ts +7 -0
- package/dist/commands/remove.js +118 -0
- package/dist/commands/run.d.ts +13 -0
- package/dist/commands/run.js +146 -0
- package/dist/commands/runs.d.ts +9 -2
- package/dist/commands/runs.js +245 -0
- package/dist/commands/serve.d.ts +9 -2
- package/dist/commands/serve.js +129 -0
- package/dist/commands/state-list.d.ts +24 -0
- package/dist/commands/state-list.js +82 -0
- package/dist/commands/state.d.ts +9 -2
- package/dist/commands/state.js +310 -0
- package/dist/commands/test.js +44 -0
- package/dist/commands/validate.d.ts +9 -0
- package/dist/commands/validate.js +106 -0
- package/dist/errors.d.ts +43 -0
- package/dist/errors.js +103 -0
- package/dist/index.d.ts +8 -1
- package/dist/index.js +41 -1000
- package/dist/prompt.d.ts +53 -0
- package/dist/prompt.js +192 -0
- package/dist/renderer.d.ts +197 -0
- package/dist/renderer.js +502 -0
- package/dist/services/index.d.ts +1 -0
- package/dist/services/index.js +1 -0
- package/dist/services/inspect.d.ts +23 -0
- package/dist/services/inspect.js +96 -0
- package/dist/standalone/index.d.ts +16 -0
- package/dist/standalone/index.js +22 -0
- package/dist/types.d.ts +132 -0
- package/dist/types.js +9 -0
- package/dist/utils/bytes.d.ts +1 -1
- package/dist/utils/bytes.js +1 -0
- package/dist/utils/duration.js +1 -0
- package/dist/utils/filter.d.ts +1 -1
- package/dist/utils/filter.js +1 -0
- package/dist/utils/index.d.ts +6 -0
- package/dist/utils/index.js +6 -0
- package/dist/utils/spawn.d.ts +27 -0
- package/dist/utils/spawn.js +35 -0
- package/dist/utils/target.d.ts +45 -0
- package/dist/utils/target.js +78 -0
- package/dist/utils/utils.d.ts +38 -0
- package/dist/utils/utils.js +111 -0
- package/package.json +10 -12
- package/dist/commands/action/index.d.ts +0 -16
- package/dist/commands/action/list.d.ts +0 -5
- package/dist/commands/action/run.d.ts +0 -4
- package/dist/commands/action/show.d.ts +0 -5
- package/dist/commands/action/sync.d.ts +0 -2
- package/dist/commands/action/validate.d.ts +0 -5
- package/dist/commands/action.d.ts +0 -1
- package/dist/commands/config.d.ts +0 -2
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { isSecretConfigKey, loadProjectConfig, resolvePackageRoot, } from "@actiondock/core";
|
|
2
|
+
import { ArgumentError } from "../../errors.js";
|
|
3
|
+
import { writeStdout } from "../../renderer.js";
|
|
4
|
+
import { getEffectiveOptions, withTarget } from "../../utils/index.js";
|
|
5
|
+
import { resolveConfigValueInput } from "../../prompt.js";
|
|
6
|
+
/**
|
|
7
|
+
* 注册 config set 子命令:写入配置值(支持标准输入与安全提示)。
|
|
8
|
+
*
|
|
9
|
+
* @param configCmd config 命令实例
|
|
10
|
+
* @param context 命令行上下文
|
|
11
|
+
*/
|
|
12
|
+
export function registerConfigSetCommand(configCmd, context) {
|
|
13
|
+
configCmd
|
|
14
|
+
.command("set <key> [value]")
|
|
15
|
+
.description("Set configuration value (supports stdin and secure prompt)")
|
|
16
|
+
.option("-P, --package <id>", "Target package ID or path")
|
|
17
|
+
.option("-g, --global", "Set in global configuration")
|
|
18
|
+
.option("-p, --profile <name>", "Configure on a remote target")
|
|
19
|
+
.option("-s, --server <url>", "Remote server URL")
|
|
20
|
+
.option("-t, --token <token>", "Auth token for remote server")
|
|
21
|
+
.option("--stdin", "Read value from standard input")
|
|
22
|
+
.option("--data-dir <path>", "Custom database storage directory")
|
|
23
|
+
.action(async (key, rawVal, rawOptions, cmd) => {
|
|
24
|
+
const options = getEffectiveOptions(rawOptions, cmd);
|
|
25
|
+
if (!key) {
|
|
26
|
+
throw new ArgumentError("Configuration key is required");
|
|
27
|
+
}
|
|
28
|
+
let root = null;
|
|
29
|
+
let projConfig = null;
|
|
30
|
+
let declaredDef;
|
|
31
|
+
if (!options.global && !options.profile && !options.server) {
|
|
32
|
+
root = resolvePackageRoot(options.package);
|
|
33
|
+
if (root) {
|
|
34
|
+
try {
|
|
35
|
+
projConfig = loadProjectConfig(root);
|
|
36
|
+
declaredDef = projConfig.config?.[key];
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
// 清单损坏时必须让错误可见:静默忽略会导致写入错误的作用域
|
|
40
|
+
throw err;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const isSecret = isSecretConfigKey(key, declaredDef);
|
|
45
|
+
let effectiveValueStr = rawVal;
|
|
46
|
+
if (effectiveValueStr === undefined || options.stdin) {
|
|
47
|
+
effectiveValueStr = await resolveConfigValueInput({
|
|
48
|
+
promptText: `Enter value for '${key}'${isSecret ? " (secret)" : ""}: `,
|
|
49
|
+
secret: isSecret,
|
|
50
|
+
context,
|
|
51
|
+
useStdin: Boolean(options.stdin),
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
let parsedVal = effectiveValueStr;
|
|
55
|
+
try {
|
|
56
|
+
parsedVal = JSON.parse(effectiveValueStr);
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
parsedVal = effectiveValueStr;
|
|
60
|
+
}
|
|
61
|
+
// 目标解析与写入(远端分支直接写远端作用域,本地分支按全局/项目作用域写入)
|
|
62
|
+
await withTarget(options, context, async (target, resolved) => {
|
|
63
|
+
if (resolved.type === "remote") {
|
|
64
|
+
await target.setConfig(options.package || "", key, parsedVal);
|
|
65
|
+
writeStdout(`[OK] Configuration '${key}' updated on remote server`, context);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (options.global) {
|
|
69
|
+
await target.setConfig("global", key, parsedVal);
|
|
70
|
+
writeStdout(`[OK] Global configuration '${key}' updated`, context);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (!root) {
|
|
74
|
+
if (options.package) {
|
|
75
|
+
throw new ArgumentError(`Package '${options.package}' not found in linked packages or path`);
|
|
76
|
+
}
|
|
77
|
+
await target.setConfig("global", key, parsedVal);
|
|
78
|
+
writeStdout(`[OK] Global configuration '${key}' updated (no project in current directory)`, context);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
await target.setConfig(projConfig.id, key, parsedVal);
|
|
82
|
+
writeStdout(`[OK] Configuration '${key}' updated for package '${projConfig.id}'`, context);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import type { CliContext } from "../types.js";
|
|
3
|
+
/**
|
|
4
|
+
* 注册顶层统一 describe 命令:查询指定 Action 的规范结构与模式定义。
|
|
5
|
+
*
|
|
6
|
+
* @param program Commander 根程序对象
|
|
7
|
+
* @param context 命令行上下文
|
|
8
|
+
*/
|
|
9
|
+
export declare function registerDescribeCommand(program: Command, context?: CliContext): void;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { ArgumentError, ExecutionError } from "../errors.js";
|
|
2
|
+
import { renderActionDetail, renderResult } from "../renderer.js";
|
|
3
|
+
import { getEffectiveOptions, resolveLocalPackageRoot, withTarget, } from "../utils/index.js";
|
|
4
|
+
/**
|
|
5
|
+
* 注册顶层统一 describe 命令:查询指定 Action 的规范结构与模式定义。
|
|
6
|
+
*
|
|
7
|
+
* @param program Commander 根程序对象
|
|
8
|
+
* @param context 命令行上下文
|
|
9
|
+
*/
|
|
10
|
+
export function registerDescribeCommand(program, context) {
|
|
11
|
+
program
|
|
12
|
+
.command("describe <id>")
|
|
13
|
+
.alias("show")
|
|
14
|
+
.description("Show action definition, schema, and description")
|
|
15
|
+
.option("-P, --package <id>", "Target package ID or path")
|
|
16
|
+
.option("-p, --profile <name>", "Query against a specific profile")
|
|
17
|
+
.option("-s, --server <url>", "Remote server URL")
|
|
18
|
+
.option("-t, --token <token>", "Auth token for remote server")
|
|
19
|
+
.option("--json", "Output as JSON")
|
|
20
|
+
.option("--envelope", "Wrap JSON output in standard envelope")
|
|
21
|
+
.option("--data-dir <path>", "Custom database storage directory")
|
|
22
|
+
.action(async (id, rawOptions, cmd) => {
|
|
23
|
+
const options = getEffectiveOptions(rawOptions, cmd);
|
|
24
|
+
if (!id) {
|
|
25
|
+
throw new ArgumentError("Action ID is required for describe");
|
|
26
|
+
}
|
|
27
|
+
// 目标拓扑解析(仅 local 分支需要包寻址)
|
|
28
|
+
const targetPackageRoot = resolveLocalPackageRoot(options.package);
|
|
29
|
+
if (options.package && !targetPackageRoot) {
|
|
30
|
+
throw new ArgumentError(`Package '${options.package}' not found in linked packages or path`);
|
|
31
|
+
}
|
|
32
|
+
let targetRef = id;
|
|
33
|
+
if (options.package && !id.includes("/") && !id.includes(":")) {
|
|
34
|
+
targetRef = `${options.package}/${id}`;
|
|
35
|
+
}
|
|
36
|
+
// 通过 Target 门面统一查询 Action 规范
|
|
37
|
+
await withTarget(options, context, async (target) => {
|
|
38
|
+
let spec;
|
|
39
|
+
try {
|
|
40
|
+
spec = await target.describeAction(targetRef);
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
const msg = err?.message || String(err);
|
|
44
|
+
if (msg.includes("not found") || msg.includes("ACTION_NOT_FOUND")) {
|
|
45
|
+
throw new ArgumentError(msg);
|
|
46
|
+
}
|
|
47
|
+
throw new ExecutionError(msg);
|
|
48
|
+
}
|
|
49
|
+
const detail = {
|
|
50
|
+
id: spec.id,
|
|
51
|
+
description: spec.description,
|
|
52
|
+
inputSchema: spec.inputSchema,
|
|
53
|
+
outputSchema: spec.outputSchema,
|
|
54
|
+
tags: spec.tags,
|
|
55
|
+
annotations: spec.annotations,
|
|
56
|
+
uses: spec.uses,
|
|
57
|
+
entry: spec.entry,
|
|
58
|
+
filePath: spec.filePath,
|
|
59
|
+
};
|
|
60
|
+
renderResult(detail, {
|
|
61
|
+
json: options.json,
|
|
62
|
+
envelope: options.envelope,
|
|
63
|
+
humanFormatter: () => renderActionDetail(detail),
|
|
64
|
+
context,
|
|
65
|
+
});
|
|
66
|
+
}, { localRoot: targetPackageRoot || undefined, scanLinkedPackages: true });
|
|
67
|
+
});
|
|
68
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { fetchRemoteDoctor, resolveTarget, runDoctorChecks } from "@actiondock/core";
|
|
2
|
+
import { ExecutionError } from "../errors.js";
|
|
3
|
+
import { renderResult } from "../renderer.js";
|
|
4
|
+
import { getEffectiveOptions } from "../utils/index.js";
|
|
5
|
+
export function registerDoctorCommand(program, context) {
|
|
6
|
+
program
|
|
7
|
+
.command("doctor")
|
|
8
|
+
.description("Check ActionDock environment, registry health, and project diagnostics")
|
|
9
|
+
.option("-P, --package <id|path>", "Target package ID or directory path for project diagnostics")
|
|
10
|
+
.option("-p, --profile <name>", "Query doctor diagnostics on a remote target")
|
|
11
|
+
.option("-s, --server <url>", "Remote server URL")
|
|
12
|
+
.option("-t, --token <token>", "Auth token for remote server")
|
|
13
|
+
.option("--json", "Output diagnostics report in JSON format")
|
|
14
|
+
.option("--envelope", "Wrap JSON output in standard envelope")
|
|
15
|
+
.action(async (rawOptions, cmd) => {
|
|
16
|
+
try {
|
|
17
|
+
const options = getEffectiveOptions(rawOptions, cmd);
|
|
18
|
+
const target = resolveTarget({
|
|
19
|
+
profile: options.profile,
|
|
20
|
+
server: options.server,
|
|
21
|
+
token: options.token,
|
|
22
|
+
}, context?.customHome);
|
|
23
|
+
let report;
|
|
24
|
+
if (target.type === "remote") {
|
|
25
|
+
const remoteRes = await fetchRemoteDoctor(target.serverUrl, target.token, options.package);
|
|
26
|
+
report = remoteRes.report || remoteRes;
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
report = await runDoctorChecks({
|
|
30
|
+
packageIdOrPath: options.package,
|
|
31
|
+
customHome: context?.customHome,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
renderResult(report, {
|
|
35
|
+
json: options.json,
|
|
36
|
+
envelope: options.envelope,
|
|
37
|
+
humanFormatter: () => {
|
|
38
|
+
const lines = [];
|
|
39
|
+
const title = target.type === "remote"
|
|
40
|
+
? `[DOCTOR] Remote ActionDock Server Diagnostics (${target.serverUrl}${target.profileName ? ` - Profile: ${target.profileName}` : ""})\n`
|
|
41
|
+
: "[DOCTOR] ActionDock System & Project Diagnostics\n";
|
|
42
|
+
lines.push(title);
|
|
43
|
+
// 1. Runtime & Environment Group
|
|
44
|
+
lines.push("[Runtime & Environment]");
|
|
45
|
+
const envChecks = (report.checks || []).filter((c) => c.category === "runtime" || c.category === "storage" || c.category === "registry");
|
|
46
|
+
for (const c of envChecks) {
|
|
47
|
+
const tag = c.status === "ok" ? "[OK]" : c.status === "warn" ? "[WARN]" : "[ERROR]";
|
|
48
|
+
lines.push(` ${tag} ${c.name}: ${c.message}`);
|
|
49
|
+
if (c.fix) {
|
|
50
|
+
lines.push(` Fix: ${c.fix}`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// 2. Project Group
|
|
54
|
+
if (report.hasProject) {
|
|
55
|
+
lines.push(`\n[Project: ${report.packageId || "unknown"}] (${report.projectRoot})`);
|
|
56
|
+
const projChecks = (report.checks || []).filter((c) => c.category === "project");
|
|
57
|
+
for (const c of projChecks) {
|
|
58
|
+
const tag = c.status === "ok" ? "[OK]" : c.status === "warn" ? "[WARN]" : "[ERROR]";
|
|
59
|
+
lines.push(` ${tag} ${c.name}: ${c.message}`);
|
|
60
|
+
if (c.fix) {
|
|
61
|
+
lines.push(` Fix: ${c.fix}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
lines.push("\n[Project Context]");
|
|
67
|
+
lines.push(" [INFO] Not inside an ActionDock project directory (skipped project checks)");
|
|
68
|
+
}
|
|
69
|
+
// 3. Summary
|
|
70
|
+
lines.push(`\n[Summary] ${report.summary.ok} passed, ${report.summary.warn} warning(s), ${report.summary.error} error(s)`);
|
|
71
|
+
return lines.join("\n");
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
if (!report.ok) {
|
|
75
|
+
process.exitCode = 1;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
throw new ExecutionError(`Doctor failed to run diagnostics: ${err.message}`);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { basename } from "node:path";
|
|
3
|
+
import { exportCompositeSkill, exportSkill, exportSkillBatch } from "@actiondock/builder";
|
|
4
|
+
import { discoverProjects, findProjectRoot, listLinkedPackages, resolvePackageRoot } from "@actiondock/core";
|
|
5
|
+
import { ExecutionError } from "../errors.js";
|
|
6
|
+
import { renderResult, writeStdout } from "../renderer.js";
|
|
7
|
+
import { getEffectiveOptions, parseListOption } from "../utils/index.js";
|
|
8
|
+
export function registerExportCommand(program, context) {
|
|
9
|
+
const exportCmd = program
|
|
10
|
+
.command("export")
|
|
11
|
+
.description("Export project artifacts");
|
|
12
|
+
exportCmd
|
|
13
|
+
.command("skill")
|
|
14
|
+
.description("Export Skill directory for AI Agents (default: source; use -m/--mode node for self-contained Node.js directory)")
|
|
15
|
+
.option("-P, --package <id...>", "Target package ID(s) or path(s) (can be specified multiple times or comma-separated)", parseListOption, [])
|
|
16
|
+
.option("--workspace", "Export all packages discovered in current workspace")
|
|
17
|
+
.option("--all", "Export all linked packages from global registry")
|
|
18
|
+
.option("--bundle [name]", "Export multiple packages as a unified composite Skill bundle (defaults to workspace directory name if omitted)")
|
|
19
|
+
.option("-m, --mode <mode>", "Skill export mode ('source' or 'node')", "source")
|
|
20
|
+
.option("-s, --standalone", "Export standalone binary skill (removed)")
|
|
21
|
+
.option("-t, --target <target>", "Target compilation platform (removed)")
|
|
22
|
+
.option("--bytecode", "Bytecode compilation (removed)")
|
|
23
|
+
.option("-o, --out <path>", "Output skill directory")
|
|
24
|
+
.option("-p, --playbook <playbooks...>", "Only export specific playbook(s) and their dependent actions", parseListOption)
|
|
25
|
+
.option("-a, --actions <actions...>", "Only export specific action(s)", parseListOption)
|
|
26
|
+
.option("-z, --archive", "Create a .zip archive of the exported skill")
|
|
27
|
+
.option("--skill-md <path>", "Use specified existing SKILL.md file instead of auto-generating")
|
|
28
|
+
.option("--custom-md <path>", "Custom skill declaration (SKILL.custom.md) with slot-marked sections and optional frontmatter description for composite bundles (auto-discovered at workspace root when omitted)")
|
|
29
|
+
.option("--skill-md-only", "Bundle mode only: regenerate only the composite SKILL.md in place (always regenerates, ignores any existing SKILL.md)")
|
|
30
|
+
.option("--vendor-deps", "Materialize locked production dependencies into the exported skill")
|
|
31
|
+
.option("--allow-install-scripts", "Allow lifecycle install scripts to run during dependency materialization")
|
|
32
|
+
.option("--require-reproducible", "Require reproducible build and fail if install scripts must run")
|
|
33
|
+
.action(async (rawOptions, cmd) => {
|
|
34
|
+
const options = getEffectiveOptions(rawOptions, cmd);
|
|
35
|
+
// 彻底删除 --standalone 单文件编译选项
|
|
36
|
+
if (options.standalone || options.target !== undefined || options.bytecode !== undefined) {
|
|
37
|
+
throw new ExecutionError("The '--standalone' option and binary target flags have been removed in ActionDock 2.0. Please use '--mode node' for self-contained Node.js directory skills, or '--mode source' for source-based skills.", undefined, "UNSUPPORTED_BUILD_MODE");
|
|
38
|
+
}
|
|
39
|
+
const mode = options.mode === "node" ? "node" : "source";
|
|
40
|
+
if (options.bundle && mode === "node") {
|
|
41
|
+
throw new ExecutionError("Composite Skill export (--bundle) currently only supports source mode. Please use '--mode source' to export as a composite workspace Skill.");
|
|
42
|
+
}
|
|
43
|
+
if (options.skillMdOnly && options.bundle === undefined) {
|
|
44
|
+
throw new ExecutionError("Option --skill-md-only requires composite bundle mode (--bundle).");
|
|
45
|
+
}
|
|
46
|
+
const sourceCount = (options.all ? 1 : 0) +
|
|
47
|
+
(options.workspace ? 1 : 0) +
|
|
48
|
+
(options.package && options.package.length > 0 ? 1 : 0);
|
|
49
|
+
if (sourceCount > 1) {
|
|
50
|
+
throw new ExecutionError("Options -P/--package, --workspace, and --all are mutually exclusive. Please specify only one package selection mode.");
|
|
51
|
+
}
|
|
52
|
+
let roots = [];
|
|
53
|
+
if (options.all) {
|
|
54
|
+
const linked = listLinkedPackages();
|
|
55
|
+
roots = linked.map((p) => p.path).filter((p) => existsSync(p));
|
|
56
|
+
if (roots.length === 0) {
|
|
57
|
+
throw new ExecutionError("No linked packages found in global registry.");
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
else if (options.workspace) {
|
|
61
|
+
const cwd = process.cwd();
|
|
62
|
+
const discovered = discoverProjects(cwd);
|
|
63
|
+
roots = discovered.length > 0 ? discovered : (findProjectRoot(cwd) ? [findProjectRoot(cwd)] : []);
|
|
64
|
+
if (roots.length === 0) {
|
|
65
|
+
throw new ExecutionError(`No ActionDock packages found in workspace '${cwd}'.\nMake sure child directories contain actiondock.json.`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
else if (options.package && options.package.length > 0) {
|
|
69
|
+
for (const pkgIdOrPath of options.package) {
|
|
70
|
+
const root = resolvePackageRoot(pkgIdOrPath);
|
|
71
|
+
if (!root) {
|
|
72
|
+
throw new ExecutionError(`Package '${pkgIdOrPath}' not found in linked packages or path`);
|
|
73
|
+
}
|
|
74
|
+
if (!roots.includes(root)) {
|
|
75
|
+
roots.push(root);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
const root = findProjectRoot();
|
|
81
|
+
if (root) {
|
|
82
|
+
roots.push(root);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
throw new ExecutionError("Not in an ActionDock project (actiondock.json not found).\nPlease specify -P, --package <id>, --workspace, --all, or cd into a project directory.");
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (roots.length > 1 && (options.actions || options.playbook)) {
|
|
89
|
+
throw new ExecutionError("Filtering options (--actions, --playbook) can only be used when exporting a single package.");
|
|
90
|
+
}
|
|
91
|
+
const isMachine = Boolean(options.json || options.envelope);
|
|
92
|
+
try {
|
|
93
|
+
if (options.bundle !== undefined) {
|
|
94
|
+
const bundleName = typeof options.bundle === "string" && options.bundle.trim()
|
|
95
|
+
? options.bundle.trim()
|
|
96
|
+
: basename(process.cwd());
|
|
97
|
+
if (!isMachine) {
|
|
98
|
+
writeStdout(`Exporting composite Skill bundle '${bundleName}' (${roots.length} package${roots.length > 1 ? "s" : ""})...`);
|
|
99
|
+
}
|
|
100
|
+
const result = await exportCompositeSkill({
|
|
101
|
+
bundleName,
|
|
102
|
+
projectRoots: roots,
|
|
103
|
+
outDir: options.out,
|
|
104
|
+
archive: options.archive,
|
|
105
|
+
workspaceRoot: options.workspace ? process.cwd() : undefined,
|
|
106
|
+
skillMdPath: options.skillMd,
|
|
107
|
+
customMdPath: options.customMd,
|
|
108
|
+
skillMdOnly: options.skillMdOnly,
|
|
109
|
+
});
|
|
110
|
+
renderResult(result, {
|
|
111
|
+
json: isMachine,
|
|
112
|
+
envelope: options.envelope,
|
|
113
|
+
humanFormatter: () => {
|
|
114
|
+
const lines = [];
|
|
115
|
+
lines.push(`[OK] Successfully exported Composite Skill: ${result.bundleName}`);
|
|
116
|
+
lines.push(` Packages: ${result.packagesCount}`);
|
|
117
|
+
lines.push(` Actions: ${result.actionsCount}`);
|
|
118
|
+
lines.push(` Playbooks: ${result.playbooksCount}`);
|
|
119
|
+
lines.push(` Skill Dir: ${result.skillDir}`);
|
|
120
|
+
if (result.skillMdFile) {
|
|
121
|
+
lines.push(` SKILL.md: Regenerated ${result.skillMdFile}`);
|
|
122
|
+
}
|
|
123
|
+
if (result.usedExistingSkillMd) {
|
|
124
|
+
lines.push(` SKILL.md: Reused existing file from ${result.usedExistingSkillMd}`);
|
|
125
|
+
}
|
|
126
|
+
if (result.archivePath) {
|
|
127
|
+
lines.push(` Archive: ${result.archivePath}`);
|
|
128
|
+
}
|
|
129
|
+
return lines.join("\n");
|
|
130
|
+
},
|
|
131
|
+
context,
|
|
132
|
+
});
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
if (roots.length > 1) {
|
|
136
|
+
if (!isMachine) {
|
|
137
|
+
writeStdout(`Batch exporting ${roots.length} Skill packages...`);
|
|
138
|
+
}
|
|
139
|
+
const batchRes = await exportSkillBatch({
|
|
140
|
+
projectRoots: roots,
|
|
141
|
+
mode,
|
|
142
|
+
outDir: options.out,
|
|
143
|
+
archive: options.archive,
|
|
144
|
+
playbooks: options.playbook,
|
|
145
|
+
actions: options.actions,
|
|
146
|
+
skillMdPath: options.skillMd,
|
|
147
|
+
vendorDeps: options.vendorDeps,
|
|
148
|
+
allowInstallScripts: options.allowInstallScripts,
|
|
149
|
+
requireReproducible: options.requireReproducible,
|
|
150
|
+
});
|
|
151
|
+
renderResult(batchRes, {
|
|
152
|
+
json: isMachine,
|
|
153
|
+
envelope: options.envelope,
|
|
154
|
+
humanFormatter: () => {
|
|
155
|
+
const lines = [];
|
|
156
|
+
lines.push(`[OK] Successfully batch exported ${batchRes.results.length} Skill packages to: ${batchRes.outDir}`);
|
|
157
|
+
for (const res of batchRes.results) {
|
|
158
|
+
lines.push(` - ${res.packageId} (v${res.version}): ${res.actionsCount} actions, ${res.playbooksCount} playbooks -> ${res.skillDir}`);
|
|
159
|
+
}
|
|
160
|
+
lines.push(` Total Actions: ${batchRes.totalActions}`);
|
|
161
|
+
lines.push(` Total Playbooks: ${batchRes.totalPlaybooks}`);
|
|
162
|
+
return lines.join("\n");
|
|
163
|
+
},
|
|
164
|
+
context,
|
|
165
|
+
});
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
const root = roots[0];
|
|
169
|
+
if (!isMachine) {
|
|
170
|
+
writeStdout(`Exporting ${mode === "node" ? "Node.js directory" : "source"} Skill artifact...`);
|
|
171
|
+
}
|
|
172
|
+
const result = await exportSkill({
|
|
173
|
+
projectRoot: root,
|
|
174
|
+
mode,
|
|
175
|
+
outDir: options.out,
|
|
176
|
+
archive: options.archive,
|
|
177
|
+
playbooks: options.playbook,
|
|
178
|
+
actions: options.actions,
|
|
179
|
+
skillMdPath: options.skillMd,
|
|
180
|
+
vendorDeps: options.vendorDeps,
|
|
181
|
+
allowInstallScripts: options.allowInstallScripts,
|
|
182
|
+
requireReproducible: options.requireReproducible,
|
|
183
|
+
});
|
|
184
|
+
renderResult(result, {
|
|
185
|
+
json: isMachine,
|
|
186
|
+
envelope: options.envelope,
|
|
187
|
+
humanFormatter: () => {
|
|
188
|
+
const lines = [];
|
|
189
|
+
lines.push(`[OK] Successfully exported ${result.mode === "node" ? "Node Directory" : "Source"} Skill: ${result.packageId} (v${result.version})`);
|
|
190
|
+
lines.push(` Mode: ${result.mode}`);
|
|
191
|
+
lines.push(` Actions: ${result.actionsCount}`);
|
|
192
|
+
lines.push(` Playbooks: ${result.playbooksCount}`);
|
|
193
|
+
lines.push(` Skill Dir: ${result.skillDir}`);
|
|
194
|
+
if (result.usedExistingSkillMd) {
|
|
195
|
+
lines.push(` SKILL.md: Reused existing file from ${result.usedExistingSkillMd}`);
|
|
196
|
+
}
|
|
197
|
+
if (result.archivePath) {
|
|
198
|
+
lines.push(` Archive: ${result.archivePath}`);
|
|
199
|
+
}
|
|
200
|
+
return lines.join("\n");
|
|
201
|
+
},
|
|
202
|
+
context,
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
catch (err) {
|
|
206
|
+
if (err?.code === "UNSUPPORTED_BUILD_MODE") {
|
|
207
|
+
throw new ExecutionError(err.message, undefined, "UNSUPPORTED_BUILD_MODE");
|
|
208
|
+
}
|
|
209
|
+
throw new ExecutionError(`Export failed: ${err.message}`);
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Command } from "commander";
|
|
2
|
+
import type { CliContext } from "../types.js";
|
|
3
|
+
/**
|
|
4
|
+
* 注册顶层 generate 代码与类型生成命令。
|
|
5
|
+
*
|
|
6
|
+
* @param program Commander 根程序对象
|
|
7
|
+
* @param context 命令行上下文
|
|
8
|
+
*/
|
|
9
|
+
export declare function registerGenerateCommands(program: Command, context?: CliContext): void;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { findProjectRoot, writeActionTypes } from "@actiondock/core";
|
|
2
|
+
import { ArgumentError, ExecutionError } from "../errors.js";
|
|
3
|
+
import { renderResult } from "../renderer.js";
|
|
4
|
+
import { getEffectiveOptions } from "../utils/index.js";
|
|
5
|
+
/**
|
|
6
|
+
* 注册顶层 generate 代码与类型生成命令。
|
|
7
|
+
*
|
|
8
|
+
* @param program Commander 根程序对象
|
|
9
|
+
* @param context 命令行上下文
|
|
10
|
+
*/
|
|
11
|
+
export function registerGenerateCommands(program, context) {
|
|
12
|
+
const generateCmd = program
|
|
13
|
+
.command("generate")
|
|
14
|
+
.description("Generate project artifacts such as TypeScript declarations");
|
|
15
|
+
generateCmd
|
|
16
|
+
.command("types")
|
|
17
|
+
.description("Generate .actiondock/generated/actions.d.ts from actiondock.json schema")
|
|
18
|
+
.option("--json", "Output as JSON")
|
|
19
|
+
.option("--envelope", "Wrap JSON output in standard envelope")
|
|
20
|
+
.action(async (rawOptions, cmd) => {
|
|
21
|
+
const options = getEffectiveOptions(rawOptions, cmd);
|
|
22
|
+
const root = findProjectRoot();
|
|
23
|
+
if (!root) {
|
|
24
|
+
throw new ArgumentError("Not in an ActionDock project (actiondock.json not found)");
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
const { filePath, digest } = writeActionTypes(root);
|
|
28
|
+
const result = {
|
|
29
|
+
success: true,
|
|
30
|
+
filePath,
|
|
31
|
+
digest,
|
|
32
|
+
};
|
|
33
|
+
renderResult(result, {
|
|
34
|
+
json: options.json,
|
|
35
|
+
envelope: options.envelope,
|
|
36
|
+
humanFormatter: () => `[OK] Generated action types at ${filePath}\nManifest digest: ${digest}`,
|
|
37
|
+
context,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
throw new ExecutionError(`Failed to generate types: ${err.message}`);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
package/dist/commands/index.d.ts
CHANGED
|
@@ -1,2 +1,32 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
|
-
|
|
2
|
+
import type { CliContext } from "../types.js";
|
|
3
|
+
import { registerActionCommands } from "./action/create.js";
|
|
4
|
+
import { registerAddCommand } from "./add.js";
|
|
5
|
+
import { registerBuildCommand } from "./build.js";
|
|
6
|
+
import { registerConfigCommands } from "./config/index.js";
|
|
7
|
+
import { registerDescribeCommand } from "./describe.js";
|
|
8
|
+
import { registerDoctorCommand } from "./doctor.js";
|
|
9
|
+
import { registerExportCommand } from "./export.js";
|
|
10
|
+
import { registerGenerateCommands } from "./generate.js";
|
|
11
|
+
import { registerInfoCommand } from "./info.js";
|
|
12
|
+
import { registerInitCommand } from "./init.js";
|
|
13
|
+
import { registerLinkCommands } from "./link.js";
|
|
14
|
+
import { registerListCommand } from "./list.js";
|
|
15
|
+
import { registerMcpCommands } from "./mcp.js";
|
|
16
|
+
import { registerNewCommands } from "./new.js";
|
|
17
|
+
import { registerPackCommand } from "./pack.js";
|
|
18
|
+
import { registerPlaybookCommands } from "./playbook.js";
|
|
19
|
+
import { registerProfileCommands } from "./profile.js";
|
|
20
|
+
import { registerRemoveCommand } from "./remove.js";
|
|
21
|
+
import { registerRunCommand } from "./run.js";
|
|
22
|
+
import { registerRunsCommands } from "./runs.js";
|
|
23
|
+
import { registerServeCommand } from "./serve.js";
|
|
24
|
+
import { registerStateCommands } from "./state.js";
|
|
25
|
+
import { registerTestCommand } from "./test.js";
|
|
26
|
+
import { registerValidateCommand } from "./validate.js";
|
|
27
|
+
/**
|
|
28
|
+
* CLI 版本号(来自 package.json 单一事实源)。
|
|
29
|
+
*/
|
|
30
|
+
export declare const CLI_VERSION: string;
|
|
31
|
+
export declare function createCliProgram(context?: CliContext): Command;
|
|
32
|
+
export { registerActionCommands, registerAddCommand, registerBuildCommand, registerConfigCommands, registerDescribeCommand, registerDoctorCommand, registerExportCommand, registerGenerateCommands, registerInfoCommand, registerInitCommand, registerLinkCommands, registerListCommand, registerMcpCommands, registerNewCommands, registerPackCommand, registerPlaybookCommands, registerProfileCommands, registerRemoveCommand, registerRunCommand, registerRunsCommands, registerServeCommand, registerStateCommands, registerTestCommand, registerValidateCommand, };
|