@actiondock/cli 2.10.0 → 2.11.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.
Files changed (64) hide show
  1. package/README.md +2 -2
  2. package/bin/ad.js +225 -5
  3. package/dist/commands/action/create.d.ts +1 -1
  4. package/dist/commands/action/create.js +6 -14
  5. package/dist/commands/add.js +1 -1
  6. package/dist/commands/config/delete.js +3 -1
  7. package/dist/commands/config/env.js +2 -1
  8. package/dist/commands/config/get.js +3 -1
  9. package/dist/commands/config/list.js +6 -5
  10. package/dist/commands/config/set.js +3 -1
  11. package/dist/commands/describe.js +2 -3
  12. package/dist/commands/export.js +34 -16
  13. package/dist/commands/index.d.ts +37 -24
  14. package/dist/commands/index.js +326 -48
  15. package/dist/commands/mcp.js +0 -1
  16. package/dist/commands/playbook.js +15 -35
  17. package/dist/commands/profile.js +2 -1
  18. package/dist/commands/remove.js +1 -1
  19. package/dist/commands/run.d.ts +2 -1
  20. package/dist/commands/run.js +4 -56
  21. package/dist/commands/runs.d.ts +6 -1
  22. package/dist/commands/runs.js +274 -11
  23. package/dist/commands/serve.js +5 -2
  24. package/dist/commands/state.js +84 -15
  25. package/dist/index.d.ts +10 -2
  26. package/dist/index.js +15 -12
  27. package/dist/prompt.d.ts +3 -0
  28. package/dist/prompt.js +6 -14
  29. package/dist/renderer.d.ts +7 -137
  30. package/dist/renderer.js +6 -438
  31. package/dist/renderers/action.d.ts +51 -0
  32. package/dist/renderers/action.js +112 -0
  33. package/dist/renderers/config.d.ts +31 -0
  34. package/dist/renderers/config.js +93 -0
  35. package/dist/renderers/playbook.d.ts +19 -0
  36. package/dist/renderers/playbook.js +42 -0
  37. package/dist/renderers/project.d.ts +45 -0
  38. package/dist/renderers/project.js +196 -0
  39. package/dist/renderers/runs.d.ts +15 -0
  40. package/dist/renderers/runs.js +47 -0
  41. package/dist/renderers/state.d.ts +4 -0
  42. package/dist/renderers/state.js +19 -0
  43. package/dist/services/config-merge.js +1 -2
  44. package/dist/services/index.d.ts +1 -0
  45. package/dist/services/index.js +1 -0
  46. package/dist/services/run-watch.d.ts +156 -0
  47. package/dist/services/run-watch.js +395 -0
  48. package/dist/utils/cert.js +1 -1
  49. package/dist/utils/index.d.ts +1 -1
  50. package/dist/utils/index.js +1 -1
  51. package/dist/utils/input.d.ts +2 -1
  52. package/dist/utils/input.js +2 -1
  53. package/dist/utils/target.d.ts +6 -2
  54. package/dist/utils/target.js +4 -4
  55. package/dist/utils/utils.js +3 -11
  56. package/dist/utils/warning.d.ts +4 -0
  57. package/dist/utils/warning.js +4 -0
  58. package/package.json +5 -5
  59. package/dist/commands/state-list.d.ts +0 -24
  60. package/dist/commands/state-list.js +0 -81
  61. package/dist/standalone/index.d.ts +0 -12
  62. package/dist/standalone/index.js +0 -13
  63. package/dist/utils/duration.d.ts +0 -1
  64. package/dist/utils/duration.js +0 -1
package/README.md CHANGED
@@ -166,7 +166,7 @@ $data | ConvertTo-Json -Depth 100 | ad run complex-action --input-file -
166
166
  | `ad remove <package>` | 卸载并更新锁定依赖,提供原子回滚保护 |
167
167
  | `ad info [patterns...]` | 检索包元数据与能力清单,支持模式匹配与树形展示 |
168
168
  | `ad list [patterns...]` | 列出包内所有已注册的 Action |
169
- | `ad describe <id>` | 编码顾问:查看 Action 的详情、模式字段明细、Flat 编码指引与建议赋值(别名 `ad show`) |
169
+ | `ad describe <id>` | 编码顾问:查看 Action 的详情、模式字段明细、Flat 编码指引与建议赋值 |
170
170
  | `ad run <id>` | 本地或远程执行指定 Action(规范语法 `ad run <id> [options] -- <assignments...>`,支持 `--json` 输出标准信封) |
