@actiondock/cli 2.0.11 → 2.0.12
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 +15 -2
- package/bin/ad.js +13 -2
- package/dist/commands/action/create.d.ts +2 -0
- package/dist/commands/action/index.d.ts +16 -0
- package/dist/commands/action/list.d.ts +5 -0
- package/dist/commands/action/run.d.ts +4 -0
- package/dist/commands/action/show.d.ts +5 -0
- package/dist/commands/action/sync.d.ts +2 -0
- package/dist/commands/action/validate.d.ts +5 -0
- package/dist/commands/build.d.ts +2 -0
- package/dist/commands/config.d.ts +2 -0
- package/dist/commands/doctor.d.ts +2 -0
- package/dist/commands/export.d.ts +2 -0
- package/dist/commands/index.d.ts +2 -0
- package/dist/commands/info.d.ts +2 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/link.d.ts +2 -0
- package/dist/commands/mcp.d.ts +2 -0
- package/dist/commands/playbook.d.ts +6 -0
- package/dist/commands/profile.d.ts +2 -0
- package/dist/commands/runs.d.ts +2 -0
- package/dist/commands/serve.d.ts +2 -0
- package/dist/commands/state.d.ts +2 -0
- package/dist/commands/test.d.ts +2 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +745 -65708
- package/{src/utils/bytes.ts → dist/utils/bytes.d.ts} +0 -1
- package/{src/utils/filter.ts → dist/utils/filter.d.ts} +0 -1
- package/package.json +20 -15
- package/src/commands/action/create.ts +0 -129
- package/src/commands/action/index.ts +0 -27
- package/src/commands/action/list.ts +0 -247
- package/src/commands/action/run.ts +0 -197
- package/src/commands/action/show.ts +0 -128
- package/src/commands/action/sync.ts +0 -76
- package/src/commands/action/validate.ts +0 -102
- package/src/commands/build.ts +0 -56
- package/src/commands/config.ts +0 -583
- package/src/commands/doctor.ts +0 -84
- package/src/commands/export.ts +0 -196
- package/src/commands/index.ts +0 -75
- package/src/commands/info.ts +0 -537
- package/src/commands/init.ts +0 -24
- package/src/commands/link.ts +0 -73
- package/src/commands/mcp.ts +0 -195
- package/src/commands/playbook.ts +0 -566
- package/src/commands/profile.ts +0 -296
- package/src/commands/runs.ts +0 -452
- package/src/commands/serve.ts +0 -132
- package/src/commands/state.ts +0 -590
- package/src/commands/test.ts +0 -48
- package/src/index.ts +0 -58
- /package/{src/commands/action.ts → dist/commands/action.d.ts} +0 -0
- /package/{src/utils/duration.ts → dist/utils/duration.d.ts} +0 -0
package/src/commands/info.ts
DELETED
|
@@ -1,537 +0,0 @@
|
|
|
1
|
-
import { existsSync } from "node:fs";
|
|
2
|
-
import {
|
|
3
|
-
fetchRemoteInfo,
|
|
4
|
-
filterWithFallbackInfo,
|
|
5
|
-
findProjectRoot,
|
|
6
|
-
getRegistryStatus,
|
|
7
|
-
listLinkedPackages,
|
|
8
|
-
loadManifest,
|
|
9
|
-
loadPlaybooks,
|
|
10
|
-
loadProjectConfig,
|
|
11
|
-
resolvePackageRoot,
|
|
12
|
-
resolveTarget,
|
|
13
|
-
} from "@actiondock/core";
|
|
14
|
-
import { Command } from "commander";
|
|
15
|
-
import { ArgumentError, CliError, ExecutionError, getEffectiveOptions, renderResult } from "@actiondock/runtime-cli";
|
|
16
|
-
import { resolveIntent } from "../utils/filter";
|
|
17
|
-
|
|
18
|
-
interface AggregatedPackage {
|
|
19
|
-
id: string;
|
|
20
|
-
name: string;
|
|
21
|
-
version: string;
|
|
22
|
-
description?: string;
|
|
23
|
-
path: string;
|
|
24
|
-
actionsCount: number;
|
|
25
|
-
playbooksCount: number;
|
|
26
|
-
actions: string[];
|
|
27
|
-
playbooks: string[];
|
|
28
|
-
configDeclared: string[];
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
async function getProjectDetailInfo(root: string) {
|
|
32
|
-
const config = loadProjectConfig(root);
|
|
33
|
-
const manifest = loadManifest(root);
|
|
34
|
-
const actionsMap = new Map<string, { id: string; description?: string }>();
|
|
35
|
-
if (manifest?.actions) {
|
|
36
|
-
for (const [id, item] of Object.entries(manifest.actions)) {
|
|
37
|
-
actionsMap.set(id, {
|
|
38
|
-
id,
|
|
39
|
-
description: item.description,
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
const playbooks = loadPlaybooks(root, config.playbooksDir);
|
|
44
|
-
|
|
45
|
-
return {
|
|
46
|
-
id: config.id,
|
|
47
|
-
name: config.name,
|
|
48
|
-
version: config.version,
|
|
49
|
-
description: config.description,
|
|
50
|
-
projectRoot: root,
|
|
51
|
-
actionsDir: config.actionsDir || "actions",
|
|
52
|
-
playbooksDir: config.playbooksDir || "playbooks",
|
|
53
|
-
actionsCount: actionsMap.size,
|
|
54
|
-
playbooksCount: playbooks.size,
|
|
55
|
-
actions: Array.from(actionsMap.keys()),
|
|
56
|
-
playbooks: Array.from(playbooks.keys()),
|
|
57
|
-
configDeclared: config.config ? Object.keys(config.config) : [],
|
|
58
|
-
configDef: config.config,
|
|
59
|
-
actionsMap,
|
|
60
|
-
playbooksMap: playbooks,
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function projectDetailToJson(info: Awaited<ReturnType<typeof getProjectDetailInfo>>) {
|
|
65
|
-
return {
|
|
66
|
-
id: info.id,
|
|
67
|
-
name: info.name,
|
|
68
|
-
version: info.version,
|
|
69
|
-
description: info.description,
|
|
70
|
-
projectRoot: info.projectRoot,
|
|
71
|
-
actionsDir: info.actionsDir,
|
|
72
|
-
playbooksDir: info.playbooksDir,
|
|
73
|
-
actionsCount: info.actionsCount,
|
|
74
|
-
playbooksCount: info.playbooksCount,
|
|
75
|
-
actions: info.actions,
|
|
76
|
-
playbooks: info.playbooks,
|
|
77
|
-
configDeclared: info.configDeclared,
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
function printProjectDetail(info: Awaited<ReturnType<typeof getProjectDetailInfo>>) {
|
|
82
|
-
console.log(`ActionDock Project: ${info.name} (${info.id})`);
|
|
83
|
-
console.log(`Version: ${info.version}`);
|
|
84
|
-
if (info.description) console.log(`Description: ${info.description}`);
|
|
85
|
-
console.log(`Root: ${info.projectRoot}`);
|
|
86
|
-
console.log(`\nActions (${info.actionsCount}):`);
|
|
87
|
-
for (const [id, act] of info.actionsMap.entries()) {
|
|
88
|
-
console.log(` - ${id.padEnd(28)} ${act.description || ""}`);
|
|
89
|
-
}
|
|
90
|
-
console.log(`\nPlaybooks (${info.playbooksCount}):`);
|
|
91
|
-
for (const [id, pb] of info.playbooksMap.entries()) {
|
|
92
|
-
console.log(` - ${id.padEnd(28)} ${pb.description || ""}`);
|
|
93
|
-
}
|
|
94
|
-
if (info.configDeclared.length > 0) {
|
|
95
|
-
console.log(`\nDeclared Config Keys:`);
|
|
96
|
-
for (const k of info.configDeclared) {
|
|
97
|
-
const item = info.configDef?.[k];
|
|
98
|
-
const isSec = item?.secret ? " [secret]" : "";
|
|
99
|
-
const def =
|
|
100
|
-
item?.default !== undefined
|
|
101
|
-
? ` (default: ${JSON.stringify(item.default)})`
|
|
102
|
-
: "";
|
|
103
|
-
console.log(
|
|
104
|
-
` - ${k.padEnd(24)} ${item?.description || ""}${def}${isSec}`
|
|
105
|
-
);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
function printAggregatedPackages(
|
|
111
|
-
packages: AggregatedPackage[],
|
|
112
|
-
options?: { header?: string; showTip?: boolean }
|
|
113
|
-
) {
|
|
114
|
-
if (options?.header) {
|
|
115
|
-
console.log(options.header);
|
|
116
|
-
} else {
|
|
117
|
-
console.log(`ActionDock Linked Packages (${packages.length}):\n`);
|
|
118
|
-
}
|
|
119
|
-
for (const p of packages) {
|
|
120
|
-
console.log(`* ${p.name} (${p.id}) v${p.version}`);
|
|
121
|
-
console.log(` Path: ${p.path}`);
|
|
122
|
-
if (p.description) {
|
|
123
|
-
console.log(` Desc: ${p.description}`);
|
|
124
|
-
}
|
|
125
|
-
console.log(
|
|
126
|
-
` Actions (${p.actionsCount}): ${p.actions.join(", ") || "(none)"}`
|
|
127
|
-
);
|
|
128
|
-
console.log(
|
|
129
|
-
` Playbooks (${p.playbooksCount}): ${p.playbooks.join(", ") || "(none)"}`
|
|
130
|
-
);
|
|
131
|
-
console.log("");
|
|
132
|
-
}
|
|
133
|
-
if (options?.showTip !== false) {
|
|
134
|
-
console.log(
|
|
135
|
-
"Tip: Run 'ad info <package-id>' to view detailed package configuration and schema."
|
|
136
|
-
);
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
function printRegistryTree(status: ReturnType<typeof getRegistryStatus>): void {
|
|
141
|
-
const hasWorkspaces = status.workspaces.length > 0;
|
|
142
|
-
const hasPackages = status.packages.length > 0;
|
|
143
|
-
|
|
144
|
-
if (!hasWorkspaces && !hasPackages) {
|
|
145
|
-
console.log("[INFO] No ActionDock packages or workspaces currently linked.");
|
|
146
|
-
console.log(" Run 'ad link' inside an Action package or workspace to register it.");
|
|
147
|
-
return;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
console.log("[ActionDock Workspace & Package Tree]\n");
|
|
151
|
-
|
|
152
|
-
if (hasWorkspaces) {
|
|
153
|
-
console.log("Workspaces:");
|
|
154
|
-
for (const ws of status.workspaces) {
|
|
155
|
-
const tag = ws.status === "active" ? "[OK]" : "[STALE]";
|
|
156
|
-
console.log(` ${tag} ${ws.path} (${ws.packagesCount} package${ws.packagesCount === 1 ? "" : "s"})`);
|
|
157
|
-
if (ws.children && ws.children.length > 0) {
|
|
158
|
-
ws.children.forEach((child: any, idx: number) => {
|
|
159
|
-
const isLast = idx === ws.children!.length - 1;
|
|
160
|
-
const prefix = isLast ? " +-- " : " |-- ";
|
|
161
|
-
console.log(`${prefix}${child.id} (v${child.version}) -> ${child.path}`);
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
if (hasPackages) {
|
|
168
|
-
if (hasWorkspaces) console.log("");
|
|
169
|
-
console.log("Standalone Packages:");
|
|
170
|
-
for (const pkg of status.packages) {
|
|
171
|
-
const tag = pkg.status === "active" ? "[OK]" : "[STALE]";
|
|
172
|
-
console.log(` ${tag} ${pkg.id} (v${pkg.version || "unknown"}) -> ${pkg.path}`);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
console.log(`\n[Summary] Total: ${status.totalPackagesCount} active package(s), ${status.workspaces.length} workspace(s)`);
|
|
177
|
-
if (status.staleCount > 0) {
|
|
178
|
-
console.log(`[WARN] ${status.staleCount} stale entry/entries detected. Run 'ad unlink --prune' to clean up.`);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
export function registerInfoCommand(program: Command): void {
|
|
183
|
-
program
|
|
184
|
-
.command("info [patterns...]")
|
|
185
|
-
.description(
|
|
186
|
-
"Display information about current project, linked package, or remote target"
|
|
187
|
-
)
|
|
188
|
-
.option(
|
|
189
|
-
"-i, --intent <pattern>",
|
|
190
|
-
"Regex or fuzzy intent filter; falls back to full list when no match"
|
|
191
|
-
)
|
|
192
|
-
.option("-P, --package <id>", "Target package ID or path")
|
|
193
|
-
.option("--tree", "Display packages in hierarchical tree view grouped by workspace")
|
|
194
|
-
.option("-p, --profile <name>", "Query against a specific profile")
|
|
195
|
-
.option("-s, --server <url>", "Remote server URL")
|
|
196
|
-
.option("-t, --token <token>", "Auth token for remote server")
|
|
197
|
-
.option("--fallback", "Enable fallback to full list when no items match intent")
|
|
198
|
-
.option(
|
|
199
|
-
"--no-fallback",
|
|
200
|
-
"Disable fallback to full list when no items match intent"
|
|
201
|
-
)
|
|
202
|
-
.option("--json", "Output information as JSON")
|
|
203
|
-
.option("--envelope", "Wrap JSON output in standard envelope")
|
|
204
|
-
.option("--data-dir <path>", "Custom database storage directory")
|
|
205
|
-
.action(async (patterns: string[] = [], rawOptions: any, cmd: any) => {
|
|
206
|
-
try {
|
|
207
|
-
const options = getEffectiveOptions(rawOptions, cmd);
|
|
208
|
-
const effectiveIntent = resolveIntent(options.intent, patterns);
|
|
209
|
-
const isMachine = Boolean(options.json || options.envelope);
|
|
210
|
-
const fallbackExplicit = options.fallback === true || (Array.isArray(process.argv) && process.argv.includes("--fallback"));
|
|
211
|
-
const shouldFallback = isMachine ? fallbackExplicit : options.fallback !== false;
|
|
212
|
-
|
|
213
|
-
const target = resolveTarget({
|
|
214
|
-
profile: options.profile,
|
|
215
|
-
server: options.server,
|
|
216
|
-
token: options.token,
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
// 1. Remote target handling
|
|
220
|
-
if (target.type === "remote") {
|
|
221
|
-
const remoteInfo = await fetchRemoteInfo(
|
|
222
|
-
target.serverUrl!,
|
|
223
|
-
target.token,
|
|
224
|
-
{
|
|
225
|
-
intent: effectiveIntent,
|
|
226
|
-
package: options.package,
|
|
227
|
-
tree: Boolean(options.tree),
|
|
228
|
-
}
|
|
229
|
-
);
|
|
230
|
-
|
|
231
|
-
if (isMachine) {
|
|
232
|
-
renderResult(remoteInfo, { json: options.json, envelope: options.envelope });
|
|
233
|
-
return;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
console.log(
|
|
237
|
-
`Remote ActionDock Server: ${target.serverUrl}${target.profileName ? ` (Profile: ${target.profileName})` : ""}\n`
|
|
238
|
-
);
|
|
239
|
-
|
|
240
|
-
// Remote Tree
|
|
241
|
-
if (remoteInfo.type === "tree" || (options.tree && remoteInfo.workspaces)) {
|
|
242
|
-
printRegistryTree(remoteInfo);
|
|
243
|
-
return;
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
// Remote Package Detail
|
|
247
|
-
if (remoteInfo.type === "package_detail" || (remoteInfo.id && !remoteInfo.packages)) {
|
|
248
|
-
console.log(`ActionDock Project: ${remoteInfo.name || remoteInfo.id} (${remoteInfo.id})`);
|
|
249
|
-
console.log(`Version: ${remoteInfo.version || "unknown"}`);
|
|
250
|
-
if (remoteInfo.description) console.log(`Description: ${remoteInfo.description}`);
|
|
251
|
-
if (remoteInfo.path || remoteInfo.projectRoot) {
|
|
252
|
-
console.log(`Root: ${remoteInfo.path || remoteInfo.projectRoot}`);
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
const actions = remoteInfo.actionsDetail || remoteInfo.actions || [];
|
|
256
|
-
console.log(`\nActions (${remoteInfo.actionsCount || actions.length}):`);
|
|
257
|
-
for (const act of actions) {
|
|
258
|
-
if (typeof act === "string") {
|
|
259
|
-
console.log(` - ${act}`);
|
|
260
|
-
} else {
|
|
261
|
-
console.log(` - ${(act.id || "").padEnd(28)} ${act.description || ""}`);
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
const playbooks = remoteInfo.playbooksDetail || remoteInfo.playbooks || [];
|
|
266
|
-
console.log(`\nPlaybooks (${remoteInfo.playbooksCount || playbooks.length}):`);
|
|
267
|
-
for (const pb of playbooks) {
|
|
268
|
-
if (typeof pb === "string") {
|
|
269
|
-
console.log(` - ${pb}`);
|
|
270
|
-
} else {
|
|
271
|
-
console.log(` - ${(pb.id || "").padEnd(28)} ${pb.description || ""}`);
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
const declared = remoteInfo.configDeclared || {};
|
|
276
|
-
const declaredKeys = Object.keys(declared);
|
|
277
|
-
if (declaredKeys.length > 0) {
|
|
278
|
-
console.log(`\nDeclared Config Keys:`);
|
|
279
|
-
for (const k of declaredKeys) {
|
|
280
|
-
const item = declared[k];
|
|
281
|
-
const isSec = item?.secret ? " [secret]" : "";
|
|
282
|
-
const def =
|
|
283
|
-
item?.default !== undefined
|
|
284
|
-
? ` (default: ${JSON.stringify(item.default)})`
|
|
285
|
-
: "";
|
|
286
|
-
console.log(
|
|
287
|
-
` - ${k.padEnd(24)} ${item?.description || ""}${def}${isSec}`
|
|
288
|
-
);
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
return;
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
// Remote Package List
|
|
295
|
-
const packages = remoteInfo.packages || remoteInfo.linkedPackages || [];
|
|
296
|
-
if (Array.isArray(packages)) {
|
|
297
|
-
console.log(`Remote ActionDock Packages (${packages.length}):\n`);
|
|
298
|
-
for (const p of packages) {
|
|
299
|
-
console.log(`* ${p.name || p.id} (${p.id}) v${p.version || "unknown"}`);
|
|
300
|
-
if (p.path) console.log(` Path: ${p.path}`);
|
|
301
|
-
if (p.description) console.log(` Desc: ${p.description}`);
|
|
302
|
-
const actNames = Array.isArray(p.actions)
|
|
303
|
-
? p.actions.map((a: any) => (typeof a === "string" ? a : a.id)).join(", ")
|
|
304
|
-
: "";
|
|
305
|
-
const pbNames = Array.isArray(p.playbooks)
|
|
306
|
-
? p.playbooks.map((pb: any) => (typeof pb === "string" ? pb : pb.id)).join(", ")
|
|
307
|
-
: "";
|
|
308
|
-
console.log(` Actions (${p.actionsCount || (p.actions ? p.actions.length : 0)}): ${actNames || "(none)"}`);
|
|
309
|
-
console.log(` Playbooks (${p.playbooksCount || (p.playbooks ? p.playbooks.length : 0)}): ${pbNames || "(none)"}`);
|
|
310
|
-
console.log("");
|
|
311
|
-
}
|
|
312
|
-
console.log("Tip: Run 'ad info <package-id> --server <url>' to view detailed package configuration and schema.");
|
|
313
|
-
return;
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
console.log(JSON.stringify(remoteInfo, null, 2));
|
|
317
|
-
return;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
// Local Tree
|
|
321
|
-
if (options.tree) {
|
|
322
|
-
const status = getRegistryStatus();
|
|
323
|
-
if (isMachine) {
|
|
324
|
-
renderResult(status, { json: options.json, envelope: options.envelope });
|
|
325
|
-
} else {
|
|
326
|
-
printRegistryTree(status);
|
|
327
|
-
}
|
|
328
|
-
return;
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
// 2. Explicit package option (-P, --package)
|
|
332
|
-
if (options.package) {
|
|
333
|
-
const directRoot = resolvePackageRoot(options.package);
|
|
334
|
-
if (directRoot) {
|
|
335
|
-
const detail = await getProjectDetailInfo(directRoot);
|
|
336
|
-
if (isMachine) {
|
|
337
|
-
renderResult(projectDetailToJson(detail), { json: options.json, envelope: options.envelope });
|
|
338
|
-
} else {
|
|
339
|
-
printProjectDetail(detail);
|
|
340
|
-
}
|
|
341
|
-
return;
|
|
342
|
-
}
|
|
343
|
-
throw new ArgumentError(
|
|
344
|
-
`Package '${options.package}' not found in linked packages or path`
|
|
345
|
-
);
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
// 3. Collect local candidate packages (current project + linked packages)
|
|
349
|
-
const currentRoot = findProjectRoot();
|
|
350
|
-
const linkedList = listLinkedPackages();
|
|
351
|
-
const aggregated: AggregatedPackage[] = [];
|
|
352
|
-
const seenPaths = new Set<string>();
|
|
353
|
-
|
|
354
|
-
if (currentRoot) {
|
|
355
|
-
try {
|
|
356
|
-
const config = loadProjectConfig(currentRoot);
|
|
357
|
-
const manifest = loadManifest(currentRoot);
|
|
358
|
-
const manifestActionIds = manifest?.actions ? Object.keys(manifest.actions) : [];
|
|
359
|
-
const playbooks = loadPlaybooks(currentRoot, config.playbooksDir);
|
|
360
|
-
aggregated.push({
|
|
361
|
-
id: config.id,
|
|
362
|
-
name: config.name,
|
|
363
|
-
version: config.version,
|
|
364
|
-
description: config.description,
|
|
365
|
-
path: currentRoot,
|
|
366
|
-
actionsCount: manifestActionIds.length,
|
|
367
|
-
playbooksCount: playbooks.size,
|
|
368
|
-
actions: manifestActionIds,
|
|
369
|
-
playbooks: Array.from(playbooks.keys()),
|
|
370
|
-
configDeclared: config.config ? Object.keys(config.config) : [],
|
|
371
|
-
});
|
|
372
|
-
seenPaths.add(currentRoot);
|
|
373
|
-
} catch {
|
|
374
|
-
// Ignore broken project root
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
for (const pkg of linkedList) {
|
|
379
|
-
if (!existsSync(pkg.path)) continue;
|
|
380
|
-
if (seenPaths.has(pkg.path)) continue;
|
|
381
|
-
try {
|
|
382
|
-
const config = loadProjectConfig(pkg.path);
|
|
383
|
-
const manifest = loadManifest(pkg.path);
|
|
384
|
-
const manifestActionIds = manifest?.actions ? Object.keys(manifest.actions) : [];
|
|
385
|
-
const playbooks = loadPlaybooks(pkg.path, config.playbooksDir);
|
|
386
|
-
|
|
387
|
-
aggregated.push({
|
|
388
|
-
id: config.id,
|
|
389
|
-
name: config.name,
|
|
390
|
-
version: config.version,
|
|
391
|
-
description: config.description,
|
|
392
|
-
path: pkg.path,
|
|
393
|
-
actionsCount: manifestActionIds.length,
|
|
394
|
-
playbooksCount: playbooks.size,
|
|
395
|
-
actions: manifestActionIds,
|
|
396
|
-
playbooks: Array.from(playbooks.keys()),
|
|
397
|
-
configDeclared: config.config ? Object.keys(config.config) : [],
|
|
398
|
-
});
|
|
399
|
-
seenPaths.add(pkg.path);
|
|
400
|
-
} catch {
|
|
401
|
-
// Ignore broken linked package
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
// 4. Case: No pattern / intent specified
|
|
406
|
-
if (!effectiveIntent) {
|
|
407
|
-
if (currentRoot) {
|
|
408
|
-
const detail = await getProjectDetailInfo(currentRoot);
|
|
409
|
-
if (isMachine) {
|
|
410
|
-
renderResult(projectDetailToJson(detail), { json: options.json, envelope: options.envelope });
|
|
411
|
-
} else {
|
|
412
|
-
printProjectDetail(detail);
|
|
413
|
-
}
|
|
414
|
-
return;
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
if (aggregated.length === 0) {
|
|
418
|
-
if (isMachine) {
|
|
419
|
-
renderResult({ linkedPackages: [] }, { json: options.json, envelope: options.envelope });
|
|
420
|
-
return;
|
|
421
|
-
}
|
|
422
|
-
console.log(
|
|
423
|
-
"No ActionDock project in current directory, and no packages linked."
|
|
424
|
-
);
|
|
425
|
-
console.log(
|
|
426
|
-
"Run 'ad link' inside an Action package or specify a target package."
|
|
427
|
-
);
|
|
428
|
-
return;
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
if (isMachine) {
|
|
432
|
-
renderResult({ linkedPackages: aggregated }, { json: options.json, envelope: options.envelope });
|
|
433
|
-
} else {
|
|
434
|
-
printAggregatedPackages(aggregated);
|
|
435
|
-
}
|
|
436
|
-
return;
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
// 5. Case: Pattern / intent specified
|
|
440
|
-
// 5.1 Check if single positional argument directly matches an exact path or package ID/slug
|
|
441
|
-
if (patterns.length === 1 && !options.intent) {
|
|
442
|
-
const directRoot = resolvePackageRoot(patterns[0]);
|
|
443
|
-
if (directRoot) {
|
|
444
|
-
const detail = await getProjectDetailInfo(directRoot);
|
|
445
|
-
if (isMachine) {
|
|
446
|
-
renderResult(projectDetailToJson(detail), { json: options.json, envelope: options.envelope });
|
|
447
|
-
} else {
|
|
448
|
-
printProjectDetail(detail);
|
|
449
|
-
}
|
|
450
|
-
return;
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
if (aggregated.length === 0) {
|
|
455
|
-
if (isMachine) {
|
|
456
|
-
renderResult({ linkedPackages: [], matchedCount: 0, isFallback: false }, { json: options.json, envelope: options.envelope });
|
|
457
|
-
return;
|
|
458
|
-
}
|
|
459
|
-
throw new ExecutionError(
|
|
460
|
-
`No ActionDock project or linked packages available to match '${effectiveIntent}'`
|
|
461
|
-
);
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
// 5.2 Intent filtering across candidate packages
|
|
465
|
-
const filterRes = filterWithFallbackInfo(
|
|
466
|
-
aggregated,
|
|
467
|
-
effectiveIntent,
|
|
468
|
-
[
|
|
469
|
-
(p) => p.id,
|
|
470
|
-
(p) => p.name,
|
|
471
|
-
(p) => p.description,
|
|
472
|
-
(p) => p.path,
|
|
473
|
-
(p) => p.actions,
|
|
474
|
-
(p) => p.playbooks,
|
|
475
|
-
],
|
|
476
|
-
shouldFallback
|
|
477
|
-
);
|
|
478
|
-
|
|
479
|
-
// Subcase A: 0 items matched
|
|
480
|
-
if (filterRes.matchedCount === 0) {
|
|
481
|
-
if (!filterRes.isFallback) {
|
|
482
|
-
if (isMachine) {
|
|
483
|
-
renderResult({ linkedPackages: [], matchedCount: 0, isFallback: false }, { json: options.json, envelope: options.envelope });
|
|
484
|
-
return;
|
|
485
|
-
}
|
|
486
|
-
throw new ExecutionError(
|
|
487
|
-
`No packages matched intent '${effectiveIntent}'`
|
|
488
|
-
);
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
// Fallback enabled: display all packages with a notice
|
|
492
|
-
if (isMachine) {
|
|
493
|
-
renderResult(
|
|
494
|
-
{ linkedPackages: filterRes.items, isFallback: true, matchedCount: 0 },
|
|
495
|
-
{ json: options.json, envelope: options.envelope }
|
|
496
|
-
);
|
|
497
|
-
return;
|
|
498
|
-
}
|
|
499
|
-
console.log(
|
|
500
|
-
`(No linked packages matched intent '${effectiveIntent}', showing all packages)\n`
|
|
501
|
-
);
|
|
502
|
-
printAggregatedPackages(filterRes.items);
|
|
503
|
-
return;
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
// Subcase B: Matched items in machine mode
|
|
507
|
-
if (isMachine) {
|
|
508
|
-
renderResult(
|
|
509
|
-
{ linkedPackages: filterRes.items, matchedCount: filterRes.matchedCount, isFallback: false },
|
|
510
|
-
{ json: options.json, envelope: options.envelope }
|
|
511
|
-
);
|
|
512
|
-
return;
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
// Subcase C: Exactly 1 item matched in human terminal mode -> Display full project detail
|
|
516
|
-
if (filterRes.matchedCount === 1) {
|
|
517
|
-
const matchedPkg = filterRes.items[0];
|
|
518
|
-
const detail = await getProjectDetailInfo(matchedPkg.path);
|
|
519
|
-
printProjectDetail(detail);
|
|
520
|
-
return;
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
// Subcase D: Multiple items matched in human terminal mode -> Display filtered summary list
|
|
524
|
-
printAggregatedPackages(filterRes.items, {
|
|
525
|
-
header: `ActionDock Linked Packages (${filterRes.matchedCount} matches for '${effectiveIntent}'):\n`,
|
|
526
|
-
showTip: true,
|
|
527
|
-
});
|
|
528
|
-
} catch (err: any) {
|
|
529
|
-
if (err instanceof CliError) {
|
|
530
|
-
throw err;
|
|
531
|
-
}
|
|
532
|
-
throw new ExecutionError(err.message);
|
|
533
|
-
}
|
|
534
|
-
});
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
|
package/src/commands/init.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { initProject } from "@actiondock/core";
|
|
2
|
-
import { ExecutionError } from "@actiondock/runtime-cli";
|
|
3
|
-
import { Command } from "commander";
|
|
4
|
-
|
|
5
|
-
export function registerInitCommand(program: Command): void {
|
|
6
|
-
program
|
|
7
|
-
.command("init [directory]")
|
|
8
|
-
.description("Initialize a new ActionDock project")
|
|
9
|
-
.option("-i, --id <id>", "Project identifier")
|
|
10
|
-
.option("-n, --name <name>", "Project display name")
|
|
11
|
-
.option("-d, --desc <description>", "Project description")
|
|
12
|
-
.action((dir = ".", options) => {
|
|
13
|
-
try {
|
|
14
|
-
initProject(dir, {
|
|
15
|
-
id: options.id,
|
|
16
|
-
name: options.name,
|
|
17
|
-
description: options.desc,
|
|
18
|
-
});
|
|
19
|
-
console.log(`Successfully initialized ActionDock project in ${dir}`);
|
|
20
|
-
} catch (err: any) {
|
|
21
|
-
throw new ExecutionError(err.message);
|
|
22
|
-
}
|
|
23
|
-
});
|
|
24
|
-
}
|
package/src/commands/link.ts
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
linkPackage,
|
|
3
|
-
pruneRegistry,
|
|
4
|
-
unlinkPackage,
|
|
5
|
-
} from "@actiondock/core";
|
|
6
|
-
import { ExecutionError } from "@actiondock/runtime-cli";
|
|
7
|
-
import { Command } from "commander";
|
|
8
|
-
|
|
9
|
-
export function registerLinkCommands(program: Command): void {
|
|
10
|
-
// ad link [path]
|
|
11
|
-
program
|
|
12
|
-
.command("link [path]")
|
|
13
|
-
.option("-r, --recursive", "Recursively discover and link packages in subdirectories")
|
|
14
|
-
.description("Link local Action package(s) or workspace directory into global registry for instant cross-directory execution")
|
|
15
|
-
.action(async (targetPath, options) => {
|
|
16
|
-
try {
|
|
17
|
-
const result = linkPackage(targetPath || process.cwd(), undefined, {
|
|
18
|
-
recursive: options.recursive,
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
if (result.isWorkspace) {
|
|
22
|
-
console.log(`[OK] Linked workspace '${result.path}' (${result.entries.length} package${result.entries.length > 1 ? "s" : ""}):`);
|
|
23
|
-
for (const e of result.entries) {
|
|
24
|
-
console.log(` - ${e.id} (v${e.version}) -> ${e.path}`);
|
|
25
|
-
}
|
|
26
|
-
console.log("[INFO] Sub-packages added to this workspace will be automatically discovered.");
|
|
27
|
-
} else {
|
|
28
|
-
console.log(`[OK] Linked package '${result.id}' (v${result.version}) from ${result.path}`);
|
|
29
|
-
}
|
|
30
|
-
} catch (err: any) {
|
|
31
|
-
throw new ExecutionError(err.message);
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
// ad unlink [id|path]
|
|
36
|
-
program
|
|
37
|
-
.command("unlink [identifier]")
|
|
38
|
-
.option("-p, --prune", "Automatically scan and prune any stale/missing paths from registry")
|
|
39
|
-
.description("Unlink a package, workspace, or prune stale entries from global developer registry")
|
|
40
|
-
.action((identifier, options) => {
|
|
41
|
-
try {
|
|
42
|
-
if (options.prune || identifier === "--prune") {
|
|
43
|
-
const result = pruneRegistry();
|
|
44
|
-
const totalPruned = result.prunedPackages.length + result.prunedWorkspaces.length;
|
|
45
|
-
if (totalPruned === 0) {
|
|
46
|
-
console.log("[OK] No stale registry entries found.");
|
|
47
|
-
} else {
|
|
48
|
-
console.log(`[OK] Pruned ${result.prunedWorkspaces.length} workspace(s) and ${result.prunedPackages.length} package(s) from registry.`);
|
|
49
|
-
for (const ws of result.prunedWorkspaces) {
|
|
50
|
-
console.log(` - [workspace] ${ws.path}`);
|
|
51
|
-
}
|
|
52
|
-
for (const pkg of result.prunedPackages) {
|
|
53
|
-
console.log(` - [package] ${pkg.id} (${pkg.path})`);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const removed = unlinkPackage(identifier || process.cwd());
|
|
60
|
-
if (removed) {
|
|
61
|
-
if (removed.type === "workspace") {
|
|
62
|
-
console.log(`[OK] Unlinked workspace '${removed.path}' (${removed.packagesCount || 0} package${(removed.packagesCount || 0) > 1 ? "s" : ""} unlinked)`);
|
|
63
|
-
} else {
|
|
64
|
-
console.log(`[OK] Unlinked package '${removed.id}' (${removed.path})`);
|
|
65
|
-
}
|
|
66
|
-
} else {
|
|
67
|
-
console.log(`Package or workspace '${identifier || process.cwd()}' was not linked in registry`);
|
|
68
|
-
}
|
|
69
|
-
} catch (err: any) {
|
|
70
|
-
throw new ExecutionError(err.message);
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
}
|