@mycadet/cli 0.12.7 → 0.12.8
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 +2 -2
- package/knip.json +1 -1
- package/node_modules/@mycadet/assistant-api/events/cloud-disconnected.ts +21 -0
- package/node_modules/@mycadet/assistant-api/events/host-bash.ts +1 -1
- package/node_modules/@mycadet/assistant-api/events/host-cu.ts +1 -1
- package/node_modules/@mycadet/assistant-api/events/host-file.ts +1 -1
- package/node_modules/@mycadet/assistant-api/events/notification-intent.ts +1 -1
- package/node_modules/@mycadet/assistant-api/events/{show-platform-login.ts → show-cloud-login.ts} +3 -5
- package/node_modules/@mycadet/assistant-api/index.ts +11 -11
- package/node_modules/@mycadet/assistant-api/node_modules/@mycadet/service-contracts/package.json +1 -1
- package/node_modules/@mycadet/{service-contracts/src/platform-credential.ts → assistant-api/node_modules/@mycadet/service-contracts/src/cloud-credential.ts} +9 -9
- package/node_modules/@mycadet/assistant-api/node_modules/@mycadet/service-contracts/src/handles.ts +3 -3
- package/node_modules/@mycadet/assistant-api/node_modules/@mycadet/service-contracts/src/index.ts +1 -1
- package/node_modules/@mycadet/assistant-api/node_modules/@mycadet/service-contracts/src/ingress.ts +11 -5
- package/node_modules/@mycadet/assistant-api/node_modules/@mycadet/service-contracts/src/remote-web-pairing.ts +1 -1
- package/node_modules/@mycadet/assistant-api/node_modules/@mycadet/service-contracts/src/rpc.ts +14 -14
- package/node_modules/@mycadet/assistant-api/node_modules/@mycadet/service-contracts/src/trust-rules.ts +5 -5
- package/node_modules/@mycadet/assistant-api/responses/home.ts +1 -1
- package/node_modules/@mycadet/assistant-api/surfaces.ts +4 -4
- package/node_modules/@mycadet/avatar-manifest/src/__tests__/notification-avatar.test.ts +1 -1
- package/node_modules/@mycadet/avatar-manifest/src/notification-avatar.ts +2 -2
- package/node_modules/@mycadet/environments/src/seeds.ts +6 -6
- package/node_modules/@mycadet/environments/src/shell.test.ts +1 -1
- package/node_modules/@mycadet/environments/src/types.ts +6 -6
- package/node_modules/@mycadet/local-mode/node_modules/@mycadet/avatar-manifest/src/__tests__/notification-avatar.test.ts +1 -1
- package/node_modules/@mycadet/local-mode/node_modules/@mycadet/avatar-manifest/src/notification-avatar.ts +2 -2
- package/node_modules/@mycadet/local-mode/node_modules/@mycadet/environments/src/seeds.ts +6 -6
- package/node_modules/@mycadet/local-mode/node_modules/@mycadet/environments/src/shell.test.ts +1 -1
- package/node_modules/@mycadet/local-mode/node_modules/@mycadet/environments/src/types.ts +6 -6
- package/node_modules/@mycadet/local-mode/node_modules/@mycadet/service-contracts/package.json +1 -1
- package/node_modules/@mycadet/{assistant-api/node_modules/@mycadet/service-contracts/src/platform-credential.ts → local-mode/node_modules/@mycadet/service-contracts/src/cloud-credential.ts} +9 -9
- package/node_modules/@mycadet/local-mode/node_modules/@mycadet/service-contracts/src/handles.ts +3 -3
- package/node_modules/@mycadet/local-mode/node_modules/@mycadet/service-contracts/src/index.ts +1 -1
- package/node_modules/@mycadet/local-mode/node_modules/@mycadet/service-contracts/src/ingress.ts +11 -5
- package/node_modules/@mycadet/local-mode/node_modules/@mycadet/service-contracts/src/remote-web-pairing.ts +1 -1
- package/node_modules/@mycadet/local-mode/node_modules/@mycadet/service-contracts/src/rpc.ts +14 -14
- package/node_modules/@mycadet/local-mode/node_modules/@mycadet/service-contracts/src/trust-rules.ts +5 -5
- package/node_modules/@mycadet/local-mode/src/__tests__/pair.test.ts +5 -5
- package/node_modules/@mycadet/local-mode/src/__tests__/retire.test.ts +1 -1
- package/node_modules/@mycadet/local-mode/src/config.ts +2 -2
- package/node_modules/@mycadet/local-mode/src/index.ts +1 -1
- package/node_modules/@mycadet/local-mode/src/lockfile-contract.test.ts +3 -3
- package/node_modules/@mycadet/local-mode/src/lockfile-contract.ts +10 -5
- package/node_modules/@mycadet/local-mode/src/lockfile.test.ts +15 -15
- package/node_modules/@mycadet/local-mode/src/lockfile.ts +9 -9
- package/node_modules/@mycadet/local-mode/src/pair.ts +2 -2
- package/node_modules/@mycadet/local-mode/src/retire.ts +3 -3
- package/node_modules/@mycadet/local-mode/src/teleport-backup-policy.ts +2 -2
- package/node_modules/@mycadet/local-mode/src/unpair.ts +2 -2
- package/node_modules/@mycadet/service-contracts/package.json +1 -1
- package/node_modules/@mycadet/{local-mode/node_modules/@mycadet/service-contracts/src/platform-credential.ts → service-contracts/src/cloud-credential.ts} +9 -9
- package/node_modules/@mycadet/service-contracts/src/handles.ts +3 -3
- package/node_modules/@mycadet/service-contracts/src/index.ts +1 -1
- package/node_modules/@mycadet/service-contracts/src/ingress.ts +11 -5
- package/node_modules/@mycadet/service-contracts/src/remote-web-pairing.ts +1 -1
- package/node_modules/@mycadet/service-contracts/src/rpc.ts +14 -14
- package/node_modules/@mycadet/service-contracts/src/trust-rules.ts +5 -5
- package/package.json +3 -2
- package/src/__tests__/assistant-api-key-resolution.test.ts +6 -6
- package/src/__tests__/{assistant-client-platform-auth.test.ts → assistant-client-cloud-auth.test.ts} +10 -10
- package/src/__tests__/assistant-client-refresh.test.ts +2 -2
- package/src/__tests__/backup.test.ts +86 -91
- package/src/__tests__/client-token.test.ts +1 -1
- package/src/__tests__/client-tui-refresh.test.ts +1 -1
- package/src/__tests__/client-web-config.test.ts +2 -2
- package/src/__tests__/{platform-client.test.ts → cloud-client.test.ts} +59 -59
- package/src/__tests__/{platform-releases.test.ts → cloud-releases.test.ts} +5 -5
- package/src/__tests__/{cloudflare-tunnel.test.ts → cloudflare.test.ts} +1 -1
- package/src/__tests__/connect-import.test.ts +55 -39
- package/src/__tests__/debug.test.ts +38 -38
- package/src/__tests__/guardian-token.test.ts +149 -56
- package/src/__tests__/hatch-provider-secrets.test.ts +2 -2
- package/src/__tests__/helpers/guardian-token.ts +22 -0
- package/src/__tests__/helpers/http.ts +10 -0
- package/src/__tests__/nginx-ingress.test.ts +18 -18
- package/src/__tests__/orphan-detection.test.ts +1 -1
- package/src/__tests__/pair.test.ts +1 -8
- package/src/__tests__/{ps-platform-status.test.ts → ps-cloud-status.test.ts} +79 -26
- package/src/__tests__/{recover.test.ts → restore.test.ts} +29 -28
- package/src/__tests__/retire.test.ts +58 -199
- package/src/__tests__/root-process-lockfile.test.ts +99 -0
- package/src/__tests__/sleep.test.ts +19 -19
- package/src/__tests__/statefulset.test.ts +8 -8
- package/src/__tests__/{tailscale-tunnel.test.ts → tailscale.test.ts} +1 -1
- package/src/__tests__/teleport-backup.test.ts +3 -3
- package/src/__tests__/teleport.test.ts +180 -196
- package/src/__tests__/tunnel.test.ts +255 -227
- package/src/__tests__/uninstall.test.ts +13 -4
- package/src/__tests__/upgrade-local.test.ts +3 -3
- package/src/__tests__/upgrade-replay-env.test.ts +12 -12
- package/src/__tests__/wake.test.ts +258 -41
- package/src/__tests__/workos-pkce.test.ts +2 -2
- package/src/commands/backup.ts +22 -22
- package/src/commands/client.ts +76 -76
- package/src/commands/debug.ts +20 -20
- package/src/commands/exec.ts +5 -5
- package/src/commands/hatch.ts +22 -22
- package/src/commands/login.ts +22 -22
- package/src/commands/logs.ts +1 -1
- package/src/commands/ps.ts +188 -79
- package/src/commands/restart.ts +30 -0
- package/src/commands/restore.ts +138 -20
- package/src/commands/retire.ts +46 -148
- package/src/commands/rollback.ts +18 -24
- package/src/commands/setup.ts +2 -2
- package/src/commands/teleport.ts +93 -93
- package/src/commands/terminal.ts +157 -17
- package/src/commands/tunnel.ts +80 -122
- package/src/commands/uninstall.ts +55 -7
- package/src/commands/unpair.ts +3 -3
- package/src/commands/upgrade.ts +22 -46
- package/src/commands/wake.ts +162 -46
- package/src/index.ts +3 -9
- package/src/lib/__tests__/{platform-client-signed-url.test.ts → cloud-client-signed-url.test.ts} +16 -16
- package/src/lib/__tests__/job-polling.test.ts +1 -1
- package/src/lib/__tests__/local-runtime-client.test.ts +4 -4
- package/src/lib/__tests__/runtime-url.test.ts +1 -1
- package/src/lib/assistant-api-key-resolution.ts +5 -5
- package/src/lib/assistant-client.ts +8 -8
- package/src/lib/assistant-config.ts +58 -12
- package/src/lib/{platform-client.ts → cloud-client.ts} +107 -98
- package/src/lib/cloud-login.ts +24 -24
- package/src/lib/{platform-releases.ts → cloud-releases.ts} +5 -5
- package/src/lib/cloud-values.ts +3 -0
- package/src/lib/config-utils.ts +1 -1
- package/src/lib/detached-process.ts +1 -1
- package/src/lib/docker.ts +111 -10
- package/src/lib/environments/__tests__/paths.test.ts +2 -2
- package/src/lib/environments/__tests__/resolve.test.ts +26 -26
- package/src/lib/environments/resolve.ts +8 -8
- package/src/lib/guardian-token.ts +36 -4
- package/src/lib/hatch-local.ts +19 -23
- package/src/lib/health-check.ts +6 -6
- package/src/lib/ingress-config.ts +8 -35
- package/src/lib/job-polling.ts +1 -1
- package/src/lib/live-voice/connection.ts +12 -12
- package/src/lib/live-voice/tunnel.test.ts +11 -11
- package/src/lib/live-voice/tunnel.ts +15 -15
- package/src/lib/local-runtime-client.ts +20 -20
- package/src/lib/local.ts +9 -30
- package/src/lib/nginx-ingress.ts +41 -14
- package/src/lib/process.ts +1 -1
- package/src/lib/provider-secrets.ts +3 -3
- package/src/lib/retire-apple-container.ts +1 -1
- package/src/lib/runtime-url.ts +8 -8
- package/src/lib/statefulset.ts +2 -2
- package/src/lib/sync-cloud-assistants.ts +18 -18
- package/src/lib/teleport-backup.ts +4 -4
- package/src/lib/terminal-client.ts +17 -17
- package/src/lib/terminal-session.ts +24 -24
- package/src/lib/{tunnel-edge.ts → tunnel.ts} +199 -11
- package/src/lib/tunnels/cadet.ts +29 -0
- package/src/lib/{cloudflare-tunnel.ts → tunnels/cloudflare.ts} +15 -4
- package/src/lib/tunnels/gateway-notify.ts +61 -0
- package/src/lib/{ngrok.ts → tunnels/ngrok.ts} +201 -30
- package/src/lib/{tailscale-tunnel.ts → tunnels/tailscale.ts} +19 -5
- package/src/lib/upgrade-lifecycle.ts +3 -17
- package/src/lib/upgrade-preflight.ts +2 -2
- package/src/lib/workos-pkce.ts +5 -5
- package/node_modules/@mycadet/assistant-api/events/platform-disconnected.ts +0 -21
- package/src/commands/recover.ts +0 -131
- package/src/commands/roadmap.ts +0 -459
- package/src/commands/ssh.ts +0 -144
- package/src/commands/workflows.ts +0 -305
- package/src/lib/managed-cloud.ts +0 -3
package/src/commands/ssh.ts
DELETED
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
import { isManagedCloud } from "../lib/managed-cloud.js";
|
|
2
|
-
import { spawn } from "child_process";
|
|
3
|
-
|
|
4
|
-
import { extractHostFromUrl, resolveAssistant } from "../lib/assistant-config";
|
|
5
|
-
import { dockerResourceNames } from "../lib/docker";
|
|
6
|
-
import { getPlatformUrl, readPlatformToken } from "../lib/platform-client";
|
|
7
|
-
import { sshAppleContainer } from "../lib/ssh-apple-container";
|
|
8
|
-
import { interactiveSession } from "../lib/terminal-session";
|
|
9
|
-
|
|
10
|
-
const SSH_OPTS = [
|
|
11
|
-
"-o",
|
|
12
|
-
"StrictHostKeyChecking=no",
|
|
13
|
-
"-o",
|
|
14
|
-
"UserKnownHostsFile=/dev/null",
|
|
15
|
-
"-o",
|
|
16
|
-
"ConnectTimeout=10",
|
|
17
|
-
"-o",
|
|
18
|
-
"LogLevel=ERROR",
|
|
19
|
-
];
|
|
20
|
-
|
|
21
|
-
export const ssh = Object.assign(
|
|
22
|
-
async function ssh(): Promise<void> {
|
|
23
|
-
const args = process.argv.slice(3);
|
|
24
|
-
if (args.includes("--help") || args.includes("-h")) {
|
|
25
|
-
console.log("Usage: cadet ssh [<name>]");
|
|
26
|
-
console.log("");
|
|
27
|
-
console.log("SSH into a remote assistant instance.");
|
|
28
|
-
console.log("");
|
|
29
|
-
console.log("Arguments:");
|
|
30
|
-
console.log(
|
|
31
|
-
" <name> Name of the assistant to connect to (defaults to latest)",
|
|
32
|
-
);
|
|
33
|
-
process.exit(0);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const name = process.argv[3];
|
|
37
|
-
const entry = resolveAssistant(name);
|
|
38
|
-
|
|
39
|
-
if (!entry) {
|
|
40
|
-
if (name) {
|
|
41
|
-
console.error(`No assistant instance found with name '${name}'.`);
|
|
42
|
-
} else {
|
|
43
|
-
console.error("No assistant instance found. Run `cadet hatch` first.");
|
|
44
|
-
}
|
|
45
|
-
process.exit(1);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const cloud = entry.cloud;
|
|
49
|
-
|
|
50
|
-
if (cloud === "local") {
|
|
51
|
-
console.error(
|
|
52
|
-
"Cannot SSH into a local assistant. Local assistants run directly on this machine.\n" +
|
|
53
|
-
`Use 'cadet ps ${entry.assistantId}' to check its processes instead.`,
|
|
54
|
-
);
|
|
55
|
-
process.exit(1);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
if (cloud === "aws") {
|
|
59
|
-
console.error("SSH to AWS instances is not yet supported.");
|
|
60
|
-
process.exit(1);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// Apple container: connect to the management socket for an interactive shell.
|
|
64
|
-
if (cloud === "apple-container") {
|
|
65
|
-
await sshAppleContainer(entry);
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
let child;
|
|
70
|
-
|
|
71
|
-
if (cloud === "docker") {
|
|
72
|
-
const res = dockerResourceNames(entry.assistantId);
|
|
73
|
-
console.log(`🔗 Connecting to ${entry.assistantId} via docker exec...\n`);
|
|
74
|
-
|
|
75
|
-
child = spawn(
|
|
76
|
-
"docker",
|
|
77
|
-
["exec", "-it", res.assistantContainer, "/bin/sh"],
|
|
78
|
-
{ stdio: "inherit", windowsHide: true },
|
|
79
|
-
);
|
|
80
|
-
} else if (cloud === "gcp") {
|
|
81
|
-
const project = entry.project;
|
|
82
|
-
const zone = entry.zone;
|
|
83
|
-
if (!project || !zone) {
|
|
84
|
-
console.error(
|
|
85
|
-
"Error: GCP project and zone not found in assistant config.",
|
|
86
|
-
);
|
|
87
|
-
process.exit(1);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const sshTarget = entry.sshUser
|
|
91
|
-
? `${entry.sshUser}@${entry.assistantId}`
|
|
92
|
-
: entry.assistantId;
|
|
93
|
-
|
|
94
|
-
console.log(`🔗 Connecting to ${entry.assistantId} via gcloud...\n`);
|
|
95
|
-
|
|
96
|
-
child = spawn(
|
|
97
|
-
"gcloud",
|
|
98
|
-
["compute", "ssh", sshTarget, `--project=${project}`, `--zone=${zone}`],
|
|
99
|
-
{ stdio: "inherit", windowsHide: true },
|
|
100
|
-
);
|
|
101
|
-
} else if (isManagedCloud(cloud)) {
|
|
102
|
-
const token = readPlatformToken();
|
|
103
|
-
if (!token) {
|
|
104
|
-
console.error(
|
|
105
|
-
"Not logged in. Run `cadet login` first to authenticate with Cadet Cloud.",
|
|
106
|
-
);
|
|
107
|
-
process.exit(1);
|
|
108
|
-
}
|
|
109
|
-
await interactiveSession({
|
|
110
|
-
assistantId: entry.assistantId,
|
|
111
|
-
token,
|
|
112
|
-
platformUrl: getPlatformUrl(),
|
|
113
|
-
});
|
|
114
|
-
return;
|
|
115
|
-
} else if (cloud === "custom") {
|
|
116
|
-
const host = extractHostFromUrl(entry.runtimeUrl);
|
|
117
|
-
const sshUser = entry.sshUser ?? "root";
|
|
118
|
-
const sshTarget = `${sshUser}@${host}`;
|
|
119
|
-
|
|
120
|
-
console.log(`🔗 Connecting to ${entry.assistantId} via ssh...\n`);
|
|
121
|
-
|
|
122
|
-
child = spawn("ssh", [...SSH_OPTS, sshTarget], {
|
|
123
|
-
stdio: "inherit",
|
|
124
|
-
windowsHide: true,
|
|
125
|
-
});
|
|
126
|
-
} else {
|
|
127
|
-
console.error(`Error: Unknown cloud type '${cloud}'.`);
|
|
128
|
-
process.exit(1);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
await new Promise<void>((resolve, reject) => {
|
|
132
|
-
child.on("close", (code) => {
|
|
133
|
-
if (code === 0) {
|
|
134
|
-
resolve();
|
|
135
|
-
} else {
|
|
136
|
-
reject(new Error(`ssh exited with code ${code}`));
|
|
137
|
-
}
|
|
138
|
-
});
|
|
139
|
-
child.on("error", reject);
|
|
140
|
-
});
|
|
141
|
-
},
|
|
142
|
-
{ description: "SSH into a remote assistant instance" },
|
|
143
|
-
);
|
|
144
|
-
|
|
@@ -1,305 +0,0 @@
|
|
|
1
|
-
import { extractAssistantFlag, extractValueFlag } from "../lib/arg-utils.js";
|
|
2
|
-
import { AssistantClient } from "../lib/assistant-client.js";
|
|
3
|
-
import {
|
|
4
|
-
formatAssistantLookupError,
|
|
5
|
-
lookupAssistantByIdentifier,
|
|
6
|
-
} from "../lib/assistant-config.js";
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Client-side mirror of the server's wire-run projection
|
|
10
|
-
* (`WorkflowRunWire` from `assistant/src/runtime/routes/workflow-routes.ts`).
|
|
11
|
-
* The CLI is an independent build unit and deliberately does NOT import from
|
|
12
|
-
* `assistant/` (see `cli/src/shared/provider-env-vars.ts`), so the shape is
|
|
13
|
-
* mirrored here. Only the fields the CLI renders are declared — the server may
|
|
14
|
-
* send a superset. Keep in sync with `workflowRunSchema`.
|
|
15
|
-
*/
|
|
16
|
-
type WorkflowRun = {
|
|
17
|
-
id: string;
|
|
18
|
-
name: string | null;
|
|
19
|
-
status: string;
|
|
20
|
-
agentsSpawned: number;
|
|
21
|
-
inputTokens: number;
|
|
22
|
-
outputTokens: number;
|
|
23
|
-
error: string | null;
|
|
24
|
-
createdAt: number | null;
|
|
25
|
-
finishedAt: number | null;
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
type SavedWorkflow = {
|
|
29
|
-
name: string;
|
|
30
|
-
description: string;
|
|
31
|
-
path: string;
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
function pad(s: string, w: number): string {
|
|
35
|
-
return s + " ".repeat(Math.max(0, w - s.length));
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function fmtTime(ms: number | null): string {
|
|
39
|
-
return ms == null ? "-" : new Date(ms).toISOString();
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function printRunsTable(runs: WorkflowRun[]): void {
|
|
43
|
-
const headers = {
|
|
44
|
-
id: "ID",
|
|
45
|
-
name: "NAME",
|
|
46
|
-
status: "STATUS",
|
|
47
|
-
agents: "AGENTS",
|
|
48
|
-
created: "CREATED",
|
|
49
|
-
};
|
|
50
|
-
const rows = runs.map((r) => ({
|
|
51
|
-
id: r.id,
|
|
52
|
-
name: r.name ?? "-",
|
|
53
|
-
status: r.status,
|
|
54
|
-
agents: String(r.agentsSpawned),
|
|
55
|
-
created: fmtTime(r.createdAt),
|
|
56
|
-
}));
|
|
57
|
-
const all = [headers, ...rows];
|
|
58
|
-
const w = {
|
|
59
|
-
id: Math.max(...all.map((r) => r.id.length)),
|
|
60
|
-
name: Math.max(...all.map((r) => r.name.length)),
|
|
61
|
-
status: Math.max(...all.map((r) => r.status.length)),
|
|
62
|
-
agents: Math.max(...all.map((r) => r.agents.length)),
|
|
63
|
-
created: Math.max(...all.map((r) => r.created.length)),
|
|
64
|
-
};
|
|
65
|
-
const formatRow = (r: typeof headers) =>
|
|
66
|
-
`${pad(r.id, w.id)} ${pad(r.name, w.name)} ${pad(r.status, w.status)} ${pad(r.agents, w.agents)} ${r.created}`;
|
|
67
|
-
console.log(formatRow(headers));
|
|
68
|
-
console.log(
|
|
69
|
-
`${"-".repeat(w.id)} ${"-".repeat(w.name)} ${"-".repeat(w.status)} ${"-".repeat(w.agents)} ${"-".repeat(w.created)}`,
|
|
70
|
-
);
|
|
71
|
-
for (const row of rows) console.log(formatRow(row));
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
function printSavedTable(workflows: SavedWorkflow[]): void {
|
|
75
|
-
const headers = { name: "NAME", description: "DESCRIPTION" };
|
|
76
|
-
const rows = workflows.map((w) => ({
|
|
77
|
-
name: w.name,
|
|
78
|
-
description: w.description,
|
|
79
|
-
}));
|
|
80
|
-
const all = [headers, ...rows];
|
|
81
|
-
const w = {
|
|
82
|
-
name: Math.max(...all.map((r) => r.name.length)),
|
|
83
|
-
description: Math.max(...all.map((r) => r.description.length)),
|
|
84
|
-
};
|
|
85
|
-
const formatRow = (r: typeof headers) =>
|
|
86
|
-
`${pad(r.name, w.name)} ${r.description}`;
|
|
87
|
-
console.log(formatRow(headers));
|
|
88
|
-
console.log(`${"-".repeat(w.name)} ${"-".repeat(w.description)}`);
|
|
89
|
-
for (const row of rows) console.log(formatRow(row));
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function printHelp(): void {
|
|
93
|
-
console.log("Usage: cadet workflows <subcommand> [options]");
|
|
94
|
-
console.log("");
|
|
95
|
-
console.log("Inspect and control workflow runs on the active assistant.");
|
|
96
|
-
console.log("");
|
|
97
|
-
console.log("Subcommands:");
|
|
98
|
-
console.log(" list List saved (named) workflows");
|
|
99
|
-
console.log(" runs List recent workflow runs");
|
|
100
|
-
console.log(" show <run-id> Show details for a single run");
|
|
101
|
-
console.log(" abort <run-id> Abort an in-flight run");
|
|
102
|
-
console.log(
|
|
103
|
-
" resume <run-id> Resume an interrupted run (orphaned by a restart)",
|
|
104
|
-
);
|
|
105
|
-
console.log("");
|
|
106
|
-
console.log("Options:");
|
|
107
|
-
console.log(
|
|
108
|
-
" --assistant <name> Target a specific assistant (display name or ID)",
|
|
109
|
-
);
|
|
110
|
-
console.log(" --limit <n> (runs) Max runs to list");
|
|
111
|
-
console.log(" --status <status> (runs) Filter by run status");
|
|
112
|
-
console.log(" --help, -h Show this help");
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
function createClient(assistantName?: string): AssistantClient {
|
|
116
|
-
let assistantId: string | undefined;
|
|
117
|
-
if (assistantName) {
|
|
118
|
-
const result = lookupAssistantByIdentifier(assistantName);
|
|
119
|
-
if (result.status !== "found") {
|
|
120
|
-
throw new Error(formatAssistantLookupError(assistantName, result));
|
|
121
|
-
}
|
|
122
|
-
assistantId = result.entry.assistantId;
|
|
123
|
-
}
|
|
124
|
-
try {
|
|
125
|
-
return new AssistantClient(assistantId ? { assistantId } : undefined);
|
|
126
|
-
} catch {
|
|
127
|
-
throw new Error(
|
|
128
|
-
assistantName
|
|
129
|
-
? `No assistant found matching '${assistantName}'.`
|
|
130
|
-
: "No assistant found. Hatch one with 'cadet hatch' first.",
|
|
131
|
-
);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function rethrowFetchError(err: unknown): never {
|
|
136
|
-
if (
|
|
137
|
-
err instanceof TypeError &&
|
|
138
|
-
(err.message.includes("fetch") || err.message.includes("connect"))
|
|
139
|
-
) {
|
|
140
|
-
throw new Error(
|
|
141
|
-
"Could not reach the assistant. Is it running? Try 'cadet wake'.",
|
|
142
|
-
);
|
|
143
|
-
}
|
|
144
|
-
throw err;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
async function requestJson<T>(
|
|
148
|
-
client: AssistantClient,
|
|
149
|
-
method: "get" | "post",
|
|
150
|
-
path: string,
|
|
151
|
-
query?: Record<string, string>,
|
|
152
|
-
): Promise<T> {
|
|
153
|
-
let res: Response;
|
|
154
|
-
try {
|
|
155
|
-
res =
|
|
156
|
-
method === "get"
|
|
157
|
-
? await client.get(path, query ? { query } : undefined)
|
|
158
|
-
: await client.post(path, undefined);
|
|
159
|
-
} catch (err) {
|
|
160
|
-
rethrowFetchError(err);
|
|
161
|
-
}
|
|
162
|
-
if (!res.ok) {
|
|
163
|
-
const body = await res.text().catch(() => "");
|
|
164
|
-
throw new Error(`Request failed: HTTP ${res.status} ${body}`.trim());
|
|
165
|
-
}
|
|
166
|
-
return (await res.json()) as T;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
async function listSaved(assistantName?: string): Promise<void> {
|
|
170
|
-
const client = createClient(assistantName);
|
|
171
|
-
const data = await requestJson<{ workflows: SavedWorkflow[] }>(
|
|
172
|
-
client,
|
|
173
|
-
"get",
|
|
174
|
-
"/workflows",
|
|
175
|
-
);
|
|
176
|
-
if (data.workflows.length === 0) {
|
|
177
|
-
console.log("No saved workflows found.");
|
|
178
|
-
return;
|
|
179
|
-
}
|
|
180
|
-
printSavedTable(data.workflows);
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
async function listRuns(
|
|
184
|
-
opts: { limit?: string; status?: string },
|
|
185
|
-
assistantName?: string,
|
|
186
|
-
): Promise<void> {
|
|
187
|
-
const client = createClient(assistantName);
|
|
188
|
-
const query: Record<string, string> = {};
|
|
189
|
-
if (opts.limit) query.limit = opts.limit;
|
|
190
|
-
if (opts.status) query.status = opts.status;
|
|
191
|
-
const data = await requestJson<{ runs: WorkflowRun[] }>(
|
|
192
|
-
client,
|
|
193
|
-
"get",
|
|
194
|
-
"/workflows/runs",
|
|
195
|
-
Object.keys(query).length ? query : undefined,
|
|
196
|
-
);
|
|
197
|
-
if (data.runs.length === 0) {
|
|
198
|
-
console.log("No workflow runs found.");
|
|
199
|
-
return;
|
|
200
|
-
}
|
|
201
|
-
printRunsTable(data.runs);
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
async function showRun(runId: string, assistantName?: string): Promise<void> {
|
|
205
|
-
const client = createClient(assistantName);
|
|
206
|
-
const run = await requestJson<WorkflowRun>(
|
|
207
|
-
client,
|
|
208
|
-
"get",
|
|
209
|
-
`/workflows/runs/${runId}`,
|
|
210
|
-
);
|
|
211
|
-
console.log(`ID: ${run.id}`);
|
|
212
|
-
console.log(`Name: ${run.name ?? "(unnamed)"}`);
|
|
213
|
-
console.log(`Status: ${run.status}`);
|
|
214
|
-
console.log(`Agents spawned: ${run.agentsSpawned}`);
|
|
215
|
-
console.log(
|
|
216
|
-
`Tokens: ${run.inputTokens} in / ${run.outputTokens} out`,
|
|
217
|
-
);
|
|
218
|
-
console.log(`Created: ${fmtTime(run.createdAt)}`);
|
|
219
|
-
console.log(`Finished: ${fmtTime(run.finishedAt)}`);
|
|
220
|
-
if (run.error) console.log(`Error: ${run.error}`);
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
async function abortRun(runId: string, assistantName?: string): Promise<void> {
|
|
224
|
-
const client = createClient(assistantName);
|
|
225
|
-
await requestJson<{ ok: boolean; runId: string }>(
|
|
226
|
-
client,
|
|
227
|
-
"post",
|
|
228
|
-
`/workflows/runs/${runId}/abort`,
|
|
229
|
-
);
|
|
230
|
-
console.log(`Abort signalled for workflow run ${runId}.`);
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
async function resumeRun(runId: string, assistantName?: string): Promise<void> {
|
|
234
|
-
const client = createClient(assistantName);
|
|
235
|
-
await requestJson<{ ok: boolean; runId: string }>(
|
|
236
|
-
client,
|
|
237
|
-
"post",
|
|
238
|
-
`/workflows/runs/${runId}/resume`,
|
|
239
|
-
);
|
|
240
|
-
console.log(
|
|
241
|
-
`Resumed workflow run ${runId}. It replays its completed steps and continues from where it was interrupted.`,
|
|
242
|
-
);
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
export const workflows = Object.assign(
|
|
246
|
-
async function workflows(): Promise<void> {
|
|
247
|
-
const args = process.argv.slice(3);
|
|
248
|
-
|
|
249
|
-
if (args.includes("--help") || args.includes("-h")) {
|
|
250
|
-
printHelp();
|
|
251
|
-
return;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
const assistantName = extractAssistantFlag(args);
|
|
255
|
-
const limit = extractValueFlag(args, "limit");
|
|
256
|
-
const status = extractValueFlag(args, "status");
|
|
257
|
-
const subcommand = args[0];
|
|
258
|
-
|
|
259
|
-
if (!subcommand || subcommand === "list") {
|
|
260
|
-
await listSaved(assistantName);
|
|
261
|
-
return;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
if (subcommand === "runs") {
|
|
265
|
-
await listRuns({ limit, status }, assistantName);
|
|
266
|
-
return;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
if (subcommand === "show") {
|
|
270
|
-
const runId = args[1];
|
|
271
|
-
if (!runId) {
|
|
272
|
-
console.error("Usage: cadet workflows show <run-id>");
|
|
273
|
-
process.exit(1);
|
|
274
|
-
}
|
|
275
|
-
await showRun(runId, assistantName);
|
|
276
|
-
return;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
if (subcommand === "abort") {
|
|
280
|
-
const runId = args[1];
|
|
281
|
-
if (!runId) {
|
|
282
|
-
console.error("Usage: cadet workflows abort <run-id>");
|
|
283
|
-
process.exit(1);
|
|
284
|
-
}
|
|
285
|
-
await abortRun(runId, assistantName);
|
|
286
|
-
return;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
if (subcommand === "resume") {
|
|
290
|
-
const runId = args[1];
|
|
291
|
-
if (!runId) {
|
|
292
|
-
console.error("Usage: cadet workflows resume <run-id>");
|
|
293
|
-
process.exit(1);
|
|
294
|
-
}
|
|
295
|
-
await resumeRun(runId, assistantName);
|
|
296
|
-
return;
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
console.error(`Unknown subcommand: ${subcommand}`);
|
|
300
|
-
printHelp();
|
|
301
|
-
process.exit(1);
|
|
302
|
-
},
|
|
303
|
-
{ description: "Inspect and control workflow runs" },
|
|
304
|
-
);
|
|
305
|
-
|
package/src/lib/managed-cloud.ts
DELETED