@mycadet/cli 0.13.0-dev.202610200020.9f20440 → 0.13.0-dev.202610201855.522ff0d
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/node_modules/@mycadet/assistant-api/constants/personality-sliders.test.ts +0 -8
- package/node_modules/@mycadet/assistant-api/constants/personality-sliders.ts +5 -41
- package/node_modules/@mycadet/assistant-api/events/message-complete.ts +0 -5
- package/node_modules/@mycadet/assistant-api/index.ts +0 -2
- package/node_modules/@mycadet/assistant-api/responses/conversation-message.ts +0 -10
- package/node_modules/@mycadet/environments/src/seeds.ts +6 -2
- package/node_modules/@mycadet/local-mode/node_modules/@mycadet/environments/src/seeds.ts +6 -2
- package/node_modules/@mycadet/local-mode/src/config.ts +0 -2
- package/node_modules/@mycadet/local-mode/src/index.ts +1 -1
- package/node_modules/@mycadet/local-mode/src/lockfile-contract.test.ts +1 -22
- package/node_modules/@mycadet/local-mode/src/lockfile-contract.ts +26 -7
- package/node_modules/@mycadet/local-mode/src/util.ts +1 -20
- package/node_modules/@mycadet/shared/github-repository.ts +5 -0
- package/node_modules/@mycadet/shared/package.json +10 -0
- package/node_modules/@mycadet/shared/scripts/run-isolated-tests.ts +700 -0
- package/package.json +3 -2
- package/src/__tests__/app-command.test.ts +164 -0
- package/src/__tests__/client-web-config.test.ts +0 -1
- package/src/__tests__/cloud-releases.test.ts +1 -1
- package/src/__tests__/local-version.test.ts +16 -0
- package/src/__tests__/nginx-ingress.test.ts +248 -630
- package/src/__tests__/ps-cloud-status.test.ts +85 -11
- package/src/__tests__/root-process-lockfile.test.ts +29 -2
- package/src/__tests__/tunnel-holder-heal.test.ts +119 -0
- package/src/__tests__/tunnel-stop.test.ts +6 -13
- package/src/__tests__/tunnel.test.ts +50 -193
- package/src/__tests__/wake.test.ts +6 -38
- package/src/__tests__/web-dist.test.ts +267 -89
- package/src/commands/app.ts +113 -0
- package/src/commands/backup.ts +5 -4
- package/src/commands/clean.ts +2 -1
- package/src/commands/client.ts +5 -68
- package/src/commands/completions.ts +12 -1
- package/src/commands/connect.ts +2 -1
- package/src/commands/debug.ts +2 -1
- package/src/commands/exec.ts +7 -6
- package/src/commands/gateway/token.ts +2 -1
- package/src/commands/gateway.ts +2 -1
- package/src/commands/hatch.ts +74 -80
- package/src/commands/login.ts +7 -6
- package/src/commands/logs.ts +2 -1
- package/src/commands/ps.ts +136 -6
- package/src/commands/restart.ts +2 -1
- package/src/commands/restore.ts +10 -9
- package/src/commands/retire.ts +4 -3
- package/src/commands/setup.ts +5 -4
- package/src/commands/sleep.ts +3 -2
- package/src/commands/teleport.ts +2 -1
- package/src/commands/terminal.ts +7 -6
- package/src/commands/tunnel.ts +196 -242
- package/src/commands/uninstall.ts +2 -1
- package/src/commands/upgrade.ts +2 -1
- package/src/commands/use.ts +2 -1
- package/src/commands/wake.ts +3 -2
- package/src/index.ts +5 -4
- package/src/lib/__tests__/web-dist.test.ts +1 -27
- package/src/lib/assistant-config.ts +101 -37
- package/src/lib/cli-name.ts +14 -0
- package/src/lib/cloud-client.ts +2 -1
- package/src/lib/cloud-login-poll.ts +2 -1
- package/src/lib/cloud-releases.ts +1 -1
- package/src/lib/docker.ts +32 -21
- package/src/lib/hatch-local.ts +1 -3
- package/src/lib/hatch-next-steps.ts +1 -9
- package/src/lib/ingress-config.ts +0 -31
- package/src/lib/local-version.ts +25 -4
- package/src/lib/local.ts +34 -9
- package/src/lib/nginx-ingress.ts +143 -244
- package/src/lib/provider-secrets.ts +0 -5
- package/src/lib/statefulset.ts +0 -1
- package/src/lib/tunnel.ts +244 -43
- package/src/lib/tunnels/ngrok.ts +57 -9
- package/src/lib/tunnels/tailscale.ts +2 -1
- package/src/lib/web-dist.ts +134 -56
- package/src/__tests__/flags.test.ts +0 -318
- package/src/__tests__/shell-mode.test.ts +0 -83
- package/src/commands/flags.ts +0 -255
- package/src/lib/flag-args.test.ts +0 -84
- package/src/lib/flag-args.ts +0 -74
- package/src/lib/github-repository.ts +0 -2
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { describe, expect, test } from "bun:test";
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
|
-
PERSONALITY_AXIS_IDS,
|
|
5
|
-
PERSONALITY_DIRECTION_AXES,
|
|
6
4
|
PERSONALITY_SLIDER_DEFAULT,
|
|
7
5
|
PERSONALITY_SLIDERS_PATH,
|
|
8
6
|
} from "./personality-sliders.js";
|
|
@@ -12,10 +10,4 @@ describe("personality slider contract", () => {
|
|
|
12
10
|
expect(PERSONALITY_SLIDERS_PATH).toBe("data/personality-sliders.json");
|
|
13
11
|
expect(PERSONALITY_SLIDER_DEFAULT).toBe(50);
|
|
14
12
|
});
|
|
15
|
-
|
|
16
|
-
test("every slider axis has a left and right direction pole", () => {
|
|
17
|
-
expect(PERSONALITY_DIRECTION_AXES.map((axis) => axis.sliderId)).toEqual(
|
|
18
|
-
Object.values(PERSONALITY_AXIS_IDS),
|
|
19
|
-
);
|
|
20
|
-
});
|
|
21
13
|
});
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Personality slider sidecar path
|
|
3
|
-
* hosted-Qwen direction poles those sliders map onto.
|
|
2
|
+
* Personality slider sidecar path and the five 0-100 axis ids.
|
|
4
3
|
*
|
|
5
|
-
* The web writes `data/personality-sliders.json
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* The web writes `data/personality-sliders.json` so the sliders reopen where
|
|
5
|
+
* the user left them. Both sides import these constants from
|
|
6
|
+
* `@mycadet/assistant-api` so the ids cannot drift.
|
|
8
7
|
*/
|
|
9
8
|
|
|
10
9
|
/** Workspace-relative sidecar holding the five 0-100 slider values. */
|
|
11
10
|
export const PERSONALITY_SLIDERS_PATH = "data/personality-sliders.json";
|
|
12
11
|
|
|
13
|
-
/** Sliders start centered.
|
|
12
|
+
/** Sliders start centered. */
|
|
14
13
|
export const PERSONALITY_SLIDER_DEFAULT = 50;
|
|
15
14
|
|
|
16
15
|
/**
|
|
@@ -27,38 +26,3 @@ export const PERSONALITY_AXIS_IDS = {
|
|
|
27
26
|
|
|
28
27
|
export type PersonalityAxisId =
|
|
29
28
|
(typeof PERSONALITY_AXIS_IDS)[keyof typeof PERSONALITY_AXIS_IDS];
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* One-sided direction poles for each slider. Center (50) activates neither.
|
|
33
|
-
* Values below 50 activate `left`; values above 50 activate `right`.
|
|
34
|
-
*/
|
|
35
|
-
export const PERSONALITY_DIRECTION_AXES = [
|
|
36
|
-
{
|
|
37
|
-
sliderId: PERSONALITY_AXIS_IDS.companionCoworker,
|
|
38
|
-
left: "companion",
|
|
39
|
-
right: "coworker",
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
sliderId: PERSONALITY_AXIS_IDS.genzBoomer,
|
|
43
|
-
left: "genz",
|
|
44
|
-
right: "boomer",
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
sliderId: PERSONALITY_AXIS_IDS.executeCollaborate,
|
|
48
|
-
left: "independent",
|
|
49
|
-
right: "collaborative",
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
sliderId: PERSONALITY_AXIS_IDS.playfulSerious,
|
|
53
|
-
left: "playful",
|
|
54
|
-
right: "serious",
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
sliderId: PERSONALITY_AXIS_IDS.politeUnfiltered,
|
|
58
|
-
left: "polite",
|
|
59
|
-
right: "unfiltered",
|
|
60
|
-
},
|
|
61
|
-
] as const;
|
|
62
|
-
|
|
63
|
-
export type PersonalityDirectionAxis =
|
|
64
|
-
(typeof PERSONALITY_DIRECTION_AXES)[number];
|
|
@@ -37,11 +37,6 @@ export const MessageCompleteEventSchema = z.object({
|
|
|
37
37
|
/** Soft warnings produced while resolving attachments (e.g. format
|
|
38
38
|
* conversions, size truncations). Display-only — not blocking. */
|
|
39
39
|
attachmentWarnings: z.array(z.string()).optional(),
|
|
40
|
-
/** How the completed row's plain text reached the user, mirroring the field
|
|
41
|
-
* of the same name on `ConversationMessage`. Set only on a turn that routed
|
|
42
|
-
* its reply through the `send_user_message` tool, so a client can give the
|
|
43
|
-
* live row the same per-row treatment it will get from history. */
|
|
44
|
-
assistantTextVisibility: z.enum(["private", "visible"]).optional(),
|
|
45
40
|
/** The default profile the Auto profile routed this turn to, mirroring the
|
|
46
41
|
* field of the same name on `ConversationMessage`. Set only on a turn that
|
|
47
42
|
* ran on Auto, so the live row can show which profile answered. */
|
|
@@ -163,11 +163,9 @@ export {
|
|
|
163
163
|
} from "./constants/document-tools.js";
|
|
164
164
|
export {
|
|
165
165
|
PERSONALITY_AXIS_IDS,
|
|
166
|
-
PERSONALITY_DIRECTION_AXES,
|
|
167
166
|
PERSONALITY_SLIDER_DEFAULT,
|
|
168
167
|
PERSONALITY_SLIDERS_PATH,
|
|
169
168
|
type PersonalityAxisId,
|
|
170
|
-
type PersonalityDirectionAxis,
|
|
171
169
|
} from "./constants/personality-sliders.js";
|
|
172
170
|
export {
|
|
173
171
|
MIN_INPUT_RESERVE_TOKENS,
|
|
@@ -633,16 +633,6 @@ export const ConversationMessageSchema = z.object({
|
|
|
633
633
|
* into the following user message. Absent on shutter photos, spoken turns
|
|
634
634
|
* carrying parked frames, and every other row. */
|
|
635
635
|
cameraFrame: z.literal(true).optional(),
|
|
636
|
-
/** How this assistant row's plain text reached the user, set only on a turn
|
|
637
|
-
* that routed its reply through the `send_user_message` tool. `"private"`
|
|
638
|
-
* means the row's text blocks are the model's working notes and the text
|
|
639
|
-
* the client shows came from the tool call; `"visible"` means the turn
|
|
640
|
-
* ended without ever calling the tool, so its raw text was surfaced as the
|
|
641
|
-
* fallback and is the reply. Absent on every other row. Clients gate
|
|
642
|
-
* per-row presentation (e.g. collapsing intermediate activity) on this
|
|
643
|
-
* rather than on the feature flag, so a row keeps the treatment it was
|
|
644
|
-
* written with. */
|
|
645
|
-
assistantTextVisibility: z.enum(["private", "visible"]).optional(),
|
|
646
636
|
/** Present on a reaction row, either direction: an inbound reaction the
|
|
647
637
|
* daemon persisted, or the assistant's own (`selfAuthored`). Clients
|
|
648
638
|
* render a reaction line from this instead of the row's stored sentinel
|
|
@@ -41,9 +41,13 @@ function portBlock(base: number): PortMap {
|
|
|
41
41
|
* package index's `.js`-suffixed runtime re-exports. Keep this file's
|
|
42
42
|
* imports type-only so it stays loadable on its own.
|
|
43
43
|
*/
|
|
44
|
-
export function
|
|
44
|
+
export function cloudWebUrl(envName: string | undefined): string {
|
|
45
45
|
const seed = (envName && SEEDS[envName]) || SEEDS.dev;
|
|
46
|
-
return
|
|
46
|
+
return seed.webUrl;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function cloudAssistantHubUrl(envName: string | undefined): string {
|
|
50
|
+
return `${cloudWebUrl(envName)}/assistant`;
|
|
47
51
|
}
|
|
48
52
|
|
|
49
53
|
/**
|
|
@@ -41,9 +41,13 @@ function portBlock(base: number): PortMap {
|
|
|
41
41
|
* package index's `.js`-suffixed runtime re-exports. Keep this file's
|
|
42
42
|
* imports type-only so it stays loadable on its own.
|
|
43
43
|
*/
|
|
44
|
-
export function
|
|
44
|
+
export function cloudWebUrl(envName: string | undefined): string {
|
|
45
45
|
const seed = (envName && SEEDS[envName]) || SEEDS.dev;
|
|
46
|
-
return
|
|
46
|
+
return seed.webUrl;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function cloudAssistantHubUrl(envName: string | undefined): string {
|
|
50
|
+
return `${cloudWebUrl(envName)}/assistant`;
|
|
47
51
|
}
|
|
48
52
|
|
|
49
53
|
/**
|
|
@@ -16,7 +16,6 @@ const PRODUCTION_ENVIRONMENT_NAME = "production";
|
|
|
16
16
|
export interface LocalEndpointConfig {
|
|
17
17
|
lockfilePaths: string[];
|
|
18
18
|
configDir: string;
|
|
19
|
-
webUrl: string;
|
|
20
19
|
cloudUrl: string;
|
|
21
20
|
}
|
|
22
21
|
|
|
@@ -35,7 +34,6 @@ export function resolveLocalConfigFromEnv(
|
|
|
35
34
|
return {
|
|
36
35
|
lockfilePaths: resolveLockfilePaths(env, options),
|
|
37
36
|
configDir: resolveConfigDir(env, options),
|
|
38
|
-
webUrl: env.CADET_WEB_URL || seed.webUrl,
|
|
39
37
|
cloudUrl: env.CADET_CLOUD_URL || seed.cloudUrl,
|
|
40
38
|
};
|
|
41
39
|
}
|
|
@@ -54,7 +54,7 @@ export {
|
|
|
54
54
|
export type { LockfileResult, WriteResult } from "./lockfile";
|
|
55
55
|
export { withLockfileLock } from "./lockfile-lock";
|
|
56
56
|
export type { LockfileLockResult } from "./lockfile-lock";
|
|
57
|
-
export { parseLockfile } from "./lockfile-contract";
|
|
57
|
+
export { getLoopbackGatewayPort, parseLockfile } from "./lockfile-contract";
|
|
58
58
|
export type {
|
|
59
59
|
Lockfile,
|
|
60
60
|
LockfileAssistant,
|
|
@@ -20,7 +20,6 @@ describe("parseLockfile", () => {
|
|
|
20
20
|
cloud: "cadet",
|
|
21
21
|
runtimeUrl: "http://127.0.0.1:7777",
|
|
22
22
|
hatchedAt: "2026-01-01T00:00:00.000Z",
|
|
23
|
-
organizationId: "org_1",
|
|
24
23
|
cloudAssistantId: "platform-assistant-1",
|
|
25
24
|
cloudBaseUrl: "https://platform.example.com",
|
|
26
25
|
cloudOrganizationId: "org_1",
|
|
@@ -169,24 +168,6 @@ describe("parseLockfile", () => {
|
|
|
169
168
|
expect(parseLockfile(raw).assistants).toEqual([]);
|
|
170
169
|
});
|
|
171
170
|
|
|
172
|
-
test("keeps organizationId on platform entries and drops it when mistyped", () => {
|
|
173
|
-
// Platform assistants carry their owning org so the host proxy can scope
|
|
174
|
-
// requests without guessing; local entries simply omit it.
|
|
175
|
-
const raw = {
|
|
176
|
-
assistants: [
|
|
177
|
-
{ assistantId: "asst_1", cloud: "cadet", organizationId: "org_1" },
|
|
178
|
-
{ assistantId: "asst_2", cloud: "cadet", organizationId: 7 }, // mistyped
|
|
179
|
-
{ assistantId: "asst_3", cloud: "local" }, // local, no org
|
|
180
|
-
],
|
|
181
|
-
activeAssistant: null,
|
|
182
|
-
};
|
|
183
|
-
expect(parseLockfile(raw).assistants).toEqual([
|
|
184
|
-
{ assistantId: "asst_1", cloud: "cadet", organizationId: "org_1" },
|
|
185
|
-
{ assistantId: "asst_2", cloud: "cadet" },
|
|
186
|
-
{ assistantId: "asst_3", cloud: "local" },
|
|
187
|
-
]);
|
|
188
|
-
});
|
|
189
|
-
|
|
190
171
|
test("keeps a well-typed ingressUrl and drops it when mistyped", () => {
|
|
191
172
|
// The tunnel-recorded public URL rides the entry so remote-web pairing
|
|
192
173
|
// surfaces can prefill it; a mistyped value is dropped, entry preserved.
|
|
@@ -312,9 +293,7 @@ describe("parseLockfile", () => {
|
|
|
312
293
|
|
|
313
294
|
test("prefers an explicit cloud over legacy remote markers", () => {
|
|
314
295
|
const raw = {
|
|
315
|
-
assistants: [
|
|
316
|
-
{ assistantId: "a", cloud: "cadet", project: "stale-proj" },
|
|
317
|
-
],
|
|
296
|
+
assistants: [{ assistantId: "a", cloud: "cadet", project: "stale-proj" }],
|
|
318
297
|
activeAssistant: null,
|
|
319
298
|
};
|
|
320
299
|
expect(parseLockfile(raw).assistants).toEqual([
|
|
@@ -61,6 +61,32 @@ export const SENSITIVE_KEYS = [
|
|
|
61
61
|
"guardianBootstrapSecret",
|
|
62
62
|
] as const;
|
|
63
63
|
|
|
64
|
+
/**
|
|
65
|
+
* Strip every `SENSITIVE_KEYS` field from a parsed lockfile, in place: from
|
|
66
|
+
* each assistant entry and from that entry's `resources`. The one redaction
|
|
67
|
+
* every host runs before lockfile data crosses to the renderer — pure, no
|
|
68
|
+
* node built-ins, so it lives beside the keys it enforces and bundles into
|
|
69
|
+
* the renderer through the `./contract` subpath.
|
|
70
|
+
*/
|
|
71
|
+
export function stripSensitiveFields(data: Record<string, unknown>): void {
|
|
72
|
+
const assistants = data.assistants;
|
|
73
|
+
if (!Array.isArray(assistants)) return;
|
|
74
|
+
for (const assistant of assistants) {
|
|
75
|
+
if (assistant && typeof assistant === "object") {
|
|
76
|
+
const entry = assistant as Record<string, unknown>;
|
|
77
|
+
for (const field of SENSITIVE_KEYS) {
|
|
78
|
+
delete entry[field];
|
|
79
|
+
}
|
|
80
|
+
const resources = entry.resources;
|
|
81
|
+
if (resources && typeof resources === "object") {
|
|
82
|
+
for (const field of SENSITIVE_KEYS) {
|
|
83
|
+
delete (resources as Record<string, unknown>)[field];
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
64
90
|
/**
|
|
65
91
|
* Resolve an entry's deployment topology from its raw on-disk fields. Prefers
|
|
66
92
|
* an explicit `cloud`, then the legacy markers that predate the field
|
|
@@ -197,19 +223,12 @@ export const LockfileAssistantSchema = z.object({
|
|
|
197
223
|
* `onboarded-assistant.ts`).
|
|
198
224
|
*/
|
|
199
225
|
onboardedAt: z.string().optional(),
|
|
200
|
-
/** Owning org for platform assistants; absent for local ones. */
|
|
201
|
-
organizationId: z.string().optional(),
|
|
202
226
|
/** Platform assistant UUID for a self-hosted local assistant registration. */
|
|
203
227
|
cloudAssistantId: z.string().optional(),
|
|
204
228
|
/** Platform base URL used for a self-hosted local assistant registration. */
|
|
205
229
|
cloudBaseUrl: z.string().optional(),
|
|
206
230
|
/** Platform organization UUID used for a self-hosted local assistant registration. */
|
|
207
231
|
cloudOrganizationId: z.string().optional(),
|
|
208
|
-
/** Pre-rename spellings of the cloud* fields above; readers fall back to
|
|
209
|
-
* them so lockfiles written before the platform→cloud rename still resolve. */
|
|
210
|
-
platformAssistantId: z.string().optional(),
|
|
211
|
-
platformBaseUrl: z.string().optional(),
|
|
212
|
-
platformOrganizationId: z.string().optional(),
|
|
213
232
|
/**
|
|
214
233
|
* Public https URL a `cadet tunnel` provider recorded for this assistant
|
|
215
234
|
* (mirrored from the workspace ingress config). A public address, so it is
|
|
@@ -2,8 +2,6 @@ import fs from "node:fs";
|
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
|
|
5
|
-
import { SENSITIVE_KEYS } from "./lockfile-contract";
|
|
6
|
-
|
|
7
5
|
const CLI_PACKAGE_NAME = "@mycadet/cli";
|
|
8
6
|
|
|
9
7
|
/**
|
|
@@ -19,24 +17,7 @@ export interface CliInvocation {
|
|
|
19
17
|
baseArgs: string[];
|
|
20
18
|
}
|
|
21
19
|
|
|
22
|
-
export
|
|
23
|
-
const assistants = data.assistants;
|
|
24
|
-
if (!Array.isArray(assistants)) return;
|
|
25
|
-
for (const assistant of assistants) {
|
|
26
|
-
if (assistant && typeof assistant === "object") {
|
|
27
|
-
const entry = assistant as Record<string, unknown>;
|
|
28
|
-
for (const field of SENSITIVE_KEYS) {
|
|
29
|
-
delete entry[field];
|
|
30
|
-
}
|
|
31
|
-
const resources = entry.resources;
|
|
32
|
-
if (resources && typeof resources === "object") {
|
|
33
|
-
for (const field of SENSITIVE_KEYS) {
|
|
34
|
-
delete (resources as Record<string, unknown>)[field];
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
20
|
+
export { stripSensitiveFields } from "./lockfile-contract";
|
|
40
21
|
|
|
41
22
|
function isLoopbackHostname(hostname: string): boolean {
|
|
42
23
|
const normalized = hostname.toLowerCase();
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** The GitHub repository Cadet's source and releases live in. */
|
|
2
|
+
export const CADET_GITHUB_REPOSITORY = "vargasjr-dev/mycadet-temp";
|
|
3
|
+
|
|
4
|
+
/** URL of the public GitHub repository. */
|
|
5
|
+
export const CADET_GITHUB_REPOSITORY_URL = `https://github.com/${CADET_GITHUB_REPOSITORY}`;
|