skydive-cli 0.1.0 → 0.2.0-beta.421
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/CHANGELOG.md +68 -0
- package/README.md +271 -28
- package/dist/js/api-CDTKq_5Q.mjs +145 -0
- package/dist/js/bin.mjs +1752 -1359
- package/dist/js/boot-CQLDUeZ9.mjs +9827 -0
- package/dist/js/client-B3ZhhF7e.mjs +366 -0
- package/dist/js/client-CpEvH2Pq.mjs +169 -0
- package/dist/js/client-D6NAkL9e.mjs +6 -0
- package/dist/js/output-B4cW10Ph.mjs +27 -0
- package/dist/js/print-B6AO13SA.mjs +5 -0
- package/dist/js/print-DausK_KZ.mjs +484 -0
- package/dist/js/print-share-D7OSxvE2.mjs +41 -0
- package/dist/js/raw-pty-2_VA1kw_.mjs +5 -0
- package/dist/js/raw-pty-GAvxm2ol.mjs +99 -0
- package/dist/js/rest-COkLEZOB.mjs +4 -0
- package/dist/js/{print-BHbFMxQv.mjs → rest-CamHVOce.mjs} +173 -158
- package/dist/js/theme-CuQhvqzN.mjs +990 -0
- package/dist/js/util-CeisaZVY.mjs +15 -0
- package/package.json +20 -9
- package/dist/js/boot-ChlVx-ts.mjs +0 -5525
|
@@ -0,0 +1,990 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import Conf from "conf";
|
|
4
|
+
import { err, ok } from "neverthrow";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
|
|
7
|
+
//#region src/config.ts
|
|
8
|
+
/** Default host for the public management API (`/v1`, API-key auth). */
|
|
9
|
+
const DEFAULT_API_URL = "https://api.skydive.com";
|
|
10
|
+
/**
|
|
11
|
+
* Default origin for the interactive chat client (`skydive chat`).
|
|
12
|
+
*
|
|
13
|
+
* The API host that serves better-auth (`/api/auth/*`) and the internal tRPC
|
|
14
|
+
* API (`/api/v1/trpc`) that chat streams over. We target the API host
|
|
15
|
+
* directly (not the web front door) because chat opens a WebSocket and
|
|
16
|
+
* authenticates with a bearer token on the upgrade request. Same host as
|
|
17
|
+
* `DEFAULT_API_URL`; override with `--api-url` / `SKYDIVE_APP_URL` for local
|
|
18
|
+
* dev or while the DNS record is still being provisioned.
|
|
19
|
+
*/
|
|
20
|
+
const DEFAULT_APP_URL = "https://api.skydive.com";
|
|
21
|
+
/** Web front door, for pages opened in the user's browser. */
|
|
22
|
+
const DEFAULT_WEB_URL = "https://skydive.com";
|
|
23
|
+
/**
|
|
24
|
+
* Origin for browser-facing links (e.g. opening a conversation's web page).
|
|
25
|
+
* The app origin is the API host, which serves no web UI in production, so
|
|
26
|
+
* map the default to the web front door. Overridden origins (local dev,
|
|
27
|
+
* previews) serve both and pass through unchanged.
|
|
28
|
+
*/
|
|
29
|
+
function resolveWebUrl(appUrl) {
|
|
30
|
+
return appUrl === DEFAULT_APP_URL ? DEFAULT_WEB_URL : appUrl;
|
|
31
|
+
}
|
|
32
|
+
/** Prefix on workspace-scoped Skydive API keys. Kept in sync with the API's
|
|
33
|
+
* `API_KEY_PREFIX` (`apps/anyone/api/src/lib/api-key.ts`); the CLI is a
|
|
34
|
+
* standalone published package so it can't import the backend constant. */
|
|
35
|
+
const API_KEY_PREFIX = "sky_live_";
|
|
36
|
+
/**
|
|
37
|
+
* Common prefix across all Skydive API key kinds — `sky_live_…` workspace
|
|
38
|
+
* keys today, `sky_user_…` account keys when ANY-5105 lands. The CLI only
|
|
39
|
+
* sanity-checks the family on `--api-key`; the server authoritatively rejects
|
|
40
|
+
* a kind that can't drive a given route, with a clearer message than the
|
|
41
|
+
* client could produce.
|
|
42
|
+
*/
|
|
43
|
+
const API_KEY_FAMILY_PREFIX = "sky_";
|
|
44
|
+
/** Where users mint and copy API keys. Shown in the login prompt. */
|
|
45
|
+
const API_KEYS_URL = "skydive.com/settings/account";
|
|
46
|
+
const store = new Conf({
|
|
47
|
+
projectName: process.env["SKYDIVE_CONFIG_NAME"] ?? "skydive",
|
|
48
|
+
projectSuffix: "",
|
|
49
|
+
configFileMode: 384
|
|
50
|
+
});
|
|
51
|
+
function resolveConfig(opts) {
|
|
52
|
+
const apiKey = process.env["SKYDIVE_API_KEY"] ?? store.get("apiKey");
|
|
53
|
+
const apiUrl = process.env["SKYDIVE_API_URL"] ?? opts.apiUrl ?? store.get("apiUrl") ?? DEFAULT_API_URL;
|
|
54
|
+
if (!apiKey) return err({ message: "Not authenticated. Run `skydive auth login` first." });
|
|
55
|
+
return ok({
|
|
56
|
+
apiKey,
|
|
57
|
+
apiUrl
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Resolve the bearer credential for the management API (`agents` / `keys` /
|
|
62
|
+
* `secrets`). The server's `/v1` gate accepts either an API key or the
|
|
63
|
+
* device-flow session bearer, so both work — but only one of them tracks the
|
|
64
|
+
* active workspace.
|
|
65
|
+
*
|
|
66
|
+
* An API key is pinned server-side to the organization that minted it and
|
|
67
|
+
* ignores the workspace header by design, so it can never follow `skydive
|
|
68
|
+
* workspace switch`. A key is also a strictly narrower credential than its
|
|
69
|
+
* owner's session. So the session wins whenever there is one, and a key is
|
|
70
|
+
* what's left for machines that never ran an interactive login.
|
|
71
|
+
*
|
|
72
|
+
* `SKYDIVE_SESSION_TOKEN=` (empty) suppresses session auth for one
|
|
73
|
+
* invocation, to drive a specific organization's key while signed in.
|
|
74
|
+
*/
|
|
75
|
+
function resolveManagementAuth(opts) {
|
|
76
|
+
const session = resolveSession({ appUrl: opts.apiUrl });
|
|
77
|
+
if (session.isOk()) return ok({
|
|
78
|
+
token: session.value.sessionToken,
|
|
79
|
+
apiUrl: session.value.appUrl,
|
|
80
|
+
kind: "session",
|
|
81
|
+
pinnedWorkspaceName: null
|
|
82
|
+
});
|
|
83
|
+
const envKey = process.env["SKYDIVE_API_KEY"];
|
|
84
|
+
const storedKey = store.get("apiKey");
|
|
85
|
+
const apiKey = envKey ?? storedKey;
|
|
86
|
+
if (apiKey) return ok({
|
|
87
|
+
token: apiKey,
|
|
88
|
+
apiUrl: process.env["SKYDIVE_API_URL"] ?? opts.apiUrl ?? store.get("apiUrl") ?? DEFAULT_API_URL,
|
|
89
|
+
kind: "api-key",
|
|
90
|
+
pinnedWorkspaceName: !envKey && storedKey ? store.get("apiKeyWorkspaceName") ?? null : null
|
|
91
|
+
});
|
|
92
|
+
return err({ message: "Not authenticated. Run `skydive auth login`." });
|
|
93
|
+
}
|
|
94
|
+
function saveConfig(config) {
|
|
95
|
+
store.set("apiKey", config.apiKey);
|
|
96
|
+
store.set("apiUrl", config.apiUrl);
|
|
97
|
+
if (config.apiKeyId) store.set("apiKeyId", config.apiKeyId);
|
|
98
|
+
else store.delete("apiKeyId");
|
|
99
|
+
if (config.workspaceName) store.set("apiKeyWorkspaceName", config.workspaceName);
|
|
100
|
+
else store.delete("apiKeyWorkspaceName");
|
|
101
|
+
}
|
|
102
|
+
/** Server-side id of the auto-minted key, if login minted one. */
|
|
103
|
+
function getStoredApiKeyId() {
|
|
104
|
+
return store.get("apiKeyId") ?? null;
|
|
105
|
+
}
|
|
106
|
+
/** Workspace the auto-minted key is pinned to, if login recorded one. */
|
|
107
|
+
function getStoredApiKeyWorkspaceName() {
|
|
108
|
+
return store.get("apiKeyWorkspaceName") ?? null;
|
|
109
|
+
}
|
|
110
|
+
function deleteConfig() {
|
|
111
|
+
store.clear();
|
|
112
|
+
}
|
|
113
|
+
function getConfigPath() {
|
|
114
|
+
return store.path;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Where the chat TUI persists its prompt history (up-arrow recall). Kept
|
|
118
|
+
* beside the config file so all CLI state lives in one directory.
|
|
119
|
+
*/
|
|
120
|
+
function getLastSeenVersion() {
|
|
121
|
+
return store.get("lastSeenVersion");
|
|
122
|
+
}
|
|
123
|
+
function setLastSeenVersion(version) {
|
|
124
|
+
store.set("lastSeenVersion", version);
|
|
125
|
+
}
|
|
126
|
+
function getPromptHistoryPath() {
|
|
127
|
+
return path.join(path.dirname(store.path), "prompt-history.jsonl");
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Where the chat TUI persists pending review comments — one JSON file per
|
|
131
|
+
* conversation, so a pending comment survives conversation switches and
|
|
132
|
+
* process death. Kept beside the config file like prompt history.
|
|
133
|
+
*/
|
|
134
|
+
function getReviewStateDir() {
|
|
135
|
+
return path.join(path.dirname(store.path), "review");
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Resolve the chat/auth origin. Precedence: `SKYDIVE_APP_URL` env > explicit
|
|
139
|
+
* `--api-url` style override > stored value > `SKYDIVE_API_URL` env >
|
|
140
|
+
* `DEFAULT_APP_URL`.
|
|
141
|
+
*
|
|
142
|
+
* The `SKYDIVE_API_URL` fallback matters for previews: the device/`--web`
|
|
143
|
+
* flow and chat hit the same api service as the management API, so pointing
|
|
144
|
+
* `SKYDIVE_API_URL` at a preview stack is enough — you don't also have to set
|
|
145
|
+
* `SKYDIVE_APP_URL`. Otherwise auth would silently fall through to prod
|
|
146
|
+
* (`DEFAULT_APP_URL`) and hand back a prod verification URL.
|
|
147
|
+
*/
|
|
148
|
+
function resolveAppUrl(opts) {
|
|
149
|
+
return process.env["SKYDIVE_APP_URL"] ?? opts.appUrl ?? store.get("appUrl") ?? process.env["SKYDIVE_API_URL"] ?? DEFAULT_APP_URL;
|
|
150
|
+
}
|
|
151
|
+
function resolveSession(opts) {
|
|
152
|
+
const sessionToken = process.env["SKYDIVE_SESSION_TOKEN"] ?? store.get("sessionToken");
|
|
153
|
+
const appUrl = resolveAppUrl(opts);
|
|
154
|
+
if (!sessionToken) return err({ message: "Not signed in for chat. Run `skydive chat` to sign in." });
|
|
155
|
+
return ok({
|
|
156
|
+
sessionToken,
|
|
157
|
+
appUrl
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
function saveSession(session) {
|
|
161
|
+
store.set("sessionToken", session.sessionToken);
|
|
162
|
+
store.set("sessionObtainedAt", (/* @__PURE__ */ new Date()).toISOString());
|
|
163
|
+
store.set("appUrl", session.appUrl);
|
|
164
|
+
}
|
|
165
|
+
function getSavedTheme(mode) {
|
|
166
|
+
return store.get(mode === "dark" ? "themeDark" : "themeLight");
|
|
167
|
+
}
|
|
168
|
+
function saveTheme(mode, themeId) {
|
|
169
|
+
store.set(mode === "dark" ? "themeDark" : "themeLight", themeId);
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Whether `skydive chat` should enable portal machine sharing on launch
|
|
173
|
+
* without `--share-machine`. Set by hand-editing `shareMachineDefault` in
|
|
174
|
+
* config.json — deliberately no CLI command (kept off the API surface).
|
|
175
|
+
* Sharing only makes the machine reachable — agents still need a
|
|
176
|
+
* (persistent) grant to run anything, so this default skips the per-session
|
|
177
|
+
* enable step, not the consent step.
|
|
178
|
+
*/
|
|
179
|
+
function getShareMachineDefault() {
|
|
180
|
+
return store.get("shareMachineDefault") ?? false;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Whether the update check is disabled via config.json (`"updateCheck":
|
|
184
|
+
* false`). The persistent counterpart to the SKYDIVE_NO_UPDATE_CHECK /
|
|
185
|
+
* NO_UPDATE_NOTIFIER env opt-outs; like shareMachineDefault, set by editing
|
|
186
|
+
* config.json — deliberately no CLI command.
|
|
187
|
+
*/
|
|
188
|
+
function getUpdateCheckDisabled() {
|
|
189
|
+
return store.get("updateCheck") === false;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
//#endregion
|
|
193
|
+
//#region src/auth/organization.ts
|
|
194
|
+
const workspaceSchema = z.object({
|
|
195
|
+
id: z.string(),
|
|
196
|
+
name: z.string(),
|
|
197
|
+
slug: z.string()
|
|
198
|
+
});
|
|
199
|
+
function authHeaders(sessionToken) {
|
|
200
|
+
return { authorization: `Bearer ${sessionToken}` };
|
|
201
|
+
}
|
|
202
|
+
async function listWorkspaces({ appUrl, sessionToken }) {
|
|
203
|
+
try {
|
|
204
|
+
const res = await fetch(`${appUrl}/api/auth/organization/list`, { headers: authHeaders(sessionToken) });
|
|
205
|
+
if (!res.ok) return err({ message: `failed to list workspaces (${res.status})` });
|
|
206
|
+
const parsed = z.array(workspaceSchema).safeParse(await res.json());
|
|
207
|
+
if (!parsed.success) return err({ message: "unexpected workspace list response" });
|
|
208
|
+
return ok(parsed.data);
|
|
209
|
+
} catch (e) {
|
|
210
|
+
return err({ message: e instanceof Error ? e.message : String(e) });
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Resolve who the current chat session belongs to: the signed-in user's
|
|
215
|
+
* email/name and the active workspace. Used by `auth status` so a user running
|
|
216
|
+
* multiple accounts can answer "am I logged into the right one?" without
|
|
217
|
+
* another command. Best-effort: any failure yields nulls rather than throwing,
|
|
218
|
+
* since `auth status` should still report the rest of the state.
|
|
219
|
+
*/
|
|
220
|
+
async function getSessionIdentity({ appUrl, sessionToken }) {
|
|
221
|
+
try {
|
|
222
|
+
const res = await fetch(`${appUrl}/api/auth/get-session?disableCookieCache=true`, { headers: authHeaders(sessionToken) });
|
|
223
|
+
if (!res.ok) return err({ message: `failed to read session (${res.status})` });
|
|
224
|
+
const parsed = z.object({
|
|
225
|
+
user: z.object({
|
|
226
|
+
email: z.string().nullable().optional(),
|
|
227
|
+
name: z.string().nullable().optional()
|
|
228
|
+
}).nullable().optional(),
|
|
229
|
+
session: z.object({ activeOrganizationId: z.string().nullable().optional() }).nullable().optional()
|
|
230
|
+
}).nullable().safeParse(await res.json());
|
|
231
|
+
if (!parsed.success) return err({ message: "unexpected session response" });
|
|
232
|
+
const activeWorkspaceId = parsed.data?.session?.activeOrganizationId ?? null;
|
|
233
|
+
let activeWorkspaceName = null;
|
|
234
|
+
if (activeWorkspaceId) {
|
|
235
|
+
const workspaces = await listWorkspaces({
|
|
236
|
+
appUrl,
|
|
237
|
+
sessionToken
|
|
238
|
+
});
|
|
239
|
+
if (workspaces.isOk()) activeWorkspaceName = workspaces.value.find((w) => w.id === activeWorkspaceId)?.name ?? null;
|
|
240
|
+
}
|
|
241
|
+
return ok({
|
|
242
|
+
email: parsed.data?.user?.email ?? null,
|
|
243
|
+
name: parsed.data?.user?.name ?? null,
|
|
244
|
+
activeWorkspaceId,
|
|
245
|
+
activeWorkspaceName
|
|
246
|
+
});
|
|
247
|
+
} catch (e) {
|
|
248
|
+
return err({ message: e instanceof Error ? e.message : String(e) });
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
/** The workspace bound to the current session, or `null` if none is set. */
|
|
252
|
+
async function getActiveWorkspaceId({ appUrl, sessionToken }) {
|
|
253
|
+
try {
|
|
254
|
+
const res = await fetch(`${appUrl}/api/auth/get-session?disableCookieCache=true`, { headers: authHeaders(sessionToken) });
|
|
255
|
+
if (!res.ok) return err({ message: `failed to read session (${res.status})` });
|
|
256
|
+
const parsed = z.object({ session: z.object({ activeOrganizationId: z.string().nullable().optional() }).nullable().optional() }).nullable().safeParse(await res.json());
|
|
257
|
+
if (!parsed.success) return err({ message: "unexpected session response" });
|
|
258
|
+
return ok(parsed.data?.session?.activeOrganizationId ?? null);
|
|
259
|
+
} catch (e) {
|
|
260
|
+
return err({ message: e instanceof Error ? e.message : String(e) });
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
async function setActiveWorkspace({ appUrl, sessionToken, organizationId }) {
|
|
264
|
+
try {
|
|
265
|
+
const res = await fetch(`${appUrl}/api/v1/workspaces/switch`, {
|
|
266
|
+
method: "POST",
|
|
267
|
+
headers: {
|
|
268
|
+
...authHeaders(sessionToken),
|
|
269
|
+
"content-type": "application/json"
|
|
270
|
+
},
|
|
271
|
+
body: JSON.stringify({ organizationId })
|
|
272
|
+
});
|
|
273
|
+
if (!res.ok) return err({ message: `failed to switch workspace (${res.status})` });
|
|
274
|
+
return ok(void 0);
|
|
275
|
+
} catch (e) {
|
|
276
|
+
return err({ message: e instanceof Error ? e.message : String(e) });
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Ensures the session has an active workspace. The device flow issues a
|
|
281
|
+
* session without one (unlike a normal web sign-in, which sets it), so the
|
|
282
|
+
* internal API rejects every request with "no active organization" until we
|
|
283
|
+
* set it. Picks the account's first workspace by join order — run `skydive
|
|
284
|
+
* workspace list` + `skydive workspace switch` afterward if that's the wrong
|
|
285
|
+
* one (e.g. a personal workspace joined before a shared team workspace).
|
|
286
|
+
*/
|
|
287
|
+
async function ensureActiveOrganization({ appUrl, sessionToken }) {
|
|
288
|
+
const workspaces = await listWorkspaces({
|
|
289
|
+
appUrl,
|
|
290
|
+
sessionToken
|
|
291
|
+
});
|
|
292
|
+
if (workspaces.isErr()) return err(workspaces.error);
|
|
293
|
+
const workspace = workspaces.value[0];
|
|
294
|
+
if (!workspace) return err({ message: "your account has no organization yet" });
|
|
295
|
+
const setResult = await setActiveWorkspace({
|
|
296
|
+
appUrl,
|
|
297
|
+
sessionToken,
|
|
298
|
+
organizationId: workspace.id
|
|
299
|
+
});
|
|
300
|
+
if (setResult.isErr()) return err(setResult.error);
|
|
301
|
+
return ok({
|
|
302
|
+
organizationId: workspace.id,
|
|
303
|
+
name: workspace.name
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
//#endregion
|
|
308
|
+
//#region src/chat/tui/theme.ts
|
|
309
|
+
const tokyonight = {
|
|
310
|
+
id: "tokyonight",
|
|
311
|
+
label: "Tokyo Night",
|
|
312
|
+
mode: "dark",
|
|
313
|
+
palette: {
|
|
314
|
+
fg: "#c0caf5",
|
|
315
|
+
muted: "#7a7a7a",
|
|
316
|
+
dim: "#565f89",
|
|
317
|
+
faint: "#3b4261",
|
|
318
|
+
surface: "#16161e",
|
|
319
|
+
accent: "#7aa2f7",
|
|
320
|
+
success: "#9ece6a",
|
|
321
|
+
warning: "#e0af68",
|
|
322
|
+
error: "#f7768e",
|
|
323
|
+
user: "#7aa2f7",
|
|
324
|
+
assistant: "#c0caf5",
|
|
325
|
+
tool: "#bb9af7",
|
|
326
|
+
reasoning: "#565f89",
|
|
327
|
+
syntaxBlue: "#7aa2f7",
|
|
328
|
+
syntaxCyan: "#7dcfff",
|
|
329
|
+
syntaxTeal: "#73daca",
|
|
330
|
+
syntaxGreen: "#9ece6a",
|
|
331
|
+
syntaxYellow: "#e0af68",
|
|
332
|
+
syntaxOrange: "#ff9e64",
|
|
333
|
+
syntaxRed: "#f7768e",
|
|
334
|
+
syntaxMagenta: "#bb9af7"
|
|
335
|
+
}
|
|
336
|
+
};
|
|
337
|
+
const tokyonightDay = {
|
|
338
|
+
id: "tokyonight-day",
|
|
339
|
+
label: "Tokyo Night Day",
|
|
340
|
+
mode: "light",
|
|
341
|
+
palette: {
|
|
342
|
+
fg: "#3760bf",
|
|
343
|
+
muted: "#848cb5",
|
|
344
|
+
dim: "#9da3c2",
|
|
345
|
+
faint: "#c4c8da",
|
|
346
|
+
surface: "#d0d1d8",
|
|
347
|
+
accent: "#2e7de9",
|
|
348
|
+
success: "#587539",
|
|
349
|
+
warning: "#8c6c3e",
|
|
350
|
+
error: "#f52a65",
|
|
351
|
+
user: "#2e7de9",
|
|
352
|
+
assistant: "#3760bf",
|
|
353
|
+
tool: "#9854f1",
|
|
354
|
+
reasoning: "#848cb5",
|
|
355
|
+
syntaxBlue: "#2e7de9",
|
|
356
|
+
syntaxCyan: "#007197",
|
|
357
|
+
syntaxTeal: "#118c74",
|
|
358
|
+
syntaxGreen: "#587539",
|
|
359
|
+
syntaxYellow: "#8c6c3e",
|
|
360
|
+
syntaxOrange: "#b15c00",
|
|
361
|
+
syntaxRed: "#f52a65",
|
|
362
|
+
syntaxMagenta: "#9854f1"
|
|
363
|
+
}
|
|
364
|
+
};
|
|
365
|
+
const catppuccinMocha = {
|
|
366
|
+
id: "catppuccin-mocha",
|
|
367
|
+
label: "Catppuccin Mocha",
|
|
368
|
+
mode: "dark",
|
|
369
|
+
palette: {
|
|
370
|
+
fg: "#cdd6f4",
|
|
371
|
+
muted: "#7f849c",
|
|
372
|
+
dim: "#6c7086",
|
|
373
|
+
faint: "#45475a",
|
|
374
|
+
surface: "#181825",
|
|
375
|
+
accent: "#89b4fa",
|
|
376
|
+
success: "#a6e3a1",
|
|
377
|
+
warning: "#f9e2af",
|
|
378
|
+
error: "#f38ba8",
|
|
379
|
+
user: "#89b4fa",
|
|
380
|
+
assistant: "#cdd6f4",
|
|
381
|
+
tool: "#cba6f7",
|
|
382
|
+
reasoning: "#6c7086",
|
|
383
|
+
syntaxBlue: "#89b4fa",
|
|
384
|
+
syntaxCyan: "#89dceb",
|
|
385
|
+
syntaxTeal: "#94e2d5",
|
|
386
|
+
syntaxGreen: "#a6e3a1",
|
|
387
|
+
syntaxYellow: "#f9e2af",
|
|
388
|
+
syntaxOrange: "#fab387",
|
|
389
|
+
syntaxRed: "#f38ba8",
|
|
390
|
+
syntaxMagenta: "#cba6f7"
|
|
391
|
+
}
|
|
392
|
+
};
|
|
393
|
+
const catppuccinLatte = {
|
|
394
|
+
id: "catppuccin-latte",
|
|
395
|
+
label: "Catppuccin Latte",
|
|
396
|
+
mode: "light",
|
|
397
|
+
palette: {
|
|
398
|
+
fg: "#4c4f69",
|
|
399
|
+
muted: "#8c8fa1",
|
|
400
|
+
dim: "#9ca0b0",
|
|
401
|
+
faint: "#bcc0cc",
|
|
402
|
+
surface: "#e6e9ef",
|
|
403
|
+
accent: "#1e66f5",
|
|
404
|
+
success: "#40a02b",
|
|
405
|
+
warning: "#df8e1d",
|
|
406
|
+
error: "#d20f39",
|
|
407
|
+
user: "#1e66f5",
|
|
408
|
+
assistant: "#4c4f69",
|
|
409
|
+
tool: "#8839ef",
|
|
410
|
+
reasoning: "#9ca0b0",
|
|
411
|
+
syntaxBlue: "#1e66f5",
|
|
412
|
+
syntaxCyan: "#04a5e5",
|
|
413
|
+
syntaxTeal: "#179299",
|
|
414
|
+
syntaxGreen: "#40a02b",
|
|
415
|
+
syntaxYellow: "#df8e1d",
|
|
416
|
+
syntaxOrange: "#fe640b",
|
|
417
|
+
syntaxRed: "#d20f39",
|
|
418
|
+
syntaxMagenta: "#8839ef"
|
|
419
|
+
}
|
|
420
|
+
};
|
|
421
|
+
const gruvboxDark = {
|
|
422
|
+
id: "gruvbox-dark",
|
|
423
|
+
label: "Gruvbox Dark",
|
|
424
|
+
mode: "dark",
|
|
425
|
+
palette: {
|
|
426
|
+
fg: "#ebdbb2",
|
|
427
|
+
muted: "#928374",
|
|
428
|
+
dim: "#7c6f64",
|
|
429
|
+
faint: "#504945",
|
|
430
|
+
surface: "#1d2021",
|
|
431
|
+
accent: "#83a598",
|
|
432
|
+
success: "#b8bb26",
|
|
433
|
+
warning: "#fabd2f",
|
|
434
|
+
error: "#fb4934",
|
|
435
|
+
user: "#83a598",
|
|
436
|
+
assistant: "#ebdbb2",
|
|
437
|
+
tool: "#d3869b",
|
|
438
|
+
reasoning: "#7c6f64",
|
|
439
|
+
syntaxBlue: "#83a598",
|
|
440
|
+
syntaxCyan: "#8ec07c",
|
|
441
|
+
syntaxTeal: "#8ec07c",
|
|
442
|
+
syntaxGreen: "#b8bb26",
|
|
443
|
+
syntaxYellow: "#fabd2f",
|
|
444
|
+
syntaxOrange: "#fe8019",
|
|
445
|
+
syntaxRed: "#fb4934",
|
|
446
|
+
syntaxMagenta: "#d3869b"
|
|
447
|
+
}
|
|
448
|
+
};
|
|
449
|
+
const gruvboxLight = {
|
|
450
|
+
id: "gruvbox-light",
|
|
451
|
+
label: "Gruvbox Light",
|
|
452
|
+
mode: "light",
|
|
453
|
+
palette: {
|
|
454
|
+
fg: "#3c3836",
|
|
455
|
+
muted: "#928374",
|
|
456
|
+
dim: "#a89984",
|
|
457
|
+
faint: "#d5c4a1",
|
|
458
|
+
surface: "#ebdbb2",
|
|
459
|
+
accent: "#076678",
|
|
460
|
+
success: "#79740e",
|
|
461
|
+
warning: "#b57614",
|
|
462
|
+
error: "#9d0006",
|
|
463
|
+
user: "#076678",
|
|
464
|
+
assistant: "#3c3836",
|
|
465
|
+
tool: "#8f3f71",
|
|
466
|
+
reasoning: "#a89984",
|
|
467
|
+
syntaxBlue: "#076678",
|
|
468
|
+
syntaxCyan: "#427b58",
|
|
469
|
+
syntaxTeal: "#427b58",
|
|
470
|
+
syntaxGreen: "#79740e",
|
|
471
|
+
syntaxYellow: "#b57614",
|
|
472
|
+
syntaxOrange: "#af3a03",
|
|
473
|
+
syntaxRed: "#9d0006",
|
|
474
|
+
syntaxMagenta: "#8f3f71"
|
|
475
|
+
}
|
|
476
|
+
};
|
|
477
|
+
const solarizedDark = {
|
|
478
|
+
id: "solarized-dark",
|
|
479
|
+
label: "Solarized Dark",
|
|
480
|
+
mode: "dark",
|
|
481
|
+
palette: {
|
|
482
|
+
fg: "#93a1a1",
|
|
483
|
+
muted: "#586e75",
|
|
484
|
+
dim: "#586e75",
|
|
485
|
+
faint: "#073642",
|
|
486
|
+
surface: "#00212b",
|
|
487
|
+
accent: "#268bd2",
|
|
488
|
+
success: "#859900",
|
|
489
|
+
warning: "#b58900",
|
|
490
|
+
error: "#dc322f",
|
|
491
|
+
user: "#268bd2",
|
|
492
|
+
assistant: "#93a1a1",
|
|
493
|
+
tool: "#6c71c4",
|
|
494
|
+
reasoning: "#586e75",
|
|
495
|
+
syntaxBlue: "#268bd2",
|
|
496
|
+
syntaxCyan: "#2aa198",
|
|
497
|
+
syntaxTeal: "#2aa198",
|
|
498
|
+
syntaxGreen: "#859900",
|
|
499
|
+
syntaxYellow: "#b58900",
|
|
500
|
+
syntaxOrange: "#cb4b16",
|
|
501
|
+
syntaxRed: "#dc322f",
|
|
502
|
+
syntaxMagenta: "#6c71c4"
|
|
503
|
+
}
|
|
504
|
+
};
|
|
505
|
+
const solarizedLight = {
|
|
506
|
+
id: "solarized-light",
|
|
507
|
+
label: "Solarized Light",
|
|
508
|
+
mode: "light",
|
|
509
|
+
palette: {
|
|
510
|
+
fg: "#657b83",
|
|
511
|
+
muted: "#839496",
|
|
512
|
+
dim: "#93a1a1",
|
|
513
|
+
faint: "#eee8d5",
|
|
514
|
+
surface: "#eee8d5",
|
|
515
|
+
accent: "#268bd2",
|
|
516
|
+
success: "#859900",
|
|
517
|
+
warning: "#b58900",
|
|
518
|
+
error: "#dc322f",
|
|
519
|
+
user: "#268bd2",
|
|
520
|
+
assistant: "#657b83",
|
|
521
|
+
tool: "#6c71c4",
|
|
522
|
+
reasoning: "#93a1a1",
|
|
523
|
+
syntaxBlue: "#268bd2",
|
|
524
|
+
syntaxCyan: "#2aa198",
|
|
525
|
+
syntaxTeal: "#2aa198",
|
|
526
|
+
syntaxGreen: "#859900",
|
|
527
|
+
syntaxYellow: "#b58900",
|
|
528
|
+
syntaxOrange: "#cb4b16",
|
|
529
|
+
syntaxRed: "#dc322f",
|
|
530
|
+
syntaxMagenta: "#6c71c4"
|
|
531
|
+
}
|
|
532
|
+
};
|
|
533
|
+
const nord = {
|
|
534
|
+
id: "nord",
|
|
535
|
+
label: "Nord",
|
|
536
|
+
mode: "dark",
|
|
537
|
+
palette: {
|
|
538
|
+
fg: "#d8dee9",
|
|
539
|
+
muted: "#616e88",
|
|
540
|
+
dim: "#4c566a",
|
|
541
|
+
faint: "#3b4252",
|
|
542
|
+
surface: "#272c36",
|
|
543
|
+
accent: "#88c0d0",
|
|
544
|
+
success: "#a3be8c",
|
|
545
|
+
warning: "#ebcb8b",
|
|
546
|
+
error: "#bf616a",
|
|
547
|
+
user: "#88c0d0",
|
|
548
|
+
assistant: "#d8dee9",
|
|
549
|
+
tool: "#b48ead",
|
|
550
|
+
reasoning: "#4c566a",
|
|
551
|
+
syntaxBlue: "#81a1c1",
|
|
552
|
+
syntaxCyan: "#88c0d0",
|
|
553
|
+
syntaxTeal: "#8fbcbb",
|
|
554
|
+
syntaxGreen: "#a3be8c",
|
|
555
|
+
syntaxYellow: "#ebcb8b",
|
|
556
|
+
syntaxOrange: "#d08770",
|
|
557
|
+
syntaxRed: "#bf616a",
|
|
558
|
+
syntaxMagenta: "#b48ead"
|
|
559
|
+
}
|
|
560
|
+
};
|
|
561
|
+
const dracula = {
|
|
562
|
+
id: "dracula",
|
|
563
|
+
label: "Dracula",
|
|
564
|
+
mode: "dark",
|
|
565
|
+
palette: {
|
|
566
|
+
fg: "#f8f8f2",
|
|
567
|
+
muted: "#6272a4",
|
|
568
|
+
dim: "#6272a4",
|
|
569
|
+
faint: "#44475a",
|
|
570
|
+
surface: "#21222c",
|
|
571
|
+
accent: "#bd93f9",
|
|
572
|
+
success: "#50fa7b",
|
|
573
|
+
warning: "#ffb86c",
|
|
574
|
+
error: "#ff5555",
|
|
575
|
+
user: "#bd93f9",
|
|
576
|
+
assistant: "#f8f8f2",
|
|
577
|
+
tool: "#ff79c6",
|
|
578
|
+
reasoning: "#6272a4",
|
|
579
|
+
syntaxBlue: "#bd93f9",
|
|
580
|
+
syntaxCyan: "#8be9fd",
|
|
581
|
+
syntaxTeal: "#8be9fd",
|
|
582
|
+
syntaxGreen: "#50fa7b",
|
|
583
|
+
syntaxYellow: "#f1fa8c",
|
|
584
|
+
syntaxOrange: "#ffb86c",
|
|
585
|
+
syntaxRed: "#ff5555",
|
|
586
|
+
syntaxMagenta: "#ff79c6"
|
|
587
|
+
}
|
|
588
|
+
};
|
|
589
|
+
const oneDark = {
|
|
590
|
+
id: "one-dark",
|
|
591
|
+
label: "One Dark",
|
|
592
|
+
mode: "dark",
|
|
593
|
+
palette: {
|
|
594
|
+
fg: "#abb2bf",
|
|
595
|
+
muted: "#5c6370",
|
|
596
|
+
dim: "#5c6370",
|
|
597
|
+
faint: "#3e4451",
|
|
598
|
+
surface: "#21252b",
|
|
599
|
+
accent: "#61afef",
|
|
600
|
+
success: "#98c379",
|
|
601
|
+
warning: "#e5c07b",
|
|
602
|
+
error: "#e06c75",
|
|
603
|
+
user: "#61afef",
|
|
604
|
+
assistant: "#abb2bf",
|
|
605
|
+
tool: "#c678dd",
|
|
606
|
+
reasoning: "#5c6370",
|
|
607
|
+
syntaxBlue: "#61afef",
|
|
608
|
+
syntaxCyan: "#56b6c2",
|
|
609
|
+
syntaxTeal: "#56b6c2",
|
|
610
|
+
syntaxGreen: "#98c379",
|
|
611
|
+
syntaxYellow: "#e5c07b",
|
|
612
|
+
syntaxOrange: "#d19a66",
|
|
613
|
+
syntaxRed: "#e06c75",
|
|
614
|
+
syntaxMagenta: "#c678dd"
|
|
615
|
+
}
|
|
616
|
+
};
|
|
617
|
+
const oneLight = {
|
|
618
|
+
id: "one-light",
|
|
619
|
+
label: "One Light",
|
|
620
|
+
mode: "light",
|
|
621
|
+
palette: {
|
|
622
|
+
fg: "#383a42",
|
|
623
|
+
muted: "#a0a1a7",
|
|
624
|
+
dim: "#a0a1a7",
|
|
625
|
+
faint: "#e5e5e6",
|
|
626
|
+
surface: "#f0f0f1",
|
|
627
|
+
accent: "#4078f2",
|
|
628
|
+
success: "#50a14f",
|
|
629
|
+
warning: "#c18401",
|
|
630
|
+
error: "#e45649",
|
|
631
|
+
user: "#4078f2",
|
|
632
|
+
assistant: "#383a42",
|
|
633
|
+
tool: "#a626a4",
|
|
634
|
+
reasoning: "#a0a1a7",
|
|
635
|
+
syntaxBlue: "#4078f2",
|
|
636
|
+
syntaxCyan: "#0184bc",
|
|
637
|
+
syntaxTeal: "#0184bc",
|
|
638
|
+
syntaxGreen: "#50a14f",
|
|
639
|
+
syntaxYellow: "#c18401",
|
|
640
|
+
syntaxOrange: "#986801",
|
|
641
|
+
syntaxRed: "#e45649",
|
|
642
|
+
syntaxMagenta: "#a626a4"
|
|
643
|
+
}
|
|
644
|
+
};
|
|
645
|
+
const rosePine = {
|
|
646
|
+
id: "rose-pine",
|
|
647
|
+
label: "Rosé Pine",
|
|
648
|
+
mode: "dark",
|
|
649
|
+
palette: {
|
|
650
|
+
fg: "#e0def4",
|
|
651
|
+
muted: "#908caa",
|
|
652
|
+
dim: "#6e6a86",
|
|
653
|
+
faint: "#403d52",
|
|
654
|
+
surface: "#16141f",
|
|
655
|
+
accent: "#c4a7e7",
|
|
656
|
+
success: "#9ccfd8",
|
|
657
|
+
warning: "#f6c177",
|
|
658
|
+
error: "#eb6f92",
|
|
659
|
+
user: "#c4a7e7",
|
|
660
|
+
assistant: "#e0def4",
|
|
661
|
+
tool: "#ebbcba",
|
|
662
|
+
reasoning: "#908caa",
|
|
663
|
+
syntaxBlue: "#9ccfd8",
|
|
664
|
+
syntaxCyan: "#9ccfd8",
|
|
665
|
+
syntaxTeal: "#31748f",
|
|
666
|
+
syntaxGreen: "#31748f",
|
|
667
|
+
syntaxYellow: "#f6c177",
|
|
668
|
+
syntaxOrange: "#ebbcba",
|
|
669
|
+
syntaxRed: "#eb6f92",
|
|
670
|
+
syntaxMagenta: "#c4a7e7"
|
|
671
|
+
}
|
|
672
|
+
};
|
|
673
|
+
const rosePineDawn = {
|
|
674
|
+
id: "rose-pine-dawn",
|
|
675
|
+
label: "Rosé Pine Dawn",
|
|
676
|
+
mode: "light",
|
|
677
|
+
palette: {
|
|
678
|
+
fg: "#575279",
|
|
679
|
+
muted: "#797593",
|
|
680
|
+
dim: "#9893a5",
|
|
681
|
+
faint: "#cecacd",
|
|
682
|
+
surface: "#f2e9e1",
|
|
683
|
+
accent: "#907aa9",
|
|
684
|
+
success: "#56949f",
|
|
685
|
+
warning: "#ea9d34",
|
|
686
|
+
error: "#b4637a",
|
|
687
|
+
user: "#907aa9",
|
|
688
|
+
assistant: "#575279",
|
|
689
|
+
tool: "#d7827e",
|
|
690
|
+
reasoning: "#9893a5",
|
|
691
|
+
syntaxBlue: "#56949f",
|
|
692
|
+
syntaxCyan: "#56949f",
|
|
693
|
+
syntaxTeal: "#286983",
|
|
694
|
+
syntaxGreen: "#286983",
|
|
695
|
+
syntaxYellow: "#ea9d34",
|
|
696
|
+
syntaxOrange: "#d7827e",
|
|
697
|
+
syntaxRed: "#b4637a",
|
|
698
|
+
syntaxMagenta: "#907aa9"
|
|
699
|
+
}
|
|
700
|
+
};
|
|
701
|
+
const everforestDark = {
|
|
702
|
+
id: "everforest-dark",
|
|
703
|
+
label: "Everforest Dark",
|
|
704
|
+
mode: "dark",
|
|
705
|
+
palette: {
|
|
706
|
+
fg: "#d3c6aa",
|
|
707
|
+
muted: "#859289",
|
|
708
|
+
dim: "#7a8478",
|
|
709
|
+
faint: "#414b50",
|
|
710
|
+
surface: "#232a2e",
|
|
711
|
+
accent: "#7fbbb3",
|
|
712
|
+
success: "#a7c080",
|
|
713
|
+
warning: "#dbbc7f",
|
|
714
|
+
error: "#e67e80",
|
|
715
|
+
user: "#7fbbb3",
|
|
716
|
+
assistant: "#d3c6aa",
|
|
717
|
+
tool: "#d699b6",
|
|
718
|
+
reasoning: "#7a8478",
|
|
719
|
+
syntaxBlue: "#7fbbb3",
|
|
720
|
+
syntaxCyan: "#83c092",
|
|
721
|
+
syntaxTeal: "#83c092",
|
|
722
|
+
syntaxGreen: "#a7c080",
|
|
723
|
+
syntaxYellow: "#dbbc7f",
|
|
724
|
+
syntaxOrange: "#e69875",
|
|
725
|
+
syntaxRed: "#e67e80",
|
|
726
|
+
syntaxMagenta: "#d699b6"
|
|
727
|
+
}
|
|
728
|
+
};
|
|
729
|
+
const everforestLight = {
|
|
730
|
+
id: "everforest-light",
|
|
731
|
+
label: "Everforest Light",
|
|
732
|
+
mode: "light",
|
|
733
|
+
palette: {
|
|
734
|
+
fg: "#5c6a72",
|
|
735
|
+
muted: "#939f91",
|
|
736
|
+
dim: "#a6b0a0",
|
|
737
|
+
faint: "#e0dcc7",
|
|
738
|
+
surface: "#f4f0d9",
|
|
739
|
+
accent: "#3a94c5",
|
|
740
|
+
success: "#8da101",
|
|
741
|
+
warning: "#dfa000",
|
|
742
|
+
error: "#f85552",
|
|
743
|
+
user: "#3a94c5",
|
|
744
|
+
assistant: "#5c6a72",
|
|
745
|
+
tool: "#df69ba",
|
|
746
|
+
reasoning: "#a6b0a0",
|
|
747
|
+
syntaxBlue: "#3a94c5",
|
|
748
|
+
syntaxCyan: "#35a77c",
|
|
749
|
+
syntaxTeal: "#35a77c",
|
|
750
|
+
syntaxGreen: "#8da101",
|
|
751
|
+
syntaxYellow: "#dfa000",
|
|
752
|
+
syntaxOrange: "#f57d26",
|
|
753
|
+
syntaxRed: "#f85552",
|
|
754
|
+
syntaxMagenta: "#df69ba"
|
|
755
|
+
}
|
|
756
|
+
};
|
|
757
|
+
const githubDark = {
|
|
758
|
+
id: "github-dark",
|
|
759
|
+
label: "GitHub Dark",
|
|
760
|
+
mode: "dark",
|
|
761
|
+
palette: {
|
|
762
|
+
fg: "#c9d1d9",
|
|
763
|
+
muted: "#8b949e",
|
|
764
|
+
dim: "#6e7681",
|
|
765
|
+
faint: "#30363d",
|
|
766
|
+
surface: "#161b22",
|
|
767
|
+
accent: "#58a6ff",
|
|
768
|
+
success: "#3fb950",
|
|
769
|
+
warning: "#d29922",
|
|
770
|
+
error: "#f85149",
|
|
771
|
+
user: "#58a6ff",
|
|
772
|
+
assistant: "#c9d1d9",
|
|
773
|
+
tool: "#bc8cff",
|
|
774
|
+
reasoning: "#6e7681",
|
|
775
|
+
syntaxBlue: "#58a6ff",
|
|
776
|
+
syntaxCyan: "#39c5cf",
|
|
777
|
+
syntaxTeal: "#39c5cf",
|
|
778
|
+
syntaxGreen: "#3fb950",
|
|
779
|
+
syntaxYellow: "#d29922",
|
|
780
|
+
syntaxOrange: "#db6d28",
|
|
781
|
+
syntaxRed: "#f85149",
|
|
782
|
+
syntaxMagenta: "#bc8cff"
|
|
783
|
+
}
|
|
784
|
+
};
|
|
785
|
+
const githubLight = {
|
|
786
|
+
id: "github-light",
|
|
787
|
+
label: "GitHub Light",
|
|
788
|
+
mode: "light",
|
|
789
|
+
palette: {
|
|
790
|
+
fg: "#24292f",
|
|
791
|
+
muted: "#57606a",
|
|
792
|
+
dim: "#8c959f",
|
|
793
|
+
faint: "#d0d7de",
|
|
794
|
+
surface: "#f6f8fa",
|
|
795
|
+
accent: "#0969da",
|
|
796
|
+
success: "#1a7f37",
|
|
797
|
+
warning: "#9a6700",
|
|
798
|
+
error: "#cf222e",
|
|
799
|
+
user: "#0969da",
|
|
800
|
+
assistant: "#24292f",
|
|
801
|
+
tool: "#8250df",
|
|
802
|
+
reasoning: "#8c959f",
|
|
803
|
+
syntaxBlue: "#0969da",
|
|
804
|
+
syntaxCyan: "#1b7c83",
|
|
805
|
+
syntaxTeal: "#1b7c83",
|
|
806
|
+
syntaxGreen: "#1a7f37",
|
|
807
|
+
syntaxYellow: "#9a6700",
|
|
808
|
+
syntaxOrange: "#bc4c00",
|
|
809
|
+
syntaxRed: "#cf222e",
|
|
810
|
+
syntaxMagenta: "#8250df"
|
|
811
|
+
}
|
|
812
|
+
};
|
|
813
|
+
const kanagawa = {
|
|
814
|
+
id: "kanagawa",
|
|
815
|
+
label: "Kanagawa",
|
|
816
|
+
mode: "dark",
|
|
817
|
+
palette: {
|
|
818
|
+
fg: "#dcd7ba",
|
|
819
|
+
muted: "#727169",
|
|
820
|
+
dim: "#54546d",
|
|
821
|
+
faint: "#363646",
|
|
822
|
+
surface: "#16161d",
|
|
823
|
+
accent: "#7e9cd8",
|
|
824
|
+
success: "#98bb6c",
|
|
825
|
+
warning: "#e6c384",
|
|
826
|
+
error: "#e46876",
|
|
827
|
+
user: "#7e9cd8",
|
|
828
|
+
assistant: "#dcd7ba",
|
|
829
|
+
tool: "#957fb8",
|
|
830
|
+
reasoning: "#727169",
|
|
831
|
+
syntaxBlue: "#7e9cd8",
|
|
832
|
+
syntaxCyan: "#7aa89f",
|
|
833
|
+
syntaxTeal: "#7aa89f",
|
|
834
|
+
syntaxGreen: "#98bb6c",
|
|
835
|
+
syntaxYellow: "#e6c384",
|
|
836
|
+
syntaxOrange: "#ffa066",
|
|
837
|
+
syntaxRed: "#e46876",
|
|
838
|
+
syntaxMagenta: "#957fb8"
|
|
839
|
+
}
|
|
840
|
+
};
|
|
841
|
+
const cursorDark = {
|
|
842
|
+
id: "cursor-dark",
|
|
843
|
+
label: "Cursor Dark",
|
|
844
|
+
mode: "dark",
|
|
845
|
+
palette: {
|
|
846
|
+
background: "#181818",
|
|
847
|
+
fg: "#d4d4d4",
|
|
848
|
+
muted: "#898989",
|
|
849
|
+
dim: "#636363",
|
|
850
|
+
faint: "#272727",
|
|
851
|
+
surface: "#141414",
|
|
852
|
+
accent: "#88c0d0",
|
|
853
|
+
success: "#70b489",
|
|
854
|
+
warning: "#f1b467",
|
|
855
|
+
error: "#fc6b83",
|
|
856
|
+
diffAdded: "#3fa266",
|
|
857
|
+
diffRemoved: "#b80049",
|
|
858
|
+
diffWeight: .2,
|
|
859
|
+
user: "#88c0d0",
|
|
860
|
+
assistant: "#d4d4d4",
|
|
861
|
+
tool: "#aaa0fa",
|
|
862
|
+
reasoning: "#636363",
|
|
863
|
+
syntaxBlue: "#ebc88d",
|
|
864
|
+
syntaxCyan: "#87c3ff",
|
|
865
|
+
syntaxTeal: "#aaa0fa",
|
|
866
|
+
syntaxGreen: "#e394dc",
|
|
867
|
+
syntaxYellow: "#d4d4d4",
|
|
868
|
+
syntaxOrange: "#f8c762",
|
|
869
|
+
syntaxRed: "#cc7c8a",
|
|
870
|
+
syntaxMagenta: "#82d2ce"
|
|
871
|
+
}
|
|
872
|
+
};
|
|
873
|
+
const themes = [
|
|
874
|
+
tokyonight,
|
|
875
|
+
tokyonightDay,
|
|
876
|
+
catppuccinMocha,
|
|
877
|
+
catppuccinLatte,
|
|
878
|
+
gruvboxDark,
|
|
879
|
+
gruvboxLight,
|
|
880
|
+
solarizedDark,
|
|
881
|
+
solarizedLight,
|
|
882
|
+
nord,
|
|
883
|
+
dracula,
|
|
884
|
+
oneDark,
|
|
885
|
+
oneLight,
|
|
886
|
+
rosePine,
|
|
887
|
+
rosePineDawn,
|
|
888
|
+
everforestDark,
|
|
889
|
+
everforestLight,
|
|
890
|
+
githubDark,
|
|
891
|
+
githubLight,
|
|
892
|
+
kanagawa,
|
|
893
|
+
cursorDark
|
|
894
|
+
];
|
|
895
|
+
const DEFAULT_THEME_ID = {
|
|
896
|
+
dark: tokyonight.id,
|
|
897
|
+
light: tokyonightDay.id
|
|
898
|
+
};
|
|
899
|
+
/** All-undefined palette for NO_COLOR: every fg/bg falls back to the
|
|
900
|
+
* terminal's own defaults, so nothing emits color. Not listed in `themes` —
|
|
901
|
+
* it's forced, never picked. */
|
|
902
|
+
const monoTheme = {
|
|
903
|
+
id: "mono",
|
|
904
|
+
label: "No color",
|
|
905
|
+
mode: "dark",
|
|
906
|
+
palette: {
|
|
907
|
+
fg: void 0,
|
|
908
|
+
muted: void 0,
|
|
909
|
+
dim: void 0,
|
|
910
|
+
faint: void 0,
|
|
911
|
+
surface: void 0,
|
|
912
|
+
accent: void 0,
|
|
913
|
+
success: void 0,
|
|
914
|
+
warning: void 0,
|
|
915
|
+
error: void 0,
|
|
916
|
+
user: void 0,
|
|
917
|
+
assistant: void 0,
|
|
918
|
+
tool: void 0,
|
|
919
|
+
reasoning: void 0,
|
|
920
|
+
syntaxBlue: void 0,
|
|
921
|
+
syntaxCyan: void 0,
|
|
922
|
+
syntaxTeal: void 0,
|
|
923
|
+
syntaxGreen: void 0,
|
|
924
|
+
syntaxYellow: void 0,
|
|
925
|
+
syntaxOrange: void 0,
|
|
926
|
+
syntaxRed: void 0,
|
|
927
|
+
syntaxMagenta: void 0
|
|
928
|
+
}
|
|
929
|
+
};
|
|
930
|
+
function themesForMode(mode) {
|
|
931
|
+
return themes.filter((t) => t.mode === mode);
|
|
932
|
+
}
|
|
933
|
+
function findTheme(id) {
|
|
934
|
+
if (id === monoTheme.id) return monoTheme;
|
|
935
|
+
return themes.find((t) => t.id === id);
|
|
936
|
+
}
|
|
937
|
+
/**
|
|
938
|
+
* The saved theme to use for a mode: the persisted pick if it exists *and*
|
|
939
|
+
* still matches the mode (a stale/renamed id falls back), else the default.
|
|
940
|
+
*/
|
|
941
|
+
function themeForMode(mode, savedId) {
|
|
942
|
+
if (savedId) {
|
|
943
|
+
const saved = findTheme(savedId);
|
|
944
|
+
if (saved && saved.mode === mode) return saved;
|
|
945
|
+
}
|
|
946
|
+
return findTheme(DEFAULT_THEME_ID[mode]) ?? tokyonight;
|
|
947
|
+
}
|
|
948
|
+
/** https://no-color.org — any non-empty value disables color output. */
|
|
949
|
+
function noColorRequested(env = process.env) {
|
|
950
|
+
const v = env["NO_COLOR"];
|
|
951
|
+
return v !== void 0 && v !== "";
|
|
952
|
+
}
|
|
953
|
+
/**
|
|
954
|
+
* Fallback light/dark sniff for terminals that never answer the OSC 10/11
|
|
955
|
+
* query: `COLORFGBG` is "<fg>;<bg>" (sometimes "<fg>;default;<bg>") with
|
|
956
|
+
* ANSI palette indexes. Background 7/15 (white/bright white) means a light
|
|
957
|
+
* terminal; anything else we call dark. Returns null when unset/unparsable.
|
|
958
|
+
*/
|
|
959
|
+
function themeModeFromColorFgBg(env = process.env) {
|
|
960
|
+
const raw = env["COLORFGBG"];
|
|
961
|
+
if (!raw) return null;
|
|
962
|
+
const parts = raw.split(";");
|
|
963
|
+
const bg = parts[parts.length - 1];
|
|
964
|
+
if (bg === void 0 || !/^\d+$/.test(bg)) return null;
|
|
965
|
+
const idx = Number(bg);
|
|
966
|
+
return idx === 7 || idx === 15 ? "light" : "dark";
|
|
967
|
+
}
|
|
968
|
+
/** Single source of truth for colors. Mutated in place by `applyTheme` so
|
|
969
|
+
* existing `theme.fg`-style reads across the TUI stay valid. */
|
|
970
|
+
const theme = { ...tokyonight.palette };
|
|
971
|
+
let version = 0;
|
|
972
|
+
function themeVersion() {
|
|
973
|
+
return version;
|
|
974
|
+
}
|
|
975
|
+
let mode = tokyonight.mode;
|
|
976
|
+
function themeMode() {
|
|
977
|
+
return mode;
|
|
978
|
+
}
|
|
979
|
+
function applyTheme(def) {
|
|
980
|
+
Object.assign(theme, def.palette);
|
|
981
|
+
theme.background = def.palette.background;
|
|
982
|
+
theme.diffAdded = def.palette.diffAdded;
|
|
983
|
+
theme.diffRemoved = def.palette.diffRemoved;
|
|
984
|
+
theme.diffWeight = def.palette.diffWeight;
|
|
985
|
+
mode = def.mode;
|
|
986
|
+
version++;
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
//#endregion
|
|
990
|
+
export { getShareMachineDefault as A, saveSession as B, DEFAULT_WEB_URL as C, getPromptHistoryPath as D, getLastSeenVersion as E, resolveConfig as F, setLastSeenVersion as H, resolveManagementAuth as I, resolveSession as L, getStoredApiKeyWorkspaceName as M, getUpdateCheckDisabled as N, getReviewStateDir as O, resolveAppUrl as P, resolveWebUrl as R, DEFAULT_APP_URL as S, getConfigPath as T, saveTheme as V, setActiveWorkspace as _, noColorRequested as a, API_KEY_PREFIX as b, themeMode as c, themes as d, themesForMode as f, listWorkspaces as g, getSessionIdentity as h, monoTheme as i, getStoredApiKeyId as j, getSavedTheme as k, themeModeFromColorFgBg as l, getActiveWorkspaceId as m, applyTheme as n, theme as o, ensureActiveOrganization as p, findTheme as r, themeForMode as s, DEFAULT_THEME_ID as t, themeVersion as u, API_KEYS_URL as v, deleteConfig as w, DEFAULT_API_URL as x, API_KEY_FAMILY_PREFIX as y, saveConfig as z };
|