@actiondock/cli 2.9.1 → 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.
- package/README.md +3 -3
- package/bin/ad.js +225 -5
- package/dist/commands/action/create.d.ts +1 -1
- package/dist/commands/action/create.js +6 -14
- package/dist/commands/add.js +1 -1
- package/dist/commands/config/delete.js +3 -1
- package/dist/commands/config/env.js +2 -1
- package/dist/commands/config/get.js +3 -1
- package/dist/commands/config/list.js +6 -5
- package/dist/commands/config/schema.js +16 -10
- package/dist/commands/config/set.js +3 -1
- package/dist/commands/describe.js +6 -4
- package/dist/commands/export.js +34 -16
- package/dist/commands/index.d.ts +37 -24
- package/dist/commands/index.js +346 -48
- package/dist/commands/info.js +34 -9
- package/dist/commands/list.js +13 -2
- package/dist/commands/mcp.js +0 -1
- package/dist/commands/playbook.js +67 -52
- package/dist/commands/profile.js +2 -1
- package/dist/commands/remove.js +1 -1
- package/dist/commands/run.d.ts +2 -1
- package/dist/commands/run.js +19 -56
- package/dist/commands/runs.d.ts +6 -1
- package/dist/commands/runs.js +274 -11
- package/dist/commands/serve.js +5 -2
- package/dist/commands/state.js +84 -15
- package/dist/errors.d.ts +5 -3
- package/dist/errors.js +23 -7
- package/dist/index.d.ts +10 -2
- package/dist/index.js +15 -12
- package/dist/prompt.d.ts +3 -0
- package/dist/prompt.js +6 -14
- package/dist/renderer.d.ts +8 -151
- package/dist/renderer.js +17 -375
- package/dist/renderers/action.d.ts +51 -0
- package/dist/renderers/action.js +112 -0
- package/dist/renderers/config.d.ts +31 -0
- package/dist/renderers/config.js +93 -0
- package/dist/renderers/playbook.d.ts +19 -0
- package/dist/renderers/playbook.js +42 -0
- package/dist/renderers/project.d.ts +45 -0
- package/dist/renderers/project.js +196 -0
- package/dist/renderers/runs.d.ts +15 -0
- package/dist/renderers/runs.js +47 -0
- package/dist/renderers/state.d.ts +4 -0
- package/dist/renderers/state.js +19 -0
- package/dist/services/config-merge.js +1 -2
- package/dist/services/index.d.ts +1 -0
- package/dist/services/index.js +1 -0
- package/dist/services/run-watch.d.ts +156 -0
- package/dist/services/run-watch.js +395 -0
- package/dist/types.d.ts +37 -0
- package/dist/utils/cert.js +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.js +1 -1
- package/dist/utils/input.d.ts +2 -1
- package/dist/utils/input.js +2 -1
- package/dist/utils/target.d.ts +6 -2
- package/dist/utils/target.js +4 -4
- package/dist/utils/utils.d.ts +1 -1
- package/dist/utils/utils.js +4 -12
- package/dist/utils/warning.d.ts +4 -0
- package/dist/utils/warning.js +4 -0
- package/package.json +5 -5
- package/dist/commands/state-list.d.ts +0 -24
- package/dist/commands/state-list.js +0 -81
- package/dist/standalone/index.d.ts +0 -12
- package/dist/standalone/index.js +0 -13
- package/dist/utils/duration.d.ts +0 -1
- package/dist/utils/duration.js +0 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { CommanderError } from "commander";
|
|
2
|
-
import {
|
|
2
|
+
import { StandaloneDispatcher } from "@actiondock/core/server";
|
|
3
|
+
import { createCliProgram, isNodeArgv } from "./commands/index.js";
|
|
3
4
|
import { formatError, SigintError } from "./errors.js";
|
|
4
5
|
import { renderError } from "./renderer.js";
|
|
5
6
|
import { ExitCode } from "./types.js";
|
|
@@ -7,10 +8,21 @@ export * from "./types.js";
|
|
|
7
8
|
export * from "./errors.js";
|
|
8
9
|
export * from "./renderer.js";
|
|
9
10
|
export * from "./prompt.js";
|
|
10
|
-
export * from "./standalone/index.js";
|
|
11
11
|
export * from "./utils/index.js";
|
|
12
12
|
export * from "./services/index.js";
|
|
13
13
|
export * from "./commands/index.js";
|
|
14
|
+
/**
|
|
15
|
+
* 运行独立二进制参数解析分发器并返回退出状态码(委托 Core 统一实现)。
|
|
16
|
+
*/
|
|
17
|
+
export async function runStandaloneCli(argv = process.argv.slice(2), options, control) {
|
|
18
|
+
const dispatcher = new StandaloneDispatcher(options);
|
|
19
|
+
return dispatcher.dispatch(argv, control);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* 独立二进制进程入口适配器(事实源位于 core 包,此处 re-export 维持既有导入路径兼容)。
|
|
23
|
+
* 仅在命令行可执行入口调用,负责全局 SIGINT 监听与退出状态码写入。
|
|
24
|
+
*/
|
|
25
|
+
export { runStandaloneProcess } from "@actiondock/core/server";
|
|
14
26
|
/**
|
|
15
27
|
* ActionDock CLI 主执行入口函数。
|
|
16
28
|
*
|
|
@@ -22,16 +34,7 @@ export async function main(argv = process.argv, control, contextOptions) {
|
|
|
22
34
|
const context = { control, exitCode: 0, ...contextOptions };
|
|
23
35
|
const program = createCliProgram(context);
|
|
24
36
|
const isMachine = argv.includes("--json");
|
|
25
|
-
const normalizedArgv = argv
|
|
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];
|
|
37
|
+
const normalizedArgv = isNodeArgv(argv) ? argv : ["node", "ad", ...argv];
|
|
35
38
|
try {
|
|
36
39
|
await program.parseAsync(normalizedArgv);
|
|
37
40
|
if (control?.cancellationSource === "sigint" && control?.signal?.aborted) {
|
package/dist/prompt.d.ts
CHANGED
|
@@ -34,6 +34,9 @@ export declare function promptText(promptText: string, options?: {
|
|
|
34
34
|
export declare function readStreamLine(stream: NodeJS.ReadableStream): Promise<string>;
|
|
35
35
|
/**
|
|
36
36
|
* 从流中完整读取所有数据,并移除末尾的换行符。
|
|
37
|
+
*
|
|
38
|
+
* 委托 readStdinBounded 统一收集:保留宽松 UTF-8 解码与 BOM,
|
|
39
|
+
* 补齐默认 10MB 上限保护,流错误通过 INPUT_FILE_READ_FAILED 透传。
|
|
37
40
|
*/
|
|
38
41
|
export declare function readEntireStdin(stream?: NodeJS.ReadableStream): Promise<string>;
|
|
39
42
|
/**
|
package/dist/prompt.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createInterface } from "node:readline";
|
|
2
|
+
import { readStdinBounded } from "@actiondock/core/project";
|
|
2
3
|
import { ArgumentError, SigintError } from "./errors.js";
|
|
3
4
|
/**
|
|
4
5
|
* 在终端中安全交互式读取用户输入的密码或敏感信息。
|
|
@@ -126,22 +127,13 @@ export async function readStreamLine(stream) {
|
|
|
126
127
|
}
|
|
127
128
|
/**
|
|
128
129
|
* 从流中完整读取所有数据,并移除末尾的换行符。
|
|
130
|
+
*
|
|
131
|
+
* 委托 readStdinBounded 统一收集:保留宽松 UTF-8 解码与 BOM,
|
|
132
|
+
* 补齐默认 10MB 上限保护,流错误通过 INPUT_FILE_READ_FAILED 透传。
|
|
129
133
|
*/
|
|
130
134
|
export async function readEntireStdin(stream = process.stdin) {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
stream.on("data", (chunk) => {
|
|
134
|
-
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
135
|
-
});
|
|
136
|
-
stream.once("end", () => {
|
|
137
|
-
const content = Buffer.concat(chunks).toString("utf-8");
|
|
138
|
-
resolve(content.replace(/[\r\n]+$/, ""));
|
|
139
|
-
});
|
|
140
|
-
stream.once("error", reject);
|
|
141
|
-
if ("resume" in stream && typeof stream.resume === "function") {
|
|
142
|
-
stream.resume();
|
|
143
|
-
}
|
|
144
|
-
});
|
|
135
|
+
const content = await readStdinBounded(stream, { strictUtf8: false });
|
|
136
|
+
return content.replace(/[\r\n]+$/, "");
|
|
145
137
|
}
|
|
146
138
|
/**
|
|
147
139
|
* 解析并获取配置项的具体输入值。
|
package/dist/renderer.d.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import type { Envelope, CliContext } from "./types.js";
|
|
2
|
+
export * from "./renderers/project.js";
|
|
3
|
+
export * from "./renderers/action.js";
|
|
4
|
+
export * from "./renderers/playbook.js";
|
|
5
|
+
export * from "./renderers/config.js";
|
|
6
|
+
export * from "./renderers/state.js";
|
|
7
|
+
export * from "./renderers/runs.js";
|
|
4
8
|
/**
|
|
5
9
|
* 构造标准成功结果信封。
|
|
6
10
|
*
|
|
@@ -16,7 +20,7 @@ export declare function createSuccessEnvelope<T>(data: T, meta?: Record<string,
|
|
|
16
20
|
* @param details 附加错误细节
|
|
17
21
|
* @param meta 附加元数据
|
|
18
22
|
*/
|
|
19
|
-
export declare function createErrorEnvelope(code: string, message: string, details?: unknown, meta?: Record<string, unknown
|
|
23
|
+
export declare function createErrorEnvelope(code: string, message: string, details?: unknown, meta?: Record<string, unknown>, hint?: string): Envelope<never>;
|
|
20
24
|
/**
|
|
21
25
|
* 序列化数据为格式化 JSON 字符串。
|
|
22
26
|
*
|
|
@@ -47,150 +51,3 @@ export declare function renderError(err: unknown, options: {
|
|
|
47
51
|
json?: boolean;
|
|
48
52
|
context?: CliContext;
|
|
49
53
|
}): void;
|
|
50
|
-
/**
|
|
51
|
-
* 将工程详情信息转换为机器输出视图(剔除 Map 明细与定义字典)。
|
|
52
|
-
*/
|
|
53
|
-
export declare function projectDetailToJson(info: ProjectDetailInfo): {
|
|
54
|
-
id: string;
|
|
55
|
-
name: string;
|
|
56
|
-
version: string;
|
|
57
|
-
description: string | undefined;
|
|
58
|
-
projectRoot: string;
|
|
59
|
-
actionsDir: string;
|
|
60
|
-
playbooksDir: string;
|
|
61
|
-
actionsCount: number;
|
|
62
|
-
playbooksCount: number;
|
|
63
|
-
actions: string[];
|
|
64
|
-
playbooks: string[];
|
|
65
|
-
configDeclared: string[];
|
|
66
|
-
};
|
|
67
|
-
/**
|
|
68
|
-
* 格式化渲染单个项目的元数据与详情信息。
|
|
69
|
-
*/
|
|
70
|
-
export declare function renderProjectDetail(info: ProjectDetailInfo): string;
|
|
71
|
-
/**
|
|
72
|
-
* 格式化渲染已链接的多个 Package 摘要信息。
|
|
73
|
-
*/
|
|
74
|
-
export declare function renderAggregatedPackages(packages: AggregatedPackage[], options?: {
|
|
75
|
-
header?: string;
|
|
76
|
-
showTip?: boolean;
|
|
77
|
-
}): string;
|
|
78
|
-
/**
|
|
79
|
-
* 远端 info 接口返回的注册表树视图(与 RegistryStatusReport 字段兼容的宽松结构)。
|
|
80
|
-
*/
|
|
81
|
-
export type RegistryTreeView = RegistryStatusReport | (Record<string, unknown> & {
|
|
82
|
-
workspaces?: Array<{
|
|
83
|
-
id?: string;
|
|
84
|
-
path: string;
|
|
85
|
-
status: string;
|
|
86
|
-
packagesCount?: number;
|
|
87
|
-
children?: Array<{
|
|
88
|
-
id: string;
|
|
89
|
-
version?: string;
|
|
90
|
-
path: string;
|
|
91
|
-
}>;
|
|
92
|
-
}>;
|
|
93
|
-
packages?: Array<{
|
|
94
|
-
id: string;
|
|
95
|
-
version?: string;
|
|
96
|
-
path: string;
|
|
97
|
-
status: string;
|
|
98
|
-
}>;
|
|
99
|
-
totalPackagesCount?: number;
|
|
100
|
-
staleCount?: number;
|
|
101
|
-
});
|
|
102
|
-
/**
|
|
103
|
-
* 格式化渲染注册表层级树结构。
|
|
104
|
-
*/
|
|
105
|
-
export declare function renderRegistryTree(status: RegistryTreeView): string;
|
|
106
|
-
/**
|
|
107
|
-
* 格式化渲染 Action 列表。
|
|
108
|
-
*/
|
|
109
|
-
export declare function renderActionList(items: Array<{
|
|
110
|
-
id: string;
|
|
111
|
-
description: string;
|
|
112
|
-
packageId?: string;
|
|
113
|
-
}>, title?: string, isFallback?: boolean, intent?: string): string;
|
|
114
|
-
/**
|
|
115
|
-
* 格式化渲染 Action 详情(编码顾问 Encoding Advisor)。
|
|
116
|
-
* 统一复用 core 下沉的 formatActionDetail 实现,与独立分发器保持完全一致。
|
|
117
|
-
*/
|
|
118
|
-
export declare function renderActionDetail(action: {
|
|
119
|
-
id: string;
|
|
120
|
-
packageId?: string;
|
|
121
|
-
projectRoot?: string;
|
|
122
|
-
description?: string;
|
|
123
|
-
inputSchema?: unknown;
|
|
124
|
-
outputSchema?: unknown;
|
|
125
|
-
}): string;
|
|
126
|
-
/**
|
|
127
|
-
* 格式化渲染 Action 校验结果。
|
|
128
|
-
*/
|
|
129
|
-
export declare function renderActionValidation(results: Array<{
|
|
130
|
-
id: string;
|
|
131
|
-
valid: boolean;
|
|
132
|
-
errors: string[];
|
|
133
|
-
}>): string;
|
|
134
|
-
/**
|
|
135
|
-
* 格式化渲染 Playbook 列表。
|
|
136
|
-
*/
|
|
137
|
-
export declare function renderPlaybookList(items: Array<{
|
|
138
|
-
id: string;
|
|
139
|
-
description?: string;
|
|
140
|
-
packageId?: string;
|
|
141
|
-
}>, title?: string, isFallback?: boolean, intent?: string): string;
|
|
142
|
-
/**
|
|
143
|
-
* 格式化渲染 Playbook 详情。
|
|
144
|
-
*/
|
|
145
|
-
export declare function renderPlaybookDetail(pb: {
|
|
146
|
-
id: string;
|
|
147
|
-
packageId?: string;
|
|
148
|
-
description?: string;
|
|
149
|
-
actions?: string[];
|
|
150
|
-
filePath?: string;
|
|
151
|
-
content?: string;
|
|
152
|
-
}): string;
|
|
153
|
-
/**
|
|
154
|
-
* 格式化渲染配置项列表。
|
|
155
|
-
* 掩码决策收敛在命令层(传入的 value 已完成是否打码处理),
|
|
156
|
-
* 此处仅负责值的字符串格式化:字符串原样输出,其余类型 JSON 序列化。
|
|
157
|
-
*/
|
|
158
|
-
export declare function renderConfigList(items: Array<{
|
|
159
|
-
key: string;
|
|
160
|
-
value: unknown;
|
|
161
|
-
source: string;
|
|
162
|
-
secret: boolean;
|
|
163
|
-
description?: string;
|
|
164
|
-
}>, scopeLabel?: string, isFallback?: boolean, intent?: string): string;
|
|
165
|
-
/**
|
|
166
|
-
* 格式化渲染配置依赖规范检查。
|
|
167
|
-
*/
|
|
168
|
-
export declare function renderConfigSchema(items: Array<{
|
|
169
|
-
key: string;
|
|
170
|
-
status: string;
|
|
171
|
-
source: string;
|
|
172
|
-
secret: boolean;
|
|
173
|
-
description: string;
|
|
174
|
-
}>, packageId: string, root: string): string;
|
|
175
|
-
/**
|
|
176
|
-
* 格式化渲染环境变量满足率诊断。
|
|
177
|
-
*/
|
|
178
|
-
export declare function renderConfigEnv(checks: EnvCheckItem[], packageId?: string): string;
|
|
179
|
-
/**
|
|
180
|
-
* 格式化渲染状态键列表。
|
|
181
|
-
*/
|
|
182
|
-
export declare function renderStateList(keys: string[], scopeLabel?: string, isFallback?: boolean, intent?: string): string;
|
|
183
|
-
/**
|
|
184
|
-
* 格式化渲染执行记录列表。
|
|
185
|
-
*/
|
|
186
|
-
export declare function renderRunsList(items: Array<{
|
|
187
|
-
id: string;
|
|
188
|
-
actionId: string;
|
|
189
|
-
packageId?: string;
|
|
190
|
-
status: string;
|
|
191
|
-
startedAt: string;
|
|
192
|
-
}>, scopeLabel?: string, isFallback?: boolean, intent?: string): string;
|
|
193
|
-
/**
|
|
194
|
-
* 格式化渲染单次执行记录详情。
|
|
195
|
-
*/
|
|
196
|
-
export declare function renderRunDetail(run: RunRecord): string;
|
package/dist/renderer.js
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
|
-
import { formatActionDetail, } from "@actiondock/core/project";
|
|
2
1
|
import { formatError } from "./errors.js";
|
|
2
|
+
export * from "./renderers/project.js";
|
|
3
|
+
export * from "./renderers/action.js";
|
|
4
|
+
export * from "./renderers/playbook.js";
|
|
5
|
+
export * from "./renderers/config.js";
|
|
6
|
+
export * from "./renderers/state.js";
|
|
7
|
+
export * from "./renderers/runs.js";
|
|
3
8
|
/**
|
|
4
9
|
* 构造标准成功结果信封。
|
|
5
10
|
*
|
|
@@ -24,7 +29,11 @@ export function createSuccessEnvelope(data, meta) {
|
|
|
24
29
|
* @param details 附加错误细节
|
|
25
30
|
* @param meta 附加元数据
|
|
26
31
|
*/
|
|
27
|
-
export function createErrorEnvelope(code, message, details, meta) {
|
|
32
|
+
export function createErrorEnvelope(code, message, details, meta, hint) {
|
|
33
|
+
const effectiveHint = hint ??
|
|
34
|
+
(details && typeof details === "object" && typeof details.hint === "string"
|
|
35
|
+
? details.hint
|
|
36
|
+
: undefined);
|
|
28
37
|
const result = {
|
|
29
38
|
ok: false,
|
|
30
39
|
error: {
|
|
@@ -33,6 +42,9 @@ export function createErrorEnvelope(code, message, details, meta) {
|
|
|
33
42
|
...(details !== undefined ? { details } : {}),
|
|
34
43
|
},
|
|
35
44
|
};
|
|
45
|
+
if (effectiveHint !== undefined) {
|
|
46
|
+
result.hint = effectiveHint;
|
|
47
|
+
}
|
|
36
48
|
if (meta && Object.keys(meta).length > 0) {
|
|
37
49
|
result.meta = meta;
|
|
38
50
|
}
|
|
@@ -93,383 +105,13 @@ export function renderError(err, options) {
|
|
|
93
105
|
const formatted = formatError(err);
|
|
94
106
|
const isMachine = Boolean(options.json);
|
|
95
107
|
if (isMachine) {
|
|
96
|
-
const errorEnv = createErrorEnvelope(formatted.code, formatted.message, formatted.details);
|
|
108
|
+
const errorEnv = createErrorEnvelope(formatted.code, formatted.message, formatted.details, undefined, formatted.hint);
|
|
97
109
|
writeStdout(formatJson(errorEnv), options.context);
|
|
98
110
|
}
|
|
99
111
|
else {
|
|
100
112
|
writeStderr(`Error: ${formatted.message}`, options.context);
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* 将工程详情信息转换为机器输出视图(剔除 Map 明细与定义字典)。
|
|
105
|
-
*/
|
|
106
|
-
export function projectDetailToJson(info) {
|
|
107
|
-
return {
|
|
108
|
-
id: info.id,
|
|
109
|
-
name: info.name || info.id,
|
|
110
|
-
version: info.version || "0.0.0",
|
|
111
|
-
description: info.description,
|
|
112
|
-
projectRoot: info.projectRoot,
|
|
113
|
-
actionsDir: info.actionsDir,
|
|
114
|
-
playbooksDir: info.playbooksDir,
|
|
115
|
-
actionsCount: info.actionsCount,
|
|
116
|
-
playbooksCount: info.playbooksCount,
|
|
117
|
-
actions: info.actions,
|
|
118
|
-
playbooks: info.playbooks,
|
|
119
|
-
configDeclared: info.configDeclared,
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* 格式化渲染单个项目的元数据与详情信息。
|
|
124
|
-
*/
|
|
125
|
-
export function renderProjectDetail(info) {
|
|
126
|
-
const lines = [];
|
|
127
|
-
lines.push(`ActionDock Project: ${info.name} (${info.id})`);
|
|
128
|
-
lines.push(`Version: ${info.version}`);
|
|
129
|
-
if (info.description) {
|
|
130
|
-
lines.push(`Description: ${info.description}`);
|
|
131
|
-
}
|
|
132
|
-
lines.push(`Root: ${info.projectRoot}`);
|
|
133
|
-
lines.push(`\nActions (${info.actionsCount}):`);
|
|
134
|
-
if (info.actionsMap) {
|
|
135
|
-
for (const [id, act] of info.actionsMap.entries()) {
|
|
136
|
-
lines.push(` - ${id.padEnd(28)} ${act.description || ""}`);
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
else {
|
|
140
|
-
for (const actId of info.actions) {
|
|
141
|
-
lines.push(` - ${actId}`);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
lines.push(`\nPlaybooks (${info.playbooksCount}):`);
|
|
145
|
-
if (info.playbooksMap) {
|
|
146
|
-
for (const [id, pb] of info.playbooksMap.entries()) {
|
|
147
|
-
lines.push(` - ${id.padEnd(28)} ${pb.description || ""}`);
|
|
113
|
+
if (formatted.hint) {
|
|
114
|
+
writeStderr(formatted.hint, options.context);
|
|
148
115
|
}
|
|
149
116
|
}
|
|
150
|
-
else {
|
|
151
|
-
for (const pbId of info.playbooks) {
|
|
152
|
-
lines.push(` - ${pbId}`);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
if (info.configDeclared.length > 0) {
|
|
156
|
-
lines.push(`\nDeclared Config Keys:`);
|
|
157
|
-
for (const k of info.configDeclared) {
|
|
158
|
-
const item = info.configDef?.[k];
|
|
159
|
-
const isSec = item?.secret ? " [secret]" : "";
|
|
160
|
-
const def = item?.default !== undefined ? ` (default: ${JSON.stringify(item.default)})` : "";
|
|
161
|
-
lines.push(` - ${k.padEnd(24)} ${item?.description || ""}${def}${isSec}`);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
return lines.join("\n");
|
|
165
|
-
}
|
|
166
|
-
/**
|
|
167
|
-
* 格式化渲染已链接的多个 Package 摘要信息。
|
|
168
|
-
*/
|
|
169
|
-
export function renderAggregatedPackages(packages, options) {
|
|
170
|
-
const lines = [];
|
|
171
|
-
if (options?.header) {
|
|
172
|
-
lines.push(options.header);
|
|
173
|
-
}
|
|
174
|
-
else {
|
|
175
|
-
lines.push(`ActionDock Linked Packages (${packages.length}):\n`);
|
|
176
|
-
}
|
|
177
|
-
for (const p of packages) {
|
|
178
|
-
lines.push(`- ${p.name} (${p.id}) v${p.version}`);
|
|
179
|
-
lines.push(` Path: ${p.path}`);
|
|
180
|
-
if (p.description) {
|
|
181
|
-
lines.push(` Desc: ${p.description}`);
|
|
182
|
-
}
|
|
183
|
-
lines.push(` Actions (${p.actionsCount}): ${p.actions.join(", ") || "(none)"}`);
|
|
184
|
-
lines.push(` Playbooks (${p.playbooksCount}): ${p.playbooks.join(", ") || "(none)"}`);
|
|
185
|
-
lines.push("");
|
|
186
|
-
}
|
|
187
|
-
if (options?.showTip !== false) {
|
|
188
|
-
lines.push("Tip: Run 'ad info <package-id>' to view detailed package configuration and schema.");
|
|
189
|
-
}
|
|
190
|
-
return lines.join("\n");
|
|
191
|
-
}
|
|
192
|
-
/**
|
|
193
|
-
* 格式化渲染注册表层级树结构。
|
|
194
|
-
*/
|
|
195
|
-
export function renderRegistryTree(status) {
|
|
196
|
-
const lines = [];
|
|
197
|
-
const workspaces = status.workspaces || [];
|
|
198
|
-
const packages = status.packages || [];
|
|
199
|
-
const hasWorkspaces = workspaces.length > 0;
|
|
200
|
-
const hasPackages = packages.length > 0;
|
|
201
|
-
if (!hasWorkspaces && !hasPackages) {
|
|
202
|
-
lines.push("[INFO] No ActionDock packages or workspaces currently linked.");
|
|
203
|
-
lines.push(" Run 'ad link' inside an Action package or workspace to register it.");
|
|
204
|
-
return lines.join("\n");
|
|
205
|
-
}
|
|
206
|
-
lines.push("[ActionDock Workspace & Package Tree]\n");
|
|
207
|
-
if (hasWorkspaces) {
|
|
208
|
-
lines.push("Workspaces:");
|
|
209
|
-
for (const ws of workspaces) {
|
|
210
|
-
const tag = ws.status === "active" ? "[OK]" : "[STALE]";
|
|
211
|
-
lines.push(` ${tag} ${ws.path} (${ws.packagesCount} package${ws.packagesCount === 1 ? "" : "s"})`);
|
|
212
|
-
if (ws.children && ws.children.length > 0) {
|
|
213
|
-
const children = ws.children;
|
|
214
|
-
children.forEach((child, idx) => {
|
|
215
|
-
const isLast = idx === children.length - 1;
|
|
216
|
-
const prefix = isLast ? " +-- " : " |-- ";
|
|
217
|
-
lines.push(`${prefix}${child.id} (v${child.version}) -> ${child.path}`);
|
|
218
|
-
});
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
if (hasPackages) {
|
|
223
|
-
if (hasWorkspaces)
|
|
224
|
-
lines.push("");
|
|
225
|
-
lines.push("Standalone Packages:");
|
|
226
|
-
for (const pkg of packages) {
|
|
227
|
-
const tag = pkg.status === "active" ? "[OK]" : "[STALE]";
|
|
228
|
-
lines.push(` ${tag} ${pkg.id} (v${pkg.version || "unknown"}) -> ${pkg.path}`);
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
const totalActive = status.totalPackagesCount ?? packages.length;
|
|
232
|
-
lines.push(`\n[Summary] Total: ${totalActive} active package(s), ${workspaces.length} workspace(s)`);
|
|
233
|
-
if (status.staleCount && status.staleCount > 0) {
|
|
234
|
-
lines.push(`[WARN] ${status.staleCount} stale entry/entries detected. Run 'ad unlink --prune' to clean up.`);
|
|
235
|
-
}
|
|
236
|
-
return lines.join("\n");
|
|
237
|
-
}
|
|
238
|
-
/**
|
|
239
|
-
* 格式化渲染 Action 列表。
|
|
240
|
-
*/
|
|
241
|
-
export function renderActionList(items, title = "Actions", isFallback = false, intent) {
|
|
242
|
-
const lines = [];
|
|
243
|
-
lines.push(`${title}:\n`);
|
|
244
|
-
if (isFallback && intent) {
|
|
245
|
-
lines.push(`(No actions matched intent '${intent}', showing all actions)\n`);
|
|
246
|
-
}
|
|
247
|
-
if (items.length === 0) {
|
|
248
|
-
lines.push(" (no actions found)");
|
|
249
|
-
}
|
|
250
|
-
else {
|
|
251
|
-
for (const a of items) {
|
|
252
|
-
lines.push(` - ${a.id.padEnd(28)} ${a.description}`);
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
return lines.join("\n");
|
|
256
|
-
}
|
|
257
|
-
/**
|
|
258
|
-
* 格式化渲染 Action 详情(编码顾问 Encoding Advisor)。
|
|
259
|
-
* 统一复用 core 下沉的 formatActionDetail 实现,与独立分发器保持完全一致。
|
|
260
|
-
*/
|
|
261
|
-
export function renderActionDetail(action) {
|
|
262
|
-
return formatActionDetail(action);
|
|
263
|
-
}
|
|
264
|
-
/**
|
|
265
|
-
* 格式化渲染 Action 校验结果。
|
|
266
|
-
*/
|
|
267
|
-
export function renderActionValidation(results) {
|
|
268
|
-
const lines = [];
|
|
269
|
-
for (const r of results) {
|
|
270
|
-
if (r.valid) {
|
|
271
|
-
lines.push(`[OK] ${r.id}: Valid`);
|
|
272
|
-
}
|
|
273
|
-
else {
|
|
274
|
-
lines.push(`[FAIL] ${r.id}: ${r.errors.join(", ")}`);
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
return lines.join("\n");
|
|
278
|
-
}
|
|
279
|
-
/**
|
|
280
|
-
* 格式化渲染 Playbook 列表。
|
|
281
|
-
*/
|
|
282
|
-
export function renderPlaybookList(items, title = "Playbooks", isFallback = false, intent) {
|
|
283
|
-
const lines = [];
|
|
284
|
-
lines.push(`${title}:\n`);
|
|
285
|
-
if (isFallback && intent) {
|
|
286
|
-
lines.push(`(No playbooks matched intent '${intent}', showing all playbooks)\n`);
|
|
287
|
-
}
|
|
288
|
-
if (items.length === 0) {
|
|
289
|
-
lines.push(" (no playbooks found)");
|
|
290
|
-
}
|
|
291
|
-
else {
|
|
292
|
-
for (const p of items) {
|
|
293
|
-
const pkgDesc = p.packageId ? ` (Package: ${p.packageId})` : "";
|
|
294
|
-
lines.push(` - ${p.id.padEnd(26)} ${p.description}${pkgDesc}`);
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
return lines.join("\n");
|
|
298
|
-
}
|
|
299
|
-
/**
|
|
300
|
-
* 格式化渲染 Playbook 详情。
|
|
301
|
-
*/
|
|
302
|
-
export function renderPlaybookDetail(pb) {
|
|
303
|
-
const lines = [];
|
|
304
|
-
const pkgDesc = pb.packageId ? ` (Package: ${pb.packageId})` : "";
|
|
305
|
-
lines.push(`Playbook: ${pb.id}${pkgDesc}`);
|
|
306
|
-
if (pb.description)
|
|
307
|
-
lines.push(`Description: ${pb.description}`);
|
|
308
|
-
if (pb.actions && pb.actions.length > 0) {
|
|
309
|
-
lines.push(`Actions: ${pb.actions.join(", ")}`);
|
|
310
|
-
}
|
|
311
|
-
if (pb.filePath)
|
|
312
|
-
lines.push(`File: ${pb.filePath}\n`);
|
|
313
|
-
if (pb.content) {
|
|
314
|
-
lines.push("--- Content ---");
|
|
315
|
-
lines.push(pb.content);
|
|
316
|
-
}
|
|
317
|
-
return lines.join("\n");
|
|
318
|
-
}
|
|
319
|
-
/**
|
|
320
|
-
* 格式化渲染配置项列表。
|
|
321
|
-
* 掩码决策收敛在命令层(传入的 value 已完成是否打码处理),
|
|
322
|
-
* 此处仅负责值的字符串格式化:字符串原样输出,其余类型 JSON 序列化。
|
|
323
|
-
*/
|
|
324
|
-
export function renderConfigList(items, scopeLabel = "Global Scope", isFallback = false, intent) {
|
|
325
|
-
const lines = [];
|
|
326
|
-
lines.push(`Configurations [${scopeLabel}]:\n`);
|
|
327
|
-
if (isFallback && intent) {
|
|
328
|
-
lines.push(`(No config entries matched intent '${intent}', showing all entries)\n`);
|
|
329
|
-
}
|
|
330
|
-
if (items.length === 0) {
|
|
331
|
-
lines.push(" (No configuration entries found)");
|
|
332
|
-
}
|
|
333
|
-
else {
|
|
334
|
-
for (const item of items) {
|
|
335
|
-
const valStr = formatConfigValue(item.value);
|
|
336
|
-
const secretBadge = item.secret ? ", secret" : "";
|
|
337
|
-
lines.push(` - ${item.key.padEnd(24)} = ${valStr} (${item.source}${secretBadge})`);
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
return lines.join("\n");
|
|
341
|
-
}
|
|
342
|
-
/**
|
|
343
|
-
* 格式化配置值:字符串原样输出,其余类型 JSON 序列化。
|
|
344
|
-
*/
|
|
345
|
-
function formatConfigValue(value) {
|
|
346
|
-
return typeof value === "string" ? value : JSON.stringify(value);
|
|
347
|
-
}
|
|
348
|
-
/**
|
|
349
|
-
* 格式化渲染配置依赖规范检查。
|
|
350
|
-
*/
|
|
351
|
-
export function renderConfigSchema(items, packageId, root) {
|
|
352
|
-
const lines = [];
|
|
353
|
-
lines.push(`Configuration Requirements for ${packageId} (${root}):\n`);
|
|
354
|
-
if (items.length === 0) {
|
|
355
|
-
lines.push(" (No configuration dependencies declared for this package)");
|
|
356
|
-
return lines.join("\n");
|
|
357
|
-
}
|
|
358
|
-
lines.push(` ${"KEY".padEnd(24)} ${"STATUS".padEnd(12)} ${"SOURCE".padEnd(10)} ${"SECRET".padEnd(8)} DESCRIPTION`);
|
|
359
|
-
lines.push(" " + "-".repeat(85));
|
|
360
|
-
const missing = [];
|
|
361
|
-
for (const item of items) {
|
|
362
|
-
const statusLabel = item.status === "SET" ? "[SET]" : item.status === "DEFAULT" ? "[DEFAULT]" : "[MISSING]";
|
|
363
|
-
const secretLabel = item.secret ? "yes" : "no";
|
|
364
|
-
lines.push(` ${item.key.padEnd(24)} ${statusLabel.padEnd(12)} ${item.source.padEnd(10)} ${secretLabel.padEnd(8)} ${item.description}`);
|
|
365
|
-
if (item.status === "MISSING") {
|
|
366
|
-
missing.push(item.key);
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
if (missing.length > 0) {
|
|
370
|
-
lines.push(`\n[WARNING] ${missing.length} required config(s) not set:`);
|
|
371
|
-
for (const m of missing) {
|
|
372
|
-
lines.push(` - ${m}: Run 'ad config set ${m} <value>' to configure.`);
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
else {
|
|
376
|
-
lines.push("\n[OK] All configuration dependencies are satisfied.");
|
|
377
|
-
}
|
|
378
|
-
return lines.join("\n");
|
|
379
|
-
}
|
|
380
|
-
/**
|
|
381
|
-
* 格式化渲染环境变量满足率诊断。
|
|
382
|
-
*/
|
|
383
|
-
export function renderConfigEnv(checks, packageId) {
|
|
384
|
-
const lines = [];
|
|
385
|
-
const targetDesc = packageId ? `for Package '${packageId}'` : "Global";
|
|
386
|
-
lines.push(`Environment Variable Satisfaction Diagnostics ${targetDesc}:\n`);
|
|
387
|
-
if (checks.length === 0) {
|
|
388
|
-
lines.push(" (No configuration dependencies declared)");
|
|
389
|
-
return lines.join("\n");
|
|
390
|
-
}
|
|
391
|
-
lines.push(` ${"KEY".padEnd(24)} ${"SATISFIED".padEnd(12)} ${"REQUIRED".padEnd(10)} ${"MATCHED ENV".padEnd(28)} SECRET`);
|
|
392
|
-
lines.push(" " + "-".repeat(85));
|
|
393
|
-
for (const c of checks) {
|
|
394
|
-
const satLabel = c.satisfied ? "[OK]" : "[MISSING]";
|
|
395
|
-
const reqLabel = c.required ? "yes" : "no";
|
|
396
|
-
const matched = c.matchedEnv || (c.hasDefault ? "(using default)" : "-");
|
|
397
|
-
const secLabel = c.secret ? "yes" : "no";
|
|
398
|
-
lines.push(` ${c.key.padEnd(24)} ${satLabel.padEnd(12)} ${reqLabel.padEnd(10)} ${matched.padEnd(28)} ${secLabel}`);
|
|
399
|
-
}
|
|
400
|
-
const missingRequired = checks.filter((c) => c.required && !c.satisfied);
|
|
401
|
-
if (missingRequired.length > 0) {
|
|
402
|
-
lines.push(`\n[WARNING] ${missingRequired.length} required environment variable(s) not satisfied:`);
|
|
403
|
-
for (const m of missingRequired) {
|
|
404
|
-
lines.push(` - ${m.key}: Please export ${m.key}=... in your environment.`);
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
else {
|
|
408
|
-
lines.push("\n[OK] All declared configuration dependencies are satisfied by environment or defaults.");
|
|
409
|
-
}
|
|
410
|
-
return lines.join("\n");
|
|
411
|
-
}
|
|
412
|
-
/**
|
|
413
|
-
* 格式化渲染状态键列表。
|
|
414
|
-
*/
|
|
415
|
-
export function renderStateList(keys, scopeLabel = "Current State", isFallback = false, intent) {
|
|
416
|
-
const lines = [];
|
|
417
|
-
lines.push(`State keys for ${scopeLabel} (${keys.length}):\n`);
|
|
418
|
-
if (isFallback && intent) {
|
|
419
|
-
lines.push(`(No state keys matched intent '${intent}', showing all keys)\n`);
|
|
420
|
-
}
|
|
421
|
-
if (keys.length === 0) {
|
|
422
|
-
lines.push(" (no state keys found)");
|
|
423
|
-
}
|
|
424
|
-
else {
|
|
425
|
-
for (const k of keys) {
|
|
426
|
-
lines.push(` - ${k}`);
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
return lines.join("\n");
|
|
430
|
-
}
|
|
431
|
-
/**
|
|
432
|
-
* 格式化渲染执行记录列表。
|
|
433
|
-
*/
|
|
434
|
-
export function renderRunsList(items, scopeLabel = "Execution Runs", isFallback = false, intent) {
|
|
435
|
-
const lines = [];
|
|
436
|
-
lines.push(`${scopeLabel} (${items.length}):\n`);
|
|
437
|
-
if (isFallback && intent) {
|
|
438
|
-
lines.push(`(No runs matched intent '${intent}', showing all runs)\n`);
|
|
439
|
-
}
|
|
440
|
-
lines.push(` ${"RUN ID".padEnd(38)} ${"PACKAGE".padEnd(18)} ${"ACTION".padEnd(22)} ${"STATUS".padEnd(10)} STARTED`);
|
|
441
|
-
lines.push(" " + "-".repeat(105));
|
|
442
|
-
for (const r of items) {
|
|
443
|
-
const time = (r.startedAt || "").replace("T", " ").slice(0, 19);
|
|
444
|
-
const pkg = (r.packageId || "").padEnd(18);
|
|
445
|
-
lines.push(` ${r.id.padEnd(38)} ${pkg} ${r.actionId.padEnd(22)} ${r.status.padEnd(10)} ${time}`);
|
|
446
|
-
}
|
|
447
|
-
return lines.join("\n");
|
|
448
|
-
}
|
|
449
|
-
/**
|
|
450
|
-
* 格式化渲染单次执行记录详情。
|
|
451
|
-
*/
|
|
452
|
-
export function renderRunDetail(run) {
|
|
453
|
-
const lines = [];
|
|
454
|
-
lines.push(`Run: ${run.id}`);
|
|
455
|
-
lines.push(`Action: ${run.actionId}`);
|
|
456
|
-
if (run.packageId)
|
|
457
|
-
lines.push(`Package: ${run.packageId}`);
|
|
458
|
-
lines.push(`Status: ${run.status}`);
|
|
459
|
-
if (run.parentRunId)
|
|
460
|
-
lines.push(`Parent Run: ${run.parentRunId}`);
|
|
461
|
-
lines.push(`Started: ${run.startedAt}`);
|
|
462
|
-
if (run.finishedAt)
|
|
463
|
-
lines.push(`Finished: ${run.finishedAt}`);
|
|
464
|
-
lines.push("\nInput:");
|
|
465
|
-
lines.push(JSON.stringify(run.input, null, 2));
|
|
466
|
-
if (run.output !== undefined) {
|
|
467
|
-
lines.push("\nOutput:");
|
|
468
|
-
lines.push(JSON.stringify(run.output, null, 2));
|
|
469
|
-
}
|
|
470
|
-
if (run.error) {
|
|
471
|
-
lines.push("\nError:");
|
|
472
|
-
lines.push(JSON.stringify(run.error, null, 2));
|
|
473
|
-
}
|
|
474
|
-
return lines.join("\n");
|
|
475
117
|
}
|