@asteroidai/cli 1.9.4 → 1.9.11
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/dist/asteroid.js +1127 -307
- package/dist/core.js +861 -52
- package/package.json +3 -2
- package/src/commands.ts +13 -0
- package/src/core.ts +31 -0
- package/src/main.ts +2 -2
- package/src/program.test.ts +19 -0
- package/src/program.ts +15 -1
- package/src/run.test.ts +35 -2
- package/src/run.ts +53 -19
- package/src/sync/activities.ts +80 -0
- package/src/sync/commands.ts +111 -0
- package/src/sync/execution-pull.ts +273 -0
- package/src/sync/node-files.ts +47 -0
- package/src/sync/paths.ts +45 -0
- package/src/sync/run.ts +102 -0
- package/src/sync/sync.test.ts +463 -0
- package/src/sync/types.ts +58 -0
- package/src/sync/workflow-pull.ts +182 -0
- package/src/sync/workflow-push.ts +155 -0
- package/src/types.ts +2 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@asteroidai/cli",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.11",
|
|
4
4
|
"description": "The asteroid command-line interface for the Asteroid platform.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -38,7 +38,8 @@
|
|
|
38
38
|
"tsx": "^4.23.12",
|
|
39
39
|
"typescript": "5.9.3",
|
|
40
40
|
"vitest": "^4.1.11",
|
|
41
|
-
"yaml": "^2.9.0"
|
|
41
|
+
"yaml": "^2.9.0",
|
|
42
|
+
"@asteroid/workflow-files": "0.1.0"
|
|
42
43
|
},
|
|
43
44
|
"scripts": {
|
|
44
45
|
"generate": "tsx scripts/generate.ts && pnpm exec prettier --write src/generated/commands.ts",
|
package/src/commands.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { COMMANDS } from "./generated/commands";
|
|
2
|
+
import { SYNC_COMMANDS } from "./sync/commands";
|
|
3
|
+
import type { CliCommand } from "./types";
|
|
4
|
+
|
|
5
|
+
export function withSyncCommands(
|
|
6
|
+
commands: readonly CliCommand[],
|
|
7
|
+
): CliCommand[] {
|
|
8
|
+
return [...commands, ...SYNC_COMMANDS].sort((a, b) =>
|
|
9
|
+
a.command.localeCompare(b.command),
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const ALL_COMMANDS = withSyncCommands(COMMANDS);
|
package/src/core.ts
CHANGED
|
@@ -8,3 +8,34 @@ export {
|
|
|
8
8
|
} from "./program";
|
|
9
9
|
export { type BuiltRequest, buildRequest, type InputReader } from "./request";
|
|
10
10
|
export type { CliCommand, Option } from "./types";
|
|
11
|
+
export { ALL_COMMANDS, withSyncCommands } from "./commands";
|
|
12
|
+
export { type Activity, formatActivitiesMarkdown } from "./sync/activities";
|
|
13
|
+
export {
|
|
14
|
+
type Execution,
|
|
15
|
+
type ExecutionPullOptions,
|
|
16
|
+
type ExecutionPullResult,
|
|
17
|
+
formatExecutionPull,
|
|
18
|
+
pullExecution,
|
|
19
|
+
} from "./sync/execution-pull";
|
|
20
|
+
export { matchesGlob } from "./sync/paths";
|
|
21
|
+
export { runSync, type SyncDeps, SYNC_COMMANDS } from "./sync/run";
|
|
22
|
+
export {
|
|
23
|
+
type FileEntry,
|
|
24
|
+
type FileTree,
|
|
25
|
+
type LocalFiles,
|
|
26
|
+
MANIFEST,
|
|
27
|
+
type Manifest,
|
|
28
|
+
type Remote,
|
|
29
|
+
type Sync,
|
|
30
|
+
} from "./sync/types";
|
|
31
|
+
export {
|
|
32
|
+
formatWorkflowPull,
|
|
33
|
+
pullWorkflow,
|
|
34
|
+
type WorkflowPullOptions,
|
|
35
|
+
type WorkflowPullResult,
|
|
36
|
+
} from "./sync/workflow-pull";
|
|
37
|
+
export {
|
|
38
|
+
formatWorkflowPush,
|
|
39
|
+
pushWorkflow,
|
|
40
|
+
type WorkflowPushResult,
|
|
41
|
+
} from "./sync/workflow-push";
|
package/src/main.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
2
|
|
|
3
|
+
import { ALL_COMMANDS } from "./commands";
|
|
3
4
|
import { readEnv } from "./config";
|
|
4
|
-
import { COMMANDS } from "./generated/commands";
|
|
5
5
|
import { runCompletion } from "./program";
|
|
6
6
|
import { BUILTINS } from "./reference";
|
|
7
7
|
import { run } from "./run";
|
|
@@ -27,7 +27,7 @@ function openUrl(url: string) {
|
|
|
27
27
|
|
|
28
28
|
const argv = process.argv.slice(2);
|
|
29
29
|
if (argv[0] === "complete") {
|
|
30
|
-
await runCompletion(argv, { commands:
|
|
30
|
+
await runCompletion(argv, { commands: ALL_COMMANDS, builtins: BUILTINS });
|
|
31
31
|
process.exit(0);
|
|
32
32
|
}
|
|
33
33
|
|
package/src/program.test.ts
CHANGED
|
@@ -133,4 +133,23 @@ describe("parseInvocation", () => {
|
|
|
133
133
|
"expected [workflow-id] <schedule-id>, got 0 argument(s)",
|
|
134
134
|
);
|
|
135
135
|
});
|
|
136
|
+
|
|
137
|
+
it("prints the version only as the first argument", async () => {
|
|
138
|
+
const options = {
|
|
139
|
+
commands: COMMANDS,
|
|
140
|
+
builtins: BUILTINS,
|
|
141
|
+
version: "1.2.3",
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const version = await parseInvocation(["--version"], options);
|
|
145
|
+
const create = await parseInvocation(
|
|
146
|
+
["workflow", "create", "--name", "W", "--version", "{}"],
|
|
147
|
+
options,
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
expect(version).toMatchObject({ kind: "exit", code: 0, stdout: "1.2.3\n" });
|
|
151
|
+
expect(create.kind).toBe("command");
|
|
152
|
+
if (create.kind === "command")
|
|
153
|
+
expect(create.parsed.flags.get("version")).toEqual(["{}"]);
|
|
154
|
+
});
|
|
136
155
|
});
|
package/src/program.ts
CHANGED
|
@@ -85,6 +85,8 @@ function leafOptions(leaf: Command, command: CliCommand) {
|
|
|
85
85
|
optionText(option),
|
|
86
86
|
collect,
|
|
87
87
|
);
|
|
88
|
+
if (option.negatable)
|
|
89
|
+
leaf.option(`--no-${option.flag}`, `Skip ${option.flag}.`);
|
|
88
90
|
}
|
|
89
91
|
for (const file of command.body?.files ?? []) {
|
|
90
92
|
leaf.option(`--${file} <path>`, "File to upload. Repeatable.", collect);
|
|
@@ -122,7 +124,11 @@ export function defineCommands(
|
|
|
122
124
|
onInvocation: (invocation: Invocation) => void = () => undefined,
|
|
123
125
|
): Command {
|
|
124
126
|
if (options.description) root.description(options.description);
|
|
125
|
-
if (options.version)
|
|
127
|
+
if (options.version)
|
|
128
|
+
root.addHelpText(
|
|
129
|
+
"after",
|
|
130
|
+
"\nRun `asteroid --version` to print the CLI version.",
|
|
131
|
+
);
|
|
126
132
|
for (const [flags, text] of GLOBAL_FLAGS) {
|
|
127
133
|
if (!flags.startsWith("-h")) root.option(flags, text);
|
|
128
134
|
}
|
|
@@ -224,6 +230,14 @@ export async function parseInvocation(
|
|
|
224
230
|
let stderr = "";
|
|
225
231
|
let result: Invocation | undefined;
|
|
226
232
|
|
|
233
|
+
if (options.version && (argv[0] === "-v" || argv[0] === "--version")) {
|
|
234
|
+
return {
|
|
235
|
+
kind: "exit",
|
|
236
|
+
code: 0,
|
|
237
|
+
stdout: `${options.version}\n`,
|
|
238
|
+
stderr: "",
|
|
239
|
+
};
|
|
240
|
+
}
|
|
227
241
|
const { argv: rest, dotted } = splitDotted(argv);
|
|
228
242
|
const root = new Command("asteroid")
|
|
229
243
|
.exitOverride()
|
package/src/run.test.ts
CHANGED
|
@@ -4,8 +4,8 @@ import { join } from "node:path";
|
|
|
4
4
|
import { beforeEach, describe, expect, it } from "vitest";
|
|
5
5
|
|
|
6
6
|
import { CredentialStore } from "./auth/store";
|
|
7
|
+
import { ALL_COMMANDS } from "./commands";
|
|
7
8
|
import { readEnv, saveConfig } from "./config";
|
|
8
|
-
import { COMMANDS } from "./generated/commands";
|
|
9
9
|
import { renderReference } from "./reference";
|
|
10
10
|
import { type Deps, run } from "./run";
|
|
11
11
|
|
|
@@ -323,12 +323,45 @@ describe("terminal safety", () => {
|
|
|
323
323
|
});
|
|
324
324
|
});
|
|
325
325
|
|
|
326
|
+
describe("workflow pull", () => {
|
|
327
|
+
it("pulls a pinned version into the folder it is given", async () => {
|
|
328
|
+
const h = harness({ ASTEROID_API_KEY: "sk_test" }, () =>
|
|
329
|
+
json({
|
|
330
|
+
rev: 1,
|
|
331
|
+
version: 2,
|
|
332
|
+
versionId: "v-2",
|
|
333
|
+
workflowName: "Fill form",
|
|
334
|
+
files: [
|
|
335
|
+
{
|
|
336
|
+
path: "settings.yaml",
|
|
337
|
+
kind: "structural",
|
|
338
|
+
size: 3,
|
|
339
|
+
content: "a: 1",
|
|
340
|
+
},
|
|
341
|
+
],
|
|
342
|
+
}),
|
|
343
|
+
);
|
|
344
|
+
const dir = join(h.configDir, "pulled");
|
|
345
|
+
|
|
346
|
+
const code = await run(
|
|
347
|
+
["workflow", "pull", "w1", "--version-id", "v-2", "--dir", dir],
|
|
348
|
+
h.deps,
|
|
349
|
+
);
|
|
350
|
+
|
|
351
|
+
expect(code).toBe(0);
|
|
352
|
+
expect(h.calls[0].url).toBe(
|
|
353
|
+
"https://odyssey.asteroid.ai/agents/v2/workflows/w1/versions/v-2/files?contents=all",
|
|
354
|
+
);
|
|
355
|
+
expect(readFileSync(join(dir, "settings.yaml"), "utf8")).toBe("a: 1");
|
|
356
|
+
});
|
|
357
|
+
});
|
|
358
|
+
|
|
326
359
|
describe("reference", () => {
|
|
327
360
|
it("matches the generated agent-docs page", () => {
|
|
328
361
|
const page = readFileSync(
|
|
329
362
|
new URL("../../../docs/cli/reference.mdx", import.meta.url),
|
|
330
363
|
"utf8",
|
|
331
364
|
);
|
|
332
|
-
expect(page).toBe(renderReference(
|
|
365
|
+
expect(page).toBe(renderReference(ALL_COMMANDS));
|
|
333
366
|
});
|
|
334
367
|
});
|
package/src/run.ts
CHANGED
|
@@ -10,13 +10,15 @@ import {
|
|
|
10
10
|
UNSET_API_KEY,
|
|
11
11
|
} from "./auth/credentials";
|
|
12
12
|
import { WorkosError } from "./auth/workos";
|
|
13
|
+
import { ALL_COMMANDS } from "./commands";
|
|
13
14
|
import { type Env, loadConfig, orgLabel, requestedOrg } from "./config";
|
|
14
|
-
import { COMMANDS } from "./generated/commands";
|
|
15
15
|
import { ApiError, send, VERSION } from "./http";
|
|
16
16
|
import { clean, render } from "./output";
|
|
17
17
|
import { parseInvocation } from "./program";
|
|
18
18
|
import { BUILTINS } from "./reference";
|
|
19
19
|
import { buildRequest } from "./request";
|
|
20
|
+
import { runSync } from "./sync/run";
|
|
21
|
+
import type { Remote } from "./sync/types";
|
|
20
22
|
import type { CliCommand } from "./types";
|
|
21
23
|
import type { Ui } from "./ui";
|
|
22
24
|
|
|
@@ -82,6 +84,28 @@ async function credentialOrganization(
|
|
|
82
84
|
?.organizationId;
|
|
83
85
|
}
|
|
84
86
|
|
|
87
|
+
async function authFor(parsed: Parsed, deps: Deps): Promise<Auth> {
|
|
88
|
+
rejectOrgWithApiKey(deps, parsed.org);
|
|
89
|
+
const config = loadConfig(deps.env);
|
|
90
|
+
return resolveAuth(
|
|
91
|
+
deps.env,
|
|
92
|
+
config,
|
|
93
|
+
requestedOrg(parsed.org, deps.env, deps.cwd, config),
|
|
94
|
+
deps.fetch,
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function announce(command: CliCommand, auth: Auth, deps: Deps) {
|
|
99
|
+
if (command.readOnly) return;
|
|
100
|
+
const org =
|
|
101
|
+
auth.kind === "api-key"
|
|
102
|
+
? "the API key's organization"
|
|
103
|
+
: auth.org
|
|
104
|
+
? orgLabel(auth.org)
|
|
105
|
+
: "your default organization";
|
|
106
|
+
deps.stderr(`Acting in ${org}.\n`);
|
|
107
|
+
}
|
|
108
|
+
|
|
85
109
|
async function runCommand(
|
|
86
110
|
command: CliCommand,
|
|
87
111
|
parsed: Parsed,
|
|
@@ -91,26 +115,11 @@ async function runCommand(
|
|
|
91
115
|
let request = needsOrganization
|
|
92
116
|
? undefined
|
|
93
117
|
: await buildRequest(command, parsed);
|
|
94
|
-
|
|
95
|
-
const config = loadConfig(deps.env);
|
|
96
|
-
const auth = await resolveAuth(
|
|
97
|
-
deps.env,
|
|
98
|
-
config,
|
|
99
|
-
requestedOrg(parsed.org, deps.env, deps.cwd, config),
|
|
100
|
-
deps.fetch,
|
|
101
|
-
);
|
|
118
|
+
const auth = await authFor(parsed, deps);
|
|
102
119
|
request ??= await buildRequest(command, parsed, {
|
|
103
120
|
organizationId: await credentialOrganization(deps, auth),
|
|
104
121
|
});
|
|
105
|
-
|
|
106
|
-
const org =
|
|
107
|
-
auth.kind === "api-key"
|
|
108
|
-
? "the API key's organization"
|
|
109
|
-
: auth.org
|
|
110
|
-
? orgLabel(auth.org)
|
|
111
|
-
: "your default organization";
|
|
112
|
-
deps.stderr(`Acting in ${org}.\n`);
|
|
113
|
-
}
|
|
122
|
+
announce(command, auth, deps);
|
|
114
123
|
|
|
115
124
|
const response = await send(
|
|
116
125
|
deps.env.apiUrl,
|
|
@@ -153,13 +162,30 @@ async function runCommand(
|
|
|
153
162
|
return 0;
|
|
154
163
|
}
|
|
155
164
|
|
|
165
|
+
function nodeRemote(
|
|
166
|
+
apiUrl: string,
|
|
167
|
+
auth: Auth,
|
|
168
|
+
fetchImpl: typeof fetch,
|
|
169
|
+
): Remote {
|
|
170
|
+
return {
|
|
171
|
+
json: async (request) =>
|
|
172
|
+
(await send(apiUrl, auth, request, false, fetchImpl)).json,
|
|
173
|
+
async download(url) {
|
|
174
|
+
const response = await fetchImpl(url);
|
|
175
|
+
if (!response.ok)
|
|
176
|
+
throw new Error(`download failed: HTTP ${response.status}`);
|
|
177
|
+
return new Uint8Array(await response.arrayBuffer());
|
|
178
|
+
},
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
|
|
156
182
|
const DESCRIPTION =
|
|
157
183
|
"The Asteroid CLI. Sign in with `asteroid login`, or set ASTEROID_API_KEY.\nAt a terminal, tables show up to 6 columns and cut long cells to fit; when output is piped, they show every column in full. Use `--json` for every field.";
|
|
158
184
|
|
|
159
185
|
export async function run(argv: string[], deps: Deps): Promise<number> {
|
|
160
186
|
try {
|
|
161
187
|
const invocation = await parseInvocation(argv, {
|
|
162
|
-
commands:
|
|
188
|
+
commands: ALL_COMMANDS,
|
|
163
189
|
builtins: BUILTINS,
|
|
164
190
|
version: VERSION,
|
|
165
191
|
description: DESCRIPTION,
|
|
@@ -172,6 +198,14 @@ export async function run(argv: string[], deps: Deps): Promise<number> {
|
|
|
172
198
|
if (invocation.kind === "builtin") {
|
|
173
199
|
return await runBuiltin(invocation.name, invocation.parsed, deps);
|
|
174
200
|
}
|
|
201
|
+
if (invocation.command.local) {
|
|
202
|
+
const auth = await authFor(invocation.parsed, deps);
|
|
203
|
+
announce(invocation.command, auth, deps);
|
|
204
|
+
return await runSync(invocation.command, invocation.parsed, {
|
|
205
|
+
...deps,
|
|
206
|
+
remote: nodeRemote(deps.env.apiUrl, auth, deps.fetch),
|
|
207
|
+
});
|
|
208
|
+
}
|
|
175
209
|
return await runCommand(invocation.command, invocation.parsed, deps);
|
|
176
210
|
} catch (error) {
|
|
177
211
|
if (error instanceof UsageError) {
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
interface Payload {
|
|
2
|
+
activityType: string;
|
|
3
|
+
display?: { turnId?: string; summaryText?: string };
|
|
4
|
+
reasoning?: string;
|
|
5
|
+
message?: string;
|
|
6
|
+
actionName?: string;
|
|
7
|
+
info?: Record<string, unknown>;
|
|
8
|
+
summaryTokens?: number;
|
|
9
|
+
durationMs?: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface Activity {
|
|
13
|
+
payload: Payload;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function indentJson(data: Record<string, unknown>): string {
|
|
17
|
+
return JSON.stringify(data, null, 2)
|
|
18
|
+
.split("\n")
|
|
19
|
+
.map((line) => ` ${line}`)
|
|
20
|
+
.join("\n");
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function action(label: string, payload: Payload): string {
|
|
24
|
+
const info = payload.info;
|
|
25
|
+
const detail =
|
|
26
|
+
info && Object.keys(info).length > 0 ? `\ninfo:\n${indentJson(info)}` : "";
|
|
27
|
+
return `[${label}: ${payload.actionName}]:${detail}\n`;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function line(payload: Payload): string {
|
|
31
|
+
switch (payload.activityType) {
|
|
32
|
+
case "reasoning":
|
|
33
|
+
return `[reasoning]:\n${payload.reasoning}\n`;
|
|
34
|
+
case "generic":
|
|
35
|
+
return `[message]:\n${payload.message}\n`;
|
|
36
|
+
case "user_message_received":
|
|
37
|
+
return `[user_message]:\n${payload.message}\n`;
|
|
38
|
+
case "action_started":
|
|
39
|
+
return action("action_started", payload);
|
|
40
|
+
case "action_completed":
|
|
41
|
+
return action("action_completed", payload);
|
|
42
|
+
case "action_failed":
|
|
43
|
+
return `[action_failed: ${payload.actionName}]:\nfailure: ${payload.message}\n`;
|
|
44
|
+
case "compaction_performed":
|
|
45
|
+
return `[compaction]: summary_tokens: ${payload.summaryTokens}, duration_ms: ${payload.durationMs}\n`;
|
|
46
|
+
case "compaction_started":
|
|
47
|
+
return "[compaction_started]\n";
|
|
48
|
+
default: {
|
|
49
|
+
const summary = payload.display?.summaryText;
|
|
50
|
+
return summary
|
|
51
|
+
? `[${payload.activityType}]: ${summary}\n`
|
|
52
|
+
: `[${payload.activityType}]\n`;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function formatActivitiesMarkdown(
|
|
58
|
+
activities: Activity[],
|
|
59
|
+
status: string,
|
|
60
|
+
createdAt: string,
|
|
61
|
+
): string {
|
|
62
|
+
const lines = [
|
|
63
|
+
"# Execution Activities\n",
|
|
64
|
+
`Status: ${status}`,
|
|
65
|
+
`Started: ${createdAt}`,
|
|
66
|
+
];
|
|
67
|
+
let currentTurn = "";
|
|
68
|
+
for (const { payload } of activities) {
|
|
69
|
+
const turnId = payload.display?.turnId ?? "";
|
|
70
|
+
if (turnId && turnId !== currentTurn) {
|
|
71
|
+
currentTurn = turnId;
|
|
72
|
+
lines.push(`\n---\n\n## ${turnId}\n`);
|
|
73
|
+
} else if (!currentTurn && !turnId) {
|
|
74
|
+
currentTurn = "_started";
|
|
75
|
+
lines.push("\n---\n");
|
|
76
|
+
}
|
|
77
|
+
lines.push(line(payload));
|
|
78
|
+
}
|
|
79
|
+
return lines.join("\n");
|
|
80
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import type { CliCommand, Option } from "../types";
|
|
2
|
+
|
|
3
|
+
function option(
|
|
4
|
+
name: string,
|
|
5
|
+
type: Option["type"],
|
|
6
|
+
description: string,
|
|
7
|
+
extra: Partial<Option> = {},
|
|
8
|
+
): Option {
|
|
9
|
+
return { name, flag: name, type, required: false, description, ...extra };
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const DIR = option(
|
|
13
|
+
"dir",
|
|
14
|
+
"string",
|
|
15
|
+
"Write here instead of `<workflow-name>/...` under the current directory.",
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
const local = {
|
|
19
|
+
method: "GET",
|
|
20
|
+
path: "",
|
|
21
|
+
binary: false,
|
|
22
|
+
destructive: false,
|
|
23
|
+
local: true,
|
|
24
|
+
} as const;
|
|
25
|
+
|
|
26
|
+
export const SYNC_COMMANDS: CliCommand[] = [
|
|
27
|
+
{
|
|
28
|
+
...local,
|
|
29
|
+
command: "workflow pull",
|
|
30
|
+
tool: "workflow_pull",
|
|
31
|
+
title: "Pull a workflow to disk",
|
|
32
|
+
description:
|
|
33
|
+
"Write a workflow's editable head to `<workflow-name>/head/` as files: settings, per-node instructions and scripts, and the workflow's own files. Pass --version-id for a pinned version, written read-only to `<workflow-name>/.versions/`. Edit the head files, then run `asteroid workflow push` from that folder.",
|
|
34
|
+
readOnly: true,
|
|
35
|
+
args: [
|
|
36
|
+
{
|
|
37
|
+
name: "workflowId",
|
|
38
|
+
flag: "workflow-id",
|
|
39
|
+
type: "string",
|
|
40
|
+
required: true,
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
query: [
|
|
44
|
+
option(
|
|
45
|
+
"version-id",
|
|
46
|
+
"string",
|
|
47
|
+
"A workflow version ID. Omit for the editable head.",
|
|
48
|
+
),
|
|
49
|
+
DIR,
|
|
50
|
+
],
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
...local,
|
|
54
|
+
command: "workflow push",
|
|
55
|
+
tool: "workflow_push",
|
|
56
|
+
title: "Push local edits to a workflow head",
|
|
57
|
+
description:
|
|
58
|
+
"Send the edits in a pulled head folder to the workflow's editable head: changed and new files are written, removed files are deleted. Fails if the head changed since the pull; pull again and reapply. Push does not publish.",
|
|
59
|
+
readOnly: false,
|
|
60
|
+
args: [],
|
|
61
|
+
query: [
|
|
62
|
+
option(
|
|
63
|
+
"dir",
|
|
64
|
+
"string",
|
|
65
|
+
"The pulled head folder. Defaults to the current directory.",
|
|
66
|
+
),
|
|
67
|
+
],
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
...local,
|
|
71
|
+
command: "execution pull",
|
|
72
|
+
tool: "execution_pull",
|
|
73
|
+
title: "Pull an execution to disk",
|
|
74
|
+
description:
|
|
75
|
+
"Write an execution to `<workflow-name>/executions/<id>/`: summary.json, activities.md (the step-by-step log), and the files the run produced.",
|
|
76
|
+
readOnly: true,
|
|
77
|
+
args: [
|
|
78
|
+
{
|
|
79
|
+
name: "executionId",
|
|
80
|
+
flag: "execution-id",
|
|
81
|
+
type: "string",
|
|
82
|
+
required: true,
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
query: [
|
|
86
|
+
option(
|
|
87
|
+
"files",
|
|
88
|
+
"string",
|
|
89
|
+
"Only download files whose path matches this glob. --no-files skips downloads.",
|
|
90
|
+
{
|
|
91
|
+
negatable: true,
|
|
92
|
+
},
|
|
93
|
+
),
|
|
94
|
+
option(
|
|
95
|
+
"summary-only",
|
|
96
|
+
"boolean",
|
|
97
|
+
"Write summary.json only: no activities, no files.",
|
|
98
|
+
),
|
|
99
|
+
option(
|
|
100
|
+
"max-file-size",
|
|
101
|
+
"integer",
|
|
102
|
+
"Skip files larger than this many bytes.",
|
|
103
|
+
),
|
|
104
|
+
option(
|
|
105
|
+
"dir",
|
|
106
|
+
"string",
|
|
107
|
+
"Write here instead of `<workflow-name>/executions/<id>/` under the current directory.",
|
|
108
|
+
),
|
|
109
|
+
],
|
|
110
|
+
},
|
|
111
|
+
];
|