171
171
  | `ad validate [id]` | 校验 Action 规范与模式规范 |
172
172
  | `ad doctor` | 执行运行环境与项目结构健康诊断 |
@@ -174,7 +174,7 @@ $data | ConvertTo-Json -Depth 100 | ad run complex-action --input-file -
174
174
  | `ad playbook list` / `show` | 查看智能体操作规程 Playbook |
175
175
  | `ad config list` / `get` / `set` | 管理包运行时配置与环境变量绑定 |
176
176
  | `ad state list` / `get` / `set` / `delete` / `clear` | 查看与维护 SQLite 持久化状态 |
177
- | `ad runs list` / `show` / `clear` | 查询任务执行历史与追踪记录,或按时间与数量策略清理历史数据 |
177
+ | `ad runs list` / `show` / `watch` / `clear` | 查询任务执行历史、阻塞等待运行终态聚合退出,或按时间与数量策略清理历史数据;list 支持 `--request-id` 过滤,watch 支持按 `--request-id` 反查等待(后台派工场景主控无 runId 时使用) |
178
178
  | `ad test` | 执行快速单元测试 |
179
179
  | `ad build` | 构建 Node.js 目录交付产物(支持 `--vendor-deps` 与 `--archive`) |
180
180
  | `ad pack` | 打包为标准 npm tarball(`.tgz`),支持 `--dry-run` |
package/bin/ad.js CHANGED
@@ -1,8 +1,26 @@
1
1
  #!/usr/bin/env node
2
+ import { enableCompileCache } from "node:module";
3
+ try {
4
+ enableCompileCache?.();
5
+ } catch {}
6
+ try {
7
+ await import("@actiondock/core/warning");
8
+ } catch {
9
+ try {
10
+ const { resolve } = await import("node:path");
11
+ const { existsSync } = await import("node:fs");
12
+ const { pathToFileURL } = await import("node:url");
13
+ const coreWarningSrc = resolve(import.meta.dirname, "../../core/src/utils/warning.ts");
14
+ if (existsSync(coreWarningSrc)) {
15
+ await import(pathToFileURL(coreWarningSrc).href);
16
+ }
17
+ } catch {}
18
+ }
19
+
2
20
  import { spawn } from "node:child_process";
3
- import { existsSync } from "node:fs";
21
+ import { existsSync, readFileSync } from "node:fs";
4
22
  import { createRequire } from "node:module";
5
- import { resolve } from "node:path";
23
+ import { resolve, dirname, join } from "node:path";
6
24
  import { fileURLToPath, pathToFileURL } from "node:url";
7
25
 
8
26
  const isBun = typeof process.versions.bun !== "undefined";
@@ -10,11 +28,206 @@ const hasTsx =
10
28
  process.execArgv.some((arg, i) => arg === "--import" && process.execArgv[i + 1]?.includes("tsx")) ||
11
29
  process.execArgv.some((arg) => arg.includes("tsx"));
12
30
 
