@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.
Files changed (54) hide show
  1. package/README.md +15 -2
  2. package/bin/ad.js +13 -2
  3. package/dist/commands/action/create.d.ts +2 -0
  4. package/dist/commands/action/index.d.ts +16 -0
  5. package/dist/commands/action/list.d.ts +5 -0
  6. package/dist/commands/action/run.d.ts +4 -0
  7. package/dist/commands/action/show.d.ts +5 -0
  8. package/dist/commands/action/sync.d.ts +2 -0
  9. package/dist/commands/action/validate.d.ts +5 -0
  10. package/dist/commands/build.d.ts +2 -0
  11. package/dist/commands/config.d.ts +2 -0
  12. package/dist/commands/doctor.d.ts +2 -0
  13. package/dist/commands/export.d.ts +2 -0
  14. package/dist/commands/index.d.ts +2 -0
  15. package/dist/commands/info.d.ts +2 -0
  16. package/dist/commands/init.d.ts +2 -0
  17. package/dist/commands/link.d.ts +2 -0
  18. package/dist/commands/mcp.d.ts +2 -0
  19. package/dist/commands/playbook.d.ts +6 -0
  20. package/dist/commands/profile.d.ts +2 -0
  21. package/dist/commands/runs.d.ts +2 -0
  22. package/dist/commands/serve.d.ts +2 -0
  23. package/dist/commands/state.d.ts +2 -0
  24. package/dist/commands/test.d.ts +2 -0
  25. package/dist/index.d.ts +8 -0
  26. package/dist/index.js +745 -65708
  27. package/{src/utils/bytes.ts → dist/utils/bytes.d.ts} +0 -1
  28. package/{src/utils/filter.ts → dist/utils/filter.d.ts} +0 -1
  29. package/package.json +20 -15
  30. package/src/commands/action/create.ts +0 -129
  31. package/src/commands/action/index.ts +0 -27
  32. package/src/commands/action/list.ts +0 -247
  33. package/src/commands/action/run.ts +0 -197
  34. package/src/commands/action/show.ts +0 -128
  35. package/src/commands/action/sync.ts +0 -76
  36. package/src/commands/action/validate.ts +0 -102
  37. package/src/commands/build.ts +0 -56
  38. package/src/commands/config.ts +0 -583
  39. package/src/commands/doctor.ts +0 -84
  40. package/src/commands/export.ts +0 -196
  41. package/src/commands/index.ts +0 -75
  42. package/src/commands/info.ts +0 -537
  43. package/src/commands/init.ts +0 -24
  44. package/src/commands/link.ts +0 -73
  45. package/src/commands/mcp.ts +0 -195
  46. package/src/commands/playbook.ts +0 -566
  47. package/src/commands/profile.ts +0 -296
  48. package/src/commands/runs.ts +0 -452
  49. package/src/commands/serve.ts +0 -132
  50. package/src/commands/state.ts +0 -590
  51. package/src/commands/test.ts +0 -48
  52. package/src/index.ts +0 -58
  53. /package/{src/commands/action.ts → dist/commands/action.d.ts} +0 -0
  54. /package/{src/utils/duration.ts → dist/utils/duration.d.ts} +0 -0
