@actiondock/cli 2.6.0 → 2.7.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 +30 -16
- package/bin/ad.js +4 -4
- package/dist/commands/action/create.js +5 -20
- package/dist/commands/describe.js +6 -18
- package/dist/commands/run.d.ts +2 -1
- package/dist/commands/run.js +46 -22
- package/dist/errors.js +33 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +60 -8
- package/dist/renderer.d.ts +3 -2
- package/dist/renderer.js +4 -19
- package/dist/standalone/index.d.ts +8 -2
- package/dist/standalone/index.js +32 -2
- package/dist/types.d.ts +6 -1
- package/dist/utils/input.d.ts +1 -46
- package/dist/utils/input.js +1 -89
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -51,10 +51,13 @@ ad add @actiondock/example-tools
|
|
|
51
51
|
|
|
52
52
|
- 本地执行 Action:
|
|
53
53
|
```bash
|
|
54
|
-
#
|
|
55
|
-
ad run sample.greet --
|
|
54
|
+
# 扁平参数赋值(规范语法,推荐)
|
|
55
|
+
ad run sample.greet -- name=Alice
|
|
56
56
|
|
|
57
|
-
#
|
|
57
|
+
# 传递 JSON 标量与结构(数值校验为有限数)
|
|
58
|
+
ad run sample.greet -- name=Alice count:=1
|
|
59
|
+
|
|
60
|
+
# 复杂参数或对象从文件读取(与扁平参数互斥)
|
|
58
61
|
ad run sample.greet --input-file input.json
|
|
59
62
|
|
|
60
63
|
# 自动化与脚本通过标准输入传递
|
|
@@ -109,20 +112,31 @@ ad pack
|
|
|
109
112
|
|
|
110
113
|
### Action 执行入参契约
|
|
111
114
|
|
|
112
|
-
执行 Action
|
|
113
|
-
|
|
114
|
-
-
|
|
115
|
-
-
|
|
116
|
-
-
|
|
117
|
-
-
|
|
118
|
-
-
|
|
119
|
-
-
|
|
115
|
+
执行 Action 推荐使用扁平参数赋值协议,同时支持传统选项,三者之间严格互斥:
|
|
116
|
+
|
|
117
|
+
- 规范调用语法:`ad run <action> [control-options] -- <assignments...>`。
|
|
118
|
+
- 协议边界:`--` 分隔符作为控制平面选项(如 `--json`、`--config`、`--data-dir`、`--profile` 等)与数据平面(Action 入参)的协议边界。
|
|
119
|
+
- 两种赋值操作符语义:
|
|
120
|
+
- `path=value`:严格保留为字符串,不执行 JSON 解析与类型猜测。
|
|
121
|
+
- `path:=json`:严格解析为 JSON 值,递归校验所有数值为有限数(`Number.isFinite`)。
|
|
122
|
+
- 路径语法规则:
|
|
123
|
+
- 命名段(`^[A-Za-z_][A-Za-z0-9_-]*$`)表示对象属性。
|
|
124
|
+
- 纯数字段(`^(0|[1-9][0-9]*)$`)表示数组索引,数组索引必须从 0 开始连续编号,拒绝稀疏数组。
|
|
125
|
+
- 根节点始终物化为对象。
|
|
126
|
+
- 路径冲突(叶节点与容器冲突、对象与数组冲突、重复赋值)严格拒绝(`INPUT_PATH_CONFLICT`)。
|
|
127
|
+
- 拦截原型污染敏感属性(`__proto__`、`constructor`、`prototype`)。
|
|
128
|
+
- 三种输入模式互斥:扁平参数、`--input` 与 `--input-file` 严格互斥,不可混用(`INPUT_CONFLICT`);未指定输入时默认为 `{}`。
|
|
129
|
+
- 传统输入选项:
|
|
130
|
+
- 简单内联参数:使用 `--input <json>` 直接解析 JSON 字符串。
|
|
131
|
+
- 复杂对象文件:使用 `--input-file <path>` 读取文件并解析 JSON,避免各类终端的引号转义损坏。
|
|
132
|
+
- 标准输入管道:使用 `--input-file -` 从标准输入读取全部数据并解析 JSON。
|
|
133
|
+
- 统一解析:解析前均自动剔除 UTF-8 BOM 标记,且不设人为大小上限。
|
|
120
134
|
|
|
121
135
|
### Windows 与多终端传参建议
|
|
122
136
|
|
|
123
137
|
针对 Windows PowerShell、cmd 以及各终端中复杂 JSON 容易遇到的双引号转义问题,推荐按以下规范传参:
|
|
124
138
|
|
|
125
|
-
-
|
|
139
|
+
- 扁平参数传参(推荐):使用 `--` 分隔并传参,如 `ad run greet -- name=Alice` 或 `ad run greet -- name=Alice count:=1`。
|
|
126
140
|
- 复杂结构:推荐先保存为 JSON 文件并使用 `--input-file`,如 `ad run complex-action --input-file input.json`。
|
|
127
141
|
- 动态生成输入:通过管道输出配合 `--input-file -` 传递,在 PowerShell 中可执行:
|
|
128
142
|
|
|
@@ -138,8 +152,8 @@ $data | ConvertTo-Json -Depth 100 | ad run complex-action --input-file -
|
|
|
138
152
|
|
|
139
153
|
### Action 输出模式与机器模式
|
|
140
154
|
|
|
141
|
-
- **默认原始纯文本输出**:`ad run` 默认采用面向终端人类阅读与 LLM Agent 上下文消费的原始输出模式。直接将执行结果正文内容(如文件 `content`、`text`、`message` 或标量字符串)输出至 stdout(保留真实换行且无 JSON 转义),相关元数据(如文件路径、行号范围、截断标记)独立输出至 stderr,符合 Unix
|
|
142
|
-
- **机器 JSON
|
|
155
|
+
- **默认原始纯文本输出**:`ad run` 默认采用面向终端人类阅读与 LLM Agent 上下文消费的原始输出模式。直接将执行结果正文内容(如文件 `content`、`text`、`message` 或标量字符串)输出至 stdout(保留真实换行且无 JSON 转义),相关元数据(如文件路径、行号范围、截断标记)独立输出至 stderr,符合 Unix 管道安全原则。业务执行失败时在 stderr 输出错误详情并以退出码 1 退出。
|
|
156
|
+
- **机器 JSON 格式**(`--json`):当需要以程序化方式消费、获取完整结构化数据或被外部系统集成时,传入 `--json`。面向智能体调用推荐使用该模式;此时输出标准 JSON 结果(包含 `ok`、`runId`、`data` 或 `error`);若参数解析出错输出标准错误信封并以退出码 2 退出。
|
|
143
157
|
|
|
144
158
|
---
|
|
145
159
|
|
|
@@ -152,8 +166,8 @@ $data | ConvertTo-Json -Depth 100 | ad run complex-action --input-file -
|
|
|
152
166
|
| `ad remove <package>` | 卸载并更新锁定依赖,提供原子回滚保护 |
|
|
153
167
|
| `ad info [patterns...]` | 检索包元数据与能力清单,支持模式匹配与树形展示 |
|
|
154
168
|
| `ad list [patterns...]` | 列出包内所有已注册的 Action |
|
|
155
|
-
| `ad describe <id>` |
|
|
156
|
-
| `ad run <id>` | 本地或远程执行指定 Action
|
|
169
|
+
| `ad describe <id>` | 编码顾问:查看 Action 的详情、模式字段明细、Flat 编码指引与建议赋值(别名 `ad show`) |
|
|
170
|
+
| `ad run <id>` | 本地或远程执行指定 Action(规范语法 `ad run <id> [options] -- <assignments...>`,支持 `--json` 输出标准信封) |
|
|
157
171
|
| `ad validate [id]` | 校验 Action 规范与模式规范 |
|
|
158
172
|
| `ad doctor` | 执行运行环境与项目结构健康诊断 |
|
|
159
173
|
| `ad action create <id>` | 创建新 Action 源码(别名 `ad action new`) |
|
package/bin/ad.js
CHANGED
|
@@ -8,8 +8,8 @@ import { fileURLToPath, pathToFileURL } from "node:url";
|
|
|
8
8
|
const distEntry = resolve(import.meta.dirname, "../dist/index.js");
|
|
9
9
|
|
|
10
10
|
if (existsSync(distEntry)) {
|
|
11
|
-
const {
|
|
12
|
-
await
|
|
11
|
+
const { runCliProcess } = await import(pathToFileURL(distEntry).href);
|
|
12
|
+
await runCliProcess(process.argv);
|
|
13
13
|
} else {
|
|
14
14
|
const isBun = typeof process.versions.bun !== "undefined";
|
|
15
15
|
const hasTsx =
|
|
@@ -37,6 +37,6 @@ if (existsSync(distEntry)) {
|
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
const {
|
|
41
|
-
await
|
|
40
|
+
const { runCliProcess } = await import("../src/index.ts");
|
|
41
|
+
await runCliProcess(process.argv);
|
|
42
42
|
}
|
|
@@ -202,27 +202,12 @@ ${returnBody}
|
|
|
202
202
|
saveManifest(root, manifest);
|
|
203
203
|
// 始终自动生成或更新类型声明文件,确保单一事实源即时生效
|
|
204
204
|
writeActionTypes(root, manifest);
|
|
205
|
-
let sampleInputStr = "{}";
|
|
206
|
-
const inputEntries = Object.entries(inputSchema.properties || {});
|
|
207
|
-
if (inputEntries.length > 0) {
|
|
208
|
-
const sampleObj = {};
|
|
209
|
-
for (const [k, prop] of inputEntries) {
|
|
210
|
-
if (prop.type === "number" || prop.type === "integer")
|
|
211
|
-
sampleObj[k] = 42;
|
|
212
|
-
else if (prop.type === "boolean")
|
|
213
|
-
sampleObj[k] = true;
|
|
214
|
-
else if (prop.type === "array")
|
|
215
|
-
sampleObj[k] = ["item"];
|
|
216
|
-
else if (prop.type === "object")
|
|
217
|
-
sampleObj[k] = {};
|
|
218
|
-
else
|
|
219
|
-
sampleObj[k] = "hello";
|
|
220
|
-
}
|
|
221
|
-
sampleInputStr = JSON.stringify(sampleObj);
|
|
222
|
-
}
|
|
223
205
|
writeStdout(`[OK] Created Action '${id}' at ${targetFullFile}`, context);
|
|
224
|
-
writeStdout(`\
|
|
225
|
-
writeStdout(` ad
|
|
206
|
+
writeStdout(`\n查阅参数契约:`, context);
|
|
207
|
+
writeStdout(` ad describe ${id}`, context);
|
|
208
|
+
writeStdout(`\n调用方式:`, context);
|
|
209
|
+
writeStdout(` 根据 describe 输出的赋值模板传递参数:ad run ${id} --json -- ASSIGNMENT...`, context);
|
|
210
|
+
writeStdout(` 复杂输入或大段文本:ad run ${id} --json --input-file input.json`, context);
|
|
226
211
|
}
|
|
227
212
|
catch (err) {
|
|
228
213
|
if (err instanceof ExecutionError)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { buildActionDescribePayload, formatActionDetail } from "@actiondock/core";
|
|
1
2
|
import { ArgumentError, ExecutionError, packageNotFoundError } from "../errors.js";
|
|
2
|
-
import {
|
|
3
|
+
import { renderResult } from "../renderer.js";
|
|
3
4
|
import { applyTargetOptions, getEffectiveOptions, resolveLocalPackageRoot, withTarget, } from "../utils/index.js";
|
|
4
5
|
/**
|
|
5
6
|
* 挂载 describe 子命令至指定 Commander 节点。
|
|
@@ -26,10 +27,7 @@ export function attachDescribeCommand(parent, context) {
|
|
|
26
27
|
if (options.package && !targetPackageRoot) {
|
|
27
28
|
throw packageNotFoundError(options.package);
|
|
28
29
|
}
|
|
29
|
-
|
|
30
|
-
if (options.package && !id.includes("/") && !id.includes(":")) {
|
|
31
|
-
targetRef = `${options.package}/${id}`;
|
|
32
|
-
}
|
|
30
|
+
const targetRef = id;
|
|
33
31
|
// 通过 Target 门面统一查询 Action 规范
|
|
34
32
|
await withTarget(options, context, async (target) => {
|
|
35
33
|
let spec;
|
|
@@ -43,20 +41,10 @@ export function attachDescribeCommand(parent, context) {
|
|
|
43
41
|
}
|
|
44
42
|
throw new ExecutionError(msg);
|
|
45
43
|
}
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
description: spec.description,
|
|
49
|
-
inputSchema: spec.inputSchema,
|
|
50
|
-
outputSchema: spec.outputSchema,
|
|
51
|
-
tags: spec.tags,
|
|
52
|
-
annotations: spec.annotations,
|
|
53
|
-
uses: spec.uses,
|
|
54
|
-
entry: spec.entry,
|
|
55
|
-
filePath: spec.filePath,
|
|
56
|
-
};
|
|
57
|
-
renderResult(detail, {
|
|
44
|
+
const payload = buildActionDescribePayload(spec);
|
|
45
|
+
renderResult(payload, {
|
|
58
46
|
json: options.json,
|
|
59
|
-
humanFormatter: () =>
|
|
47
|
+
humanFormatter: () => formatActionDetail(payload),
|
|
60
48
|
context,
|
|
61
49
|
});
|
|
62
50
|
}, { localRoot: targetPackageRoot || undefined, scanLinkedPackages: true });
|
package/dist/commands/run.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type InvocationControl } from "@actiondock/core";
|
|
1
2
|
import type { ExecutionResult } from "@actiondock/sdk";
|
|
2
3
|
import { Command } from "commander";
|
|
3
4
|
import type { CliContext } from "../types.js";
|
|
@@ -11,7 +12,7 @@ export declare function renderRawExecutionResult(targetRef: string, result: Exec
|
|
|
11
12
|
/**
|
|
12
13
|
* 统一执行 Action 核心逻辑(使用 ActionDockTarget 门面)。
|
|
13
14
|
*/
|
|
14
|
-
export declare function executeAction(id: string, options: any, context?: CliContext): Promise<void>;
|
|
15
|
+
export declare function executeAction(id: string, options: any, context?: CliContext, flatArgs?: string[], control?: InvocationControl): Promise<void>;
|
|
15
16
|
/**
|
|
16
17
|
* 挂载 run 子命令至指定 Commander 节点。
|
|
17
18
|
*
|
package/dist/commands/run.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { parseDuration, resolveTarget } from "@actiondock/core";
|
|
1
|
+
import { parseDuration, resolveTarget, validateActionInputValue, mapInputValidationFailure, } from "@actiondock/core";
|
|
2
2
|
import { ArgumentError, ExecutionError, SigintError, packageNotFoundError } from "../errors.js";
|
|
3
3
|
import { writeStderr, writeStdout } from "../renderer.js";
|
|
4
4
|
import { applyTargetOptions, getEffectiveOptions, resolveActionInput, resolveLocalPackageRoot, withTarget, } from "../utils/index.js";
|
|
@@ -86,21 +86,34 @@ export function renderRawExecutionResult(targetRef, result, context) {
|
|
|
86
86
|
? result.error.details
|
|
87
87
|
: JSON.stringify(result.error.details, null, 2), context);
|
|
88
88
|
}
|
|
89
|
-
|
|
89
|
+
if (context) {
|
|
90
|
+
context.exitCode = 1;
|
|
91
|
+
}
|
|
92
|
+
if (!context?.control) {
|
|
93
|
+
process.exitCode = 1;
|
|
94
|
+
}
|
|
90
95
|
}
|
|
91
96
|
}
|
|
92
97
|
/**
|
|
93
98
|
* 统一执行 Action 核心逻辑(使用 ActionDockTarget 门面)。
|
|
94
99
|
*/
|
|
95
|
-
export async function executeAction(id, options, context) {
|
|
100
|
+
export async function executeAction(id, options, context, flatArgs, control) {
|
|
96
101
|
if (!id) {
|
|
97
102
|
throw new ArgumentError("Action ID is required for run");
|
|
98
103
|
}
|
|
104
|
+
const effectiveControl = control ?? context?.control;
|
|
105
|
+
const effectiveSignal = effectiveControl?.signal;
|
|
106
|
+
const effectiveFlatArgs = flatArgs ?? options.flatArgs;
|
|
99
107
|
const input = await resolveActionInput({
|
|
100
108
|
input: options.input,
|
|
101
109
|
inputFile: options.inputFile,
|
|
110
|
+
flatArgs: effectiveFlatArgs && effectiveFlatArgs.length > 0 ? effectiveFlatArgs : undefined,
|
|
102
111
|
stdin: context?.stdin,
|
|
103
112
|
});
|
|
113
|
+
const check = validateActionInputValue(input);
|
|
114
|
+
if (!check.valid) {
|
|
115
|
+
throw mapInputValidationFailure("cli-pre-target", check);
|
|
116
|
+
}
|
|
104
117
|
let timeoutMs;
|
|
105
118
|
if (options.timeout) {
|
|
106
119
|
try {
|
|
@@ -119,13 +132,6 @@ export async function executeAction(id, options, context) {
|
|
|
119
132
|
configOverrides[k] = v.join("=");
|
|
120
133
|
}
|
|
121
134
|
}
|
|
122
|
-
const controller = new AbortController();
|
|
123
|
-
let receivedSigint = false;
|
|
124
|
-
const sigintHandler = () => {
|
|
125
|
-
receivedSigint = true;
|
|
126
|
-
controller.abort(new Error("Interrupted by SIGINT"));
|
|
127
|
-
};
|
|
128
|
-
process.once("SIGINT", sigintHandler);
|
|
129
135
|
try {
|
|
130
136
|
// 异步执行仅支持远端目标,本地模式直接拒绝
|
|
131
137
|
const resolvedTopology = resolveTarget({
|
|
@@ -151,7 +157,7 @@ export async function executeAction(id, options, context) {
|
|
|
151
157
|
const isMachine = Boolean(options.json);
|
|
152
158
|
if (options.async) {
|
|
153
159
|
const ticket = await target.startAction(targetRef, input, {
|
|
154
|
-
signal:
|
|
160
|
+
signal: effectiveSignal,
|
|
155
161
|
timeoutMs,
|
|
156
162
|
config: configOverrides,
|
|
157
163
|
requestId: options.requestId,
|
|
@@ -169,17 +175,23 @@ export async function executeAction(id, options, context) {
|
|
|
169
175
|
writeStdout(ticket.runId, context);
|
|
170
176
|
}
|
|
171
177
|
if (ticket.status === "failed") {
|
|
172
|
-
|
|
178
|
+
if (context) {
|
|
179
|
+
context.exitCode = 1;
|
|
180
|
+
}
|
|
173
181
|
return;
|
|
174
182
|
}
|
|
175
183
|
}
|
|
176
184
|
else {
|
|
177
185
|
const result = await target.runAction(targetRef, input, {
|
|
178
|
-
signal:
|
|
186
|
+
signal: effectiveSignal,
|
|
179
187
|
timeoutMs,
|
|
180
188
|
config: configOverrides,
|
|
181
189
|
requestId: options.requestId,
|
|
182
190
|
});
|
|
191
|
+
if (effectiveControl?.cancellationSource === "sigint" &&
|
|
192
|
+
(effectiveSignal?.aborted || (!result.ok && result.error?.code === "ACTION_CANCELLED"))) {
|
|
193
|
+
throw new SigintError();
|
|
194
|
+
}
|
|
183
195
|
if (isMachine) {
|
|
184
196
|
writeStdout(JSON.stringify(result, null, 2), context);
|
|
185
197
|
}
|
|
@@ -187,21 +199,23 @@ export async function executeAction(id, options, context) {
|
|
|
187
199
|
renderRawExecutionResult(targetRef, result, context);
|
|
188
200
|
}
|
|
189
201
|
if (!result.ok) {
|
|
190
|
-
|
|
202
|
+
if (context) {
|
|
203
|
+
context.exitCode = 1;
|
|
204
|
+
}
|
|
191
205
|
return;
|
|
192
206
|
}
|
|
193
207
|
}
|
|
194
208
|
}, { localRoot: targetPackageRoot || undefined, scanLinkedPackages: true, ownDataDir: true });
|
|
195
209
|
}
|
|
196
210
|
catch (err) {
|
|
197
|
-
|
|
211
|
+
const isSigint = effectiveControl?.cancellationSource === "sigint" ||
|
|
212
|
+
err?.message?.includes("Interrupted by SIGINT");
|
|
213
|
+
if (isSigint &&
|
|
214
|
+
(err?.name === "AbortError" || effectiveSignal?.aborted || err?.message?.includes("SIGINT") || err instanceof SigintError)) {
|
|
198
215
|
throw new SigintError();
|
|
199
216
|
}
|
|
200
217
|
throw err;
|
|
201
218
|
}
|
|
202
|
-
finally {
|
|
203
|
-
process.removeListener("SIGINT", sigintHandler);
|
|
204
|
-
}
|
|
205
219
|
}
|
|
206
220
|
/**
|
|
207
221
|
* 挂载 run 子命令至指定 Commander 节点。
|
|
@@ -211,7 +225,7 @@ export async function executeAction(id, options, context) {
|
|
|
211
225
|
*/
|
|
212
226
|
export function attachRunCommand(parent, context) {
|
|
213
227
|
const cmd = parent
|
|
214
|
-
.command("run <id>")
|
|
228
|
+
.command("run <id> [params...]")
|
|
215
229
|
.description("Execute an action (from current project, linked packages, or remote profile)")
|
|
216
230
|
.option("-P, --package <id>", "Target package ID or path")
|
|
217
231
|
.option("-i, --input <json>", "Action input as inline JSON")
|
|
@@ -223,9 +237,19 @@ export function attachRunCommand(parent, context) {
|
|
|
223
237
|
.option("--async", "Execute asynchronously in background (requires remote server or profile)")
|
|
224
238
|
.option("--data-dir <path>", "Custom database directory")
|
|
225
239
|
.option("--json", "Output as JSON")
|
|
226
|
-
.action(async (id, rawOptions, cmd) => {
|
|
227
|
-
|
|
228
|
-
|
|
240
|
+
.action(async (id, params, rawOptions, cmd) => {
|
|
241
|
+
let flatArgs;
|
|
242
|
+
let effectiveRawOptions = rawOptions;
|
|
243
|
+
let effectiveCmd = cmd;
|
|
244
|
+
if (Array.isArray(params)) {
|
|
245
|
+
flatArgs = params.length > 0 ? params : undefined;
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
effectiveCmd = rawOptions;
|
|
249
|
+
effectiveRawOptions = params;
|
|
250
|
+
}
|
|
251
|
+
const options = getEffectiveOptions(effectiveRawOptions, effectiveCmd);
|
|
252
|
+
await executeAction(id, { ...options, flatArgs }, context, undefined, context?.control);
|
|
229
253
|
});
|
|
230
254
|
}
|
|
231
255
|
/**
|
package/dist/errors.js
CHANGED
|
@@ -1,4 +1,20 @@
|
|
|
1
|
+
import { InputError, INVALID_FLAT_ARGUMENT, INVALID_JSON, INVALID_JSON_LITERAL, INPUT_PATH_CONFLICT, FLAT_INPUT_LIMIT_EXCEEDED, INPUT_LIMIT_EXCEEDED, INPUT_POLICY_VIOLATION, INPUT_CONFLICT, INPUT_FILE_NOT_FOUND, INPUT_FILE_READ_FAILED, } from "@actiondock/core";
|
|
1
2
|
import { ExitCode } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* 扁平与解析输入错误码集合。
|
|
5
|
+
*/
|
|
6
|
+
const FLAT_ERROR_CODES = new Set([
|
|
7
|
+
INVALID_FLAT_ARGUMENT,
|
|
8
|
+
INVALID_JSON,
|
|
9
|
+
INVALID_JSON_LITERAL,
|
|
10
|
+
INPUT_PATH_CONFLICT,
|
|
11
|
+
FLAT_INPUT_LIMIT_EXCEEDED,
|
|
12
|
+
INPUT_LIMIT_EXCEEDED,
|
|
13
|
+
INPUT_POLICY_VIOLATION,
|
|
14
|
+
INPUT_CONFLICT,
|
|
15
|
+
INPUT_FILE_NOT_FOUND,
|
|
16
|
+
INPUT_FILE_READ_FAILED,
|
|
17
|
+
]);
|
|
2
18
|
/**
|
|
3
19
|
* CLI 信封错误码常量(仅 CLI 输出协议使用,属包内部码,就地常量化管理)。
|
|
4
20
|
*/
|
|
@@ -80,10 +96,26 @@ export function formatError(err) {
|
|
|
80
96
|
details: err.details,
|
|
81
97
|
};
|
|
82
98
|
}
|
|
99
|
+
if (err instanceof InputError) {
|
|
100
|
+
return {
|
|
101
|
+
code: err.code,
|
|
102
|
+
message: err.message,
|
|
103
|
+
exitCode: ExitCode.INVALID_ARGUMENT,
|
|
104
|
+
details: err.details,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
83
107
|
// Commander.js 原生错误处理
|
|
84
108
|
if (typeof err === "object" && err !== null && "code" in err && typeof err.code === "string") {
|
|
109
|
+
const code = err.code;
|
|
110
|
+
if (FLAT_ERROR_CODES.has(code)) {
|
|
111
|
+
return {
|
|
112
|
+
code,
|
|
113
|
+
message: err.message || String(err),
|
|
114
|
+
exitCode: ExitCode.INVALID_ARGUMENT,
|
|
115
|
+
details: err.details,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
85
118
|
const commanderErr = err;
|
|
86
|
-
const code = commanderErr.code;
|
|
87
119
|
// 参数类异常
|
|
88
120
|
if (code.startsWith("commander.unknownOption") ||
|
|
89
121
|
code.startsWith("commander.missingArgument") ||
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type InvocationControl } from "./types.js";
|
|
1
2
|
export * from "./types.js";
|
|
2
3
|
export * from "./errors.js";
|
|
3
4
|
export * from "./renderer.js";
|
|
@@ -10,6 +11,12 @@ export * from "./commands/index.js";
|
|
|
10
11
|
* ActionDock CLI 主执行入口函数。
|
|
11
12
|
*
|
|
12
13
|
* @param argv 命令行参数数组(默认使用 process.argv)
|
|
14
|
+
* @param control 可选的中断与取消控制契约
|
|
13
15
|
* @returns 进程退出码
|
|
14
16
|
*/
|
|
15
|
-
export declare function main(argv?: string[]): Promise<number>;
|
|
17
|
+
export declare function main(argv?: string[], control?: InvocationControl): Promise<number>;
|
|
18
|
+
/**
|
|
19
|
+
* 命令行独立进程适配器。
|
|
20
|
+
* 仅在命令行可执行入口调用,负责全局 SIGINT 监听与退出状态码写入。
|
|
21
|
+
*/
|
|
22
|
+
export declare function runCliProcess(argv?: string[]): Promise<void>;
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { CommanderError } from "commander";
|
|
2
2
|
import { createCliProgram } from "./commands/index.js";
|
|
3
|
-
import { formatError } from "./errors.js";
|
|
3
|
+
import { formatError, SigintError } from "./errors.js";
|
|
4
4
|
import { renderError } from "./renderer.js";
|
|
5
|
+
import { ExitCode } from "./types.js";
|
|
5
6
|
export * from "./types.js";
|
|
6
7
|
export * from "./errors.js";
|
|
7
8
|
export * from "./renderer.js";
|
|
@@ -14,16 +15,37 @@ export * from "./commands/index.js";
|
|
|
14
15
|
* ActionDock CLI 主执行入口函数。
|
|
15
16
|
*
|
|
16
17
|
* @param argv 命令行参数数组(默认使用 process.argv)
|
|
18
|
+
* @param control 可选的中断与取消控制契约
|
|
17
19
|
* @returns 进程退出码
|
|
18
20
|
*/
|
|
19
|
-
export async function main(argv = process.argv) {
|
|
20
|
-
const
|
|
21
|
+
export async function main(argv = process.argv, control) {
|
|
22
|
+
const context = { control, exitCode: 0 };
|
|
23
|
+
const program = createCliProgram(context);
|
|
21
24
|
const isMachine = argv.includes("--json");
|
|
25
|
+
const normalizedArgv = argv.length >= 2 &&
|
|
26
|
+
(argv[0].endsWith("node") ||
|
|
27
|
+
argv[0].endsWith("bun") ||
|
|
28
|
+
argv[0].endsWith("tsx") ||
|
|
29
|
+
argv[1].includes("/") ||
|
|
30
|
+
argv[1].includes("\\") ||
|
|
31
|
+
argv[1].endsWith(".js") ||
|
|
32
|
+
argv[1].endsWith(".ts"))
|
|
33
|
+
? argv
|
|
34
|
+
: ["node", "ad", ...argv];
|
|
22
35
|
try {
|
|
23
|
-
await program.parseAsync(
|
|
24
|
-
|
|
36
|
+
await program.parseAsync(normalizedArgv);
|
|
37
|
+
if (control?.cancellationSource === "sigint" && control?.signal?.aborted) {
|
|
38
|
+
return ExitCode.SIGINT;
|
|
39
|
+
}
|
|
40
|
+
return (context.exitCode && context.exitCode !== 0)
|
|
41
|
+
? context.exitCode
|
|
42
|
+
: (typeof process.exitCode === "number" ? process.exitCode : 0);
|
|
25
43
|
}
|
|
26
44
|
catch (err) {
|
|
45
|
+
if (control?.cancellationSource === "sigint" &&
|
|
46
|
+
(control?.signal?.aborted || err?.name === "AbortError" || err?.message?.includes("SIGINT") || err instanceof SigintError)) {
|
|
47
|
+
return ExitCode.SIGINT;
|
|
48
|
+
}
|
|
27
49
|
if (err instanceof CommanderError) {
|
|
28
50
|
if (err.exitCode === 0) {
|
|
29
51
|
return 0;
|
|
@@ -32,9 +54,39 @@ export async function main(argv = process.argv) {
|
|
|
32
54
|
// 复用 renderer 的 renderError 统一错误信封,消除手工拼装的双实现
|
|
33
55
|
renderError(err, {
|
|
34
56
|
json: isMachine,
|
|
57
|
+
context,
|
|
35
58
|
});
|
|
36
|
-
|
|
37
|
-
|
|
59
|
+
return formatError(err).exitCode;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* 命令行独立进程适配器。
|
|
64
|
+
* 仅在命令行可执行入口调用,负责全局 SIGINT 监听与退出状态码写入。
|
|
65
|
+
*/
|
|
66
|
+
export async function runCliProcess(argv = process.argv) {
|
|
67
|
+
const controller = new AbortController();
|
|
68
|
+
const control = {
|
|
69
|
+
signal: controller.signal,
|
|
70
|
+
};
|
|
71
|
+
let sigintCount = 0;
|
|
72
|
+
const sigintHandler = () => {
|
|
73
|
+
sigintCount++;
|
|
74
|
+
if (sigintCount === 1) {
|
|
75
|
+
control.cancellationSource = "sigint";
|
|
76
|
+
controller.abort(new Error("Interrupted by SIGINT"));
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
process.exitCode = 130;
|
|
80
|
+
process.exit(130);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
process.on("SIGINT", sigintHandler);
|
|
84
|
+
try {
|
|
85
|
+
const exitCode = await main(argv, control);
|
|
86
|
+
process.exitCode = exitCode;
|
|
87
|
+
}
|
|
88
|
+
finally {
|
|
89
|
+
process.removeListener("SIGINT", sigintHandler);
|
|
38
90
|
}
|
|
39
91
|
}
|
|
40
92
|
import { fileURLToPath } from "node:url";
|
|
@@ -42,7 +94,7 @@ import { resolve } from "node:path";
|
|
|
42
94
|
const isDirectRun = Boolean(process.argv[1]) &&
|
|
43
95
|
resolve(process.argv[1]) === fileURLToPath(import.meta.url);
|
|
44
96
|
if (isDirectRun) {
|
|
45
|
-
|
|
97
|
+
runCliProcess().catch((err) => {
|
|
46
98
|
console.error("Fatal error:", err);
|
|
47
99
|
process.exitCode = 1;
|
|
48
100
|
});
|
package/dist/renderer.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { RunRecord } from "@actiondock/sdk";
|
|
2
|
-
import type
|
|
2
|
+
import { type RegistryStatusReport } from "@actiondock/core";
|
|
3
3
|
import type { Envelope, ProjectDetailInfo, AggregatedPackage, EnvCheckItem, CliContext } from "./types.js";
|
|
4
4
|
/**
|
|
5
5
|
* 构造标准成功结果信封。
|
|
@@ -112,7 +112,8 @@ export declare function renderActionList(items: Array<{
|
|
|
112
112
|
packageId?: string;
|
|
113
113
|
}>, title?: string, isFallback?: boolean, intent?: string): string;
|
|
114
114
|
/**
|
|
115
|
-
* 格式化渲染 Action
|
|
115
|
+
* 格式化渲染 Action 详情(编码顾问 Encoding Advisor)。
|
|
116
|
+
* 统一复用 core 下沉的 formatActionDetail 实现,与独立分发器保持完全一致。
|
|
116
117
|
*/
|
|
117
118
|
export declare function renderActionDetail(action: {
|
|
118
119
|
id: string;
|
package/dist/renderer.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { formatActionDetail } from "@actiondock/core";
|
|
1
2
|
import { formatError } from "./errors.js";
|
|
2
3
|
/**
|
|
3
4
|
* 构造标准成功结果信封。
|
|
@@ -254,27 +255,11 @@ export function renderActionList(items, title = "Actions", isFallback = false, i
|
|
|
254
255
|
return lines.join("\n");
|
|
255
256
|
}
|
|
256
257
|
/**
|
|
257
|
-
* 格式化渲染 Action
|
|
258
|
+
* 格式化渲染 Action 详情(编码顾问 Encoding Advisor)。
|
|
259
|
+
* 统一复用 core 下沉的 formatActionDetail 实现,与独立分发器保持完全一致。
|
|
258
260
|
*/
|
|
259
261
|
export function renderActionDetail(action) {
|
|
260
|
-
|
|
261
|
-
lines.push(`Action: ${action.id}`);
|
|
262
|
-
if (action.packageId) {
|
|
263
|
-
const rootDesc = action.projectRoot ? ` (${action.projectRoot})` : "";
|
|
264
|
-
lines.push(`Package: ${action.packageId}${rootDesc}`);
|
|
265
|
-
}
|
|
266
|
-
if (action.description) {
|
|
267
|
-
lines.push(`Description: ${action.description}`);
|
|
268
|
-
}
|
|
269
|
-
if (action.inputSchema) {
|
|
270
|
-
lines.push("\nInput Schema:");
|
|
271
|
-
lines.push(JSON.stringify(action.inputSchema, null, 2));
|
|
272
|
-
}
|
|
273
|
-
if (action.outputSchema) {
|
|
274
|
-
lines.push("\nOutput Schema:");
|
|
275
|
-
lines.push(JSON.stringify(action.outputSchema, null, 2));
|
|
276
|
-
}
|
|
277
|
-
return lines.join("\n");
|
|
262
|
+
return formatActionDetail(action);
|
|
278
263
|
}
|
|
279
264
|
/**
|
|
280
265
|
* 格式化渲染 Action 校验结果。
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { StandaloneDispatcher as CoreStandaloneDispatcher } from "@actiondock/core";
|
|
1
|
+
import { StandaloneDispatcher as CoreStandaloneDispatcher, type InvocationControl } from "@actiondock/core";
|
|
2
2
|
import type { StandaloneOptions } from "../types.js";
|
|
3
|
+
export { type InvocationControl };
|
|
3
4
|
/**
|
|
4
5
|
* 独立二进制轻量参数解析分发器(委托 Core 统一实现,消除重复逻辑)。
|
|
5
6
|
*/
|
|
@@ -9,8 +10,13 @@ export declare class StandaloneDispatcher extends CoreStandaloneDispatcher {
|
|
|
9
10
|
/**
|
|
10
11
|
* 运行独立二进制参数解析分发器并返回退出状态码。
|
|
11
12
|
*/
|
|
12
|
-
export declare function runStandaloneCli(argv: string[] | undefined, options: StandaloneOptions): Promise<number>;
|
|
13
|
+
export declare function runStandaloneCli(argv: string[] | undefined, options: StandaloneOptions, control?: InvocationControl): Promise<number>;
|
|
13
14
|
/**
|
|
14
15
|
* 创建独立二进制运行时分发器实例。
|
|
15
16
|
*/
|
|
16
17
|
export declare function createStandaloneDispatcher(options: StandaloneOptions): StandaloneDispatcher;
|
|
18
|
+
/**
|
|
19
|
+
* 独立二进制进程入口适配器。
|
|
20
|
+
* 仅在命令行可执行入口调用,负责全局 SIGINT 监听与退出状态码写入。
|
|
21
|
+
*/
|
|
22
|
+
export declare function runStandaloneProcess(argv: string[] | undefined, options: StandaloneOptions): Promise<void>;
|
package/dist/standalone/index.js
CHANGED
|
@@ -10,9 +10,9 @@ export class StandaloneDispatcher extends CoreStandaloneDispatcher {
|
|
|
10
10
|
/**
|
|
11
11
|
* 运行独立二进制参数解析分发器并返回退出状态码。
|
|
12
12
|
*/
|
|
13
|
-
export async function runStandaloneCli(argv = process.argv.slice(2), options) {
|
|
13
|
+
export async function runStandaloneCli(argv = process.argv.slice(2), options, control) {
|
|
14
14
|
const dispatcher = new StandaloneDispatcher(options);
|
|
15
|
-
return dispatcher.dispatch(argv);
|
|
15
|
+
return dispatcher.dispatch(argv, control);
|
|
16
16
|
}
|
|
17
17
|
/**
|
|
18
18
|
* 创建独立二进制运行时分发器实例。
|
|
@@ -20,3 +20,33 @@ export async function runStandaloneCli(argv = process.argv.slice(2), options) {
|
|
|
20
20
|
export function createStandaloneDispatcher(options) {
|
|
21
21
|
return new StandaloneDispatcher(options);
|
|
22
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* 独立二进制进程入口适配器。
|
|
25
|
+
* 仅在命令行可执行入口调用,负责全局 SIGINT 监听与退出状态码写入。
|
|
26
|
+
*/
|
|
27
|
+
export async function runStandaloneProcess(argv = process.argv.slice(2), options) {
|
|
28
|
+
const controller = new AbortController();
|
|
29
|
+
const control = {
|
|
30
|
+
signal: controller.signal,
|
|
31
|
+
};
|
|
32
|
+
let sigintCount = 0;
|
|
33
|
+
const sigintHandler = () => {
|
|
34
|
+
sigintCount++;
|
|
35
|
+
if (sigintCount === 1) {
|
|
36
|
+
control.cancellationSource = "sigint";
|
|
37
|
+
controller.abort(new Error("Interrupted by SIGINT"));
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
process.exitCode = 130;
|
|
41
|
+
process.exit(130);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
process.on("SIGINT", sigintHandler);
|
|
45
|
+
try {
|
|
46
|
+
const exitCode = await runStandaloneCli(argv, options, control);
|
|
47
|
+
process.exitCode = exitCode;
|
|
48
|
+
}
|
|
49
|
+
finally {
|
|
50
|
+
process.removeListener("SIGINT", sigintHandler);
|
|
51
|
+
}
|
|
52
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ActionDefinition } from "@actiondock/sdk";
|
|
2
|
-
import type { ConfigItemDefinition } from "@actiondock/core";
|
|
2
|
+
import type { ConfigItemDefinition, InvocationControl } from "@actiondock/core";
|
|
3
|
+
export type { InvocationControl };
|
|
3
4
|
/**
|
|
4
5
|
* 统一退出码定义(事实源位于 core 包 StandaloneDispatcher,此处仅 re-export 维持既有导入路径兼容)。
|
|
5
6
|
* - SUCCESS: 执行成功(0)
|
|
@@ -78,6 +79,10 @@ export interface CliContext {
|
|
|
78
79
|
secret?: boolean;
|
|
79
80
|
mask?: string;
|
|
80
81
|
}) => Promise<string>;
|
|
82
|
+
/** 可选的中断与取消控制契约 */
|
|
83
|
+
control?: InvocationControl;
|
|
84
|
+
/** 退出码收集器(避免污染全局 process.exitCode) */
|
|
85
|
+
exitCode?: number;
|
|
81
86
|
}
|
|
82
87
|
/**
|
|
83
88
|
* 工程自省详情信息结构。
|
package/dist/utils/input.d.ts
CHANGED
|
@@ -1,46 +1 @@
|
|
|
1
|
-
|
|
2
|
-
/**
|
|
3
|
-
* 获取异常的标准描述信息。
|
|
4
|
-
*
|
|
5
|
-
* @param err 待提取消息的异常对象
|
|
6
|
-
*/
|
|
7
|
-
export declare function getErrorMessage(err: unknown): string;
|
|
8
|
-
/**
|
|
9
|
-
* 剔除 UTF-8 文本起始处的 BOM 字节标记(\uFEFF)。
|
|
10
|
-
*
|
|
11
|
-
* @param text 原始输入文本
|
|
12
|
-
*/
|
|
13
|
-
export declare function stripBom(text: string): string;
|
|
14
|
-
/**
|
|
15
|
-
* 统一解析 JSON 字符串为标准 JSON 值对象,并在失败时抛出结构化参数异常。
|
|
16
|
-
*
|
|
17
|
-
* @param text 待解析文本内容
|
|
18
|
-
* @param source 输入源描述(如 "--input"、"stdin" 或文件物理路径)
|
|
19
|
-
*/
|
|
20
|
-
export declare function parseJson(text: string, source: string): JsonValue;
|
|
21
|
-
/**
|
|
22
|
-
* 从标准输入流中完整读取全部数据并转换为 UTF-8 字符串。
|
|
23
|
-
*
|
|
24
|
-
* @param stream 标准输入可读流,默认为 process.stdin
|
|
25
|
-
*/
|
|
26
|
-
export declare function readStdin(stream?: NodeJS.ReadableStream): Promise<string>;
|
|
27
|
-
/**
|
|
28
|
-
* Action 执行输入解析选项。
|
|
29
|
-
*/
|
|
30
|
-
export interface ResolveActionInputOptions {
|
|
31
|
-
input?: string;
|
|
32
|
-
inputFile?: string;
|
|
33
|
-
stdin?: NodeJS.ReadableStream;
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* 统一解析 Action 执行入参。
|
|
37
|
-
*
|
|
38
|
-
* 遵循确定性入参契约:
|
|
39
|
-
* - 当未指定任何输入参数时,默认返回空对象 `{}`。
|
|
40
|
-
* - 简单输入通过 `--input` 传递内联 JSON 字符串。
|
|
41
|
-
* - 复杂输入或标准输入通过 `--input-file` 传递(`-` 表示标准输入 stdin)。
|
|
42
|
-
* - 严禁同时指定 `--input` 与 `--input-file`,检测到冲突时明确抛出参数错误。
|
|
43
|
-
*
|
|
44
|
-
* @param options 输入解析选项
|
|
45
|
-
*/
|
|
46
|
-
export declare function resolveActionInput(options: ResolveActionInputOptions): Promise<JsonValue>;
|
|
1
|
+
export { resolveActionInput, type ResolveActionInputOptions, parseJson, readStdin, stripBom, InputError, FlatInputError, buildActionInputAdvice, formatActionDetail, } from "@actiondock/core";
|
package/dist/utils/input.js
CHANGED
|
@@ -1,89 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { ArgumentError } from "../errors.js";
|
|
3
|
-
/**
|
|
4
|
-
* 获取异常的标准描述信息。
|
|
5
|
-
*
|
|
6
|
-
* @param err 待提取消息的异常对象
|
|
7
|
-
*/
|
|
8
|
-
export function getErrorMessage(err) {
|
|
9
|
-
if (err instanceof Error) {
|
|
10
|
-
return err.message;
|
|
11
|
-
}
|
|
12
|
-
return String(err);
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* 剔除 UTF-8 文本起始处的 BOM 字节标记(\uFEFF)。
|
|
16
|
-
*
|
|
17
|
-
* @param text 原始输入文本
|
|
18
|
-
*/
|
|
19
|
-
export function stripBom(text) {
|
|
20
|
-
return text.replace(/^\uFEFF/, "");
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* 统一解析 JSON 字符串为标准 JSON 值对象,并在失败时抛出结构化参数异常。
|
|
24
|
-
*
|
|
25
|
-
* @param text 待解析文本内容
|
|
26
|
-
* @param source 输入源描述(如 "--input"、"stdin" 或文件物理路径)
|
|
27
|
-
*/
|
|
28
|
-
export function parseJson(text, source) {
|
|
29
|
-
try {
|
|
30
|
-
return JSON.parse(stripBom(text));
|
|
31
|
-
}
|
|
32
|
-
catch (err) {
|
|
33
|
-
throw new ArgumentError(`Invalid JSON input from ${source}: ${getErrorMessage(err)}`, undefined, "INVALID_JSON");
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* 从标准输入流中完整读取全部数据并转换为 UTF-8 字符串。
|
|
38
|
-
*
|
|
39
|
-
* @param stream 标准输入可读流,默认为 process.stdin
|
|
40
|
-
*/
|
|
41
|
-
export async function readStdin(stream = process.stdin) {
|
|
42
|
-
const chunks = [];
|
|
43
|
-
for await (const chunk of stream) {
|
|
44
|
-
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
45
|
-
}
|
|
46
|
-
return Buffer.concat(chunks).toString("utf8");
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* 统一解析 Action 执行入参。
|
|
50
|
-
*
|
|
51
|
-
* 遵循确定性入参契约:
|
|
52
|
-
* - 当未指定任何输入参数时,默认返回空对象 `{}`。
|
|
53
|
-
* - 简单输入通过 `--input` 传递内联 JSON 字符串。
|
|
54
|
-
* - 复杂输入或标准输入通过 `--input-file` 传递(`-` 表示标准输入 stdin)。
|
|
55
|
-
* - 严禁同时指定 `--input` 与 `--input-file`,检测到冲突时明确抛出参数错误。
|
|
56
|
-
*
|
|
57
|
-
* @param options 输入解析选项
|
|
58
|
-
*/
|
|
59
|
-
export async function resolveActionInput(options) {
|
|
60
|
-
if (options.input !== undefined && options.inputFile !== undefined) {
|
|
61
|
-
throw new ArgumentError("--input and --input-file cannot be used together", undefined, "INPUT_CONFLICT");
|
|
62
|
-
}
|
|
63
|
-
if (options.input !== undefined) {
|
|
64
|
-
return parseJson(options.input, "--input");
|
|
65
|
-
}
|
|
66
|
-
if (options.inputFile !== undefined) {
|
|
67
|
-
let text;
|
|
68
|
-
if (options.inputFile === "-") {
|
|
69
|
-
try {
|
|
70
|
-
text = await readStdin(options.stdin || process.stdin);
|
|
71
|
-
}
|
|
72
|
-
catch (err) {
|
|
73
|
-
throw new ArgumentError(`Failed to read stdin: ${getErrorMessage(err)}`, undefined, "INPUT_FILE_READ_FAILED");
|
|
74
|
-
}
|
|
75
|
-
return parseJson(text, "stdin");
|
|
76
|
-
}
|
|
77
|
-
try {
|
|
78
|
-
text = await readFile(options.inputFile, "utf8");
|
|
79
|
-
}
|
|
80
|
-
catch (err) {
|
|
81
|
-
if (err && err.code === "ENOENT") {
|
|
82
|
-
throw new ArgumentError(`Input file not found: ${options.inputFile}`, undefined, "INPUT_FILE_NOT_FOUND");
|
|
83
|
-
}
|
|
84
|
-
throw new ArgumentError(`Failed to read input file '${options.inputFile}': ${getErrorMessage(err)}`, undefined, "INPUT_FILE_READ_FAILED");
|
|
85
|
-
}
|
|
86
|
-
return parseJson(text, options.inputFile);
|
|
87
|
-
}
|
|
88
|
-
return {};
|
|
89
|
-
}
|
|
1
|
+
export { resolveActionInput, parseJson, readStdin, stripBom, InputError, FlatInputError, buildActionInputAdvice, formatActionDetail, } from "@actiondock/core";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@actiondock/cli",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.0",
|
|
4
4
|
"description": "ActionDock CLI facade for developing, testing, building, and exporting standalone Agent Actions and Skills",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -34,11 +34,11 @@
|
|
|
34
34
|
"test": "node ../../scripts/run-tests.ts"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@actiondock/builder": "^2.
|
|
38
|
-
"@actiondock/core": "^2.
|
|
39
|
-
"@actiondock/mcp": "^2.
|
|
40
|
-
"@actiondock/runtime-node": "^2.
|
|
41
|
-
"@actiondock/sdk": "^2.
|
|
37
|
+
"@actiondock/builder": "^2.7.0",
|
|
38
|
+
"@actiondock/core": "^2.7.0",
|
|
39
|
+
"@actiondock/mcp": "^2.7.0",
|
|
40
|
+
"@actiondock/runtime-node": "^2.7.0",
|
|
41
|
+
"@actiondock/sdk": "^2.7.0",
|
|
42
42
|
"commander": "^13.1.0",
|
|
43
43
|
"selfsigned": "^5.5.0"
|
|
44
44
|
},
|