13
- if (!isBun && !hasTsx) {
31
+ const nodeMajor = parseInt(process.versions.node?.split(".")[0] || "0", 10);
32
+ const hasNativeTypeStripping =
33
+ nodeMajor >= 24 ||
34
+ Boolean(process.features?.typescript) ||
35
+ process.execArgv.includes("--experimental-strip-types") ||
36
+ process.execArgv.includes("--experimental-transform-types") ||
37
+ Boolean(process.env.NODE_OPTIONS?.includes("--experimental-strip-types")) ||
38
+ Boolean(process.env.NODE_OPTIONS?.includes("--experimental-transform-types"));
39
+
40
+ const ROUTINE_COMMANDS = new Set([
41
+ "list",
42
+ "info",
43
+ "describe",
44
+ "validate",
45
+ "config",
46
+ "doctor",
47
+ "state",
48
+ "runs",
49
+ "add",
50
+ "remove",
51
+ "init",
52
+ "new",
53
+ "link",
54
+ "unlink",
55
+ "pack",
56
+ "generate",
57
+ "profile",
58
+ "help",
59
+ ]);
60
+
61
+ function findNearestProjectRoot(startDir = process.cwd()) {
62
+ let current;
63
+ try {
64
+ current = resolve(startDir);
65
+ } catch {
66
+ return startDir;
67
+ }
68
+ while (true) {
69
+ if (existsSync(join(current, "actiondock.json"))) {
70
+ return current;
71
+ }
72
+ const parent = dirname(current);
73
+ if (parent === current) break;
74
+ current = parent;
75
+ }
76
+ return startDir;
77
+ }
78
+
79
+ /**
80
+ * 决定是否需要派生 tsx 加载器:
81
+ * - 纯 TypeScript 工程在 Node 24 原生环境下直接执行,绝不派生进程;
82
+ * - 常规运维与元数据命令(ad -v、ad info、ad list、ad config 等)绝不派生;
83
+ * - 仅当环境显式要求、或直接执行的 Action / 工程配置声明了 JSX/TSX 等非标准语法时,按需派生 tsx。
84
+ */
85
+ function checkNeedsTsx(rawArgv) {
86
+ if (isBun || hasTsx) {
87
+ return { needsTsx: false, projectRoot: process.cwd() };
88
+ }
89
+
90
+ const explicitTsx =
91
+ process.env.ACTIONDOCK_FORCE_TSX === "1" ||
92
+ process.env.ACTIONDOCK_FORCE_TSX === "true" ||
93
+ process.env.ACTIONDOCK_TSX === "1" ||
94
+ process.env.ACTIONDOCK_TSX === "true" ||
95
+ process.env.TSX === "1" ||
96
+ rawArgv.includes("--tsx") ||
97
+ rawArgv.includes("--force-tsx");
98
+
99
+ if (explicitTsx) {
100
+ return { needsTsx: true, projectRoot: process.cwd() };
101
+ }
102
+
103
+ if (!hasNativeTypeStripping) {
104
+ return { needsTsx: true, projectRoot: process.cwd() };
105
+ }
106
+
107
+ if (
108
+ rawArgv.length === 0 ||
109
+ rawArgv.includes("-v") ||
110
+ rawArgv.includes("--version") ||
111
+ rawArgv.includes("-V") ||
112
+ rawArgv.includes("-h") ||
113
+ rawArgv.includes("--help")
114
+ ) {
115
+ return { needsTsx: false, projectRoot: process.cwd() };
116
+ }
117
+
118
+ let mainCommand = null;
119
+ let actionTarget = null;
120
+ let targetDir = process.cwd();
121
+
122
+ for (let i = 0; i < rawArgv.length; i++) {
123
+ const token = rawArgv[i];
124
+ if (token === "--cwd" || token === "-C" || token === "--project" || token === "--dir") {
125
+ const next = rawArgv[i + 1];
126
+ if (next && !next.startsWith("-")) {
127
+ try {
128
+ targetDir = resolve(next);
129
+ } catch {}
130
+ }
131
+ i++;
132
+ continue;
133
+ }
134
+ if (token.startsWith("-")) {
135
+ continue;
136
+ }
137
+ if (!mainCommand) {
138
+ mainCommand = token;
139
+ continue;
140
+ }
141
+ if (!actionTarget) {
142
+ actionTarget = token;
143
+ break;
144
+ }
145
+ }
146
+
147
+ if (!mainCommand || ROUTINE_COMMANDS.has(mainCommand)) {
148
+ return { needsTsx: false, projectRoot: targetDir };
149
+ }
150
+
151
+ if (mainCommand === "action") {
152
+ if (!actionTarget || actionTarget === "create") {
153
+ return { needsTsx: false, projectRoot: targetDir };
154
+ }
155
+ } else if (mainCommand === "playbook") {
156
+ if (!actionTarget || actionTarget === "list" || actionTarget === "show" || actionTarget === "validate" || actionTarget === "create") {
157
+ return { needsTsx: false, projectRoot: targetDir };
158
+ }
159
+ }
160
+
161
+ if (actionTarget && (actionTarget.endsWith(".tsx") || actionTarget.endsWith(".jsx"))) {
162
+ return { needsTsx: true, projectRoot: targetDir };
163
+ }
164
+
165
+ const projectRoot = findNearestProjectRoot(targetDir);
166
+
167
+ const manifestPath = join(projectRoot, "actiondock.json");
168
+ if (existsSync(manifestPath)) {
169
+ try {
170
+ const manifest = JSON.parse(readFileSync(manifestPath, "utf-8"));
171
+ if (
172
+ manifest.jsx === true ||
173
+ manifest.tsx === true ||
174
+ manifest.transpile === true ||
175
+ manifest.runtime === "tsx" ||
176
+ manifest.runtime?.transpiler === "tsx" ||
177
+ Boolean(manifest.compilerOptions?.jsx)
178
+ ) {
179
+ return { needsTsx: true, projectRoot };
180
+ }
181
+
182
+ if (actionTarget && manifest.actions?.[actionTarget]?.entry) {
183
+ const entry = String(manifest.actions[actionTarget].entry);
184
+ if (entry.endsWith(".tsx") || entry.endsWith(".jsx")) {
185
+ return { needsTsx: true, projectRoot };
186
+ }
187
+ }
188
+
189
+ if (manifest.actions) {
190
+ for (const entry of Object.values(manifest.actions)) {
191
+ if (typeof entry?.entry === "string" && (entry.entry.endsWith(".tsx") || entry.entry.endsWith(".jsx"))) {
192
+ return { needsTsx: true, projectRoot };
193
+ }
194
+ }
195
+ }
196
+ } catch {}
197
+ }
198
+
199
+ const tsconfigPath = join(projectRoot, "tsconfig.json");
200
+ if (existsSync(tsconfigPath)) {
201
+ try {
202
+ const content = readFileSync(tsconfigPath, "utf-8");
203
+ if (/"jsx"\s*:/i.test(content)) {
204
+ return { needsTsx: true, projectRoot };
205
+ }
206
+ } catch {}
207
+ }
208
+
209
+ const pkgPath = join(projectRoot, "package.json");
210
+ if (existsSync(pkgPath)) {
211
+ try {
212
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
213
+ if (pkg.jsx) {
214
+ return { needsTsx: true, projectRoot };
215
+ }
216
+ } catch {}
217
+ }
218
+
219
+ return { needsTsx: false, projectRoot };
220
+ }
221
+
222
+ const rawArgv = process.argv.slice(2);
223
+ const { needsTsx, projectRoot } = checkNeedsTsx(rawArgv);
224
+
225
+ if (needsTsx) {
14
226
  const require = createRequire(import.meta.url);
15
227
  let tsxSpecifier = null;
228
+ const searchPaths = [import.meta.dirname, process.cwd(), projectRoot];
16
229
  try {
17
- tsxSpecifier = pathToFileURL(require.resolve("tsx", { paths: [import.meta.dirname, process.cwd()] })).href;
230
+ tsxSpecifier = pathToFileURL(require.resolve("tsx", { paths: searchPaths })).href;
18
231
  } catch {
19
232
  try {
20
233
  tsxSpecifier = pathToFileURL(require.resolve("tsx")).href;
@@ -24,9 +237,16 @@ if (!isBun && !hasTsx) {
24
237
  }
25
238
 
26
239
  if (tsxSpecifier) {
240
+ const extraFlags = [];
241
+ if (process.env.ACTIONDOCK_SILENCE_WARNINGS !== "0") {
242
+ extraFlags.push("--no-warnings=ExperimentalWarning");
243
+ }
244
+ if (nodeMajor >= 24) {
245
+ extraFlags.push("--no-strip-types");
246
+ }
27
247
  const child = spawn(
28
248
  process.execPath,
29
- ["--import", tsxSpecifier, fileURLToPath(import.meta.url), ...process.argv.slice(2)],
249
+ [...extraFlags, "--import", tsxSpecifier, fileURLToPath(import.meta.url), ...rawArgv],
30
250
  {
31
251
  stdio: "inherit",
32
252
  }
@@ -8,7 +8,7 @@ export declare function parseSchemaFields(rawFields?: string[] | string): {
8
8
  required: string[];
9
9
  } | null;
10
10
  /**
11
- * 注册 action 命令组(action create, action list, action describe, action run, action validate)。
11
+ * 注册 action 命令组(仅保留脚手架创建指令 action create)。
12
12
  *
13
13
  * @param program Commander 根程序对象
14
14
  * @param context 命令行上下文
@@ -4,10 +4,6 @@ import { assertPathWithinRoot, getPackageSlug, loadManifest, saveManifest, write
4
4
  import { findProjectRoot, loadProjectConfig, } from "@actiondock/core";
5
5
  import { ExecutionError, notInProjectError, wrapAsExecutionError } from "../../errors.js";
6
6
  import { writeStdout } from "../../renderer.js";
7
- import { attachDescribeCommand } from "../describe.js";
8
- import { attachListCommand } from "../list.js";
9
- import { attachRunCommand } from "../run.js";
10
- import { attachValidateCommand } from "../validate.js";
11
7
  /**
12
8
  * 解析用户通过命令行传入的字段定义字符串(如 name:string, count?:number)。
13
9
  */
@@ -63,7 +59,7 @@ export function parseSchemaFields(rawFields) {
63
59
  return { properties, required };
64
60
  }
65
61
  /**
66
- * 注册 action 命令组(action create, action list, action describe, action run, action validate)。
62
+ * 注册 action 命令组(仅保留脚手架创建指令 action create)。
67
63
  *
68
64
  * @param program Commander 根程序对象
69
65
  * @param context 命令行上下文
@@ -71,7 +67,7 @@ export function parseSchemaFields(rawFields) {
71
67
  export function registerActionCommands(program, context) {
72
68
  const actionCmd = program
73
69
  .command("action")
74
- .description("Manage Action definitions and lifecycle (create, list, describe, run, validate)");
70
+ .description("Manage Action definitions and scaffolding (create)");
75
71
  actionCmd
76
72
  .command("create <id>")
77
73
  .description("Scaffold a new Action definition file")
@@ -82,10 +78,6 @@ export function registerActionCommands(program, context) {
82
78
  .action(async (id, options) => {
83
79
  await handleActionCreate(id, options, context);
84
80
  });
85
- attachListCommand(actionCmd, context);
86
- attachDescribeCommand(actionCmd, context);
87
- attachRunCommand(actionCmd, context);
88
- attachValidateCommand(actionCmd, context);
89
81
  }
90
82
  export async function handleActionCreate(id, options, context) {
91
83
  const root = findProjectRoot();
@@ -204,11 +196,11 @@ ${returnBody}
204
196
  // 始终自动生成或更新类型声明文件,确保单一事实源即时生效
205
197
  writeActionTypes(root, manifest);
206
198
  writeStdout(`[OK] Created Action '${id}' at ${targetFullFile}`, context);
207
- writeStdout(`\n查阅参数契约:`, context);
199
+ writeStdout(`\nParameter contract:`, context);
208
200
  writeStdout(` ad describe ${id}`, context);
209
- writeStdout(`\n调用方式:`, context);
210
- writeStdout(` 根据 describe 输出的赋值模板传递参数:ad run ${id} --json -- ASSIGNMENT...`, context);
211
- writeStdout(` 复杂输入或大段文本:ad run ${id} --json --input-file input.json`, context);
201
+ writeStdout(`\nUsage:`, context);
202
+ writeStdout(` Pass parameters according to describe assignment template: ad run ${id} --json -- ASSIGNMENT...`, context);
203
+ writeStdout(` Complex input or large text: ad run ${id} --json --input-file input.json`, context);
212
204
  }
213
205
  catch (err) {
214
206
  throw wrapAsExecutionError(err);
@@ -44,7 +44,7 @@ export function registerAddCommand(program, context) {
44
44
  const tx = await beginTransaction(root, `ad add ${packageSpec}`);
45
45
  try {
46
46
  // 调用包管理器执行安装(默认禁用生命周期安装脚本)
47
- const installCmd = getInstallCommand(root);
47
+ const installCmd = await getInstallCommand(root);
48
48
  const pm = installCmd[0];
49
49
  const args = [];
50
50
  if (pm === "bun") {
@@ -45,6 +45,8 @@ export function registerConfigDeleteCommand(configCmd, context) {
45
45
  const projConfig = loadProjectConfig(root);
46
46
  await service.management?.config.delete(projConfig.id, key);
47
47
  writeStdout(`[OK] Configuration '${key}' deleted for package '${projConfig.id}'`, context);
48
- });
48
+ },
49
+ // 按实际查询范围打开存储:显式包寻址结果作为本地根目录传递
50
+ { localRoot: root || undefined });
49
51
  });
50
52
  }
@@ -1,4 +1,5 @@
1
- import { fetchRemoteConfigEnv, resolveEnvValue, } from "@actiondock/core/profile";
1
+ import { resolveEnvValue } from "@actiondock/core";
2
+ import { fetchRemoteConfigEnv } from "@actiondock/core/profile";
2
3
  import { isSecretConfigKey, } from "@actiondock/core/project";
3
4
  import { renderConfigEnv, renderResult } from "../../renderer.js";
4
5
  import { applyTargetOptions, getEffectiveOptions, requirePackageRoot, resolveTargetFromOptions } from "../../utils/index.js";
@@ -89,6 +89,8 @@ export function registerConfigGetCommand(configCmd, context) {
89
89
  humanFormatter: () => (displayValue !== undefined ? String(displayValue) : ""),
90
90
  context,
91
91
  });
92
- });
92
+ },
93
+ // 按实际查询范围打开存储:显式包寻址结果作为本地根目录传递
94
+ { localRoot: root || undefined });
93
95
  });
94
96
  }
@@ -1,11 +1,10 @@
1
1
  import { fetchRemoteConfig, } from "@actiondock/core/profile";
2
- import { findProjectRoot, loadProjectConfig, } from "@actiondock/core";
2
+ import { loadProjectConfig, } from "@actiondock/core";
3
3
  import { filterWithFallbackInfo, isSecretConfigKey, maskSecretValue, } from "@actiondock/core/project";
4
- import { resolvePackageRoot, } from "@actiondock/core/registry";
5
4
  import { packageNotFoundError } from "../../errors.js";
6
5
  import { renderConfigList, renderResult } from "../../renderer.js";
7
6
  import { buildMergedConfigEntries } from "../../services/config-merge.js";
8
- import { applyTargetOptions, getEffectiveOptions, remoteTargetLabel, resolveFallbackStrategy, resolveIntent, resolveTargetFromOptions, withService, } from "../../utils/index.js";
7
+ import { applyTargetOptions, getEffectiveOptions, remoteTargetLabel, resolveFallbackStrategy, resolveIntent, resolveLocalPackageRoot, resolveTargetFromOptions, withService, } from "../../utils/index.js";
9
8
  /**
10
9
  * 构造单条配置项的展示视图(含掩码决策,reveal 为假且为敏感键时打码)。
11
10
  * 掩码决策收敛于命令层,renderer 仅负责值的字符串格式化。
@@ -58,9 +57,9 @@ export function registerConfigListCommand(configCmd, context) {
58
57
  });
59
58
  return;
60
59
  }
61
- // 本地分支(通过 Service 门面统一访问)
60
+ // 本地分支(通过 Service 门面统一访问):显式包寻址结果作为本地根目录传递(仅 local 分支求值)
62
61
  await withService(options, context, async (service) => {
63
- const root = options.package ? resolvePackageRoot(options.package) : findProjectRoot();
62
+ const root = resolveLocalPackageRoot(options.package) || undefined;
64
63
  // 全局作用域分支:显式 --global 或无工程回退时仅列举全局配置
65
64
  if (options.global || !root) {
66
65
  if (!options.global && options.package) {
@@ -85,6 +84,8 @@ export function registerConfigListCommand(configCmd, context) {
85
84
  humanFormatter: () => renderConfigList(filterRes.items, `${projConfig.name} (${projConfig.id})`, filterRes.isFallback, effectiveIntent),
86
85
  context,
87
86
  });
87
+ }, {
88
+ localRoot: () => resolveLocalPackageRoot(options.package) || undefined,
88
89
  });
89
90
  });
90
91
  }
@@ -79,6 +79,8 @@ export function registerConfigSetCommand(configCmd, context) {
79
79
  }
80
80
  await service.management?.config.set(projConfig.id, key, parsedVal);
81
81
  writeStdout(`[OK] Configuration '${key}' updated for package '${projConfig.id}'`, context);
82
- });
82
+ },
83
+ // 按实际查询范围打开存储:显式包寻址结果作为本地根目录传递
84
+ { localRoot: root || undefined });
83
85
  });
84
86
  }
@@ -1,7 +1,7 @@
1
1
  import { ACTION_NOT_FOUND, PACKAGE_NOT_FOUND, NOT_FOUND, } from "@actiondock/core";
2
- import { buildActionDescribePayload, formatActionDetail, } from "@actiondock/core/project";
2
+ import { buildActionDescribePayload, } from "@actiondock/core/project";
3
3
  import { ArgumentError, ExecutionError, packageNotFoundError } from "../errors.js";
4
- import { renderResult } from "../renderer.js";
4
+ import { formatActionDetail, renderResult } from "../renderer.js";
5
5
  import { applyTargetOptions, getEffectiveOptions, resolveLocalPackageRoot, withService, } from "../utils/index.js";
6
6
  /**
7
7
  * 挂载 describe 子命令至指定 Commander 节点。
@@ -12,7 +12,6 @@ import { applyTargetOptions, getEffectiveOptions, resolveLocalPackageRoot, withS
12
12
  export function attachDescribeCommand(parent, context) {
13
13
  const cmd = parent
14
14
  .command("describe <id>")
15
- .alias("show")
16
15
  .description("Show action definition, schema, and description")
17
16
  .option("-P, --package <id>", "Target package ID or path");
18
17
  return applyTargetOptions(cmd)
@@ -1,7 +1,7 @@
1
- import { existsSync } from "node:fs";
2
- import { basename } from "node:path";
1
+ import { existsSync, mkdirSync } from "node:fs";
2
+ import { basename, join, resolve } from "node:path";
3
3
  import { discoverProjects, listLinkedPackages, resolvePackageRoot, } from "@actiondock/core/registry";
4
- import { findProjectRoot, } from "@actiondock/core";
4
+ import { findProjectRoot, loadProjectConfig, } from "@actiondock/core";
5
5
  import { ExecutionError, notInProjectError, packageNotFoundError, wrapAsExecutionError } from "../errors.js";
6
6
  import { renderResult, writeStdout } from "../renderer.js";
7
7
  import { getEffectiveOptions, parseListOption } from "../utils/index.js";
@@ -83,7 +83,7 @@ export function registerExportCommand(program, context) {
83
83
  }
84
84
  const isMachine = Boolean(options.json);
85
85
  try {
86
- const { exportCompositeSkill, exportSkill, exportSkillBatch } = await import("@actiondock/builder");
86
+ const { allocatePackageDirName, exportCompositeSkill, exportSkill } = await import("@actiondock/builder");
87
87
  if (options.bundle !== undefined) {
88
88
  const bundleName = typeof options.bundle === "string" && options.bundle.trim()
89
89
  ? options.bundle.trim()
@@ -129,18 +129,36 @@ export function registerExportCommand(program, context) {
129
129
  if (!isMachine) {
130
130
  writeStdout(`Batch exporting ${roots.length} Skill packages...`);
131
131
  }
132
- const batchRes = await exportSkillBatch({
133
- projectRoots: roots,
134
- mode,
135
- outDir: options.out,
136
- archive: options.archive,
137
- playbooks: options.playbook,
138
- actions: options.actions,
139
- skillMdPath: options.skillMd,
140
- vendorDeps: options.vendorDeps,
141
- allowInstallScripts: options.allowInstallScripts,
142
- requireReproducible: options.requireReproducible,
143
- });
132
+ const baseOutDir = resolve(options.out || join(process.cwd(), "dist", "skills"));
133
+ mkdirSync(baseOutDir, { recursive: true });
134
+ const usedDirNames = new Set();
135
+ const results = [];
136
+ for (const projectRoot of roots) {
137
+ const config = loadProjectConfig(projectRoot);
138
+ const pkgSlug = allocatePackageDirName(usedDirNames, config.id);
139
+ const pkgOutDir = join(baseOutDir, `${pkgSlug}-skill`);
140
+ const res = await exportSkill({
141
+ projectRoot,
142
+ mode,
143
+ outDir: pkgOutDir,
144
+ archive: options.archive,
145
+ playbooks: options.playbook,
146
+ actions: options.actions,
147
+ skillMdPath: options.skillMd,
148
+ vendorDeps: options.vendorDeps,
149
+ allowInstallScripts: options.allowInstallScripts,
150
+ requireReproducible: options.requireReproducible,
151
+ });
152
+ results.push(res);
153
+ }
154
+ const totalActions = results.reduce((sum, r) => sum + r.actionsCount, 0);
155
+ const totalPlaybooks = results.reduce((sum, r) => sum + r.playbooksCount, 0);
156
+ const batchRes = {
157
+ results,
158
+ outDir: baseOutDir,
159
+ totalActions,
160
+ totalPlaybooks,
161
+ };
144
162
  renderResult(batchRes, {
145
163
  json: isMachine,
146
164
  humanFormatter: () => {
@@ -1,31 +1,44 @@
1
1
  import { Command } from "commander";
2
2
  import type { CliContext } from "../types.js";
3
- import { registerActionCommands } from "./action/index.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 { registerPackCommand } from "./pack.js";
17
- import { registerPlaybookCommands } from "./playbook.js";
18
- import { registerProfileCommands } from "./profile.js";
19
- import { registerRemoveCommand } from "./remove.js";
20
- import { registerRunCommand } from "./run.js";
21
- import { registerRunsCommands } from "./runs.js";
22
- import { registerServeCommand } from "./serve.js";
23
- import { registerStateCommands } from "./state.js";
24
- import { registerTestCommand } from "./test.js";
25
- import { registerValidateCommand } from "./validate.js";
26
3
  /**
27
4
  * CLI 版本号(来自 package.json 单一事实源)。
28
5
  */
29
6
  export declare const CLI_VERSION: string;
7
+ /**
8
+ * 判断命令行参数数组是否以宿主运行环境(node、bun、tsx 等)及入口脚本为前置元素。
9
+ */
10
+ export declare function isNodeArgv(argv: readonly string[]): boolean;
11
+ /**
12
+ * 从命令行参数数组中解析出目标子命令名称(跳过全局选项与启动包装参数)。
13
+ *
14
+ * @param argv 命令行原始参数数组
15
+ * @param parseOptions Commander 解析选项(如 { from: 'user' })
16
+ * @returns 目标子命令名称或 null
17
+ */
18
+ export declare function resolveTargetSubcommand(argv: readonly string[], parseOptions?: {
19
+ from?: string;
20
+ }): string | null;
30
21
  export declare function createCliProgram(context?: CliContext): Command;
31
- export { registerActionCommands, registerAddCommand, registerBuildCommand, registerConfigCommands, registerDescribeCommand, registerDoctorCommand, registerExportCommand, registerGenerateCommands, registerInfoCommand, registerInitCommand, registerLinkCommands, registerListCommand, registerMcpCommands, registerPackCommand, registerPlaybookCommands, registerProfileCommands, registerRemoveCommand, registerRunCommand, registerRunsCommands, registerServeCommand, registerStateCommands, registerTestCommand, registerValidateCommand, };
22
+ export declare const registerActionCommands: (program: Command, context?: CliContext) => Promise<any>;
23
+ export declare const registerAddCommand: (program: Command, context?: CliContext) => Promise<any>;
24
+ export declare const registerBuildCommand: (program: Command, context?: CliContext) => Promise<any>;
25
+ export declare const registerConfigCommands: (program: Command, context?: CliContext) => Promise<any>;
26
+ export declare const registerDescribeCommand: (program: Command, context?: CliContext) => Promise<any>;
27
+ export declare const registerDoctorCommand: (program: Command, context?: CliContext) => Promise<any>;
28
+ export declare const registerExportCommand: (program: Command, context?: CliContext) => Promise<any>;
29
+ export declare const registerGenerateCommands: (program: Command, context?: CliContext) => Promise<any>;
30
+ export declare const registerInfoCommand: (program: Command, context?: CliContext) => Promise<any>;
31
+ export declare const registerInitCommand: (program: Command) => Promise<any>;
32
+ export declare const registerLinkCommands: (program: Command) => Promise<any>;
33
+ export declare const registerListCommand: (program: Command, context?: CliContext) => Promise<any>;
34
+ export declare const registerMcpCommands: (program: Command, context?: CliContext) => Promise<any>;
35
+ export declare const registerPackCommand: (program: Command, context?: CliContext) => Promise<any>;
36
+ export declare const registerPlaybookCommands: (program: Command, context?: CliContext) => Promise<any>;
37
+ export declare const registerProfileCommands: (program: Command) => Promise<any>;
38
+ export declare const registerRemoveCommand: (program: Command, context?: CliContext) => Promise<any>;
39
+ export declare const registerRunCommand: (program: Command, context?: CliContext) => Promise<any>;
40
+ export declare const registerRunsCommands: (program: Command, context?: CliContext) => Promise<any>;
41
+ export declare const registerServeCommand: (program: Command, context?: CliContext) => Promise<any>;
42
+ export declare const registerStateCommands: (program: Command, context?: CliContext) => Promise<any>;
43
+ export declare const registerTestCommand: (program: Command) => Promise<any>;
44
+ export declare const registerValidateCommand: (program: Command, context?: CliContext) => Promise<any>;