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 +11 -6
- package/dist/agent/agent.js +80 -8
- package/dist/agent/tools.js +526 -20
- package/dist/bus.js +1 -1
- package/dist/server/api.js +6 -3
- package/package.json +3 -1
- package/public/assets/index-BE9Nw_-t.css +1 -0
- package/public/assets/index-DxB6uahH.js +8 -0
- package/public/index.html +2 -2
- package/public/assets/index-DIs0rfrk.css +0 -1
- package/public/assets/index-JRXeHcww.js +0 -8
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
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
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
|
package/dist/agent/agent.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
/**
|
|
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
|
-
|
|
324
|
-
|
|
325
|
-
this.
|
|
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 (
|
|
435
|
+
if (this.stopRequested)
|
|
376
436
|
break;
|
|
377
|
-
|
|
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
|
}
|
package/dist/agent/tools.js
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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 (
|
|
84
|
+
if (killReason) {
|
|
72
85
|
resolve({
|
|
73
86
|
ok: false,
|
|
74
|
-
result:
|
|
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.
|
|
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
|
|
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
|
-
|
|
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
|
|
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: "
|
|
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
|
|
519
|
+
if (lfCount >= 1) {
|
|
153
520
|
text = lf;
|
|
154
|
-
count =
|
|
521
|
+
count = lfCount;
|
|
155
522
|
normalized = true;
|
|
156
523
|
}
|
|
157
524
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
if (count
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
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
|
|
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(
|
|
4
|
+
bus.setMaxListeners(1000); // one per connected client (WS + SSE) — headroom for busy LAN setups
|
package/dist/server/api.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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.
|
|
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,`&`).replace(/</g,`<`).replace(/>/g,`>`).replace(/"/g,`"`)}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&<(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-
|
|
8
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
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,`&`).replace(/</g,`<`).replace(/>/g,`>`).replace(/"/g,`"`)}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`));
|