@mycadet/cli 0.12.7 → 0.12.9-dev.202610131452.9acab64
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 +6 -4
- 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 +1 -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 +15 -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 +149 -85
- package/src/__tests__/{ps-platform-status.test.ts → ps-cloud-status.test.ts} +80 -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 +180 -211
- package/src/__tests__/tunnel.test.ts +490 -270
- package/src/__tests__/uninstall.test.ts +150 -9
- 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 -78
- 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 +27 -24
- package/src/commands/login.ts +22 -22
- package/src/commands/logs.ts +8 -8
- package/src/commands/pair.ts +140 -37
- package/src/commands/ps.ts +232 -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 +110 -129
- package/src/commands/terminal.ts +158 -18
- package/src/commands/tunnel.ts +156 -175
- package/src/commands/uninstall.ts +137 -54
- 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-gateway-cli.test.ts +42 -0
- 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} +105 -99
- package/src/lib/cloud-login.ts +23 -24
- package/src/lib/{platform-releases.ts → cloud-releases.ts} +11 -9
- package/src/lib/cloud-values.ts +3 -0
- package/src/lib/color.ts +4 -0
- package/src/lib/config-utils.ts +1 -1
- package/src/lib/detached-process.ts +1 -1
- package/src/lib/docker.ts +300 -111
- package/src/lib/ensure-binary.ts +171 -0
- package/src/lib/environments/__tests__/paths.test.ts +29 -3
- package/src/lib/environments/__tests__/resolve.test.ts +26 -26
- package/src/lib/environments/paths.ts +16 -8
- package/src/lib/environments/resolve.ts +10 -12
- 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 +32 -29
- package/src/lib/hatch-next-steps.ts +5 -9
- 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 +46 -34
- package/src/lib/nginx-ingress.ts +40 -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/step-runner.ts +6 -1
- 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
package/src/commands/pair.ts
CHANGED
|
@@ -3,9 +3,12 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Print the pairing link for another device, and the same link rendered as a
|
|
5
5
|
* QR code. Runs on the machine hosting the assistant: it mints a remote-web
|
|
6
|
-
* pairing challenge
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* pairing challenge through the gateway CLI (`gateway pairing mint <url>` —
|
|
7
|
+
* locally, or docker-exec'd into the gateway container) which approves it
|
|
8
|
+
* immediately, so running this command IS the local-presence proof and one
|
|
9
|
+
* scan (or one paste into `cadet connect import`) completes the pairing.
|
|
10
|
+
* local and docker assistants mint without any HTTP; other topologies keep
|
|
11
|
+
* the loopback HTTP mint.
|
|
9
12
|
*
|
|
10
13
|
* `--web-approve` is the reverse direction: approve a code a device already
|
|
11
14
|
* shows, for pairings that device started on its own.
|
|
@@ -38,8 +41,11 @@ import {
|
|
|
38
41
|
import { GATEWAY_PORT } from "../lib/constants.js";
|
|
39
42
|
import { getCurrentEnvironment } from "../lib/environments/resolve.js";
|
|
40
43
|
import { isLoopbackUrl, loopbackSafeFetch } from "../lib/loopback-fetch.js";
|
|
44
|
+
import { dockerResourceNames } from "../lib/docker.js";
|
|
45
|
+
import { gatewayCliInvocation } from "../lib/local.js";
|
|
41
46
|
import { formatWebApproveFailure, parseGatewayErrorCode } from "../lib/pair.js";
|
|
42
47
|
import { STALE_CLI_UPDATE_HINT } from "../lib/stale-cli-hint.js";
|
|
48
|
+
import { execOutput } from "../lib/step-runner.js";
|
|
43
49
|
|
|
44
50
|
function assistantDisplayName(entry: AssistantEntry): string {
|
|
45
51
|
return entry.name || entry.assistantName || entry.assistantId;
|
|
@@ -89,9 +95,10 @@ function printUsage(): void {
|
|
|
89
95
|
USAGE:
|
|
90
96
|
cadet pair [assistant] [options]
|
|
91
97
|
|
|
92
|
-
Mints a pairing challenge on the assistant's gateway
|
|
93
|
-
|
|
94
|
-
|
|
98
|
+
Mints a pairing challenge on the assistant's gateway (via the gateway CLI
|
|
99
|
+
for local and docker assistants, over loopback HTTP otherwise) and approves
|
|
100
|
+
it on the spot (running this command on the host machine is the approval),
|
|
101
|
+
then prints the pairing link and the same link as a QR code.
|
|
95
102
|
Scanning the QR, opening the link, or passing it to 'cadet connect import'
|
|
96
103
|
on the other device completes the pairing in one step.
|
|
97
104
|
|
|
@@ -214,26 +221,122 @@ async function exitOnHttpError(response: Response): Promise<Response> {
|
|
|
214
221
|
return response;
|
|
215
222
|
}
|
|
216
223
|
|
|
217
|
-
/**
|
|
218
|
-
|
|
219
|
-
|
|
224
|
+
/**
|
|
225
|
+
* Mint (and approve) a remote-web pairing challenge. `local` and `docker`
|
|
226
|
+
* remotes mint through the gateway CLI — `gateway pairing mint <url>` run on
|
|
227
|
+
* the assistant's host (locally, or docker-exec'd into the gateway container)
|
|
228
|
+
* — replacing the old loopback HTTP mint whose loopback-peer gate
|
|
229
|
+
* containerized gateways could never satisfy (published-port NAT rewrites
|
|
230
|
+
* host-originated peers to the docker bridge address). The mint executes the
|
|
231
|
+
* pairing logic directly against the file-backed challenge store, so the
|
|
232
|
+
* running gateway's verification routes see it with no IPC round-trip.
|
|
233
|
+
* Process execution is the local-presence proof; the mint command approves
|
|
234
|
+
* on the spot, so the returned challenge is already paired-ready. Other
|
|
235
|
+
* topologies keep the loopback HTTP mint they used before.
|
|
236
|
+
*/
|
|
237
|
+
async function mintPairingChallengeOrExit(
|
|
238
|
+
entry: AssistantEntry,
|
|
239
|
+
publicBaseUrl: string,
|
|
240
|
+
): Promise<RemoteWebPairingChallengeResponse> {
|
|
241
|
+
if (entry.cloud !== "local" && entry.cloud !== "docker") {
|
|
242
|
+
return mintPairingChallengeOverLoopbackOrExit(entry, publicBaseUrl);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
let stdout: string;
|
|
246
|
+
try {
|
|
247
|
+
if (entry.cloud === "docker") {
|
|
248
|
+
stdout = await execOutput(
|
|
249
|
+
"docker",
|
|
250
|
+
[
|
|
251
|
+
"exec",
|
|
252
|
+
dockerResourceNames(entry.assistantId).gatewayContainer,
|
|
253
|
+
"bun",
|
|
254
|
+
"run",
|
|
255
|
+
"src/cli/index.ts",
|
|
256
|
+
"pairing",
|
|
257
|
+
"mint",
|
|
258
|
+
publicBaseUrl,
|
|
259
|
+
],
|
|
260
|
+
{ timeoutMs: 30_000 },
|
|
261
|
+
);
|
|
262
|
+
} else {
|
|
263
|
+
const invocation = gatewayCliInvocation(entry.resources);
|
|
264
|
+
stdout = await execOutput(
|
|
265
|
+
invocation.command,
|
|
266
|
+
[...invocation.args, "pairing", "mint", publicBaseUrl],
|
|
267
|
+
{
|
|
268
|
+
cwd: invocation.cwd,
|
|
269
|
+
env: invocation.env,
|
|
270
|
+
timeoutMs: 30_000,
|
|
271
|
+
},
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
} catch (err) {
|
|
275
|
+
console.error(
|
|
276
|
+
`Error: could not mint a pairing challenge on the gateway ` +
|
|
277
|
+
`(${err instanceof Error ? err.message : String(err)}).`,
|
|
278
|
+
);
|
|
279
|
+
console.error("Is the assistant running? Try `cadet wake`.");
|
|
280
|
+
process.exit(1);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const lastLine = stdout.split("\n").filter(Boolean).pop() ?? "";
|
|
284
|
+
let challenge: RemoteWebPairingChallengeResponse;
|
|
285
|
+
try {
|
|
286
|
+
challenge = JSON.parse(lastLine) as RemoteWebPairingChallengeResponse;
|
|
287
|
+
} catch {
|
|
288
|
+
console.error(
|
|
289
|
+
"Error: could not parse the gateway's pairing mint output.",
|
|
290
|
+
);
|
|
291
|
+
process.exit(1);
|
|
292
|
+
}
|
|
293
|
+
if (!challenge.deviceCode || !challenge.userCode) {
|
|
294
|
+
console.error(
|
|
295
|
+
"Error: the gateway's pairing mint output is missing the challenge codes.",
|
|
296
|
+
);
|
|
297
|
+
process.exit(1);
|
|
298
|
+
}
|
|
299
|
+
return challenge;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Mint a challenge over the gateway's loopback HTTP route — the path every
|
|
304
|
+
* topology took before the gateway-CLI mint existed. Kept for remotes that
|
|
305
|
+
* are neither `local` nor `docker` (apple containers, SSH-managed hosts,
|
|
306
|
+
* cloud-managed), where no gateway-CLI execution surface is defined.
|
|
307
|
+
*/
|
|
308
|
+
async function mintPairingChallengeOverLoopbackOrExit(
|
|
309
|
+
entry: AssistantEntry,
|
|
220
310
|
publicBaseUrl: string,
|
|
221
311
|
): Promise<RemoteWebPairingChallengeResponse> {
|
|
312
|
+
// Mint over loopback (localUrl avoids mDNS for same-machine calls), then
|
|
313
|
+
// approve immediately: running this CLI on the host IS the local-presence
|
|
314
|
+
// proof, so the other device completes pairing in one step from the link.
|
|
315
|
+
const mintUrl = (
|
|
316
|
+
entry.localUrl ||
|
|
317
|
+
entry.runtimeUrl ||
|
|
318
|
+
`http://127.0.0.1:${GATEWAY_PORT}`
|
|
319
|
+
).replace(/\/+$/, "");
|
|
222
320
|
const response = await gatewayPostOrExit(
|
|
223
|
-
|
|
321
|
+
mintUrl,
|
|
224
322
|
"/v1/remote-web/pairing-challenge",
|
|
225
323
|
{ publicBaseUrl } satisfies RemoteWebPairingChallengeRequest,
|
|
226
324
|
);
|
|
227
|
-
|
|
325
|
+
const challenge: RemoteWebPairingChallengeResponse =
|
|
326
|
+
await response.json();
|
|
327
|
+
await gatewayPostOrExit(mintUrl, "/v1/remote-web/pairing-verification", {
|
|
328
|
+
userCode: challenge.userCode,
|
|
329
|
+
} satisfies RemoteWebPairingVerificationRequest);
|
|
330
|
+
return challenge;
|
|
228
331
|
}
|
|
229
332
|
|
|
230
333
|
/**
|
|
231
334
|
* Approve a pending pairing challenge by its user code, the local-presence
|
|
232
335
|
* proof for the device-code flow. Single owner of the pairing-verification
|
|
233
|
-
* route and request body:
|
|
234
|
-
*
|
|
235
|
-
*
|
|
236
|
-
*
|
|
336
|
+
* route and request body: `--web-approve` calls this directly to inspect
|
|
337
|
+
* rejections and print mismatch diagnostics (see
|
|
338
|
+
* {@link formatWebApproveFailure}); the link flow needs no separate
|
|
339
|
+
* verification call — the gateway-CLI mint approves on the spot.
|
|
237
340
|
*/
|
|
238
341
|
async function postPairingVerification(
|
|
239
342
|
gatewayUrl: string,
|
|
@@ -244,20 +347,6 @@ async function postPairingVerification(
|
|
|
244
347
|
} satisfies RemoteWebPairingVerificationRequest);
|
|
245
348
|
}
|
|
246
349
|
|
|
247
|
-
/**
|
|
248
|
-
* Approve the challenge this command just minted so one scan completes
|
|
249
|
-
* pairing, exiting with a generic message on non-2xx.
|
|
250
|
-
*/
|
|
251
|
-
async function approveRemoteWebPairing(
|
|
252
|
-
gatewayUrl: string,
|
|
253
|
-
userCode: string,
|
|
254
|
-
): Promise<RemoteWebPairingVerificationResponse> {
|
|
255
|
-
const response = await exitOnHttpError(
|
|
256
|
-
await postPairingVerification(gatewayUrl, userCode),
|
|
257
|
-
);
|
|
258
|
-
return (await response.json()) as RemoteWebPairingVerificationResponse;
|
|
259
|
-
}
|
|
260
|
-
|
|
261
350
|
export const pair = Object.assign(
|
|
262
351
|
async function pair(): Promise<void> {
|
|
263
352
|
const rawArgs = process.argv.slice(3);
|
|
@@ -355,6 +444,24 @@ export const pair = Object.assign(
|
|
|
355
444
|
}
|
|
356
445
|
}
|
|
357
446
|
|
|
447
|
+
// Minting requires host presence on this machine. Native and docker
|
|
448
|
+
// topologies qualify (the latter via docker exec); an assistant this
|
|
449
|
+
// machine only knows through `connect import` has no host presence here
|
|
450
|
+
// at all, and `cadet pair` never worked against it (its loopback gate
|
|
451
|
+
// denied remote mints). Refuse clearly instead of a confusing mint
|
|
452
|
+
// failure.
|
|
453
|
+
if (entry.cloud === "paired") {
|
|
454
|
+
console.error(
|
|
455
|
+
`Error: ${formatAssistantReference(entry)} was paired as a remote ` +
|
|
456
|
+
"assistant (cadet connect import), so this machine does not host it.",
|
|
457
|
+
);
|
|
458
|
+
console.error(
|
|
459
|
+
"Run `cadet pair` on the machine hosting the assistant, or approve " +
|
|
460
|
+
"a code it shows with `cadet pair --web-approve <code>`.",
|
|
461
|
+
);
|
|
462
|
+
process.exit(1);
|
|
463
|
+
}
|
|
464
|
+
|
|
358
465
|
// Mint over loopback (localUrl avoids mDNS for same-machine calls), but
|
|
359
466
|
// advertise a REACHABLE url in the link, since the loopback url would point
|
|
360
467
|
// the other device at its own localhost. Prefer an explicit --url, then the
|
|
@@ -437,14 +544,10 @@ export const pair = Object.assign(
|
|
|
437
544
|
}
|
|
438
545
|
const publicBaseUrl = resolved.url;
|
|
439
546
|
|
|
440
|
-
// Mint a challenge
|
|
441
|
-
// IS the local-presence proof, so the other
|
|
442
|
-
// step from the link alone.
|
|
443
|
-
const challenge = await
|
|
444
|
-
mintUrl,
|
|
445
|
-
publicBaseUrl,
|
|
446
|
-
);
|
|
447
|
-
await approveRemoteWebPairing(mintUrl, challenge.userCode);
|
|
547
|
+
// Mint a challenge (approved on the spot by the gateway-CLI invocation):
|
|
548
|
+
// running this CLI on the host IS the local-presence proof, so the other
|
|
549
|
+
// device completes pairing in one step from the link alone.
|
|
550
|
+
const challenge = await mintPairingChallengeOrExit(entry, publicBaseUrl);
|
|
448
551
|
const pairUrl = buildRemoteWebPairingUrl(challenge);
|
|
449
552
|
const displayName = assistantDisplayName(entry);
|
|
450
553
|
const appUrl = appVariant
|