@mycadet/cli 0.12.7 → 0.12.9
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-cloud-login.ts +18 -0
- package/node_modules/@mycadet/assistant-api/index.ts +11 -11
- package/node_modules/@mycadet/assistant-api/node_modules/@mycadet/service-contracts/package.json +2 -2
- 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 +2 -2
- 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 +2 -2
- 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} +28 -18
- 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__/ensure-binary.test.ts +182 -0
- 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 +21 -20
- package/src/__tests__/ngrok-spawn.test.ts +49 -0
- 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__/ps-table.test.ts +79 -0
- 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} +2 -2
- package/src/__tests__/teleport-backup.test.ts +3 -3
- package/src/__tests__/teleport.test.ts +181 -197
- package/src/__tests__/tunnel.test.ts +257 -222
- 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 +260 -43
- package/src/__tests__/workos-pkce.test.ts +2 -2
- package/src/commands/backup.ts +24 -24
- package/src/commands/client.ts +76 -76
- package/src/commands/completions.test.ts +104 -0
- package/src/commands/completions.ts +87 -0
- package/src/commands/debug.ts +20 -20
- package/src/commands/exec.ts +12 -12
- package/src/commands/flags.ts +2 -2
- package/src/commands/hatch.ts +23 -23
- package/src/commands/login.ts +22 -22
- package/src/commands/logs.ts +8 -8
- package/src/commands/ps.ts +244 -86
- package/src/commands/restart.ts +30 -0
- package/src/commands/restore.ts +140 -22
- package/src/commands/retire.ts +48 -150
- package/src/commands/rollback.ts +20 -26
- package/src/commands/setup.ts +2 -2
- package/src/commands/sleep.ts +2 -2
- package/src/commands/teleport.ts +109 -109
- package/src/commands/terminal.ts +158 -18
- package/src/commands/tunnel.ts +138 -157
- package/src/commands/uninstall.ts +57 -9
- package/src/commands/unpair.ts +3 -3
- package/src/commands/upgrade.ts +30 -54
- package/src/commands/use.ts +1 -1
- package/src/commands/wake.ts +166 -50
- package/src/index.ts +18 -9
- package/src/lib/__tests__/{platform-client-signed-url.test.ts → cloud-client-signed-url.test.ts} +16 -16
- package/src/lib/__tests__/docker.test.ts +168 -20
- package/src/lib/__tests__/job-polling.test.ts +2 -2
- 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} +11 -9
- 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 +260 -53
- package/src/lib/ensure-binary.ts +171 -0
- 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/flag-args.test.ts +1 -1
- package/src/lib/flag-args.ts +1 -1
- package/src/lib/guardian-token.ts +37 -5
- 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 +2 -2
- 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 +10 -31
- package/src/lib/nginx-ingress.ts +42 -15
- package/src/lib/pair.ts +1 -1
- 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 +19 -19
- 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} +36 -15
- package/src/lib/tunnels/gateway-notify.ts +61 -0
- package/src/lib/{ngrok.ts → tunnels/ngrok.ts} +350 -89
- package/src/lib/{tailscale-tunnel.ts → tunnels/tailscale.ts} +53 -9
- package/src/lib/upgrade-lifecycle.ts +8 -21
- 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/node_modules/@mycadet/assistant-api/events/show-platform-login.ts +0 -20
- 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
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { loadAllAssistants } from "../lib/assistant-config.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Commands whose first positional argument is an assistant name — completing
|
|
5
|
+
* their first word offers the names of known assistants (from the lockfile)
|
|
6
|
+
* instead of falling through to shell file completion.
|
|
7
|
+
*/
|
|
8
|
+
const ASSISTANT_NAME_COMMANDS = new Set([
|
|
9
|
+
"exec",
|
|
10
|
+
"logs",
|
|
11
|
+
"message",
|
|
12
|
+
"restart",
|
|
13
|
+
"restore",
|
|
14
|
+
"retire",
|
|
15
|
+
"rollback",
|
|
16
|
+
"sleep",
|
|
17
|
+
"teleport",
|
|
18
|
+
"terminal",
|
|
19
|
+
"tunnel",
|
|
20
|
+
"unpair",
|
|
21
|
+
"upgrade",
|
|
22
|
+
"use",
|
|
23
|
+
"wake",
|
|
24
|
+
]);
|
|
25
|
+
|
|
26
|
+
/** Assistant names known to this CLI's lockfile; [] when the lockfile is unreadable. */
|
|
27
|
+
function assistantNames(): string[] {
|
|
28
|
+
try {
|
|
29
|
+
return loadAllAssistants()
|
|
30
|
+
.map((entry) => entry.assistantId)
|
|
31
|
+
.sort();
|
|
32
|
+
} catch {
|
|
33
|
+
return [];
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Resolve completion candidates for the word the cursor is on.
|
|
39
|
+
*
|
|
40
|
+
* `words` carries every command-line word after `cadet` up to the cursor,
|
|
41
|
+
* INCLUDING the (possibly empty) word being completed — the same shape bash
|
|
42
|
+
* passes via `COMP_WORDS[@]:1`. The returned list is UNFILTERED: the shell
|
|
43
|
+
* (`compgen -W`) does the prefix filtering, so the CLI only decides WHAT
|
|
44
|
+
* KIND of thing completes here.
|
|
45
|
+
*/
|
|
46
|
+
export function completeCadet(
|
|
47
|
+
input: string[],
|
|
48
|
+
commandNames: readonly string[],
|
|
49
|
+
): string[] {
|
|
50
|
+
const words = [...input];
|
|
51
|
+
const toComplete = words.pop() ?? "";
|
|
52
|
+
const preceding = words;
|
|
53
|
+
|
|
54
|
+
// Completing the command word itself (or nothing typed yet).
|
|
55
|
+
if (preceding.length === 0) {
|
|
56
|
+
return [...commandNames].sort();
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// First positional of an assistant-name command: offer instance names.
|
|
60
|
+
// Flag prefixes fall through to shell default (no flag completion yet).
|
|
61
|
+
if (
|
|
62
|
+
preceding.length === 1 &&
|
|
63
|
+
ASSISTANT_NAME_COMMANDS.has(preceding[0]) &&
|
|
64
|
+
!toComplete.startsWith("-")
|
|
65
|
+
) {
|
|
66
|
+
return assistantNames();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return [];
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const BASH_COMPLETION_SCRIPT = `# bash completion for the cadet CLI — load with: eval "$(cadet completions)"
|
|
73
|
+
_cadet_completions() {
|
|
74
|
+
local candidates
|
|
75
|
+
candidates=$(cadet __complete "\${COMP_WORDS[@]:1}" 2>/dev/null)
|
|
76
|
+
COMPREPLY=($(compgen -W "$candidates" -- "\${COMP_WORDS[COMP_CWORD]}"))
|
|
77
|
+
}
|
|
78
|
+
complete -F _cadet_completions cadet`;
|
|
79
|
+
|
|
80
|
+
// ── Entry point ─────────────────────────────────────────────────
|
|
81
|
+
|
|
82
|
+
export const completions = Object.assign(
|
|
83
|
+
async function completions(): Promise<void> {
|
|
84
|
+
console.log(BASH_COMPLETION_SCRIPT);
|
|
85
|
+
},
|
|
86
|
+
{ description: `Print bash completion setup (eval "$(cadet completions)")` },
|
|
87
|
+
);
|
package/src/commands/debug.ts
CHANGED
|
@@ -3,15 +3,15 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Send Cadet staff a debug bundle of a self-hosted assistant: the
|
|
5
5
|
* workspace, its logs, and the gateway's own database, with no credentials.
|
|
6
|
-
* Staff open it on a throwaway debug clone. The
|
|
6
|
+
* Staff open it on a throwaway debug clone. The cloud only hands out the
|
|
7
7
|
* upload URL while "Allow Staff Access" is on, and the bundle is deleted
|
|
8
8
|
* after seven days.
|
|
9
9
|
*
|
|
10
|
-
* Steps: the daemon is checked for the debug profile, the
|
|
10
|
+
* Steps: the daemon is checked for the debug profile, the cloud mints
|
|
11
11
|
* the upload URL, the daemon exports with the debug profile, and this
|
|
12
12
|
* command waits for the job so the result is real.
|
|
13
13
|
*/
|
|
14
|
-
import {
|
|
14
|
+
import { isCloudHome } from "../lib/cloud-values.js";
|
|
15
15
|
import {
|
|
16
16
|
formatAssistantReference,
|
|
17
17
|
resolveTargetAssistant,
|
|
@@ -29,9 +29,9 @@ import { loopbackSafeFetch } from "../lib/loopback-fetch.js";
|
|
|
29
29
|
import {
|
|
30
30
|
authHeaders,
|
|
31
31
|
authHeadersForKnownOrganization,
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
} from "../lib/
|
|
32
|
+
getCloudUrl,
|
|
33
|
+
readCloudToken,
|
|
34
|
+
} from "../lib/cloud-client.js";
|
|
35
35
|
import { compareVersions } from "../lib/version-compat.js";
|
|
36
36
|
|
|
37
37
|
// Matches the daemon's own upload deadline (EXPORT_TO_GCS_PUT_TIMEOUT_MS in
|
|
@@ -60,7 +60,7 @@ Arguments:
|
|
|
60
60
|
Requirements:
|
|
61
61
|
- 'Allow Staff Access' is on for the assistant (Settings > Privacy).
|
|
62
62
|
- You are logged in ('cadet login'), which also registers the
|
|
63
|
-
assistant with the
|
|
63
|
+
assistant with the cloud.
|
|
64
64
|
- The assistant runs version ${DEBUG_PROFILE_MIN_VERSION} or newer.
|
|
65
65
|
- The assistant is self-hosted. Cadet-hosted assistants need no bundle;
|
|
66
66
|
staff clone them directly.
|
|
@@ -88,30 +88,30 @@ export const debug = Object.assign(
|
|
|
88
88
|
|
|
89
89
|
const entry = resolveTargetAssistant(parseAssistantTargetArg(args));
|
|
90
90
|
const reference = formatAssistantReference(entry);
|
|
91
|
-
if (
|
|
91
|
+
if (isCloudHome(entry.cloud)) {
|
|
92
92
|
console.error(
|
|
93
93
|
`${reference} is hosted by Cadet, so staff can clone it directly. No bundle is needed.`,
|
|
94
94
|
);
|
|
95
95
|
process.exit(1);
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
const
|
|
99
|
-
if (!
|
|
98
|
+
const cloudToken = readCloudToken();
|
|
99
|
+
if (!cloudToken) {
|
|
100
100
|
console.error("Not logged in. Run 'cadet login' first.");
|
|
101
101
|
process.exit(1);
|
|
102
102
|
}
|
|
103
|
-
const
|
|
104
|
-
if (!
|
|
103
|
+
const cloudAssistantId = entry.cloudAssistantId?.trim();
|
|
104
|
+
if (!cloudAssistantId) {
|
|
105
105
|
console.error(
|
|
106
|
-
`${reference} is not registered with the
|
|
106
|
+
`${reference} is not registered with the cloud yet. Run 'cadet login' and retry.`,
|
|
107
107
|
);
|
|
108
108
|
process.exit(1);
|
|
109
109
|
}
|
|
110
|
-
const
|
|
111
|
-
const organizationId = entry.
|
|
110
|
+
const cloudUrl = entry.cloudBaseUrl?.trim() || getCloudUrl();
|
|
111
|
+
const organizationId = entry.cloudOrganizationId?.trim();
|
|
112
112
|
|
|
113
113
|
// Step 1: a guardian token for the daemon, and a check that the daemon
|
|
114
|
-
// knows the debug profile. This comes before the
|
|
114
|
+
// knows the debug profile. This comes before the cloud call so a
|
|
115
115
|
// daemon that would export credentials is refused before any URL exists.
|
|
116
116
|
let accessToken = await daemonAccessToken(entry, reference, false);
|
|
117
117
|
const { version } = await localRuntimeIdentity(entry, accessToken);
|
|
@@ -123,13 +123,13 @@ export const debug = Object.assign(
|
|
|
123
123
|
process.exit(1);
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
-
// Step 2: the
|
|
126
|
+
// Step 2: the cloud mints the upload URL, and refuses unless the
|
|
127
127
|
// owner's staff access grant is active.
|
|
128
128
|
const headers = organizationId
|
|
129
|
-
? authHeadersForKnownOrganization(
|
|
130
|
-
: await authHeaders(
|
|
129
|
+
? authHeadersForKnownOrganization(cloudToken, organizationId)
|
|
130
|
+
: await authHeaders(cloudToken, cloudUrl);
|
|
131
131
|
const urlResponse = await loopbackSafeFetch(
|
|
132
|
-
`${
|
|
132
|
+
`${cloudUrl}/v1/assistants/${encodeURIComponent(cloudAssistantId)}/debug-bundle-upload-url/`,
|
|
133
133
|
{ method: "POST", headers },
|
|
134
134
|
);
|
|
135
135
|
if (urlResponse.status === 403) {
|
package/src/commands/exec.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync } from "fs";
|
|
2
2
|
import { join } from "path";
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { isCloudHome } from "../lib/cloud-values.js";
|
|
5
5
|
import { spawn } from "child_process";
|
|
6
6
|
import { red } from "../lib/color";
|
|
7
7
|
|
|
@@ -9,7 +9,7 @@ import { resolveAssistant } from "../lib/assistant-config";
|
|
|
9
9
|
import { dockerResourceNames } from "../lib/docker";
|
|
10
10
|
import type { ServiceName } from "../lib/docker";
|
|
11
11
|
import { execAppleContainer } from "../lib/exec-apple-container";
|
|
12
|
-
import {
|
|
12
|
+
import { getCloudUrl, readCloudToken } from "../lib/cloud-client";
|
|
13
13
|
import { sshAppleContainer } from "../lib/ssh-apple-container";
|
|
14
14
|
import {
|
|
15
15
|
interactiveSession,
|
|
@@ -75,28 +75,28 @@ export const exec = Object.assign(
|
|
|
75
75
|
console.log("");
|
|
76
76
|
console.log("Arguments:");
|
|
77
77
|
console.log(
|
|
78
|
-
" <name> Name of the assistant
|
|
78
|
+
" <name> Name of the assistant, defaults to active",
|
|
79
79
|
);
|
|
80
80
|
console.log(
|
|
81
81
|
" <command...> Command and arguments to run (after --)",
|
|
82
82
|
);
|
|
83
83
|
console.log("");
|
|
84
84
|
console.log("Options:");
|
|
85
|
-
console.log(" --service <svc> Target service
|
|
85
|
+
console.log(" --service <svc> Target service, defaults to assistant");
|
|
86
86
|
console.log(
|
|
87
87
|
" -it Interactive mode with TTY (like docker exec -it)",
|
|
88
88
|
);
|
|
89
89
|
console.log(
|
|
90
|
-
" --timeout <secs> Timeout in seconds
|
|
90
|
+
" --timeout <secs> Timeout in seconds — default 30, 0 = no timeout",
|
|
91
91
|
);
|
|
92
92
|
console.log(
|
|
93
|
-
" --verbose Show debug output
|
|
93
|
+
" --verbose Show debug output",
|
|
94
94
|
);
|
|
95
95
|
console.log("");
|
|
96
96
|
console.log("Services:");
|
|
97
|
-
console.log(" assistant
|
|
98
|
-
console.log(" gateway
|
|
99
|
-
console.log(" credential-executor
|
|
97
|
+
console.log(" assistant");
|
|
98
|
+
console.log(" gateway");
|
|
99
|
+
console.log(" credential-executor");
|
|
100
100
|
console.log("");
|
|
101
101
|
console.log("Examples:");
|
|
102
102
|
console.log(" cadet exec -- ls -la /workspace");
|
|
@@ -243,8 +243,8 @@ export const exec = Object.assign(
|
|
|
243
243
|
return;
|
|
244
244
|
}
|
|
245
245
|
|
|
246
|
-
if (
|
|
247
|
-
const token =
|
|
246
|
+
if (isCloudHome(cloud)) {
|
|
247
|
+
const token = readCloudToken();
|
|
248
248
|
if (!token) {
|
|
249
249
|
console.error(
|
|
250
250
|
red("Not logged in. Run `cadet login` first to authenticate with Cadet Cloud."),
|
|
@@ -255,7 +255,7 @@ export const exec = Object.assign(
|
|
|
255
255
|
const assistant = {
|
|
256
256
|
assistantId: entry.assistantId,
|
|
257
257
|
token,
|
|
258
|
-
|
|
258
|
+
cloudUrl: getCloudUrl(),
|
|
259
259
|
};
|
|
260
260
|
|
|
261
261
|
const serviceParam = service === "assistant" ? undefined : service;
|
package/src/commands/flags.ts
CHANGED
|
@@ -59,7 +59,7 @@ function printFlagTable(flags: FeatureFlagEntry[]): void {
|
|
|
59
59
|
console.log(formatRow(row));
|
|
60
60
|
}
|
|
61
61
|
console.log("");
|
|
62
|
-
console.log("* = overridden
|
|
62
|
+
console.log("* = overridden");
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
function printHelp(): void {
|
|
@@ -67,7 +67,7 @@ function printHelp(): void {
|
|
|
67
67
|
console.log("");
|
|
68
68
|
console.log("Show and toggle feature flags for the active assistant.");
|
|
69
69
|
console.log(
|
|
70
|
-
"Reads from the gateway's merged flag state
|
|
70
|
+
"Reads from the gateway's merged flag state.",
|
|
71
71
|
);
|
|
72
72
|
console.log("");
|
|
73
73
|
console.log("Subcommands:");
|
package/src/commands/hatch.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Direct import — bun embeds this at compile time so it works in compiled binaries.
|
|
2
|
-
import {
|
|
2
|
+
import { isCloudHome } from "../lib/cloud-values.js";
|
|
3
3
|
import cliPkg from "../../package.json";
|
|
4
4
|
|
|
5
5
|
import {
|
|
@@ -12,10 +12,10 @@ import { hatchDocker } from "../lib/docker";
|
|
|
12
12
|
import { parseFeatureFlagArgs, readAmbientFlagEnvVars } from "../lib/flag-args";
|
|
13
13
|
import { hatchLocal } from "../lib/hatch-local";
|
|
14
14
|
import {
|
|
15
|
-
|
|
15
|
+
getCloudUrl,
|
|
16
16
|
hatchAssistant,
|
|
17
|
-
|
|
18
|
-
} from "../lib/
|
|
17
|
+
readCloudToken,
|
|
18
|
+
} from "../lib/cloud-client";
|
|
19
19
|
import { validateAssistantName } from "../lib/retire-archive";
|
|
20
20
|
|
|
21
21
|
const DEFAULT_REMOTE: RemoteHost = "local";
|
|
@@ -30,7 +30,7 @@ interface HatchArgs {
|
|
|
30
30
|
configValues: Record<string, string>;
|
|
31
31
|
flagEnvVars: Record<string, string>;
|
|
32
32
|
analyze: boolean;
|
|
33
|
-
|
|
33
|
+
disableCloud: boolean;
|
|
34
34
|
netnsContainer: string | null;
|
|
35
35
|
gatewayPort: number | null;
|
|
36
36
|
assistantCaCert: string | null;
|
|
@@ -41,10 +41,10 @@ function parseArgs(): HatchArgs {
|
|
|
41
41
|
process.argv.slice(3),
|
|
42
42
|
);
|
|
43
43
|
const flagEnvVars = { ...readAmbientFlagEnvVars(), ...cliFlagVars };
|
|
44
|
-
const
|
|
45
|
-
process.env.
|
|
46
|
-
let
|
|
47
|
-
|
|
44
|
+
const disableCloudAmbient =
|
|
45
|
+
process.env.CADET_DISABLE_CLOUD?.trim().toLowerCase();
|
|
46
|
+
let disableCloud =
|
|
47
|
+
disableCloudAmbient === "true" || disableCloudAmbient === "1";
|
|
48
48
|
let verbose = false;
|
|
49
49
|
let keepAlive = false;
|
|
50
50
|
let name: string | null = null;
|
|
@@ -76,7 +76,7 @@ function parseArgs(): HatchArgs {
|
|
|
76
76
|
" --watch Run assistant and gateway in watch mode (hot reload on source changes)",
|
|
77
77
|
);
|
|
78
78
|
console.log(
|
|
79
|
-
" --source <path> Build images from a local source tree at <path
|
|
79
|
+
" --source <path> Build images from a local source tree at <path>. Useful for callers that want each run to pick up local CLI changes.",
|
|
80
80
|
);
|
|
81
81
|
console.log(
|
|
82
82
|
" --keep-alive Stay alive after hatch, exit when gateway stops",
|
|
@@ -91,7 +91,7 @@ function parseArgs(): HatchArgs {
|
|
|
91
91
|
" --analyze Emit a structured hatch-timing log line on stdout",
|
|
92
92
|
);
|
|
93
93
|
console.log(
|
|
94
|
-
" --disable-
|
|
94
|
+
" --disable-cloud Suppress all outbound platform API calls",
|
|
95
95
|
);
|
|
96
96
|
console.log(
|
|
97
97
|
" --netns-container <name> Join an existing container's network namespace (docker target only) instead of creating a per-instance network. The namespace owner publishes host ports, so --gateway-port is required.",
|
|
@@ -162,8 +162,8 @@ function parseArgs(): HatchArgs {
|
|
|
162
162
|
const value = next.slice(eqIndex + 1);
|
|
163
163
|
configValues[key] = value;
|
|
164
164
|
i++;
|
|
165
|
-
} else if (arg === "--disable-
|
|
166
|
-
|
|
165
|
+
} else if (arg === "--disable-cloud") {
|
|
166
|
+
disableCloud = true;
|
|
167
167
|
} else if (arg === "--netns-container") {
|
|
168
168
|
const next = args[i + 1];
|
|
169
169
|
if (!next || next.startsWith("-")) {
|
|
@@ -193,7 +193,7 @@ function parseArgs(): HatchArgs {
|
|
|
193
193
|
i++;
|
|
194
194
|
} else {
|
|
195
195
|
console.error(
|
|
196
|
-
`Error: Unknown argument '${arg}'. Valid options: -v, --verbose, --watch, --source <path>, --keep-alive, --name <name>, --remote <${VALID_REMOTE_HOSTS.join("|")}>, --config <key=value>, --flag <key=value>, --analyze, --disable-
|
|
196
|
+
`Error: Unknown argument '${arg}'. Valid options: -v, --verbose, --watch, --source <path>, --keep-alive, --name <name>, --remote <${VALID_REMOTE_HOSTS.join("|")}>, --config <key=value>, --flag <key=value>, --analyze, --disable-cloud, --netns-container <name>, --gateway-port <port>, --assistant-ca-cert <path>`,
|
|
197
197
|
);
|
|
198
198
|
process.exit(1);
|
|
199
199
|
}
|
|
@@ -209,7 +209,7 @@ function parseArgs(): HatchArgs {
|
|
|
209
209
|
configValues,
|
|
210
210
|
flagEnvVars,
|
|
211
211
|
analyze,
|
|
212
|
-
|
|
212
|
+
disableCloud,
|
|
213
213
|
netnsContainer,
|
|
214
214
|
gatewayPort,
|
|
215
215
|
assistantCaCert,
|
|
@@ -237,15 +237,15 @@ export const hatch = Object.assign(
|
|
|
237
237
|
configValues,
|
|
238
238
|
flagEnvVars,
|
|
239
239
|
analyze,
|
|
240
|
-
|
|
240
|
+
disableCloud,
|
|
241
241
|
netnsContainer,
|
|
242
242
|
gatewayPort,
|
|
243
243
|
assistantCaCert,
|
|
244
244
|
} = parseArgs();
|
|
245
245
|
|
|
246
|
-
if (
|
|
247
|
-
process.env.
|
|
248
|
-
flagEnvVars.
|
|
246
|
+
if (disableCloud) {
|
|
247
|
+
process.env.CADET_DISABLE_CLOUD = "true";
|
|
248
|
+
flagEnvVars.CADET_DISABLE_CLOUD = "true";
|
|
249
249
|
}
|
|
250
250
|
|
|
251
251
|
if (watch && remote !== "local" && remote !== "docker") {
|
|
@@ -308,7 +308,7 @@ export const hatch = Object.assign(
|
|
|
308
308
|
return;
|
|
309
309
|
}
|
|
310
310
|
|
|
311
|
-
if (
|
|
311
|
+
if (isCloudHome(remote)) {
|
|
312
312
|
await hatchCadetPlatform();
|
|
313
313
|
return;
|
|
314
314
|
}
|
|
@@ -321,7 +321,7 @@ export const hatch = Object.assign(
|
|
|
321
321
|
|
|
322
322
|
|
|
323
323
|
async function hatchCadetPlatform(): Promise<void> {
|
|
324
|
-
const token =
|
|
324
|
+
const token = readCloudToken();
|
|
325
325
|
if (!token) {
|
|
326
326
|
console.error("Not logged in. Run `cadet login --token <token>` first.");
|
|
327
327
|
process.exit(1);
|
|
@@ -337,11 +337,11 @@ async function hatchCadetPlatform(): Promise<void> {
|
|
|
337
337
|
|
|
338
338
|
const { assistant: result } = await hatchAssistant(token);
|
|
339
339
|
|
|
340
|
-
const
|
|
340
|
+
const cloudUrl = getCloudUrl();
|
|
341
341
|
|
|
342
342
|
saveAssistantEntry({
|
|
343
343
|
assistantId: result.id,
|
|
344
|
-
runtimeUrl:
|
|
344
|
+
runtimeUrl: cloudUrl,
|
|
345
345
|
cloud: "cloud",
|
|
346
346
|
hatchedAt: new Date().toISOString(),
|
|
347
347
|
});
|
package/src/commands/login.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isCloudHome } from "../lib/cloud-values.js";
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
getActiveAssistant,
|
|
@@ -7,18 +7,18 @@ import {
|
|
|
7
7
|
setActiveAssistant,
|
|
8
8
|
} from "../lib/assistant-config";
|
|
9
9
|
import {
|
|
10
|
-
|
|
10
|
+
clearCloudToken,
|
|
11
11
|
fetchCurrentUser,
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
} from "../lib/
|
|
12
|
+
fetchCloudAssistants,
|
|
13
|
+
readCloudToken,
|
|
14
|
+
saveCloudToken,
|
|
15
|
+
} from "../lib/cloud-client";
|
|
16
16
|
import {
|
|
17
17
|
describeLoginError,
|
|
18
18
|
registerLocalAssistantWithPlatform,
|
|
19
19
|
workosPkceLogin,
|
|
20
20
|
} from "../lib/cloud-login.js";
|
|
21
|
-
import {
|
|
21
|
+
import { getCloudUrl } from "../lib/cloud-client";
|
|
22
22
|
import { syncCloudAssistants } from "../lib/sync-cloud-assistants";
|
|
23
23
|
|
|
24
24
|
|
|
@@ -34,7 +34,7 @@ export const login = Object.assign(
|
|
|
34
34
|
console.log("By default, opens a browser window for authentication.");
|
|
35
35
|
console.log("Alternatively, pass a session token directly with --token.");
|
|
36
36
|
console.log("");
|
|
37
|
-
console.log("On success, syncs cloud
|
|
37
|
+
console.log("On success, syncs cloud assistants to the local");
|
|
38
38
|
console.log("lockfile so they appear in `cadet ps`.");
|
|
39
39
|
console.log("");
|
|
40
40
|
console.log("Options:");
|
|
@@ -66,7 +66,7 @@ export const login = Object.assign(
|
|
|
66
66
|
|
|
67
67
|
// Block if already authenticated (unless --force)
|
|
68
68
|
if (!forceFlag && !token) {
|
|
69
|
-
const existingToken =
|
|
69
|
+
const existingToken = readCloudToken();
|
|
70
70
|
if (existingToken) {
|
|
71
71
|
try {
|
|
72
72
|
const existingUser = await fetchCurrentUser(existingToken);
|
|
@@ -83,7 +83,7 @@ export const login = Object.assign(
|
|
|
83
83
|
// If no --token flag, use app-held WorkOS PKCE login.
|
|
84
84
|
if (!token) {
|
|
85
85
|
try {
|
|
86
|
-
token = await workosPkceLogin(
|
|
86
|
+
token = await workosPkceLogin(getCloudUrl());
|
|
87
87
|
} catch (error) {
|
|
88
88
|
console.error(`❌ ${describeLoginError(error)}`);
|
|
89
89
|
process.exit(1);
|
|
@@ -94,10 +94,10 @@ export const login = Object.assign(
|
|
|
94
94
|
|
|
95
95
|
try {
|
|
96
96
|
const user = await fetchCurrentUser(token);
|
|
97
|
-
|
|
97
|
+
saveCloudToken(token);
|
|
98
98
|
console.log(`✅ Logged in as ${user.email}`);
|
|
99
99
|
|
|
100
|
-
// Register the local assistant with the
|
|
100
|
+
// Register the local assistant with the cloud (non-fatal).
|
|
101
101
|
// Mirrors the desktop app's LocalAssistantBootstrapService flow.
|
|
102
102
|
try {
|
|
103
103
|
await registerLocalAssistantWithPlatform(token, user);
|
|
@@ -105,8 +105,8 @@ export const login = Object.assign(
|
|
|
105
105
|
// Non-fatal — login succeeded even if registration fails
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
-
// Sync cloud assistants from the
|
|
109
|
-
// This ensures `cadet ps` shows
|
|
108
|
+
// Sync cloud assistants from the cloud into the local lockfile.
|
|
109
|
+
// This ensures `cadet ps` shows cloud assistants immediately
|
|
110
110
|
// after login (e.g. after a retire-and-rehatch cycle). We've just
|
|
111
111
|
// saved this token, so it's guaranteed non-empty here.
|
|
112
112
|
try {
|
|
@@ -122,9 +122,9 @@ export const login = Object.assign(
|
|
|
122
122
|
|
|
123
123
|
// If no active assistant is set, activate the first cloud one.
|
|
124
124
|
if (!getActiveAssistant()) {
|
|
125
|
-
const
|
|
126
|
-
if (
|
|
127
|
-
setActiveAssistant(
|
|
125
|
+
const cloudAssistants = await fetchCloudAssistants(token);
|
|
126
|
+
if (cloudAssistants.length > 0) {
|
|
127
|
+
setActiveAssistant(cloudAssistants[0].id);
|
|
128
128
|
}
|
|
129
129
|
}
|
|
130
130
|
} catch {
|
|
@@ -148,13 +148,13 @@ export const logout = Object.assign(
|
|
|
148
148
|
console.log("Usage: cadet logout");
|
|
149
149
|
console.log("");
|
|
150
150
|
console.log("Log out of Cadet Cloud, remove the stored session token,");
|
|
151
|
-
console.log("and remove cloud
|
|
151
|
+
console.log("and remove cloud assistants from the local lockfile.");
|
|
152
152
|
process.exit(0);
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
-
// Remove cloud
|
|
155
|
+
// Remove cloud assistants from the lockfile.
|
|
156
156
|
const cloudAssistants = loadAllAssistants().filter((a) =>
|
|
157
|
-
|
|
157
|
+
isCloudHome(a.cloud),
|
|
158
158
|
);
|
|
159
159
|
for (const a of cloudAssistants) {
|
|
160
160
|
removeAssistantEntry(a.assistantId);
|
|
@@ -165,7 +165,7 @@ export const logout = Object.assign(
|
|
|
165
165
|
);
|
|
166
166
|
}
|
|
167
167
|
|
|
168
|
-
|
|
168
|
+
clearCloudToken();
|
|
169
169
|
console.log("Logged out. Cadet Cloud token removed.");
|
|
170
170
|
},
|
|
171
171
|
{ description: "Log out of Cadet Cloud" },
|
|
@@ -182,7 +182,7 @@ export const whoami = Object.assign(
|
|
|
182
182
|
process.exit(0);
|
|
183
183
|
}
|
|
184
184
|
|
|
185
|
-
const token =
|
|
185
|
+
const token = readCloudToken();
|
|
186
186
|
if (!token) {
|
|
187
187
|
console.error("Not logged in. Run `cadet login` first.");
|
|
188
188
|
process.exit(1);
|
package/src/commands/logs.ts
CHANGED
|
@@ -32,19 +32,19 @@ function printHelp(): void {
|
|
|
32
32
|
console.log("");
|
|
33
33
|
console.log("Arguments:");
|
|
34
34
|
console.log(
|
|
35
|
-
" <name> Name of the assistant
|
|
35
|
+
" <name> Name of the assistant, defaults to latest",
|
|
36
36
|
);
|
|
37
37
|
console.log("");
|
|
38
38
|
console.log("Options:");
|
|
39
|
-
console.log(" -f, --follow Follow log output
|
|
40
|
-
console.log(" -n, --tail <N> Show last N lines
|
|
39
|
+
console.log(" -f, --follow Follow log output");
|
|
40
|
+
console.log(" -n, --tail <N> Show last N lines");
|
|
41
41
|
console.log(" -t, --timestamps Show timestamps on each line");
|
|
42
42
|
console.log(
|
|
43
|
-
" --since <time> Show logs since timestamp or relative
|
|
43
|
+
" --since <time> Show logs since timestamp or relative, e.g. 10m or 2h",
|
|
44
44
|
);
|
|
45
45
|
console.log(" --until <time> Show logs until timestamp or relative");
|
|
46
46
|
console.log(
|
|
47
|
-
" -s, --service <name> Filter to a specific service
|
|
47
|
+
" -s, --service <name> Filter to a specific service",
|
|
48
48
|
);
|
|
49
49
|
console.log(" -h, --help Show this help");
|
|
50
50
|
}
|
|
@@ -186,13 +186,13 @@ async function showLocalLogs(
|
|
|
186
186
|
|
|
187
187
|
if (opts.since && !sinceDate) {
|
|
188
188
|
console.error(
|
|
189
|
-
`Error: Could not parse --since value '${opts.since}'. Use relative
|
|
189
|
+
`Error: Could not parse --since value '${opts.since}'. Use a relative value such as 10m or 2h, or ISO format.`,
|
|
190
190
|
);
|
|
191
191
|
process.exit(1);
|
|
192
192
|
}
|
|
193
193
|
if (opts.until && !untilDate) {
|
|
194
194
|
console.error(
|
|
195
|
-
`Error: Could not parse --until value '${opts.until}'. Use relative
|
|
195
|
+
`Error: Could not parse --until value '${opts.until}'. Use a relative value such as 10m or 2h, or ISO format.`,
|
|
196
196
|
);
|
|
197
197
|
process.exit(1);
|
|
198
198
|
}
|
|
@@ -623,7 +623,7 @@ export const logs = Object.assign(
|
|
|
623
623
|
|
|
624
624
|
case "cadet":
|
|
625
625
|
console.error(
|
|
626
|
-
"Logs for Cadet
|
|
626
|
+
"Logs for Cadet Cloud instances are not yet supported.\n" +
|
|
627
627
|
"View logs in the Cadet Cloud dashboard.",
|
|
628
628
|
);
|
|
629
629
|
process.exit(1);
|