@@ -1,296 +0,0 @@
1
- import {
2
- addProfile,
3
- checkRemoteHealth,
4
- filterWithFallbackInfo,
5
- getProfile,
6
- listProfiles,
7
- loadProfiles,
8
- maskSecretValue,
9
- removeProfile,
10
- resolveProfileToken,
11
- resolveTarget,
12
- toSnakeUpperCase,
13
- useProfile,
14
- } from "@actiondock/core";
15
- import { Command } from "commander";
16
- import {
17
- ArgumentError,
18
- CliError,
19
- ExecutionError,
20
- getEffectiveOptions,
21
- renderResult,
22
- } from "@actiondock/runtime-cli";
23
- import { resolveIntent } from "../utils/filter";
24
-
25
- export function registerProfileCommands(program: Command): void {
26
- const profileCmd = program
27
- .command("profile")
28
- .description("Manage multi-cloud and remote execution profiles");
29
-
30
- // ad profile list
31
- profileCmd
32
- .command("list [patterns...]")
33
- .description("List all configured profiles")
34
- .option("-i, --intent <pattern>", "Regex or fuzzy intent filter; falls back to full list when no match")
35
- .option("--reveal, --show-secrets", "Reveal plain text values for tokens")
36
- .option("--fallback", "Enable fallback to full list when no items match intent")
37
- .option("--no-fallback", "Disable fallback to full list when no items match intent")
38
- .option("--json", "Output as JSON")
39
- .option("--envelope", "Wrap JSON output in standard envelope")
40
- .action((patterns, rawOptions, cmd) => {
41
- try {
42
- const options = getEffectiveOptions(rawOptions, cmd);
43
- const effectiveIntent = resolveIntent(options.intent, patterns);
44
- const isMachine = Boolean(options.json || options.envelope);
45
- const fallbackExplicit = options.fallback === true || (Array.isArray(process.argv) && process.argv.includes("--fallback"));
46
- const shouldFallback = isMachine ? fallbackExplicit : options.fallback !== false;
47
- const reveal = Boolean(options.reveal || options.showSecrets);
48
-
49
- const list = listProfiles();
50
- const enriched = list.map((p) => {
51
- const resolved = resolveProfileToken(p.name, p.entry);
52
- return {
53
- name: p.name,
54
- isCurrent: p.isCurrent,
55
- serverUrl: p.entry.serverUrl,
56
- description: p.entry.description || "",
57
- tokenEnv: p.entry.tokenEnv,
58
- tokenConfigured: resolved.source !== "none",
59
- tokenSource: resolved.source,
60
- token: reveal ? resolved.token : (resolved.token ? maskSecretValue(resolved.token) : undefined),
61
- };
62
- });
63
-
64
- const filterRes = filterWithFallbackInfo(
65
- enriched,
66
- effectiveIntent,
67
- [(p) => p.name, (p) => p.serverUrl, (p) => p.description, (p) => p.tokenSource],
68
- shouldFallback
69
- );
70
-
71
- if (filterRes.isFallback && isMachine) {
72
- renderResult(
73
- { items: filterRes.items, isFallback: true, matchedCount: 0 },
74
- { json: options.json, envelope: options.envelope }
75
- );
76
- return;
77
- }
78
-
79
- renderResult(filterRes.items, {
80
- json: options.json,
81
- envelope: options.envelope,
82
- humanFormatter: () => {
83
- const lines = ["ActionDock Execution Profiles:\n"];
84
- if (filterRes.isFallback && effectiveIntent) {
85
- lines.push(`(No profiles matched intent '${effectiveIntent}', showing all profiles)\n`);
86
- }
87
- for (const item of filterRes.items) {
88
- const currentMarker = item.isCurrent ? "* " : " ";
89
- let tokenInfo = "";
90
- if (item.tokenSource === "tokenEnv") {
91
- tokenInfo = ` [token: env(${item.tokenEnv})]`;
92
- } else if (item.tokenSource === "profileEnv") {
93
- tokenInfo = ` [token: env(ACTIONDOCK_${toSnakeUpperCase(item.name)}_TOKEN)]`;
94
- } else if (item.tokenSource === "profile") {
95
- tokenInfo = ` [token: stored in profile]`;
96
- } else if (item.tokenSource === "globalEnv") {
97
- tokenInfo = ` [token: env(ACTIONDOCK_TOKEN)]`;
98
- }
99
-
100
- if (reveal && item.token) {
101
- tokenInfo += ` = ${item.token}`;
102
- }
103
-
104
- const desc = item.description ? ` - ${item.description}` : "";
105
- lines.push(
106
- `${currentMarker}${item.name.padEnd(20)} ${item.serverUrl}${tokenInfo}${desc}`
107
- );
108
- }
109
- lines.push(
110
- "\nUse 'ad profile use <name>' to switch or 'ad run <action> --profile <name>' to execute on a specific target."
111
- );
112
- return lines.join("\n");
113
- },
114
- });
115
- } catch (err: any) {
116
- if (err instanceof ArgumentError || err instanceof CliError) throw err;
117
- throw new ExecutionError(err.message);
118
- }
119
- });
120
-
121
- // ad profile add <name>
122
- profileCmd
123
- .command("add <name>")
124
- .description("Add or update a remote execution profile")
125
- .requiredOption("-s, --server <url>", "Remote ActionDock server URL (e.g. http://1.2.3.4:5177)")
126
- .option("-t, --token <token>", "Authentication token for the remote server (deprecated; prefer --token-env)")
127
- .option("--token-env <env>", "Environment variable name containing the authentication token")
128
- .option("-d, --desc <description>", "Description of this profile/machine")
129
- .action((name, options) => {
130
- try {
131
- if (options.token) {
132
- console.warn(
133
- "Warning: storing tokens directly in profiles.json is deprecated. Use --token-env or standard environment variables (e.g. ACTIONDOCK_<PROFILE>_TOKEN) instead."
134
- );
135
- }
136
- addProfile(name, {
137
- serverUrl: options.server,
138
- token: options.token,
139
- tokenEnv: options.tokenEnv,
140
- description: options.desc,
141
- });
142
- console.log(`[OK] Profile '${name}' configured for server: ${options.server}`);
143
- } catch (err: any) {
144
- throw new ExecutionError(err.message);
145
- }
146
- });
147
-
148
- // ad profile use <name>
149
- profileCmd
150
- .command("use <name>")
151
- .description("Switch active default profile")
152
- .action((name) => {
153
- try {
154
- useProfile(name);
155
- console.log(`[OK] Active profile switched to '${name}'`);
156
- } catch (err: any) {
157
- throw new ExecutionError(err.message);
158
- }
159
- });
160
-
161
- // ad profile show [name]
162
- profileCmd
163
- .command("show [name]")
164
- .description("Display details of a profile (defaults to active profile)")
165
- .option("--reveal, --show-secrets", "Reveal plain text values for tokens")
166
- .option("--json", "Output as JSON")
167
- .option("--envelope", "Wrap JSON output in standard envelope")
168
- .action((name, rawOptions, cmd) => {
169
- try {
170
- const options = getEffectiveOptions(rawOptions, cmd);
171
- const config = loadProfiles();
172
- const targetName = name || config.currentProfile || "local";
173
- const entry = getProfile(targetName);
174
- const reveal = Boolean(options.reveal || options.showSecrets);
175
-
176
- if (!entry && targetName !== "local") {
177
- throw new ArgumentError(`Profile '${targetName}' not found.`);
178
- }
179
-
180
- const resolved = resolveProfileToken(targetName, entry);
181
- const displayToken = reveal
182
- ? resolved.token
183
- : (resolved.token ? maskSecretValue(resolved.token) : undefined);
184
-
185
- const data = {
186
- name: targetName,
187
- isCurrent: config.currentProfile === targetName,
188
- serverUrl: entry?.serverUrl || "local",
189
- tokenConfigured: resolved.source !== "none",
190
- tokenSource: resolved.source,
191
- tokenEnv: entry?.tokenEnv,
192
- token: displayToken,
193
- description: entry?.description || "",
194
- };
195
-
196
- renderResult(data, {
197
- json: options.json,
198
- envelope: options.envelope,
199
- humanFormatter: () => {
200
- const lines: string[] = [];
201
- lines.push(`Profile: ${data.name}${data.isCurrent ? " (Active)" : ""}`);
202
- lines.push(`Server URL: ${data.serverUrl}`);
203
- let sourceDetail = "None";
204
- if (data.tokenSource === "tokenEnv") {
205
- sourceDetail = `Environment Variable ($${data.tokenEnv})`;
206
- } else if (data.tokenSource === "profileEnv") {
207
- sourceDetail = `Profile Environment Variable ($ACTIONDOCK_${toSnakeUpperCase(data.name)}_TOKEN)`;
208
- } else if (data.tokenSource === "profile") {
209
- sourceDetail = "Stored in profiles.json (Deprecated)";
210
- } else if (data.tokenSource === "globalEnv") {
211
- sourceDetail = "Global Environment Variable ($ACTIONDOCK_TOKEN)";
212
- }
213
- lines.push(`Auth Source: ${sourceDetail}`);
214
- if (data.tokenConfigured) {
215
- lines.push(`Token Value: ${data.token}`);
216
- }
217
- if (data.description) {
218
- lines.push(`Description: ${data.description}`);
219
- }
220
- return lines.join("\n");
221
- },
222
- });
223
- } catch (err: any) {
224
- if (err instanceof ArgumentError || err instanceof CliError) {
225
- throw err;
226
- }
227
- throw new ExecutionError(err.message);
228
- }
229
- });
230
-
231
- // ad profile rm / remove <name>
232
- profileCmd
233
- .command("rm <name>")
234
- .alias("remove")
235
- .description("Remove a profile")
236
- .action((name) => {
237
- try {
238
- if (name === "local") {
239
- throw new ExecutionError("Cannot remove built-in 'local' profile");
240
- }
241
- const removed = removeProfile(name);
242
- if (!removed) {
243
- throw new ExecutionError(`Profile '${name}' not found`);
244
- }
245
- console.log(`[OK] Profile '${name}' removed`);
246
- } catch (err: any) {
247
- if (err instanceof CliError) {
248
- throw err;
249
- }
250
- throw new ExecutionError(err.message);
251
- }
252
- });
253
-
254
- // ad profile test [name]
255
- profileCmd
256
- .command("test [name]")
257
- .description("Test connection latency and health of a profile")
258
- .option("--json", "Output as JSON")
259
- .option("--envelope", "Wrap JSON output in standard envelope")
260
- .action(async (name, rawOptions, cmd) => {
261
- try {
262
- const options = getEffectiveOptions(rawOptions, cmd);
263
- const target = resolveTarget({ profile: name });
264
- if (target.type === "local") {
265
- renderResult(
266
- { ok: true, type: "local", message: "Local execution" },
267
- {
268
- json: options.json,
269
- envelope: options.envelope,
270
- humanFormatter: () =>
271
- `Target profile '${target.profileName || "local"}' is local (runs in local runtime).`,
272
- }
273
- );
274
- return;
275
- }
276
-
277
- const health = await checkRemoteHealth(target.serverUrl!, target.token);
278
- renderResult(health, {
279
- json: options.json,
280
- envelope: options.envelope,
281
- humanFormatter: () => {
282
- if (health.ok) {
283
- return `[OK] Connected to ${target.serverUrl} (${health.latencyMs}ms) - Version: ${health.version}, Status: ${health.status}`;
284
- }
285
- return `[FAIL] Connection to ${target.serverUrl} failed (${health.latencyMs}ms): ${health.error}`;
286
- },
287
- });
288
- if (!health.ok) {
289
- process.exitCode = 1;
290
- }
291
- } catch (err: any) {
292
- if (err instanceof ArgumentError || err instanceof CliError) throw err;
293
- throw new ExecutionError(err.message);
294
- }
295
- });
296
- }