teapot-coding-agent 0.26.13 → 0.27.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/README.md +1 -3
- package/dist/agent/agent.js +85 -14
- package/dist/agent/kill.js +70 -0
- package/dist/agent/skills.js +4 -1
- package/dist/agent/tools.js +23 -22
- package/dist/home.js +51 -0
- package/dist/log/events.js +41 -7
- package/dist/master.js +35 -1
- package/dist/server/api.js +51 -27
- package/package.json +3 -2
- package/public/assets/index-B7AL8hNs.css +1 -0
- package/public/assets/{index-B_BBXIta.js → index-CaKIcOkZ.js} +19 -19
- package/public/assets/index-CaKIcOkZ.js.map +1 -0
- package/public/assets/{shiki-gZkMv9DA.js → shiki-B6zAhgc_.js} +2 -2
- package/public/assets/{shiki-gZkMv9DA.js.map → shiki-B6zAhgc_.js.map} +1 -1
- package/public/index.html +2 -2
- package/README.ja.md +0 -243
- package/public/assets/index-B_BBXIta.js.map +0 -1
- package/public/assets/index-DBx_UTjS.css +0 -1
package/dist/server/api.js
CHANGED
|
@@ -11,6 +11,7 @@ import { promises as fs } from "node:fs";
|
|
|
11
11
|
import { fileURLToPath } from "node:url";
|
|
12
12
|
import { parseSchedule } from "../scheduler/cron.js";
|
|
13
13
|
import { TermSizeTracker } from "./term-size.js";
|
|
14
|
+
import { expandTilde, homeDir } from "../home.js";
|
|
14
15
|
import { SUB_PERSONAS, resolveWorkspace } from "../master.js";
|
|
15
16
|
import { ConfigPatchSchema, formatZodError } from "../config-schema.js";
|
|
16
17
|
import { providerHeaders } from "../agent/llm.js";
|
|
@@ -440,8 +441,11 @@ export function buildApp(master) {
|
|
|
440
441
|
});
|
|
441
442
|
// ---- filesystem browsing (read-only, for the workspace picker) ----
|
|
442
443
|
app.get("/api/fs", async (c) => {
|
|
443
|
-
|
|
444
|
-
|
|
444
|
+
// #110: read the home directory through the shared helper. `process.env.HOME`
|
|
445
|
+
// is unset on Windows, which made the old fallback yield the literal "~" —
|
|
446
|
+
// and /api/fs would then browse a directory named ~.
|
|
447
|
+
let p = c.req.query("path") || homeDir() || path.parse(process.cwd()).root;
|
|
448
|
+
p = path.resolve(expandTilde(p));
|
|
445
449
|
try {
|
|
446
450
|
const entries = await fs.readdir(p, { withFileTypes: true });
|
|
447
451
|
return c.json({
|
|
@@ -521,14 +525,18 @@ export function buildApp(master) {
|
|
|
521
525
|
app.get("/api/agents/:id/tree", async (c) => {
|
|
522
526
|
const a = master.agents.get(c.req.param("id"));
|
|
523
527
|
if (!a)
|
|
524
|
-
return c
|
|
528
|
+
return notFound(c, "agent", c.req.param("id"));
|
|
525
529
|
const rel = c.req.query("path") || ".";
|
|
526
530
|
let abs;
|
|
527
531
|
try {
|
|
528
532
|
abs = safeJoin(a.workspace, rel);
|
|
529
533
|
}
|
|
530
534
|
catch (err) {
|
|
531
|
-
|
|
535
|
+
// #126: safeJoin's message embeds the RESOLVED absolute path
|
|
536
|
+
// ("path escapes workspace: /home/user/secret/project/…"), so returning it
|
|
537
|
+
// verbatim hands the caller the server's directory layout. The rejection is
|
|
538
|
+
// correct; the disclosure was not. Echo back the path AS GIVEN.
|
|
539
|
+
return c.json({ error: `path is outside the workspace: ${rel}` }, 400);
|
|
532
540
|
}
|
|
533
541
|
let dirents;
|
|
534
542
|
try {
|
|
@@ -576,7 +584,7 @@ export function buildApp(master) {
|
|
|
576
584
|
app.get("/api/agents/:id/file", async (c) => {
|
|
577
585
|
const a = master.agents.get(c.req.param("id"));
|
|
578
586
|
if (!a)
|
|
579
|
-
return c
|
|
587
|
+
return notFound(c, "agent", c.req.param("id"));
|
|
580
588
|
const rel = c.req.query("path") ?? "";
|
|
581
589
|
if (!rel.trim())
|
|
582
590
|
return c.json({ error: "path required" }, 400);
|
|
@@ -607,7 +615,7 @@ export function buildApp(master) {
|
|
|
607
615
|
app.get("/api/agents/:id/raw", async (c) => {
|
|
608
616
|
const a = master.agents.get(c.req.param("id"));
|
|
609
617
|
if (!a)
|
|
610
|
-
return c
|
|
618
|
+
return notFound(c, "agent", c.req.param("id"));
|
|
611
619
|
const rel = c.req.query("path") ?? "";
|
|
612
620
|
if (!rel.trim())
|
|
613
621
|
return c.json({ error: "path required" }, 400);
|
|
@@ -645,7 +653,7 @@ export function buildApp(master) {
|
|
|
645
653
|
app.put("/api/agents/:id/file", async (c) => {
|
|
646
654
|
const a = master.agents.get(c.req.param("id"));
|
|
647
655
|
if (!a)
|
|
648
|
-
return c
|
|
656
|
+
return notFound(c, "agent", c.req.param("id"));
|
|
649
657
|
const rel = c.req.query("path") ?? "";
|
|
650
658
|
if (!rel.trim())
|
|
651
659
|
return c.json({ error: "path required" }, 400);
|
|
@@ -751,20 +759,20 @@ export function buildApp(master) {
|
|
|
751
759
|
});
|
|
752
760
|
app.get("/api/agents/:id", (c) => {
|
|
753
761
|
const a = master.agents.get(c.req.param("id"));
|
|
754
|
-
return a ? c.json(a.snapshot()) : c
|
|
762
|
+
return a ? c.json(a.snapshot()) : notFound(c, "agent", c.req.param("id"));
|
|
755
763
|
});
|
|
756
764
|
// lazy session load: stopped (not restored) → idle, history rebuilt from the log
|
|
757
765
|
app.post("/api/agents/:id/load", async (c) => {
|
|
758
766
|
const a = master.agents.get(c.req.param("id"));
|
|
759
767
|
if (!a)
|
|
760
|
-
return c
|
|
768
|
+
return notFound(c, "agent", c.req.param("id"));
|
|
761
769
|
await a.load();
|
|
762
770
|
return c.json({ ok: true, agent: a.snapshot() });
|
|
763
771
|
});
|
|
764
772
|
app.post("/api/agents/:id/prompt", async (c) => {
|
|
765
773
|
const a = master.agents.get(c.req.param("id"));
|
|
766
774
|
if (!a)
|
|
767
|
-
return c
|
|
775
|
+
return notFound(c, "agent", c.req.param("id"));
|
|
768
776
|
const body = await c.req
|
|
769
777
|
.json()
|
|
770
778
|
.catch(() => null); // #110
|
|
@@ -793,7 +801,7 @@ export function buildApp(master) {
|
|
|
793
801
|
app.post("/api/agents/:id/prompt/cancel", async (c) => {
|
|
794
802
|
const a = master.agents.get(c.req.param("id"));
|
|
795
803
|
if (!a)
|
|
796
|
-
return c
|
|
804
|
+
return notFound(c, "agent", c.req.param("id"));
|
|
797
805
|
const body = await c.req.json().catch(() => null); // #110
|
|
798
806
|
if (!body)
|
|
799
807
|
return c.json({ error: "invalid JSON" }, 400);
|
|
@@ -807,7 +815,7 @@ export function buildApp(master) {
|
|
|
807
815
|
app.post("/api/agents/:id/start", (c) => {
|
|
808
816
|
const a = master.agents.get(c.req.param("id"));
|
|
809
817
|
if (!a)
|
|
810
|
-
return c
|
|
818
|
+
return notFound(c, "agent", c.req.param("id"));
|
|
811
819
|
a.start("api start");
|
|
812
820
|
return c.json({ ok: true });
|
|
813
821
|
});
|
|
@@ -870,14 +878,14 @@ export function buildApp(master) {
|
|
|
870
878
|
app.post("/api/agents/:id/stop", (c) => {
|
|
871
879
|
const a = master.agents.get(c.req.param("id"));
|
|
872
880
|
if (!a)
|
|
873
|
-
return c
|
|
881
|
+
return notFound(c, "agent", c.req.param("id"));
|
|
874
882
|
a.stop("stopped via api");
|
|
875
883
|
return c.json({ ok: true });
|
|
876
884
|
});
|
|
877
885
|
app.post("/api/agents/:id/goal", async (c) => {
|
|
878
886
|
const a = master.agents.get(c.req.param("id"));
|
|
879
887
|
if (!a)
|
|
880
|
-
return c
|
|
888
|
+
return notFound(c, "agent", c.req.param("id"));
|
|
881
889
|
const body = await c.req.json()
|
|
882
890
|
.catch(() => null); // #110
|
|
883
891
|
if (!body)
|
|
@@ -907,7 +915,7 @@ export function buildApp(master) {
|
|
|
907
915
|
app.get("/api/agents/:id/skills", async (c) => {
|
|
908
916
|
const a = master.agents.get(c.req.param("id"));
|
|
909
917
|
if (!a)
|
|
910
|
-
return c
|
|
918
|
+
return notFound(c, "agent", c.req.param("id"));
|
|
911
919
|
try {
|
|
912
920
|
const list = await currentSkills(a.toolCtx);
|
|
913
921
|
return c.json({
|
|
@@ -922,7 +930,7 @@ export function buildApp(master) {
|
|
|
922
930
|
app.post("/api/agents/:id/compact", async (c) => {
|
|
923
931
|
const a = master.agents.get(c.req.param("id"));
|
|
924
932
|
if (!a)
|
|
925
|
-
return c
|
|
933
|
+
return notFound(c, "agent", c.req.param("id"));
|
|
926
934
|
try {
|
|
927
935
|
return c.json({ ok: true, ...(await a.compactNow()) });
|
|
928
936
|
}
|
|
@@ -950,7 +958,7 @@ export function buildApp(master) {
|
|
|
950
958
|
app.post("/api/agents/:id/auto-continue", async (c) => {
|
|
951
959
|
const a = master.agents.get(c.req.param("id"));
|
|
952
960
|
if (!a)
|
|
953
|
-
return c
|
|
961
|
+
return notFound(c, "agent", c.req.param("id"));
|
|
954
962
|
const body = await c.req.json().catch(() => null);
|
|
955
963
|
if (!body || typeof body.value !== "boolean")
|
|
956
964
|
return c.json({ error: "boolean value required" }, 400);
|
|
@@ -966,7 +974,7 @@ export function buildApp(master) {
|
|
|
966
974
|
app.post("/api/agents/:id/auto-compact", async (c) => {
|
|
967
975
|
const a = master.agents.get(c.req.param("id"));
|
|
968
976
|
if (!a)
|
|
969
|
-
return c
|
|
977
|
+
return notFound(c, "agent", c.req.param("id"));
|
|
970
978
|
const body = await c.req.json().catch(() => null);
|
|
971
979
|
if (!body || typeof body.value !== "boolean")
|
|
972
980
|
return c.json({ error: "boolean value required" }, 400);
|
|
@@ -986,7 +994,7 @@ export function buildApp(master) {
|
|
|
986
994
|
app.post("/api/agents/:id/spawn", async (c) => {
|
|
987
995
|
const a = master.agents.get(c.req.param("id"));
|
|
988
996
|
if (!a)
|
|
989
|
-
return c
|
|
997
|
+
return notFound(c, "agent", c.req.param("id"));
|
|
990
998
|
const body = await c.req
|
|
991
999
|
.json()
|
|
992
1000
|
.catch(() => null);
|
|
@@ -1009,7 +1017,7 @@ export function buildApp(master) {
|
|
|
1009
1017
|
app.post("/api/agents/:id/stop-children", async (c) => {
|
|
1010
1018
|
const a = master.agents.get(c.req.param("id"));
|
|
1011
1019
|
if (!a)
|
|
1012
|
-
return c
|
|
1020
|
+
return notFound(c, "agent", c.req.param("id"));
|
|
1013
1021
|
const body = await c.req.json().catch(() => ({ ids: undefined }));
|
|
1014
1022
|
try {
|
|
1015
1023
|
const r = await master.stopChildrenFor(c.req.param("id"), body.ids);
|
|
@@ -1023,20 +1031,26 @@ export function buildApp(master) {
|
|
|
1023
1031
|
app.post("/api/agents/:id/todo", async (c) => {
|
|
1024
1032
|
const a = master.agents.get(c.req.param("id"));
|
|
1025
1033
|
if (!a)
|
|
1026
|
-
return c
|
|
1034
|
+
return notFound(c, "agent", c.req.param("id"));
|
|
1027
1035
|
const body = await c.req.json().catch(() => null);
|
|
1028
1036
|
if (!body)
|
|
1029
1037
|
return c.json({ error: "invalid JSON" }, 400);
|
|
1030
1038
|
await a.setTodo(body.text ?? "");
|
|
1031
1039
|
if (body.notify !== false && body.text?.trim())
|
|
1032
1040
|
a.enqueuePrompt(`[harness] The operator updated the task list:\n\n${body.text}\n\nWork through it (get_todo() always has the latest).`, "harness");
|
|
1041
|
+
// #123: an idle agent must actually START on the queued prompt. The goal
|
|
1042
|
+
// route above learned this (the queued prompt sat forever otherwise); the
|
|
1043
|
+
// todo route did not, so saving a task list on an idle session looked like
|
|
1044
|
+
// it had been ignored.
|
|
1045
|
+
if (a.status !== "running")
|
|
1046
|
+
a.start("todo set");
|
|
1033
1047
|
return c.json({ ok: true });
|
|
1034
1048
|
});
|
|
1035
1049
|
// edit a previously-sent prompt: forks there, optionally summarizes the tail
|
|
1036
1050
|
app.post("/api/agents/:id/edit-prompt", async (c) => {
|
|
1037
1051
|
const a = master.agents.get(c.req.param("id"));
|
|
1038
1052
|
if (!a)
|
|
1039
|
-
return c
|
|
1053
|
+
return notFound(c, "agent", c.req.param("id"));
|
|
1040
1054
|
const body = await c.req
|
|
1041
1055
|
.json()
|
|
1042
1056
|
.catch(() => null);
|
|
@@ -1062,7 +1076,7 @@ export function buildApp(master) {
|
|
|
1062
1076
|
app.post("/api/agents/:id/fork", async (c) => {
|
|
1063
1077
|
const a = master.agents.get(c.req.param("id"));
|
|
1064
1078
|
if (!a)
|
|
1065
|
-
return c
|
|
1079
|
+
return notFound(c, "agent", c.req.param("id"));
|
|
1066
1080
|
const body = await c.req.json().catch(() => ({ fromEvent: null }));
|
|
1067
1081
|
const r = await a.fork(body.fromEvent ?? null);
|
|
1068
1082
|
return c.json({ ok: true, ...r });
|
|
@@ -1092,7 +1106,7 @@ export function buildApp(master) {
|
|
|
1092
1106
|
app.get("/api/agents/:id/events", async (c) => {
|
|
1093
1107
|
const a = master.agents.get(c.req.param("id"));
|
|
1094
1108
|
if (!a)
|
|
1095
|
-
return c
|
|
1109
|
+
return notFound(c, "agent", c.req.param("id"));
|
|
1096
1110
|
// #54: the frontend pairs a tool_call with its tool_result by walking the
|
|
1097
1111
|
// events it holds, so a window that can contain a result WITHOUT its call
|
|
1098
1112
|
// strands the bash row at "waiting for output…" forever — the call scrolled
|
|
@@ -1109,7 +1123,7 @@ export function buildApp(master) {
|
|
|
1109
1123
|
if (sessionId) {
|
|
1110
1124
|
const rec = master.sessionById(sessionId);
|
|
1111
1125
|
if (!rec || rec.agentId !== c.req.param("id"))
|
|
1112
|
-
return c
|
|
1126
|
+
return notFound(c, "session (or it belongs to another agent)", sessionId);
|
|
1113
1127
|
filePath = path.join(rec.dir, "chat.jsonl");
|
|
1114
1128
|
}
|
|
1115
1129
|
// #59: the plain "latest N" request is what the UI polls every ~120 ms for
|
|
@@ -1148,13 +1162,13 @@ export function buildApp(master) {
|
|
|
1148
1162
|
const known = master.agents.has(id) || master.config.agents.some((a) => a.id === id);
|
|
1149
1163
|
const owned = master.sessionsOf(id);
|
|
1150
1164
|
if (!known && owned.length === 0)
|
|
1151
|
-
return c
|
|
1165
|
+
return notFound(c, "agent", id);
|
|
1152
1166
|
return c.json({ sessions: owned });
|
|
1153
1167
|
});
|
|
1154
1168
|
app.get("/api/agents/:id/branches", async (c) => {
|
|
1155
1169
|
const a = master.agents.get(c.req.param("id"));
|
|
1156
1170
|
if (!a)
|
|
1157
|
-
return c
|
|
1171
|
+
return notFound(c, "agent", c.req.param("id"));
|
|
1158
1172
|
// cached like /events — this used to bypass it and re-read the whole log
|
|
1159
1173
|
const events = await readEventsCached(a.log.filePath);
|
|
1160
1174
|
const branches = new Map();
|
|
@@ -1186,6 +1200,16 @@ export function buildApp(master) {
|
|
|
1186
1200
|
// ---- metrics / SSE ----
|
|
1187
1201
|
app.get("/api/metrics", (c) => c.json(master.metrics()));
|
|
1188
1202
|
// current server version (for live-update polling)
|
|
1203
|
+
/**
|
|
1204
|
+
* A 404 that says WHICH thing was missing.
|
|
1205
|
+
*
|
|
1206
|
+
* #126: there were 24 hand-copied `c.json({ error: "not found" }, 404)` lines.
|
|
1207
|
+
* From a client they are indistinguishable — a typo in an agent id, a deleted
|
|
1208
|
+
* session, or a bad route all produce the same three words, and none carries
|
|
1209
|
+
* the id that was looked up. The id is the first thing anyone debugging this
|
|
1210
|
+
* needs, and it is already in hand.
|
|
1211
|
+
*/
|
|
1212
|
+
const notFound = (c, what, id) => c.json({ error: `${what} not found: ${id || "(no id given)"}` }, 404);
|
|
1189
1213
|
app.get("/api/version", (c) => c.json({ version: master.getVersion() }));
|
|
1190
1214
|
// trigger a full server restart (agents stopped gracefully, new process spawned)
|
|
1191
1215
|
app.post("/api/update/restart", async (c) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "teapot-coding-agent",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.27.0",
|
|
4
4
|
"description": "A lightweight, always-on multi-agent harness for AI coding agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "AGPL-3.0-or-later",
|
|
@@ -39,7 +39,8 @@
|
|
|
39
39
|
"start": "node dist/index.js",
|
|
40
40
|
"dev": "node src/index.ts",
|
|
41
41
|
"dev-web": "vite",
|
|
42
|
-
"test": "node --test test/*.test.ts"
|
|
42
|
+
"test": "node --test test/*.test.ts",
|
|
43
|
+
"test:portable": "node scripts/run-portable-tests.mjs"
|
|
43
44
|
},
|
|
44
45
|
"dependencies": {
|
|
45
46
|
"@hono/node-server": "^2.1.1",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
:root{--bg-darkest:#1a1c22;--bg-dark:#232630;--bg-mid:#2b2e39;--bg-light:#343845;--fg:#dcdee4;--dim:#9298a5;--line:#1d2027;--acc:#5865f2;--ok:#3ba55d;--warn:#faa81a;--err:#ed4245;--tool:#3ba0c9;--term-bg:#0d0e12;--term-fg:#dcdee4;font-family:gg sans,ui-sans-serif,system-ui,-apple-system,Segoe UI,sans-serif}[data-theme=midnight]{--bg-darkest:#0d0f18;--bg-dark:#12141f;--bg-mid:#1b1f31;--bg-light:#252a42;--fg:#dfe2f2;--dim:#8a90ad;--line:#0a0c14;--acc:#8b7cf7;--ok:#54c08a;--warn:#e5b567;--err:#ef6a6a;--tool:#6aa9e9;--term-bg:#0a0c13;--term-fg:#dfe2f2}[data-theme=tea]{--bg-darkest:#241c16;--bg-dark:#2e241c;--bg-mid:#3b2f24;--bg-light:#493b2d;--fg:#f0e4d2;--dim:#b39d82;--line:#1b140f;--acc:#d98e32;--ok:#7fa653;--warn:#e0b058;--err:#cf5b47;--tool:#c9975f;--term-bg:#1d1712;--term-fg:#ecdcc3}[data-theme=coffee]{--bg-darkest:#191410;--bg-dark:#211a14;--bg-mid:#30271e;--bg-light:#403527;--fg:#ede3d0;--dim:#a89478;--line:#120d07;--acc:#c68a4b;--ok:#8aa15c;--warn:#d9a441;--err:#c25450;--tool:#a67c52;--term-bg:#15100c;--term-fg:#e8dcc5}[data-theme=matcha]{--bg-darkest:#1b2217;--bg-dark:#232b1e;--bg-mid:#2f3a28;--bg-light:#3c4a33;--fg:#e8eeda;--dim:#9aab84;--line:#131a10;--acc:#8db64e;--ok:#6fae4e;--warn:#d8b13c;--err:#cd5c50;--tool:#5da88f;--term-bg:#151b11;--term-fg:#dfe8cb}[data-theme=matrix]{--bg-darkest:#060a06;--bg-dark:#0a0f0a;--bg-mid:#122116;--bg-light:#18301d;--fg:#c9f2cf;--dim:#6fa075;--line:#030603;--acc:#2fd558;--ok:#39c95f;--warn:#b8d977;--err:#ff6b6b;--tool:#57c99b;--term-bg:#030503;--term-fg:#3f7}[data-theme=sunset]{--bg-darkest:#1c1422;--bg-dark:#241b2b;--bg-mid:#33253e;--bg-light:#452f52;--fg:#f2e6ea;--dim:#ab93a8;--line:#150e1b;--acc:#f2784b;--ok:#63b46f;--warn:#eda63d;--err:#e25563;--tool:#b06ac9;--term-bg:#170f1d;--term-fg:#f0dfe4}[data-theme=light]{--bg-darkest:#eceef4;--bg-dark:#f6f7fa;--bg-mid:#e2e5ee;--bg-light:#fff;--fg:#24272f;--dim:#5d6470;--line:#d8dbe4;--acc:#4757d8;--ok:#2b8a4b;--warn:#b97a0f;--err:#d83c3f;--tool:#2278a8;--term-bg:#fff;--term-fg:#24272f}[data-theme=strawberry]{--bg-darkest:#fbe4ea;--bg-dark:#fdf0f3;--bg-mid:#f7d4de;--bg-light:#fffafb;--fg:#4a2733;--dim:#96707e;--line:#f0ccd6;--acc:#e05575;--ok:#4d9e63;--warn:#c98a2d;--err:#d43d51;--tool:#b05687;--term-bg:#fff5f8;--term-fg:#4a2733}[data-theme=ramune]{--bg-darkest:#ddeff7;--bg-dark:#ecf7fb;--bg-mid:#c9e7f4;--bg-light:#fbfeff;--fg:#173342;--dim:#5b7d90;--line:#c2e2ef;--acc:#1d86ae;--ok:#3a9e6e;--warn:#cf9a2a;--err:#d64f5c;--tool:#3a9db8;--term-bg:#f4fbfd;--term-fg:#173342}*{box-sizing:border-box}html,body,#root{height:100%;margin:0}body{background:var(--bg-dark);color:var(--fg);font-size:15px}.layout{grid-template-columns:250px 1fr 370px;height:100dvh;display:grid;overflow:hidden}.layout.right-hidden{grid-template-columns:250px 1fr}.layout.right-hidden .rightbar{display:none}@media (width<=1100px){.layout,.layout.right-hidden{grid-template-columns:220px 1fr}.layout.right-hidden .rightbar,.layout .rightbarbackdrop{display:block}.rightbar .rightbarhead{z-index:1;display:flex;position:sticky;top:0}.rightbar{z-index:5;width:min(420px,92vw);box-shadow:none;transition:transform .18s,box-shadow .18s;position:fixed;top:0;bottom:0;right:0;transform:translate(100%)}.rightbar.open{transform:none;box-shadow:-8px 0 24px #0007}}.sidebar{background:var(--bg-darkest);flex-direction:column;padding:10px 8px;display:flex;overflow:hidden auto}.themepop{background:var(--bg-mid);border:1px solid var(--bg-light);border-radius:8px;flex-direction:column;gap:8px;padding:10px;display:flex;position:static}.trow{color:var(--fg);cursor:pointer;align-items:center;gap:6px;font-size:12.5px;display:flex}.trow select{background:var(--bg-darkest);color:var(--fg);border:none;border-radius:5px;outline:none;padding:3px 6px}.themegrid{grid-template-columns:1fr 1fr;gap:4px;display:grid}.themebtn{background:var(--bg-light);color:var(--fg);cursor:pointer;text-align:left;border:1px solid #0000;border-radius:6px;align-items:center;gap:6px;min-width:0;padding:5px 8px;font-size:12px;display:flex;overflow:hidden}.themebtn>:last-child{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.themebtn:hover{filter:brightness(1.15)}.themebtn.on{border-color:var(--acc)}.swdots{flex-shrink:0;gap:2px;display:inline-flex}.swdots i{border-radius:50%;width:9px;height:9px;display:inline-block;box-shadow:inset 0 0 0 1px #0004}.agent-list{flex:1;min-width:0;min-height:0;overflow-y:auto}.wsheader{letter-spacing:.04em;text-transform:uppercase;color:var(--dim);cursor:pointer;-webkit-user-select:none;user-select:none;border-top:1px solid var(--line);align-items:center;gap:6px;margin-top:6px;padding:10px 10px 4px;font-size:11px;font-weight:600;display:flex}.wsheader:first-child{border-top:none;margin-top:0}.wsheader:hover{color:var(--fg)}.wsheader .wscaret{flex-shrink:0;width:12px;font-size:9px}.wsheader .wscount{background:var(--bg-light);color:var(--dim);letter-spacing:0;border-radius:999px;flex-shrink:0;margin-left:auto;padding:0 6px;font-size:10px;font-weight:600;line-height:15px}.agent-item{cursor:pointer;color:var(--fg);border-radius:6px;align-items:center;gap:8px;min-width:0;margin-bottom:2px;padding:7px 10px;display:flex}.agent-item>span:not(.dot):not(.caret):not(.caret-spacer):not(.notifbadge):not(.subcount):not(.subtag):not(.ghosttag):not(.mini-cron):not(.goaldone){text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.agent-item .subtag{color:var(--dim);font-size:10px}.agent-item .goaldone{flex-shrink:0}.caret{cursor:pointer;width:12px;color:var(--dim);text-align:center;-webkit-user-select:none;user-select:none;flex-shrink:0;font-size:9px}.caret:hover{color:var(--fg)}.caret-spacer{flex-shrink:0;width:12px}.agent-item:hover{background:var(--bg-mid)}.agent-item.collapsed{cursor:pointer}.agent-item.sel{background:var(--bg-mid)}.agent-item.sub-row{color:var(--dim)}.agent-item.sub-row.sel{color:var(--fg)}.dot{border-radius:50%;flex-shrink:0;width:9px;height:9px}.dot.running{background:var(--ok);box-shadow:0 0 6px var(--ok)}.dot.waiting{background:var(--acc);box-shadow:0 0 6px var(--acc);animation:1.6s ease-in-out infinite pulse}.badge.waiting{color:var(--acc)}.dot.idle{background:var(--warn)}.dot.stopped{background:var(--dim)}.dot.error{background:var(--err);box-shadow:0 0 6px var(--err)}.sidebar .metrics{color:var(--dim);border-top:1px solid var(--line);margin-top:12px;padding:8px 10px;font-size:11px;line-height:1.7}.sidebar-footer{border-top:1px solid var(--line);flex-direction:column;gap:2px;margin-top:auto;padding-top:8px;display:flex}.footer-row{align-items:center;gap:8px;display:flex}.footer-row .conn{margin-left:0}.sidebar-footer .metrics{border-top:none;margin-top:4px;padding:0}.brand{color:var(--fg);align-items:center;gap:8px;font-size:14px;display:flex}.version{color:var(--dim);font-family:ui-monospace,Menlo,monospace;font-size:11px}.channel{flex-direction:column;min-width:0;min-height:0;display:flex;position:relative;overflow:hidden}.chan-head{border-bottom:2px solid var(--line);background:var(--bg-dark);flex-shrink:0;align-items:center;gap:10px;padding:10px 16px;display:flex}.chan-head .hash{color:var(--dim);font-size:20px}.chan-head .title{font-weight:700}.chan-head .sub{color:var(--dim);text-overflow:ellipsis;white-space:nowrap;margin-left:8px;font-size:12px;overflow:hidden}.badge{background:var(--bg-light);vertical-align:middle;border-radius:10px;padding:1px 8px;font-size:11px}.badge.running{color:var(--ok)}.badge.error{color:var(--err)}.badge.idle{color:var(--warn)}.badge.done{color:var(--acc)}.badge.queued{color:var(--warn);white-space:nowrap;background:#faa81a1a;border:1px solid #faa81a44}.feed{overscroll-behavior:contain;flex:1;min-height:0;padding:14px 0 8px;overflow-y:auto}.msg{gap:14px;padding:3px 18px;display:flex}.msg:hover{background:#ffffff08}.msg.pending{opacity:.75}.msg.pending .ts{color:var(--warn);font-weight:600}.msg.pending .avatar{animation:1.6s ease-in-out infinite pulse}.msg.pending .editbtn.cancel{color:var(--err)}.msg.withdrawn{opacity:.55}.msg.withdrawn .msg-body{text-decoration:line-through;-webkit-text-decoration-color:var(--muted);text-decoration-color:var(--muted)}.msg.withdrawn .msg-head{text-decoration:none}.msg.withdrawn .ts{color:var(--muted);font-weight:600}.msg.grouped{padding-top:0}.avatar{border-radius:50%;flex-shrink:0;justify-content:center;align-items:center;width:38px;height:38px;margin-top:2px;font-size:17px;display:flex}.msg-body{flex:1;min-width:0}.msg-head{align-items:baseline;gap:8px;display:flex}.actor{color:var(--warn);white-space:nowrap;font-size:11px}.runcard{flex-direction:column;gap:8px;display:flex}.statgrid{grid-template-columns:repeat(3,1fr);gap:6px;display:grid}.stat{background:var(--bg-mid);border-radius:6px;flex-direction:column;gap:1px;min-width:0;padding:5px 8px;display:flex}.stat span{color:var(--dim);text-transform:uppercase;letter-spacing:.05em;font-size:10px}.stat b{text-overflow:ellipsis;font-size:15px;overflow:hidden}.statrow{align-items:center;gap:8px;min-width:0;font-size:12.5px;display:flex}.statrow .k{color:var(--dim);text-transform:uppercase;letter-spacing:.05em;white-space:nowrap;flex-shrink:0;width:auto;min-width:58px;font-size:10px}.pill{background:var(--bg-mid);white-space:nowrap;border-radius:999px;margin-left:auto;padding:1px 8px;font-size:11px}.pill.ok{color:var(--ok)}.pill.warn{color:var(--warn)}.pill.crit{color:var(--err);background:#ed42451a}.bartrack{background:var(--bg-light);border-radius:3px;height:6px;margin-top:2px;overflow:hidden}.barfill{background:var(--ok);border-radius:3px;min-width:2px;height:100%;transition:width .3s}.barfill.warn{background:var(--warn)}.barfill.crit{background:var(--err)}.author{font-size:14.5px;font-weight:600}.ts{color:var(--dim);font-size:11px}.content{white-space:pre-wrap;word-break:break-word;line-height:1.45}.content p{margin:2px 0}.content pre{background:var(--bg-darkest);border-radius:6px;padding:8px;overflow-x:auto}.content pre>code{white-space:pre-wrap;overflow-wrap:anywhere}.content code{background:var(--bg-darkest);border-radius:4px;padding:1px 4px;font-size:13px}.content pre code{background:0 0;padding:0}.content h1,.content h2,.content h3,.content h4,.content h5,.content h6{margin:8px 0 2px;font-size:15px}.content h1{font-size:16.5px}.content h2{font-size:15.5px}.content blockquote{border-left:3px solid var(--bg-light);color:var(--dim);background:#ffffff05;border-radius:0 4px 4px 0;margin:4px 0;padding:2px 10px}.content blockquote p{margin:2px 0}.content hr{border:none;border-top:1px solid var(--bg-light);margin:8px 0}.content del{color:var(--dim)}.content img{border-radius:6px;max-width:100%}.content li.task{margin-left:-18px;list-style:none}.content li:has(>input[type=checkbox]){margin-left:-18px;list-style:none}.content li input[type=checkbox]{accent-color:var(--ok);margin-right:6px}input[type=checkbox]{accent-color:var(--acc)}.content a{color:var(--tool);text-decoration:underline;-webkit-text-decoration-color:color-mix(in srgb, var(--tool) 45%, transparent);text-decoration-color:color-mix(in srgb, var(--tool) 45%, transparent);text-underline-offset:2px}.content a:hover{filter:brightness(1.15)}.themebtn.on{background:var(--acc);color:#fff}.trow select:focus{outline:1px solid var(--acc)}.tbl{margin:6px 0;overflow-x:auto}.tbl table{border-collapse:collapse;font-size:13px}.tbl th,.tbl td{border:1px solid var(--bg-light);text-align:left;padding:3px 9px}.tbl th{background:var(--bg-darkest);font-weight:600}.embed{border-left:3px solid var(--tool);background:var(--bg-darkest);border-radius:4px;margin-top:3px;padding:6px 10px;font-size:13.5px}.embed.fail{border-color:var(--err)}.embed.warn-embed{border-color:var(--warn)}.embed.warn-embed .mono{color:var(--warn)}.embed.done{border-color:var(--ok)}.embed.running{border-color:var(--warn)}.embed.running summary .meta:after{content:"⋯";color:var(--warn);margin-left:6px;animation:1s step-end infinite blink;display:inline-block}.embed summary{gap:8px}.embed summary .mono{font-family:ui-monospace,Menlo,monospace}.toolbody{background:var(--bg-darkest);white-space:pre-wrap;word-break:break-word;border-radius:4px;max-height:340px;margin:4px 0;padding:6px 8px;font-size:12.5px;overflow-y:auto}.toolbody.del{border-left:2px solid var(--err);color:#f0a5a6;background:#ed424514}.toolbody.add{border-left:2px solid var(--ok);color:#9fd8ae;background:#3ba55d14}.toolbody.patch{padding:4px 8px}.toolbody.patch .pline{white-space:pre-wrap;word-break:break-word}.toolbody.patch .pline.add{color:#9fd8ae;border-left:2px solid var(--ok);background:#3ba55d14;padding-left:4px}.toolbody.patch .pline.del{color:#f0a5a6;border-left:2px solid var(--err);background:#ed424514;padding-left:4px}.toolbody.patch .pline.meta{color:var(--dim)}.embed.question{border-color:var(--acc);background:#5865f20f}.qopts{flex-wrap:wrap;gap:6px;margin-top:6px;display:flex}.qopt{background:var(--acc);color:#fff;cursor:pointer;border:none;border-radius:999px;padding:3px 12px;font-size:12.5px}.qopt:hover{filter:brightness(1.15)}.qopt:disabled{opacity:.45;cursor:default;filter:none}.embed.question.answered{opacity:.75}.qfree{gap:6px;margin-top:8px;display:flex}.qfree input{background:var(--bg-mid);border:1px solid var(--bg-light);color:var(--fg);border-radius:6px;outline:none;flex:1;padding:4px 10px;font-size:13px}.qfree input:focus{border-color:var(--acc)}.qfree button{background:var(--bg-light);color:var(--fg);cursor:pointer;border:none;border-radius:6px;padding:4px 12px;font-size:12.5px}.qfree button:disabled{opacity:.45;cursor:default}.bashelapsed{color:var(--warn);margin-left:8px;font-size:11px}.embed.question .meta{margin-top:6px}.embed.decision{border-color:var(--acc);background:#5865f20f}.embed.decision summary .meta{margin-left:6px}.embed.decision .content{margin-top:3px;font-size:13px}.embed summary{cursor:pointer;-webkit-user-select:none;user-select:none;list-style-position:outside}.embed summary::marker{color:var(--dim)}.embed[open] summary{margin-bottom:4px}.embed .mono{white-space:pre-wrap;word-break:break-word;max-height:340px;font-family:ui-monospace,Menlo,monospace;font-size:12.5px;overflow-y:auto}.embed .meta{color:var(--dim);margin-top:3px;font-size:11px}.reasoning{border-left:3px dashed var(--bg-light);color:var(--dim);background:#ffffff05;border-radius:4px;margin:2px 0;padding:2px 10px;font-size:12.5px}.reasoning summary{cursor:pointer;-webkit-user-select:none;user-select:none;opacity:.75}.reasoning summary:hover{opacity:1;color:var(--fg)}.reasoning[open] summary{margin-bottom:4px}.reasoning .mono{white-space:pre-wrap;word-break:break-word;max-height:260px;overflow-y:auto}.msg.live .avatar{animation:1.6s ease-in-out infinite pulse}.cursor{color:var(--acc);animation:1s step-end infinite blink}.interrupted{color:var(--warn);margin-top:3px;font-size:11.5px}@keyframes blink{50%{opacity:0}}@keyframes pulse{50%{opacity:.55}}.conn{background:var(--err);vertical-align:middle;width:8px;height:8px;box-shadow:0 0 6px var(--err);border-radius:50%;display:inline-block}.conn.ok{background:var(--ok);box-shadow:0 0 6px var(--ok)}.copybtn{border:1px solid var(--bg-light);color:var(--dim);cursor:pointer;background:0 0;border-radius:4px;flex-shrink:0;padding:0 5px;font-size:11px;line-height:16px}.copybtn:hover{color:var(--fg);filter:brightness(1.3)}.embed summary{align-items:center;gap:6px;display:flex}.embed summary .iconmeta{flex-shrink:0;font-size:11px}.toolcopy{flex-shrink:0;gap:4px;margin-left:auto;display:flex}.msgfoot{color:var(--dim);align-items:center;gap:6px;margin-top:4px;font-size:11px;display:flex}.imgstage{flex-wrap:wrap;gap:6px;margin-bottom:6px;display:flex}.imgchip{display:inline-flex;position:relative}.imgchip img{object-fit:cover;border:1px solid var(--line);border-radius:6px;width:64px;height:64px}.imgchip .imgx{background:var(--err);color:#fff;cursor:pointer;border:none;border-radius:50%;justify-content:center;align-items:center;width:16px;height:16px;padding:0;font-size:9px;line-height:1;display:inline-flex;position:absolute;top:-5px;right:-5px}.promptimgs{flex-wrap:wrap;gap:6px;margin-top:4px;display:flex}img.promptimg{border:1px solid var(--line);border-radius:6px;max-width:180px;max-height:120px}.bgjob-note{color:var(--warn)}.bgjob-note b{color:var(--fg);font-family:ui-monospace,Menlo,monospace}details.reasoning .thinkscroll{white-space:pre-wrap;word-break:break-word;scrollbar-gutter:stable;max-height:220px;overflow-y:auto}.thinktimer{color:var(--dim);margin-left:6px;font-size:11px;font-weight:400}.termdrawer{background:var(--term-bg);border-top:2px solid var(--line);flex-direction:column;display:flex}.termgrip{cursor:ns-resize;background:var(--bg-light);opacity:.6;border-bottom:1px solid var(--line);height:6px}.termgrip:hover{opacity:1}.termbar{color:var(--dim);border-bottom:1px solid var(--line);background:var(--bg-darkest);justify-content:space-between;align-items:center;padding:4px 10px;font-size:11.5px;display:flex}.termtabs{flex:1;align-items:center;gap:2px;min-width:0;display:flex;overflow-x:auto}.termtab{cursor:pointer;color:var(--dim);white-space:nowrap;background:var(--bg-mid);border-radius:5px;align-items:center;gap:6px;padding:2px 8px;font-size:11.5px;display:inline-flex}.termtab.active{color:var(--fg);outline:1px solid var(--acc)}.termtab:hover{filter:brightness(1.15)}.tabx{color:inherit;opacity:.5;cursor:pointer;background:0 0;border:none;padding:0;font-size:10px}.tabx:hover{opacity:1;color:var(--err)}.termbody{background:var(--term-bg);flex:1;gap:4px;min-height:0;padding:4px;display:flex}.termbody.split .termpane{width:50%}.termpane{background:var(--term-bg);border-radius:6px;flex:1;min-width:0;position:relative;overflow:hidden}.termpane:not(.focused){opacity:.9}.termpane.focused{box-shadow:inset 0 0 0 2px var(--acc)}.termhost{position:absolute;inset:0}.termsession{padding:4px 6px;position:absolute;inset:0}.termsplit{background:var(--line);cursor:col-resize;border-radius:2px;flex-shrink:0;width:3px}.termempty{color:var(--dim);place-items:center;font-size:12px;display:grid;position:absolute;inset:0}.jump{background:var(--acc);color:#fff;cursor:pointer;z-index:2;border:none;border-radius:999px;padding:6px 14px;font-size:12.5px;font-weight:600;position:absolute;top:-34px;left:50%;transform:translate(-50%);box-shadow:0 4px 14px #0008}body:has(.termdrawer) .jump{top:auto;bottom:calc(var(--termh,300px) + 56px);left:50%}.divider-msg{color:var(--dim);align-items:center;gap:10px;padding:4px 18px;font-size:11.5px;display:flex}.divider-msg:before,.divider-msg:after{content:"";background:var(--line);flex:1;height:1px}.divider-msg.err{color:var(--err)}.divider-msg.compacting{color:var(--acc);animation:1.6s ease-in-out infinite pulse}.goalline{color:var(--dim);padding:4px 18px;font-size:11.5px}.goalline-label{color:var(--dim);display:block}.goalline.warn .goalline-label{color:var(--warn)}.goalline.err .goalline-label{color:var(--err)}.goalline .card{text-align:left;margin-top:6px}.day-divider{align-items:center;gap:10px;padding:14px 18px 6px;display:flex}.day-divider:before,.day-divider:after{content:"";background:var(--bg-light);flex:1;height:1px}.day-divider span{color:var(--dim);font-size:11px}.composer{padding:0 16px 18px;position:relative}.composer form{background:var(--bg-light);border-radius:10px;align-items:flex-end;gap:8px;padding:10px 12px;display:flex}.composer textarea{color:var(--fg);font:inherit;resize:none;background:0 0;border:none;outline:none;flex:1;max-height:160px;line-height:1.4;overflow-y:auto}.cmds{background:var(--bg-mid);border:1px solid var(--bg-light);z-index:3;border-radius:8px;position:absolute;bottom:calc(100% - 8px);left:16px;right:16px;overflow:hidden;box-shadow:0 -6px 20px #0007}.cmdrow{cursor:pointer;align-items:baseline;gap:10px;padding:7px 12px;font-size:13.5px;display:flex}.cmdrow:hover{background:var(--bg-light)}.cmdrow.active{background:var(--acc);color:#fff}.cmdrow.active .muted{color:#e6e9ff}.cmdrow .muted{font-size:12px}.composer button{background:var(--acc);color:#fff;cursor:pointer;border:none;border-radius:8px;padding:7px 14px;font-weight:600}.composer button:hover{opacity:.9}.composer label{color:var(--dim);white-space:nowrap;align-items:center;gap:4px;font-size:12px;display:flex}.hint{color:var(--dim);margin-top:5px;font-size:11px}.rightbarbackdrop{z-index:4;background:#0004;display:none;position:fixed;inset:0}.rightbarhead{background:var(--bg-dark);border-bottom:1px solid var(--line);justify-content:space-between;align-items:center;gap:8px;margin:-14px -14px 0;padding:10px 14px;display:none}.rightbarhead .muted{text-transform:uppercase;letter-spacing:.04em;font-size:11px}.rightbar{background:var(--bg-dark);border-left:2px solid var(--line);scrollbar-gutter:stable;flex-direction:column;min-height:0;padding:14px;font-size:13px;display:flex;overflow-y:auto}.rightbar>*{flex-shrink:0}.rightbar h3{text-transform:uppercase;letter-spacing:.04em;color:var(--dim);margin:14px 0 6px;font-size:11px}.rightbar h3:first-of-type{margin-top:0}.card{background:var(--bg-darkest);white-space:pre-wrap;word-break:break-word;border-radius:8px;max-height:200px;padding:10px;overflow-y:auto}.card.runcard{max-height:none;overflow-y:visible}.muted{color:var(--dim)}.prog .progrow{gap:8px;margin-bottom:4px;display:flex}.prog .progrow b{color:var(--dim);text-transform:uppercase;letter-spacing:.05em;flex-shrink:0;min-width:62px;padding-top:2px;font-size:10px}.embed .progrow{gap:8px;margin-bottom:4px;display:flex}.embed .progrow b{color:var(--dim);text-transform:uppercase;letter-spacing:.05em;flex-shrink:0;min-width:62px;padding-top:2px;font-size:10px}.embed .progrow span{min-width:0}.inline-md{display:inline}.inline-md>:first-child{margin-top:0}.inline-md>:last-child{margin-bottom:0}.prog .progrow.warn span{color:var(--err)}.msg-head .editbtn{color:var(--dim);cursor:pointer;opacity:0;background:0 0;border:none;padding:0 2px;font-size:11px;transition:opacity .12s}.msg:hover .msg-head .editbtn,.msg.pending .msg-head .editbtn{opacity:1}.msg-head .editbtn:focus-visible{opacity:1;outline:2px solid var(--acc);outline-offset:1px}.msg-head .editbtn:hover{color:var(--acc)}.branch-row{color:var(--dim);cursor:pointer;justify-content:space-between;padding:3px 0;font-size:12px;display:flex}.branch-row:hover,.branch-row.cur{color:var(--fg)}.mini-cron{opacity:.75;margin-left:auto;font-size:10px}.sched-row{cursor:pointer;border-radius:6px;margin-bottom:2px;padding:6px 8px}.sched-row:hover,.sched-row.cur{background:var(--bg-mid)}.sched-top{align-items:baseline;gap:6px;font-size:12.5px;display:flex}.sched-row .sched-meta{color:var(--dim);margin-top:2px;font-size:11px}.sched-row .sched-prompt{color:var(--dim);text-overflow:ellipsis;white-space:nowrap;margin-top:2px;font-size:11.5px;overflow:hidden}.badge.cron{color:var(--tool);white-space:nowrap;background:#3ba0c91a;border:1px solid #3ba0c944}.sesscard{flex-direction:column;gap:6px;font-size:12.5px;display:flex}.sessrow{align-items:center;gap:8px;display:flex}.filebox{background:var(--bg-darkest);border-radius:8px;height:260px;padding:4px;overflow-y:auto}.filerow{cursor:pointer;color:var(--fg);border-radius:4px;align-items:center;gap:6px;padding:3px 8px;font-size:12.5px;display:flex}.filerow:hover{background:var(--bg-mid)}.filerow .ficon{width:10px;color:var(--dim);text-align:center;flex-shrink:0;font-size:9px}.filerow.isdir .fname{font-weight:600}.fname{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.fsize{color:var(--dim);flex-shrink:0;margin-left:auto;font-size:10px}.sessrow .k{color:var(--dim);text-transform:uppercase;letter-spacing:.05em;flex-shrink:0;width:74px;font-size:10px}.ellip{text-overflow:ellipsis;white-space:nowrap;text-align:left;direction:rtl;overflow:hidden}.modelbox{background:var(--bg-darkest);border-radius:8px;flex-direction:column;gap:6px;padding:10px;display:flex}.modelbox select,.modelbox input[type=text]{background:var(--bg-mid);color:var(--fg);font:inherit;border:none;border-radius:6px;outline:none;min-width:0;padding:6px 8px}.modelbox button{background:var(--acc);color:#fff;cursor:pointer;white-space:nowrap;border:none;border-radius:6px;padding:6px 10px;font-size:12.5px;font-weight:600}.modelbox button:hover{opacity:.9}.modelbox .meta{color:var(--dim);font-size:11px}.btnrow{gap:6px;margin:8px 0;display:flex}.btnrow button{background:var(--bg-light);color:var(--fg);cursor:pointer;border:none;border-radius:6px;padding:6px 10px;font-size:13px}.btnrow button:hover{filter:brightness(1.2)}.btnrow .runbtn{background:var(--ok);color:#fff;font-weight:600}.btnrow .runbtn,.btnrow .danger{min-width:74px}.btnrow .danger{background:var(--err);color:#fff;font-weight:600}.ctrlrow{align-items:center;gap:8px;margin-top:6px;font-size:12.5px;display:flex}.ctrlrow label{cursor:pointer;color:var(--fg);white-space:nowrap;align-items:center;gap:5px;display:flex}.ctrlrow .muted{font-size:11.5px}.goalstate{background:var(--bg-light);color:var(--fg);cursor:pointer;border:none;border-radius:6px;padding:3px 10px;font-size:12px}.goalstate.on.active{background:var(--ok);color:#fff;font-weight:600}.goalstate.on.done{background:var(--acc);color:#fff;font-weight:600}.goalstate.on.paused{background:var(--warn);color:#fff;font-weight:600}.goalstate:disabled{cursor:default;filter:none}.verifycard{border-left:3px solid var(--tool);margin-top:6px}.auditcard{border-left:3px solid var(--warn);margin-top:6px}.auditcard.ok{border-left-color:var(--ok)}.vtitle{color:var(--dim);text-transform:uppercase;letter-spacing:.04em;align-items:center;gap:6px;margin-bottom:4px;font-size:12px;font-weight:600;display:flex}.iconbtn{background:var(--bg-light);color:var(--fg);cursor:pointer;border:none;border-radius:6px;flex:none;justify-content:center;align-self:flex-end;align-items:center;width:26px;height:24px;padding:0;font-size:13px;display:inline-flex}.iconbtn-glyph{justify-content:center;align-items:center;width:100%;height:100%;line-height:1;display:inline-flex}.iconbtn:hover{filter:brightness(1.3)}.iconbtn.active{background:var(--acc);color:#fff}.overlay{z-index:10;background:#0009;place-items:center;display:grid;position:fixed;inset:0}.modal{background:var(--bg-mid);border-radius:10px;width:min(620px,92vw);max-height:88vh;padding:16px 18px;overflow-y:auto}.modal-head{justify-content:space-between;align-items:center;margin-bottom:12px;font-size:16px;display:flex}.modal label{color:var(--dim);flex-direction:column;gap:4px;font-size:12.5px;display:flex}.modal input[type=text],.modal input[type=number],.modal input[type=password],.modal input[type=url],.modal input[type=email],.modal select,.modal textarea{background:var(--bg-darkest);color:var(--fg);font:inherit;border:1px solid #0000;border-radius:6px;outline:none;min-width:0;padding:7px 9px}.modal input:focus,.modal select:focus,.modal textarea:focus{border-color:var(--acc)}.modal ::placeholder{color:#7c818f;opacity:1}.modal select option{background:var(--bg-darkest);color:var(--fg)}.modal input.compact{padding:5px 8px;font-size:12.5px}.modal textarea{resize:vertical}.w100{width:100%}.mono{font-family:ui-monospace,Menlo,monospace;font-size:13px}.modal fieldset{border:1px solid var(--bg-light);border-radius:8px;margin:0 0 4px;padding:10px}.modal fieldset legend{color:var(--dim);text-transform:uppercase;letter-spacing:.05em;padding:0 6px;font-size:11px}.cfgrow{flex-wrap:wrap;align-items:center;gap:6px;margin-bottom:6px;display:flex}.cfgrow input{background:var(--bg-darkest);border:1px solid var(--bg-light);color:var(--fg);border-radius:5px;flex:1;min-width:0;padding:5px 8px;font-size:12.5px}.cfgrow select{background:var(--bg-darkest);border:1px solid var(--bg-light);color:var(--fg);border-radius:5px;padding:5px 8px;font-size:12.5px}.cfgrow .cfgname{width:90px;color:var(--warn);flex:none;font-weight:600}.cfgrow button{background:var(--bg-mid);border:1px solid var(--bg-light);color:var(--fg);cursor:pointer;border-radius:5px;padding:4px 8px;font-size:12px}.cfgrow button:hover{background:var(--bg-light)}.cfgrow button.danger{background:var(--err);border-color:var(--err);color:#fff}.cfggrid{grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:8px;display:grid}.cfggrid label,.cfgcol label{color:var(--dim);flex-direction:column;gap:3px;font-size:11px;display:flex}.cfggrid input{background:var(--bg-darkest);border:1px solid var(--bg-light);color:var(--fg);border-radius:5px;width:100%;padding:5px 8px}.cfgcol{margin-bottom:8px}.cfgcol textarea{background:var(--bg-darkest);border:1px solid var(--bg-light);color:var(--fg);font:inherit;border-radius:5px;width:100%;margin-top:4px;padding:5px 8px;font-size:12.5px}.presetbtn{background:var(--bg-light);color:var(--fg);cursor:pointer;border:1px solid #0000;border-radius:6px;flex:1;padding:7px 10px;font-size:13px}.presetbtn.active{background:var(--acc);color:#fff}.forkchip{white-space:nowrap;color:var(--dim);cursor:pointer;align-items:center;gap:4px;font-size:11.5px;display:flex}.dirlist{background:var(--bg-darkest);border-radius:6px;max-height:160px;padding:4px;overflow-y:auto}.direntry{cursor:pointer;border-radius:4px;padding:4px 8px;font-size:14px}.direntry:hover{background:var(--bg-light)}.filepreview{border-radius:8px;max-height:62vh;overflow:auto}.filetoolbar{gap:6px;margin-bottom:8px;display:flex}.filetoolbar button{background:var(--bg-light);color:var(--dim);cursor:pointer;border:none;border-radius:6px;padding:4px 12px;font-size:12.5px}.filetoolbar button:hover{color:var(--fg);filter:brightness(1.15)}.filetoolbar button.on{background:var(--acc);color:#fff;font-weight:600}.fileeditor{flex-direction:column;gap:8px;display:flex}.fileeditor textarea{background:var(--bg-darkest);min-height:55vh;max-height:65vh;color:var(--fg);border:1px solid var(--bg-light);white-space:pre;border-radius:8px;padding:10px;font-size:12.5px;line-height:1.45;overflow:auto}.filerow-actions{justify-content:flex-end;align-items:center;gap:10px;display:flex}.savebtn{background:var(--ok);color:#fff;cursor:pointer;border:none;border-radius:6px;padding:5px 14px;font-size:13px;font-weight:600}.savebtn:disabled{opacity:.4;cursor:default}.mdpreview{background:var(--bg-darkest);border-radius:8px;max-height:62vh;padding:14px 16px;overflow:auto}.filepreview .shiki,.filepreview .shiki span{color:var(--shiki-light);font-family:ui-monospace,Menlo,monospace;font-size:12.5px}html[data-appearance=dark] .filepreview .shiki,html[data-appearance=dark] .filepreview .shiki span{color:var(--shiki-dark)}.filepreview .shiki{background-color:var(--shiki-dark-bg);white-space:pre-wrap;word-break:break-word;overflow-wrap:anywhere;margin:0;padding:10px 12px;font-size:12.5px}html[data-appearance=light] .filepreview .shiki{background-color:var(--shiki-light-bg)}.notifbtn{position:relative}.notifbtn.has-unread{color:var(--acc)}.notifdot{background:var(--err);color:#fff;border-radius:999px;padding:2px 4px;font-size:9px;font-style:normal;font-weight:700;line-height:1;position:absolute;top:-4px;right:-4px}.brand-row{align-items:center;margin-top:2px;display:flex}.notifbackdrop{z-index:7;position:fixed;inset:0}.notifpanel{z-index:8;background:var(--bg-mid);border:1px solid var(--bg-light);border-radius:10px;width:min(360px,88vw);position:absolute;bottom:8px;left:8px;overflow:hidden;box-shadow:0 8px 30px #000a}.notifhead{border-bottom:1px solid var(--line);text-transform:uppercase;letter-spacing:.04em;color:var(--dim);justify-content:space-between;align-items:center;padding:8px 12px;font-size:11px;display:flex}.notiflist{max-height:46vh;overflow-y:auto}.notifitem{border-bottom:1px solid var(--line);cursor:pointer;padding:8px 12px}.notifitem:last-child{border-bottom:none}.notifitem:hover{background:var(--bg-light)}.notifitem .nhead{align-items:baseline;gap:6px;min-width:0;display:flex}.notifitem .ntitle{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;font-size:13px;font-weight:600;overflow:hidden}.notifitem.error .ntitle{color:var(--err)}.notifitem.finish .ntitle{color:var(--ok)}.notifitem.question .ntitle{color:var(--acc)}.notifitem .nbody{color:var(--dim);word-break:break-word;margin-top:3px;font-size:12px}.subcount{color:var(--dim);background:var(--bg-light);white-space:nowrap;border-radius:999px;flex-shrink:0;padding:1px 7px;font-size:10px}.subcount.live{color:var(--ok)}.mediapreview{flex-direction:column;align-items:center;gap:8px;display:flex}.mediapreview img{background:var(--bg-darkest);border-radius:8px;max-width:100%;max-height:65vh}.mediapreview video{background:#000;border-radius:8px;max-width:100%;max-height:65vh}.mediapreview audio{width:100%}.composer{flex-direction:column;display:flex}.composer .hint{flex-shrink:0}.composer.maximized{z-index:5;background:var(--bg-dark);padding:16px 16px 18px;position:absolute;inset:0}.composer.maximized:before{content:"";background:var(--bg-dark);z-index:-1;position:absolute;inset:0}.composer.maximized form{flex:1;align-items:stretch;min-height:0}.composer.maximized textarea{resize:none;flex:1;max-height:none;height:auto!important}.composer.maximized .maxbtn,.composer.maximized form>button[type=submit]{align-self:flex-end}.maxbtn{justify-content:center;align-items:center;font-size:12px;line-height:1;display:inline-flex;padding:0!important}.filerow.gitignored .fname,.filerow.gitignored .ficon,.filerow.gitignored .fsize{opacity:.38}.embed.compaction{border-left-color:var(--tool)}.embed.compaction summary .meta{color:var(--tool)}.avatar.ghosted{opacity:.35;transition:opacity .15s}.msg:hover .avatar.ghosted{opacity:1}.grouptime{display:none}.notifitem{opacity:1}.notifitem.read{opacity:.55}.notifitem.read .ntitle{font-weight:400}.nreadbtn{flex-shrink:0;width:auto;padding:0 6px;font-size:11px}.flash-target{outline:2px solid var(--acc);border-radius:8px;transition:outline-color .6s}.msg.flash-target{background:color-mix(in srgb, var(--acc) 12%, transparent)}.agent-item .ghost{opacity:.55}.ghosttag{flex-shrink:0;font-size:10px}.filetoggle{text-align:center;flex-shrink:0;width:26px;padding:0}h3 .filetoggle{margin-left:0}.notifbadge{color:var(--acc);background:var(--bg-light);white-space:nowrap;border-radius:999px;flex-shrink:0;margin-left:auto;padding:1px 6px;font-size:10px}.agent-item.sel .notifbadge{background:var(--bg-darkest)}input[type=checkbox]{background-color:var(--bg-darkest);border:1px solid var(--dim);border-radius:3px}input[type=number]{appearance:textfield}input[type=number]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}input[type=number]::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}input[type=number]{-moz-appearance:textfield}.modal>button,.modal button:not(.iconbtn):not([class]){background:var(--bg-light);color:var(--fg);border:1px solid var(--dim);font:inherit;cursor:pointer;border-radius:6px;padding:6px 10px}.modal>button:hover,.modal button:not(.iconbtn):not([class]):hover{background:var(--bg-mid);border-color:var(--acc)}.modal>button:focus-visible,.modal button:not(.iconbtn):not([class]):focus-visible{outline:2px solid var(--acc);outline-offset:1px}.todopane,.todopane-edit{box-sizing:border-box;background:var(--bg-darkest);width:100%;height:11.5em;min-height:7em;max-height:40vh;color:var(--fg);resize:vertical;border:none;border-radius:6px;padding:6px 8px;font-family:ui-monospace,Menlo,monospace;font-size:12.5px;line-height:1.45;display:block;overflow-y:auto}.xterm{cursor:text;-webkit-user-select:none;user-select:none;position:relative}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{z-index:5;position:absolute;top:0}.xterm .xterm-helper-textarea{opacity:0;z-index:-5;white-space:nowrap;resize:none;border:0;width:0;height:0;margin:0;padding:0;position:absolute;top:0;left:-9999em;overflow:hidden}.xterm .composition-view{color:#fff;white-space:nowrap;z-index:1;background:#000;display:none;position:absolute}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{cursor:default;background-color:#000;position:absolute;inset:0;overflow-y:scroll}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;top:0;left:0}.xterm-char-measure-element{visibility:hidden;line-height:normal;display:inline-block;position:absolute;top:0;left:-9999em}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{z-index:10;color:#0000;pointer-events:none;position:absolute;inset:0}.xterm .xterm-accessibility-tree:not(.debug) ::selection{color:#0000}.xterm .xterm-accessibility-tree{-webkit-user-select:text;user-select:text;white-space:pre;font-family:monospace}.xterm .xterm-accessibility-tree>div{transform-origin:0;width:fit-content}.xterm .live-region{width:1px;height:1px;position:absolute;left:-9999px;overflow:hidden}.xterm-dim{opacity:1!important}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{-webkit-text-decoration:underline double;text-decoration:underline double}.xterm-underline-3{-webkit-text-decoration:underline wavy;text-decoration:underline wavy}.xterm-underline-4{-webkit-text-decoration:underline dotted;text-decoration:underline dotted}.xterm-underline-5{-webkit-text-decoration:underline dashed;text-decoration:underline dashed}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:underline overline}.xterm-overline.xterm-underline-2{-webkit-text-decoration:overline double underline;text-decoration:overline double underline}.xterm-overline.xterm-underline-3{-webkit-text-decoration:overline wavy underline;text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{-webkit-text-decoration:overline dotted underline;text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{-webkit-text-decoration:overline dashed underline;text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;pointer-events:none;position:absolute;top:0;right:0}.xterm-decoration-top{z-index:2;position:relative}.xterm .xterm-scrollable-element>.scrollbar{cursor:default}.xterm .xterm-scrollable-element>.scrollbar>.scra{cursor:pointer;font-size:11px!important}.xterm .xterm-scrollable-element>.visible{opacity:1;z-index:11;background:0 0;transition:opacity .1s linear}.xterm .xterm-scrollable-element>.invisible{opacity:0;pointer-events:none}.xterm .xterm-scrollable-element>.invisible.fade{transition:opacity .8s linear}.xterm .xterm-scrollable-element>.shadow{display:none;position:absolute}.xterm .xterm-scrollable-element>.shadow.top{width:100%;height:3px;box-shadow:var(--vscode-scrollbar-shadow,#000) 0 6px 6px -6px inset;display:block;top:0;left:3px}.xterm .xterm-scrollable-element>.shadow.left{width:3px;height:100%;box-shadow:var(--vscode-scrollbar-shadow,#000) 6px 0 6px -6px inset;display:block;top:3px;left:0}.xterm .xterm-scrollable-element>.shadow.top-left-corner{width:3px;height:3px;display:block;top:0;left:0}.xterm .xterm-scrollable-element>.shadow.top.left{box-shadow:var(--vscode-scrollbar-shadow,#000) 6px 0 6px -6px inset}
|