@tiagojct/subsub 0.6.1 → 0.7.0
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/LICENSE +21 -0
- package/README.md +200 -62
- package/THIRD_PARTY_NOTICES +55 -0
- package/dist/bench.js +60 -5
- package/dist/config.js +28 -1
- package/dist/doctor.js +23 -2
- package/dist/init.js +17 -3
- package/dist/notes.js +42 -0
- package/dist/profiles.js +15 -0
- package/dist/prompt.js +3 -0
- package/dist/roles.js +7 -1
- package/dist/subsub.js +94 -9
- package/dist/web.js +17 -3
- package/package.json +7 -3
- package/prompts/compare.md +23 -0
- package/prompts/digest.md +23 -0
- package/prompts/lit.md +87 -0
- package/prompts/request-copy.md +35 -0
- package/prompts/review.md +31 -0
- package/prompts/verify.md +18 -0
- package/roles/researcher.md +18 -5
- package/src/bench.ts +63 -4
- package/src/config.ts +39 -1
- package/src/doctor.ts +32 -2
- package/src/init.ts +33 -4
- package/src/notes.ts +46 -0
- package/src/profiles.ts +17 -0
- package/src/prompt.ts +6 -0
- package/src/roles.ts +8 -1
- package/src/subsub.ts +100 -9
- package/src/web.ts +15 -3
- package/templates/Zotero agent.md +2 -0
- package/themes/subsub-glauca-dark.json +34 -34
- package/themes/subsub-glauca-light.json +32 -32
- package/themes/subsub-try-works-dark.json +34 -34
- package/themes/subsub-try-works-light.json +34 -34
- package/web/app.css +801 -164
- package/web/app.js +78 -8
- package/web/glauca.css +51 -70
- package/web/i18n.js +36 -0
- package/web/icon.svg +12 -1
- package/web/index.html +9 -2
package/src/subsub.ts
CHANGED
|
@@ -8,24 +8,41 @@
|
|
|
8
8
|
* - Profiles (reader, scholar, author, editor) set what Sub-Sub writes and which
|
|
9
9
|
* tools it offers; /profile changes it.
|
|
10
10
|
* - Commands: /librarian, /researcher, /profile, /subsub, /history, /undo.
|
|
11
|
+
* - Add-on: with "addons": ["starbuck"], Starbuck runs as a third server
|
|
12
|
+
* ("verify") for reference checks; its tools belong to researcher mode.
|
|
11
13
|
*
|
|
12
14
|
* The Python servers start in session_start (not in the factory) and stop in
|
|
13
15
|
* session_shutdown. Tools are registered once and use the current bridge.
|
|
14
16
|
*/
|
|
15
17
|
|
|
16
18
|
import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
17
|
-
import { readFileSync } from "node:fs";
|
|
19
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
18
20
|
import { dirname, join } from "node:path";
|
|
19
21
|
import { fileURLToPath } from "node:url";
|
|
20
22
|
import { Bridge, type ServerSpec } from "./bridge.ts";
|
|
21
|
-
import {
|
|
22
|
-
|
|
23
|
+
import {
|
|
24
|
+
expand,
|
|
25
|
+
findUv,
|
|
26
|
+
isProfile,
|
|
27
|
+
loadConfig,
|
|
28
|
+
type Mode,
|
|
29
|
+
parseEnvFile,
|
|
30
|
+
type Profile,
|
|
31
|
+
saveConfig,
|
|
32
|
+
serverCommand,
|
|
33
|
+
starbuckCommand,
|
|
34
|
+
starbuckEnabled,
|
|
35
|
+
type SubsubConfig,
|
|
36
|
+
who,
|
|
37
|
+
} from "./config.ts";
|
|
38
|
+
import { profileList, profileSpec, promptBlocked } from "./profiles.ts";
|
|
23
39
|
import { coerceArgs, loosenArrays } from "./args.ts";
|
|
40
|
+
import { applyEdits, checkLiteratureNote } from "./notes.ts";
|
|
24
41
|
import { buildPolicy, judgePath, normalizeToolPath, realish, within } from "./paths.ts";
|
|
25
42
|
import { describeArgs, formatPreview } from "./preview.ts";
|
|
26
43
|
import { headerLines, type LibraryState, paintPreview, QUOTES, type Scheme, schemeFromAnsi, themeName } from "./look.ts";
|
|
27
44
|
import { systemAddition } from "./prompt.ts";
|
|
28
|
-
import { gateKind, toolsFor, unavailableReason } from "./roles.ts";
|
|
45
|
+
import { gateKind, SERVER_PREFIXES, toolsFor, unavailableReason } from "./roles.ts";
|
|
29
46
|
|
|
30
47
|
export interface SubsubDeps {
|
|
31
48
|
config?: SubsubConfig;
|
|
@@ -48,12 +65,30 @@ function ownVersion(): string {
|
|
|
48
65
|
|
|
49
66
|
export { findUv };
|
|
50
67
|
|
|
51
|
-
export function serverSpecs(cfg: SubsubConfig): ServerSpec[] {
|
|
68
|
+
export function serverSpecs(cfg: SubsubConfig, processEnv: NodeJS.ProcessEnv = process.env): ServerSpec[] {
|
|
52
69
|
const env: Record<string, string> = cfg.envFile ? { ZOTERO_MCP_ENV: cfg.envFile } : {};
|
|
53
|
-
|
|
54
|
-
{ name: "zotero", ...serverCommand(cfg, "zotero-local-mcp"), env },
|
|
55
|
-
{ name: "scholar", ...serverCommand(cfg, "zotero-scholar-mcp"), env },
|
|
70
|
+
const specs: ServerSpec[] = [
|
|
71
|
+
{ name: "zotero", ...serverCommand(cfg, "zotero-local-mcp", [], processEnv), env },
|
|
72
|
+
{ name: "scholar", ...serverCommand(cfg, "zotero-scholar-mcp", [], processEnv), env },
|
|
56
73
|
];
|
|
74
|
+
if (starbuckEnabled(cfg)) specs.push({ name: "verify", ...starbuckCommand(cfg, processEnv), env: starbuckEnv(cfg, processEnv) });
|
|
75
|
+
return specs;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Starbuck reads its contact address and API keys from the environment. Sub-Sub keeps
|
|
80
|
+
* them in the zotero-local-mcp env file, so they are passed on (the environment wins).
|
|
81
|
+
*/
|
|
82
|
+
export function starbuckEnv(cfg: Pick<SubsubConfig, "envFile">, processEnv: NodeJS.ProcessEnv = process.env): Record<string, string> {
|
|
83
|
+
const file = cfg.envFile ? parseEnvFile(cfg.envFile) : {};
|
|
84
|
+
const out: Record<string, string> = {};
|
|
85
|
+
const email = processEnv.STARBUCK_EMAIL || file.STARBUCK_EMAIL || processEnv.ZOTERO_CONTACT_EMAIL || file.ZOTERO_CONTACT_EMAIL;
|
|
86
|
+
if (email) out.STARBUCK_EMAIL = email;
|
|
87
|
+
for (const key of ["NCBI_API_KEY", "OPENALEX_API_KEY"]) {
|
|
88
|
+
const v = processEnv[key] || file[key];
|
|
89
|
+
if (v) out[key] = v;
|
|
90
|
+
}
|
|
91
|
+
return out;
|
|
57
92
|
}
|
|
58
93
|
|
|
59
94
|
export async function createSubsub(pi: ExtensionAPI, deps: SubsubDeps = {}): Promise<void> {
|
|
@@ -125,6 +160,7 @@ export async function createSubsub(pi: ExtensionAPI, deps: SubsubDeps = {}): Pro
|
|
|
125
160
|
language: cfg.language,
|
|
126
161
|
userName: cfg.userName ?? null,
|
|
127
162
|
vault: cfg.vault ?? null,
|
|
163
|
+
starbuck: starbuckEnabled(cfg),
|
|
128
164
|
};
|
|
129
165
|
try {
|
|
130
166
|
ctx.ui.setStatus("subsub.web", JSON.stringify(state));
|
|
@@ -262,6 +298,15 @@ export async function createSubsub(pi: ExtensionAPI, deps: SubsubDeps = {}): Pro
|
|
|
262
298
|
|
|
263
299
|
pi.on("model_select", async (_event, ctx) => status(ctx));
|
|
264
300
|
|
|
301
|
+
// Prompt commands that the profile does not run (/lit for Reader, /review for Reader and Scholar).
|
|
302
|
+
// The input event comes before pi expands a prompt template.
|
|
303
|
+
pi.on("input", async (event, ctx) => {
|
|
304
|
+
const why = promptBlocked(event.text, profile);
|
|
305
|
+
if (!why) return { action: "continue" };
|
|
306
|
+
ctx.ui.notify(`Sub-Sub: ${why}`, "warning");
|
|
307
|
+
return { action: "handled" };
|
|
308
|
+
});
|
|
309
|
+
|
|
265
310
|
pi.on("before_agent_start", async (event, ctx) => ({
|
|
266
311
|
systemPrompt: `${event.systemPrompt}\n\n${systemAddition(mode, { ...cfg, profile }, ctx.cwd)}`,
|
|
267
312
|
}));
|
|
@@ -276,18 +321,21 @@ export async function createSubsub(pi: ExtensionAPI, deps: SubsubDeps = {}): Pro
|
|
|
276
321
|
// Previews and the real call must see the same, repaired arguments.
|
|
277
322
|
const schema = schemas.get(name);
|
|
278
323
|
if (schema) coerceArgs(schema, input);
|
|
279
|
-
if (
|
|
324
|
+
if (SERVER_PREFIXES.some((p) => name.startsWith(p))) {
|
|
280
325
|
const why = unavailableReason(name, mode, registered(), profile);
|
|
281
326
|
if (why) {
|
|
282
327
|
if (benchOut) record({ kind: "wrong_mode", tool: name, input });
|
|
283
328
|
return { block: true, reason: why };
|
|
284
329
|
}
|
|
285
330
|
}
|
|
331
|
+
if (name.startsWith("verify_")) return verifyGate(name, input, ctx);
|
|
286
332
|
const kind = benchOut && name === "scholar_queue_imports" ? "confirm" : gateKind(name, input);
|
|
287
333
|
if (!kind) return undefined;
|
|
288
334
|
if (benchOut) return benchGate(name, input, kind, ctx.cwd, ctx.signal);
|
|
289
335
|
if (kind === "path") {
|
|
290
336
|
const target = normalizeToolPath(String(input.path ?? ""), ctx.cwd);
|
|
337
|
+
const noteProblem = literatureNoteProblem(name, target, input);
|
|
338
|
+
if (noteProblem) return { block: true, reason: noteProblem };
|
|
291
339
|
const verdict = judgePath(target, buildPolicy({ vault: cfg.vault, cwd: ctx.cwd, serverDir: cfg.serverDir, packageDir: PACKAGE_DIR }));
|
|
292
340
|
if (verdict.ok) return undefined;
|
|
293
341
|
if (!ctx.hasUI) return { block: true, reason: `Writing ${target} needs ${user}'s approval: ${verdict.why}.` };
|
|
@@ -318,9 +366,52 @@ export async function createSubsub(pi: ExtensionAPI, deps: SubsubDeps = {}): Pro
|
|
|
318
366
|
return ok ? undefined : { block: true, reason: `${user} did not approve this change. Ask what to change; do not retry the same call.` };
|
|
319
367
|
});
|
|
320
368
|
|
|
369
|
+
/** A literature note (front matter with a citekey) must state its evidence; see notes.ts. */
|
|
370
|
+
function literatureNoteProblem(name: string, target: string, input: Record<string, unknown>): string | undefined {
|
|
371
|
+
if (!target.toLowerCase().endsWith(".md")) return undefined;
|
|
372
|
+
if (name === "write") return checkLiteratureNote(String(input.content ?? ""));
|
|
373
|
+
if (name === "edit" && Array.isArray(input.edits) && existsSync(target)) {
|
|
374
|
+
const current = readFileSync(target, "utf8");
|
|
375
|
+
return checkLiteratureNote(applyEdits(current, input.edits as Array<{ oldText?: unknown; newText?: unknown }>));
|
|
376
|
+
}
|
|
377
|
+
return undefined;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Starbuck writes its reports into a folder: report_dir, or _starbuck next to the
|
|
382
|
+
* manuscript. Inside the vault or the working folder that needs no approval; elsewhere
|
|
383
|
+
* Sub-Sub asks, as for any file write. record_claims gets the current model's name.
|
|
384
|
+
*/
|
|
385
|
+
async function verifyGate(name: string, input: Record<string, unknown>, ctx: ExtensionContext) {
|
|
386
|
+
if (name === "verify_record_claims") {
|
|
387
|
+
input.judged_by = ctx.model ? [ctx.model.provider, ctx.model.id].filter(Boolean).join("/") : "the agent's model";
|
|
388
|
+
}
|
|
389
|
+
if (name === "verify_check_references") return undefined;
|
|
390
|
+
const dir = input.report_dir
|
|
391
|
+
? normalizeToolPath(String(input.report_dir), ctx.cwd)
|
|
392
|
+
: input.path
|
|
393
|
+
? join(dirname(normalizeToolPath(String(input.path), ctx.cwd)), "_starbuck")
|
|
394
|
+
: undefined;
|
|
395
|
+
if (!dir) return undefined;
|
|
396
|
+
const verdict = judgePath(dir, buildPolicy({ vault: cfg.vault, cwd: ctx.cwd, serverDir: cfg.serverDir, packageDir: PACKAGE_DIR }));
|
|
397
|
+
if (verdict.ok) return undefined;
|
|
398
|
+
if (benchOut) {
|
|
399
|
+
record({ kind: "path_blocked", tool: name, path: dir });
|
|
400
|
+
return { block: true, reason: `Model test: Starbuck reports only inside the vault or ${benchOut}.` };
|
|
401
|
+
}
|
|
402
|
+
if (!ctx.hasUI) return { block: true, reason: `Writing a Starbuck report to ${dir} needs ${user}'s approval: ${verdict.why}.` };
|
|
403
|
+
const ok = await ctx.ui.confirm(`Sub-Sub: write the Starbuck report to ${dir}?`, `Asking because ${verdict.why}.`);
|
|
404
|
+
return ok ? undefined : { block: true, reason: `${user} did not allow writing the report there. Ask where to put it (report_dir).` };
|
|
405
|
+
}
|
|
406
|
+
|
|
321
407
|
async function benchGate(name: string, input: Record<string, unknown>, kind: string, cwd: string, signal?: AbortSignal) {
|
|
322
408
|
if (kind === "path") {
|
|
323
409
|
const target = normalizeToolPath(String(input.path ?? ""), cwd);
|
|
410
|
+
const noteProblem = literatureNoteProblem(name, target, input);
|
|
411
|
+
if (noteProblem) {
|
|
412
|
+
record({ kind: "note_blocked", tool: name, path: target, reason: noteProblem });
|
|
413
|
+
return { block: true, reason: noteProblem };
|
|
414
|
+
}
|
|
324
415
|
if (within(target, realish(benchOut!))) return undefined;
|
|
325
416
|
record({ kind: "path_blocked", tool: name, path: target });
|
|
326
417
|
return { block: true, reason: `Model test: write only inside ${benchOut}.` };
|
package/src/web.ts
CHANGED
|
@@ -22,9 +22,9 @@ import { homedir } from "node:os";
|
|
|
22
22
|
import { extname, join, normalize, resolve, sep } from "node:path";
|
|
23
23
|
import { StringDecoder } from "node:string_decoder";
|
|
24
24
|
import { agentDirFor, chooseCwd, PACKAGE_DIR, packageVersion } from "./cli.ts";
|
|
25
|
-
import { expand, loadConfig, saveConfig, type SubsubConfig } from "./config.ts";
|
|
25
|
+
import { expand, loadConfig, saveConfig, type SubsubConfig, withStarbuck } from "./config.ts";
|
|
26
26
|
import { TESTED_MODELS } from "./init.ts";
|
|
27
|
-
import { within } from "./paths.ts";
|
|
27
|
+
import { realish, within } from "./paths.ts";
|
|
28
28
|
|
|
29
29
|
// ---------------------------------------------------------------- options
|
|
30
30
|
|
|
@@ -577,6 +577,15 @@ export async function startWeb(opts: WebOptions, env: NodeJS.ProcessEnv = proces
|
|
|
577
577
|
await restartAgent();
|
|
578
578
|
return send(res, 200, { ok: true });
|
|
579
579
|
}
|
|
580
|
+
case "POST /api/addons": {
|
|
581
|
+
// Turn an add-on on or off, then restart pi so the extension starts or stops its server.
|
|
582
|
+
if (busy) return send(res, 409, { error: "busy" });
|
|
583
|
+
const body = await readJson(req);
|
|
584
|
+
if (typeof body.starbuck !== "boolean") return send(res, 400, { error: "starbuck must be true or false" });
|
|
585
|
+
saveConfig({ addons: withStarbuck(loadConfig(env).addons, body.starbuck) }, env);
|
|
586
|
+
await restartAgent();
|
|
587
|
+
return send(res, 200, { ok: true });
|
|
588
|
+
}
|
|
580
589
|
case "POST /api/restart":
|
|
581
590
|
if (agent.proc) return send(res, 200, { ok: true });
|
|
582
591
|
agent.start();
|
|
@@ -595,7 +604,10 @@ export async function startWeb(opts: WebOptions, env: NodeJS.ProcessEnv = proces
|
|
|
595
604
|
const body = await readJson(req);
|
|
596
605
|
const target = resolve(cwd, expand(String(body.path ?? "")));
|
|
597
606
|
const vault = cfg.vault;
|
|
598
|
-
|
|
607
|
+
// Judge the real file, so a link inside the notes folder cannot open a document outside it.
|
|
608
|
+
const real = realish(target);
|
|
609
|
+
const inside = within(real, realish(cwd)) || Boolean(vault && within(real, realish(vault)));
|
|
610
|
+
if (!inside || !existsSync(target)) return send(res, 404, { error: "not found in the notes folder" });
|
|
599
611
|
// Documents only: a file that the model wrote must never be run.
|
|
600
612
|
if (!OPENABLE.has(extname(target).toLowerCase())) return send(res, 403, { error: "Sub-Sub opens only notes and documents (.md, .txt, .pdf, .bib, .csv, .qmd)." });
|
|
601
613
|
if (vault && within(target, vault) && existsSync(join(vault, ".obsidian"))) openExternal(`obsidian://open?path=${encodeURIComponent(target)}`);
|
|
@@ -40,6 +40,7 @@ Shared rules for the Sub-Sub librarian and researcher. Sub-Sub reads this file a
|
|
|
40
40
|
- Folder: Literature/. File name: the citekey (smith2026.md).
|
|
41
41
|
- Create a note only when the user asks. Ask before creating more than 10 notes.
|
|
42
42
|
- Write from the full text (get_fulltext) when it exists. Otherwise use the abstract and the Zotero notes, and write "(from abstract)" after the summary.
|
|
43
|
+
- Front matter field evidence: full text, abstract or metadata (what you read). Page numbers only with evidence: full text. Sub-Sub refuses a literature note without this field.
|
|
43
44
|
- Do not copy the abstract in full. Give page numbers for quotes when the text shows them.
|
|
44
45
|
- If a note for the citekey exists, do not overwrite it. Add a dated section or ask.
|
|
45
46
|
- After the note is written, offer to link it in Zotero with attach_note.
|
|
@@ -58,6 +59,7 @@ item-type: journalArticle
|
|
|
58
59
|
venue: Journal name
|
|
59
60
|
doi: 10.xxxx/xxxxx
|
|
60
61
|
zotero: zotero://select/library/items/ITEMKEY
|
|
62
|
+
evidence: full text
|
|
61
63
|
status: to-read
|
|
62
64
|
tags:
|
|
63
65
|
- topic/example
|
|
@@ -2,28 +2,28 @@
|
|
|
2
2
|
"$schema": "https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
|
|
3
3
|
"name": "subsub-glauca-dark",
|
|
4
4
|
"vars": {
|
|
5
|
-
"bg": "#
|
|
6
|
-
"surface": "#
|
|
7
|
-
"raised": "#
|
|
8
|
-
"text": "#
|
|
9
|
-
"muted": "#
|
|
10
|
-
"line": "#
|
|
11
|
-
"mark": "#
|
|
12
|
-
"markBright": "#
|
|
13
|
-
"markDeep": "#
|
|
14
|
-
"toneDeep": "#
|
|
15
|
-
"tone": "#
|
|
16
|
-
"toneBright": "#
|
|
17
|
-
"tonePale": "#
|
|
18
|
-
"green": "#
|
|
19
|
-
"red": "#
|
|
20
|
-
"yellow": "#
|
|
21
|
-
"violet": "#
|
|
22
|
-
"link": "#
|
|
23
|
-
"dim": "#
|
|
24
|
-
"select": "#
|
|
25
|
-
"okBg": "#
|
|
26
|
-
"errBg": "#
|
|
5
|
+
"bg": "#121517",
|
|
6
|
+
"surface": "#181d20",
|
|
7
|
+
"raised": "#20272b",
|
|
8
|
+
"text": "#e5ebec",
|
|
9
|
+
"muted": "#8a9699",
|
|
10
|
+
"line": "#283236",
|
|
11
|
+
"mark": "#5d99be",
|
|
12
|
+
"markBright": "#78b4da",
|
|
13
|
+
"markDeep": "#41789c",
|
|
14
|
+
"toneDeep": "#0e181c",
|
|
15
|
+
"tone": "#263e48",
|
|
16
|
+
"toneBright": "#486e7e",
|
|
17
|
+
"tonePale": "#8cb6cb",
|
|
18
|
+
"green": "#68aa80",
|
|
19
|
+
"red": "#cf5c5c",
|
|
20
|
+
"yellow": "#c49a46",
|
|
21
|
+
"violet": "#9d82b3",
|
|
22
|
+
"link": "#78b4da",
|
|
23
|
+
"dim": "#5d6a6d",
|
|
24
|
+
"select": "#263e48",
|
|
25
|
+
"okBg": "#1b2920",
|
|
26
|
+
"errBg": "#331c19"
|
|
27
27
|
},
|
|
28
28
|
"colors": {
|
|
29
29
|
"accent": "mark",
|
|
@@ -65,15 +65,15 @@
|
|
|
65
65
|
"toolDiffAdded": "green",
|
|
66
66
|
"toolDiffRemoved": "red",
|
|
67
67
|
"toolDiffContext": "muted",
|
|
68
|
-
"syntaxComment": "#
|
|
69
|
-
"syntaxKeyword": "#
|
|
70
|
-
"syntaxFunction": "#
|
|
71
|
-
"syntaxVariable": "#
|
|
72
|
-
"syntaxString": "#
|
|
73
|
-
"syntaxNumber": "#
|
|
74
|
-
"syntaxType": "#
|
|
75
|
-
"syntaxOperator": "#
|
|
76
|
-
"syntaxPunctuation": "#
|
|
68
|
+
"syntaxComment": "#5d6a6d",
|
|
69
|
+
"syntaxKeyword": "#78b4da",
|
|
70
|
+
"syntaxFunction": "#5d99be",
|
|
71
|
+
"syntaxVariable": "#e5ebec",
|
|
72
|
+
"syntaxString": "#68aa80",
|
|
73
|
+
"syntaxNumber": "#9d82b3",
|
|
74
|
+
"syntaxType": "#8cb6cb",
|
|
75
|
+
"syntaxOperator": "#8a9699",
|
|
76
|
+
"syntaxPunctuation": "#8a9699",
|
|
77
77
|
"thinkingOff": "line",
|
|
78
78
|
"thinkingMinimal": "dim",
|
|
79
79
|
"thinkingLow": "toneBright",
|
|
@@ -84,8 +84,8 @@
|
|
|
84
84
|
"bashMode": "mark"
|
|
85
85
|
},
|
|
86
86
|
"export": {
|
|
87
|
-
"pageBg": "#
|
|
88
|
-
"cardBg": "#
|
|
89
|
-
"infoBg": "#
|
|
87
|
+
"pageBg": "#121517",
|
|
88
|
+
"cardBg": "#181d20",
|
|
89
|
+
"infoBg": "#20272b"
|
|
90
90
|
}
|
|
91
91
|
}
|
|
@@ -2,28 +2,28 @@
|
|
|
2
2
|
"$schema": "https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
|
|
3
3
|
"name": "subsub-glauca-light",
|
|
4
4
|
"vars": {
|
|
5
|
-
"bg": "#
|
|
6
|
-
"surface": "#
|
|
5
|
+
"bg": "#f8f6f0",
|
|
6
|
+
"surface": "#f2ede2",
|
|
7
7
|
"raised": "#ffffff",
|
|
8
|
-
"text": "#
|
|
9
|
-
"muted": "#
|
|
10
|
-
"line": "#
|
|
11
|
-
"mark": "#
|
|
12
|
-
"markBright": "#
|
|
13
|
-
"markDeep": "#
|
|
14
|
-
"toneDeep": "#
|
|
15
|
-
"tone": "#
|
|
16
|
-
"toneBright": "#
|
|
17
|
-
"tonePale": "#
|
|
18
|
-
"green": "#
|
|
19
|
-
"red": "#
|
|
20
|
-
"yellow": "#
|
|
21
|
-
"violet": "#
|
|
22
|
-
"link": "#
|
|
23
|
-
"dim": "#
|
|
24
|
-
"select": "#
|
|
25
|
-
"okBg": "#
|
|
26
|
-
"errBg": "#
|
|
8
|
+
"text": "#211e1b",
|
|
9
|
+
"muted": "#5c554a",
|
|
10
|
+
"line": "#ded6c4",
|
|
11
|
+
"mark": "#234b6e",
|
|
12
|
+
"markBright": "#2f648e",
|
|
13
|
+
"markDeep": "#15344e",
|
|
14
|
+
"toneDeep": "#16222b",
|
|
15
|
+
"tone": "#2e4854",
|
|
16
|
+
"toneBright": "#436574",
|
|
17
|
+
"tonePale": "#b5cad6",
|
|
18
|
+
"green": "#205438",
|
|
19
|
+
"red": "#9c281b",
|
|
20
|
+
"yellow": "#8f6b28",
|
|
21
|
+
"violet": "#604e76",
|
|
22
|
+
"link": "#234b6e",
|
|
23
|
+
"dim": "#827768",
|
|
24
|
+
"select": "#ded6c4",
|
|
25
|
+
"okBg": "#dfebe3",
|
|
26
|
+
"errBg": "#f5e4e2"
|
|
27
27
|
},
|
|
28
28
|
"colors": {
|
|
29
29
|
"accent": "mark",
|
|
@@ -65,15 +65,15 @@
|
|
|
65
65
|
"toolDiffAdded": "green",
|
|
66
66
|
"toolDiffRemoved": "red",
|
|
67
67
|
"toolDiffContext": "muted",
|
|
68
|
-
"syntaxComment": "#
|
|
69
|
-
"syntaxKeyword": "#
|
|
70
|
-
"syntaxFunction": "#
|
|
71
|
-
"syntaxVariable": "#
|
|
72
|
-
"syntaxString": "#
|
|
73
|
-
"syntaxNumber": "#
|
|
74
|
-
"syntaxType": "#
|
|
75
|
-
"syntaxOperator": "#
|
|
76
|
-
"syntaxPunctuation": "#
|
|
68
|
+
"syntaxComment": "#827768",
|
|
69
|
+
"syntaxKeyword": "#234b6e",
|
|
70
|
+
"syntaxFunction": "#2e4854",
|
|
71
|
+
"syntaxVariable": "#211e1b",
|
|
72
|
+
"syntaxString": "#205438",
|
|
73
|
+
"syntaxNumber": "#604e76",
|
|
74
|
+
"syntaxType": "#436574",
|
|
75
|
+
"syntaxOperator": "#5c554a",
|
|
76
|
+
"syntaxPunctuation": "#5c554a",
|
|
77
77
|
"thinkingOff": "line",
|
|
78
78
|
"thinkingMinimal": "dim",
|
|
79
79
|
"thinkingLow": "toneBright",
|
|
@@ -84,8 +84,8 @@
|
|
|
84
84
|
"bashMode": "mark"
|
|
85
85
|
},
|
|
86
86
|
"export": {
|
|
87
|
-
"pageBg": "#
|
|
88
|
-
"cardBg": "#
|
|
87
|
+
"pageBg": "#f8f6f0",
|
|
88
|
+
"cardBg": "#f2ede2",
|
|
89
89
|
"infoBg": "#ffffff"
|
|
90
90
|
}
|
|
91
91
|
}
|
|
@@ -2,28 +2,28 @@
|
|
|
2
2
|
"$schema": "https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
|
|
3
3
|
"name": "subsub-try-works-dark",
|
|
4
4
|
"vars": {
|
|
5
|
-
"bg": "#
|
|
6
|
-
"surface": "#
|
|
7
|
-
"raised": "#
|
|
8
|
-
"text": "#
|
|
9
|
-
"muted": "#
|
|
10
|
-
"line": "#
|
|
11
|
-
"mark": "#
|
|
12
|
-
"markBright": "#
|
|
13
|
-
"markDeep": "#
|
|
14
|
-
"toneDeep": "#
|
|
15
|
-
"tone": "#
|
|
16
|
-
"toneBright": "#
|
|
17
|
-
"tonePale": "#
|
|
18
|
-
"green": "#
|
|
19
|
-
"red": "#
|
|
20
|
-
"yellow": "#
|
|
21
|
-
"violet": "#
|
|
22
|
-
"link": "#
|
|
23
|
-
"dim": "#
|
|
24
|
-
"select": "#
|
|
25
|
-
"okBg": "#
|
|
26
|
-
"errBg": "#
|
|
5
|
+
"bg": "#141210",
|
|
6
|
+
"surface": "#1c1916",
|
|
7
|
+
"raised": "#24201c",
|
|
8
|
+
"text": "#eae4d5",
|
|
9
|
+
"muted": "#9e9585",
|
|
10
|
+
"line": "#2e2924",
|
|
11
|
+
"mark": "#cf663d",
|
|
12
|
+
"markBright": "#eb7c52",
|
|
13
|
+
"markDeep": "#ad4c24",
|
|
14
|
+
"toneDeep": "#0e0d0b",
|
|
15
|
+
"tone": "#5c4a3e",
|
|
16
|
+
"toneBright": "#8c7362",
|
|
17
|
+
"tonePale": "#b5a08d",
|
|
18
|
+
"green": "#68aa80",
|
|
19
|
+
"red": "#cf663d",
|
|
20
|
+
"yellow": "#cca047",
|
|
21
|
+
"violet": "#a88bb5",
|
|
22
|
+
"link": "#6ea3cc",
|
|
23
|
+
"dim": "#736b5e",
|
|
24
|
+
"select": "#332c25",
|
|
25
|
+
"okBg": "#1b2920",
|
|
26
|
+
"errBg": "#331c19"
|
|
27
27
|
},
|
|
28
28
|
"colors": {
|
|
29
29
|
"accent": "mark",
|
|
@@ -65,15 +65,15 @@
|
|
|
65
65
|
"toolDiffAdded": "green",
|
|
66
66
|
"toolDiffRemoved": "red",
|
|
67
67
|
"toolDiffContext": "muted",
|
|
68
|
-
"syntaxComment": "#
|
|
69
|
-
"syntaxKeyword": "#
|
|
70
|
-
"syntaxFunction": "#
|
|
71
|
-
"syntaxVariable": "#
|
|
72
|
-
"syntaxString": "#
|
|
73
|
-
"syntaxNumber": "#
|
|
74
|
-
"syntaxType": "#
|
|
75
|
-
"syntaxOperator": "#
|
|
76
|
-
"syntaxPunctuation": "#
|
|
68
|
+
"syntaxComment": "#736b5e",
|
|
69
|
+
"syntaxKeyword": "#cf663d",
|
|
70
|
+
"syntaxFunction": "#6ea3cc",
|
|
71
|
+
"syntaxVariable": "#eae4d5",
|
|
72
|
+
"syntaxString": "#68aa80",
|
|
73
|
+
"syntaxNumber": "#a88bb5",
|
|
74
|
+
"syntaxType": "#8c7362",
|
|
75
|
+
"syntaxOperator": "#9e9585",
|
|
76
|
+
"syntaxPunctuation": "#9e9585",
|
|
77
77
|
"thinkingOff": "line",
|
|
78
78
|
"thinkingMinimal": "dim",
|
|
79
79
|
"thinkingLow": "toneBright",
|
|
@@ -84,8 +84,8 @@
|
|
|
84
84
|
"bashMode": "mark"
|
|
85
85
|
},
|
|
86
86
|
"export": {
|
|
87
|
-
"pageBg": "#
|
|
88
|
-
"cardBg": "#
|
|
89
|
-
"infoBg": "#
|
|
87
|
+
"pageBg": "#141210",
|
|
88
|
+
"cardBg": "#1c1916",
|
|
89
|
+
"infoBg": "#24201c"
|
|
90
90
|
}
|
|
91
91
|
}
|
|
@@ -2,28 +2,28 @@
|
|
|
2
2
|
"$schema": "https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
|
|
3
3
|
"name": "subsub-try-works-light",
|
|
4
4
|
"vars": {
|
|
5
|
-
"bg": "#
|
|
6
|
-
"surface": "#
|
|
7
|
-
"raised": "#
|
|
8
|
-
"text": "#
|
|
9
|
-
"muted": "#
|
|
10
|
-
"line": "#
|
|
11
|
-
"mark": "#
|
|
12
|
-
"markBright": "#
|
|
13
|
-
"markDeep": "#
|
|
14
|
-
"toneDeep": "#
|
|
15
|
-
"tone": "#
|
|
16
|
-
"toneBright": "#
|
|
17
|
-
"tonePale": "#
|
|
18
|
-
"green": "#
|
|
19
|
-
"red": "#
|
|
20
|
-
"yellow": "#
|
|
21
|
-
"violet": "#
|
|
22
|
-
"link": "#
|
|
23
|
-
"dim": "#
|
|
24
|
-
"select": "#
|
|
25
|
-
"okBg": "#
|
|
26
|
-
"errBg": "#
|
|
5
|
+
"bg": "#f8f6f0",
|
|
6
|
+
"surface": "#f2ede2",
|
|
7
|
+
"raised": "#ffffff",
|
|
8
|
+
"text": "#211e1b",
|
|
9
|
+
"muted": "#5c554a",
|
|
10
|
+
"line": "#ded6c4",
|
|
11
|
+
"mark": "#8b2500",
|
|
12
|
+
"markBright": "#a83000",
|
|
13
|
+
"markDeep": "#6e1d00",
|
|
14
|
+
"toneDeep": "#1f1b18",
|
|
15
|
+
"tone": "#4a3b32",
|
|
16
|
+
"toneBright": "#6e594d",
|
|
17
|
+
"tonePale": "#c9baa7",
|
|
18
|
+
"green": "#205438",
|
|
19
|
+
"red": "#9c281b",
|
|
20
|
+
"yellow": "#9e6b18",
|
|
21
|
+
"violet": "#664b63",
|
|
22
|
+
"link": "#244662",
|
|
23
|
+
"dim": "#827768",
|
|
24
|
+
"select": "#ded6c4",
|
|
25
|
+
"okBg": "#e2ebe5",
|
|
26
|
+
"errBg": "#f5e4e2"
|
|
27
27
|
},
|
|
28
28
|
"colors": {
|
|
29
29
|
"accent": "mark",
|
|
@@ -65,15 +65,15 @@
|
|
|
65
65
|
"toolDiffAdded": "green",
|
|
66
66
|
"toolDiffRemoved": "red",
|
|
67
67
|
"toolDiffContext": "muted",
|
|
68
|
-
"syntaxComment": "#
|
|
69
|
-
"syntaxKeyword": "#
|
|
70
|
-
"syntaxFunction": "#
|
|
71
|
-
"syntaxVariable": "#
|
|
72
|
-
"syntaxString": "#
|
|
73
|
-
"syntaxNumber": "#
|
|
74
|
-
"syntaxType": "#
|
|
75
|
-
"syntaxOperator": "#
|
|
76
|
-
"syntaxPunctuation": "#
|
|
68
|
+
"syntaxComment": "#827768",
|
|
69
|
+
"syntaxKeyword": "#8b2500",
|
|
70
|
+
"syntaxFunction": "#244662",
|
|
71
|
+
"syntaxVariable": "#211e1b",
|
|
72
|
+
"syntaxString": "#205438",
|
|
73
|
+
"syntaxNumber": "#664b63",
|
|
74
|
+
"syntaxType": "#6e594d",
|
|
75
|
+
"syntaxOperator": "#5c554a",
|
|
76
|
+
"syntaxPunctuation": "#5c554a",
|
|
77
77
|
"thinkingOff": "line",
|
|
78
78
|
"thinkingMinimal": "dim",
|
|
79
79
|
"thinkingLow": "toneBright",
|
|
@@ -84,8 +84,8 @@
|
|
|
84
84
|
"bashMode": "mark"
|
|
85
85
|
},
|
|
86
86
|
"export": {
|
|
87
|
-
"pageBg": "#
|
|
88
|
-
"cardBg": "#
|
|
89
|
-
"infoBg": "#
|
|
87
|
+
"pageBg": "#f8f6f0",
|
|
88
|
+
"cardBg": "#f2ede2",
|
|
89
|
+
"infoBg": "#ffffff"
|
|
90
90
|
}
|
|
91
91
|
}
|