teapot-coding-agent 0.8.0 → 0.9.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 CHANGED
@@ -108,12 +108,17 @@ master (Hono server, src/master.ts + src/server/api.ts)
108
108
  - **LLM** (`src/agent/llm.ts`): official `openai` npm client against any
109
109
  OpenAI-compatible endpoint (OpenRouter, vLLM, Ollama...). Model is config,
110
110
  never hard-coded.
111
- - **Tools** (`src/agent/tools.ts`): provider-agnostic JSON-schema function
112
- specs `read_file`, `write_file`, `edit_file`, `list_dir`, `bash` (git goes
113
- through bash), plus meta tools `finish` / `report_progress` / `get_goal` /
114
- `set_goal` / `read_memory` / `set_memory` / `list_skills`. Paths are
115
- confined to the workspace; bash runs detached in its own process group and
116
- the whole group is SIGKILLed on timeout.
111
+ - **Tools** (`src/agent/tools.ts`): provider-agnostic JSON-schema function specs —
112
+ file work via `read_file` (numbered lines, grep-style `pattern` mode, negative
113
+ offsets), `write_file`, `edit_file` (unique replacement, `replace_all`,
114
+ whitespace-tolerant fallbacks with recovery hints), `apply_patch`
115
+ (Codex-style multi-file add/update/rename/delete patches, validated
116
+ atomically before writing) and `list_dir`; `bash` for git/builds/tests and
117
+ quick bulk transforms; `read_url` fetches a web page's readable content
118
+ (Mozilla Readability + happy-dom); plus meta tools `finish` /
119
+ `report_progress` / `get_goal` / `set_goal` / `read_memory` / `set_memory` /
120
+ `list_skills`. Paths are confined to the workspace; bash runs detached in its
121
+ own process group and the whole group is SIGKILLed on timeout or shutdown.
117
122
  - **Cache-friendly prompt design** — the system prompt is byte-identical on
118
123
  every turn; session state (goal, memory, skills) is fetched via tools, never
119
124
  injected. Combined with the append-only message history this keeps provider
@@ -33,6 +33,12 @@ Session state is not injected into prompts — fetch it with tools instead:
33
33
 
34
34
  ## Rules
35
35
  - Work step by step with tools. Verify results (run tests/builds) before claiming progress.
36
+ - File changes — pick by scope: write_file (one new file / full rewrite) ·
37
+ edit_file (exactly one small unique replacement) · apply_patch (several
38
+ edits, renames or deletes across one or more files, applied atomically).
39
+ read_file numbers lines and can grep via its pattern option. bash
40
+ text-munging (sed/awk/heredoc) remains available for quick bulk transforms
41
+ when that is genuinely faster.
36
42
  - When a loaded skill matches your task, follow its playbook.
37
43
  - When you make meaningful progress, call report_progress.
