@actiondock/cli 2.7.0 → 2.8.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 -6
- package/dist/commands/action/create.js +4 -5
- package/dist/commands/add.js +9 -17
- package/dist/commands/build.js +3 -18
- package/dist/commands/config/delete.js +8 -7
- package/dist/commands/config/env.js +7 -11
- package/dist/commands/config/get.js +8 -5
- package/dist/commands/config/list.js +16 -22
- package/dist/commands/config/schema.d.ts +7 -1
- package/dist/commands/config/schema.js +44 -67
- package/dist/commands/config/set.js +9 -7
- package/dist/commands/describe.js +10 -9
- package/dist/commands/doctor.js +4 -3
- package/dist/commands/export.js +5 -13
- package/dist/commands/generate.js +4 -3
- package/dist/commands/info.js +3 -1
- package/dist/commands/init.js +3 -3
- package/dist/commands/link.js +4 -4
- package/dist/commands/list.js +19 -10
- package/dist/commands/mcp.js +27 -66
- package/dist/commands/pack.js +3 -12
- package/dist/commands/playbook.js +30 -10
- package/dist/commands/profile.js +10 -19
- package/dist/commands/remove.js +5 -14
- package/dist/commands/run.d.ts +5 -2
- package/dist/commands/run.js +19 -20
- package/dist/commands/runs.js +26 -35
- package/dist/commands/serve.js +66 -44
- package/dist/commands/state-list.d.ts +2 -2
- package/dist/commands/state-list.js +10 -8
- package/dist/commands/state.d.ts +2 -2
- package/dist/commands/state.js +110 -103
- package/dist/commands/test.js +1 -1
- package/dist/commands/validate.js +4 -17
- package/dist/errors.d.ts +14 -0
- package/dist/errors.js +46 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3 -3
- package/dist/renderer.d.ts +1 -1
- package/dist/renderer.js +1 -1
- package/dist/services/config-merge.d.ts +6 -5
- package/dist/services/config-merge.js +10 -8
- package/dist/services/inspect.js +3 -1
- package/dist/standalone/index.d.ts +4 -14
- package/dist/standalone/index.js +5 -44
- package/dist/types.d.ts +2 -1
- package/dist/types.js +1 -1
- package/dist/utils/cert.js +1 -1
- package/dist/utils/duration.d.ts +1 -1
- package/dist/utils/duration.js +1 -1
- package/dist/utils/index.d.ts +1 -2
- package/dist/utils/index.js +1 -2
- package/dist/utils/input.d.ts +9 -1
- package/dist/utils/input.js +12 -1
- package/dist/utils/server-launch.d.ts +61 -0
- package/dist/utils/server-launch.js +114 -0
- package/dist/utils/target.d.ts +14 -13
- package/dist/utils/target.js +20 -39
- package/dist/utils/utils.d.ts +101 -1
- package/dist/utils/utils.js +97 -7
- package/package.json +5 -6
- package/dist/utils/bytes.d.ts +0 -1
- package/dist/utils/bytes.js +0 -1
- package/dist/utils/filter.d.ts +0 -1
- package/dist/utils/filter.js +0 -1
package/dist/commands/export.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
2
|
import { basename } from "node:path";
|
|
3
|
-
import { discoverProjects,
|
|
4
|
-
import {
|
|
3
|
+
import { discoverProjects, listLinkedPackages, resolvePackageRoot, } from "@actiondock/core/registry";
|
|
4
|
+
import { findProjectRoot, } from "@actiondock/core";
|
|
5
|
+
import { ExecutionError, notInProjectError, packageNotFoundError, wrapAsExecutionError } from "../errors.js";
|
|
5
6
|
import { renderResult, writeStdout } from "../renderer.js";
|
|
6
7
|
import { getEffectiveOptions, parseListOption } from "../utils/index.js";
|
|
7
8
|
export function registerExportCommand(program, context) {
|
|
@@ -16,9 +17,6 @@ export function registerExportCommand(program, context) {
|
|
|
16
17
|
.option("--all", "Export all linked packages from global registry")
|
|
17
18
|
.option("--bundle [name]", "Export multiple packages as a unified composite Skill bundle (defaults to workspace directory name if omitted)")
|
|
18
19
|
.option("-m, --mode <mode>", "Skill export mode ('source' or 'node')", "source")
|
|
19
|
-
.option("-s, --standalone", "Export standalone binary skill (removed)")
|
|
20
|
-
.option("-t, --target <target>", "Target compilation platform (removed)")
|
|
21
|
-
.option("--bytecode", "Bytecode compilation (removed)")
|
|
22
20
|
.option("-o, --out <path>", "Output skill directory")
|
|
23
21
|
.option("-p, --playbook <playbooks...>", "Only export specific playbook(s) and their dependent actions", parseListOption)
|
|
24
22
|
.option("-a, --actions <actions...>", "Only export specific action(s)", parseListOption)
|
|
@@ -31,10 +29,6 @@ export function registerExportCommand(program, context) {
|
|
|
31
29
|
.option("--require-reproducible", "Require reproducible build and fail if install scripts must run")
|
|
32
30
|
.action(async (rawOptions, cmd) => {
|
|
33
31
|
const options = getEffectiveOptions(rawOptions, cmd);
|
|
34
|
-
// 彻底删除 --standalone 单文件编译选项
|
|
35
|
-
if (options.standalone || options.target !== undefined || options.bytecode !== undefined) {
|
|
36
|
-
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");
|
|
37
|
-
}
|
|
38
32
|
const mode = options.mode === "node" ? "node" : "source";
|
|
39
33
|
if (options.bundle && mode === "node") {
|
|
40
34
|
throw new ExecutionError("Composite Skill export (--bundle) currently only supports source mode. Please use '--mode source' to export as a composite workspace Skill.");
|
|
@@ -200,10 +194,8 @@ export function registerExportCommand(program, context) {
|
|
|
200
194
|
});
|
|
201
195
|
}
|
|
202
196
|
catch (err) {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
}
|
|
206
|
-
throw new ExecutionError(`Export failed: ${err.message}`);
|
|
197
|
+
// wrapAsExecutionError 保留原始错误码(含 UNSUPPORTED_BUILD_MODE)
|
|
198
|
+
throw wrapAsExecutionError(err, "Export failed: ");
|
|
207
199
|
}
|
|
208
200
|
});
|
|
209
201
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { findProjectRoot,
|
|
2
|
-
import {
|
|
1
|
+
import { findProjectRoot, } from "@actiondock/core";
|
|
2
|
+
import { writeActionTypes, } from "@actiondock/core/project";
|
|
3
|
+
import { notInProjectError, wrapAsExecutionError } from "../errors.js";
|
|
3
4
|
import { renderResult } from "../renderer.js";
|
|
4
5
|
import { getEffectiveOptions } from "../utils/index.js";
|
|
5
6
|
/**
|
|
@@ -36,7 +37,7 @@ export function registerGenerateCommands(program, context) {
|
|
|
36
37
|
});
|
|
37
38
|
}
|
|
38
39
|
catch (err) {
|
|
39
|
-
throw
|
|
40
|
+
throw wrapAsExecutionError(err, "Failed to generate types: ");
|
|
40
41
|
}
|
|
41
42
|
});
|
|
42
43
|
}
|
package/dist/commands/info.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { fetchRemoteInfo,
|
|
1
|
+
import { fetchRemoteInfo, } from "@actiondock/core/profile";
|
|
2
|
+
import { filterWithFallbackInfo, } from "@actiondock/core/project";
|
|
3
|
+
import { getRegistryStatus, resolvePackageRoot, } from "@actiondock/core/registry";
|
|
2
4
|
import { ExecutionError, NO_PROJECT_NO_LINKED_MESSAGE, packageNotFoundError } from "../errors.js";
|
|
3
5
|
import { projectDetailToJson, renderAggregatedPackages, renderProjectDetail, renderRegistryTree, renderResult, } from "../renderer.js";
|
|
4
6
|
import { getProjectDetailInfo, scanLocalAggregatedPackages } from "../services/index.js";
|
package/dist/commands/init.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { initProject } from "@actiondock/core";
|
|
1
|
+
import { initProject, } from "@actiondock/core";
|
|
2
2
|
import { writeStdout } from "../renderer.js";
|
|
3
|
-
import {
|
|
3
|
+
import { wrapAsExecutionError } from "../errors.js";
|
|
4
4
|
export function registerInitCommand(program) {
|
|
5
5
|
program
|
|
6
6
|
.command("init [directory]")
|
|
@@ -18,7 +18,7 @@ export function registerInitCommand(program) {
|
|
|
18
18
|
writeStdout(`Successfully initialized ActionDock project in ${dir}`);
|
|
19
19
|
}
|
|
20
20
|
catch (err) {
|
|
21
|
-
throw
|
|
21
|
+
throw wrapAsExecutionError(err);
|
|
22
22
|
}
|
|
23
23
|
});
|
|
24
24
|
}
|
package/dist/commands/link.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { linkPackage, pruneRegistry, unlinkPackage, } from "@actiondock/core";
|
|
2
|
-
import {
|
|
1
|
+
import { linkPackage, pruneRegistry, unlinkPackage, } from "@actiondock/core/registry";
|
|
2
|
+
import { wrapAsExecutionError } from "../errors.js";
|
|
3
3
|
import { writeStdout } from "../renderer.js";
|
|
4
4
|
export function registerLinkCommands(program) {
|
|
5
5
|
// ad link [path]
|
|
@@ -24,7 +24,7 @@ export function registerLinkCommands(program) {
|
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
catch (err) {
|
|
27
|
-
throw
|
|
27
|
+
throw wrapAsExecutionError(err);
|
|
28
28
|
}
|
|
29
29
|
});
|
|
30
30
|
// ad unlink [id|path]
|
|
@@ -65,7 +65,7 @@ export function registerLinkCommands(program) {
|
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
catch (err) {
|
|
68
|
-
throw
|
|
68
|
+
throw wrapAsExecutionError(err);
|
|
69
69
|
}
|
|
70
70
|
});
|
|
71
71
|
}
|
package/dist/commands/list.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { filterWithFallbackInfo } from "@actiondock/core";
|
|
1
|
+
import { filterWithFallbackInfo, } from "@actiondock/core/project";
|
|
2
2
|
import { packageNotFoundError } from "../errors.js";
|
|
3
3
|
import { renderActionList, renderResult } from "../renderer.js";
|
|
4
|
-
import { applyTargetOptions, getEffectiveOptions, resolveFallbackStrategy, resolveIntent, resolveLocalPackageRoot,
|
|
4
|
+
import { applyTargetOptions, getEffectiveOptions, remoteTargetSuffix, resolveFallbackStrategy, resolveIntent, resolveLocalPackageRoot, withService, } from "../utils/index.js";
|
|
5
5
|
/**
|
|
6
6
|
* 挂载 list 子命令至指定 Commander 节点。
|
|
7
7
|
*
|
|
@@ -28,14 +28,23 @@ export function attachListCommand(parent, context) {
|
|
|
28
28
|
if (options.package && !targetPackageRoot) {
|
|
29
29
|
throw packageNotFoundError(options.package);
|
|
30
30
|
}
|
|
31
|
-
// 通过
|
|
32
|
-
await
|
|
33
|
-
let rawSummaries = await
|
|
34
|
-
//
|
|
31
|
+
// 通过 Service 门面统一获取 Action 列表
|
|
32
|
+
await withService(options, context, async (service, resolved) => {
|
|
33
|
+
let rawSummaries = await service.discovery.listActions();
|
|
34
|
+
// 若指定了目标包但本地未过滤,则按包归属精确过滤:
|
|
35
|
+
// 仅保留全限定名命中目标包前缀、或 packageId 归属目标包的条目;
|
|
36
|
+
// 无法归属到目标包的无前缀短 id 条目不放行,避免他包短 id 混入
|
|
35
37
|
if (options.package && !options.profile && !options.server) {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
const targetPkg = options.package;
|
|
39
|
+
rawSummaries = rawSummaries.filter((s) => {
|
|
40
|
+
if (s.packageId) {
|
|
41
|
+
return (s.packageId === targetPkg ||
|
|
42
|
+
s.id === targetPkg ||
|
|
43
|
+
s.id.startsWith(`${targetPkg}/`));
|
|
44
|
+
}
|
|
45
|
+
// 无 packageId 归属信息的条目:仅全限定名前缀命中时放行
|
|
46
|
+
return s.id === targetPkg || s.id.startsWith(`${targetPkg}/`);
|
|
47
|
+
});
|
|
39
48
|
}
|
|
40
49
|
const rawList = rawSummaries.map((s) => {
|
|
41
50
|
let id = s.id;
|
|
@@ -59,7 +68,7 @@ export function attachListCommand(parent, context) {
|
|
|
59
68
|
return;
|
|
60
69
|
}
|
|
61
70
|
const title = resolved.type === "remote"
|
|
62
|
-
? `Actions
|
|
71
|
+
? `Actions ${remoteTargetSuffix(resolved)}`
|
|
63
72
|
: targetPackageRoot
|
|
64
73
|
? `Actions in ${options.package || "current project"}`
|
|
65
74
|
: "Available Actions";
|
package/dist/commands/mcp.js
CHANGED
|
@@ -1,9 +1,22 @@
|
|
|
1
1
|
import { resolve } from "node:path";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { getEffectiveOptions,
|
|
2
|
+
import { createNodePlatform, findProjectRoot, loadProjectConfig, } from "@actiondock/core";
|
|
3
|
+
import { formatHostForUrl, } from "@actiondock/core/server";
|
|
4
|
+
import { ExecutionError } from "../errors.js";
|
|
5
|
+
import { writeStdout } from "../renderer.js";
|
|
6
|
+
import { getEffectiveOptions, normalizeCorsOrigins, parseListOption, printServerBanner, registerStopSignalHandler, resolveMaxBodyBytes, resolveServerHost, resolveServerPort, resolveServerToken, resolveTimeoutMs, } from "../utils/index.js";
|
|
7
|
+
/**
|
|
8
|
+
* 解析 mcp 命令双分支共享的目标选项(目录、包、超时)。
|
|
9
|
+
*/
|
|
10
|
+
function resolveMcpServeOptions(options) {
|
|
11
|
+
return {
|
|
12
|
+
projectRoots: options.dir && options.dir.length > 0
|
|
13
|
+
? options.dir.map((d) => resolve(d))
|
|
14
|
+
: undefined,
|
|
15
|
+
packageIds: options.package && options.package.length > 0 ? options.package : undefined,
|
|
16
|
+
all: Boolean(options.all),
|
|
17
|
+
timeoutMs: resolveTimeoutMs(options.timeout),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
7
20
|
/**
|
|
8
21
|
* 注册 mcp 命令(STDIO 与 HTTP 传输服务模式)。
|
|
9
22
|
*
|
|
@@ -21,20 +34,7 @@ export function registerMcpCommands(program, context) {
|
|
|
21
34
|
.option("--data-dir <path>", "Custom database storage directory")
|
|
22
35
|
.action(async (rawOptions, cmd) => {
|
|
23
36
|
const options = getEffectiveOptions(rawOptions, cmd);
|
|
24
|
-
|
|
25
|
-
if (options.timeout) {
|
|
26
|
-
try {
|
|
27
|
-
timeoutMs = parseDuration(options.timeout);
|
|
28
|
-
}
|
|
29
|
-
catch (err) {
|
|
30
|
-
throw new ArgumentError(`Invalid timeout format: ${err.message}`);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
const projectRoots = options.dir && options.dir.length > 0
|
|
34
|
-
? options.dir.map((d) => resolve(d))
|
|
35
|
-
: undefined;
|
|
36
|
-
const packageIds = options.package && options.package.length > 0 ? options.package : undefined;
|
|
37
|
-
const all = Boolean(options.all);
|
|
37
|
+
const { projectRoots, packageIds, all, timeoutMs } = resolveMcpServeOptions(options);
|
|
38
38
|
try {
|
|
39
39
|
const { startMcpStdio } = await import("@actiondock/mcp");
|
|
40
40
|
await startMcpStdio({
|
|
@@ -69,38 +69,15 @@ export function registerMcpCommands(program, context) {
|
|
|
69
69
|
.option("--data-dir <path>", "Custom database storage directory")
|
|
70
70
|
.action(async (rawOptions, cmd) => {
|
|
71
71
|
const options = getEffectiveOptions(rawOptions, cmd);
|
|
72
|
-
const port =
|
|
73
|
-
const host = options.host
|
|
74
|
-
const token = options.token
|
|
75
|
-
(options.tokenEnv && typeof process !== "undefined" ? process.env?.[options.tokenEnv] : undefined) ||
|
|
76
|
-
(typeof process !== "undefined" ? process.env?.ACTIONDOCK_TOKEN : undefined);
|
|
72
|
+
const port = resolveServerPort(options.port, 5178, true);
|
|
73
|
+
const host = resolveServerHost(options.host);
|
|
74
|
+
const token = resolveServerToken(options.token, options.tokenEnv);
|
|
77
75
|
const allowInsecureNoAuth = Boolean(options.allowInsecureNoAuth);
|
|
78
76
|
const allowInsecureHttp = Boolean(options.allowInsecureHttp);
|
|
79
77
|
const allowQueryToken = Boolean(options.allowQueryToken);
|
|
80
|
-
const corsOrigins = options.corsOrigin
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
try {
|
|
84
|
-
maxBodyBytes = parseByteSize(options.maxBody);
|
|
85
|
-
}
|
|
86
|
-
catch (err) {
|
|
87
|
-
throw new ArgumentError(`Invalid max-body format: ${err.message}`);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
let timeoutMs;
|
|
91
|
-
if (options.timeout) {
|
|
92
|
-
try {
|
|
93
|
-
timeoutMs = parseDuration(options.timeout);
|
|
94
|
-
}
|
|
95
|
-
catch (err) {
|
|
96
|
-
throw new ArgumentError(`Invalid timeout format: ${err.message}`);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
const projectRoots = options.dir && options.dir.length > 0
|
|
100
|
-
? options.dir.map((d) => resolve(d))
|
|
101
|
-
: undefined;
|
|
102
|
-
const packageIds = options.package && options.package.length > 0 ? options.package : undefined;
|
|
103
|
-
const all = Boolean(options.all);
|
|
78
|
+
const corsOrigins = normalizeCorsOrigins(options.corsOrigin);
|
|
79
|
+
const maxBodyBytes = resolveMaxBodyBytes(options.maxBody);
|
|
80
|
+
const { projectRoots, packageIds, all, timeoutMs } = resolveMcpServeOptions(options);
|
|
104
81
|
let targetDescription = "ActionDock MCP Server";
|
|
105
82
|
if (all) {
|
|
106
83
|
targetDescription = "All Linked Packages (Global Registry Mode)";
|
|
@@ -161,30 +138,14 @@ export function registerMcpCommands(program, context) {
|
|
|
161
138
|
});
|
|
162
139
|
const displayHost = formatHostForUrl(host);
|
|
163
140
|
const actualMcpHost = formatHostForUrl(host === "0.0.0.0" ? "127.0.0.1" : host);
|
|
164
|
-
|
|
165
|
-
writeStdout(` ActionDock 2.0 MCP HTTP Server`, context);
|
|
166
|
-
writeStdout(`======================================================`, context);
|
|
167
|
-
writeStdout(` * Listening on: http://${displayHost}:${server.port}`, context);
|
|
141
|
+
printServerBanner(`ActionDock 2.0 MCP HTTP Server`, "http", displayHost, server.port, context);
|
|
168
142
|
writeStdout(` * MCP Endpoint: http://${actualMcpHost}:${server.port}/mcp`, context);
|
|
169
143
|
writeStdout(` * Target: ${targetDescription}`, context);
|
|
170
144
|
writeStdout(` * Authentication: ${token ? "Bearer Token Enabled" : "Disabled (Local)"}`, context);
|
|
171
145
|
writeStdout(` * CORS Origins: ${corsOrigins ? corsOrigins.join(", ") : "Disabled (Default)"}`, context);
|
|
172
146
|
writeStdout(`======================================================\n`, context);
|
|
173
147
|
writeStdout(`Press Ctrl+C to terminate.\n`, context);
|
|
174
|
-
|
|
175
|
-
writeStdout("\nStopping MCP HTTP server...", context);
|
|
176
|
-
Promise.resolve(server.stop())
|
|
177
|
-
.catch((err) => {
|
|
178
|
-
// 停止失败必须可见:写入 stderr 一行并标记失败退出码
|
|
179
|
-
writeStderr(`[ERROR] Failed to stop MCP HTTP server gracefully: ${err instanceof Error ? err.message : String(err)}`, context);
|
|
180
|
-
process.exitCode = 1;
|
|
181
|
-
})
|
|
182
|
-
.finally(() => {
|
|
183
|
-
process.exit(typeof process.exitCode === "number" ? process.exitCode : 0);
|
|
184
|
-
});
|
|
185
|
-
};
|
|
186
|
-
process.once("SIGINT", stopSignalHandler);
|
|
187
|
-
process.once("SIGTERM", stopSignalHandler);
|
|
148
|
+
registerStopSignalHandler(server, `MCP HTTP server`, context);
|
|
188
149
|
}
|
|
189
150
|
catch (err) {
|
|
190
151
|
throw new ExecutionError(`Failed to start ActionDock MCP HTTP server: ${err.message}`, err);
|
package/dist/commands/pack.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { ExecutionError, notInProjectError, packageNotFoundError } from "../errors.js";
|
|
1
|
+
import { ExecutionError } from "../errors.js";
|
|
3
2
|
import { renderResult, writeStdout } from "../renderer.js";
|
|
4
|
-
import { getEffectiveOptions } from "../utils/index.js";
|
|
3
|
+
import { getEffectiveOptions, requirePackageRoot } from "../utils/index.js";
|
|
5
4
|
export function registerPackCommand(program, context) {
|
|
6
5
|
program
|
|
7
6
|
.command("pack")
|
|
@@ -12,15 +11,7 @@ export function registerPackCommand(program, context) {
|
|
|
12
11
|
.option("--json", "Output as JSON")
|
|
13
12
|
.action(async (rawOptions, cmd) => {
|
|
14
13
|
const options = getEffectiveOptions(rawOptions, cmd);
|
|
15
|
-
const root = options.package
|
|
16
|
-
? resolvePackageRoot(options.package)
|
|
17
|
-
: findProjectRoot();
|
|
18
|
-
if (!root) {
|
|
19
|
-
if (options.package) {
|
|
20
|
-
throw packageNotFoundError(options.package);
|
|
21
|
-
}
|
|
22
|
-
throw notInProjectError("Please specify -P, --package <id> or cd into a project directory.");
|
|
23
|
-
}
|
|
14
|
+
const { root } = requirePackageRoot(options.package);
|
|
24
15
|
const isMachine = Boolean(options.json);
|
|
25
16
|
if (!isMachine && !options.dryRun) {
|
|
26
17
|
writeStdout("Packing Action package...");
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { dirname, isAbsolute, relative, resolve } from "node:path";
|
|
3
|
-
import { assertPathWithinRoot,
|
|
4
|
-
import {
|
|
3
|
+
import { assertPathWithinRoot, loadActions, loadManifest, loadPlaybooks, saveManifest, filterWithFallbackInfo, } from "@actiondock/core/project";
|
|
4
|
+
import { DefaultActionCatalog, PackageGraphBuilder, resolveAction, resolvePlaybook, } from "@actiondock/core/graph";
|
|
5
|
+
import { fetchRemotePlaybooks, fetchRemotePlaybookShow, } from "@actiondock/core/profile";
|
|
6
|
+
import { findProjectRoot, loadProjectConfig, } from "@actiondock/core";
|
|
7
|
+
import { listLinkedPackages, resolvePackageRoot, } from "@actiondock/core/registry";
|
|
8
|
+
import { ArgumentError, CliError, ExecutionError, NO_PROJECT_NO_LINKED_MESSAGE, notInProjectError, packageNotFoundError, wrapAsExecutionError, } from "../errors.js";
|
|
5
9
|
import { renderPlaybookDetail, renderPlaybookList, renderResult, writeStdout, } from "../renderer.js";
|
|
6
|
-
import { applyTargetOptions, getEffectiveOptions, resolveIntent, resolveTargetFromOptions, } from "../utils/index.js";
|
|
10
|
+
import { applyTargetOptions, getEffectiveOptions, remoteTargetSuffix, resolveFallbackStrategy, resolveIntent, resolveTargetFromOptions, } from "../utils/index.js";
|
|
7
11
|
/**
|
|
8
12
|
* 注册 Playbook 命令集合(list, show, validate, create)。
|
|
9
13
|
*
|
|
@@ -20,13 +24,13 @@ export function registerPlaybookCommands(program, context) {
|
|
|
20
24
|
.description("List playbooks in current project or linked packages")
|
|
21
25
|
.option("-i, --intent <pattern>", "Regex or fuzzy intent filter; falls back to full list when no match")
|
|
22
26
|
.option("-P, --package <id>", "Target package ID or path"))
|
|
27
|
+
.option("--fallback", "Enable fallback to full list when no items match intent")
|
|
23
28
|
.option("--no-fallback", "Disable fallback to full list when no items match intent")
|
|
24
29
|
.option("--json", "Output as JSON")
|
|
25
30
|
.action(async (patterns = [], rawOptions, cmd) => {
|
|
26
31
|
const options = getEffectiveOptions(rawOptions, cmd);
|
|
27
32
|
const effectiveIntent = resolveIntent(options.intent, patterns);
|
|
28
|
-
const shouldFallback = options
|
|
29
|
-
const isMachine = Boolean(options.json);
|
|
33
|
+
const { shouldFallback, isMachine } = resolveFallbackStrategy(options);
|
|
30
34
|
// 1. 远端服务分支
|
|
31
35
|
const target = resolveTargetFromOptions(options, context);
|
|
32
36
|
if (target.type === "remote") {
|
|
@@ -38,7 +42,7 @@ export function registerPlaybookCommands(program, context) {
|
|
|
38
42
|
});
|
|
39
43
|
renderResult(remotePbs, {
|
|
40
44
|
json: options.json,
|
|
41
|
-
humanFormatter: () => renderPlaybookList(remotePbs, `Playbooks
|
|
45
|
+
humanFormatter: () => renderPlaybookList(remotePbs, `Playbooks ${remoteTargetSuffix(target)}`, false, effectiveIntent),
|
|
42
46
|
context,
|
|
43
47
|
});
|
|
44
48
|
return;
|
|
@@ -187,7 +191,12 @@ export function registerPlaybookCommands(program, context) {
|
|
|
187
191
|
}
|
|
188
192
|
let resolved;
|
|
189
193
|
try {
|
|
190
|
-
|
|
194
|
+
const graph = new PackageGraphBuilder({
|
|
195
|
+
root: findProjectRoot() || undefined,
|
|
196
|
+
customHome: context?.customHome,
|
|
197
|
+
allowDevLinks: true,
|
|
198
|
+
}).buildSync();
|
|
199
|
+
resolved = resolvePlaybook(showTarget, { graph });
|
|
191
200
|
}
|
|
192
201
|
catch (err) {
|
|
193
202
|
throw new ArgumentError(err.message);
|
|
@@ -243,7 +252,12 @@ export function registerPlaybookCommands(program, context) {
|
|
|
243
252
|
else if (id) {
|
|
244
253
|
let resolved;
|
|
245
254
|
try {
|
|
246
|
-
|
|
255
|
+
const graph = new PackageGraphBuilder({
|
|
256
|
+
root: findProjectRoot() || undefined,
|
|
257
|
+
customHome: context?.customHome,
|
|
258
|
+
allowDevLinks: true,
|
|
259
|
+
}).buildSync();
|
|
260
|
+
resolved = resolvePlaybook(id, { graph });
|
|
247
261
|
}
|
|
248
262
|
catch (err) {
|
|
249
263
|
throw new ArgumentError(err.message);
|
|
@@ -277,6 +291,12 @@ export function registerPlaybookCommands(program, context) {
|
|
|
277
291
|
}
|
|
278
292
|
}
|
|
279
293
|
const results = [];
|
|
294
|
+
const graph = new PackageGraphBuilder({
|
|
295
|
+
root: findProjectRoot() || undefined,
|
|
296
|
+
customHome: context?.customHome,
|
|
297
|
+
allowDevLinks: true,
|
|
298
|
+
}).buildSync();
|
|
299
|
+
const catalog = new DefaultActionCatalog(graph);
|
|
280
300
|
for (const target of targets) {
|
|
281
301
|
const config = loadProjectConfig(target.root);
|
|
282
302
|
const manifest = loadManifest(target.root);
|
|
@@ -294,7 +314,7 @@ export function registerPlaybookCommands(program, context) {
|
|
|
294
314
|
for (const actRef of pb.actions) {
|
|
295
315
|
if (actRef.includes("/")) {
|
|
296
316
|
try {
|
|
297
|
-
|
|
317
|
+
resolveAction(actRef, { graph, catalog, caller: target.packageId });
|
|
298
318
|
}
|
|
299
319
|
catch (e) {
|
|
300
320
|
errors.push(`Referenced cross-package action '${actRef}' not resolvable: ${e.message}`);
|
|
@@ -408,6 +428,6 @@ This playbook provides task execution guidance for AI Agents.
|
|
|
408
428
|
if (err instanceof CliError) {
|
|
409
429
|
throw err;
|
|
410
430
|
}
|
|
411
|
-
throw
|
|
431
|
+
throw wrapAsExecutionError(err);
|
|
412
432
|
}
|
|
413
433
|
}
|
package/dist/commands/profile.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { addProfile, checkRemoteHealth,
|
|
2
|
-
import {
|
|
1
|
+
import { addProfile, checkRemoteHealth, getProfile, listProfiles, loadProfiles, removeProfile, resolveProfileToken, resolveTarget, toSnakeUpperCase, updateProfile, useProfile, } from "@actiondock/core/profile";
|
|
2
|
+
import { filterWithFallbackInfo, maskSecretValue, } from "@actiondock/core/project";
|
|
3
|
+
import { ArgumentError, ExecutionError, wrapAsExecutionError, } from "../errors.js";
|
|
3
4
|
import { renderResult, writeStderr, writeStdout } from "../renderer.js";
|
|
4
5
|
import { getEffectiveOptions, resolveFallbackStrategy, resolveIntent } from "../utils/index.js";
|
|
5
6
|
export function registerProfileCommands(program) {
|
|
@@ -76,9 +77,7 @@ export function registerProfileCommands(program) {
|
|
|
76
77
|
});
|
|
77
78
|
}
|
|
78
79
|
catch (err) {
|
|
79
|
-
|
|
80
|
-
throw err;
|
|
81
|
-
throw new ExecutionError(err.message);
|
|
80
|
+
throw wrapAsExecutionError(err);
|
|
82
81
|
}
|
|
83
82
|
});
|
|
84
83
|
// ad profile add <name>
|
|
@@ -105,7 +104,7 @@ export function registerProfileCommands(program) {
|
|
|
105
104
|
writeStdout(`[OK] Profile '${name}' configured for server: ${options.server}${options.insecure ? " (insecure: true)" : ""}`);
|
|
106
105
|
}
|
|
107
106
|
catch (err) {
|
|
108
|
-
throw
|
|
107
|
+
throw wrapAsExecutionError(err);
|
|
109
108
|
}
|
|
110
109
|
});
|
|
111
110
|
// ad profile update <name>
|
|
@@ -140,7 +139,7 @@ export function registerProfileCommands(program) {
|
|
|
140
139
|
writeStdout(`[OK] Profile '${name}' updated`);
|
|
141
140
|
}
|
|
142
141
|
catch (err) {
|
|
143
|
-
throw
|
|
142
|
+
throw wrapAsExecutionError(err);
|
|
144
143
|
}
|
|
145
144
|
});
|
|
146
145
|
// ad profile use <name>
|
|
@@ -153,7 +152,7 @@ export function registerProfileCommands(program) {
|
|
|
153
152
|
writeStdout(`[OK] Active profile switched to '${name}'`);
|
|
154
153
|
}
|
|
155
154
|
catch (err) {
|
|
156
|
-
throw
|
|
155
|
+
throw wrapAsExecutionError(err);
|
|
157
156
|
}
|
|
158
157
|
});
|
|
159
158
|
// ad profile show [name]
|
|
@@ -221,10 +220,7 @@ export function registerProfileCommands(program) {
|
|
|
221
220
|
});
|
|
222
221
|
}
|
|
223
222
|
catch (err) {
|
|
224
|
-
|
|
225
|
-
throw err;
|
|
226
|
-
}
|
|
227
|
-
throw new ExecutionError(err.message);
|
|
223
|
+
throw wrapAsExecutionError(err);
|
|
228
224
|
}
|
|
229
225
|
});
|
|
230
226
|
// ad profile rm / remove <name>
|
|
@@ -244,10 +240,7 @@ export function registerProfileCommands(program) {
|
|
|
244
240
|
writeStdout(`[OK] Profile '${name}' removed`);
|
|
245
241
|
}
|
|
246
242
|
catch (err) {
|
|
247
|
-
|
|
248
|
-
throw err;
|
|
249
|
-
}
|
|
250
|
-
throw new ExecutionError(err.message);
|
|
243
|
+
throw wrapAsExecutionError(err);
|
|
251
244
|
}
|
|
252
245
|
});
|
|
253
246
|
// ad profile test [name]
|
|
@@ -290,9 +283,7 @@ export function registerProfileCommands(program) {
|
|
|
290
283
|
}
|
|
291
284
|
}
|
|
292
285
|
catch (err) {
|
|
293
|
-
|
|
294
|
-
throw err;
|
|
295
|
-
throw new ExecutionError(err.message);
|
|
286
|
+
throw wrapAsExecutionError(err);
|
|
296
287
|
}
|
|
297
288
|
});
|
|
298
289
|
}
|
package/dist/commands/remove.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { ArgumentError, ExecutionError, notInProjectError } from "../errors.js";
|
|
1
|
+
import { beginTransaction, getInstallCommand, loadLockfile, saveLockfile, saveManifest, } from "@actiondock/core/project";
|
|
2
|
+
import { ArgumentError, ExecutionError } from "../errors.js";
|
|
4
3
|
import { renderResult, writeStderr } from "../renderer.js";
|
|
5
|
-
import { assertSafePackageSpec, getEffectiveOptions, spawnAsync } from "../utils/index.js";
|
|
4
|
+
import { assertSafePackageSpec, getEffectiveOptions, requireProjectManifestRoot, rollbackAndRethrow, spawnAsync, } from "../utils/index.js";
|
|
6
5
|
/**
|
|
7
6
|
* 注册 ad remove 依赖移除命令。
|
|
8
7
|
* 遵循规范:移除依赖并更新锁文件,保留该包的历史存储数据,检查反向引用防止误删。
|
|
@@ -15,14 +14,7 @@ export function registerRemoveCommand(program, context) {
|
|
|
15
14
|
.option("--json", "Output as JSON")
|
|
16
15
|
.action(async (packageIdentifier, rawOptions, cmd) => {
|
|
17
16
|
const options = getEffectiveOptions(rawOptions, cmd);
|
|
18
|
-
const root
|
|
19
|
-
if (!root) {
|
|
20
|
-
throw notInProjectError("Please specify -P, --package <path> or cd into a project directory.");
|
|
21
|
-
}
|
|
22
|
-
const manifest = loadManifest(root);
|
|
23
|
-
if (!manifest) {
|
|
24
|
-
throw new ArgumentError(`actiondock.json not found in ${root}`);
|
|
25
|
-
}
|
|
17
|
+
const { root, manifest } = requireProjectManifestRoot(options.package);
|
|
26
18
|
// 寻址逻辑包标识
|
|
27
19
|
let targetPackageId = null;
|
|
28
20
|
let npmPackageName = packageIdentifier;
|
|
@@ -115,8 +107,7 @@ export function registerRemoveCommand(program, context) {
|
|
|
115
107
|
});
|
|
116
108
|
}
|
|
117
109
|
catch (err) {
|
|
118
|
-
await tx
|
|
119
|
-
throw new ExecutionError(err.message, err, err.code || "REMOVE_DEPENDENCY_FAILED");
|
|
110
|
+
await rollbackAndRethrow(tx, err, "REMOVE_DEPENDENCY_FAILED");
|
|
120
111
|
}
|
|
121
112
|
});
|
|
122
113
|
}
|
package/dist/commands/run.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type InvocationControl } from "@actiondock/core";
|
|
1
|
+
import { type InvocationControl } from "@actiondock/core/server";
|
|
2
2
|
import type { ExecutionResult } from "@actiondock/sdk";
|
|
3
3
|
import { Command } from "commander";
|
|
4
4
|
import type { CliContext } from "../types.js";
|
|
@@ -10,7 +10,10 @@ import type { CliContext } from "../types.js";
|
|
|
10
10
|
*/
|
|
11
11
|
export declare function renderRawExecutionResult(targetRef: string, result: ExecutionResult, context?: CliContext): void;
|
|
12
12
|
/**
|
|
13
|
-
* 统一执行 Action 核心逻辑(使用
|
|
13
|
+
* 统一执行 Action 核心逻辑(使用 ActionDockService 服务端口)。
|
|
14
|
+
*
|
|
15
|
+
* @param id 目标 Action 标识
|
|
16
|
+
* @param options 执行选项(由 Command 统一构造)
|
|
14
17
|
*/
|
|
15
18
|
export declare function executeAction(id: string, options: any, context?: CliContext, flatArgs?: string[], control?: InvocationControl): Promise<void>;
|
|
16
19
|
/**
|
package/dist/commands/run.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { validateActionInputValue, mapInputValidationFailure, } from "@actiondock/core/project";
|
|
2
|
+
import { resolveTarget, } from "@actiondock/core/profile";
|
|
2
3
|
import { ArgumentError, ExecutionError, SigintError, packageNotFoundError } from "../errors.js";
|
|
3
4
|
import { writeStderr, writeStdout } from "../renderer.js";
|
|
4
|
-
import { applyTargetOptions, getEffectiveOptions, resolveActionInput, resolveLocalPackageRoot,
|
|
5
|
+
import { applyTargetOptions, getEffectiveOptions, resolveActionInput, resolveLocalPackageRoot, resolveTimeoutMs, withService, } from "../utils/index.js";
|
|
5
6
|
/**
|
|
6
7
|
* 以原始纯文本形式渲染 Action 执行终态结果(默认纯文本模式)。
|
|
7
8
|
*
|
|
@@ -95,7 +96,10 @@ export function renderRawExecutionResult(targetRef, result, context) {
|
|
|
95
96
|
}
|
|
96
97
|
}
|
|
97
98
|
/**
|
|
98
|
-
* 统一执行 Action 核心逻辑(使用
|
|
99
|
+
* 统一执行 Action 核心逻辑(使用 ActionDockService 服务端口)。
|
|
100
|
+
*
|
|
101
|
+
* @param id 目标 Action 标识
|
|
102
|
+
* @param options 执行选项(由 Command 统一构造)
|
|
99
103
|
*/
|
|
100
104
|
export async function executeAction(id, options, context, flatArgs, control) {
|
|
101
105
|
if (!id) {
|
|
@@ -114,15 +118,7 @@ export async function executeAction(id, options, context, flatArgs, control) {
|
|
|
114
118
|
if (!check.valid) {
|
|
115
119
|
throw mapInputValidationFailure("cli-pre-target", check);
|
|
116
120
|
}
|
|
117
|
-
|
|
118
|
-
if (options.timeout) {
|
|
119
|
-
try {
|
|
120
|
-
timeoutMs = parseDuration(options.timeout);
|
|
121
|
-
}
|
|
122
|
-
catch (err) {
|
|
123
|
-
throw new ArgumentError(`Invalid timeout format: ${err.message}`);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
121
|
+
const timeoutMs = resolveTimeoutMs(options.timeout);
|
|
126
122
|
const configOverrides = {};
|
|
127
123
|
if (options.config) {
|
|
128
124
|
const list = Array.isArray(options.config) ? options.config : [options.config];
|
|
@@ -149,14 +145,14 @@ export async function executeAction(id, options, context, flatArgs, control) {
|
|
|
149
145
|
throw packageNotFoundError(options.package);
|
|
150
146
|
}
|
|
151
147
|
let targetRef = id;
|
|
152
|
-
if (options.package && !id.includes("/")
|
|
148
|
+
if (options.package && !id.includes("/")) {
|
|
153
149
|
targetRef = `${options.package}/${id}`;
|
|
154
150
|
}
|
|
155
|
-
// 通过
|
|
156
|
-
await
|
|
151
|
+
// 通过 Service 统一执行
|
|
152
|
+
await withService(options, context, async (service) => {
|
|
157
153
|
const isMachine = Boolean(options.json);
|
|
158
154
|
if (options.async) {
|
|
159
|
-
const ticket = await
|
|
155
|
+
const ticket = await service.execution.start(targetRef, input, {
|
|
160
156
|
signal: effectiveSignal,
|
|
161
157
|
timeoutMs,
|
|
162
158
|
config: configOverrides,
|
|
@@ -182,7 +178,7 @@ export async function executeAction(id, options, context, flatArgs, control) {
|
|
|
182
178
|
}
|
|
183
179
|
}
|
|
184
180
|
else {
|
|
185
|
-
const result = await
|
|
181
|
+
const result = await service.execution.run(targetRef, input, {
|
|
186
182
|
signal: effectiveSignal,
|
|
187
183
|
timeoutMs,
|
|
188
184
|
config: configOverrides,
|
|
@@ -208,10 +204,13 @@ export async function executeAction(id, options, context, flatArgs, control) {
|
|
|
208
204
|
}, { localRoot: targetPackageRoot || undefined, scanLinkedPackages: true, ownDataDir: true });
|
|
209
205
|
}
|
|
210
206
|
catch (err) {
|
|
207
|
+
// sigint 取消源、中断链路特征错误码或 SigintError 本身,均统一归并为 SigintError
|
|
208
|
+
// 原 if 中额外的「cancellationSource 为 sigint 且 AbortError/aborted/ACTION_CANCELLED」
|
|
209
|
+
// 子句被首项 cancellationSource === "sigint" 完全蕴含,等价化简后移除
|
|
211
210
|
const isSigint = effectiveControl?.cancellationSource === "sigint" ||
|
|
212
|
-
err?.
|
|
213
|
-
|
|
214
|
-
|
|
211
|
+
err?.code === "SIGINT_INTERRUPTED" ||
|
|
212
|
+
err instanceof SigintError;
|
|
213
|
+
if (isSigint) {
|
|
215
214
|
throw new SigintError();
|
|
216
215
|
}
|
|
217
216
|
throw err;
|