@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/ps.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isCloudHome } from "../lib/cloud-values.js";
|
|
2
2
|
import { join } from "path";
|
|
3
3
|
|
|
4
4
|
import {
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
getDaemonPidPath,
|
|
12
12
|
loadAllAssistants,
|
|
13
13
|
lookupAssistantByIdentifier,
|
|
14
|
+
readRootProcesses,
|
|
14
15
|
type AssistantEntry,
|
|
15
16
|
} from "../lib/assistant-config";
|
|
16
17
|
import { parseAssistantTargetArg } from "../lib/assistant-target-args.js";
|
|
@@ -23,7 +24,7 @@ import {
|
|
|
23
24
|
fetchManagedPs,
|
|
24
25
|
type ManagedProcessEntry,
|
|
25
26
|
} from "../lib/health-check";
|
|
26
|
-
import {
|
|
27
|
+
import { readCloudToken } from "../lib/cloud-client";
|
|
27
28
|
import { dockerResourceNames } from "../lib/docker";
|
|
28
29
|
import { existsSync } from "fs";
|
|
29
30
|
import {
|
|
@@ -44,14 +45,21 @@ import {
|
|
|
44
45
|
|
|
45
46
|
// ── Table formatting helpers ────────────────────────────────────
|
|
46
47
|
|
|
48
|
+
/** What each row's `type` column says: the KIND of process the row describes. */
|
|
49
|
+
const ASSISTANT_TYPE = "🧑🚀 Assistant";
|
|
50
|
+
const TUNNEL_TYPE = "🚇 Tunnel";
|
|
51
|
+
const APP_TYPE = "🌐 App";
|
|
52
|
+
|
|
47
53
|
interface TableRow {
|
|
48
54
|
name: string;
|
|
55
|
+
type: string;
|
|
49
56
|
status: string;
|
|
50
57
|
info: string;
|
|
51
58
|
}
|
|
52
59
|
|
|
53
60
|
interface ColWidths {
|
|
54
61
|
name: number;
|
|
62
|
+
type: number;
|
|
55
63
|
status: number;
|
|
56
64
|
info: number;
|
|
57
65
|
}
|
|
@@ -62,27 +70,38 @@ function pad(s: string, w: number): string {
|
|
|
62
70
|
|
|
63
71
|
function computeColWidths(
|
|
64
72
|
rows: TableRow[],
|
|
65
|
-
headers: TableRow = {
|
|
73
|
+
headers: TableRow = {
|
|
74
|
+
name: "NAME",
|
|
75
|
+
type: "TYPE",
|
|
76
|
+
status: "STATUS",
|
|
77
|
+
info: "INFO",
|
|
78
|
+
},
|
|
66
79
|
): ColWidths {
|
|
67
80
|
const all = [headers, ...rows];
|
|
68
81
|
return {
|
|
69
82
|
name: Math.max(...all.map((r) => r.name.length)),
|
|
83
|
+
type: Math.max(...all.map((r) => r.type.length)),
|
|
70
84
|
status: Math.max(...all.map((r) => r.status.length), "checking...".length),
|
|
71
85
|
info: Math.max(...all.map((r) => r.info.length)),
|
|
72
86
|
};
|
|
73
87
|
}
|
|
74
88
|
|
|
75
89
|
function formatRow(r: TableRow, colWidths: ColWidths): string {
|
|
76
|
-
return ` ${pad(r.name, colWidths.name)} ${pad(r.status, colWidths.status)} ${r.info}`;
|
|
90
|
+
return ` ${pad(r.name, colWidths.name)} ${pad(r.type, colWidths.type)} ${pad(r.status, colWidths.status)} ${r.info}`;
|
|
77
91
|
}
|
|
78
92
|
|
|
79
93
|
function printTable(
|
|
80
94
|
rows: TableRow[],
|
|
81
|
-
headers: TableRow = {
|
|
95
|
+
headers: TableRow = {
|
|
96
|
+
name: "PROCESS",
|
|
97
|
+
type: "TYPE",
|
|
98
|
+
status: "STATUS",
|
|
99
|
+
info: "INFO",
|
|
100
|
+
},
|
|
82
101
|
): void {
|
|
83
102
|
const colWidths = computeColWidths(rows, headers);
|
|
84
103
|
console.log(formatRow(headers, colWidths));
|
|
85
|
-
const sep = ` ${"-".repeat(colWidths.name)} ${"-".repeat(colWidths.status)} ${"-".repeat(colWidths.info)}`;
|
|
104
|
+
const sep = ` ${"-".repeat(colWidths.name)} ${"-".repeat(colWidths.type)} ${"-".repeat(colWidths.status)} ${"-".repeat(colWidths.info)}`;
|
|
86
105
|
console.log(sep);
|
|
87
106
|
for (const row of rows) {
|
|
88
107
|
console.log(formatRow(row, colWidths));
|
|
@@ -108,6 +127,7 @@ function flattenProcessTree(
|
|
|
108
127
|
rows.push({
|
|
109
128
|
name:
|
|
110
129
|
depth === 0 ? entry.name : `${" ".repeat(depth - 1)}├─ ${entry.name}`,
|
|
130
|
+
type: ASSISTANT_TYPE,
|
|
111
131
|
status: withStatusEmoji(STATUS_LABELS[entry.status]),
|
|
112
132
|
info: entry.info ?? "",
|
|
113
133
|
});
|
|
@@ -118,6 +138,7 @@ function flattenProcessTree(
|
|
|
118
138
|
const prefix = `${" ".repeat(depth)}${isLast ? "└─" : "├─"} ${child.name}`;
|
|
119
139
|
rows.push({
|
|
120
140
|
name: prefix,
|
|
141
|
+
type: ASSISTANT_TYPE,
|
|
121
142
|
status: withStatusEmoji(STATUS_LABELS[child.status]),
|
|
122
143
|
info: child.info ?? "",
|
|
123
144
|
});
|
|
@@ -284,9 +305,7 @@ async function getLocalProcesses(entry: AssistantEntry): Promise<TableRow[]> {
|
|
|
284
305
|
// tree (assistant + every child it owns, built from the OS process table)
|
|
285
306
|
// with the gateway's own entry appended — no hard-coded subsystem list to
|
|
286
307
|
// drift out of sync with what the assistant actually spawns.
|
|
287
|
-
const tree = gatewayUrl
|
|
288
|
-
? await fetchGatewayPs(gatewayUrl, token)
|
|
289
|
-
: null;
|
|
308
|
+
const tree = gatewayUrl ? await fetchGatewayPs(gatewayUrl, token) : null;
|
|
290
309
|
|
|
291
310
|
const rows: TableRow[] =
|
|
292
311
|
tree && tree.length > 0
|
|
@@ -303,6 +322,7 @@ async function getLocalProcesses(entry: AssistantEntry): Promise<TableRow[]> {
|
|
|
303
322
|
});
|
|
304
323
|
rows.push({
|
|
305
324
|
name: "credential-executor",
|
|
325
|
+
type: ASSISTANT_TYPE,
|
|
306
326
|
status: withStatusEmoji(ces.running ? "running" : "not running"),
|
|
307
327
|
info: ces.running ? formatDetectionInfo(ces) : "not detected",
|
|
308
328
|
});
|
|
@@ -349,6 +369,7 @@ async function detectLocalProcessesFallback(
|
|
|
349
369
|
|
|
350
370
|
return results.map((proc, i) => ({
|
|
351
371
|
name: allSpecs[i].name,
|
|
372
|
+
type: ASSISTANT_TYPE,
|
|
352
373
|
status: withStatusEmoji(proc.running ? "running" : "not running"),
|
|
353
374
|
info: proc.running ? formatDetectionInfo(proc) : "not detected",
|
|
354
375
|
}));
|
|
@@ -393,12 +414,14 @@ async function getDockerProcesses(entry: AssistantEntry): Promise<TableRow[]> {
|
|
|
393
414
|
if (!state) {
|
|
394
415
|
return {
|
|
395
416
|
name,
|
|
417
|
+
type: ASSISTANT_TYPE,
|
|
396
418
|
status: withStatusEmoji("not found"),
|
|
397
419
|
info: `container ${containerName}`,
|
|
398
420
|
};
|
|
399
421
|
}
|
|
400
422
|
return {
|
|
401
423
|
name,
|
|
424
|
+
type: ASSISTANT_TYPE,
|
|
402
425
|
status: withStatusEmoji(state === "running" ? "running" : state),
|
|
403
426
|
info: `container ${containerName}`,
|
|
404
427
|
};
|
|
@@ -412,6 +435,7 @@ async function getDockerProcesses(entry: AssistantEntry): Promise<TableRow[]> {
|
|
|
412
435
|
const alive = isLocalProcessAlive(watcherPid);
|
|
413
436
|
results.push({
|
|
414
437
|
name: "file-watcher",
|
|
438
|
+
type: ASSISTANT_TYPE,
|
|
415
439
|
status: withStatusEmoji(alive ? "running" : "not running"),
|
|
416
440
|
info: alive ? `PID ${watcherPid}` : "not detected",
|
|
417
441
|
});
|
|
@@ -430,44 +454,39 @@ function locationFor(entry: AssistantEntry): string {
|
|
|
430
454
|
return entry.runtimeUrl ?? "unknown — no runtime URL recorded";
|
|
431
455
|
}
|
|
432
456
|
|
|
433
|
-
async function
|
|
457
|
+
async function getAssistantProcessRows(
|
|
458
|
+
entry: AssistantEntry,
|
|
459
|
+
): Promise<TableRow[]> {
|
|
434
460
|
const cloud = entry.cloud;
|
|
435
461
|
|
|
436
462
|
console.log(`Processes for ${formatAssistantReference(entry)} (${cloud}):`);
|
|
437
463
|
console.log(`Location: ${locationFor(entry)}\n`);
|
|
438
464
|
|
|
439
465
|
if (cloud === "local") {
|
|
440
|
-
|
|
441
|
-
printTable(rows);
|
|
442
|
-
return;
|
|
466
|
+
return getLocalProcesses(entry);
|
|
443
467
|
}
|
|
444
468
|
|
|
445
469
|
if (cloud === "docker") {
|
|
446
|
-
|
|
447
|
-
printTable(rows);
|
|
448
|
-
return;
|
|
470
|
+
return getDockerProcesses(entry);
|
|
449
471
|
}
|
|
450
472
|
|
|
451
|
-
if (
|
|
473
|
+
if (isCloudHome(cloud)) {
|
|
452
474
|
console.log(` Cadet Cloud ID: ${entry.assistantId}\n`);
|
|
453
475
|
|
|
454
476
|
const psData = await fetchManagedPs(entry.runtimeUrl, entry.assistantId);
|
|
455
477
|
|
|
456
478
|
if (!psData) {
|
|
457
|
-
|
|
479
|
+
return [
|
|
458
480
|
{
|
|
459
481
|
name: "assistant",
|
|
482
|
+
type: ASSISTANT_TYPE,
|
|
460
483
|
status: withStatusEmoji("unreachable"),
|
|
461
484
|
info: "could not reach Cadet Cloud API — run `cadet login`",
|
|
462
485
|
},
|
|
463
486
|
];
|
|
464
|
-
printTable(rows);
|
|
465
|
-
return;
|
|
466
487
|
}
|
|
467
488
|
|
|
468
|
-
|
|
469
|
-
printTable(rows);
|
|
470
|
-
return;
|
|
489
|
+
return flattenProcessTree(psData.processes);
|
|
471
490
|
}
|
|
472
491
|
|
|
473
492
|
if (cloud === "apple-container") {
|
|
@@ -476,6 +495,7 @@ async function showAssistantProcesses(entry: AssistantEntry): Promise<void> {
|
|
|
476
495
|
const rows: TableRow[] = [
|
|
477
496
|
{
|
|
478
497
|
name: "container",
|
|
498
|
+
type: ASSISTANT_TYPE,
|
|
479
499
|
status: withStatusEmoji(socketAlive ? "running" : "not running"),
|
|
480
500
|
info: socketAlive
|
|
481
501
|
? `mgmt ${mgmtSocket}`
|
|
@@ -487,12 +507,12 @@ async function showAssistantProcesses(entry: AssistantEntry): Promise<void> {
|
|
|
487
507
|
const health = await checkHealth(entry.runtimeUrl, token);
|
|
488
508
|
rows.push({
|
|
489
509
|
name: "gateway",
|
|
510
|
+
type: ASSISTANT_TYPE,
|
|
490
511
|
status: withStatusEmoji(health.status),
|
|
491
512
|
info: entry.runtimeUrl + (health.detail ? ` | ${health.detail}` : ""),
|
|
492
513
|
});
|
|
493
514
|
}
|
|
494
|
-
|
|
495
|
-
return;
|
|
515
|
+
return rows;
|
|
496
516
|
}
|
|
497
517
|
|
|
498
518
|
if (cloud === "paired") {
|
|
@@ -500,15 +520,14 @@ async function showAssistantProcesses(entry: AssistantEntry): Promise<void> {
|
|
|
500
520
|
// list — probe the remote gateway's health over the bearer token instead.
|
|
501
521
|
const token = loadGuardianToken(entry.assistantId)?.accessToken;
|
|
502
522
|
const health = await checkHealth(entry.runtimeUrl, token);
|
|
503
|
-
|
|
523
|
+
return [
|
|
504
524
|
{
|
|
505
525
|
name: "gateway",
|
|
526
|
+
type: ASSISTANT_TYPE,
|
|
506
527
|
status: withStatusEmoji(health.status),
|
|
507
528
|
info: entry.runtimeUrl + (health.detail ? ` | ${health.detail}` : ""),
|
|
508
529
|
},
|
|
509
530
|
];
|
|
510
|
-
printTable(rows);
|
|
511
|
-
return;
|
|
512
531
|
}
|
|
513
532
|
|
|
514
533
|
let output: string;
|
|
@@ -525,7 +544,7 @@ async function showAssistantProcesses(entry: AssistantEntry): Promise<void> {
|
|
|
525
544
|
const msg = error instanceof Error ? error.message : String(error);
|
|
526
545
|
if (msg.includes("timed out")) {
|
|
527
546
|
console.warn(`Warning: remote process listing timed out — ${msg}`);
|
|
528
|
-
return;
|
|
547
|
+
return [];
|
|
529
548
|
}
|
|
530
549
|
console.error(`Failed to list processes: ${msg}`);
|
|
531
550
|
process.exit(1);
|
|
@@ -535,16 +554,93 @@ async function showAssistantProcesses(entry: AssistantEntry): Promise<void> {
|
|
|
535
554
|
|
|
536
555
|
if (procs.length === 0) {
|
|
537
556
|
console.log("No cadet processes found on the remote instance.");
|
|
538
|
-
return;
|
|
557
|
+
return [];
|
|
539
558
|
}
|
|
540
559
|
|
|
541
|
-
|
|
560
|
+
return procs.map((p) => ({
|
|
542
561
|
name: classifyProcess(p.command),
|
|
562
|
+
type: ASSISTANT_TYPE,
|
|
543
563
|
status: withStatusEmoji("running"),
|
|
544
564
|
info: `PID ${p.pid} | ${p.command.slice(0, 80)}`,
|
|
545
565
|
}));
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
// ── Root-managed process rows (tunnel agent, app edge) ──────────
|
|
569
|
+
|
|
570
|
+
/** A CLI-managed process row, plus the assistant it fronts (when recorded). */
|
|
571
|
+
interface RootManagedRow {
|
|
572
|
+
row: TableRow;
|
|
573
|
+
assistantId?: string;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
/**
|
|
577
|
+
* Rows for the CLI-managed processes recorded at the lockfile root: the
|
|
578
|
+
* `tunnel` agent and the `app` nginx edge. Pids are liveness-checked so a
|
|
579
|
+
* stale entry reads as not running rather than as a lie. Each row carries the
|
|
580
|
+
* assistant it fronts so the listing can nest it under that assistant.
|
|
581
|
+
*/
|
|
582
|
+
async function getRootManagedRows(): Promise<RootManagedRow[]> {
|
|
583
|
+
const { tunnel, app } = readRootProcesses();
|
|
584
|
+
const rows: RootManagedRow[] = [];
|
|
585
|
+
|
|
586
|
+
if (tunnel) {
|
|
587
|
+
const alive = isLocalProcessAlive(tunnel.pid);
|
|
588
|
+
rows.push({
|
|
589
|
+
assistantId: tunnel.assistantId,
|
|
590
|
+
row: {
|
|
591
|
+
name: tunnel.provider ?? "unknown provider",
|
|
592
|
+
type: TUNNEL_TYPE,
|
|
593
|
+
status: withStatusEmoji(alive ? "running" : "not running"),
|
|
594
|
+
info: alive ? `PID ${tunnel.pid}` : `PID ${tunnel.pid} (exited)`,
|
|
595
|
+
},
|
|
596
|
+
});
|
|
597
|
+
}
|
|
598
|
+
if (app) {
|
|
599
|
+
const alive = isLocalProcessAlive(app.pid);
|
|
600
|
+
rows.push({
|
|
601
|
+
assistantId: app.assistantId,
|
|
602
|
+
row: {
|
|
603
|
+
name: "nginx edge",
|
|
604
|
+
type: APP_TYPE,
|
|
605
|
+
status: withStatusEmoji(alive ? "running" : "not running"),
|
|
606
|
+
info: alive ? `PID ${app.pid}` : `PID ${app.pid} (exited)`,
|
|
607
|
+
},
|
|
608
|
+
});
|
|
609
|
+
}
|
|
610
|
+
return rows;
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
/**
|
|
614
|
+
* Fold the CLI-managed process rows into ONE table with the assistant rows:
|
|
615
|
+
* a process fronts an assistant when it recorded that assistant's id, and
|
|
616
|
+
* those rows nest under it; anything unattributed (or fronting an assistant
|
|
617
|
+
* this environment no longer lists) renders at the bottom, machine-level.
|
|
618
|
+
*/
|
|
619
|
+
async function assistantRowsWithRootProcesses(
|
|
620
|
+
assistants: AssistantEntry[],
|
|
621
|
+
healths: AssistantHealth[],
|
|
622
|
+
activeAssistantId: string | null,
|
|
623
|
+
): Promise<TableRow[]> {
|
|
624
|
+
const nestedByAssistant = new Map<string, TableRow[]>();
|
|
625
|
+
const unattributed: TableRow[] = [];
|
|
626
|
+
const knownIds = new Set(assistants.map((entry) => entry.assistantId));
|
|
627
|
+
for (const managed of await getRootManagedRows()) {
|
|
628
|
+
if (managed.assistantId && knownIds.has(managed.assistantId)) {
|
|
629
|
+
const nested = nestedByAssistant.get(managed.assistantId) ?? [];
|
|
630
|
+
nested.push({ ...managed.row, name: ` └ ${managed.row.name}` });
|
|
631
|
+
nestedByAssistant.set(managed.assistantId, nested);
|
|
632
|
+
} else {
|
|
633
|
+
unattributed.push(managed.row);
|
|
634
|
+
}
|
|
635
|
+
}
|
|
546
636
|
|
|
547
|
-
|
|
637
|
+
const rows: TableRow[] = [];
|
|
638
|
+
assistants.forEach((entry, i) => {
|
|
639
|
+
rows.push(formatAssistantListRow(entry, activeAssistantId, healths[i]!));
|
|
640
|
+
rows.push(...(nestedByAssistant.get(entry.assistantId) ?? []));
|
|
641
|
+
});
|
|
642
|
+
rows.push(...unattributed);
|
|
643
|
+
return rows;
|
|
548
644
|
}
|
|
549
645
|
|
|
550
646
|
// ── List all assistants (no arg) ────────────────────────────────
|
|
@@ -590,7 +686,7 @@ async function getAssistantListHealth(
|
|
|
590
686
|
: { status: "unknown", detail: "no runtime URL" };
|
|
591
687
|
}
|
|
592
688
|
|
|
593
|
-
if (
|
|
689
|
+
if (isCloudHome(entry.cloud)) {
|
|
594
690
|
return checkManagedHealth(entry.runtimeUrl, entry.assistantId);
|
|
595
691
|
}
|
|
596
692
|
|
|
@@ -611,6 +707,7 @@ function formatAssistantListRow(
|
|
|
611
707
|
const prefix = entry.assistantId === activeAssistantId ? "* " : " ";
|
|
612
708
|
return {
|
|
613
709
|
name: prefix + getAssistantDisplayName(entry),
|
|
710
|
+
type: ASSISTANT_TYPE,
|
|
614
711
|
status: withStatusEmoji(health.status),
|
|
615
712
|
info: infoParts.join(" | "),
|
|
616
713
|
};
|
|
@@ -630,13 +727,13 @@ export async function listAllAssistants(verbose: boolean): Promise<void> {
|
|
|
630
727
|
|
|
631
728
|
// Sync cloud assistants (when logged in) before listing. Login status has
|
|
632
729
|
// its own command — `cadet whoami` — so ps stays silent about it.
|
|
633
|
-
const
|
|
634
|
-
if (!
|
|
730
|
+
const cloudToken = readCloudToken();
|
|
731
|
+
if (!cloudToken) {
|
|
635
732
|
log?.("No platform token found — skipping cloud sync");
|
|
636
733
|
} else {
|
|
637
734
|
// A failed sync (offline, expired token) just means cloud-managed
|
|
638
735
|
// assistants may be stale — the local list still renders.
|
|
639
|
-
await syncCloudAssistants(
|
|
736
|
+
await syncCloudAssistants(cloudToken, { log });
|
|
640
737
|
}
|
|
641
738
|
console.log("");
|
|
642
739
|
|
|
@@ -654,6 +751,7 @@ export async function listAllAssistants(verbose: boolean): Promise<void> {
|
|
|
654
751
|
console.log("\nOrphaned processes detected:\n");
|
|
655
752
|
const rows: TableRow[] = orphans.map((o) => ({
|
|
656
753
|
name: o.name,
|
|
754
|
+
type: ASSISTANT_TYPE,
|
|
657
755
|
status: withStatusEmoji("running"),
|
|
658
756
|
info: `PID ${o.pid} (from ${o.source})`,
|
|
659
757
|
}));
|
|
@@ -666,60 +764,71 @@ export async function listAllAssistants(verbose: boolean): Promise<void> {
|
|
|
666
764
|
return;
|
|
667
765
|
}
|
|
668
766
|
|
|
669
|
-
const
|
|
670
|
-
assistants.map(
|
|
671
|
-
formatAssistantListRow(
|
|
672
|
-
entry,
|
|
673
|
-
activeAssistantId,
|
|
674
|
-
await getAssistantListHealth(entry),
|
|
675
|
-
),
|
|
676
|
-
),
|
|
767
|
+
const healths = await Promise.all(
|
|
768
|
+
assistants.map((entry) => getAssistantListHealth(entry)),
|
|
677
769
|
);
|
|
678
770
|
|
|
679
|
-
printTable(
|
|
680
|
-
|
|
771
|
+
printTable(
|
|
772
|
+
await assistantRowsWithRootProcesses(
|
|
773
|
+
assistants,
|
|
774
|
+
healths,
|
|
775
|
+
activeAssistantId,
|
|
776
|
+
),
|
|
777
|
+
{ name: "NAME", type: "TYPE", status: "STATUS", info: "INFO" },
|
|
778
|
+
);
|
|
681
779
|
}
|
|
682
780
|
|
|
683
781
|
// ── Entry point ─────────────────────────────────────────────────
|
|
684
782
|
|
|
685
783
|
export const ps = Object.assign(
|
|
686
784
|
async function ps(): Promise<void> {
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
785
|
+
const args = process.argv.slice(3);
|
|
786
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
787
|
+
console.log("Usage: cadet ps [<name-or-id>] [--verbose]");
|
|
788
|
+
console.log("");
|
|
789
|
+
console.log(
|
|
790
|
+
"List all assistants, or show processes for a specific assistant.",
|
|
791
|
+
);
|
|
792
|
+
console.log("");
|
|
793
|
+
console.log("Arguments:");
|
|
794
|
+
console.log(
|
|
795
|
+
" <name-or-id> Show processes for the assistant display name or ID",
|
|
796
|
+
);
|
|
797
|
+
console.log("");
|
|
798
|
+
console.log("Options:");
|
|
799
|
+
console.log(
|
|
800
|
+
" --verbose Show diagnostic logs (platform sync, auth issues)",
|
|
801
|
+
);
|
|
802
|
+
process.exit(0);
|
|
803
|
+
}
|
|
706
804
|
|
|
707
|
-
|
|
708
|
-
|
|
805
|
+
const verbose = args.includes("--verbose");
|
|
806
|
+
const assistantIdentifier = parseAssistantTargetArg(args);
|
|
709
807
|
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
808
|
+
if (!assistantIdentifier) {
|
|
809
|
+
await listAllAssistants(verbose);
|
|
810
|
+
return;
|
|
811
|
+
}
|
|
714
812
|
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
813
|
+
const result = lookupAssistantByIdentifier(assistantIdentifier);
|
|
814
|
+
if (result.status !== "found") {
|
|
815
|
+
console.error(formatAssistantLookupError(assistantIdentifier, result));
|
|
816
|
+
process.exit(1);
|
|
817
|
+
}
|
|
720
818
|
|
|
721
|
-
|
|
722
|
-
|
|
819
|
+
const rows = await getAssistantProcessRows(result.entry);
|
|
820
|
+
// The CLI-managed processes (root lockfile) that front THIS assistant ride
|
|
821
|
+
// the same table; ones fronting another assistant stay in the list view.
|
|
822
|
+
for (const managed of await getRootManagedRows()) {
|
|
823
|
+
if (
|
|
824
|
+
managed.assistantId &&
|
|
825
|
+
managed.assistantId !== result.entry.assistantId
|
|
826
|
+
) {
|
|
827
|
+
continue;
|
|
828
|
+
}
|
|
829
|
+
rows.push(managed.row);
|
|
830
|
+
}
|
|
831
|
+
printTable(rows);
|
|
832
|
+
},
|
|
723
833
|
{ description: "List assistants (or processes for a specific assistant)" },
|
|
724
834
|
);
|
|
725
|
-
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { sleep } from "./sleep.js";
|
|
2
|
+
import { wake } from "./wake.js";
|
|
3
|
+
|
|
4
|
+
export const restart = Object.assign(
|
|
5
|
+
async function restart(): Promise<void> {
|
|
6
|
+
const args = process.argv.slice(3);
|
|
7
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
8
|
+
console.log(
|
|
9
|
+
"Usage: cadet restart [<name> | --all] [--force] [--wait [<duration>]] [--repair-guardian]",
|
|
10
|
+
);
|
|
11
|
+
console.log("");
|
|
12
|
+
console.log("Sleep, then wake the assistant.");
|
|
13
|
+
console.log("");
|
|
14
|
+
console.log(
|
|
15
|
+
"Arguments and flags pass through to `cadet sleep` and `cadet wake`.",
|
|
16
|
+
);
|
|
17
|
+
console.log(
|
|
18
|
+
" --repair-guardian Re-provision the guardian token during the wake",
|
|
19
|
+
);
|
|
20
|
+
process.exit(0);
|
|
21
|
+
}
|
|
22
|
+
if (args.includes("--all") && args.includes("--repair-guardian")) {
|
|
23
|
+
console.error("Error: --all cannot be combined with --repair-guardian.");
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
await sleep();
|
|
27
|
+
await wake();
|
|
28
|
+
},
|
|
29
|
+
{ description: "Sleep, then wake the assistant" },
|
|
30
|
+
);
|