38
44
  - Be frugal: prefer small precise edits, avoid runaway loops.`;
@@ -56,9 +62,18 @@ export class Agent {
56
62
  };
57
63
  opts;
58
64
  messages = [];
65
+ /**
66
+ * User prompts waiting for the next turn boundary. Deliberately NOT queued
67
+ * on runChain: that chain holds the long-running loop, so queueing behind
68
+ * it would delay both the log entry (UI) and delivery until the round —
69
+ * sometimes the whole goal — finished.
70
+ */
71
+ pendingPrompts = [];
59
72
  stopRequested = false;
60
73
  wake = null;
61
74
  abort = null;
75
+ /** aborted only by dispose(): kills in-flight subprocess groups instantly */
76
+ toolAbort = new AbortController();
62
77
  runChain = Promise.resolve();
63
78
  lastProgressAt = Date.now();
64
79
  consecutiveToolErrors = 0;
@@ -84,6 +99,7 @@ export class Agent {
84
99
  defaultTimeoutMs: 120_000,
85
100
  maxOutputBytes: 60_000,
86
101
  skillRoots: this.skillRoots,
102
+ signal: this.toolAbort.signal,
87
103
  };
88
104
  // the session id IS the directory name — one directory per incarnation
89
105
  this.mainSession = path.basename(opts.sessionDir);
@@ -195,10 +211,29 @@ export class Agent {
195
211
  while (lineage.length && lineage[0].type === "fork")
196
212
  lineage.shift();
197
213
  const msgs = [];
214
+ // Prompts are logged the moment the user hits send — which can be while a
215
+ // tool batch is still open. Replaying them verbatim would slot a user
216
+ // message BETWEEN an assistant tool_call and its tool_result (API-invalid),
217
+ // so hold them until the open batch is answered, like live delivery does.
218
+ const META_TOOLS = new Set([
219
+ "finish", "report_progress", "set_goal", "get_goal",
220
+ "read_memory", "set_memory", "list_skills",
221
+ ]);
222
+ const openCalls = new Map(); // real tool_call id -> name
223
+ const bufferedUsers = [];
224
+ const flushUsers = () => {
225
+ if (openCalls.size === 0) {
226
+ for (const text of bufferedUsers.splice(0))
227
+ msgs.push({ role: "user", content: text });
228
+ }
229
+ };
198
230
  for (const e of lineage) {
199
231
  const d = e.data;
200
232
  if (e.type === "prompt" && typeof d.text === "string") {
201
- msgs.push({ role: "user", content: d.text });
233
+ if (openCalls.size > 0)
234
+ bufferedUsers.push(d.text);
235
+ else
236
+ msgs.push({ role: "user", content: d.text });
202
237
  }
203
238
  else if (e.type === "message") {
204
239
  const role = d.role === "assistant" ? "assistant" : "user";
@@ -209,6 +244,11 @@ export class Agent {
209
244
  type: "function",
210
245
  function: { name: c.name, arguments: "{}" },
211
246
  }));
247
+ // meta tools are answered inline by the harness (no logged result);
248
+ // the hole-filling pass below synthesizes theirs where they belong
249
+ for (const t of m.tool_calls)
250
+ if (!META_TOOLS.has(t.function.name))
251
+ openCalls.set(t.id, t.function.name);
212
252
  }
213
253
  msgs.push(m);
214
254
  }
@@ -225,6 +265,8 @@ export class Agent {
225
265
  tool_call_id: String(d.callId ?? ""),
226
266
  content: `${d.ok === false ? "(failed) " : ""}${typeof d.result === "string" ? d.result : ""}`,
227
267
  });
268
+ openCalls.delete(String(d.callId ?? ""));
269
+ flushUsers();
228
270
  }
229
271
  else if (e.type === "progress") {
230
272
  // progress events may follow an assistant report_progress call that
@@ -235,7 +277,9 @@ export class Agent {
235
277
  if (!msgs.some((x) => x.role === "tool" && x.tool_call_id === t.id)) {
236
278
  msgs.push({ role: "tool", tool_call_id: t.id, content: "progress recorded" });
237
279
  }
280
+ openCalls.delete(t.id);
238
281
  }
282
+ flushUsers();
239
283
  }
240
284
  }
241
285
  }
@@ -256,6 +300,9 @@ export class Agent {
256
300
  }
257
301
  }
258
302
  }
303
+ // prompts that were still waiting on a hole-filled tail land here
304
+ for (const text of bufferedUsers.splice(0))
305
+ msgs.push({ role: "user", content: text });
259
306
  if (msgs.length > 0) {
260
307
  this.messages = msgs;
261
308
  this.currentBranch = last.branch;
@@ -316,14 +363,27 @@ export class Agent {
316
363
  model: this.opts.llm.model,
317
364
  provider: this.opts.provider,
318
365
  sessionDir: this.opts.sessionDir,
366
+ pendingPrompts: this.pendingPrompts.length,
319
367
  };
320
368
  }
321
- /** Queue a user prompt; wakes the loop if needed. Returns immediately. */
369
+ /**
370
+ * Queue a user prompt. Returns immediately: the event is logged right away
371
+ * (so every connected UI sees it instantly) and the text is handed to the
372
+ * model at the next turn boundary — never mid-turn, and never blocked by
373
+ * the running loop.
374
+ */
322
375
  enqueuePrompt(text, source = "user") {
323
- return this.enqueue(async () => {
324
- await this.log.append("prompt", this.currentSession, this.currentBranch, { source, text });
325
- this.messages.push({ role: "user", content: text });
326
- });
376
+ this.pendingPrompts.push({ source, text });
377
+ void this.log
378
+ .append("prompt", this.currentSession, this.currentBranch, { source, text })
379
+ .then(() => bus.emit("update", { kind: "agent-update", agentId: this.opts.id }))
380
+ .catch(() => { });
381
+ }
382
+ /** Hand queued user prompts to the model at a turn boundary. */
383
+ drainPendingPrompts() {
384
+ for (const p of this.pendingPrompts.splice(0)) {
385
+ this.messages.push({ role: "user", content: p.text });
386
+ }
327
387
  }
328
388
  /** Resolves when all queued work (including a running loop) has settled. */
329
389
  settled() {
@@ -372,9 +432,16 @@ export class Agent {
372
432
  while (!this.stopRequested) {
373
433
  try {
374
434
  const finished = await this.runTurnsUntilIdle();
375
- if (finished || this.stopRequested)
435
+ if (this.stopRequested)
376
436
  break;
377
- if (!this.opts.autoContinue || this.goal.status !== "active")
437
+ // fresh user input arrived while we were finishing up — another round now
438
+ if (this.pendingPrompts.length)
439
+ continue;
440
+ // auto-continue only makes sense with an active goal to continue toward
441
+ if (finished ||
442
+ !this.opts.autoContinue ||
443
+ this.goal.status !== "active" ||
444
+ !this.goal.text.trim())
378
445
  break;
379
446
  // auto-continue: wait quietly, then nudge with a fresh round
380
447
  await this.sleepInterruptible(this.opts.continueDelayMs);
@@ -458,6 +525,8 @@ export class Agent {
458
525
  for (let guard = 0; guard < 200; guard++) {
459
526
  if (this.stopRequested)
460
527
  return finished;
528
+ // deliver prompts queued while the previous turn was running
529
+ this.drainPendingPrompts();
461
530
  // skills may have been created last turn — refresh the prompt listing
462
531
  await this.refreshSkills();
463
532
  // periodic progress report at turn boundary (no mid-turn interruption)
@@ -764,6 +833,9 @@ export class Agent {
764
833
  }
765
834
  async dispose() {
766
835
  this.stop("disposed");
836
+ // kill any in-flight subprocess group NOW so shutdown never waits out a
837
+ // long-running command (up to 10 min otherwise)
838
+ this.toolAbort.abort();
767
839
  await this.runChain.catch(() => { });
768
840
  await this.log.close();
769
841
  }
@@ -3,7 +3,7 @@
3
3
  * Tool specs are plain JSON-schema function definitions — provider-agnostic.
4
4
  */
5
5
  import { spawn } from "node:child_process";
6
- import { promises as fs } from "node:fs";
6
+ import { existsSync, promises as fs } from "node:fs";
7
7
  import path from "node:path";
8
8
  import { discoverSkills, isValidSkillName, readSkillFile, saveSkill, } from "./skills.js";
9
9
  const str = (v, fallback = "") => (typeof v === "string" ? v : fallback);
@@ -36,7 +36,7 @@ function runShell(cmd, ctx, timeoutMs) {
36
36
  });
37
37
  let out = "";
38
38
  let done = false;
39
- let timedOut = false;
39
+ let killReason = null;
40
40
  const collect = (chunk) => {
41
41
  if (out.length < ctx.maxOutputBytes)
42
42
  out += chunk.toString("utf8");
@@ -53,11 +53,23 @@ function runShell(cmd, ctx, timeoutMs) {
53
53
  }
54
54
  };
55
55
  const timer = setTimeout(() => {
56
- timedOut = true;
56
+ killReason = `TIMEOUT after ${timeoutMs}ms`;
57
57
  killGroup();
58
58
  }, timeoutMs);
59
+ // harness shutdown must not wait out a long-running command
60
+ const onAbort = () => {
61
+ killReason = "ABORTED (harness shutdown)";
62
+ killGroup();
63
+ };
64
+ if (ctx.signal) {
65
+ if (ctx.signal.aborted)
66
+ onAbort();
67
+ else
68
+ ctx.signal.addEventListener("abort", onAbort, { once: true });
69
+ }
59
70
  child.on("error", (err) => {
60
71
  clearTimeout(timer);
72
+ ctx.signal?.removeEventListener("abort", onAbort);
61
73
  if (!done) {
62
74
  done = true;
63
75
  resolve({ ok: false, result: `spawn error: ${err.message}` });
@@ -65,13 +77,14 @@ function runShell(cmd, ctx, timeoutMs) {
65
77
  });
66
78
  child.on("close", (code, signal) => {
67
79
  clearTimeout(timer);
80
+ ctx.signal?.removeEventListener("abort", onAbort);
68
81
  if (done)
69
82
  return;
70
83
  done = true;
71
- if (timedOut) {
84
+ if (killReason) {
72
85
  resolve({
73
86
  ok: false,
74
- result: `TIMEOUT after ${timeoutMs}ms. Partial output:\n${clip(out.trim() || "(no output)", ctx.maxOutputBytes)}`,
87
+ result: `${killReason}. Partial output:\n${clip(out.trim() || "(no output)", ctx.maxOutputBytes)}`,
75
88
  });
76
89
  return;
77
90
  }
@@ -83,17 +96,328 @@ function runShell(cmd, ctx, timeoutMs) {
83
96
  });
84
97
  });
85
98
  }
99
+ /** 1-based line number of each occurrence of needle in text. */
100
+ function matchLines(text, needle) {
101
+ const out = [];
102
+ let idx = text.indexOf(needle);
103
+ while (idx !== -1) {
104
+ out.push(text.slice(0, idx).split("\n").length);
105
+ idx = text.indexOf(needle, idx + Math.max(needle.length, 1));
106
+ }
107
+ return out;
108
+ }
109
+ /**
110
+ * Fuzzy-but-safe locator: find windows of lines equal to the pattern after
111
+ * trimming trailing whitespace on each side. Returns 0-based start line hits.
112
+ */
113
+ function trailingWsMatches(srcLines, patLines) {
114
+ const hits = [];
115
+ for (let i = 0; i + patLines.length <= srcLines.length; i++) {
116
+ let ok = true;
117
+ for (let j = 0; j < patLines.length; j++) {
118
+ if (srcLines[i + j].trimEnd() !== patLines[j].trimEnd()) {
119
+ ok = false;
120
+ break;
121
+ }
122
+ }
123
+ if (ok)
124
+ hits.push(i);
125
+ }
126
+ return hits;
127
+ }
86
128
  export const DEFAULT_TIMEOUT_MS = 120_000;
129
+ /* ---------- read_url cache ---------- */
130
+ const URL_CACHE_TTL_MS = 3_600_000;
131
+ const urlCache = new Map();
132
+ function clipText(s, max) {
133
+ const n = Math.max(1000, Math.min(max, 80_000));
134
+ return s.length <= n ? s : `${s.slice(0, n)}\n… [truncated, ${s.length} chars total]`;
135
+ }
136
+ function compileRegex(pattern, ignoreCase) {
137
+ try {
138
+ return new RegExp(pattern, ignoreCase ? "i" : "");
139
+ }
140
+ catch (e) {
141
+ return `invalid regex: ${e.message}`;
142
+ }
143
+ }
144
+ /** Codex seek_sequence: find pattern lines at/after `start`, loosening match rules stepwise. */
145
+ function seekSequence(lines, pattern, start, eof) {
146
+ if (pattern.length === 0)
147
+ return start;
148
+ if (pattern.length > lines.length)
149
+ return null;
150
+ const searchStart = eof && lines.length >= pattern.length ? Math.max(start, lines.length - pattern.length) : start;
151
+ const eqExact = (a, b) => a === b;
152
+ const eqRstrip = (a, b) => a.trimEnd() === b.trimEnd();
153
+ const eqTrim = (a, b) => a.trim() === b.trim();
154
+ // typographic dashes/quotes/spaces → ASCII, mirroring codex's final pass
155
+ const normalise = (s) => s
156
+ .trim()
157
+ .replace(/[\u2010-\u2015\u2212]/g, "-")
158
+ .replace(/[\u2018-\u201B]/g, "'")
159
+ .replace(/[\u201C-\u201F]/g, '"')
160
+ .replace(/[\u00A0\u2002-\u200A\u202F\u205F\u3000]/g, " ");
161
+ const eqNorm = (a, b) => normalise(a) === normalise(b);
162
+ for (const eq of [eqExact, eqRstrip, eqTrim, eqNorm]) {
163
+ for (let i = searchStart; i + pattern.length <= lines.length; i++) {
164
+ let ok = true;
165
+ for (let j = 0; j < pattern.length; j++) {
166
+ if (!eq(lines[i + j], pattern[j])) {
167
+ ok = false;
168
+ break;
169
+ }
170
+ }
171
+ if (ok)
172
+ return i;
173
+ }
174
+ }
175
+ return null;
176
+ }
177
+ function parsePatch(patch) {
178
+ let text = patch.trim();
179
+ // lenient: strip a heredoc wrapper (<<EOF … EOF), as models sometimes emit one
180
+ const lines0 = text.split("\n");
181
+ if (lines0.length >= 4 &&
182
+ ["<<EOF", "<<'EOF'", '<<"EOF"'].includes(lines0[0].trim()) &&
183
+ lines0[lines0.length - 1].trimEnd().endsWith("EOF")) {
184
+ text = lines0.slice(1, -1).join("\n").trim();
185
+ }
186
+ const lines = text.split("\n").map((l) => l.replace(/\r$/, ""));
187
+ if (lines[0]?.trim() !== "*** Begin Patch")
188
+ return `invalid patch: The first line must be '*** Begin Patch'`;
189
+ if (lines[lines.length - 1]?.trim() !== "*** End Patch")
190
+ return `invalid patch: The last line must be '*** End Patch'`;
191
+ const ops = [];
192
+ let i = 1;
193
+ while (i < lines.length) {
194
+ const line = lines[i];
195
+ const t = line.trim();
196
+ if (t === "*** End Patch")
197
+ break;
198
+ if (!t || t.startsWith("*** Environment ID:")) {
199
+ i++;
200
+ continue;
201
+ }
202
+ let m = t.match(/^\*\*\* Add File: (.+)$/);
203
+ if (m) {
204
+ const body = [];
205
+ i++;
206
+ while (i < lines.length && lines[i].startsWith("+"))
207
+ body.push(lines[i++].slice(1));
208
+ if (body.length === 0)
209
+ return `invalid patch: Add File hunk for '${m[1].trim()}' has no + lines`;
210
+ ops.push({ kind: "add", path: m[1].trim(), contents: body.join("\n") + "\n" });
211
+ continue;
212
+ }
213
+ m = t.match(/^\*\*\* Delete File: (.+)$/);
214
+ if (m) {
215
+ ops.push({ kind: "delete", path: m[1].trim() });
216
+ i++;
217
+ continue;
218
+ }
219
+ m = t.match(/^\*\*\* Update File: (.+)$/);
220
+ if (m) {
221
+ const filePath = m[1].trim();
222
+ let movePath = null;
223
+ i++;
224
+ const mv = lines[i]?.trim().match(/^\*\*\* Move to: (.+)$/);
225
+ if (mv) {
226
+ movePath = mv[1].trim();
227
+ i++;
228
+ }
229
+ const chunks = [];
230
+ let cur = null;
231
+ const flush = () => {
232
+ if (cur)
233
+ chunks.push(cur);
234
+ cur = null;
235
+ };
236
+ while (i < lines.length && !lines[i].trim().startsWith("*** ")) {
237
+ const l = lines[i];
238
+ if (l.startsWith("@@")) {
239
+ flush();
240
+ cur = { changeContext: l.slice(2).trim() || null, oldLines: [], newLines: [], isEndOfFile: false };
241
+ i++;
242
+ continue;
243
+ }
244
+ if (l.startsWith("+") || l.startsWith("-") || l.startsWith(" ")) {
245
+ cur ??= { changeContext: null, oldLines: [], newLines: [], isEndOfFile: false }; // implicit first chunk
246
+ if (l.startsWith("+"))
247
+ cur.newLines.push(l.slice(1));
248
+ else if (l.startsWith("-"))
249
+ cur.oldLines.push(l.slice(1));
250
+ else {
251
+ cur.oldLines.push(l.slice(1));
252
+ cur.newLines.push(l.slice(1));
253
+ }
254
+ i++;
255
+ continue;
256
+ }
257
+ if (l.trim() === "*** End of File") {
258
+ if (!cur)
259
+ return `invalid patch: *** End of File outside a hunk in '${filePath}'`;
260
+ cur.isEndOfFile = true;
261
+ i++;
262
+ continue;
263
+ }
264
+ if (!l.trim()) {
265
+ i++;
266
+ continue; // blank between hunks
267
+ }
268
+ return `invalid patch: bad line in Update File '${filePath}': "${l.slice(0, 60)}" (expected ' ', '-', '+' or '@@')`;
269
+ }
270
+ flush();
271
+ if (chunks.length === 0)
272
+ return `invalid patch: Update File hunk for path '${filePath}' is empty`;
273
+ ops.push({ kind: "update", path: filePath, movePath, chunks });
274
+ continue;
275
+ }
276
+ return `invalid patch: unrecognized directive "${t.slice(0, 60)}"`;
277
+ }
278
+ return ops;
279
+ }
280
+ /** Compute the updated content of one file (no I/O writes). Error string on failure. */
281
+ async function deriveUpdate(p, displayPath, chunks) {
282
+ let raw;
283
+ try {
284
+ raw = await fs.readFile(p, "utf8");
285
+ }
286
+ catch {
287
+ return `Failed to read file to update ${displayPath}`;
288
+ }
289
+ const hadCrlf = raw.includes("\r\n");
290
+ const originalLines = raw.split("\n");
291
+ if (originalLines.at(-1) === "")
292
+ originalLines.pop(); // trailing newline → diff-standard line list
293
+ const replacements = [];
294
+ let lineIndex = 0;
295
+ for (const ch of chunks) {
296
+ if (ch.changeContext != null) {
297
+ const idx = seekSequence(originalLines, [ch.changeContext], lineIndex, false);
298
+ if (idx == null)
299
+ return `Failed to find context '${ch.changeContext}' in ${displayPath}`;
300
+ lineIndex = idx + 1;
301
+ }
302
+ let pattern = ch.oldLines;
303
+ let newSlice = ch.newLines;
304
+ if (pattern.length === 0) {
305
+ // codex semantics: a chunk with no context/removed lines appends at end of file
306
+ replacements.push([originalLines.length, 0, newSlice]);
307
+ continue;
308
+ }
309
+ let found = seekSequence(originalLines, pattern, lineIndex, ch.isEndOfFile);
310
+ if (found == null && pattern.at(-1) === "") {
311
+ // trailing "" usually represents the file's final newline sentinel
312
+ const p2 = pattern.slice(0, -1);
313
+ const n2 = newSlice.at(-1) === "" ? newSlice.slice(0, -1) : newSlice;
314
+ found = seekSequence(originalLines, p2, lineIndex, ch.isEndOfFile);
315
+ if (found != null) {
316
+ pattern = p2;
317
+ newSlice = n2;
318
+ }
319
+ }
320
+ if (found == null)
321
+ return (`Failed to find expected lines in ${displayPath}:\n${pattern.join("\n")}\n` +
322
+ `(re-read the file and regenerate the patch)`);
323
+ replacements.push([found, pattern.length, newSlice]);
324
+ lineIndex = found + pattern.length;
325
+ }
326
+ replacements.sort((a, b) => b[0] - a[0]); // descending so earlier edits keep indices valid
327
+ const out = originalLines.slice();
328
+ for (const [startIdx, oldLen, seg] of replacements)
329
+ out.splice(startIdx, oldLen, ...seg);
330
+ if (out.at(-1) !== "")
331
+ out.push("");
332
+ return { content: out.join("\n"), note: hadCrlf ? " (CRLF→LF)" : "" };
333
+ }
334
+ async function applyPatch(patch, ctx) {
335
+ const ops = parsePatch(patch);
336
+ if (typeof ops === "string")
337
+ return { ok: false, result: ops };
338
+ if (ops.length === 0)
339
+ return { ok: false, result: "patch contains no file operations" };
340
+ // resolve every path up front (workspace confinement + duplicate guard)
341
+ const seen = new Set();
342
+ const resolved = [];
343
+ try {
344
+ for (const op of ops) {
345
+ const abs = safeJoin(ctx.cwd, op.path);
346
+ if (seen.has(abs))
347
+ return { ok: false, result: `path touched twice in one patch: ${op.path}` };
348
+ seen.add(abs);
349
+ const r = { op, abs };
350
+ if (op.kind === "update" && op.movePath) {
351
+ r.absMove = safeJoin(ctx.cwd, op.movePath);
352
+ if (r.absMove === abs)
353
+ return { ok: false, result: `Move to: destination equals source (${op.path})` };
354
+ seen.add(r.absMove);
355
+ }
356
+ resolved.push(r);
357
+ }
358
+ }
359
+ catch (e) {
360
+ return { ok: false, result: e.message };
361
+ }
362
+ // phase 1 — validate everything, write nothing
363
+ const writes = [];
364
+ const deletes = [];
365
+ const summary = [];
366
+ try {
367
+ for (const { op, abs, absMove } of resolved) {
368
+ if (op.kind === "add") {
369
+ if (existsSync(abs))
370
+ return { ok: false, result: `Add File: ${op.path} already exists` };
371
+ writes.push({ abs, content: op.contents });
372
+ summary.push(`A ${op.path} (+${op.contents.split("\n").length - 1})`);
373
+ }
374
+ else if (op.kind === "delete") {
375
+ if (!existsSync(abs))
376
+ return { ok: false, result: `Delete File: ${op.path} not found` };
377
+ deletes.push(abs);
378
+ summary.push(`D ${op.path}`);
379
+ }
380
+ else {
381
+ const r = await deriveUpdate(abs, op.path, op.chunks);
382
+ if (typeof r === "string")
383
+ return { ok: false, result: r };
384
+ const dest = absMove ?? abs;
385
+ if (absMove && existsSync(absMove))
386
+ return { ok: false, result: `Move to: destination already exists (${op.movePath})` };
387
+ writes.push({ abs: dest, content: r.content });
388
+ if (absMove)
389
+ deletes.push(abs);
390
+ summary.push(`${absMove ? "R" : "U"} ${op.path}${absMove ? ` → ${op.movePath}` : ""} (${op.chunks.length} hunk${op.chunks.length > 1 ? "s" : ""})${r.note}`);
391
+ }
392
+ }
393
+ }
394
+ catch (e) {
395
+ return { ok: false, result: `patch validation failed: ${e.message}` };
396
+ }
397
+ // phase 2 — commit
398
+ for (const w of writes) {
399
+ await fs.mkdir(path.dirname(w.abs), { recursive: true });
400
+ await fs.writeFile(w.abs, w.content, "utf8");
401
+ }
402
+ for (const d of deletes)
403
+ await fs.rm(d).catch(() => { });
404
+ return { ok: true, result: `patch applied:\n${summary.join("\n")}` };
405
+ }
87
406
  export const TOOLS = [
88
407
  {
89
408
  name: "read_file",
90
- description: "Read a text file from the workspace. Supports offset/limit for large files. Returns numbered lines.",
409
+ description: "Read a text file from the workspace. Returns numbered lines (`N| ` prefixes are display-only — never copy them into edit_file). " +
410
+ "With `pattern`, acts like grep: only matching lines (JS regex, optional `ignore_case`) plus `context` surrounding lines are returned. " +
411
+ "A negative `offset` counts from the end (-30 → last 30 lines, or last 30 matches in pattern mode).",
91
412
  parameters: {
92
413
  type: "object",
93
414
  properties: {
94
415
  path: { type: "string", description: "Path relative to workspace root" },
95
- offset: { type: "number", description: "1-indexed start line" },
96
- limit: { type: "number", description: "Max lines to return" },
416
+ offset: { type: "number", description: "1-indexed start line (negative = from end)" },
417
+ limit: { type: "number", description: "Max lines (or max matches in pattern mode)" },
418
+ pattern: { type: "string", description: "JS regex — return only matching lines (+context) instead of the whole file" },
419
+ context: { type: "number", description: "context lines around each pattern match (max 5)" },
420
+ ignore_case: { type: "boolean", description: "case-insensitive pattern matching" },
97
421
  },
98
422
  required: ["path"],
99
423
  },
@@ -101,7 +425,41 @@ export const TOOLS = [
101
425
  const p = safeJoin(ctx.cwd, str(args.path));
102
426
  const text = await readText(p);
103
427
  const lines = text.split("\n");
104
- const off = Math.max(0, num(args.offset, 1) - 1);
428
+ // grep mode
429
+ if (typeof args.pattern === "string" && args.pattern !== "") {
430
+ const re = compileRegex(args.pattern, args.ignore_case === true);
431
+ if (typeof re === "string")
432
+ return { ok: false, result: re };
433
+ const idxs = [];
434
+ for (let i = 0; i < lines.length; i++)
435
+ if (re.test(lines[i]))
436
+ idxs.push(i);
437
+ if (idxs.length === 0)
438
+ return { ok: true, result: `(no matches for /${args.pattern}/)` };
439
+ let off = num(args.offset, 1);
440
+ off = off < 0 ? Math.max(0, idxs.length + off) : Math.max(0, off - 1);
441
+ const lim = Math.min(num(args.limit, 100), 1000);
442
+ const page = idxs.slice(off, off + lim);
443
+ const cN = Math.max(0, Math.min(num(args.context, 0), 5));
444
+ const regions = [];
445
+ for (const m of page) {
446
+ const s = Math.max(0, m - cN);
447
+ const e = Math.min(lines.length - 1, m + cN);
448
+ const last = regions[regions.length - 1];
449
+ if (last && s <= last[1] + 1)
450
+ last[1] = Math.max(last[1], e);
451
+ else
452
+ regions.push([s, e]);
453
+ }
454
+ const parts = regions.map(([s, e]) => lines.slice(s, e + 1).map((l, k) => `${s + k + 1}| ${l}`).join("\n"));
455
+ let result = parts.join("\n--\n");
456
+ if (idxs.length > page.length || off > 0)
457
+ result += `\n(${off + 1}–${off + page.length} of ${idxs.length} matches)`;
458
+ return { ok: true, result };
459
+ }
460
+ // plain mode
461
+ let off = num(args.offset, 1);
462
+ off = off < 0 ? Math.max(0, lines.length + off) : Math.max(0, off - 1);
105
463
  const lim = num(args.limit, 2000);
106
464
  const slice = lines.slice(off, off + lim).map((l, i) => `${off + i + 1}| ${l}`);
107
465
  const more = off + lim < lines.length ? `\n... (${lines.length - off - lim} more lines)` : "";
@@ -110,7 +468,9 @@ export const TOOLS = [
110
468
  },
111
469
  {
112
470
  name: "write_file",
113
- description: "Create or overwrite a file with the given content (parent dirs auto-created).",
471
+ description: "Create ONE new file, or replace a file's entire content (parent dirs auto-created). " +
472
+ "Creating files as part of a larger batch of edits → one apply_patch instead. " +
473
+ "Partial changes to an existing file → edit_file.",
114
474
  parameters: {
115
475
  type: "object",
116
476
  properties: {
@@ -128,13 +488,17 @@ export const TOOLS = [
128
488
  },
129
489
  {
130
490
  name: "edit_file",
131
- description: "Replace an exact unique substring in a file. old_text must match exactly and be unique.",
491
+ description: "Make exactly ONE small, unique replacement in one existing file the cheapest tool for a single spot change. " +
492
+ "Copy old_text from the file contents (NOT from read_file's `N| ` prefixed display); it must appear exactly once — " +
493
+ "if it matches several places, add surrounding lines or pass replace_all=true. " +
494
+ "Two or more changes (or a rename/delete) → use apply_patch instead.",
132
495
  parameters: {
133
496
  type: "object",
134
497
  properties: {
135
498
  path: { type: "string" },
136
499
  old_text: { type: "string" },
137
500
  new_text: { type: "string" },
501
+ replace_all: { type: "boolean", description: "replace every occurrence instead of requiring uniqueness" },
138
502
  },
139
503
  required: ["path", "old_text", "new_text"],
140
504
  },
@@ -143,24 +507,91 @@ export const TOOLS = [
143
507
  let text = await readText(p);
144
508
  const oldText = str(args.old_text);
145
509
  const newText = str(args.new_text);
510
+ if (!oldText)
511
+ return { ok: false, result: "old_text is required" };
512
+ const replaceAll = args.replace_all === true;
146
513
  let count = text.split(oldText).length - 1;
147
514
  let normalized = false;
148
515
  // tolerate LF patterns against CRLF files (convert once, on success)
149
516
  if (count === 0 && oldText.includes("\n") && text.includes("\r\n")) {
150
517
  const lf = text.replace(/\r\n/g, "\n");
151
518
  const lfCount = lf.split(oldText).length - 1;
152
- if (lfCount === 1) {
519
+ if (lfCount >= 1) {
153
520
  text = lf;
154
- count = 1;
521
+ count = lfCount;
155
522
  normalized = true;
156
523
  }
157
524
  }
158
- if (count === 0)
159
- return { ok: false, result: "old_text not found in file" };
160
- if (count > 1)
161
- return { ok: false, result: `old_text matched ${count} times; must be unique` };
162
- await fs.writeFile(p, text.replace(oldText, newText), "utf8");
163
- return { ok: true, result: normalized ? "edited (file converted CRLF→LF)" : "edited" };
525
+ // tolerate patterns whose only difference is trailing whitespace per line
526
+ // (the most common near-miss) applied only when it resolves uniquely
527
+ if (count === 0) {
528
+ const srcLines = text.replace(/\r\n/g, "\n").split("\n");
529
+ const patLines = oldText.replace(/\r\n/g, "\n").split("\n");
530
+ const hits = trailingWsMatches(srcLines, patLines);
531
+ if (hits.length === 1 && patLines.length > 0) {
532
+ const eol = text.includes("\r\n") ? "\r\n" : "\n";
533
+ const rebuilt = [
534
+ ...srcLines.slice(0, hits[0]),
535
+ ...newText.replace(/\r\n/g, "\n").split("\n"),
536
+ ...srcLines.slice(hits[0] + patLines.length),
537
+ ].join(eol);
538
+ await fs.writeFile(p, rebuilt, "utf8");
539
+ return {
540
+ ok: true,
541
+ result: `edited (matched ignoring trailing whitespace around ${path.basename(str(args.path))}:${hits[0] + 1})`,
542
+ };
543
+ }
544
+ if (hits.length > 1)
545
+ return {
546
+ ok: false,
547
+ result: `old_text matched ${hits.length} times ignoring trailing whitespace (lines ${hits.map((h) => h + 1).join(", ")}); add surrounding lines to disambiguate`,
548
+ };
549
+ }
550
+ if (count === 0) {
551
+ // actionable miss: point the model at recovery instead of pushing it
552
+ // toward bash-based editing
553
+ const lines = matchLines(text, oldText.trim());
554
+ const hint = lines.length
555
+ ? `A trimmed variant appears at line(s) ${lines.slice(0, 5).join(", ")}.`
556
+ : `No similar text found — re-read ${str(args.path)} around the target area and copy old_text exactly.`;
557
+ return {
558
+ ok: false,
559
+ result: `old_text not found in file. ${hint} Watch indentation/trailing spaces and drop the \`N| \` line-number prefixes.`,
560
+ };
561
+ }
562
+ if (count > 1 && !replaceAll) {
563
+ const at = matchLines(text, oldText);
564
+ return {
565
+ ok: false,
566
+ result: `old_text matched ${count} times (lines ${at.slice(0, 5).join(", ")}) and must be unique — add surrounding lines to old_text, or pass replace_all=true`,
567
+ };
568
+ }
569
+ await fs.writeFile(p, replaceAll ? text.split(oldText).join(newText) : text.replace(oldText, newText), "utf8");
570
+ const where = count > 1 ? ` (${count} occurrences)` : "";
571
+ return {
572
+ ok: true,
573
+ result: `${replaceAll ? "replaced all" : "edited"}${where}${normalized ? " (file converted CRLF→LF)" : ""}`,
574
+ };
575
+ },
576
+ },
577
+ {
578
+ name: "apply_patch",
579
+ description: "Apply a Codex-style patch: several edits in one file, changes across MULTIPLE files, renames, deletes — " +
580
+ "all validated first and applied atomically (any failure → nothing is written). Reach for this whenever " +
581
+ "one edit_file call would not cover the change. Every hunk is located with whitespace-tolerant fallbacks. Format:\n" +
582
+ '*** Begin Patch\n*** Add File: rel/new.txt\n+created line\n*** Update File: src/app.py\n@@ def main():\n context line\n-old line\n+new line\n*** Move to: src/main.py\n*** Delete File: obsolete.txt\n*** End Patch\n' +
583
+ "Update hunks: lines prefixed ' ' are context, '-' removed, '+' added. '@@ hint' optionally locates the area first; " +
584
+ "several hunks apply top-to-bottom. A hunk with only + lines appends at end of file; " +
585
+ "'*** End of File' anchors a hunk at the tail. For a single tiny replacement, edit_file is cheaper.",
586
+ parameters: {
587
+ type: "object",
588
+ properties: {
589
+ patch: { type: "string", description: "the full *** Begin Patch … *** End Patch text" },
590
+ },
591
+ required: ["patch"],
592
+ },
593
+ async run(args, ctx) {
594
+ return applyPatch(str(args.patch), ctx);
164
595
  },
165
596
  },
