@actiondock/cli 2.0.9 → 2.0.11-beta.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 +17 -0
- package/dist/index.js +46701 -35780
- package/package.json +7 -7
- package/src/commands/action/create.ts +129 -0
- package/src/commands/action/index.ts +27 -0
- package/src/commands/action/list.ts +247 -0
- package/src/commands/action/run.ts +197 -0
- package/src/commands/action/show.ts +128 -0
- package/src/commands/action/sync.ts +76 -0
- package/src/commands/action/validate.ts +102 -0
- package/src/commands/action.ts +1 -633
- package/src/commands/build.ts +19 -17
- package/src/commands/config.ts +168 -69
- package/src/commands/doctor.ts +44 -42
- package/src/commands/export.ts +140 -14
- package/src/commands/index.ts +33 -1
- package/src/commands/info.ts +93 -74
- package/src/commands/init.ts +2 -2
- package/src/commands/link.ts +3 -4
- package/src/commands/mcp.ts +6 -10
- package/src/commands/playbook.ts +289 -161
- package/src/commands/profile.ts +125 -92
- package/src/commands/runs.ts +92 -49
- package/src/commands/serve.ts +3 -4
- package/src/commands/state.ts +145 -64
- package/src/commands/test.ts +1 -1
- package/src/index.ts +39 -3
- package/src/utils/bytes.ts +1 -35
- package/src/utils/filter.ts +2 -24
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import {
|
|
2
|
+
fetchRemoteActionShow,
|
|
3
|
+
loadManifest,
|
|
4
|
+
loadProjectConfig,
|
|
5
|
+
resolveActionProject,
|
|
6
|
+
resolvePackageRoot,
|
|
7
|
+
resolveTarget,
|
|
8
|
+
} from "@actiondock/core";
|
|
9
|
+
import {
|
|
10
|
+
ArgumentError,
|
|
11
|
+
ExecutionError,
|
|
12
|
+
getEffectiveOptions,
|
|
13
|
+
renderResult,
|
|
14
|
+
} from "@actiondock/runtime-cli";
|
|
15
|
+
import type { Command } from "commander";
|
|
16
|
+
|
|
17
|
+
export function registerActionShowCommand(actionCmd: Command): void {
|
|
18
|
+
actionCmd
|
|
19
|
+
.command("show <id>")
|
|
20
|
+
.alias("describe")
|
|
21
|
+
.description("Show action definition, schema, and description")
|
|
22
|
+
.option("-P, --package <id>", "Target package ID or path")
|
|
23
|
+
.option("-p, --profile <name>", "Execute or query against a specific profile")
|
|
24
|
+
.option("-s, --server <url>", "Remote server URL")
|
|
25
|
+
.option("-t, --token <token>", "Auth token for remote server")
|
|
26
|
+
.option("--json", "Output as JSON")
|
|
27
|
+
.option("--envelope", "Wrap JSON output in standard envelope")
|
|
28
|
+
.action(async (id, rawOptions, cmd) => {
|
|
29
|
+
try {
|
|
30
|
+
const options = getEffectiveOptions(rawOptions, cmd);
|
|
31
|
+
if (!id) {
|
|
32
|
+
throw new ArgumentError("Action ID is required for show/describe");
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const target = resolveTarget({
|
|
36
|
+
profile: options.profile,
|
|
37
|
+
server: options.server,
|
|
38
|
+
token: options.token,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
if (target.type === "remote") {
|
|
42
|
+
const detail = await fetchRemoteActionShow(
|
|
43
|
+
target.serverUrl!,
|
|
44
|
+
id,
|
|
45
|
+
target.token
|
|
46
|
+
);
|
|
47
|
+
renderResult(detail, {
|
|
48
|
+
json: options.json,
|
|
49
|
+
envelope: options.envelope,
|
|
50
|
+
humanFormatter: () => {
|
|
51
|
+
const lines = [`Action: ${detail.id}`];
|
|
52
|
+
if (detail.packageId) lines.push(`Package: ${detail.packageId}`);
|
|
53
|
+
if (detail.description) lines.push(`Description: ${detail.description}`);
|
|
54
|
+
if (detail.inputSchema) {
|
|
55
|
+
lines.push("\nInput Schema:", JSON.stringify(detail.inputSchema, null, 2));
|
|
56
|
+
}
|
|
57
|
+
if (detail.outputSchema) {
|
|
58
|
+
lines.push("\nOutput Schema:", JSON.stringify(detail.outputSchema, null, 2));
|
|
59
|
+
}
|
|
60
|
+
return lines.join("\n");
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
let showTarget = id;
|
|
67
|
+
if (options.package && !id.includes("/") && !id.includes(":")) {
|
|
68
|
+
const pkgRoot = resolvePackageRoot(options.package);
|
|
69
|
+
if (!pkgRoot) {
|
|
70
|
+
throw new ArgumentError(
|
|
71
|
+
`Package '${options.package}' not found in linked packages or path`
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
showTarget = `${options.package}/${id}`;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
let resolved;
|
|
78
|
+
try {
|
|
79
|
+
resolved = await resolveActionProject(showTarget);
|
|
80
|
+
} catch (err: any) {
|
|
81
|
+
if (err.message?.includes("not found") || err.message?.includes("no longer exists")) {
|
|
82
|
+
throw new ArgumentError(err.message);
|
|
83
|
+
}
|
|
84
|
+
throw new ExecutionError(err.message);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const manifest = loadManifest(resolved.projectRoot);
|
|
88
|
+
const actionMeta = manifest?.actions?.[resolved.actionId];
|
|
89
|
+
|
|
90
|
+
if (!actionMeta) {
|
|
91
|
+
throw new ArgumentError(
|
|
92
|
+
`Action '${resolved.actionId}' not found in package '${resolved.packageId}'`
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const payload = {
|
|
97
|
+
id: resolved.actionId,
|
|
98
|
+
packageId: resolved.packageId,
|
|
99
|
+
projectRoot: resolved.projectRoot,
|
|
100
|
+
description: actionMeta.description,
|
|
101
|
+
inputSchema: actionMeta.inputSchema,
|
|
102
|
+
outputSchema: actionMeta.outputSchema,
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
renderResult(payload, {
|
|
106
|
+
json: options.json,
|
|
107
|
+
envelope: options.envelope,
|
|
108
|
+
humanFormatter: () => {
|
|
109
|
+
const lines = [
|
|
110
|
+
`Action: ${resolved.actionId}`,
|
|
111
|
+
`Package: ${resolved.packageId} (${resolved.projectRoot})`,
|
|
112
|
+
];
|
|
113
|
+
if (actionMeta.description) lines.push(`Description: ${actionMeta.description}`);
|
|
114
|
+
if (actionMeta.inputSchema) {
|
|
115
|
+
lines.push("\nInput Schema:", JSON.stringify(actionMeta.inputSchema, null, 2));
|
|
116
|
+
}
|
|
117
|
+
if (actionMeta.outputSchema) {
|
|
118
|
+
lines.push("\nOutput Schema:", JSON.stringify(actionMeta.outputSchema, null, 2));
|
|
119
|
+
}
|
|
120
|
+
return lines.join("\n");
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
} catch (err: any) {
|
|
124
|
+
if (err instanceof ArgumentError || err instanceof ExecutionError) throw err;
|
|
125
|
+
throw new ExecutionError(err.message);
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { findProjectRoot, syncManifest } from "@actiondock/core";
|
|
2
|
+
import { ExecutionError, getEffectiveOptions, renderResult } from "@actiondock/runtime-cli";
|
|
3
|
+
import type { Command } from "commander";
|
|
4
|
+
|
|
5
|
+
export function registerActionSyncCommand(actionCmd: Command): void {
|
|
6
|
+
actionCmd
|
|
7
|
+
.command("sync")
|
|
8
|
+
.description("Synchronize action metadata manifest with TypeScript definitions")
|
|
9
|
+
.option("--check", "Check if manifest is synchronized without modifying files")
|
|
10
|
+
.option("--no-prune", "Do not remove deleted actions from manifest")
|
|
11
|
+
.option("--json", "Output as JSON")
|
|
12
|
+
.option("--envelope", "Wrap JSON output in standard envelope")
|
|
13
|
+
.action(async (rawOptions, cmd) => {
|
|
14
|
+
const options = getEffectiveOptions(rawOptions, cmd);
|
|
15
|
+
const root = findProjectRoot();
|
|
16
|
+
if (!root) {
|
|
17
|
+
throw new ExecutionError("Not in an ActionDock project (actiondock.json not found)");
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
const result = await syncManifest(root, {
|
|
22
|
+
check: Boolean(options.check),
|
|
23
|
+
prune: options.prune !== false,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
renderResult(result, {
|
|
27
|
+
json: options.json,
|
|
28
|
+
envelope: options.envelope,
|
|
29
|
+
humanFormatter: () => {
|
|
30
|
+
const lines: string[] = [];
|
|
31
|
+
if (options.check) {
|
|
32
|
+
if (result.inSync) {
|
|
33
|
+
lines.push("[OK] actiondock.manifest.json is up to date.");
|
|
34
|
+
} else {
|
|
35
|
+
lines.push("[FAIL] actiondock.manifest.json is out of sync with action definitions:\n");
|
|
36
|
+
if (result.added.length > 0) {
|
|
37
|
+
lines.push(` - Added actions: ${result.added.join(", ")}`);
|
|
38
|
+
}
|
|
39
|
+
if (result.updated.length > 0) {
|
|
40
|
+
lines.push(` - Updated actions: ${result.updated.join(", ")}`);
|
|
41
|
+
}
|
|
42
|
+
if (result.removed.length > 0) {
|
|
43
|
+
lines.push(` - Removed actions: ${result.removed.join(", ")}`);
|
|
44
|
+
}
|
|
45
|
+
lines.push("\nRun 'ad action sync' to synchronize metadata manifest.");
|
|
46
|
+
}
|
|
47
|
+
} else {
|
|
48
|
+
if (result.inSync) {
|
|
49
|
+
lines.push(`[OK] actiondock.manifest.json is already up to date (${result.unchanged.length} action(s)).`);
|
|
50
|
+
} else {
|
|
51
|
+
lines.push("[OK] Successfully synchronized actiondock.manifest.json:\n");
|
|
52
|
+
if (result.added.length > 0) {
|
|
53
|
+
lines.push(` - Added: ${result.added.join(", ")}`);
|
|
54
|
+
}
|
|
55
|
+
if (result.updated.length > 0) {
|
|
56
|
+
lines.push(` - Updated: ${result.updated.join(", ")}`);
|
|
57
|
+
}
|
|
58
|
+
if (result.removed.length > 0) {
|
|
59
|
+
lines.push(` - Removed: ${result.removed.join(", ")}`);
|
|
60
|
+
}
|
|
61
|
+
lines.push(`\nManifest updated at ${result.manifestPath}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return lines.join("\n");
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
if (options.check && !result.inSync) {
|
|
69
|
+
process.exitCode = 1;
|
|
70
|
+
}
|
|
71
|
+
} catch (err: any) {
|
|
72
|
+
if (err instanceof ExecutionError) throw err;
|
|
73
|
+
throw new ExecutionError(err.message);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import {
|
|
2
|
+
findProjectRoot,
|
|
3
|
+
loadActions,
|
|
4
|
+
loadProjectConfig,
|
|
5
|
+
resolvePackageRoot,
|
|
6
|
+
validateSchema,
|
|
7
|
+
} from "@actiondock/core";
|
|
8
|
+
import {
|
|
9
|
+
ArgumentError,
|
|
10
|
+
ExecutionError,
|
|
11
|
+
getEffectiveOptions,
|
|
12
|
+
renderResult,
|
|
13
|
+
} from "@actiondock/runtime-cli";
|
|
14
|
+
import type { Command } from "commander";
|
|
15
|
+
|
|
16
|
+
export function registerActionValidateCommand(actionCmd: Command): void {
|
|
17
|
+
actionCmd
|
|
18
|
+
.command("validate [id]")
|
|
19
|
+
.description("Validate action schemas and definitions")
|
|
20
|
+
.option("-P, --package <id>", "Target package ID or path")
|
|
21
|
+
.option("--json", "Output as JSON")
|
|
22
|
+
.option("--envelope", "Wrap JSON output in standard envelope")
|
|
23
|
+
.action(async (id, rawOptions, cmd) => {
|
|
24
|
+
const options = getEffectiveOptions(rawOptions, cmd);
|
|
25
|
+
let root: string | null = null;
|
|
26
|
+
if (options.package) {
|
|
27
|
+
root = resolvePackageRoot(options.package);
|
|
28
|
+
if (!root) {
|
|
29
|
+
throw new ArgumentError(
|
|
30
|
+
`Package '${options.package}' not found in linked packages or path`
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
} else {
|
|
34
|
+
root = findProjectRoot();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (!root) {
|
|
38
|
+
throw new ArgumentError("Not in an ActionDock project (actiondock.json not found)");
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
try {
|
|
42
|
+
const config = loadProjectConfig(root);
|
|
43
|
+
const actions = await loadActions(root, config.actionsDir);
|
|
44
|
+
|
|
45
|
+
const toValidate = id ? [actions.get(id)].filter(Boolean) : Array.from(actions.values());
|
|
46
|
+
if (id && toValidate.length === 0) {
|
|
47
|
+
throw new ArgumentError(`Action '${id}' not found in project`);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const results: Array<{ id: string; valid: boolean; errors: string[] }> = [];
|
|
51
|
+
|
|
52
|
+
for (const act of toValidate as any[]) {
|
|
53
|
+
const errors: string[] = [];
|
|
54
|
+
if (!act.id) errors.push("Missing id property");
|
|
55
|
+
if (!act.run || typeof act.run !== "function") errors.push("Missing run method");
|
|
56
|
+
if (act.inputSchema) {
|
|
57
|
+
validateSchema(act.inputSchema, {});
|
|
58
|
+
if (typeof act.inputSchema !== "object") {
|
|
59
|
+
errors.push("Invalid inputSchema object");
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (act.outputSchema) {
|
|
63
|
+
if (typeof act.outputSchema !== "object") {
|
|
64
|
+
errors.push("Invalid outputSchema object");
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
results.push({
|
|
68
|
+
id: act.id,
|
|
69
|
+
valid: errors.length === 0,
|
|
70
|
+
errors,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const allValid = results.every((r) => r.valid);
|
|
75
|
+
renderResult(
|
|
76
|
+
{ valid: allValid, results },
|
|
77
|
+
{
|
|
78
|
+
json: options.json,
|
|
79
|
+
envelope: options.envelope,
|
|
80
|
+
humanFormatter: () => {
|
|
81
|
+
const lines: string[] = [];
|
|
82
|
+
for (const r of results) {
|
|
83
|
+
if (r.valid) {
|
|
84
|
+
lines.push(`[OK] ${r.id}: Valid`);
|
|
85
|
+
} else {
|
|
86
|
+
lines.push(`[FAIL] ${r.id}: ${r.errors.join(", ")}`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return lines.join("\n");
|
|
90
|
+
},
|
|
91
|
+
}
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
if (!allValid) {
|
|
95
|
+
process.exitCode = 1;
|
|
96
|
+
}
|
|
97
|
+
} catch (err: any) {
|
|
98
|
+
if (err instanceof ArgumentError || err instanceof ExecutionError) throw err;
|
|
99
|
+
throw new ExecutionError(err.message);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
}
|