166
597
  {
@@ -181,7 +612,9 @@ export const TOOLS = [
181
612
  },
182
613
  {
183
614
  name: "bash",
184
- description: "Run a bash command inside the workspace (use it for git, builds, tests, etc.). " +
615
+ description: "Run a bash command inside the workspace git, builds, tests, searches and other COMMANDS. " +
616
+ "Also fine for quick shell-style file edits (sed/awk bulk transforms) when that is genuinely the better tool; " +
617
+ "for most changes the file tools below are easier to get right (no quoting, validated before writing). " +
185
618
  "Killed (whole process group) on timeout. stdout+stderr are returned.",
186
619
  parameters: {
187
620
  type: "object",
@@ -195,6 +628,77 @@ export const TOOLS = [
195
628
  return runShell(str(args.command), ctx, Math.min(num(args.timeout_ms, ctx.defaultTimeoutMs), 600_000));
196
629
  },
197
630
  },
631
+ {
632
+ name: "read_url",
633
+ description: "Fetch a web page and return its main readable content (title + plain text, boilerplate stripped via " +
634
+ "Mozilla Readability) — documentation, articles, issue threads. Cached for an hour per URL. " +
635
+ "For raw JSON/API responses or file downloads prefer bash curl.",
636
+ parameters: {
637
+ type: "object",
638
+ properties: {
639
+ url: { type: "string", description: "absolute http(s) URL" },
640
+ limit: { type: "number", description: "max characters returned (default 20000)" },
641
+ },
642
+ required: ["url"],
643
+ },
644
+ async run(args) {
645
+ const raw = str(args.url);
646
+ if (!URL.canParse(raw))
647
+ return { ok: false, result: `invalid url: ${raw.slice(0, 200)}` };
648
+ const u = new URL(raw);
649
+ if (u.protocol !== "http:" && u.protocol !== "https:")
650
+ return { ok: false, result: `unsupported protocol: ${u.protocol}` };
651
+ const key = u.toString();
652
+ const cached = urlCache.get(key);
653
+ if (cached && Date.now() - cached.at < URL_CACHE_TTL_MS)
654
+ return { ok: true, result: clipText(cached.text, num(args.limit, 20_000)) };
655
+ let res;
656
+ try {
657
+ res = await fetch(u, {
658
+ redirect: "follow",
659
+ signal: AbortSignal.timeout(45_000),
660
+ headers: { "user-agent": "Mozilla/5.0 (compatible; teapot-coding-agent)" },
661
+ });
662
+ }
663
+ catch (e) {
664
+ return { ok: false, result: `fetch failed: ${e.message}` };
665
+ }
666
+ const html = await res.text();
667
+ if (!html.trim())
668
+ return { ok: false, result: `HTTP ${res.status} with an empty body` };
669
+ // heavy DOM deps are loaded lazily so the master's idle startup stays lean
670
+ const { Browser } = await import("happy-dom");
671
+ const { Readability } = await import("@mozilla/readability");
672
+ const browser = new Browser();
673
+ let text = "";
674
+ try {
675
+ const page = browser.newPage();
676
+ page.url = key;
677
+ page.content = html;
678
+ const article = new Readability(page.mainFrame.document).parse();
679
+ text =
680
+ [article?.title, article?.byline]
681
+ .filter(Boolean)
682
+ .join(" — ") + `\n(HTTP ${res.status}, ~${(article?.textContent ?? "").length} chars extracted)\n\n` +
683
+ (article?.textContent ?? page.mainFrame.document.body?.textContent ?? "").replace(/\n{3,}/g, "\n\n").trim();
684
+ }
685
+ catch (e) {
686
+ return { ok: false, result: `failed to parse page: ${e.message}` };
687
+ }
688
+ finally {
689
+ await browser.close().catch(() => { });
690
+ }
691
+ if (res.ok && text.trim()) {
692
+ if (urlCache.size >= 40) {
693
+ const oldest = [...urlCache.entries()].sort((a, b) => a[1].at - b[1].at)[0];
694
+ if (oldest)
695
+ urlCache.delete(oldest[0]);
696
+ }
697
+ urlCache.set(key, { at: Date.now(), text });
698
+ }
699
+ return { ok: res.ok || text.length > 0, result: clipText(text, num(args.limit, 20_000)) };
700
+ },
701
+ },
198
702
  {
199
703
  name: "load_skill",
200
704
  description: "Load a skill's full instructions by name. Use when the system prompt's skill list " +
@@ -265,6 +769,8 @@ export async function executeTool(name, rawArgs, ctx) {
265
769
  const def = TOOLS.find((t) => t.name === name);
266
770
  if (!def)
267
771
  return { ok: false, result: `unknown tool: ${name}` };
772
+ if (ctx.signal?.aborted)
773
+ return { ok: false, result: "aborted (harness shutdown)" };
268
774
  let args;
269
775
  try {
270
776
  args = rawArgs ? JSON.parse(rawArgs) : {};
package/dist/bus.js CHANGED
@@ -1,4 +1,4 @@
1
1
  import { EventEmitter } from "node:events";
2
2
  /** Tiny process-wide pub/sub used to push updates to SSE clients (no polling). */
3
3
  export const bus = new EventEmitter();
4
- bus.setMaxListeners(100);
4
+ bus.setMaxListeners(1000); // one per connected client (WS + SSE) — headroom for busy LAN setups
@@ -264,10 +264,12 @@ export function buildApp(master) {
264
264
  const body = await c.req.json();
265
265
  if (!body.text?.trim())
266
266
  return c.json({ error: "text required" }, 400);
267
- await a.enqueuePrompt(body.text, "user");
267
+ // returns immediately: the prompt is logged + broadcast now, delivered to
268
+ // the model at the next turn boundary (never blocks on a running agent)
269
+ a.enqueuePrompt(body.text, "user");
268
270
  if (body.start !== false && a.status !== "running")
269
271
  a.start("prompt");
270
- return c.json({ ok: true });
272
+ return c.json({ ok: true, queued: a.snapshot().pendingPrompts });
271
273
  });
272
274
  app.post("/api/agents/:id/start", (c) => {
273
275
  const a = master.agents.get(c.req.param("id"));
@@ -421,7 +423,8 @@ export function buildApp(master) {
421
423
  app.on(["GET", "POST", "BREW"], "/brew", (c) => c.text("418 I'm a teapot \u{1FAD6}", 418));
422
424
  app.on(["GET", "POST", "BREW"], "/brew/coffee", (c) => c.text("418 I'm a teapot — coffee not supported (see RFC 2324 §2.3.2)", 418));
423
425
  // ---- web ui (built by vite into ./public; no bundler needed to serve) ----
424
- const webRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), import.meta.url.includes("/dist/") ? "../../public" : "../../public");
426
+ // works both from dist/server/api.js and src/server/api.ts: ../../public
427
+ const webRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../../public");
425
428
  const mime = {
426
429
  ".html": "text/html",
427
430
  ".js": "text/javascript",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "teapot-coding-agent",
3
- "version": "0.8.0",
3
+ "version": "0.9.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,6 +39,8 @@
39
39
  },
40
40
  "dependencies": {
41
41
  "@hono/node-server": "^2.1.1",
42
+ "@mozilla/readability": "^0.6.0",
43
+ "happy-dom": "^20.11.6",
42
44
  "hono": "^4.7.0",
43
45
  "openai": "^5.0.0",
44
46
  "ws": "^8.21.3"
@@ -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;font-family:gg sans,ui-sans-serif,system-ui,-apple-system,Segoe UI,sans-serif}*{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 300px;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{display:block}.rightbar{z-index:5;width:min(320px,88vw);transition:transform .18s;position:fixed;top:0;bottom:0;right:0;transform:translate(100%);box-shadow:-8px 0 24px #0007}.rightbar.open{transform:none}}.sidebar{background:var(--bg-darkest);flex-direction:column;padding:10px 8px;display:flex;overflow-y:auto}.sidebar h1{color:var(--fg);flex-shrink:0;margin:0;padding:4px 8px 10px;font-size:14px}.agent-list{flex:1;min-height:0;overflow-y:auto}.agent-item{cursor:pointer;color:var(--dim);border-radius:6px;align-items:center;gap:8px;margin-bottom:2px;padding:7px 10px;display:flex}.agent-item:hover{background:var(--bg-mid)}.agent-item.sel{background:var(--bg-mid);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.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}.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.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}.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 code{background:var(--bg-darkest);border-radius:4px;padding:1px 4px;font-size:13px}.content h1,.content h2,.content h3,.content h4{margin:8px 0 2px;font-size:15px}.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 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}@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%;margin-left:8px;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}.msgfoot{color:var(--dim);align-items:center;gap:6px;margin-top:4px;font-size:11px;display:flex}.termdrawer{border-top:2px solid var(--line);background:#0d0e12;flex-direction:column;flex-shrink:0;height:38vh;min-height:220px;display:flex}.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}.termhost{flex:1;min-height:0;padding:6px 8px;overflow:hidden}.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;bottom:86px;left:50%;transform:translate(-50%);box-shadow:0 4px 14px #0008}.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)}.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}.composer form{background:var(--bg-light);border-radius:10px;align-items:center;gap:8px;padding:10px 12px;display:flex}.composer input[type=text]{color:var(--fg);font:inherit;background:0 0;border:none;outline:none;flex:1}.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}.rightbar{background:var(--bg-dark);border-left:2px solid var(--line);flex-direction:column;min-height:0;padding:14px;font-size:13px;display:flex;overflow-y:auto}.rightbar h3{text-transform:uppercase;letter-spacing:.04em;color:var(--dim);margin:14px 0 6px;font-size:11px}.rightbar h3:first-child{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}.muted{color:var(--dim)}.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)}.sesscard{flex-direction:column;gap:6px;font-size:12.5px;display:flex}.sessrow{align-items:center;gap:8px;display:flex}.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)}.iconbtn{background:var(--bg-light);color:var(--fg);cursor:pointer;border:none;border-radius:6px;width:26px;height:24px;font-size:13px}.iconbtn:hover{filter:brightness(1.3)}.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 select,.modal textarea{background:var(--bg-darkest);color:var(--fg);font:inherit;border:none;border-radius:6px;outline:none;padding:7px 9px}.modal textarea{resize:vertical}.w100{width:100%}.mono{font-family:ui-monospace,Menlo,monospace;font-size:13px}.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)}.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}
@@ -0,0 +1,8 @@
1
+ (function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var e={context:void 0,registry:void 0,effects:void 0,done:!1,getContextId(){return t(this.context.count)},getNextContextId(){return t(this.context.count++)}};function t(t){let n=String(t),r=n.length-1;return e.context.id+(r?String.fromCharCode(96+r):``)+n}function n(t){e.context=t}var r=(e,t)=>e===t,i=Symbol(`solid-track`),a={equals:r},o=null,s=oe,c=1,l=2,u={owned:null,cleanups:null,context:null,owner:null},d=null,f=null,p=null,m=null,h=null,g=0;function _(e,t){let n=p,r=d,i=e.length===0,a=t===void 0?r:t,o=i?u:{owned:null,cleanups:null,context:a?a.context:null,owner:a},s=i?e:()=>e(()=>S(()=>N(o)));d=o,p=null;try{return A(s,!0)}finally{p=n,d=r}}function v(e,t){t=t?Object.assign({},a,t):a;let n={value:e,observers:null,observerSlots:null,comparator:t.equals||void 0};return[ne.bind(n),e=>(typeof e==`function`&&(e=f&&f.running&&f.sources.has(n)?e(n.tValue):e(n.value)),re(n,e))]}function y(e,t,n){D(O(e,t,!1,c))}function b(e,t,n){s=se;let r=O(e,t,!1,c),i=te&&ee(te);i&&(r.suspense=i),(!n||!n.render)&&(r.user=!0),h?h.push(r):D(r)}function x(e,t,n){n=n?Object.assign({},a,n):a;let r=O(e,t,!0,0);return r.observers=null,r.observerSlots=null,r.comparator=n.equals||void 0,D(r),ne.bind(r)}function S(e){if(p===null)return e();let t=p;p=null;try{return e()}finally{p=t}}function C(e){b(()=>S(e))}function w(e){return d===null||(d.cleanups===null?d.cleanups=[e]:d.cleanups.push(e)),e}var[T,E]=v(!1);function ee(e){let t;return d&&d.context&&(t=d.context[e.id])!==void 0?t:e.defaultValue}var te;function ne(){let e=f&&f.running;if(this.sources&&(e?this.tState:this.state)){if((e?this.tState:this.state)===c)D(this);else{let e=m;m=null,A(()=>j(this),!1),m=e}}if(p){let e=this.observers;if(!e||e[e.length-1]!==p){let t=e?e.length:0;p.sources?(p.sources.push(this),p.sourceSlots.push(t)):(p.sources=[this],p.sourceSlots=[t]),e?(e.push(p),this.observerSlots.push(p.sources.length-1)):(this.observers=[p],this.observerSlots=[p.sources.length-1])}}return e&&f.sources.has(this)?this.tValue:this.value}function re(e,t,n){let r=f&&f.running&&f.sources.has(e)?e.tValue:e.value;if(!e.comparator||!e.comparator(r,t)){if(f){let r=f.running;(r||!n&&f.sources.has(e))&&(f.sources.add(e),e.tValue=t),r||(e.value=t)}else e.value=t;e.observers&&e.observers.length&&A(()=>{for(let t=0;t<e.observers.length;t+=1){let n=e.observers[t],r=f&&f.running;r&&f.disposed.has(n)||((r?!n.tState:!n.state)&&(n.pure?m.push(n):h.push(n),n.observers&&M(n)),r?n.tState=c:n.state=c)}if(m.length>1e6)throw m=[],Error()},!1)}return t}function D(e){if(!e.fn)return;N(e);let t=g;ie(e,f&&f.running&&f.sources.has(e)?e.tValue:e.value,t),f&&!f.running&&f.sources.has(e)&&queueMicrotask(()=>{A(()=>{f&&(f.running=!0),p=d=e,ie(e,e.tValue,t),p=d=null},!1)})}function ie(e,t,n){let r,i=d,a=p;p=d=e;try{r=e.fn(t)}catch(t){return e.pure&&(f&&f.running?(e.tState=c,e.tOwned&&e.tOwned.forEach(N),e.tOwned=void 0):(e.state=c,e.owned&&e.owned.forEach(N),e.owned=null)),e.updatedAt=n+1,I(t)}finally{p=a,d=i}(!e.updatedAt||e.updatedAt<=n)&&(e.updatedAt!=null&&`observers`in e?re(e,r,!0):f&&f.running&&e.pure?(f.sources.has(e)||(e.value=r),f.sources.add(e),e.tValue=r):e.value=r,e.updatedAt=n)}function O(e,t,n,r=c,i){let a={fn:e,state:r,updatedAt:null,owned:null,sources:null,sourceSlots:null,cleanups:null,value:t,owner:d,context:d?d.context:null,pure:n};return f&&f.running&&(a.state=0,a.tState=r),d===null||d!==u&&(f&&f.running&&d.pure?d.tOwned?d.tOwned.push(a):d.tOwned=[a]:d.owned?d.owned.push(a):d.owned=[a]),a}function k(e){let t=f&&f.running;if((t?e.tState:e.state)===0)return;if((t?e.tState:e.state)===l)return j(e);if(e.suspense&&S(e.suspense.inFallback))return e.suspense.effects.push(e);let n=[e];for(;(e=e.owner)&&(!e.updatedAt||e.updatedAt<g);){if(t&&f.disposed.has(e))return;(t?e.tState:e.state)&&n.push(e)}for(let r=n.length-1;r>=0;r--){if(e=n[r],t){let t=e,i=n[r+1];for(;(t=t.owner)&&t!==i;)if(f.disposed.has(t))return}if((t?e.tState:e.state)===c)D(e);else if((t?e.tState:e.state)===l){let t=m;m=null,A(()=>j(e,n[0]),!1),m=t}}}function A(e,t){if(m)return e();let n=!1;t||(m=[]),h?n=!0:h=[],g++;try{let t=e();return ae(n),t}catch(e){n||(h=null),m=null,I(e)}}function ae(e){if(m&&=(oe(m),null),e)return;let t;if(f){if(!f.promises.size&&!f.queue.size){let e=f.sources,n=f.disposed;h.push.apply(h,f.effects),t=f.resolve;for(let e of h)`tState`in e&&(e.state=e.tState),delete e.tState;f=null,A(()=>{for(let e of n)N(e);for(let t of e){if(t.value=t.tValue,t.owned)for(let e=0,n=t.owned.length;e<n;e++)N(t.owned[e]);t.tOwned&&(t.owned=t.tOwned),delete t.tValue,delete t.tOwned,t.tState=0}E(!1)},!1)}else if(f.running){f.running=!1,f.effects.push.apply(f.effects,h),h=null,E(!0);return}}let n=h;h=null,n.length&&A(()=>s(n),!1),t&&t()}function oe(e){for(let t=0;t<e.length;t++)k(e[t])}function se(t){let r,i=0;for(r=0;r<t.length;r++){let e=t[r];e.user?t[i++]=e:k(e)}if(e.context){if(e.count){e.effects||=[],e.effects.push(...t.slice(0,i));return}n()}for(e.effects&&(e.done||!e.count)&&(t=[...e.effects,...t],i+=e.effects.length,delete e.effects),r=0;r<i;r++)k(t[r])}function j(e,t){let n=f&&f.running;n?e.tState=0:e.state=0;for(let r=0;r<e.sources.length;r+=1){let i=e.sources[r];if(i.sources){let e=n?i.tState:i.state;e===c?i!==t&&(!i.updatedAt||i.updatedAt<g)&&k(i):e===l&&j(i,t)}}}function M(e){let t=f&&f.running;for(let n=0;n<e.observers.length;n+=1){let r=e.observers[n];(t?!r.tState:!r.state)&&(t?r.tState=l:r.state=l,r.pure?m.push(r):h.push(r),r.observers&&M(r))}}function N(e){let t;if(e.sources)for(;e.sources.length;){let t=e.sources.pop(),n=e.sourceSlots.pop(),r=t.observers;if(r&&r.length){let e=r.pop(),i=t.observerSlots.pop();n<r.length&&(e.sourceSlots[i]=n,r[n]=e,t.observerSlots[n]=i)}}if(e.tOwned){for(t=e.tOwned.length-1;t>=0;t--)N(e.tOwned[t]);delete e.tOwned}if(f&&f.running&&e.pure)P(e,!0);else if(e.owned){for(t=e.owned.length-1;t>=0;t--)N(e.owned[t]);e.owned=null}if(e.cleanups){for(t=e.cleanups.length-1;t>=0;t--)e.cleanups[t]();e.cleanups=null}f&&f.running?e.tState=0:e.state=0}function P(e,t){if(t||(e.tState=0,f.disposed.add(e)),e.owned)for(let t=0;t<e.owned.length;t++)P(e.owned[t])}function ce(e){return e instanceof Error?e:Error(typeof e==`string`?e:`Unknown error`,{cause:e})}function F(e,t,n){try{for(let n of t)n(e)}catch(e){I(e,n&&n.owner||null)}}function I(e,t=d){let n=o&&t&&t.context&&t.context[o],r=ce(e);if(!n)throw r;h?h.push({fn(){F(r,n,t)},state:c}):F(r,n,t)}var L=Symbol(`fallback`);function R(e){for(let t=0;t<e.length;t++)e[t]()}function z(e,t,n={}){let r=[],a=[],o=[],s=0,c=t.length>1?[]:null;return w(()=>R(o)),()=>{let l=e()||[],u=l.length,d,f;return l[i],S(()=>{let e,t,i,m,h,g,v,y,b;if(u===0)s!==0&&(R(o),o=[],r=[],a=[],s=0,c&&=[]),n.fallback&&(r=[L],a[0]=_(e=>(o[0]=e,n.fallback())),s=1);else if(s===0){for(a=Array(u),f=0;f<u;f++)r[f]=l[f],a[f]=_(p);s=u}else{for(i=Array(u),m=Array(u),c&&(h=Array(u)),g=0,v=Math.min(s,u);g<v&&r[g]===l[g];g++);for(v=s-1,y=u-1;v>=g&&y>=g&&r[v]===l[y];v--,y--)i[y]=a[v],m[y]=o[v],c&&(h[y]=c[v]);for(e=new Map,t=Array(y+1),f=y;f>=g;f--)b=l[f],d=e.get(b),t[f]=d===void 0?-1:d,e.set(b,f);for(d=g;d<=v;d++)b=r[d],f=e.get(b),f!==void 0&&f!==-1?(i[f]=a[d],m[f]=o[d],c&&(h[f]=c[d]),f=t[f],e.set(b,f)):o[d]();for(f=g;f<u;f++)f in i?(a[f]=i[f],o[f]=m[f],c&&(c[f]=h[f],c[f](f))):a[f]=_(p);a=a.slice(0,s=u),r=l.slice(0)}return a});function p(e){if(o[f]=e,c){let[e,n]=v(f);return c[f]=n,t(l[f],e)}return t(l[f])}}}function B(e,t){return S(()=>e(t||{}))}var le=e=>`Stale read from <${e}>.`;function V(e){let t=`fallback`in e&&{fallback:()=>e.fallback};return x(z(()=>e.each,e.children,t||void 0))}function H(e){let t=e.keyed,n=x(()=>e.when,void 0,void 0),r=t?n:x(n,void 0,{equals:(e,t)=>!e==!t});return x(()=>{let i=r();if(i){let a=e.children;return typeof a==`function`&&a.length>0?S(()=>a(t?i:()=>{if(!S(r))throw le(`Show`);return n()})):a}return e.fallback},void 0,void 0)}var U=e=>x(()=>e());function ue(e,t,n){let r=n.length,i=t.length,a=r,o=0,s=0,c=t[i-1].nextSibling,l=null;for(;o<i||s<a;){if(t[o]===n[s]){o++,s++;continue}for(;t[i-1]===n[a-1];)i--,a--;if(i===o){let t=a<r?s?n[s-1].nextSibling:n[a-s]:c;for(;s<a;)e.insertBefore(n[s++],t)}else if(a===s)for(;o<i;)(!l||!l.has(t[o]))&&t[o].remove(),o++;else if(t[o]===n[a-1]&&n[s]===t[i-1]){let r=t[--i].nextSibling;e.insertBefore(n[s++],t[o++].nextSibling),e.insertBefore(n[--a],r),t[i]=n[a]}else{if(!l){l=new Map;let e=s;for(;e<a;)l.set(n[e],e++)}let r=l.get(t[o]);if(r!=null){if(s<r&&r<a){let c=o,u=1,d;for(;++c<i&&c<a&&(d=l.get(t[c]))!=null&&d===r+u;)u++;if(u>r-s){let i=t[o];for(;s<r;)e.insertBefore(n[s++],i)}else e.replaceChild(n[s++],t[o++])}else o++}else t[o++].remove()}}}var de=`_$DX_DELEGATE`;function fe(e,t,n,r={}){let i;return _(r=>{i=r,t===document?e():Y(t,e(),t.firstChild?null:void 0,n)},r.owner),()=>{i(),t.textContent=``}}function W(e,t,n,r){let i,a=()=>{let t=r?document.createElementNS(`http://www.w3.org/1998/Math/MathML`,`template`):document.createElement(`template`);return t.innerHTML=e,n?t.content.firstChild.firstChild:r?t.firstChild:t.content.firstChild},o=t?()=>S(()=>document.importNode(i||=a(),!0)):()=>(i||=a()).cloneNode(!0);return o.cloneNode=o,o}function G(e,t=window.document){let n=t[de]||(t[de]=new Set);for(let r=0,i=e.length;r<i;r++){let i=e[r];n.has(i)||(n.add(i),t.addEventListener(i,X))}}function K(e,t,n){he(e)||(n==null?e.removeAttribute(t):e.setAttribute(t,n))}function q(e,t){he(e)||(t==null?e.removeAttribute(`class`):e.className=t)}function pe(e,t,n,r){if(r)Array.isArray(n)?(e[`$$${t}`]=n[0],e[`$$${t}Data`]=n[1]):e[`$$${t}`]=n;else if(Array.isArray(n)){let r=n[0];e.addEventListener(t,n[0]=t=>r.call(e,n[1],t))}else e.addEventListener(t,n,typeof n!=`function`&&n)}function J(e,t,n){n==null?e.style.removeProperty(t):e.style.setProperty(t,n)}function me(e,t,n){return S(()=>e(t,n))}function Y(e,t,n,r){if(n!==void 0&&!r&&(r=[]),typeof t!=`function`)return Z(e,t,r,n);y(r=>Z(e,t(),r,n),r)}function he(t){return!!e.context&&!e.done&&(!t||t.isConnected)}function X(t){if(e.registry&&e.events&&e.events.find(([e,n])=>n===t))return;let n=t.target,r=`$$${t.type}`,i=t.target,a=t.currentTarget,o=e=>Object.defineProperty(t,"target",{configurable:!0,value:e}),s=()=>{let e=n[r];if(e&&!n.disabled){let i=n[`${r}Data`];if(i===void 0?e.call(n,t):e.call(n,i,t),t.cancelBubble)return}return n.host&&typeof n.host!=`string`&&!n.host._$host&&n.contains(t.target)&&o(n.host),!0},c=()=>{for(;s()&&(n=n._$host||n.parentNode||n.host););};if(Object.defineProperty(t,"currentTarget",{configurable:!0,get(){return n||document}}),e.registry&&!e.done&&(e.done=_$HY.done=!0),t.composedPath){let e=t.composedPath();o(e[0]);for(let t=0;t<e.length-2&&(n=e[t],s());t++){if(n._$host){n=n._$host,c();break}if(n.parentNode===a)break}}else c();o(i)}function Z(e,t,n,r,i){let a=he(e);if(a){!n&&(n=[...e.childNodes]);let t=[];for(let e=0;e<n.length;e++){let r=n[e];r.nodeType===8&&r.data.slice(0,2)===`!$`?r.remove():t.push(r)}n=t}for(;typeof n==`function`;)n=n();if(t===n)return n;let o=typeof t,s=r!==void 0;if(e=s&&n[0]&&n[0].parentNode||e,o===`string`||o===`number`){if(a||o===`number`&&(t=t.toString(),t===n))return n;if(s){let i=n[0];i&&i.nodeType===3?i.data!==t&&(i.data=t):i=document.createTextNode(t),n=Q(e,n,r,i)}else n=n!==``&&typeof n==`string`?e.firstChild.data=t:e.textContent=t}else if(t==null||o===`boolean`){if(a)return n;n=Q(e,n,r)}else if(o===`function`)return y(()=>{let i=t();for(;typeof i==`function`;)i=i();n=Z(e,i,n,r)}),()=>n;else if(Array.isArray(t)){let o=[],c=n&&Array.isArray(n);if(ge(o,t,n,i))return y(()=>n=Z(e,o,n,r,!0)),()=>n;if(a){if(!o.length)return n;if(r===void 0)return n=[...e.childNodes];let t=o[0];if(t.parentNode!==e)return n;let i=[t];for(;(t=t.nextSibling)!==r;)i.push(t);return n=i}if(o.length===0){if(n=Q(e,n,r),s)return n}else c?n.length===0?_e(e,o,r):ue(e,n,o):(n&&Q(e),_e(e,o));n=o}else if(t.nodeType){if(a&&t.parentNode)return n=s?[t]:t;if(Array.isArray(n)){if(s)return n=Q(e,n,r,t);Q(e,n,null,t)}else n==null||n===``||!e.firstChild?e.appendChild(t):e.replaceChild(t,e.firstChild);n=t}return n}function ge(e,t,n,r){let i=!1;for(let a=0,o=t.length;a<o;a++){let o=t[a],s=n&&n[e.length],c;if(o!=null&&o!==!0&&o!==!1){if((c=typeof o)==`object`&&o.nodeType)e.push(o);else if(Array.isArray(o))i=ge(e,o,s)||i;else if(c===`function`){if(r){for(;typeof o==`function`;)o=o();i=ge(e,Array.isArray(o)?o:[o],Array.isArray(s)?s:[s])||i}else e.push(o),i=!0}else{let t=String(o);s&&s.nodeType===3&&s.data===t?e.push(s):e.push(document.createTextNode(t))}}}return i}function _e(e,t,n=null){for(let r=0,i=t.length;r<i;r++)e.insertBefore(t[r],n)}function Q(e,t,n,r){if(n===void 0)return e.textContent=``;let i=r||document.createTextNode(``);if(t.length){let r=!1;for(let a=t.length-1;a>=0;a--){let o=t[a];if(i!==o){let t=o.parentNode===e;!r&&!a?t?e.replaceChild(i,o):e.insertBefore(i,n):t&&o.remove()}else r=!0}}else e.insertBefore(i,n);return[i]}function ve(e){let t=ye(e.replace(/\r\n/g,`
2
+ `)).split(`
3
+ `),n=[],r=0;for(;r<t.length;){let e=t[r];if(/^```\w*\s*$/.test(e)){let e=[];for(r++;r<t.length&&!/^```\s*$/.test(t[r]);)e.push(t[r++]);r++,n.push(`<pre><code>${e.join(`
4
+ `)}</code></pre>`);continue}let a=e.match(/^(#{1,4})\s+(.*)$/);if(a){n.push(`<h${a[1].length}>${i(a[2])}</h${a[1].length}>`),r++;continue}let o=/^\s*\d+[.)]\s+/.test(e);if(o||/^\s*[-*]\s+/.test(e)){let e=[];for(;r<t.length;){let n=t[r].match(/^\s*[-*]\s+(.*)$/)??(o?t[r].match(/^\s*\d+[.)]\s+(.*)$/):null);if(!n)break;e.push(`<li>${i(n[1])}</li>`),r++}n.push(o?`<ol>${e.join(``)}</ol>`:`<ul>${e.join(``)}</ul>`);continue}if(/^\s*$/.test(e)){r++;continue}let s=[];for(;r<t.length&&!/^\s*$/.test(t[r])&&!/^#{1,4}\s/.test(t[r])&&!/^```/.test(t[r])&&!/^\s*([-*]|\d+[.)])\s/.test(t[r]);)s.push(t[r++]);n.push(`<p>${s.map(i).join(`<br>`)}</p>`)}return n.join(`
5
+ `);function i(e){return e.replace(/`([^`]+)`/g,`<code>$1</code>`).replace(/\*\*([^*]+)\*\*/g,`<strong>$1</strong>`).replace(/(^|\W)\*([^*]+)\*(?=\W|$)/g,`$1<em>$2</em>`).replace(/\[([^\]]+)\]\((https?:\/\/[^)\s]+)\)/g,`<a href="$2" rel="noopener noreferrer" target="_blank">$1</a>`)}}function ye(e){return e.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`).replace(/"/g,`&quot;`)}var be=`modulepreload`,xe=function(e){return`/`+e},Se={},Ce=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){let e=document.getElementsByTagName(`link`),i=document.querySelector(`meta[property=csp-nonce]`),a=i?.nonce||i?.getAttribute(`nonce`);function o(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}))))}function s(e){return import.meta.resolve?import.meta.resolve(e):new URL(e,import.meta.url).href}r=o(t.map(t=>{if(t=xe(t,n),t=s(t),t in Se)return;Se[t]=!0;let r=t.endsWith(`.css`);for(let n=e.length-1;n>=0;n--){let i=e[n];if(i.href===t&&(!r||i.rel===`stylesheet`))return}let i=document.createElement(`link`);if(i.rel=r?`stylesheet`:be,r||(i.as=`script`),i.crossOrigin=``,i.href=t,a&&i.setAttribute(`nonce`,a),document.head.appendChild(i),r)return new Promise((e,n)=>{i.addEventListener(`load`,e),i.addEventListener(`error`,()=>n(Error(`Unable to preload CSS for ${t}`)))})}))}function i(e){let t=new Event(`vite:preloadError`,{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then(t=>{for(let e of t||[])e.status===`rejected`&&i(e.reason);return e().catch(i)})},we=W(`<br>`),Te=W(`<span class="badge queued">⏳ <!> queued`),Ee=W(`<span class=sub>ℹ`),De=W(`<header class=chan-head><span class=hash>#</span><span class=title></span><span></span><span class=sub> · <!>/<!> · turns <!> · tools </span><span style=margin-left:auto;display:flex;gap:4px><button class=iconbtn title="terminal (t)">⌨</button><button class=iconbtn title="toggle details panel (d)">▤`),Oe=W(`<details class=reasoning><summary>💭 reasoning</summary><div class=mono>`),ke=W(`<div class=content><span class=cursor>▍`),Ae=W(`<div class="msg live"><div class=avatar style="background:#5865f233;border:1px solid #5865f266">🫖</div><div class=msg-body><div class=msg-head><span class=author style=color:var(--acc)>agent</span><span class=ts>streaming…`),je=W(`<div class=feed>`),Me=W(`<button class=jump>↓ `),Ne=W(`<div class=termdrawer><div class=termbar><span>⌨ terminal — <span class=mono></span></span><button class=iconbtn title="close terminal (t)">✕</button></div><div class=termhost>`),Pe=W(`<div class=composer><form><input type=text><label><input type=checkbox>auto-start</label><button type=submit>send</button></form><div class=hint>enter send · ↑↓ sessions · / focus · t terminal · d panel · esc interrupt · messages sent while the agent works are queued and delivered at the next turn boundary`),Fe=W(`<h3>🎛 session`),Ie=W(`<div class="card sesscard"><div class=sessrow><span class=k>agent</span><b></b><span></span></div><div class=sessrow><span class=k>workspace</span><span class="mono ellip"></span></div><div class=sessrow><span class=k>session</span><span class=mono>/`),Le=W(`<h3>🧦 model`),Re=W(`<div class=modelbox><select title="provider (OpenAI-compatible endpoint)"></select><div style=display:flex;gap:4px><input type=text list=model-list style=flex:1;min-width:0><datalist id=model-list></datalist><button title="apply to this session — takes effect from the agent's next turn">apply</button></div><div class=meta>current: `),ze=W(`<h3>⏯ controls`),Be=W(`<div class=btnrow><button title="run toward the goal (starts the loop)">▶ start</button><button title="interrupt: aborts the current LLM call; the running tool finishes first">■ stop</button><button title="branch off the conversation here — try things without disturbing the main line">⑂ fork</button><button title="remove agent from teapot (session log stays on disk)">🗑 remove`),Ve=W(`<h3>🎯 goal <span>`),He=W(`<form style=display:flex;gap:4px;margin-bottom:6px><input id=goal-input type=text placeholder="set new goal…"style="flex:1;background:var(--bg-darkest);border:none;border-radius:6px;padding:6px 8px;color:var(--fg);font:inherit"><button type=submit style="background:var(--acc);border:none;border-radius:6px;color:#fff;padding:0 10px;cursor:pointer">✓`),Ue=W(`<div class=card>`),We=W(`<h3>📈 progress`),Ge=W(`<div class=card>
6
+ <!>
7
+ <span class=muted>`),Ke=W(`<h3>📊 runtime`),qe=W(`<div class="card muted">turns <!> · tools <!> · compacted <!>
8
+ tokens in/out <!>/`),Je=W(`<h3>🌿 branches <span class=muted style=text-transform:none;letter-spacing:0>· click to filter the feed`),Ye=W(`<div><nav class=sidebar><h1>🫖 teapot<span></span><span style=float:right;display:flex;gap:4px><button class=iconbtn title="new agent">+</button><button class=iconbtn title=settings>⚙</button></span></h1><div class=agent-list></div><div class=metrics></div></nav><section class=channel></section><aside>`),Xe=W(`<span title="goal done">✓`),Ze=W(`<div><span></span><span>`),Qe=W(`<div class=muted style=display:grid;place-items:center;height:100%>select an agent`),$e=W(`<div class=muted style=display:grid;place-items:center;height:100%>no events yet — say something or press ▶ start`),et=W(`<div class="content muted">thinking…`),tt=W(`<option>`),nt=W(`<div class=muted>none yet`),rt=W(`<div><span></span><span> events`),it=W(`<div class=divider-msg>⑂ forked from <!> → `),at=W(`<div class=divider-msg>🎯 goal <!>: `),ot=W(`<div> → `),st=W(`<div class=avatar>`),ct=W(`<div class=msg-head><span class=author></span><span class=ts></span><span class=ts>`),lt=W(`<div><div class=msg-body>`),ut=W(`<span style=width:38px>`),dt=W(`<div class=content>`),ft=W(`<div class=msgfoot><span>copy summary`),pt=W(`<details class=embed><summary><b>⚙ </b> <span class=meta></span></summary><div class=mono>`),mt=W(`<details><summary><span class=meta></span></summary><div class=mono></div><div class=meta>ms`),ht=W(`<div class=meta>`),gt=W(`<div class=meta>⚠ `),_t=W(`<div class=meta>→ `),vt=W(`<div class=embed style=border-color:var(--ok)><div>📈 `),yt=W(`<div class="embed fail"><div class=mono>⚠ `),bt=W(`<div class="content muted">`),xt=W(`<button class=copybtn title="copy to clipboard">`),St=W(`<div class=overlay><div class=modal><div class=modal-head><b></b><button class=iconbtn>✕`),Ct=W(`<span style=color:var(--err);font-size:13px>`),wt=W(`<form style=display:flex;flex-direction:column;gap:10px><label>workspace directory<div style=display:flex;gap:6px><input type=text class="w100 mono"><button type=button>go</button><button type=button>↑</button></div></label><div class=dirlist></div><div style=display:flex;gap:10px><label style=flex:1>agent name <input type=text placeholder="(directory name)"></label><label>provider<select></select></label><label style=flex:1>model <input type=text placeholder="(provider default)"></label></div><button type=submit style=align-self:flex-end>create & start`),Tt=W(`<div class=direntry>📁 `),Et=W(`<form style=display:flex;flex-direction:column;gap:10px><label>providers (<!>)<textarea rows=8 class="mono w100"></textarea></label><div style=display:flex;gap:10px><label style=flex:1>default provider <input type=text></label><label>progress interval (min) <input type=number min=1 style=width:90px></label></div><label>scheduled tasks (JSON array)<textarea rows=7 class="mono w100"></textarea></label><button type=submit style=align-self:flex-end>save`),Dt={prompt:{name:`you`,icon:`🟧`,color:`#faa81a`},user:{name:`you`,icon:`🟧`,color:`#faa81a`},message:{name:`agent`,icon:`🫖`,color:`#5865f2`},tool_call:{name:`tool`,icon:`🔧`,color:`#3ba0c9`},progress:{name:`progress`,icon:`📈`,color:`#3ba55d`}},Ot=e=>Dt[e.type]??{name:e.type,icon:`•`,color:`#9298a5`},kt=new Set([`user`,`message`,`prompt`,`tool_call`,`tool_result`,`progress`,`state`,`error`,`fork`,`goal`]),At=e=>kt.has(e.type),jt=e=>{let t=new Date(e);return`${String(t.getHours()).padStart(2,`0`)}:${String(t.getMinutes()).padStart(2,`0`)}`};async function $(e,t){let n=localStorage.getItem(`teapot.token`),r=new Headers(t?.headers);n&&!r.has(`authorization`)&&r.set(`authorization`,`Bearer ${n}`);let i=await fetch(e,{...t,headers:r});if(!i.ok){let t=``;try{t=(await i.json())?.error??``}catch{}throw Error(t||`${e}: HTTP ${i.status}`)}return i.json()}var Mt=location.hash.match(/[#&]token=([^&]+)/);Mt&&(localStorage.setItem(`teapot.token`,decodeURIComponent(Mt[1])),history.replaceState(null,``,location.pathname+location.search));var Nt=()=>{let e=localStorage.getItem(`teapot.token`);return e?`?token=${encodeURIComponent(e)}`:``};function Pt(){let[e,t]=v([]),[n,r]=v(null),[i,a]=v([]),[o,s]=v([]),[c,l]=v(null),[u,d]=v(``),[f,p]=v(!0),[m,h]=v({providers:{}}),[g,_]=v(!1),[S,T]=v(!1),[E,ee]=v(localStorage.getItem(`teapot.panel`)===null?window.innerWidth>1100:localStorage.getItem(`teapot.panel`)===`1`),te=()=>{let e=!E();ee(e),localStorage.setItem(`teapot.panel`,e?`1`:`0`)},[ne,re]=v(``),[D,ie]=v(``),[O,k]=v([]),A=()=>Object.keys(m().providers??{});async function ae(e){if(e)try{let t=await $(`/api/models?provider=${encodeURIComponent(e)}`);k(t.models??[])}catch{k([])}}b(()=>{let e=I();e&&(re(e.provider||m().defaultProvider||A()[0]||``),ie(``),ae(ne()))});let[oe,se]=v(!0),[j,M]=v(0),[N,P]=v(null),ce=x(()=>i().filter(At)),F=()=>$(`/api/config`).then(h).catch(()=>{}),I=x(()=>e().find(e=>e.id===n())),L=()=>$(`/api/agents`).then(e=>t(e.agents)).catch(()=>{}),R=()=>$(`/api/metrics`).then(l).catch(()=>{}),[z,le]=v(null);async function ue(e){try{let t=z(),[n,r]=await Promise.all([$(`/api/agents/${e}/events?limit=300${t?`&branch=${encodeURIComponent(t)}`:``}`),$(`/api/agents/${e}/branches`)]);a(n.events),s(r.branches)}catch{}}function de(){return document.querySelector(`.feed`)}function fe(){let e=de();return!e||e.scrollHeight-e.scrollTop-e.clientHeight<80}function W(e=!1){let t=de();t&&(e||oe())&&(t.scrollTop=t.scrollHeight,M(0))}async function G(e,t=!0){r(e),P(null),le(null),localStorage.setItem(`teapot.session`,e),Q(e,t),await ue(e),requestAnimationFrame(()=>W(!0))}let[J,he]=v(!1),X=null,Z=null;w(()=>X?.close());function ge(){let e=location.protocol===`https:`?`wss://`:`ws://`;X=new WebSocket(`${e}${location.host}/api/ws${Nt()}`),X.onopen=()=>he(!0),X.onclose=()=>{he(!1),setTimeout(ge,1500)},X.onerror=()=>X?.close(),X.onmessage=e=>{let t=JSON.parse(e.data);if(t.kind!==`ping`&&t.kind!==`pong`){if(t.kind===`llm-delta`){t.agentId===n()&&P({text:t.text??``,reasoning:t.reasoning??``});return}Z||=setTimeout(async()=>{if(Z=null,await L(),await R(),n()){let e=i().length;await ue(n()),i().length!==e&&(P(null),fe()?W(!0):M(j()+(i().length-e)))}},400)}}}let _e=()=>decodeURIComponent(location.pathname.split(`/`)[2]??``);function Q(e,t=!0){let n=`/session/${encodeURIComponent(e)}`;t?history.pushState(null,``,n):history.replaceState(null,``,n)}window.addEventListener(`popstate`,()=>{let t=_e();t&&e().some(e=>e.id===t)&&t!==n()&&G(t,!1)}),b(()=>{let e=I();document.title=e?`${e.status===`running`?`▶ `:e.status===`error`?`⚠ `:``}${e.id} · teapot`:`teapot`}),window.addEventListener(`keydown`,t=>{let r=t.target;if(r&&(r.tagName===`INPUT`||r.tagName===`TEXTAREA`||r.isContentEditable)){t.key===`Escape`&&r.blur();return}if(t.key===`Escape`){if(g()){_(!1);return}if(S()){T(!1);return}let e=I();if(e?.status===`running`){$(`/api/agents/${e.id}/stop`,{method:`POST`}).then(L);return}E()&&window.innerWidth<=1100&&ee(!1);return}if(!(g()||S())){if(t.key===`/`)t.preventDefault(),document.querySelector(`.composer input[type=text]`)?.focus();else if(t.key===`d`)te();else if(t.key===`t`)be();else if(t.key===`ArrowDown`||t.key===`ArrowUp`){let r=e();if(r.length===0)return;t.preventDefault();let i=r.findIndex(e=>e.id===n()),a=t.key===`ArrowDown`?Math.min(i+1,r.length-1):Math.max(i-1,0);a!==i&&G(r[a].id)}}});let[ve,ye]=v(localStorage.getItem(`teapot.term`)===`1`),be=()=>{let e=!ve();ye(e),localStorage.setItem(`teapot.term`,e?`1`:`0`)},xe=null,Se=null,it=null,at=null,ot={cols:0,rows:0},st=null;function ct(){at?.disconnect(),at=null,it?.close(),it=null,Se?.dispose(),Se=null}function lt(e){ct(),xe&&Promise.all([Ce(()=>import(`./xterm-C3BHN0de.js`),[]),Ce(()=>import(`./addon-fit-DIOBYJe3.js`),[])]).then(([{Terminal:t},{FitAddon:n}])=>{let r=new t({cursorBlink:!0,fontSize:12.5,fontFamily:`ui-monospace, Menlo, Consolas, monospace`,theme:{background:`#0d0e12`,foreground:`#dcdee4`}}),i=new n;r.loadAddon(i),r.open(xe),i.fit(),Se=r;let a=location.protocol===`https:`?`wss://`:`ws://`,o=new WebSocket(`${a}${location.host}/api/agents/${e}/term${Nt()}`);it=o,o.onmessage=e=>{let t=JSON.parse(e.data);t.kind===`data`?r.write(t.data):t.kind===`exit`&&r.write(`\r\n\x1b[2m[terminal exited ${t.code??``}]\x1b[0m\r\n`)},r.onData(e=>{o.readyState===WebSocket.OPEN&&o.send(JSON.stringify({kind:`input`,data:e}))});let s=()=>{try{i.fit()}catch{}let{cols:e,rows:t}=r;(e!==ot.cols||t!==ot.rows)&&o.readyState===WebSocket.OPEN&&(ot={cols:e,rows:t},o.send(JSON.stringify({kind:`resize`,cols:e,rows:t})))};at=new ResizeObserver(()=>{st&&clearTimeout(st),st=setTimeout(s,300)}),at.observe(xe),setTimeout(s,50)})}b(()=>{let e=n();!ve()||!e?ct():requestAnimationFrame(()=>e&&lt(e))}),w(ct),C(()=>{F(),L().then(()=>{let t=_e()||localStorage.getItem(`teapot.session`)||``,n=e().find(e=>e.id===t)??e()[0];n&&G(n.id,!1)}),R(),ge();let t=setInterval(R,3e4);w(()=>clearInterval(t))});let ut=async e=>{e.preventDefault();let t=n(),r=u().trim();if(!(!t||!r)){d(``);try{await $(`/api/agents/${t}/prompt`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({text:r,start:f()})})}catch(e){d(r),console.error(`send failed:`,e)}}},dt=e=>()=>n()&&$(`/api/agents/${n()}${e}`,{method:`POST`}).then(L),ft=async e=>{e.preventDefault();let t=document.getElementById(`goal-input`);!n()||!t.value.trim()||(await $(`/api/agents/${n()}/goal`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({text:t.value})}),t.value=``,L())};return[(()=>{var i=Ye(),s=i.firstChild,l=s.firstChild,h=l.firstChild.nextSibling,g=h.nextSibling.firstChild,v=g.nextSibling,b=l.nextSibling,x=b.nextSibling,S=s.nextSibling,C=S.nextSibling;return g.$$click=()=>{F(),_(!0)},v.$$click=()=>{F(),T(!0)},Y(b,B(V,{get each(){return e()},children:e=>(()=>{var t=Ze(),r=t.firstChild,i=r.nextSibling;return t.$$click=()=>G(e.id),Y(i,()=>e.id),Y(t,B(H,{get when(){return e.goal.status===`done`},get children(){return Xe()}}),null),y(i=>{var a=`agent-item`+(e.id===n()?` sel`:``),o=`dot ${e.status}`;return a!==i.e&&q(t,i.e=a),o!==i.t&&q(r,i.t=o),i},{e:void 0,t:void 0}),t})()})),Y(x,B(H,{get when(){return c()},get children(){return[`master rss `,U(()=>c().rssMb),`MB · heap `,U(()=>c().heapUsedMb),`MB`,we(),`load1 `,U(()=>c().loadavg1),` · up `,U(()=>Math.floor(c().uptimeSec/60)),`m`]}})),Y(S,B(H,{get when(){return I()},get fallback(){return Qe()},get children(){return[(()=>{var e=De(),t=e.firstChild.nextSibling,n=t.nextSibling,r=n.nextSibling,i=r.firstChild,a=i.nextSibling,o=a.nextSibling.nextSibling,s=o.nextSibling.nextSibling;s.nextSibling;var c=r.nextSibling,l=c.firstChild,u=l.nextSibling;return Y(t,()=>I().id),Y(n,()=>I().status),Y(e,B(H,{get when(){return(I().pendingPrompts??0)>0},get children(){var e=Te(),t=e.firstChild.nextSibling;return t.nextSibling,Y(e,()=>I().pendingPrompts,t),y(()=>K(e,`title`,`${I().pendingPrompts} prompt(s) waiting — the agent picks them up at the next turn boundary`)),e}}),r),Y(r,()=>I().model,i),Y(r,()=>I().session,a),Y(r,()=>I().branch,o),Y(r,()=>I().stats.turns,s),Y(r,()=>I().stats.toolCalls,null),Y(c,B(H,{get when(){return I().statusReason},get children(){var e=Ee();return y(()=>K(e,`title`,I().statusReason)),e}}),l),l.$$click=be,u.$$click=te,y(()=>q(n,`badge ${I().status}`)),e})(),(()=>{var e=je();return e.addEventListener(`scroll`,()=>{let e=fe();e&&j()&&M(0),se(e)}),Y(e,B(H,{get when(){return ce().length>0},get fallback(){return $e()},get children(){return[B(V,{get each(){return ce()},children:(e,t)=>B(Ft,{e,get prev(){return ce()[t()-1]}})}),B(H,{get when(){return N()},get children(){var e=Ae(),t=e.firstChild.nextSibling;return t.firstChild,Y(t,B(H,{get when(){return N().reasoning},get children(){var e=Oe(),t=e.firstChild.nextSibling;return Y(t,()=>N().reasoning),e}}),null),Y(t,B(H,{get when(){return N().text},get fallback(){return et()},get children(){var e=ke(),t=e.firstChild;return Y(e,()=>N().text,t),e}}),null),e}})]}})),e})(),B(H,{get when(){return!oe()||j()>0},get children(){var e=Me();return e.firstChild,e.$$click=()=>W(!0),Y(e,(()=>{var e=U(()=>j()>0);return()=>e()?`${j()} new message${j()>1?`s`:``}`:`jump to present`})(),null),e}}),B(H,{get when(){return U(()=>!!ve())()&&I()},get children(){var e=Ne(),t=e.firstChild,n=t.firstChild,r=n.firstChild.nextSibling,i=n.nextSibling,a=t.nextSibling;return Y(r,()=>I().workspace),i.$$click=be,me(e=>xe=e,a),e}}),(()=>{var e=Pe(),t=e.firstChild,n=t.firstChild,r=n.nextSibling.firstChild;return t.addEventListener(`submit`,ut),n.$$input=e=>d(e.currentTarget.value),r.addEventListener(`change`,e=>p(e.currentTarget.checked)),y(()=>K(n,`placeholder`,`message #${I().id}`)),y(()=>n.value=u()),y(()=>r.checked=f()),e})()]}})),Y(C,B(H,{get when(){return I()},get children(){return[Fe(),(()=>{var e=Ie(),t=e.firstChild,n=t.firstChild.nextSibling,r=n.nextSibling,i=t.nextSibling,a=i.firstChild.nextSibling,o=i.nextSibling.firstChild.nextSibling,s=o.firstChild;return Y(n,()=>I().id),Y(r,()=>I().status),Y(a,()=>I().workspace),Y(o,()=>I().session,s),Y(o,()=>I().branch,null),y(e=>{var t=`badge ${I().status}`,n=I().workspace;return t!==e.e&&q(r,e.e=t),n!==e.t&&K(a,`title`,e.t=n),e},{e:void 0,t:void 0}),e})(),Le(),(()=>{var e=Re(),t=e.firstChild,r=t.nextSibling,i=r.firstChild,a=i.nextSibling,o=a.nextSibling,s=r.nextSibling;return s.firstChild,t.addEventListener(`change`,e=>{re(e.currentTarget.value),ae(e.currentTarget.value)}),Y(t,B(V,{get each(){return A()},children:e=>(()=>{var t=tt();return t.value=e,Y(t,e,null),Y(t,()=>e===m().defaultProvider?` ★`:``,null),t})()})),i.$$input=e=>ie(e.currentTarget.value),Y(a,B(V,{get each(){return O()},children:e=>(()=>{var t=tt();return t.value=e,t})()})),o.$$click=async e=>{if(!n())return;let t=e.currentTarget;t.disabled=!0;try{await $(`/api/agents/${n()}/model`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({provider:ne(),model:D().trim()||void 0})}),t.textContent=`✓ applied`,L()}catch(e){alert(`model switch failed: ${e.message}`)}finally{setTimeout(()=>{t.textContent=`apply`,t.disabled=!1},1200)}},Y(s,()=>I().model,null),Y(s,B(H,{get when(){return O().length},get children(){return[` · `,U(()=>O().length),` models loaded`]}}),null),y(()=>K(i,`placeholder`,I().model)),y(()=>t.value=ne()),y(()=>i.value=D()),e})(),ze(),(()=>{var i=Be(),o=i.firstChild,s=o.nextSibling,c=s.nextSibling,l=c.nextSibling;return pe(o,`click`,dt(`/start`),!0),pe(s,`click`,dt(`/stop`),!0),c.$$click=()=>$(`/api/agents/${I().id}/fork`,{method:`POST`,headers:{"content-type":`application/json`},body:`{}`}).then(()=>G(I().id)),l.$$click=async()=>{let i=n();if(!i||!confirm(`remove agent ${i}? (log is kept)`))return;await $(`/api/agents/${i}`,{method:`DELETE`}).catch(()=>{});let o=e().filter(e=>e.id!==i);t(o),o[0]?G(o[0].id):(r(null),a([]))},i})(),(()=>{var e=Ve(),t=e.firstChild.nextSibling;return Y(t,()=>I().goal.status),y(()=>q(t,`badge ${I().goal.status===`done`?`done`:``}`)),e})(),(()=>{var e=He();return e.addEventListener(`submit`,ft),e})(),(()=>{var e=Ue();return Y(e,()=>I().goal.text||`no goal set`),e})(),We(),B(H,{get when(){return I().latestProgress},get fallback(){return nt()},get children(){var e=Ge(),t=e.firstChild,n=t.nextSibling,r=n.nextSibling.nextSibling;return Y(e,()=>I().latestProgress.doing,t),Y(e,()=>I().latestProgress.recent??``,n),Y(r,()=>I().latestProgress.ts),e}}),Ke(),(()=>{var e=qe(),t=e.firstChild.nextSibling,n=t.nextSibling.nextSibling,r=n.nextSibling.nextSibling,i=r.nextSibling.nextSibling;return i.nextSibling,Y(e,()=>I().stats.turns,t),Y(e,()=>I().stats.toolCalls,n),Y(e,()=>I().stats.compactions??0,r),Y(e,()=>I().stats.inputTokens,i),Y(e,()=>I().stats.outputTokens,null),e})(),Je(),B(V,{get each(){return o()},children:e=>(()=>{var t=rt(),r=t.firstChild,i=r.nextSibling,a=i.firstChild;return t.$$click=()=>{let t=z()===e.branch?null:e.branch;le(t),n()&&ue(n())},Y(r,()=>e.branch,null),Y(r,()=>e.branch===I().branch?` (current)`:``,null),Y(i,()=>e.events,a),y(n=>{var r=`branch-row`+(e.branch===I().branch||e.branch===z()?` cur`:``),i=e.branch===z()?`click to show all branches again`:`show only ${e.branch}`;return r!==n.e&&q(t,n.e=r),i!==n.t&&K(t,`title`,n.t=i),n},{e:void 0,t:void 0}),t})()})]}})),y(e=>{var t=`layout`+(E()?``:` right-hidden`),n=`conn`+(J()?` ok`:``),r=J()?`live (websocket)`:`reconnecting…`,a=`rightbar`+(E()?` open`:``);return t!==e.e&&q(i,e.e=t),n!==e.t&&q(h,e.t=n),r!==e.a&&K(h,`title`,e.a=r),a!==e.o&&q(C,e.o=a),e},{e:void 0,t:void 0,a:void 0,o:void 0}),i})(),B(H,{get when(){return g()},get children(){return B(Vt,{get providers(){return Object.keys(m().providers??{})},onClose:()=>_(!1),onCreated:e=>{_(!1),L(),G(e)}})}}),B(H,{get when(){return S()},get children(){return B(Ht,{get cfg(){return m()},onClose:()=>T(!1),onSaved:F})}})]}function Ft(e){let t=e.e,n=Ot(t),r=e.prev&&e.prev.type===t.type&&t.session===e.prev.session&&t.branch===e.prev.branch;if(t.type===`fork`){let e=t.data??{};return(()=>{var n=it(),r=n.firstChild.nextSibling;return r.nextSibling,Y(n,()=>String(e.fromBranch??`?`),r),Y(n,()=>String(e.newBranch??t.branch),null),n})()}if(t.type===`goal`){let e=t.data??{},n=e.event===`status`?`marked ${String(e.status??``)}`:Rt(String(e.text??``),80);return(()=>{var t=at(),r=t.firstChild.nextSibling;return r.nextSibling,Y(t,()=>String(e.event??``),r),Y(t,n,null),t})()}return t.type===`state`?t.data.from===t.data.to?null:(()=>{var e=ot(),n=e.firstChild;return Y(e,()=>t.data.from,n),Y(e,()=>t.data.to,null),Y(e,(()=>{var e=U(()=>!!t.data.reason);return()=>e()?` — ${t.data.reason}`:``})(),null),y(()=>q(e,`divider-msg`+(t.data.to===`error`?` err`:``))),e})():(()=>{var e=lt(),i=e.firstChild;return q(e,`msg`+(r?` grouped`:``)),Y(e,B(H,{when:!r,get fallback(){return ut()},get children(){var e=st();return Y(e,()=>n.icon),y(t=>{var r=n.color+`33`,i=`1px solid ${n.color}66`;return r!==t.e&&J(e,`background`,t.e=r),i!==t.t&&J(e,`border`,t.t=i),t},{e:void 0,t:void 0}),e}}),i),Y(i,B(H,{when:!r,get children(){var e=ct(),r=e.firstChild,i=r.nextSibling,a=i.nextSibling;return Y(r,()=>n.name),Y(i,()=>jt(t.ts)),Y(a,()=>t.branch),y(e=>J(r,`color`,n.color)),e}}),null),Y(i,B(It,{e:t}),null),e})()}function It(e){let t=e.e;switch(t.type){case`prompt`:return(()=>{var e=dt();return y(()=>e.innerHTML=ve(String(t.data.text??``))),e})();case`message`:return[B(H,{get when(){return U(()=>typeof t.data.reasoning==`string`)()&&t.data.reasoning.trim()},get children(){var e=Oe(),n=e.firstChild.nextSibling;return Y(n,()=>String(t.data.reasoning)),e}}),(()=>{var e=dt();return y(()=>e.innerHTML=ve(String(t.data.content??``))),e})(),B(H,{get when(){return t.data.final},get children(){var e=ft(),n=e.firstChild;return Y(e,B(zt,{get text(){return String(t.data.content??``)}}),n),e}})];case`tool_call`:{let e=JSON.stringify(t.data.args,null,1),n=Rt(JSON.stringify(t.data.args??{}),110);return(()=>{var r=pt(),i=r.firstChild,a=i.firstChild;a.firstChild;var o=a.nextSibling.nextSibling,s=i.nextSibling;return Y(a,()=>String(t.data.name),null),Y(o,n),Y(s,e),r})()}case`tool_result`:{let e=String(t.data.result);return(()=>{var n=mt(),r=n.firstChild,i=r.firstChild,a=r.nextSibling,o=a.nextSibling,s=o.firstChild;return Y(i,()=>Rt(e,120)),Y(r,B(zt,{text:e}),null),Y(a,()=>Lt(e,4e3)),Y(o,()=>t.data.durationMs,s),Y(o,()=>t.data.ok?``:` · FAILED`,null),y(()=>q(n,`embed`+(t.data.ok?``:` fail`))),n})()}case`progress`:return(()=>{var e=vt(),n=e.firstChild;return n.firstChild,Y(n,()=>String(t.data.doing??``),null),Y(e,B(H,{get when(){return t.data.recent},get children(){var e=ht();return Y(e,()=>String(t.data.recent)),e}}),null),Y(e,B(H,{get when(){return t.data.problems},get children(){var e=gt();return e.firstChild,Y(e,()=>String(t.data.problems),null),e}}),null),Y(e,B(H,{get when(){return t.data.next},get children(){var e=_t();return e.firstChild,Y(e,()=>String(t.data.next),null),e}}),null),e})();case`error`:return(()=>{var e=yt(),n=e.firstChild;return n.firstChild,Y(n,()=>String(t.data.message??``),null),e})();default:return(()=>{var e=bt();return Y(e,()=>Lt(JSON.stringify(t.data),200)),e})()}}function Lt(e,t){return e.length>t?e.slice(0,t)+` …`:e}function Rt(e,t){return Lt(e.replace(/\s+/g,` `).trim(),t)}function zt(e){let[t,n]=v(!1);return(()=>{var r=xt();return r.$$click=t=>{t.stopPropagation(),navigator.clipboard.writeText(e.text).then(()=>{n(!0),setTimeout(()=>n(!1),900)})},Y(r,()=>t()?`✓`:`⧉`),r})()}function Bt(e){return(()=>{var t=St(),n=t.firstChild,r=n.firstChild.firstChild,i=r.nextSibling;return t.$$click=t=>t.target===t.currentTarget&&e.onClose(),Y(r,()=>e.title),pe(i,`click`,e.onClose,!0),Y(n,()=>e.children,null),t})()}function Vt(e){let[t,n]=v(`~`),[r,i]=v([]),[a,o]=v(``),[s,c]=v(e.providers[0]??``),[l,u]=v(``),[d,f]=v(``);async function p(e){let t=await $(`/api/fs${e?`?path=${encodeURIComponent(e)}`:``}`);n(t.path),i(t.entries)}C(()=>p(t()));let m=async n=>{n.preventDefault(),f(``);try{let n=await $(`/api/agents`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({workspace:t(),id:a(),provider:s()||void 0,model:l()||void 0})});e.onCreated(n.agent.id)}catch(e){f(String(e.message))}};return B(Bt,{title:`new agent`,get onClose(){return e.onClose},get children(){var i=wt(),f=i.firstChild,h=f.firstChild.nextSibling.firstChild,g=h.nextSibling,_=g.nextSibling,v=f.nextSibling,b=v.nextSibling,x=b.firstChild,S=x.firstChild.nextSibling,C=x.nextSibling,w=C.firstChild.nextSibling,T=C.nextSibling.firstChild.nextSibling,E=b.nextSibling;return i.addEventListener(`submit`,m),h.$$input=e=>n(e.currentTarget.value),g.$$click=()=>p(t()),_.$$click=()=>p(`..`),Y(v,B(V,{get each(){return r()},children:e=>(()=>{var n=Tt();return n.firstChild,n.$$click=()=>p(`${t()}/${e}`.replace(/\/+/g,`/`)),Y(n,e,null),n})()})),S.$$input=e=>o(e.currentTarget.value),w.addEventListener(`change`,e=>c(e.currentTarget.value)),Y(w,B(V,{get each(){return e.providers},children:e=>(()=>{var t=tt();return Y(t,e),t})()})),T.$$input=e=>u(e.currentTarget.value),Y(i,B(H,{get when(){return d()},get children(){var e=Ct();return Y(e,d),e}}),E),y(()=>h.value=t()),y(()=>S.value=a()),y(()=>w.value=s()),y(()=>T.value=l()),i}})}function Ht(e){let[t,n]=v(JSON.stringify(Object.fromEntries(Object.entries(e.cfg.providers??{}).map(([e,t])=>[e,{baseUrl:t.baseUrl,apiKey:t.apiKey??``,model:t.model??``}])),null,2)),[r,i]=v(e.cfg.defaultProvider??Object.keys(e.cfg.providers??{})[0]??``),[a,o]=v(Math.round((e.cfg.progressIntervalMs??6e5)/6e4)),[s,c]=v(JSON.stringify(e.cfg.tasks??[],null,2)),[l,u]=v(``),d=async n=>{n.preventDefault(),u(``);let i,o;try{i=JSON.parse(t())}catch{return u(`providers: invalid JSON`)}try{o=JSON.parse(s())}catch{return u(`tasks: invalid JSON`)}try{await $(`/api/config`,{method:`PUT`,headers:{"content-type":`application/json`},body:JSON.stringify({providers:i,defaultProvider:r(),progressIntervalMs:Math.max(1,a())*6e4,tasks:o})}),e.onSaved(),e.onClose()}catch(e){u(String(e.message))}};return B(Bt,{title:`settings`,get onClose(){return e.onClose},get children(){var u=Et(),f=u.firstChild,p=f.firstChild.nextSibling,m=p.nextSibling.nextSibling,h=f.nextSibling,g=h.firstChild,_=g.firstChild.nextSibling,v=g.nextSibling.firstChild.nextSibling,b=h.nextSibling,x=b.firstChild.nextSibling,S=b.nextSibling;return u.addEventListener(`submit`,d),Y(f,()=>e.cfg.configPath,p),m.$$input=e=>n(e.currentTarget.value),_.$$input=e=>i(e.currentTarget.value),v.$$input=e=>o(Number(e.currentTarget.value)),x.$$input=e=>c(e.currentTarget.value),Y(u,B(H,{get when(){return l()},get children(){var e=Ct();return Y(e,l),e}}),S),y(()=>m.value=t()),y(()=>_.value=r()),y(()=>v.value=a()),y(()=>x.value=s()),u}})}G([`click`,`input`]),fe(()=>B(Pt,{}),document.getElementById(`root`));
package/public/index.html CHANGED
@@ -4,8 +4,8 @@
4
4
  <meta charset="utf-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1">
6
6
  <title>teapot</title>
7
- <script type="module" crossorigin src="/assets/index-JRXeHcww.js"></script>
8
- <link rel="stylesheet" crossorigin href="/assets/index-DIs0rfrk.css">
7
+ <script type="module" crossorigin src="/assets/index-DxB6uahH.js"></script>
8
+ <link rel="stylesheet" crossorigin href="/assets/index-BE9Nw_-t.css">
9
9
  </head>
10
10
  <body>
11
11
  <div id="root"></div>
@@ -1 +0,0 @@
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;font-family:gg sans,ui-sans-serif,system-ui,-apple-system,Segoe UI,sans-serif}*{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 300px;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{display:block}.rightbar{z-index:5;width:min(320px,88vw);transition:transform .18s;position:fixed;top:0;bottom:0;right:0;transform:translate(100%);box-shadow:-8px 0 24px #0007}.rightbar.open{transform:none}}.sidebar{background:var(--bg-darkest);flex-direction:column;padding:10px 8px;display:flex;overflow-y:auto}.sidebar h1{color:var(--fg);flex-shrink:0;margin:0;padding:4px 8px 10px;font-size:14px}.agent-list{flex:1;min-height:0;overflow-y:auto}.agent-item{cursor:pointer;color:var(--dim);border-radius:6px;align-items:center;gap:8px;margin-bottom:2px;padding:7px 10px;display:flex}.agent-item:hover{background:var(--bg-mid)}.agent-item.sel{background:var(--bg-mid);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.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}.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)}.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.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}.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 code{background:var(--bg-darkest);border-radius:4px;padding:1px 4px;font-size:13px}.content h1,.content h2,.content h3,.content h4{margin:8px 0 2px;font-size:15px}.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 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}@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%;margin-left:8px;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}.msgfoot{color:var(--dim);align-items:center;gap:6px;margin-top:4px;font-size:11px;display:flex}.termdrawer{border-top:2px solid var(--line);background:#0d0e12;flex-direction:column;flex-shrink:0;height:38vh;min-height:220px;display:flex}.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}.termhost{flex:1;min-height:0;padding:6px 8px;overflow:hidden}.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;bottom:86px;left:50%;transform:translate(-50%);box-shadow:0 4px 14px #0008}.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)}.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}.composer form{background:var(--bg-light);border-radius:10px;align-items:center;gap:8px;padding:10px 12px;display:flex}.composer input[type=text]{color:var(--fg);font:inherit;background:0 0;border:none;outline:none;flex:1}.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}.rightbar{background:var(--bg-dark);border-left:2px solid var(--line);flex-direction:column;min-height:0;padding:14px;font-size:13px;display:flex;overflow-y:auto}.rightbar h3{text-transform:uppercase;letter-spacing:.04em;color:var(--dim);margin:14px 0 6px;font-size:11px}.rightbar h3:first-child{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}.muted{color:var(--dim)}.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)}.sesscard{flex-direction:column;gap:6px;font-size:12.5px;display:flex}.sessrow{align-items:center;gap:8px;display:flex}.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)}.iconbtn{background:var(--bg-light);color:var(--fg);cursor:pointer;border:none;border-radius:6px;width:26px;height:24px;font-size:13px}.iconbtn:hover{filter:brightness(1.3)}.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 select,.modal textarea{background:var(--bg-darkest);color:var(--fg);font:inherit;border:none;border-radius:6px;outline:none;padding:7px 9px}.modal textarea{resize:vertical}.w100{width:100%}.mono{font-family:ui-monospace,Menlo,monospace;font-size:13px}.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)}.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}
@@ -1,8 +0,0 @@
1
- (function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var e={context:void 0,registry:void 0,effects:void 0,done:!1,getContextId(){return t(this.context.count)},getNextContextId(){return t(this.context.count++)}};function t(t){let n=String(t),r=n.length-1;return e.context.id+(r?String.fromCharCode(96+r):``)+n}function n(t){e.context=t}var r=(e,t)=>e===t,i=Symbol(`solid-track`),a={equals:r},o=null,s=oe,c=1,l=2,u={owned:null,cleanups:null,context:null,owner:null},d=null,f=null,p=null,m=null,h=null,g=0;function _(e,t){let n=p,r=d,i=e.length===0,a=t===void 0?r:t,o=i?u:{owned:null,cleanups:null,context:a?a.context:null,owner:a},s=i?e:()=>e(()=>S(()=>N(o)));d=o,p=null;try{return A(s,!0)}finally{p=n,d=r}}function v(e,t){t=t?Object.assign({},a,t):a;let n={value:e,observers:null,observerSlots:null,comparator:t.equals||void 0};return[E.bind(n),e=>(typeof e==`function`&&(e=f&&f.running&&f.sources.has(n)?e(n.tValue):e(n.value)),re(n,e))]}function y(e,t,n){D(O(e,t,!1,c))}function b(e,t,n){s=se;let r=O(e,t,!1,c),i=ne&&te(ne);i&&(r.suspense=i),(!n||!n.render)&&(r.user=!0),h?h.push(r):D(r)}function x(e,t,n){n=n?Object.assign({},a,n):a;let r=O(e,t,!0,0);return r.observers=null,r.observerSlots=null,r.comparator=n.equals||void 0,D(r),E.bind(r)}function S(e){if(p===null)return e();let t=p;p=null;try{return e()}finally{p=t}}function ee(e){b(()=>S(e))}function C(e){return d===null||(d.cleanups===null?d.cleanups=[e]:d.cleanups.push(e)),e}var[w,T]=v(!1);function te(e){let t;return d&&d.context&&(t=d.context[e.id])!==void 0?t:e.defaultValue}var ne;function E(){let e=f&&f.running;if(this.sources&&(e?this.tState:this.state)){if((e?this.tState:this.state)===c)D(this);else{let e=m;m=null,A(()=>j(this),!1),m=e}}if(p){let e=this.observers;if(!e||e[e.length-1]!==p){let t=e?e.length:0;p.sources?(p.sources.push(this),p.sourceSlots.push(t)):(p.sources=[this],p.sourceSlots=[t]),e?(e.push(p),this.observerSlots.push(p.sources.length-1)):(this.observers=[p],this.observerSlots=[p.sources.length-1])}}return e&&f.sources.has(this)?this.tValue:this.value}function re(e,t,n){let r=f&&f.running&&f.sources.has(e)?e.tValue:e.value;if(!e.comparator||!e.comparator(r,t)){if(f){let r=f.running;(r||!n&&f.sources.has(e))&&(f.sources.add(e),e.tValue=t),r||(e.value=t)}else e.value=t;e.observers&&e.observers.length&&A(()=>{for(let t=0;t<e.observers.length;t+=1){let n=e.observers[t],r=f&&f.running;r&&f.disposed.has(n)||((r?!n.tState:!n.state)&&(n.pure?m.push(n):h.push(n),n.observers&&M(n)),r?n.tState=c:n.state=c)}if(m.length>1e6)throw m=[],Error()},!1)}return t}function D(e){if(!e.fn)return;N(e);let t=g;ie(e,f&&f.running&&f.sources.has(e)?e.tValue:e.value,t),f&&!f.running&&f.sources.has(e)&&queueMicrotask(()=>{A(()=>{f&&(f.running=!0),p=d=e,ie(e,e.tValue,t),p=d=null},!1)})}function ie(e,t,n){let r,i=d,a=p;p=d=e;try{r=e.fn(t)}catch(t){return e.pure&&(f&&f.running?(e.tState=c,e.tOwned&&e.tOwned.forEach(N),e.tOwned=void 0):(e.state=c,e.owned&&e.owned.forEach(N),e.owned=null)),e.updatedAt=n+1,I(t)}finally{p=a,d=i}(!e.updatedAt||e.updatedAt<=n)&&(e.updatedAt!=null&&`observers`in e?re(e,r,!0):f&&f.running&&e.pure?(f.sources.has(e)||(e.value=r),f.sources.add(e),e.tValue=r):e.value=r,e.updatedAt=n)}function O(e,t,n,r=c,i){let a={fn:e,state:r,updatedAt:null,owned:null,sources:null,sourceSlots:null,cleanups:null,value:t,owner:d,context:d?d.context:null,pure:n};return f&&f.running&&(a.state=0,a.tState=r),d===null||d!==u&&(f&&f.running&&d.pure?d.tOwned?d.tOwned.push(a):d.tOwned=[a]:d.owned?d.owned.push(a):d.owned=[a]),a}function k(e){let t=f&&f.running;if((t?e.tState:e.state)===0)return;if((t?e.tState:e.state)===l)return j(e);if(e.suspense&&S(e.suspense.inFallback))return e.suspense.effects.push(e);let n=[e];for(;(e=e.owner)&&(!e.updatedAt||e.updatedAt<g);){if(t&&f.disposed.has(e))return;(t?e.tState:e.state)&&n.push(e)}for(let r=n.length-1;r>=0;r--){if(e=n[r],t){let t=e,i=n[r+1];for(;(t=t.owner)&&t!==i;)if(f.disposed.has(t))return}if((t?e.tState:e.state)===c)D(e);else if((t?e.tState:e.state)===l){let t=m;m=null,A(()=>j(e,n[0]),!1),m=t}}}function A(e,t){if(m)return e();let n=!1;t||(m=[]),h?n=!0:h=[],g++;try{let t=e();return ae(n),t}catch(e){n||(h=null),m=null,I(e)}}function ae(e){if(m&&=(oe(m),null),e)return;let t;if(f){if(!f.promises.size&&!f.queue.size){let e=f.sources,n=f.disposed;h.push.apply(h,f.effects),t=f.resolve;for(let e of h)`tState`in e&&(e.state=e.tState),delete e.tState;f=null,A(()=>{for(let e of n)N(e);for(let t of e){if(t.value=t.tValue,t.owned)for(let e=0,n=t.owned.length;e<n;e++)N(t.owned[e]);t.tOwned&&(t.owned=t.tOwned),delete t.tValue,delete t.tOwned,t.tState=0}T(!1)},!1)}else if(f.running){f.running=!1,f.effects.push.apply(f.effects,h),h=null,T(!0);return}}let n=h;h=null,n.length&&A(()=>s(n),!1),t&&t()}function oe(e){for(let t=0;t<e.length;t++)k(e[t])}function se(t){let r,i=0;for(r=0;r<t.length;r++){let e=t[r];e.user?t[i++]=e:k(e)}if(e.context){if(e.count){e.effects||=[],e.effects.push(...t.slice(0,i));return}n()}for(e.effects&&(e.done||!e.count)&&(t=[...e.effects,...t],i+=e.effects.length,delete e.effects),r=0;r<i;r++)k(t[r])}function j(e,t){let n=f&&f.running;n?e.tState=0:e.state=0;for(let r=0;r<e.sources.length;r+=1){let i=e.sources[r];if(i.sources){let e=n?i.tState:i.state;e===c?i!==t&&(!i.updatedAt||i.updatedAt<g)&&k(i):e===l&&j(i,t)}}}function M(e){let t=f&&f.running;for(let n=0;n<e.observers.length;n+=1){let r=e.observers[n];(t?!r.tState:!r.state)&&(t?r.tState=l:r.state=l,r.pure?m.push(r):h.push(r),r.observers&&M(r))}}function N(e){let t;if(e.sources)for(;e.sources.length;){let t=e.sources.pop(),n=e.sourceSlots.pop(),r=t.observers;if(r&&r.length){let e=r.pop(),i=t.observerSlots.pop();n<r.length&&(e.sourceSlots[i]=n,r[n]=e,t.observerSlots[n]=i)}}if(e.tOwned){for(t=e.tOwned.length-1;t>=0;t--)N(e.tOwned[t]);delete e.tOwned}if(f&&f.running&&e.pure)P(e,!0);else if(e.owned){for(t=e.owned.length-1;t>=0;t--)N(e.owned[t]);e.owned=null}if(e.cleanups){for(t=e.cleanups.length-1;t>=0;t--)e.cleanups[t]();e.cleanups=null}f&&f.running?e.tState=0:e.state=0}function P(e,t){if(t||(e.tState=0,f.disposed.add(e)),e.owned)for(let t=0;t<e.owned.length;t++)P(e.owned[t])}function ce(e){return e instanceof Error?e:Error(typeof e==`string`?e:`Unknown error`,{cause:e})}function F(e,t,n){try{for(let n of t)n(e)}catch(e){I(e,n&&n.owner||null)}}function I(e,t=d){let n=o&&t&&t.context&&t.context[o],r=ce(e);if(!n)throw r;h?h.push({fn(){F(r,n,t)},state:c}):F(r,n,t)}var L=Symbol(`fallback`);function R(e){for(let t=0;t<e.length;t++)e[t]()}function le(e,t,n={}){let r=[],a=[],o=[],s=0,c=t.length>1?[]:null;return C(()=>R(o)),()=>{let l=e()||[],u=l.length,d,f;return l[i],S(()=>{let e,t,i,m,h,g,v,y,b;if(u===0)s!==0&&(R(o),o=[],r=[],a=[],s=0,c&&=[]),n.fallback&&(r=[L],a[0]=_(e=>(o[0]=e,n.fallback())),s=1);else if(s===0){for(a=Array(u),f=0;f<u;f++)r[f]=l[f],a[f]=_(p);s=u}else{for(i=Array(u),m=Array(u),c&&(h=Array(u)),g=0,v=Math.min(s,u);g<v&&r[g]===l[g];g++);for(v=s-1,y=u-1;v>=g&&y>=g&&r[v]===l[y];v--,y--)i[y]=a[v],m[y]=o[v],c&&(h[y]=c[v]);for(e=new Map,t=Array(y+1),f=y;f>=g;f--)b=l[f],d=e.get(b),t[f]=d===void 0?-1:d,e.set(b,f);for(d=g;d<=v;d++)b=r[d],f=e.get(b),f!==void 0&&f!==-1?(i[f]=a[d],m[f]=o[d],c&&(h[f]=c[d]),f=t[f],e.set(b,f)):o[d]();for(f=g;f<u;f++)f in i?(a[f]=i[f],o[f]=m[f],c&&(c[f]=h[f],c[f](f))):a[f]=_(p);a=a.slice(0,s=u),r=l.slice(0)}return a});function p(e){if(o[f]=e,c){let[e,n]=v(f);return c[f]=n,t(l[f],e)}return t(l[f])}}}function z(e,t){return S(()=>e(t||{}))}var ue=e=>`Stale read from <${e}>.`;function B(e){let t=`fallback`in e&&{fallback:()=>e.fallback};return x(le(()=>e.each,e.children,t||void 0))}function V(e){let t=e.keyed,n=x(()=>e.when,void 0,void 0),r=t?n:x(n,void 0,{equals:(e,t)=>!e==!t});return x(()=>{let i=r();if(i){let a=e.children;return typeof a==`function`&&a.length>0?S(()=>a(t?i:()=>{if(!S(r))throw ue(`Show`);return n()})):a}return e.fallback},void 0,void 0)}var H=e=>x(()=>e());function de(e,t,n){let r=n.length,i=t.length,a=r,o=0,s=0,c=t[i-1].nextSibling,l=null;for(;o<i||s<a;){if(t[o]===n[s]){o++,s++;continue}for(;t[i-1]===n[a-1];)i--,a--;if(i===o){let t=a<r?s?n[s-1].nextSibling:n[a-s]:c;for(;s<a;)e.insertBefore(n[s++],t)}else if(a===s)for(;o<i;)(!l||!l.has(t[o]))&&t[o].remove(),o++;else if(t[o]===n[a-1]&&n[s]===t[i-1]){let r=t[--i].nextSibling;e.insertBefore(n[s++],t[o++].nextSibling),e.insertBefore(n[--a],r),t[i]=n[a]}else{if(!l){l=new Map;let e=s;for(;e<a;)l.set(n[e],e++)}let r=l.get(t[o]);if(r!=null){if(s<r&&r<a){let c=o,u=1,d;for(;++c<i&&c<a&&(d=l.get(t[c]))!=null&&d===r+u;)u++;if(u>r-s){let i=t[o];for(;s<r;)e.insertBefore(n[s++],i)}else e.replaceChild(n[s++],t[o++])}else o++}else t[o++].remove()}}}var U=`_$DX_DELEGATE`;function W(e,t,n,r={}){let i;return _(r=>{i=r,t===document?e():J(t,e(),t.firstChild?null:void 0,n)},r.owner),()=>{i(),t.textContent=``}}function G(e,t,n,r){let i,a=()=>{let t=r?document.createElementNS(`http://www.w3.org/1998/Math/MathML`,`template`):document.createElement(`template`);return t.innerHTML=e,n?t.content.firstChild.firstChild:r?t.firstChild:t.content.firstChild},o=t?()=>S(()=>document.importNode(i||=a(),!0)):()=>(i||=a()).cloneNode(!0);return o.cloneNode=o,o}function fe(e,t=window.document){let n=t[U]||(t[U]=new Set);for(let r=0,i=e.length;r<i;r++){let i=e[r];n.has(i)||(n.add(i),t.addEventListener(i,_e))}}function pe(e,t,n){ge(e)||(n==null?e.removeAttribute(t):e.setAttribute(t,n))}function K(e,t){ge(e)||(t==null?e.removeAttribute(`class`):e.className=t)}function me(e,t,n,r){if(r)Array.isArray(n)?(e[`$$${t}`]=n[0],e[`$$${t}Data`]=n[1]):e[`$$${t}`]=n;else if(Array.isArray(n)){let r=n[0];e.addEventListener(t,n[0]=t=>r.call(e,n[1],t))}else e.addEventListener(t,n,typeof n!=`function`&&n)}function q(e,t,n){n==null?e.style.removeProperty(t):e.style.setProperty(t,n)}function he(e,t,n){return S(()=>e(t,n))}function J(e,t,n,r){if(n!==void 0&&!r&&(r=[]),typeof t!=`function`)return Y(e,t,r,n);y(r=>Y(e,t(),r,n),r)}function ge(t){return!!e.context&&!e.done&&(!t||t.isConnected)}function _e(t){if(e.registry&&e.events&&e.events.find(([e,n])=>n===t))return;let n=t.target,r=`$$${t.type}`,i=t.target,a=t.currentTarget,o=e=>Object.defineProperty(t,"target",{configurable:!0,value:e}),s=()=>{let e=n[r];if(e&&!n.disabled){let i=n[`${r}Data`];if(i===void 0?e.call(n,t):e.call(n,i,t),t.cancelBubble)return}return n.host&&typeof n.host!=`string`&&!n.host._$host&&n.contains(t.target)&&o(n.host),!0},c=()=>{for(;s()&&(n=n._$host||n.parentNode||n.host););};if(Object.defineProperty(t,"currentTarget",{configurable:!0,get(){return n||document}}),e.registry&&!e.done&&(e.done=_$HY.done=!0),t.composedPath){let e=t.composedPath();o(e[0]);for(let t=0;t<e.length-2&&(n=e[t],s());t++){if(n._$host){n=n._$host,c();break}if(n.parentNode===a)break}}else c();o(i)}function Y(e,t,n,r,i){let a=ge(e);if(a){!n&&(n=[...e.childNodes]);let t=[];for(let e=0;e<n.length;e++){let r=n[e];r.nodeType===8&&r.data.slice(0,2)===`!$`?r.remove():t.push(r)}n=t}for(;typeof n==`function`;)n=n();if(t===n)return n;let o=typeof t,s=r!==void 0;if(e=s&&n[0]&&n[0].parentNode||e,o===`string`||o===`number`){if(a||o===`number`&&(t=t.toString(),t===n))return n;if(s){let i=n[0];i&&i.nodeType===3?i.data!==t&&(i.data=t):i=document.createTextNode(t),n=Z(e,n,r,i)}else n=n!==``&&typeof n==`string`?e.firstChild.data=t:e.textContent=t}else if(t==null||o===`boolean`){if(a)return n;n=Z(e,n,r)}else if(o===`function`)return y(()=>{let i=t();for(;typeof i==`function`;)i=i();n=Y(e,i,n,r)}),()=>n;else if(Array.isArray(t)){let o=[],c=n&&Array.isArray(n);if(ve(o,t,n,i))return y(()=>n=Y(e,o,n,r,!0)),()=>n;if(a){if(!o.length)return n;if(r===void 0)return n=[...e.childNodes];let t=o[0];if(t.parentNode!==e)return n;let i=[t];for(;(t=t.nextSibling)!==r;)i.push(t);return n=i}if(o.length===0){if(n=Z(e,n,r),s)return n}else c?n.length===0?X(e,o,r):de(e,n,o):(n&&Z(e),X(e,o));n=o}else if(t.nodeType){if(a&&t.parentNode)return n=s?[t]:t;if(Array.isArray(n)){if(s)return n=Z(e,n,r,t);Z(e,n,null,t)}else n==null||n===``||!e.firstChild?e.appendChild(t):e.replaceChild(t,e.firstChild);n=t}return n}function ve(e,t,n,r){let i=!1;for(let a=0,o=t.length;a<o;a++){let o=t[a],s=n&&n[e.length],c;if(o!=null&&o!==!0&&o!==!1){if((c=typeof o)==`object`&&o.nodeType)e.push(o);else if(Array.isArray(o))i=ve(e,o,s)||i;else if(c===`function`){if(r){for(;typeof o==`function`;)o=o();i=ve(e,Array.isArray(o)?o:[o],Array.isArray(s)?s:[s])||i}else e.push(o),i=!0}else{let t=String(o);s&&s.nodeType===3&&s.data===t?e.push(s):e.push(document.createTextNode(t))}}}return i}function X(e,t,n=null){for(let r=0,i=t.length;r<i;r++)e.insertBefore(t[r],n)}function Z(e,t,n,r){if(n===void 0)return e.textContent=``;let i=r||document.createTextNode(``);if(t.length){let r=!1;for(let a=t.length-1;a>=0;a--){let o=t[a];if(i!==o){let t=o.parentNode===e;!r&&!a?t?e.replaceChild(i,o):e.insertBefore(i,n):t&&o.remove()}else r=!0}}else e.insertBefore(i,n);return[i]}function ye(e){let t=be(e.replace(/\r\n/g,`
2
- `)).split(`
3
- `),n=[],r=0;for(;r<t.length;){let e=t[r];if(/^```\w*\s*$/.test(e)){let e=[];for(r++;r<t.length&&!/^```\s*$/.test(t[r]);)e.push(t[r++]);r++,n.push(`<pre><code>${e.join(`
4
- `)}</code></pre>`);continue}let a=e.match(/^(#{1,4})\s+(.*)$/);if(a){n.push(`<h${a[1].length}>${i(a[2])}</h${a[1].length}>`),r++;continue}let o=/^\s*\d+[.)]\s+/.test(e);if(o||/^\s*[-*]\s+/.test(e)){let e=[];for(;r<t.length;){let n=t[r].match(/^\s*[-*]\s+(.*)$/)??(o?t[r].match(/^\s*\d+[.)]\s+(.*)$/):null);if(!n)break;e.push(`<li>${i(n[1])}</li>`),r++}n.push(o?`<ol>${e.join(``)}</ol>`:`<ul>${e.join(``)}</ul>`);continue}if(/^\s*$/.test(e)){r++;continue}let s=[];for(;r<t.length&&!/^\s*$/.test(t[r])&&!/^#{1,4}\s/.test(t[r])&&!/^```/.test(t[r])&&!/^\s*([-*]|\d+[.)])\s/.test(t[r]);)s.push(t[r++]);n.push(`<p>${s.map(i).join(`<br>`)}</p>`)}return n.join(`
5
- `);function i(e){return e.replace(/`([^`]+)`/g,`<code>$1</code>`).replace(/\*\*([^*]+)\*\*/g,`<strong>$1</strong>`).replace(/(^|\W)\*([^*]+)\*(?=\W|$)/g,`$1<em>$2</em>`).replace(/\[([^\]]+)\]\((https?:\/\/[^)\s]+)\)/g,`<a href="$2" rel="noopener noreferrer" target="_blank">$1</a>`)}}function be(e){return e.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`).replace(/"/g,`&quot;`)}var xe=`modulepreload`,Se=function(e){return`/`+e},Q={},Ce=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){let e=document.getElementsByTagName(`link`),i=document.querySelector(`meta[property=csp-nonce]`),a=i?.nonce||i?.getAttribute(`nonce`);function o(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}))))}function s(e){return import.meta.resolve?import.meta.resolve(e):new URL(e,import.meta.url).href}r=o(t.map(t=>{if(t=Se(t,n),t=s(t),t in Q)return;Q[t]=!0;let r=t.endsWith(`.css`);for(let n=e.length-1;n>=0;n--){let i=e[n];if(i.href===t&&(!r||i.rel===`stylesheet`))return}let i=document.createElement(`link`);if(i.rel=r?`stylesheet`:xe,r||(i.as=`script`),i.crossOrigin=``,i.href=t,a&&i.setAttribute(`nonce`,a),document.head.appendChild(i),r)return new Promise((e,n)=>{i.addEventListener(`load`,e),i.addEventListener(`error`,()=>n(Error(`Unable to preload CSS for ${t}`)))})}))}function i(e){let t=new Event(`vite:preloadError`,{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then(t=>{for(let e of t||[])e.status===`rejected`&&i(e.reason);return e().catch(i)})},we=G(`<br>`),Te=G(`<span class=sub>ℹ`),Ee=G(`<header class=chan-head><span class=hash>#</span><span class=title></span><span></span><span class=sub> · <!>/<!> · turns <!> · tools </span><span style=margin-left:auto;display:flex;gap:4px><button class=iconbtn title="terminal (t)">⌨</button><button class=iconbtn title="toggle details panel (d)">▤`),De=G(`<details class=reasoning><summary>💭 reasoning</summary><div class=mono>`),Oe=G(`<div class=content><span class=cursor>▍`),ke=G(`<div class="msg live"><div class=avatar style="background:#5865f233;border:1px solid #5865f266">🫖</div><div class=msg-body><div class=msg-head><span class=author style=color:var(--acc)>agent</span><span class=ts>streaming…`),Ae=G(`<div class=feed>`),je=G(`<button class=jump>↓ `),Me=G(`<div class=termdrawer><div class=termbar><span>⌨ terminal — <span class=mono></span></span><button class=iconbtn title="close terminal (t)">✕</button></div><div class=termhost>`),Ne=G(`<div class=composer><form><input type=text><label><input type=checkbox>auto-start</label><button type=submit>send</button></form><div class=hint>enter send · ↑↓ sessions · / focus · t terminal · d panel · esc stop · prompts queue while the agent works`),Pe=G(`<h3>🎛 session`),Fe=G(`<div class="card sesscard"><div class=sessrow><span class=k>agent</span><b></b><span></span></div><div class=sessrow><span class=k>workspace</span><span class="mono ellip"></span></div><div class=sessrow><span class=k>session</span><span class=mono>/`),Ie=G(`<h3>🧦 model`),Le=G(`<div class=modelbox><select title="provider (OpenAI-compatible endpoint)"></select><div style=display:flex;gap:4px><input type=text list=model-list style=flex:1;min-width:0><datalist id=model-list></datalist><button title="apply model to this session">apply</button></div><div class=meta>current: `),Re=G(`<h3>⏯ controls`),ze=G(`<div class=btnrow><button title="run toward the goal">▶ start</button><button title="interrupt after the current tool finishes">■ stop</button><button>⑂ fork</button><button title="remove agent">🗑`),Be=G(`<h3>🎯 goal <span>`),Ve=G(`<form style=display:flex;gap:4px;margin-bottom:6px><input id=goal-input type=text placeholder="set new goal…"style="flex:1;background:var(--bg-darkest);border:none;border-radius:6px;padding:6px 8px;color:var(--fg);font:inherit"><button type=submit style="background:var(--acc);border:none;border-radius:6px;color:#fff;padding:0 10px;cursor:pointer">✓`),He=G(`<div class=card>`),Ue=G(`<h3>📈 progress`),We=G(`<div class=card>
6
- <!>
7
- <span class=muted>`),Ge=G(`<h3>📊 runtime`),Ke=G(`<div class="card muted">turns <!> · tools <!> · compacted <!>
8
- tokens in/out <!>/`),qe=G(`<h3>🌿 branches`),Je=G(`<div><nav class=sidebar><h1>🫖 teapot<span></span><span style=float:right;display:flex;gap:4px><button class=iconbtn title="new agent">+</button><button class=iconbtn title=settings>⚙</button></span></h1><div class=agent-list></div><div class=metrics></div></nav><section class=channel></section><aside>`),Ye=G(`<span title="goal done">✓`),Xe=G(`<div><span></span><span>`),Ze=G(`<div class=muted style=display:grid;place-items:center;height:100%>select an agent`),Qe=G(`<div class=muted style=display:grid;place-items:center;height:100%>no events yet — say something or press ▶ start`),$e=G(`<div class="content muted">thinking…`),et=G(`<option>`),tt=G(`<div class=muted>none yet`),nt=G(`<div><span>`),rt=G(`<div> → `),it=G(`<div class=avatar>`),at=G(`<div class=msg-head><span class=author></span><span class=ts></span><span class=ts>`),ot=G(`<div><div class=msg-body>`),st=G(`<span style=width:38px>`),ct=G(`<div class=content>`),lt=G(`<div class=msgfoot><span>copy summary`),ut=G(`<details class=embed><summary><b>⚙ </b> <span class=meta></span></summary><div class=mono>`),dt=G(`<details><summary><span class=meta></span></summary><div class=mono></div><div class=meta>ms`),ft=G(`<div class=meta>`),pt=G(`<div class=meta>⚠ `),mt=G(`<div class=meta>→ `),ht=G(`<div class=embed style=border-color:var(--ok)><div>📈 `),gt=G(`<div class="embed fail"><div class=mono>⚠ `),_t=G(`<div class="content muted">`),vt=G(`<button class=copybtn title="copy to clipboard">`),yt=G(`<div class=overlay><div class=modal><div class=modal-head><b></b><button class=iconbtn>✕`),bt=G(`<span style=color:var(--err);font-size:13px>`),xt=G(`<form style=display:flex;flex-direction:column;gap:10px><label>workspace directory<div style=display:flex;gap:6px><input type=text class="w100 mono"><button type=button>go</button><button type=button>↑</button></div></label><div class=dirlist></div><div style=display:flex;gap:10px><label style=flex:1>agent name <input type=text placeholder="(directory name)"></label><label>provider<select></select></label><label style=flex:1>model <input type=text placeholder="(provider default)"></label></div><button type=submit style=align-self:flex-end>create & start`),St=G(`<div class=direntry>📁 `),Ct=G(`<form style=display:flex;flex-direction:column;gap:10px><label>providers (<!>)<textarea rows=8 class="mono w100"></textarea></label><div style=display:flex;gap:10px><label style=flex:1>default provider <input type=text></label><label>progress interval (min) <input type=number min=1 style=width:90px></label></div><label>scheduled tasks (JSON array)<textarea rows=7 class="mono w100"></textarea></label><button type=submit style=align-self:flex-end>save`),wt={user:{name:`you`,icon:`🧑`,color:`#faa81a`},message:{name:`agent`,icon:`🫖`,color:`#5865f2`},tool_call:{name:`tool`,icon:`🔧`,color:`#3ba0c9`},progress:{name:`progress`,icon:`📈`,color:`#3ba55d`}},Tt=e=>wt[e.type]??{name:e.type,icon:`•`,color:`#9298a5`},Et=new Set([`user`,`message`,`prompt`,`tool_call`,`tool_result`,`progress`]),Dt=e=>Et.has(e.type),Ot=e=>{let t=new Date(e);return`${String(t.getHours()).padStart(2,`0`)}:${String(t.getMinutes()).padStart(2,`0`)}`};async function $(e,t){let n=localStorage.getItem(`teapot.token`),r=new Headers(t?.headers);n&&!r.has(`authorization`)&&r.set(`authorization`,`Bearer ${n}`);let i=await fetch(e,{...t,headers:r});if(!i.ok)throw Error(`${e}: ${i.status}`);return i.json()}var kt=location.hash.match(/[#&]token=([^&]+)/);kt&&(localStorage.setItem(`teapot.token`,decodeURIComponent(kt[1])),history.replaceState(null,``,location.pathname+location.search));var At=()=>{let e=localStorage.getItem(`teapot.token`);return e?`?token=${encodeURIComponent(e)}`:``};function jt(){let[e,t]=v([]),[n,r]=v(null),[i,a]=v([]),[o,s]=v([]),[c,l]=v(null),[u,d]=v(``),[f,p]=v(!0),[m,h]=v({providers:{}}),[g,_]=v(!1),[S,w]=v(!1),[T,te]=v(localStorage.getItem(`teapot.panel`)===null?window.innerWidth>1100:localStorage.getItem(`teapot.panel`)===`1`),ne=()=>{te(!T()),localStorage.setItem(`teapot.panel`,T()?`1`:`0`)},[E,re]=v(``),[D,ie]=v(``),[O,k]=v([]),A=()=>Object.keys(m().providers??{});async function ae(e){if(e)try{let t=await $(`/api/models?provider=${encodeURIComponent(e)}`);k(t.models??[])}catch{k([])}}b(()=>{let e=I();e&&(re(e.provider||m().defaultProvider||A()[0]||``),ie(``),ae(E()))});let[oe,se]=v(!0),[j,M]=v(0),[N,P]=v(null),ce=x(()=>i().filter(Dt)),F=()=>$(`/api/config`).then(h).catch(()=>{}),I=x(()=>e().find(e=>e.id===n())),L=()=>$(`/api/agents`).then(e=>t(e.agents)).catch(()=>{}),R=()=>$(`/api/metrics`).then(l).catch(()=>{});async function le(e){try{let[t,n]=await Promise.all([$(`/api/agents/${e}/events?limit=300`),$(`/api/agents/${e}/branches`)]);a(t.events),s(n.branches)}catch{}}function ue(){return document.querySelector(`.feed`)}function de(){let e=ue();return!e||e.scrollHeight-e.scrollTop-e.clientHeight<80}function U(e=!1){let t=ue();t&&(e||oe())&&(t.scrollTop=t.scrollHeight,M(0))}async function W(e,t=!0){r(e),P(null),localStorage.setItem(`teapot.session`,e),ve(e,t),await le(e),requestAnimationFrame(()=>U(!0))}let[G,fe]=v(!1),q=null,ge=null;C(()=>q?.close());function _e(){let e=location.protocol===`https:`?`wss://`:`ws://`;q=new WebSocket(`${e}${location.host}/api/ws${At()}`),q.onopen=()=>fe(!0),q.onclose=()=>{fe(!1),setTimeout(_e,1500)},q.onerror=()=>q?.close(),q.onmessage=e=>{let t=JSON.parse(e.data);if(t.kind!==`ping`&&t.kind!==`pong`){if(t.kind===`llm-delta`){t.agentId===n()&&P({text:t.text??``,reasoning:t.reasoning??``});return}ge||=setTimeout(async()=>{if(ge=null,await L(),await R(),n()){let e=i().length;await le(n()),i().length!==e&&(P(null),de()?U(!0):M(j()+(i().length-e)))}},400)}}}let Y=()=>decodeURIComponent(location.pathname.split(`/`)[2]??``);function ve(e,t=!0){let n=`/session/${encodeURIComponent(e)}`;t?history.pushState(null,``,n):history.replaceState(null,``,n)}window.addEventListener(`popstate`,()=>{let t=Y();t&&e().some(e=>e.id===t)&&t!==n()&&W(t,!1)}),b(()=>{let e=I();document.title=e?`${e.status===`running`?`▶ `:e.status===`error`?`⚠ `:``}${e.id} · teapot`:`teapot`}),window.addEventListener(`keydown`,t=>{let r=t.target;if(r&&(r.tagName===`INPUT`||r.tagName===`TEXTAREA`||r.isContentEditable)){t.key===`Escape`&&r.blur();return}if(t.key===`Escape`){if(g()){_(!1);return}if(S()){w(!1);return}let e=I();if(e?.status===`running`){$(`/api/agents/${e.id}/stop`,{method:`POST`}).then(L);return}T()&&window.innerWidth<=1100&&te(!1);return}if(!(g()||S())){if(t.key===`/`)t.preventDefault(),document.querySelector(`.composer input[type=text]`)?.focus();else if(t.key===`d`)ne();else if(t.key===`t`)ye();else if(t.key===`ArrowDown`||t.key===`ArrowUp`){let r=e();if(r.length===0)return;t.preventDefault();let i=r.findIndex(e=>e.id===n()),a=t.key===`ArrowDown`?Math.min(i+1,r.length-1):Math.max(i-1,0);a!==i&&W(r[a].id)}}});let[X,Z]=v(localStorage.getItem(`teapot.term`)===`1`),ye=()=>{Z(!X()),localStorage.setItem(`teapot.term`,X()?`1`:`0`)},be=null,xe=null,Se=null,Q=null,rt={cols:0,rows:0},it=null;function at(){Q?.disconnect(),Q=null,Se?.close(),Se=null,xe?.dispose(),xe=null}function ot(e){at(),be&&Promise.all([Ce(()=>import(`./xterm-C3BHN0de.js`),[]),Ce(()=>import(`./addon-fit-DIOBYJe3.js`),[])]).then(([{Terminal:t},{FitAddon:n}])=>{let r=new t({cursorBlink:!0,fontSize:12.5,fontFamily:`ui-monospace, Menlo, Consolas, monospace`,theme:{background:`#0d0e12`,foreground:`#dcdee4`}}),i=new n;r.loadAddon(i),r.open(be),i.fit(),xe=r;let a=location.protocol===`https:`?`wss://`:`ws://`,o=new WebSocket(`${a}${location.host}/api/agents/${e}/term${At()}`);Se=o,o.onmessage=e=>{let t=JSON.parse(e.data);t.kind===`data`?r.write(t.data):t.kind===`exit`&&r.write(`\r\n\x1b[2m[terminal exited ${t.code??``}]\x1b[0m\r\n`)},r.onData(e=>{o.readyState===WebSocket.OPEN&&o.send(JSON.stringify({kind:`input`,data:e}))});let s=()=>{try{i.fit()}catch{}let{cols:e,rows:t}=r;(e!==rt.cols||t!==rt.rows)&&o.readyState===WebSocket.OPEN&&(rt={cols:e,rows:t},o.send(JSON.stringify({kind:`resize`,cols:e,rows:t})))};Q=new ResizeObserver(()=>{it&&clearTimeout(it),it=setTimeout(s,300)}),Q.observe(be),setTimeout(s,50)})}b(()=>{let e=n();!X()||!e?at():requestAnimationFrame(()=>e&&ot(e))}),C(at),ee(()=>{F(),L().then(()=>{let t=Y()||localStorage.getItem(`teapot.session`)||``,n=e().find(e=>e.id===t)??e()[0];n&&W(n.id,!1)}),R(),_e(),setInterval(R,3e4)});let st=async e=>{if(e.preventDefault(),!n()||!u().trim())return;let t=u();d(``),await $(`/api/agents/${n()}/prompt`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({text:t,start:f()})})},ct=e=>()=>n()&&$(`/api/agents/${n()}${e}`,{method:`POST`}).then(L),lt=async e=>{e.preventDefault();let t=document.getElementById(`goal-input`);!n()||!t.value.trim()||(await $(`/api/agents/${n()}/goal`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({text:t.value})}),t.value=``,L())};return[(()=>{var i=Je(),a=i.firstChild,s=a.firstChild,l=s.firstChild.nextSibling,h=l.nextSibling.firstChild,g=h.nextSibling,v=s.nextSibling,b=v.nextSibling,x=a.nextSibling,S=x.nextSibling;return h.$$click=()=>{F(),_(!0)},g.$$click=()=>{F(),w(!0)},J(v,z(B,{get each(){return e()},children:e=>(()=>{var t=Xe(),r=t.firstChild,i=r.nextSibling;return t.$$click=()=>W(e.id),J(i,()=>e.id),J(t,z(V,{get when(){return e.goal.status===`done`},get children(){return Ye()}}),null),y(i=>{var a=`agent-item`+(e.id===n()?` sel`:``),o=`dot ${e.status}`;return a!==i.e&&K(t,i.e=a),o!==i.t&&K(r,i.t=o),i},{e:void 0,t:void 0}),t})()})),J(b,z(V,{get when(){return c()},get children(){return[`master rss `,H(()=>c().rssMb),`MB · heap `,H(()=>c().heapUsedMb),`MB`,we(),`load1 `,H(()=>c().loadavg1),` · up `,H(()=>Math.floor(c().uptimeSec/60)),`m`]}})),J(x,z(V,{get when(){return I()},get fallback(){return Ze()},get children(){return[(()=>{var e=Ee(),t=e.firstChild.nextSibling,n=t.nextSibling,r=n.nextSibling,i=r.firstChild,a=i.nextSibling,o=a.nextSibling.nextSibling,s=o.nextSibling.nextSibling;s.nextSibling;var c=r.nextSibling,l=c.firstChild,u=l.nextSibling;return J(t,()=>I().id),J(n,()=>I().status),J(r,()=>I().model,i),J(r,()=>I().session,a),J(r,()=>I().branch,o),J(r,()=>I().stats.turns,s),J(r,()=>I().stats.toolCalls,null),J(c,z(V,{get when(){return I().statusReason},get children(){var e=Te();return y(()=>pe(e,`title`,I().statusReason)),e}}),l),l.$$click=ye,u.$$click=ne,y(()=>K(n,`badge ${I().status}`)),e})(),(()=>{var e=Ae();return e.addEventListener(`scroll`,()=>{let e=de();e&&j()&&M(0),se(e)}),J(e,z(V,{get when(){return ce().length>0},get fallback(){return Qe()},get children(){return[z(B,{get each(){return ce()},children:(e,t)=>z(Mt,{e,get prev(){return ce()[t()-1]}})}),z(V,{get when(){return N()},get children(){var e=ke(),t=e.firstChild.nextSibling;return t.firstChild,J(t,z(V,{get when(){return N().reasoning},get children(){var e=De(),t=e.firstChild.nextSibling;return J(t,()=>N().reasoning),e}}),null),J(t,z(V,{get when(){return N().text},get fallback(){return $e()},get children(){var e=Oe(),t=e.firstChild;return J(e,()=>N().text,t),e}}),null),e}})]}})),e})(),z(V,{get when(){return!oe()||j()>0},get children(){var e=je();return e.firstChild,e.$$click=()=>U(!0),J(e,(()=>{var e=H(()=>j()>0);return()=>e()?`${j()} new message${j()>1?`s`:``}`:`jump to present`})(),null),e}}),z(V,{get when(){return H(()=>!!X())()&&I()},get children(){var e=Me(),t=e.firstChild,n=t.firstChild,r=n.firstChild.nextSibling,i=n.nextSibling,a=t.nextSibling;return J(r,()=>I().workspace),i.$$click=ye,he(e=>be=e,a),e}}),(()=>{var e=Ne(),t=e.firstChild,n=t.firstChild,r=n.nextSibling.firstChild;return t.addEventListener(`submit`,st),n.$$input=e=>d(e.currentTarget.value),r.addEventListener(`change`,e=>p(e.currentTarget.checked)),y(()=>pe(n,`placeholder`,`message #${I().id}`)),y(()=>n.value=u()),y(()=>r.checked=f()),e})()]}})),J(S,z(V,{get when(){return I()},get children(){return[Pe(),(()=>{var e=Fe(),t=e.firstChild,n=t.firstChild.nextSibling,r=n.nextSibling,i=t.nextSibling,a=i.firstChild.nextSibling,o=i.nextSibling.firstChild.nextSibling,s=o.firstChild;return J(n,()=>I().id),J(r,()=>I().status),J(a,()=>I().workspace),J(o,()=>I().session,s),J(o,()=>I().branch,null),y(e=>{var t=`badge ${I().status}`,n=I().workspace;return t!==e.e&&K(r,e.e=t),n!==e.t&&pe(a,`title`,e.t=n),e},{e:void 0,t:void 0}),e})(),Ie(),(()=>{var e=Le(),t=e.firstChild,r=t.nextSibling,i=r.firstChild,a=i.nextSibling,o=a.nextSibling,s=r.nextSibling;return s.firstChild,t.addEventListener(`change`,e=>{re(e.currentTarget.value),ae(e.currentTarget.value)}),J(t,z(B,{get each(){return A()},children:e=>(()=>{var t=et();return t.value=e,J(t,e,null),J(t,()=>e===m().defaultProvider?` ★`:``,null),t})()})),i.$$input=e=>ie(e.currentTarget.value),J(a,z(B,{get each(){return O()},children:e=>(()=>{var t=et();return t.value=e,t})()})),o.$$click=async()=>{n()&&(await $(`/api/agents/${n()}/model`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({provider:E(),model:D().trim()||void 0})}),L())},J(s,()=>I().model,null),J(s,z(V,{get when(){return O().length},get children(){return[` · `,H(()=>O().length),` models loaded`]}}),null),y(()=>pe(i,`placeholder`,I().model)),y(()=>t.value=E()),y(()=>i.value=D()),e})(),Re(),(()=>{var n=ze(),i=n.firstChild,a=i.nextSibling,o=a.nextSibling,s=o.nextSibling;return me(i,`click`,ct(`/start`),!0),me(a,`click`,ct(`/stop`),!0),o.$$click=()=>$(`/api/agents/${I().id}/fork`,{method:`POST`,headers:{"content-type":`application/json`},body:`{}`}).then(()=>W(I().id)),s.$$click=async()=>{confirm(`remove agent ${I().id}? (log is kept)`)&&(await $(`/api/agents/${I().id}`,{method:`DELETE`}),r(null),t(e().filter(e=>e.id!==I().id)))},n})(),(()=>{var e=Be(),t=e.firstChild.nextSibling;return J(t,()=>I().goal.status),y(()=>K(t,`badge ${I().goal.status===`done`?`done`:``}`)),e})(),(()=>{var e=Ve();return e.addEventListener(`submit`,lt),e})(),(()=>{var e=He();return J(e,()=>I().goal.text||`no goal set`),e})(),Ue(),z(V,{get when(){return I().latestProgress},get fallback(){return tt()},get children(){var e=We(),t=e.firstChild,n=t.nextSibling,r=n.nextSibling.nextSibling;return J(e,()=>I().latestProgress.doing,t),J(e,()=>I().latestProgress.recent??``,n),J(r,()=>I().latestProgress.ts),e}}),Ge(),(()=>{var e=Ke(),t=e.firstChild.nextSibling,n=t.nextSibling.nextSibling,r=n.nextSibling.nextSibling,i=r.nextSibling.nextSibling;return i.nextSibling,J(e,()=>I().stats.turns,t),J(e,()=>I().stats.toolCalls,n),J(e,()=>I().stats.compactions??0,r),J(e,()=>I().stats.inputTokens,i),J(e,()=>I().stats.outputTokens,null),e})(),qe(),z(B,{get each(){return o()},children:e=>(()=>{var t=nt(),n=t.firstChild;return J(t,()=>e.branch,n),J(n,()=>e.events),y(()=>K(t,`branch-row`+(e.branch===I().branch?` cur`:``))),t})()})]}})),y(e=>{var t=`layout`+(T()?``:` right-hidden`),n=`conn`+(G()?` ok`:``),r=G()?`live (websocket)`:`reconnecting…`,a=`rightbar`+(T()?` open`:``);return t!==e.e&&K(i,e.e=t),n!==e.t&&K(l,e.t=n),r!==e.a&&pe(l,`title`,e.a=r),a!==e.o&&K(S,e.o=a),e},{e:void 0,t:void 0,a:void 0,o:void 0}),i})(),z(V,{get when(){return g()},get children(){return z(Rt,{get providers(){return Object.keys(m().providers??{})},onClose:()=>_(!1),onCreated:e=>{_(!1),L(),W(e)}})}}),z(V,{get when(){return S()},get children(){return z(zt,{get cfg(){return m()},onClose:()=>w(!1),onSaved:F})}})]}function Mt(e){let t=e.e,n=Tt(t),r=e.prev&&e.prev.type===t.type&&t.session===e.prev.session&&t.branch===e.prev.branch;return t.type===`state`?t.data.from===t.data.to?null:(()=>{var e=rt(),n=e.firstChild;return J(e,()=>t.data.from,n),J(e,()=>t.data.to,null),J(e,(()=>{var e=H(()=>!!t.data.reason);return()=>e()?` — ${t.data.reason}`:``})(),null),y(()=>K(e,`divider-msg`+(t.data.to===`error`?` err`:``))),e})():(()=>{var e=ot(),i=e.firstChild;return K(e,`msg`+(r?` grouped`:``)),J(e,z(V,{when:!r,get fallback(){return st()},get children(){var e=it();return J(e,()=>n.icon),y(t=>{var r=n.color+`33`,i=`1px solid ${n.color}66`;return r!==t.e&&q(e,`background`,t.e=r),i!==t.t&&q(e,`border`,t.t=i),t},{e:void 0,t:void 0}),e}}),i),J(i,z(V,{when:!r,get children(){var e=at(),r=e.firstChild,i=r.nextSibling,a=i.nextSibling;return J(r,()=>n.name),J(i,()=>Ot(t.ts)),J(a,()=>t.branch),y(e=>q(r,`color`,n.color)),e}}),null),J(i,z(Nt,{e:t}),null),e})()}function Nt(e){let t=e.e;switch(t.type){case`prompt`:return(()=>{var e=ct();return y(()=>e.innerHTML=ye(String(t.data.text??``))),e})();case`message`:return[z(V,{get when(){return H(()=>typeof t.data.reasoning==`string`)()&&t.data.reasoning.trim()},get children(){var e=De(),n=e.firstChild.nextSibling;return J(n,()=>String(t.data.reasoning)),e}}),(()=>{var e=ct();return y(()=>e.innerHTML=ye(String(t.data.content??``))),e})(),z(V,{get when(){return t.data.final},get children(){var e=lt(),n=e.firstChild;return J(e,z(It,{get text(){return String(t.data.content??``)}}),n),e}})];case`tool_call`:{let e=JSON.stringify(t.data.args,null,1),n=Ft(JSON.stringify(t.data.args??{}),110);return(()=>{var r=ut(),i=r.firstChild,a=i.firstChild;a.firstChild;var o=a.nextSibling.nextSibling,s=i.nextSibling;return J(a,()=>String(t.data.name),null),J(o,n),J(s,e),r})()}case`tool_result`:{let e=String(t.data.result);return(()=>{var n=dt(),r=n.firstChild,i=r.firstChild,a=r.nextSibling,o=a.nextSibling,s=o.firstChild;return J(i,()=>Ft(e,120)),J(r,z(It,{text:e}),null),J(a,()=>Pt(e,4e3)),J(o,()=>t.data.durationMs,s),J(o,()=>t.data.ok?``:` · FAILED`,null),y(()=>K(n,`embed`+(t.data.ok?``:` fail`))),n})()}case`progress`:return(()=>{var e=ht(),n=e.firstChild;return n.firstChild,J(n,()=>String(t.data.doing??``),null),J(e,z(V,{get when(){return t.data.recent},get children(){var e=ft();return J(e,()=>String(t.data.recent)),e}}),null),J(e,z(V,{get when(){return t.data.problems},get children(){var e=pt();return e.firstChild,J(e,()=>String(t.data.problems),null),e}}),null),J(e,z(V,{get when(){return t.data.next},get children(){var e=mt();return e.firstChild,J(e,()=>String(t.data.next),null),e}}),null),e})();case`error`:return(()=>{var e=gt(),n=e.firstChild;return n.firstChild,J(n,()=>String(t.data.message??``),null),e})();default:return(()=>{var e=_t();return J(e,()=>Pt(JSON.stringify(t.data),200)),e})()}}function Pt(e,t){return e.length>t?e.slice(0,t)+` …`:e}function Ft(e,t){return Pt(e.replace(/\s+/g,` `).trim(),t)}function It(e){let[t,n]=v(!1);return(()=>{var r=vt();return r.$$click=t=>{t.stopPropagation(),navigator.clipboard.writeText(e.text).then(()=>{n(!0),setTimeout(()=>n(!1),900)})},J(r,()=>t()?`✓`:`⧉`),r})()}function Lt(e){return(()=>{var t=yt(),n=t.firstChild,r=n.firstChild.firstChild,i=r.nextSibling;return t.$$click=t=>t.target===t.currentTarget&&e.onClose(),J(r,()=>e.title),me(i,`click`,e.onClose,!0),J(n,()=>e.children,null),t})()}function Rt(e){let[t,n]=v(`~`),[r,i]=v([]),[a,o]=v(``),[s,c]=v(e.providers[0]??``),[l,u]=v(``),[d,f]=v(``);async function p(e){let t=await $(`/api/fs${e?`?path=${encodeURIComponent(e)}`:``}`);n(t.path),i(t.entries)}ee(()=>p(t()));let m=async n=>{n.preventDefault(),f(``);try{let n=await $(`/api/agents`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({workspace:t(),id:a(),provider:s()||void 0,model:l()||void 0})});e.onCreated(n.agent.id)}catch(e){f(String(e.message))}};return z(Lt,{title:`new agent`,get onClose(){return e.onClose},get children(){var i=xt(),f=i.firstChild,h=f.firstChild.nextSibling.firstChild,g=h.nextSibling,_=g.nextSibling,v=f.nextSibling,b=v.nextSibling,x=b.firstChild,S=x.firstChild.nextSibling,ee=x.nextSibling,C=ee.firstChild.nextSibling,w=ee.nextSibling.firstChild.nextSibling,T=b.nextSibling;return i.addEventListener(`submit`,m),h.$$input=e=>n(e.currentTarget.value),g.$$click=()=>p(t()),_.$$click=()=>p(`..`),J(v,z(B,{get each(){return r()},children:e=>(()=>{var n=St();return n.firstChild,n.$$click=()=>p(`${t()}/${e}`.replace(/\/+/g,`/`)),J(n,e,null),n})()})),S.$$input=e=>o(e.currentTarget.value),C.addEventListener(`change`,e=>c(e.currentTarget.value)),J(C,z(B,{get each(){return e.providers},children:e=>(()=>{var t=et();return J(t,e),t})()})),w.$$input=e=>u(e.currentTarget.value),J(i,z(V,{get when(){return d()},get children(){var e=bt();return J(e,d),e}}),T),y(()=>h.value=t()),y(()=>S.value=a()),y(()=>C.value=s()),y(()=>w.value=l()),i}})}function zt(e){let[t,n]=v(JSON.stringify(Object.fromEntries(Object.entries(e.cfg.providers??{}).map(([e,t])=>[e,{baseUrl:t.baseUrl,apiKey:t.apiKey??``,model:t.model??``}])),null,2)),[r,i]=v(e.cfg.defaultProvider??Object.keys(e.cfg.providers??{})[0]??``),[a,o]=v(Math.round((e.cfg.progressIntervalMs??6e5)/6e4)),[s,c]=v(JSON.stringify(e.cfg.tasks??[],null,2)),[l,u]=v(``),d=async n=>{n.preventDefault(),u(``);let i,o;try{i=JSON.parse(t())}catch{return u(`providers: invalid JSON`)}try{o=JSON.parse(s())}catch{return u(`tasks: invalid JSON`)}try{await $(`/api/config`,{method:`PUT`,headers:{"content-type":`application/json`},body:JSON.stringify({providers:i,defaultProvider:r(),progressIntervalMs:Math.max(1,a())*6e4,tasks:o})}),e.onSaved(),e.onClose()}catch(e){u(String(e.message))}};return z(Lt,{title:`settings`,get onClose(){return e.onClose},get children(){var u=Ct(),f=u.firstChild,p=f.firstChild.nextSibling,m=p.nextSibling.nextSibling,h=f.nextSibling,g=h.firstChild,_=g.firstChild.nextSibling,v=g.nextSibling.firstChild.nextSibling,b=h.nextSibling,x=b.firstChild.nextSibling,S=b.nextSibling;return u.addEventListener(`submit`,d),J(f,()=>e.cfg.configPath,p),m.$$input=e=>n(e.currentTarget.value),_.$$input=e=>i(e.currentTarget.value),v.$$input=e=>o(Number(e.currentTarget.value)),x.$$input=e=>c(e.currentTarget.value),J(u,z(V,{get when(){return l()},get children(){var e=bt();return J(e,l),e}}),S),y(()=>m.value=t()),y(()=>_.value=r()),y(()=>v.value=a()),y(()=>x.value=s()),u}})}fe([`click`,`input`]),W(()=>z(jt,{}),document.getElementById(`root`));