teapot-coding-agent 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -173,8 +173,10 @@ description: Steps to cut a release safely
173
173
  - The system prompt lists every discovered skill (name + description);
174
174
  workspace skills override same-named global ones.
175
175
  - The agent calls `load_skill(name)` when a task matches and follows it.
176
- - The agent calls `save_skill(name, description, content)` to distill a
177
- reusable procedure it developed available from the next turn, forever.
176
+ - The agent calls `save_skill(name, description, content, files?)` to distill a
177
+ reusable procedure `files` bundles helper scripts next to `SKILL.md`
178
+ (made executable automatically), and `load_skill` lists them as runnable
179
+ workspace paths. Available from the next turn, forever.
178
180
 
179
181
  ### Session log format (JSONL)
180
182
 
@@ -218,10 +220,13 @@ GET /api/agents list snapshots
218
220
  GET /api/agents/:id one snapshot
219
221
  POST /api/agents/:id/prompt {text, start?}
220
222
  POST /api/agents/:id/start | /stop
221
- POST /api/agents/:id/goal {text} or {status}
223
+ POST /api/agents/:id/load lazy session restore (stopped → idle)
224
+ POST /api/agents/:id/goal {text, notify?} or {status}
222
225
  POST /api/agents/:id/fork {} → new branch, same session log
226
+ POST /api/agents/:id/edit-prompt {eventId, text, tail: "discard"|"summarize"} → fork & resend
223
227
  GET /api/agents/:id/events?limit&branch&session
224
228
  GET /api/agents/:id/branches
229
+ GET /api/tasks scheduled tasks with computed next-fire times
225
230
  GET /api/metrics master rss/heap/load + per-agent stats
226
231
  GET /api/events SSE updates (push, no polling)
227
232
  GET /brew 418 I'm a teapot (RFC 2324)
@@ -40,6 +40,10 @@ Session state is not injected into prompts — fetch it with tools instead:
40
40
  text-munging (sed/awk/heredoc) remains available for quick bulk transforms
41
41
  when that is genuinely faster.
42
42
  - When a loaded skill matches your task, follow its playbook.
43
+ - Turn proven procedures into skills: once something non-trivial worked well,
44
+ save_skill(name, description, content, files=[{name, content}]) so future
45
+ sessions can load_skill them — helper scripts go through files and are made
46
+ executable automatically.
43
47
  - When you make meaningful progress, call report_progress.
44
48
  - Be frugal: prefer small precise edits, avoid runaway loops.`;
45
49
  export class Agent {
@@ -52,6 +56,8 @@ export class Agent {
52
56
  currentBranch = "br0";
53
57
  goal = { text: "", status: "active", updatedAt: new Date().toISOString() };
54
58
  latestProgress = null;
59
+ /** set once the conversation has been restored (lazy: on first interaction) */
60
+ readyPromise = null;
55
61
  stats = {
56
62
  turns: 0,
57
63
  toolCalls: 0,
@@ -76,14 +82,20 @@ export class Agent {
76
82
  toolAbort = new AbortController();
77
83
  runChain = Promise.resolve();
78
84
  lastProgressAt = Date.now();
85
+ /** real assistant output since the last progress report (chars / turns) */
86
+ activityChars = 0;
87
+ turnsSinceProgress = 0;
79
88
  consecutiveToolErrors = 0;
80
89
  constructor(opts) {
81
90
  this.opts = {
82
91
  progressIntervalMs: 10 * 60_000,
92
+ progressMinChars: 4_000,
93
+ progressMaxQuietTurns: 40,
83
94
  autoContinue: true,
84
95
  continueDelayMs: 15_000,
85
96
  maxConsecutiveToolErrors: 5,
86
97
  contextTokenBudget: 96_000,
98
+ contextWindowTokens: 0,
87
99
  restoreSession: true,
88
100
  globalSkillsDir: "",
89
101
  provider: "",
@@ -143,9 +155,35 @@ export class Agent {
143
155
  await this.migrateGoalFromWorkspace();
144
156
  const stored = await this.readGoalStore();
145
157
  this.goal = stored ?? { text: "", status: "active", updatedAt: new Date().toISOString() };
146
- if (this.opts.restoreSession)
147
- await this.restoreFromLog();
148
158
  await this.refreshSkills();
159
+ // the conversation is NOT restored here: boot cost stays O(agents), not
160
+ // O(history). It is rebuilt lazily by ensureReady() on first interaction.
161
+ if (this.opts.restoreSession) {
162
+ this.status = "stopped";
163
+ this.statusReason = "session not loaded — select it or send a prompt";
164
+ bus.emit("update", { kind: "agent-update", agentId: this.opts.id });
165
+ }
166
+ }
167
+ /**
168
+ * Restore the conversation from the JSONL log exactly once, on demand.
169
+ * Everything that touches history (prompts, start, fork, UI selection)
170
+ * funnels through here; boot stays cheap no matter how many sessions exist.
171
+ */
172
+ ensureReady() {
173
+ if (!this.readyPromise) {
174
+ this.readyPromise = (async () => {
175
+ if (this.opts.restoreSession) {
176
+ await this.restoreFromLog();
177
+ if (this.status === "stopped")
178
+ this.setStatus("idle", "session loaded");
179
+ }
180
+ })();
181
+ }
182
+ return this.readyPromise;
183
+ }
184
+ /** Explicit load (e.g. the user clicked the agent in the UI): stopped → idle. */
185
+ async load() {
186
+ await this.ensureReady();
149
187
  }
150
188
  /** harness-managed files inside the session directory */
151
189
  get goalFile() {
@@ -195,114 +233,11 @@ export class Agent {
195
233
  const events = await readEvents(this.log.filePath);
196
234
  if (events.length === 0)
197
235
  return;
198
- const byId = new Map(events.map((e) => [e.id, e]));
199
- let last = events[events.length - 1];
200
- // walk backwards to the root via parent links (fork-safe)
201
- const lineage = [];
202
- const seen = new Set();
203
- for (let cur = last; cur; cur = cur.parent ? byId.get(cur.parent) : undefined) {
204
- if (seen.has(cur.id))
205
- break;
206
- seen.add(cur.id);
207
- lineage.push(cur);
208
- }
209
- lineage.reverse();
210
- // skip the trailing fork event itself (it is bookkeeping, not conversation)
211
- while (lineage.length && lineage[0].type === "fork")
212
- lineage.shift();
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
- };
230
- for (const e of lineage) {
231
- const d = e.data;
232
- if (e.type === "prompt" && typeof d.text === "string") {
233
- if (openCalls.size > 0)
234
- bufferedUsers.push(d.text);
235
- else
236
- msgs.push({ role: "user", content: d.text });
237
- }
238
- else if (e.type === "message") {
239
- const role = d.role === "assistant" ? "assistant" : "user";
240
- const m = { role, content: typeof d.content === "string" ? d.content : "" };
241
- if (Array.isArray(d.toolCalls) && d.toolCalls.length > 0) {
242
- m.tool_calls = d.toolCalls.map((c) => ({
243
- id: c.id,
244
- type: "function",
245
- function: { name: c.name, arguments: "{}" },
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);
252
- }
253
- msgs.push(m);
254
- }
255
- else if (e.type === "tool_call") {
256
- // enrich the preceding assistant tool_calls with real arguments
257
- const prev = [...msgs].reverse().find((x) => x.role === "assistant" && x.tool_calls?.some((t) => t.id === d.callId));
258
- const tc = prev?.tool_calls?.find((t) => t.id === d.callId);
259
- if (tc)
260
- tc.function.arguments = JSON.stringify(d.args ?? {});
261
- }
262
- else if (e.type === "tool_result") {
263
- msgs.push({
264
- role: "tool",
265
- tool_call_id: String(d.callId ?? ""),
266
- content: `${d.ok === false ? "(failed) " : ""}${typeof d.result === "string" ? d.result : ""}`,
267
- });
268
- openCalls.delete(String(d.callId ?? ""));
269
- flushUsers();
270
- }
271
- else if (e.type === "progress") {
272
- // progress events may follow an assistant report_progress call that
273
- // has no logged tool result — patch it in when present
274
- const lastAssistant = [...msgs].reverse().find((x) => x.role === "assistant" && x.tool_calls?.length);
275
- if (lastAssistant?.tool_calls?.some((t) => t.function.name === "report_progress")) {
276
- for (const t of lastAssistant.tool_calls) {
277
- if (!msgs.some((x) => x.role === "tool" && x.tool_call_id === t.id)) {
278
- msgs.push({ role: "tool", tool_call_id: t.id, content: "progress recorded" });
279
- }
280
- openCalls.delete(t.id);
281
- }
282
- flushUsers();
283
- }
284
- }
285
- }
286
- // every assistant tool_call must be answered by a tool message, or the
287
- // API rejects the sequence — close any holes left by meta tools (finish)
288
- for (let i = 0; i < msgs.length; i++) {
289
- const m = msgs[i];
290
- if (m.role === "assistant" && m.tool_calls?.length) {
291
- for (const t of m.tool_calls) {
292
- if (!msgs.slice(i + 1).some((x) => x.role === "tool" && x.tool_call_id === t.id)) {
293
- msgs.splice(i + 1, 0, {
294
- role: "tool",
295
- tool_call_id: t.id,
296
- content: t.function.name === "finish" ? `(round ended: ${m.content || "finished"})` : "(no result recorded)",
297
- });
298
- i++;
299
- }
300
- }
301
- }
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 });
236
+ const lineage = lineageOf(events);
237
+ if (!lineage.length)
238
+ return;
239
+ const last = lineage[lineage.length - 1];
240
+ const msgs = rebuildMessagesFrom(lineage);
306
241
  if (msgs.length > 0) {
307
242
  this.messages = msgs;
308
243
  this.currentBranch = last.branch;
@@ -313,6 +248,61 @@ export class Agent {
313
248
  });
314
249
  }
315
250
  }
251
+ /**
252
+ * Edit a previously-sent prompt: fork the conversation at that point,
253
+ * replace its text, and optionally fold everything that happened after it
254
+ * into a summary note on the new branch (ChatGPT-edit style). The agent
255
+ * must not be running — editing under a live loop would race its history.
256
+ */
257
+ async editPromptAt(eventId, text, tail) {
258
+ if (this.status === "running")
259
+ throw new Error("agent is running — stop it before editing history");
260
+ const all = await readEvents(this.log.filePath);
261
+ const target = all.find((e) => e.id === eventId);
262
+ if (!target || target.type !== "prompt")
263
+ throw new Error("event not found on this session (or not a prompt)");
264
+ const lineage = lineageOf(all);
265
+ const tIdx = lineage.findIndex((e) => e.id === eventId);
266
+ if (tIdx === -1)
267
+ throw new Error("prompt is not on this agent's current lineage");
268
+ const kept = lineage.slice(0, tIdx);
269
+ const dropped = lineage.slice(tIdx); // includes the original prompt itself
270
+ const msgs = rebuildMessagesFrom(kept);
271
+ if (tail === "summarize" && dropped.length > 0) {
272
+ try {
273
+ const droppedMsgs = rebuildMessagesFrom(dropped);
274
+ if (droppedMsgs.length) {
275
+ const summary = await this.summarize(droppedMsgs);
276
+ if (summary.trim()) {
277
+ msgs.push({
278
+ role: "user",
279
+ content: "[harness] The conversation continued past this point on another timeline. " +
280
+ `Notes from what happened there:\n\n${summary}`,
281
+ });
282
+ }
283
+ }
284
+ }
285
+ catch {
286
+ // summarization is best-effort; the fork proceeds without notes
287
+ }
288
+ }
289
+ msgs.push({ role: "user", content: text });
290
+ const newBranch = `br${this.branchCount()}${Date.now().toString(36).slice(-4)}`;
291
+ await this.log.append("fork", this.currentSession, newBranch, {
292
+ fromSession: this.currentSession,
293
+ fromBranch: this.currentBranch,
294
+ fromEvent: kept.at(-1)?.id ?? null,
295
+ newBranch,
296
+ reason: "prompt-edited",
297
+ droppedEvents: dropped.length,
298
+ tailMode: tail,
299
+ });
300
+ this.currentBranch = newBranch;
301
+ this.messages = msgs;
302
+ await this.log.append("prompt", this.currentSession, this.currentBranch, { source: "user", text });
303
+ bus.emit("update", { kind: "agent-update", agentId: this.opts.id });
304
+ return { droppedEvents: dropped.length, branch: newBranch };
305
+ }
316
306
  parseGoalFile(text) {
317
307
  // humans and agents may append their own status lines — latest wins
318
308
  const all = [...text.matchAll(/status:\s*(\w+)/gi)];
@@ -363,6 +353,11 @@ export class Agent {
363
353
  model: this.opts.llm.model,
364
354
  provider: this.opts.provider,
365
355
  sessionDir: this.opts.sessionDir,
356
+ ctx: {
357
+ usedTokens: this.estimateTokens(),
358
+ compactAt: this.opts.contextTokenBudget,
359
+ window: this.opts.contextWindowTokens || 0,
360
+ },
366
361
  pendingPrompts: this.pendingPrompts.length,
367
362
  };
368
363
  }
@@ -370,12 +365,15 @@ export class Agent {
370
365
  * Queue a user prompt. Returns immediately: the event is logged right away
371
366
  * (so every connected UI sees it instantly) and the text is handed to the
372
367
  * model at the next turn boundary — never mid-turn, and never blocked by
373
- * the running loop.
368
+ * the running loop. The very first prompt on a fresh boot also triggers the
369
+ * lazy session restore (before the mailbox is filled, so no duplicates).
374
370
  */
375
371
  enqueuePrompt(text, source = "user") {
376
- this.pendingPrompts.push({ source, text });
377
- void this.log
378
- .append("prompt", this.currentSession, this.currentBranch, { source, text })
372
+ void this.ensureReady()
373
+ .then(() => {
374
+ this.pendingPrompts.push({ source, text });
375
+ return this.log.append("prompt", this.currentSession, this.currentBranch, { source, text });
376
+ })
379
377
  .then(() => bus.emit("update", { kind: "agent-update", agentId: this.opts.id }))
380
378
  .catch(() => { });
381
379
  }
@@ -400,6 +398,7 @@ export class Agent {
400
398
  return;
401
399
  this.stopRequested = false;
402
400
  void this.enqueue(async () => {
401
+ await this.ensureReady(); // lazy restore before the loop touches history
403
402
  this.setStatus("running", reason);
404
403
  this.stats.startedAt ??= new Date().toISOString();
405
404
  });
@@ -540,14 +539,40 @@ export class Agent {
540
539
  turn: ++this.stats.turns,
541
540
  });
542
541
  // stream the assistant reply live to connected clients
543
- const res = await this.llmCall(this.buildMessages(), allToolSpecs(), (s) => {
544
- bus.emit("update", {
545
- kind: "llm-delta",
546
- agentId: this.opts.id,
547
- text: s.text,
548
- reasoning: s.reasoning,
542
+ let res;
543
+ try {
544
+ res = await this.llmCall(this.buildMessages(), allToolSpecs(), (s) => {
545
+ bus.emit("update", {
546
+ kind: "llm-delta",
547
+ agentId: this.opts.id,
548
+ text: s.text,
549
+ reasoning: s.reasoning,
550
+ });
549
551
  });
550
- });
552
+ }
553
+ catch (err) {
554
+ // user stop mid-stream: persist the partial output so the timeline
555
+ // keeps what was already visible (otherwise it silently vanishes)
556
+ const partial = err.partial;
557
+ if (this.stopRequested && partial && (partial.text || partial.reasoning)) {
558
+ await this.log.append("message", this.currentSession, this.currentBranch, {
559
+ role: "assistant",
560
+ content: partial.text ?? "",
561
+ reasoning: partial.reasoning,
562
+ interrupted: true,
563
+ });
564
+ this.messages.push({ role: "assistant", content: partial.text ?? "" });
565
+ }
566
+ else if (this.stopRequested) {
567
+ // nothing had streamed — leave an explicit marker so the log shows
568
+ // why this prompt has no reply
569
+ await this.log.append("system_note", this.currentSession, this.currentBranch, {
570
+ event: "turn-interrupted",
571
+ detail: "stopped before any output arrived",
572
+ });
573
+ }
574
+ throw err;
575
+ }
551
576
  if (res.usage) {
552
577
  this.stats.inputTokens += res.usage.inputTokens ?? 0;
553
578
  this.stats.outputTokens += res.usage.outputTokens ?? 0;
@@ -561,6 +586,8 @@ export class Agent {
561
586
  reasoning: res.reasoning,
562
587
  });
563
588
  this.messages.push(m);
589
+ this.turnsSinceProgress++;
590
+ this.activityChars += m.content?.length ?? 0;
564
591
  if (!m.tool_calls?.length)
565
592
  return finished;
566
593
  for (const call of m.tool_calls) {
@@ -677,9 +704,14 @@ export class Agent {
677
704
  });
678
705
  }
679
706
  async maybeRequestProgress() {
680
- if (Date.now() - this.lastProgressAt < this.opts.progressIntervalMs)
681
- return;
707
+ const elapsedOk = Date.now() - this.lastProgressAt >= this.opts.progressIntervalMs;
708
+ const activityOk = this.activityChars >= this.opts.progressMinChars ||
709
+ this.turnsSinceProgress >= this.opts.progressMaxQuietTurns;
710
+ if (!elapsedOk || !activityOk)
711
+ return; // stalling provider → don't waste a turn asking
682
712
  this.lastProgressAt = Date.now();
713
+ this.activityChars = 0;
714
+ this.turnsSinceProgress = 0;
683
715
  const request = "[harness] Please give a brief progress report now: what you are doing, goal progress, " +
684
716
  "what you recently tried, any problems, and your next step. Keep it under 10 lines.";
685
717
  // log both sides so a session restore replays this exchange faithfully
@@ -815,6 +847,10 @@ export class Agent {
815
847
  next: str(a.next) || undefined,
816
848
  ts: new Date().toISOString(),
817
849
  };
850
+ // a report (voluntary or requested) restarts the progress gates
851
+ this.lastProgressAt = Date.now();
852
+ this.activityChars = 0;
853
+ this.turnsSinceProgress = 0;
818
854
  await this.log.append("progress", this.currentSession, this.currentBranch, this.latestProgress);
819
855
  bus.emit("update", { kind: "agent-update", agentId: this.opts.id });
820
856
  }
@@ -962,3 +998,120 @@ function safeParse(json) {
962
998
  return {};
963
999
  }
964
1000
  }
1001
+ /** Walk parent links backwards from the newest event, then flip forward. */
1002
+ function lineageOf(events) {
1003
+ if (events.length === 0)
1004
+ return [];
1005
+ const byId = new Map(events.map((e) => [e.id, e]));
1006
+ const last = events[events.length - 1];
1007
+ const lineage = [];
1008
+ const seen = new Set();
1009
+ for (let cur = last; cur; cur = cur.parent ? byId.get(cur.parent) : undefined) {
1010
+ if (seen.has(cur.id))
1011
+ break;
1012
+ seen.add(cur.id);
1013
+ lineage.push(cur);
1014
+ }
1015
+ lineage.reverse();
1016
+ // the trailing fork event itself is bookkeeping, not conversation
1017
+ while (lineage.length && lineage[0].type === "fork")
1018
+ lineage.shift();
1019
+ return lineage;
1020
+ }
1021
+ /**
1022
+ * Replay ordered events into ChatMessages (shared by session restore and
1023
+ * prompt-edit forks). Prompts logged inside an open tool batch are buffered
1024
+ * until it closes, so user messages never split a tool_call/tool_result pair.
1025
+ */
1026
+ function rebuildMessagesFrom(list) {
1027
+ const msgs = [];
1028
+ const META_TOOLS = new Set([
1029
+ "finish", "report_progress", "set_goal", "get_goal",
1030
+ "read_memory", "set_memory", "list_skills",
1031
+ ]);
1032
+ const openCalls = new Map(); // real tool_call id -> name
1033
+ const bufferedUsers = [];
1034
+ const flushUsers = () => {
1035
+ if (openCalls.size === 0) {
1036
+ for (const text of bufferedUsers.splice(0))
1037
+ msgs.push({ role: "user", content: text });
1038
+ }
1039
+ };
1040
+ for (const e of list) {
1041
+ const d = e.data;
1042
+ if (e.type === "prompt" && typeof d.text === "string") {
1043
+ if (openCalls.size > 0)
1044
+ bufferedUsers.push(d.text);
1045
+ else
1046
+ msgs.push({ role: "user", content: d.text });
1047
+ }
1048
+ else if (e.type === "message") {
1049
+ const role = d.role === "assistant" ? "assistant" : "user";
1050
+ const m = { role, content: typeof d.content === "string" ? d.content : "" };
1051
+ if (Array.isArray(d.toolCalls) && d.toolCalls.length > 0) {
1052
+ m.tool_calls = d.toolCalls.map((c) => ({
1053
+ id: c.id,
1054
+ type: "function",
1055
+ function: { name: c.name, arguments: "{}" },
1056
+ }));
1057
+ // meta tools are answered inline by the harness (no logged result);
1058
+ // the hole-filling pass below synthesizes theirs where they belong
1059
+ for (const t of m.tool_calls)
1060
+ if (!META_TOOLS.has(t.function.name))
1061
+ openCalls.set(t.id, t.function.name);
1062
+ }
1063
+ msgs.push(m);
1064
+ }
1065
+ else if (e.type === "tool_call") {
1066
+ // enrich the preceding assistant tool_calls with real arguments
1067
+ const prev = [...msgs].reverse().find((x) => x.role === "assistant" && x.tool_calls?.some((t) => t.id === d.callId));
1068
+ const tc = prev?.tool_calls?.find((t) => t.id === d.callId);
1069
+ if (tc)
1070
+ tc.function.arguments = JSON.stringify(d.args ?? {});
1071
+ }
1072
+ else if (e.type === "tool_result") {
1073
+ msgs.push({
1074
+ role: "tool",
1075
+ tool_call_id: String(d.callId ?? ""),
1076
+ content: `${d.ok === false ? "(failed) " : ""}${typeof d.result === "string" ? d.result : ""}`,
1077
+ });
1078
+ openCalls.delete(String(d.callId ?? ""));
1079
+ flushUsers();
1080
+ }
1081
+ else if (e.type === "progress") {
1082
+ // progress events may follow an assistant report_progress call that
1083
+ // has no logged tool result — patch it in when present
1084
+ const lastAssistant = [...msgs].reverse().find((x) => x.role === "assistant" && x.tool_calls?.length);
1085
+ if (lastAssistant?.tool_calls?.some((t) => t.function.name === "report_progress")) {
1086
+ for (const t of lastAssistant.tool_calls) {
1087
+ if (!msgs.some((x) => x.role === "tool" && x.tool_call_id === t.id)) {
1088
+ msgs.push({ role: "tool", tool_call_id: t.id, content: "progress recorded" });
1089
+ }
1090
+ openCalls.delete(t.id);
1091
+ }
1092
+ flushUsers();
1093
+ }
1094
+ }
1095
+ }
1096
+ // every assistant tool_call must be answered by a tool message, or the
1097
+ // API rejects the sequence — close any holes left by meta tools (finish)
1098
+ for (let i = 0; i < msgs.length; i++) {
1099
+ const m = msgs[i];
1100
+ if (m.role === "assistant" && m.tool_calls?.length) {
1101
+ for (const t of m.tool_calls) {
1102
+ if (!msgs.slice(i + 1).some((x) => x.role === "tool" && x.tool_call_id === t.id)) {
1103
+ msgs.splice(i + 1, 0, {
1104
+ role: "tool",
1105
+ tool_call_id: t.id,
1106
+ content: t.function.name === "finish" ? `(round ended: ${m.content || "finished"})` : "(no result recorded)",
1107
+ });
1108
+ i++;
1109
+ }
1110
+ }
1111
+ }
1112
+ }
1113
+ // prompts that were still waiting on a hole-filled tail land here
1114
+ for (const text of bufferedUsers.splice(0))
1115
+ msgs.push({ role: "user", content: text });
1116
+ return msgs;
1117
+ }
package/dist/agent/llm.js CHANGED
@@ -96,6 +96,9 @@ export async function chat(cfg, messages, tools, signal) {
96
96
  */
97
97
  export async function chatStream(cfg, messages, tools, signal, onDelta) {
98
98
  let gotChunk = false;
99
+ // hoisted so the abort handler below can attach whatever streamed so far
100
+ let text = "";
101
+ let reasoning = "";
99
102
  try {
100
103
  const stream = await client(cfg).chat.completions.create({
101
104
  model: cfg.model,
@@ -103,8 +106,6 @@ export async function chatStream(cfg, messages, tools, signal, onDelta) {
103
106
  ...(tools.length ? { tools } : {}),
104
107
  stream: true,
105
108
  }, { signal });
106
- let text = "";
107
- let reasoning = "";
108
109
  const calls = {};
109
110
  let finishReason;
110
111
  let usage;
@@ -155,6 +156,11 @@ export async function chatStream(cfg, messages, tools, signal, onDelta) {
155
156
  // provider may not support streaming at all — one clean fallback
156
157
  if (!gotChunk && !signal?.aborted)
157
158
  return chat(cfg, messages, tools, signal);
159
+ // user interrupt: hand back whatever streamed so far so the harness can
160
+ // keep the partial output visible instead of losing it
161
+ if (signal?.aborted && (text || reasoning)) {
162
+ err.partial = { text, reasoning };
163
+ }
158
164
  throw err;
159
165
  }
160
166
  }
@@ -64,11 +64,24 @@ export async function discoverSkills(roots) {
64
64
  const name = parsed.meta.name || e.name;
65
65
  if (byName.has(name))
66
66
  continue; // higher-priority root already defined it
67
+ // collect bundled files (helper scripts, templates, ...) next to SKILL.md
68
+ let files = [];
69
+ try {
70
+ const siblings = await fs.readdir(path.join(root.dir, e.name), { withFileTypes: true });
71
+ files = siblings
72
+ .filter((f) => f.isFile() && f.name !== SKILL_FILE && !f.name.startsWith("."))
73
+ .map((f) => f.name)
74
+ .sort();
75
+ }
76
+ catch {
77
+ /* unreadable dir → no bundled files */
78
+ }
67
79
  byName.set(name, {
68
80
  name,
69
81
  description: parsed.meta.description || "",
70
82
  source: root.source,
71
83
  filePath,
84
+ files,
72
85
  });
73
86
  }
74
87
  }
@@ -5,7 +5,7 @@
5
5
  import { spawn } from "node:child_process";
6
6
  import { existsSync, promises as fs } from "node:fs";
7
7
  import path from "node:path";
8
- import { discoverSkills, isValidSkillName, readSkillFile, saveSkill, } from "./skills.js";
8
+ import { discoverSkills, isValidSkillName, readSkillFile, saveSkill, SKILL_FILE, } from "./skills.js";
9
9
  const str = (v, fallback = "") => (typeof v === "string" ? v : fallback);
10
10
  const num = (v, fallback) => (typeof v === "number" ? v : fallback);
11
11
  function clip(s, max) {
@@ -720,20 +720,50 @@ export const TOOLS = [
720
720
  result: `unknown skill: ${str(args.name)}. Available: ${skills.map((s) => s.name).join(", ") || "(none)"}`,
721
721
  };
722
722
  }
723
- return { ok: true, result: await readSkillFile(def) };
723
+ let result = await readSkillFile(def);
724
+ if (def.files.length) {
725
+ // surface bundled scripts as runnable paths: workspace-relative when
726
+ // possible (bash runs in the workspace), absolute for global skills
727
+ const dirAbs = path.dirname(def.filePath);
728
+ const rootDir = roots
729
+ .map((r) => r.dir)
730
+ .find((d) => def.filePath.startsWith(d + path.sep));
731
+ const listed = def.files.map((f) => {
732
+ const abs = path.join(dirAbs, f);
733
+ return rootDir ? path.relative(ctx.cwd, abs) || f : abs;
734
+ });
735
+ result +=
736
+ `\n\n--- Files bundled with this skill:\n` +
737
+ listed.map((f) => `- ${f}`).join("\n") +
738
+ `\nRun scripts with bash (chmod +x first if needed).`;
739
+ }
740
+ return { ok: true, result };
724
741
  },
725
742
  },
726
743
  {
727
744
  name: "save_skill",
728
745
  description: "Create or update a reusable skill (a playbook you want to survive this session and be " +
729
746
  "loadable later via load_skill). Write distilled, step-by-step instructions — not a chat log. " +
730
- "The skill becomes available in your system prompt from the next turn.",
747
+ "Bundle helper scripts with the files argument; they are saved NEXT TO SKILL.md, listed by " +
748
+ "load_skill, and made executable (.sh/.py/.js). Available from the next turn.",
731
749
  parameters: {
732
750
  type: "object",
733
751
  properties: {
734
752
  name: { type: "string", description: "kebab-case id, e.g. release-checklist" },
735
753
  description: { type: "string", description: "one line: what it is for / when to use it" },
736
754
  content: { type: "string", description: "markdown instructions" },
755
+ files: {
756
+ type: "array",
757
+ description: "helper scripts/files stored beside SKILL.md",
758
+ items: {
759
+ type: "object",
760
+ properties: {
761
+ name: { type: "string", description: 'bare file name, e.g. "rollback.sh"' },
762
+ content: { type: "string" },
763
+ },
764
+ required: ["name", "content"],
765
+ },
766
+ },
737
767
  },
738
768
  required: ["name", "description", "content"],
739
769
  },
@@ -751,7 +781,24 @@ export const TOOLS = [
751
781
  if (!content.trim())
752
782
  return { ok: false, result: "content required" };
753
783
  const filePath = await saveSkill(roots[0].dir, name, description, content.slice(0, 64_000));
754
- return { ok: true, result: `saved skill "${name}" to ${filePath} (listed from next turn)` };
784
+ // bundled scripts/files next to SKILL.md
785
+ const written = [];
786
+ const rawFiles = Array.isArray(args.files) ? args.files : [];
787
+ for (const f of rawFiles.slice(0, 10)) {
788
+ const fname = str(f?.name);
789
+ const fcontent = str(f?.content);
790
+ if (!fcontent.trim())
791
+ continue;
792
+ if (!/^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/.test(fname) || fname === SKILL_FILE)
793
+ continue;
794
+ const abs = path.join(path.dirname(filePath), fname);
795
+ await fs.writeFile(abs, fcontent, "utf8");
796
+ if (/\.(sh|py|js|mjs)$/.test(fname))
797
+ await fs.chmod(abs, 0o755);
798
+ written.push(fname);
799
+ }
800
+ const extra = written.length ? `\nbundled files: ${written.join(", ")}` : "";
801
+ return { ok: true, result: `saved skill "${name}" to ${filePath}${extra} (listed from next turn)` };
755
802
  },
756
803
  },
757
804
  ];
package/dist/master.js CHANGED
@@ -8,7 +8,8 @@ import { randomUUID } from "node:crypto";
8
8
  import path from "node:path";
9
9
  import os from "node:os";
10
10
  import { Agent } from "./agent/agent.js";
11
- import { parseSchedule, matches } from "./scheduler/cron.js";
11
+ import { parseSchedule, matches, nextFireAt } from "./scheduler/cron.js";
12
+ import { bus } from "./bus.js";
12
13
  const CONFIG_DIR = process.env.TEAPOT_CONFIG_DIR ??
13
14
  path.join(process.env.XDG_CONFIG_HOME ?? path.join(os.homedir(), ".config"), "teapot-coding-agent");
14
15
  const DATA_DIR = process.env.TEAPOT_DATA_DIR ??
@@ -152,6 +153,8 @@ export class Master {
152
153
  this.raw.tasks = this.config.tasks;
153
154
  if (this.raw.progressIntervalMs === undefined && this.config.progressIntervalMs !== undefined)
154
155
  this.raw.progressIntervalMs = this.config.progressIntervalMs;
156
+ if (this.raw.progressMinChars === undefined && this.config.progressMinChars !== undefined)
157
+ this.raw.progressMinChars = this.config.progressMinChars;
155
158
  writeFileSync(this.configPath, JSON.stringify(this.raw, null, 2) + "\n");
156
159
  }
157
160
  raw = loadedRaw();
@@ -167,6 +170,12 @@ export class Master {
167
170
  a.opts.progressIntervalMs =
168
171
  patch.progressIntervalMs;
169
172
  }
173
+ if (patch.progressMinChars !== undefined) {
174
+ this.config.progressMinChars = patch.progressMinChars;
175
+ for (const a of this.agents.values())
176
+ a.opts.progressMinChars =
177
+ patch.progressMinChars;
178
+ }
170
179
  if (patch.tasks) {
171
180
  this.config.tasks = patch.tasks;
172
181
  // rebuild schedule table live
@@ -225,12 +234,22 @@ export class Master {
225
234
  llm,
226
235
  sessionDir,
227
236
  progressIntervalMs: this.config.progressIntervalMs,
237
+ ...(this.config.progressMinChars ? { progressMinChars: this.config.progressMinChars } : {}),
228
238
  autoContinue: true,
229
239
  ...(this.config.contextTokenBudget ? { contextTokenBudget: this.config.contextTokenBudget } : {}),
240
+ ...(ac.contextWindowTokens || this.config.contextWindowTokens
241
+ ? { contextWindowTokens: (ac.contextWindowTokens ?? this.config.contextWindowTokens) }
242
+ : {}),
230
243
  globalSkillsDir: path.join(CONFIG_DIR, "skills"),
231
244
  provider: provName,
232
245
  });
233
- agent.log.onEvent = (e) => printAgentEvent(e);
246
+ // console line + broadcast: the web UI only refreshes on bus traffic, so
247
+ // every appended event must reach it (otherwise messages sit invisible
248
+ // until an unrelated status change happens to fire)
249
+ agent.log.onEvent = (e) => {
250
+ printAgentEvent(e);
251
+ bus.emit("update", { kind: "event", agentId: e.agent, event: e });
252
+ };
234
253
  await agent.init();
235
254
  this.agents.set(ac.id, agent);
236
255
  if (opts.persist) {
@@ -363,6 +382,7 @@ export class Master {
363
382
  if (t.lastRunMin === minuteKey)
364
383
  continue; // dedupe within the same minute
365
384
  t.lastRunMin = minuteKey;
385
+ t.lastRunAt = Date.now();
366
386
  const agent = this.agents.get(t.task.agent);
367
387
  if (!agent)
368
388
  continue;
@@ -380,6 +400,18 @@ export class Master {
380
400
  }
381
401
  }
382
402
  }
403
+ /** Everything the UI needs to make cron schedules legible. */
404
+ tasksView() {
405
+ return this.tasks.map((t) => ({
406
+ id: t.task.id,
407
+ agent: t.task.agent,
408
+ schedule: t.schedule.raw,
409
+ forked: !!t.task.forked,
410
+ prompt: t.task.prompt,
411
+ next: nextFireAt(t.schedule),
412
+ last: t.lastRunAt ? new Date(t.lastRunAt).toISOString() : null,
413
+ }));
414
+ }
383
415
  metrics() {
384
416
  const mu = process.memoryUsage();
385
417
  const cu = process.cpuUsage();
@@ -79,3 +79,18 @@ export function matches(schedule, d) {
79
79
  }
80
80
  return true;
81
81
  }
82
+ /**
83
+ * Next fire time after `from`, scanning minute by minute (cheap: a handful of
84
+ * integer compares per minute). Returns null when nothing fires within ~31
85
+ * days (e.g. a Feb-29-only cron in August).
86
+ */
87
+ export function nextFireAt(schedule, from = new Date()) {
88
+ const startMinute = Math.floor(from.getTime() / 60_000) + 1; // next whole minute
89
+ const horizon = 60 * 24 * 31;
90
+ for (let i = 0; i < horizon; i++) {
91
+ const d = new Date((startMinute + i) * 60_000);
92
+ if (matches(schedule, d))
93
+ return d.toISOString();
94
+ }
95
+ return null;
96
+ }
@@ -257,6 +257,14 @@ export function buildApp(master) {
257
257
  const a = master.agents.get(c.req.param("id"));
258
258
  return a ? c.json(a.snapshot()) : c.json({ error: "not found" }, 404);
259
259
  });
260
+ // lazy session load: stopped (not restored) → idle, history rebuilt from the log
261
+ app.post("/api/agents/:id/load", async (c) => {
262
+ const a = master.agents.get(c.req.param("id"));
263
+ if (!a)
264
+ return c.json({ error: "not found" }, 404);
265
+ await a.load();
266
+ return c.json({ ok: true, agent: a.snapshot() });
267
+ });
260
268
  app.post("/api/agents/:id/prompt", async (c) => {
261
269
  const a = master.agents.get(c.req.param("id"));
262
270
  if (!a)
@@ -334,14 +342,37 @@ export function buildApp(master) {
334
342
  if (!a)
335
343
  return c.json({ error: "not found" }, 404);
336
344
  const body = await c.req.json();
337
- if (body.text)
345
+ if (body.text) {
338
346
  await a.setGoal(body.text);
347
+ // goals live behind get_goal(), so a silent save would go unnoticed —
348
+ // queue a harness prompt unless the caller explicitly declines
349
+ if (body.notify !== false)
350
+ a.enqueuePrompt(`[harness] The operator set a new goal:\n\n${body.text}\n\nAlign your work with it.`, "harness");
351
+ }
339
352
  else if (body.status)
340
353
  await a.setGoalStatus(body.status);
341
354
  else
342
355
  return c.json({ error: "text or status required" }, 400);
343
356
  return c.json({ ok: true });
344
357
  });
358
+ // edit a previously-sent prompt: forks there, optionally summarizes the tail
359
+ app.post("/api/agents/:id/edit-prompt", async (c) => {
360
+ const a = master.agents.get(c.req.param("id"));
361
+ if (!a)
362
+ return c.json({ error: "not found" }, 404);
363
+ const body = await c.req
364
+ .json()
365
+ .catch(() => null);
366
+ if (!body?.eventId || !body.text?.trim())
367
+ return c.json({ error: "eventId and text required" }, 400);
368
+ try {
369
+ const r = await a.editPromptAt(body.eventId, body.text, body.tail === "summarize" ? "summarize" : "discard");
370
+ return c.json({ ok: true, ...r });
371
+ }
372
+ catch (err) {
373
+ return c.json({ error: err.message }, 409);
374
+ }
375
+ });
345
376
  app.post("/api/agents/:id/fork", async (c) => {
346
377
  const a = master.agents.get(c.req.param("id"));
347
378
  if (!a)
@@ -382,6 +413,8 @@ export function buildApp(master) {
382
413
  });
383
414
  // ---- metrics / SSE ----
384
415
  app.get("/api/metrics", (c) => c.json(master.metrics()));
416
+ // scheduled tasks with computed next-fire times (cron visibility for the UI)
417
+ app.get("/api/tasks", (c) => c.json({ tasks: master.tasksView() }));
385
418
  app.get("/api/events", (c) => {
386
419
  c.header("content-type", "text/event-stream");
387
420
  c.header("cache-control", "no-cache");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "teapot-coding-agent",
3
- "version": "0.9.0",
3
+ "version": "0.10.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",
@@ -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 pre code{background:0 0;padding:0}.content h1,.content h2,.content h3,.content h4,.content h5,.content h6{margin:8px 0 2px;font-size:15px}.content h1{font-size:16.5px}.content h2{font-size:15.5px}.content blockquote{border-left:3px solid var(--bg-light);color:var(--dim);background:#ffffff05;border-radius:0 4px 4px 0;margin:4px 0;padding:2px 10px}.content blockquote p{margin:2px 0}.content hr{border:none;border-top:1px solid var(--bg-light);margin:8px 0}.content del{color:var(--dim)}.content img{border-radius:6px;max-width:100%}.content li.task{margin-left:-18px;list-style:none}.content li:has(>input[type=checkbox]){margin-left:-18px;list-style:none}.content li input[type=checkbox]{accent-color:var(--ok);margin-right:6px}.tbl{margin:6px 0;overflow-x:auto}.tbl table{border-collapse:collapse;font-size:13px}.tbl th,.tbl td{border:1px solid var(--bg-light);text-align:left;padding:3px 9px}.tbl th{background:var(--bg-darkest);font-weight:600}.embed{border-left:3px solid var(--tool);background:var(--bg-darkest);border-radius:4px;margin-top:3px;padding:6px 10px;font-size:13.5px}.embed.fail{border-color:var(--err)}.embed.done{border-color:var(--ok)}.embed.running{border-color:var(--warn)}.embed.running summary .meta:after{content:"⋯";color:var(--warn);margin-left:6px;animation:1s step-end infinite blink;display:inline-block}.embed summary{gap:8px}.embed summary .mono{font-family:ui-monospace,Menlo,monospace}.toolbody{background:var(--bg-darkest);white-space:pre-wrap;word-break:break-word;border-radius:4px;max-height:340px;margin:4px 0;padding:6px 8px;font-size:12.5px;overflow-y:auto}.toolbody.del{border-left:2px solid var(--err);color:#f0a5a6;background:#ed424514}.toolbody.add{border-left:2px solid var(--ok);color:#9fd8ae;background:#3ba55d14}.toolbody.patch{padding:4px 8px}.toolbody.patch .pline{white-space:pre-wrap;word-break:break-word}.toolbody.patch .pline.add{color:#9fd8ae;border-left:2px solid var(--ok);background:#3ba55d14;padding-left:4px}.toolbody.patch .pline.del{color:#f0a5a6;border-left:2px solid var(--err);background:#ed424514;padding-left:4px}.toolbody.patch .pline.meta{color:var(--dim)}.embed summary{cursor:pointer;-webkit-user-select:none;user-select:none;list-style-position:outside}.embed summary::marker{color:var(--dim)}.embed[open] summary{margin-bottom:4px}.embed .mono{white-space:pre-wrap;word-break:break-word;max-height:340px;font-family:ui-monospace,Menlo,monospace;font-size:12.5px;overflow-y:auto}.embed .meta{color:var(--dim);margin-top:3px;font-size:11px}.reasoning{border-left:3px dashed var(--bg-light);color:var(--dim);background:#ffffff05;border-radius:4px;margin:2px 0;padding:2px 10px;font-size:12.5px}.reasoning summary{cursor:pointer;-webkit-user-select:none;user-select:none;opacity:.75}.reasoning summary:hover{opacity:1;color:var(--fg)}.reasoning[open] summary{margin-bottom:4px}.reasoning .mono{white-space:pre-wrap;word-break:break-word;max-height:260px;overflow-y:auto}.msg.live .avatar{animation:1.6s ease-in-out infinite pulse}.cursor{color:var(--acc);animation:1s step-end infinite blink}.interrupted{color:var(--warn);margin-top:3px;font-size:11.5px}@keyframes blink{50%{opacity:0}}@keyframes pulse{50%{opacity:.55}}.conn{background:var(--err);vertical-align:middle;width:8px;height:8px;box-shadow:0 0 6px var(--err);border-radius:50%;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;position:relative}.composer form{background:var(--bg-light);border-radius:10px;align-items:flex-end;gap:8px;padding:10px 12px;display:flex}.composer textarea{color:var(--fg);font:inherit;resize:none;background:0 0;border:none;outline:none;flex:1;max-height:160px;line-height:1.4;overflow-y:auto}.cmds{background:var(--bg-mid);border:1px solid var(--bg-light);z-index:3;border-radius:8px;position:absolute;bottom:calc(100% - 8px);left:16px;right:16px;overflow:hidden;box-shadow:0 -6px 20px #0007}.cmdrow{cursor:pointer;align-items:baseline;gap:10px;padding:7px 12px;font-size:13.5px;display:flex}.cmdrow:hover{background:var(--bg-light)}.cmdrow .muted{font-size:12px}.composer button{background:var(--acc);color:#fff;cursor:pointer;border:none;border-radius:8px;padding:7px 14px;font-weight:600}.composer button:hover{opacity:.9}.composer label{color:var(--dim);white-space:nowrap;align-items:center;gap:4px;font-size:12px;display:flex}.hint{color:var(--dim);margin-top:5px;font-size:11px}.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)}.prog .progrow{gap:8px;margin-bottom:4px;display:flex}.prog .progrow b{color:var(--dim);text-transform:uppercase;letter-spacing:.05em;flex-shrink:0;min-width:62px;padding-top:2px;font-size:10px}.prog .progrow.warn span{color:var(--err)}.msg-head .editbtn{color:var(--dim);cursor:pointer;opacity:0;background:0 0;border:none;padding:0 2px;font-size:11px;transition:opacity .12s}.msg:hover .msg-head .editbtn{opacity:1}.msg-head .editbtn:hover{color:var(--acc)}.branch-row{color:var(--dim);cursor:pointer;justify-content:space-between;padding:3px 0;font-size:12px;display:flex}.branch-row:hover,.branch-row.cur{color:var(--fg)}.mini-cron{opacity:.75;margin-left:auto;font-size:10px}.sched-row{cursor:pointer;border-radius:6px;margin-bottom:2px;padding:6px 8px}.sched-row:hover,.sched-row.cur{background:var(--bg-mid)}.sched-top{align-items:baseline;gap:6px;font-size:12.5px;display:flex}.sched-row .sched-meta{color:var(--dim);margin-top:2px;font-size:11px}.sched-row .sched-prompt{color:var(--dim);text-overflow:ellipsis;white-space:nowrap;margin-top:2px;font-size:11.5px;overflow:hidden}.badge.cron{color:var(--tool);white-space:nowrap;background:#3ba0c91a;border:1px solid #3ba0c944}.sesscard{flex-direction:column;gap:6px;font-size:12.5px;display:flex}.sessrow{align-items:center;gap:8px;display:flex}.sessrow .k{color:var(--dim);text-transform:uppercase;letter-spacing:.05em;flex-shrink:0;width:74px;font-size:10px}.ellip{text-overflow:ellipsis;white-space:nowrap;text-align:left;direction:rtl;overflow:hidden}.modelbox{background:var(--bg-darkest);border-radius:8px;flex-direction:column;gap:6px;padding:10px;display:flex}.modelbox select,.modelbox input[type=text]{background:var(--bg-mid);color:var(--fg);font:inherit;border:none;border-radius:6px;outline:none;min-width:0;padding:6px 8px}.modelbox button{background:var(--acc);color:#fff;cursor:pointer;white-space:nowrap;border:none;border-radius:6px;padding:6px 10px;font-size:12.5px;font-weight:600}.modelbox button:hover{opacity:.9}.modelbox .meta{color:var(--dim);font-size:11px}.btnrow{gap:6px;margin:8px 0;display:flex}.btnrow button{background:var(--bg-light);color:var(--fg);cursor:pointer;border:none;border-radius:6px;padding:6px 10px;font-size:13px}.btnrow button:hover{filter:brightness(1.2)}.btnrow .runbtn{background:var(--ok);color:#fff;font-weight:600}.btnrow .danger{background:var(--err);color:#fff;font-weight:600}.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,13 @@
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=ce,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(()=>A(o)));d=o,p=null;try{return O(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[re.bind(n),e=>(typeof e==`function`&&(e=f&&f.running&&f.sources.has(n)?e(n.tValue):e(n.value)),ie(n,e))]}function y(e,t,n){E(oe(e,t,!1,c))}function b(e,t,n){s=le;let r=oe(e,t,!1,c),i=ne&&te(ne);i&&(r.suspense=i),(!n||!n.render)&&(r.user=!0),h?h.push(r):E(r)}function x(e,t,n){n=n?Object.assign({},a,n):a;let r=oe(e,t,!0,0);return r.observers=null,r.observerSlots=null,r.comparator=n.equals||void 0,E(r),re.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[ee,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 re(){let e=f&&f.running;if(this.sources&&(e?this.tState:this.state)){if((e?this.tState:this.state)===c)E(this);else{let e=m;m=null,O(()=>ue(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 ie(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&&O(()=>{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&&k(n)),r?n.tState=c:n.state=c)}if(m.length>1e6)throw m=[],Error()},!1)}return t}function E(e){if(!e.fn)return;A(e);let t=g;ae(e,f&&f.running&&f.sources.has(e)?e.tValue:e.value,t),f&&!f.running&&f.sources.has(e)&&queueMicrotask(()=>{O(()=>{f&&(f.running=!0),p=d=e,ae(e,e.tValue,t),p=d=null},!1)})}function ae(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(A),e.tOwned=void 0):(e.state=c,e.owned&&e.owned.forEach(A),e.owned=null)),e.updatedAt=n+1,M(t)}finally{p=a,d=i}(!e.updatedAt||e.updatedAt<=n)&&(e.updatedAt!=null&&`observers`in e?ie(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 oe(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 D(e){let t=f&&f.running;if((t?e.tState:e.state)===0)return;if((t?e.tState:e.state)===l)return ue(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)E(e);else if((t?e.tState:e.state)===l){let t=m;m=null,O(()=>ue(e,n[0]),!1),m=t}}}function O(e,t){if(m)return e();let n=!1;t||(m=[]),h?n=!0:h=[],g++;try{let t=e();return se(n),t}catch(e){n||(h=null),m=null,M(e)}}function se(e){if(m&&=(ce(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,O(()=>{for(let e of n)A(e);for(let t of e){if(t.value=t.tValue,t.owned)for(let e=0,n=t.owned.length;e<n;e++)A(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&&O(()=>s(n),!1),t&&t()}function ce(e){for(let t=0;t<e.length;t++)D(e[t])}function le(t){let r,i=0;for(r=0;r<t.length;r++){let e=t[r];e.user?t[i++]=e:D(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++)D(t[r])}function ue(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)&&D(i):e===l&&ue(i,t)}}}function k(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&&k(r))}}function A(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--)A(e.tOwned[t]);delete e.tOwned}if(f&&f.running&&e.pure)j(e,!0);else if(e.owned){for(t=e.owned.length-1;t>=0;t--)A(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 j(e,t){if(t||(e.tState=0,f.disposed.add(e)),e.owned)for(let t=0;t<e.owned.length;t++)j(e.owned[t])}function de(e){return e instanceof Error?e:Error(typeof e==`string`?e:`Unknown error`,{cause:e})}function fe(e,t,n){try{for(let n of t)n(e)}catch(e){M(e,n&&n.owner||null)}}function M(e,t=d){let n=o&&t&&t.context&&t.context[o],r=de(e);if(!n)throw r;h?h.push({fn(){fe(r,n,t)},state:c}):fe(r,n,t)}var pe=Symbol(`fallback`);function N(e){for(let t=0;t<e.length;t++)e[t]()}function me(e,t,n={}){let r=[],a=[],o=[],s=0,c=t.length>1?[]:null;return w(()=>N(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&&(N(o),o=[],r=[],a=[],s=0,c&&=[]),n.fallback&&(r=[pe],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 P(e,t){return S(()=>e(t||{}))}var he=e=>`Stale read from <${e}>.`;function F(e){let t=`fallback`in e&&{fallback:()=>e.fallback};return x(me(()=>e.each,e.children,t||void 0))}function I(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 he(`Show`);return n()})):a}return e.fallback},void 0,void 0)}var L=e=>x(()=>e());function R(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 ge=`_$DX_DELEGATE`;function _e(e,t,n,r={}){let i;return _(r=>{i=r,t===document?e():U(t,e(),t.firstChild?null:void 0,n)},r.owner),()=>{i(),t.textContent=``}}function z(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 ve(e,t=window.document){let n=t[ge]||(t[ge]=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,xe))}}function B(e,t,n){W(e)||(n==null?e.removeAttribute(t):e.setAttribute(t,n))}function V(e,t){W(e)||(t==null?e.removeAttribute(`class`):e.className=t)}function ye(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 H(e,t,n){n==null?e.style.removeProperty(t):e.style.setProperty(t,n)}function be(e,t,n){return S(()=>e(t,n))}function U(e,t,n,r){if(n!==void 0&&!r&&(r=[]),typeof t!=`function`)return G(e,t,r,n);y(r=>G(e,t(),r,n),r)}function W(t){return!!e.context&&!e.done&&(!t||t.isConnected)}function xe(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 G(e,t,n,r,i){let a=W(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=K(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=K(e,n,r)}else if(o===`function`)return y(()=>{let i=t();for(;typeof i==`function`;)i=i();n=G(e,i,n,r)}),()=>n;else if(Array.isArray(t)){let o=[],c=n&&Array.isArray(n);if(Se(o,t,n,i))return y(()=>n=G(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=K(e,n,r),s)return n}else c?n.length===0?Ce(e,o,r):R(e,n,o):(n&&K(e),Ce(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=K(e,n,r,t);K(e,n,null,t)}else n==null||n===``||!e.firstChild?e.appendChild(t):e.replaceChild(t,e.firstChild);n=t}return n}function Se(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=Se(e,o,s)||i;else if(c===`function`){if(r){for(;typeof o==`function`;)o=o();i=Se(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 Ce(e,t,n=null){for(let r=0,i=t.length;r<i;r++)e.insertBefore(t[r],n)}function K(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]}var q=/^(\s*)([-*+]|\d+[.)])\s+(.*)$/;function we(e){return Te(De(e.replace(/\r\n/g,`
2
+ `)).split(`
3
+ `))}function Te(e){let t=[],n=0;for(;n<e.length;){let o=e[n];if(/^```\w*\s*$/.test(o)){let r=[];for(n++;n<e.length&&!/^```\s*$/.test(e[n]);)r.push(e[n++]);n++,t.push(`<pre><code>${r.join(`
4
+ `)}</code></pre>`);continue}if(/^ {0,3}(?:-{3,}|\*{3,}|_{3,})\s*$/.test(o)){t.push(`<hr>`),n++;continue}let s=o.match(/^(#{1,6})\s+(.*)$/);if(s){t.push(`<h${s[1].length}>${a(s[2])}</h${s[1].length}>`),n++;continue}if(/^\s*&gt;/.test(o)){let r=[];for(;n<e.length&&/^\s*&gt;/.test(e[n]);)r.push(e[n++].replace(/^\s*&gt;\s?/,``));t.push(`<blockquote>${Te(r)}</blockquote>`);continue}if(o.includes(`|`)&&n+1<e.length&&Ee(e[n+1])){let r=J(e[n+1]).map(e=>e.startsWith(`:`)&&e.endsWith(`:`)?`center`:e.endsWith(`:`)?`right`:`left`),i=J(o);n+=2;let s=[];for(;n<e.length&&/\S/.test(e[n])&&e[n].includes(`|`);)s.push(J(e[n])),n++;let c=(e,t,n)=>{let i=r[t];return`<${n}${i&&i!==`left`?` style="text-align:${i}"`:``}>${a(e)}</${n}>`};t.push(`<div class="tbl"><table><thead><tr>${i.map((e,t)=>c(e,t,`th`)).join(``)}</tr></thead><tbody>${s.map(e=>`<tr>${e.map((e,t)=>c(e,t,`td`)).join(``)}</tr>`).join(``)}</tbody></table></div>`);continue}if(q.test(o)){t.push(i(r(o.match(q)[1])));continue}if(/^\s*$/.test(o)){n++;continue}let c=[];for(;n<e.length&&!/^\s*$/.test(e[n])&&!/^#{1,6}\s/.test(e[n])&&!/^```/.test(e[n])&&!/^ {0,3}(?:-{3,}|\*{3,}|_{3,})\s*$/.test(e[n])&&!/^\s*&gt;/.test(e[n])&&!q.test(e[n])&&!(e[n].includes(`|`)&&n+1<e.length&&Ee(e[n+1]));)c.push(e[n++]);t.push(`<p>${c.map(a).join(`<br>`)}</p>`)}return t.join(`
5
+ `);function r(e){return e.replace(/\t/g,` `).length}function i(t){let o=null,s=[];for(;n<e.length;){let c=e[n].match(q);if(!c)break;let l=r(c[1]);if(l<t)break;let u=/^\d/.test(c[2]);if(o===null)o=u;else if(u!==o)break;n++;let d=c[3];for(;n<e.length&&/\S/.test(e[n])&&!q.test(e[n])&&!/^#{1,6}\s/.test(e[n])&&!/^```/.test(e[n])&&!/^\s*&gt;/.test(e[n]);)d+=` `+e[n].trim(),n++;let f=``,p=e[n]?.match(q);p&&r(p[1])>l&&(f=i(r(p[1])));let m=d.match(/^\[( |x|X)\]\s+(.*)$/),h=m?`<input type="checkbox" disabled${m[1].toLowerCase()===`x`?` checked`:``}> `:``;s.push(`<li>${h}${a(m?m[2]:d)}${f}</li>`)}return o?`<ol>${s.join(``)}</ol>`:`<ul>${s.join(``)}</ul>`}function a(e){let t=[];return e=e.replace(/`([^`]+)`/g,(e,n)=>(t.push(`<code>${n}</code>`),`\u0000${t.length-1}\u0000`)),e=e.replace(/!\[([^\]]*)\]\((https?:\/\/[^)\s]+)(?:\s+&quot;[^)]*&quot;)?\)/g,`<img src="$2" alt="$1" loading="lazy">`),e=e.replace(/\[([^\]]+)\]\((https?:\/\/[^)\s]+)(?:\s+&quot;[^)]*&quot;)?\)/g,`<a href="$2" rel="noopener noreferrer" target="_blank">$1</a>`),e=e.replace(/(?<!["'=\w])(https?:\/\/[^\s<>"')\]]*[^\s<>"')\].,;:!?"')\]])/g,`<a href="$1">$1</a>`),e=e.replace(/\*\*\*([\s\S]+?)\*\*\*/g,`<strong><em>$1</em></strong>`),e=e.replace(/\*\*([\s\S]+?)\*\*/g,`<strong>$1</strong>`),e=e.replace(/(^|[^\w])__(?=\S)([\s\S]*?\S)__(?!\w)/g,`$1<strong>$2</strong>`),e=e.replace(/(^|[^\w*])\*(?!\s)([^*\n]+?)\*(?![\w*])/g,`$1<em>$2</em>`),e=e.replace(/(^|[^\w])_(?!\s)([^_\n]+?)_(?!\w)/g,`$1<em>$2</em>`),e=e.replace(/~~([\s\S]+?)~~/g,`<del>$1</del>`),e.replace(/\u0000(\d+)\u0000/g,(e,n)=>t[+n])}}function J(e){let t=e.trim();t.startsWith(`|`)&&(t=t.slice(1));let n=[],r=``;for(let e=0;e<t.length;e++){if(t[e]===`\\`&&t[e+1]===`|`){r+=`|`,e++;continue}if(t[e]===`|`&&e===t.length-1)break;if(t[e]===`|`){n.push(r.trim()),r=``;continue}r+=t[e]}return n.push(r.trim()),n.filter((e,r)=>!(e===``&&r===n.length-1&&t.endsWith(`|`)))}function Ee(e){let t=e.trim();if(!t.includes(`|`)||!t.includes(`-`))return!1;let n=J(t);return n.every(e=>/^:?-+:?$/.test(e))&&n.some(e=>e!==``)}function De(e){return e.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`).replace(/"/g,`&quot;`)}var Oe=`modulepreload`,ke=function(e){return`/`+e},Ae={},je=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=ke(t,n),t=s(t),t in Ae)return;Ae[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`:Oe,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)})},Me=z(`<br>`),Ne=z(`<span class="badge queued">⏳ <!> queued`),Pe=z(`<span class="badge cron">⏰ `),Fe=z(`<span class=sub>ℹ`),Ie=z(`<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)">▤`),Le=z(`<details class=reasoning><summary>💭 reasoning</summary><div class=mono>`),Re=z(`<div class=content><span class=cursor>▍`),ze=z(`<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…`),Be=z(`<div class=feed>`),Ve=z(`<button class=jump>↓ `),He=z(`<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>`),Ue=z(`<div class=cmds>`),We=z(`<div class=composer><form><textarea rows=1></textarea><label title="when unchecked, sending only queues the prompt without waking an idle agent"><input type=checkbox>start if idle</label><button type=submit>send</button></form><div class=hint>`),Ge=z(`<h3>🎛 session`),Ke=z(`<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>/`),qe=z(`<h3>🧦 model`),Je=z(`<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: `),Ye=z(`<h3>⏯ controls`),Xe=z(`<button class=danger title="interrupt: aborts the current LLM call; the running tool finishes first">■ stop`),Ze=z(`<div class=btnrow><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`),Qe=z(`<h3>🎯 goal <span>`),$e=z(`<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"><label class=muted title="queue a harness prompt telling the agent about the new goal at its next turn boundary"style=display:flex;align-items:center;gap:3px;font-size:11px;white-space:nowrap;cursor:pointer><input id=goal-notify type=checkbox checked> notify</label><button type=submit style="background:var(--acc);border:none;border-radius:6px;color:#fff;padding:0 10px;cursor:pointer">✓`),et=z(`<div class=card>`),tt=z(`<div class=muted style=font-size:11px;margin-top:4px>stored with the session · the model reads it via get_goal() ·`),nt=z(`<h3>📈 progress`),rt=z(`<h3>📊 runtime`),it=z(`<div class="card muted">turns <!> · tools <!> · compacted <!>
6
+ tokens in/out <!>/`),at=z(`<h3>🌿 branches <span class=muted style=text-transform:none;letter-spacing:0>· click to filter the feed`),ot=z(`<h3>⏰ schedule <span class=muted style=text-transform:none;letter-spacing:0>· cron tasks, all agents · edit in settings`),st=z(`<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>`),ct=z(`<span class=mini-cron>⏰`),lt=z(`<span title="goal done">✓`),ut=z(`<div><span></span><span>`),dt=z(`<div class=muted style=display:grid;place-items:center;height:100%>select an agent`),ft=z(`<div class=muted style=display:grid;place-items:center;height:100%>no events yet — say something or press ▶ start`),pt=z(`<div class="content muted">thinking…`),mt=z(`<div class=cmdrow><b></b><span class=muted>`),ht=z(`<option>`),gt=z(`<button class=runbtn title="run toward the goal (starts the loop)">▶ start`),_t=z(`<div class=muted>none yet — the harness asks for a report after real activity, and the agent can report_progress anytime`),vt=z(`<div class=progrow><b>recent</b><span>`),yt=z(`<div class="progrow warn"><b>⚠ problems</b><span>`),bt=z(`<div class=progrow><b>next</b><span>`),xt=z(`<div class=progrow><b>goal</b><span>`),St=z(`<div class="card prog"><div class=progrow><b>doing</b><span></span></div><div class="meta muted">`),Ct=z(`<div><span></span><span> events`),wt=z(`<div class=muted>no scheduled tasks — add them in ⚙ settings ("scheduled tasks")`),Tt=z(`<span title="runs on a forked branch so chatter stays off the main line">⑂`),Et=z(`<div><div class=sched-top><b></b><span class=muted>@</span></div><div class="sched-meta mono"> → next </div><div class="sched-prompt muted">`),Dt=z(`<div><div style=font-size:12.5px;margin-bottom:4px> event(s) came after this prompt — what should happen to them on the new branch?</div><label style=display:flex;gap:6px;align-items:center;font-size:13px;color:var(--fg)><input type=radio name=tail>summarize them into a note the agent can still read</label><label style=display:flex;gap:6px;align-items:center;font-size:13px;color:var(--fg)><input type=radio name=tail>discard them entirely (clean timeline)`),Ot=z(`<form style=display:flex;flex-direction:column;gap:10px><textarea id=edit-text class="mono w100"rows=6></textarea><div style=display:flex;justify-content:flex-end;gap:8px><button type=button>cancel</button><button type=submit style="background:var(--acc);border:none;border-radius:6px;color:#fff;padding:6px 12px;cursor:pointer">⑂ fork & resend`),kt=z(`<div class=mono>`),At=z(`<pre class="mono toolbody">`),Y=z(`<div class=meta>ms`),jt=z(`<div class=meta>waiting for output…`),X=z(`<div class=meta>`),Mt=z(`<div class=meta>writing…`),Nt=z(`<pre class="mono toolbody del">`),Pt=z(`<pre class="mono toolbody add">`),Ft=z(`<div class=meta> · <!>ms`),It=z(`<div class=meta>applying…`),Lt=z(`<pre class="mono toolbody patch">`),Rt=z(`<div>`),zt=z(`<div class=meta>validating…`),Bt=z(`<div class=meta><a target=_blank rel="noopener noreferrer">open ↗`),Vt=z(`<div class=content>`),Ht=z(`<div class=meta>loading…`),Ut=z(`<div class=meta>bundled: `),Wt=z(`<div class=meta>saving…`),Gt=z(`<details><summary><b>⚙ </b><span class=meta>`),Kt=z(`<div class=divider-msg>⑂ forked from <!> → `),qt=z(`<div class=divider-msg>🎯 goal <!>: `),Jt=z(`<div> → `),Yt=z(`<div class=avatar>`),Xt=z(`<button class=editbtn title="edit this prompt — forks the conversation here (later events are dropped or summarized)">✎ edit`),Zt=z(`<div class=msg-head><span class=author></span><span class=ts></span><span class=ts>`),Qt=z(`<div><div class=msg-body>`),$t=z(`<span style=width:38px>`),en=z(`<div class=interrupted>⚠ interrupted — partial output kept`),tn=z(`<div class=msgfoot><span>copy summary`),nn=z(`<details><summary><span class=meta></span></summary><div class=mono></div><div class=meta>ms`),rn=z(`<div class=meta>⚠ `),an=z(`<div class=meta>→ `),on=z(`<div class=embed style=border-color:var(--ok)><div>📈 `),sn=z(`<div class="embed fail"><div class=mono>⚠ `),cn=z(`<div class="content muted">`),ln=z(`<button class=copybtn title="copy to clipboard">`),un=z(`<div class=overlay><div class=modal><div class=modal-head><b></b><button class=iconbtn>✕`),dn=z(`<span style=color:var(--err);font-size:13px>`),fn=z(`<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`),pn=z(`<div class=direntry>📁 `),mn=z(`<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`),hn={prompt:{name:`you`,icon:`🟧`,color:`#faa81a`},user:{name:`you`,icon:`🟧`,color:`#faa81a`},message:{name:`agent`,icon:`🫖`,color:`#5865f2`},progress:{name:`progress`,icon:`📈`,color:`#3ba55d`}},gn={name:`harness`,icon:`📣`,color:`#3ba55d`},_n=e=>{if(e.type===`tool_call`||e.type===`tool_result`)return{name:String(e.data?.name??`tool`),icon:`⚙`,color:`#3ba0c9`};if(e.type===`prompt`){let t=String(e.data?.source??`user`);return t===`user`?hn.prompt:t.startsWith(`scheduler:`)?{name:t.slice(10),icon:`📣`,color:`#3ba55d`}:gn}return hn[e.type]??{name:e.type,icon:`•`,color:`#9298a5`}},vn=new Set([`user`,`message`,`prompt`,`tool_call`,`tool_result`,`progress`,`state`,`error`,`fork`,`goal`]),yn=e=>{let t=new Date(e);return`${String(t.getHours()).padStart(2,`0`)}:${String(t.getMinutes()).padStart(2,`0`)}`};async function Z(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 bn=location.hash.match(/[#&]token=([^&]+)/);bn&&(localStorage.setItem(`teapot.token`,decodeURIComponent(bn[1])),history.replaceState(null,``,location.pathname+location.search));var xn=()=>{let e=localStorage.getItem(`teapot.token`);return e?`?token=${encodeURIComponent(e)}`:``};function Sn(){let[e,t]=v([]),[n,r]=v(null),[i,a]=v([]),[o,s]=v([]),[c,l]=v(null),[u,d]=v(``),[f,p]=v(localStorage.getItem(`teapot.autostart`)!==`0`),m=e=>{p(e),localStorage.setItem(`teapot.autostart`,e?`1`:`0`)},[h,g]=v({providers:{}}),[_,S]=v(!1),[ee,T]=v(!1),[te,ne]=v(localStorage.getItem(`teapot.panel`)===null?window.innerWidth>1100:localStorage.getItem(`teapot.panel`)===`1`),re=()=>{let e=!te();ne(e),localStorage.setItem(`teapot.panel`,e?`1`:`0`)},[ie,E]=v(``),[ae,oe]=v(``),[D,O]=v([]),se=()=>Object.keys(h().providers??{});async function ce(e){if(e)try{let t=await Z(`/api/models?provider=${encodeURIComponent(e)}`);O(t.models??[])}catch{O([])}}b(()=>{let e=N();e&&(E(e.provider||h().defaultProvider||se()[0]||``),oe(``),ce(ie()))});let[le,ue]=v(!0),[k,A]=v(0),[j,de]=v(null),fe=x(()=>{let e=new Map,t=new Set,n=new Map;for(let r of i())if(vn.has(r.type)){if(r.type===`tool_call`){let e=n.get(r.data.callId)??[];e.push(r),n.set(r.data.callId,e)}else if(r.type===`tool_result`){let i=n.get(r.data.callId)?.shift();i&&(e.set(i.id,r),t.add(r.id))}}return{resFor:e,consumed:t}}),M=x(()=>{let{consumed:e}=fe();return i().filter(t=>vn.has(t.type)&&!(t.type===`tool_result`&&e.has(t.id)))}),pe=()=>Z(`/api/config`).then(g).catch(()=>{}),N=x(()=>e().find(e=>e.id===n())),[me,he]=v(null),R=()=>Z(`/api/agents`).then(e=>t(e.agents)).catch(()=>{}),ge=()=>Z(`/api/metrics`).then(l).catch(()=>{}),[_e,z]=v([]),ve=()=>Z(`/api/tasks`).then(e=>z(e.tasks)).catch(()=>{}),H=e=>_e().filter(t=>t.agent===e),[W,xe]=v(null);async function G(e){try{let t=W(),[n,r]=await Promise.all([Z(`/api/agents/${e}/events?limit=300${t?`&branch=${encodeURIComponent(t)}`:``}`),Z(`/api/agents/${e}/branches`)]);a(n.events),s(r.branches)}catch{}}function Se(){return document.querySelector(`.feed`)}function Ce(){let e=Se();return!e||e.scrollHeight-e.scrollTop-e.clientHeight<80}function K(e=!1){let t=Se();t&&(e||le())&&(t.scrollTop=t.scrollHeight,A(0))}async function q(e,t=!0){r(e),de(null),xe(null),localStorage.setItem(`teapot.session`,e),ke(e,t),Z(`/api/agents/${e}/load`,{method:`POST`}).then(R).catch(()=>{}),await G(e),requestAnimationFrame(()=>K(!0))}let[we,Te]=v(!1),J=null,Ee=null;w(()=>J?.close());function De(){let e=location.protocol===`https:`?`wss://`:`ws://`;J=new WebSocket(`${e}${location.host}/api/ws${xn()}`),J.onopen=()=>Te(!0),J.onclose=()=>{Te(!1),setTimeout(De,1500)},J.onerror=()=>J?.close();let t=new Set([`state`,`usage`,`session_start`]),r=null;J.onmessage=e=>{let a=JSON.parse(e.data);if(a.kind!==`ping`&&a.kind!==`pong`){if(a.kind===`llm-delta`){r={id:a.agentId,at:Date.now()},a.agentId===n()&&de({text:a.text??``,reasoning:a.reasoning??``});return}a.kind===`event`&&t.has(a.event?.type)||(Ee||=setTimeout(async()=>{if(Ee=null,await R(),await ge(),n()){let e=i().length,t=Date.now();await G(n()),i().length!==e&&(r?.id===n()&&r.at>=t||de(null),Ce()?K(!0):A(k()+(i().length-e)))}},400))}}}let Oe=()=>decodeURIComponent(location.pathname.split(`/`)[2]??``);function ke(e,t=!0){let n=`/session/${encodeURIComponent(e)}`;t?history.pushState(null,``,n):history.replaceState(null,``,n)}window.addEventListener(`popstate`,()=>{let t=Oe();t&&e().some(e=>e.id===t)&&t!==n()&&q(t,!1)}),b(()=>{let e=N();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(_()){S(!1);return}if(ee()){T(!1);return}let e=N();if(e?.status===`running`){Z(`/api/agents/${e.id}/stop`,{method:`POST`}).then(R);return}te()&&window.innerWidth<=1100&&ne(!1);return}if(!(_()||ee())){if(t.key===`/`)t.preventDefault(),document.querySelector(`.composer textarea`)?.focus();else if(t.key===`d`)re();else if(t.key===`t`)At();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&&q(r[a].id)}}});let[Ae,kt]=v(localStorage.getItem(`teapot.term`)===`1`),At=()=>{let e=!Ae();kt(e),localStorage.setItem(`teapot.term`,e?`1`:`0`)},Y=null,jt=null,X=null,Mt=null,Nt={cols:0,rows:0},Pt=null;function Ft(){Mt?.disconnect(),Mt=null,X?.close(),X=null,jt?.dispose(),jt=null}function It(e){Ft(),Y&&Promise.all([je(()=>import(`./xterm-C3BHN0de.js`),[]),je(()=>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(Y),i.fit(),jt=r;let a=location.protocol===`https:`?`wss://`:`ws://`,o=new WebSocket(`${a}${location.host}/api/agents/${e}/term${xn()}`);X=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!==Nt.cols||t!==Nt.rows)&&o.readyState===WebSocket.OPEN&&(Nt={cols:e,rows:t},o.send(JSON.stringify({kind:`resize`,cols:e,rows:t})))};Mt=new ResizeObserver(()=>{Pt&&clearTimeout(Pt),Pt=setTimeout(s,300)}),Mt.observe(Y),setTimeout(s,50)})}b(()=>{let e=n();!Ae()||!e?Ft():requestAnimationFrame(()=>e&&It(e))}),w(Ft),C(()=>{pe(),R().then(()=>{let t=Oe()||localStorage.getItem(`teapot.session`)||``,n=e().find(e=>e.id===t)??e()[0];n&&q(n.id,!1)}),ge(),ve(),De();let t=setInterval(()=>{ge(),ve()},3e4);w(()=>clearInterval(t))});let[Lt,Rt]=v(``),zt,Bt=e=>{Rt(e),clearTimeout(zt),zt=setTimeout(()=>Rt(``),3200)},Vt=[{cmd:`/start`,desc:`start working toward the goal`},{cmd:`/stop`,desc:`interrupt the running agent`},{cmd:`/fork`,desc:`branch the conversation here`},{cmd:`/goal`,desc:`/goal <text> — set goal & notify the agent`}],Ht=()=>{let e=u();return!e.startsWith(`/`)||e.includes(` `)||e.includes(`
7
+ `)?[]:Vt.filter(t=>t.cmd.slice(1).startsWith(e.slice(1).toLowerCase()))},Ut=async e=>{e.preventDefault();let t=n(),r=u().trim();if(!(!t||!r)){if(r.startsWith(`/`)){let e=r.indexOf(` `),n=(e===-1?r.slice(1):r.slice(1,e)).toLowerCase(),i=e===-1?``:r.slice(e+1).trim(),a=(e,n)=>Z(`/api/agents/${t}${e}`,{method:`POST`,headers:{"content-type":`application/json`},...n===void 0?{}:{body:JSON.stringify(n)}}).then(R);try{if(n===`start`)await a(`/start`);else if(n===`stop`)await a(`/stop`);else if(n===`fork`)await a(`/fork`,{}),await q(t);else if(n===`goal`){if(!i){Bt(`usage: /goal <text>`);return}await a(`/goal`,{text:i,notify:!0}),Bt(`goal saved & notification queued`)}else{Bt(`unknown command "${n}" — /start /stop /fork /goal`);return}d(``)}catch(e){Bt(`/${n} failed: ${e.message}`)}return}d(``);try{await Z(`/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)}}},Wt=e=>()=>n()&&Z(`/api/agents/${n()}${e}`,{method:`POST`}).then(R),Gt=async e=>{e.preventDefault();let t=document.getElementById(`goal-input`),r=document.getElementById(`goal-notify`)?.checked??!0;!n()||!t.value.trim()||(await Z(`/api/agents/${n()}/goal`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({text:t.value,notify:r})}),t.value=``,R())};return[(()=>{var i=st(),s=i.firstChild,l=s.firstChild,p=l.firstChild.nextSibling,g=p.nextSibling.firstChild,_=g.nextSibling,v=l.nextSibling,b=v.nextSibling,x=s.nextSibling,C=x.nextSibling;return g.$$click=()=>{pe(),S(!0)},_.$$click=()=>{pe(),T(!0)},U(v,P(F,{get each(){return e()},children:e=>(()=>{var t=ut(),r=t.firstChild,i=r.nextSibling;return t.$$click=()=>q(e.id),U(i,()=>e.id),U(t,P(I,{get when(){return H(e.id).length>0},get children(){var t=ct();return y(()=>B(t,`title`,H(e.id).map(e=>`${e.id}: ${e.schedule}`).join(`
8
+ `))),t}}),null),U(t,P(I,{get when(){return e.goal.status===`done`},get children(){return lt()}}),null),y(i=>{var a=`agent-item`+(e.id===n()?` sel`:``),o=`dot ${e.status}`;return a!==i.e&&V(t,i.e=a),o!==i.t&&V(r,i.t=o),i},{e:void 0,t:void 0}),t})()})),U(b,P(I,{get when(){return c()},get children(){return[`master rss `,L(()=>c().rssMb),`MB · heap `,L(()=>c().heapUsedMb),`MB`,Me(),`load1 `,L(()=>c().loadavg1),` · up `,L(()=>Math.floor(c().uptimeSec/60)),`m`]}})),U(x,P(I,{get when(){return N()},get fallback(){return dt()},get children(){return[(()=>{var e=Ie(),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 U(t,()=>N().id),U(n,()=>N().status),U(e,P(I,{get when(){return(N().pendingPrompts??0)>0},get children(){var e=Ne(),t=e.firstChild.nextSibling;return t.nextSibling,U(e,()=>N().pendingPrompts,t),y(()=>B(e,`title`,`${N().pendingPrompts} prompt(s) waiting — the agent picks them up at the next turn boundary`)),e}}),r),U(e,P(I,{get when(){return H(N().id).length>0},get children(){var e=Pe();return e.firstChild,U(e,()=>H(N().id).length,null),y(()=>B(e,`title`,`scheduled tasks:\n${H(N().id).map(e=>`${e.schedule} · ${e.id}${e.forked?` (forked)`:``}`).join(`
9
+ `)}`)),e}}),r),U(r,()=>N().model,i),U(r,()=>N().session,a),U(r,()=>N().branch,o),U(r,()=>N().stats.turns,s),U(r,()=>N().stats.toolCalls,null),U(c,P(I,{get when(){return N().statusReason},get children(){var e=Fe();return y(()=>B(e,`title`,N().statusReason)),e}}),l),l.$$click=At,u.$$click=re,y(()=>V(n,`badge ${N().status}`)),e})(),(()=>{var e=Be();return e.addEventListener(`scroll`,()=>{let e=Ce();e&&k()&&A(0),ue(e)}),U(e,P(I,{get when(){return M().length>0},get fallback(){return ft()},get children(){return[P(F,{get each(){return M()},children:(e,t)=>P(wn,{e,get prev(){return M()[t()-1]},get res(){return fe().resFor.get(e.id)},get onEdit(){return e.type===`prompt`&&e.data?.source===`user`?()=>he({eventId:e.id,text:String(e.data?.text??``)}):void 0}})}),P(I,{get when(){return j()},get children(){var e=ze(),t=e.firstChild.nextSibling;return t.firstChild,U(t,P(I,{get when(){return j().reasoning},get children(){var e=Le(),t=e.firstChild.nextSibling;return U(t,()=>j().reasoning),e}}),null),U(t,P(I,{get when(){return j().text},get fallback(){return pt()},get children(){var e=Re(),t=e.firstChild;return U(e,()=>j().text,t),e}}),null),e}})]}})),e})(),P(I,{get when(){return!le()||k()>0},get children(){var e=Ve();return e.firstChild,e.$$click=()=>K(!0),U(e,(()=>{var e=L(()=>k()>0);return()=>e()?`${k()} new message${k()>1?`s`:``}`:`jump to present`})(),null),e}}),P(I,{get when(){return L(()=>!!Ae())()&&N()},get children(){var e=He(),t=e.firstChild,n=t.firstChild,r=n.firstChild.nextSibling,i=n.nextSibling,a=t.nextSibling;return U(r,()=>N().workspace),i.$$click=At,be(e=>Y=e,a),e}}),(()=>{var e=We(),t=e.firstChild,n=t.firstChild,r=n.nextSibling.firstChild,i=t.nextSibling;return U(e,P(I,{get when(){return Ht().length>0},get children(){var e=Ue();return U(e,P(F,{get each(){return Ht()},children:e=>(()=>{var t=mt(),n=t.firstChild,r=n.nextSibling;return t.$$click=()=>d(e.cmd+` `),U(n,()=>e.cmd),U(r,()=>e.desc),y(()=>B(t,`title`,e.desc)),t})()})),e}}),t),t.addEventListener(`submit`,Ut),n.$$keydown=e=>{e.key===`Enter`&&!e.shiftKey&&(e.preventDefault(),Ut(e))},n.$$input=e=>d(e.currentTarget.value),r.addEventListener(`change`,e=>m(e.currentTarget.checked)),U(i,()=>Lt()||`enter send · shift+enter newline · ↑↓ sessions · / commands & focus · t terminal · d panel · esc interrupt · messages sent while the agent works queue up and land at the next turn boundary`),y(()=>B(n,`placeholder`,`message #${N().id} — / for commands`)),y(()=>n.value=u()),y(()=>r.checked=f()),e})()]}})),U(C,P(I,{get when(){return N()},get children(){return[Ge(),(()=>{var e=Ke(),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 U(n,()=>N().id),U(r,()=>N().status),U(a,()=>N().workspace),U(o,()=>N().session,s),U(o,()=>N().branch,null),y(e=>{var t=`badge ${N().status}`,n=N().workspace;return t!==e.e&&V(r,e.e=t),n!==e.t&&B(a,`title`,e.t=n),e},{e:void 0,t:void 0}),e})(),qe(),(()=>{var e=Je(),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=>{E(e.currentTarget.value),ce(e.currentTarget.value)}),U(t,P(F,{get each(){return se()},children:e=>(()=>{var t=ht();return t.value=e,U(t,e,null),U(t,()=>e===h().defaultProvider?` ★`:``,null),t})()})),i.$$input=e=>oe(e.currentTarget.value),U(a,P(F,{get each(){return D()},children:e=>(()=>{var t=ht();return t.value=e,t})()})),o.$$click=async e=>{if(!n())return;let t=e.currentTarget;t.disabled=!0;try{await Z(`/api/agents/${n()}/model`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({provider:ie(),model:ae().trim()||void 0})}),t.textContent=`✓ applied`,R()}catch(e){alert(`model switch failed: ${e.message}`)}finally{setTimeout(()=>{t.textContent=`apply`,t.disabled=!1},1200)}},U(s,()=>N().model,null),U(s,P(I,{get when(){return D().length},get children(){return[` · `,L(()=>D().length),` models loaded`]}}),null),y(()=>B(i,`placeholder`,N().model)),y(()=>t.value=ie()),y(()=>i.value=ae()),e})(),Ye(),(()=>{var i=Ze(),o=i.firstChild,s=o.nextSibling;return U(i,P(I,{get when(){return N().status===`running`},get fallback(){return(()=>{var e=gt();return ye(e,`click`,Wt(`/start`),!0),e})()},get children(){var e=Xe();return ye(e,`click`,Wt(`/stop`),!0),e}}),o),o.$$click=()=>Z(`/api/agents/${N().id}/fork`,{method:`POST`,headers:{"content-type":`application/json`},body:`{}`}).then(()=>q(N().id)),s.$$click=async()=>{let i=n();if(!i||!confirm(`remove agent ${i}? (log is kept)`))return;await Z(`/api/agents/${i}`,{method:`DELETE`}).catch(()=>{});let o=e().filter(e=>e.id!==i);t(o),o[0]?q(o[0].id):(r(null),a([]))},i})(),(()=>{var e=Qe(),t=e.firstChild.nextSibling;return U(t,()=>N().goal.status),y(()=>V(t,`badge ${N().goal.status===`done`?`done`:``}`)),e})(),(()=>{var e=$e();return e.addEventListener(`submit`,Gt),e})(),(()=>{var e=et();return U(e,()=>N().goal.text||`no goal set — the agent has nothing to auto-continue toward`),e})(),(()=>{var e=tt();return e.firstChild,U(e,P(I,{get when(){return L(()=>!!N().goal.text)()&&N().goal.status===`active`},children:` auto-continue keeps it working until this is done`}),null),U(e,P(I,{get when(){return!N().goal.text},children:` set one and tick ▶ start to begin`}),null),e})(),nt(),P(I,{get when(){return N().latestProgress},get fallback(){return _t()},children:e=>(()=>{var t=St(),n=t.firstChild,r=n.firstChild.nextSibling,i=n.nextSibling;return U(r,()=>e().doing),U(t,P(I,{get when(){return e().recent},get children(){var t=vt(),n=t.firstChild.nextSibling;return U(n,()=>e().recent),t}}),i),U(t,P(I,{get when(){return e().problems},get children(){var t=yt(),n=t.firstChild.nextSibling;return U(n,()=>e().problems),t}}),i),U(t,P(I,{get when(){return e().next},get children(){var t=bt(),n=t.firstChild.nextSibling;return U(n,()=>e().next),t}}),i),U(t,P(I,{get when(){return e().goalStatus},get children(){var t=xt(),n=t.firstChild.nextSibling;return U(n,()=>e().goalStatus),t}}),i),U(i,()=>En(e().ts)),t})()}),rt(),(()=>{var e=it(),t=e.firstChild.nextSibling,n=t.nextSibling.nextSibling,r=n.nextSibling.nextSibling,i=r.nextSibling.nextSibling;return i.nextSibling,U(e,()=>N().stats.turns,t),U(e,()=>N().stats.toolCalls,n),U(e,()=>N().stats.compactions??0,r),U(e,()=>N().stats.inputTokens,i),U(e,()=>N().stats.outputTokens,null),U(e,P(I,{get when(){return N().ctx},children:e=>[`
10
+ `,`context ~`,L(()=>Dn(e().usedTokens)),` tok`,P(I,{get when(){return e().window},get children(){return[` · `,L(()=>Math.min(999,Math.round(e().usedTokens/e().window*100))),`% of `,L(()=>Dn(e().window))]}}),`
11
+ `,`compaction at ~`,L(()=>Dn(e().compactAt)),` tok (older turns summarized)`]}),null),e})(),at(),P(F,{get each(){return o()},children:e=>(()=>{var t=Ct(),r=t.firstChild,i=r.nextSibling,a=i.firstChild;return t.$$click=()=>{let t=W()===e.branch?null:e.branch;xe(t),n()&&G(n())},U(r,()=>e.branch,null),U(r,()=>e.branch===N().branch?` (current)`:``,null),U(i,()=>e.events,a),y(n=>{var r=`branch-row`+(e.branch===N().branch||e.branch===W()?` cur`:``),i=e.branch===W()?`click to show all branches again`:`show only ${e.branch}`;return r!==n.e&&V(t,n.e=r),i!==n.t&&B(t,`title`,n.t=i),n},{e:void 0,t:void 0}),t})()}),ot(),P(I,{get when(){return _e().length>0},get fallback(){return wt()},get children(){return P(F,{get each(){return _e()},children:e=>(()=>{var t=Et(),r=t.firstChild,i=r.firstChild,a=i.nextSibling;a.firstChild;var o=r.nextSibling,s=o.firstChild,c=o.nextSibling;return t.$$click=()=>q(e.agent),U(i,()=>e.id),U(a,()=>e.agent,null),U(r,P(I,{get when(){return e.forked},get children(){return Tt()}}),null),U(o,()=>e.schedule,s),U(o,(()=>{var t=L(()=>!!e.next);return()=>t()?En(e.next):`—`})(),null),U(o,(()=>{var t=L(()=>!!e.last);return()=>t()?` · last ${En(e.last)}`:` · never ran`})(),null),U(c,()=>$(e.prompt,90)),y(r=>{var i=`sched-row`+(e.agent===n()?` cur`:``),a=`${$(e.prompt,200)}\nclick to open #${e.agent}`;return i!==r.e&&V(t,r.e=i),a!==r.t&&B(t,`title`,r.t=a),r},{e:void 0,t:void 0}),t})()})}})]}})),y(e=>{var t=`layout`+(te()?``:` right-hidden`),n=`conn`+(we()?` ok`:``),r=we()?`live (websocket)`:`reconnecting…`,a=`rightbar`+(te()?` open`:``);return t!==e.e&&V(i,e.e=t),n!==e.t&&V(p,e.t=n),r!==e.a&&B(p,`title`,e.a=r),a!==e.o&&V(C,e.o=a),e},{e:void 0,t:void 0,a:void 0,o:void 0}),i})(),P(I,{get when(){return _()},get children(){return P(An,{get providers(){return Object.keys(h().providers??{})},onClose:()=>S(!1),onCreated:e=>{S(!1),R(),q(e)}})}}),P(I,{get when(){return ee()},get children(){return P(jn,{get cfg(){return h()},onClose:()=>T(!1),onSaved:()=>{pe(),ve()}})}}),P(I,{get when(){return me()},fallback:null,children:e=>{let t=()=>i().findIndex(t=>t.id===e().eventId),r=()=>Math.max(0,i().length-t()-1),[a,o]=v(r()>0?`summarize`:`discard`);return P(kn,{title:`edit prompt — forks the conversation`,onClose:()=>he(null),get children(){var t=Ot(),i=t.firstChild,s=i.nextSibling,c=s.firstChild;return t.addEventListener(`submit`,async t=>{t.preventDefault();let r=document.getElementById(`edit-text`);try{await Z(`/api/agents/${n()}/edit-prompt`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({eventId:e().eventId,text:r.value,tail:a()})}),he(null),R(),n()&&await q(n())}catch(e){alert(`edit failed: ${e.message}`)}}),U(t,P(I,{get when(){return r()>0},get children(){var e=Dt(),t=e.firstChild,n=t.firstChild,i=t.nextSibling,s=i.firstChild,c=i.nextSibling.firstChild;return U(t,r,n),s.addEventListener(`change`,()=>o(`summarize`)),c.addEventListener(`change`,()=>o(`discard`)),y(()=>s.checked=a()===`summarize`),y(()=>c.checked=a()===`discard`),e}}),s),c.$$click=()=>he(null),y(()=>i.value=e().text),t}})}})]}function Cn(e){let t=e.e,n=e.res,r=t.data??{},i=String(r.name??`tool`),a=()=>n?String(n.data?.result??``):``,o=i,s=``,c=(()=>{var e=kt();return U(e,()=>Q(JSON.stringify(r.args??{},null,1),2e3)),e})(),l=e=>String(r.args?.[e]??``),u=(e,t=1500)=>(()=>{var n=At();return U(n,()=>Q(e,t)),n})(),d=(e=4e3)=>n?[L(()=>u(a(),e)),(()=>{var e=Y(),t=e.firstChild;return U(e,()=>n.data?.durationMs,t),U(e,()=>n.data?.ok===!1?` · FAILED`:``,null),U(e,P(On,{get text(){return a()}}),null),e})()]:jt();try{switch(i){case`bash`:{let e=l(`command`);o=`$ `+$(e,96),s=l(`timeout_ms`)?`timeout ${Math.round(Number(l(`timeout_ms`))/1e3)}s`:``,c=[L(()=>L(()=>e!==o.slice(2))()?u(e,800):null),L(()=>d(6e3))];break}case`read_file`:{o=l(`path`)||`(no path)`;let e=[];l(`pattern`)&&e.push(`grep /${$(l(`pattern`),40)}/`),Number(r.args?.offset)<0?e.push(`last ${-Number(r.args.offset)} lines`):r.args?.offset&&e.push(`from L${r.args.offset}`),r.args?.limit&&e.push(`≤${r.args.limit} lines`),s=e.join(` · `),c=d(6e3);break}case`write_file`:{let e=String(r.args?.content??``);o=l(`path`)||`(no path)`,s=`${e.length} bytes`,c=[L(()=>u(e)),n?(()=>{var e=X();return U(e,()=>$(a(),160)),e})():Mt()];break}case`edit_file`:o=l(`path`)||`(no path)`,s=r.args?.replace_all===!0?`replace all`:`unique spot`,c=[(()=>{var e=Nt();return U(e,()=>Q(`- `+l(`old_text`),900)),e})(),(()=>{var e=Pt();return U(e,()=>`+ `+Q(l(`new_text`),900)),e})(),n?(()=>{var e=Ft(),t=e.firstChild,r=t.nextSibling;return r.nextSibling,U(e,()=>$(a(),120),t),U(e,()=>n.data?.durationMs,r),e})():It()];break;case`apply_patch`:{let e=l(`patch`).split(`
12
+ `).filter(e=>e&&!/^---$/.test(e.trim())),t=e.map(e=>e.match(/^\*\*\* (?:Add|Update|Delete) File: (.+)$/)?.[1]).filter(Boolean);o=t.length?`${t.length} file${t.length>1?`s`:``}: ${$(t.join(`, `),80)}`:`patch`,c=[(()=>{var t=Lt();return U(t,()=>e.map(e=>{let t=e.startsWith(`+`)?` add`:e.startsWith(`-`)?` del`:/^\*\*\*|^@@/.test(e)?` meta`:``;return(()=>{var n=Rt();return V(n,`pline`+t),U(n,(()=>{var t=L(()=>e.length>240);return()=>t()?e.slice(0,240)+`…`:e})()),n})()})),t})(),n?(()=>{var e=X();return U(e,()=>$(a().split(`
13
+ `)[0]??``,140),null),U(e,()=>n.data?.ok===!1?` · FAILED`:``,null),e})():zt()];break}case`list_dir`:o=l(`path`)||`.`,c=d(4e3);break;case`read_url`:{let e=l(`url`);try{let t=new URL(e);e=t.host+t.pathname}catch{}o=$(e,70),s=`web`,c=[(()=>{var e=Bt(),t=e.firstChild;return y(()=>B(t,`href`,l(`url`))),e})(),L(()=>d(3e3))];break}case`load_skill`:{o=`skill: ${l(`name`)}`;let e=a().replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/,``);c=n?[(()=>{var t=Vt();return y(()=>t.innerHTML=we(e)),t})(),(()=>{var e=Y(),t=e.firstChild;return U(e,()=>n.data?.durationMs,t),e})()]:Ht();break}case`save_skill`:{o=`skill: ${l(`name`)}`,s=$(l(`description`),60);let e=Array.isArray(r.args?.files)?r.args.files.map(e=>e?.name).filter(Boolean):[];c=[L(()=>L(()=>!!e.length)()?(()=>{var t=Ut();return t.firstChild,U(t,()=>e.join(`, `),null),t})():null),n?(()=>{var e=Ft(),t=e.firstChild,r=t.nextSibling;return r.nextSibling,U(e,()=>$(a(),160),t),U(e,()=>n.data?.durationMs,r),e})():Wt()];break}}}catch{}return(()=>{var e=Gt(),t=e.firstChild.firstChild;t.firstChild;var r=t.nextSibling;return B(e,`title`,`${i}${s?` — `+s:``}`),U(t,o,null),U(r,n?s||``:`running…`),U(e,c,null),y(()=>V(e,`embed`+(n?n.data?.ok===!1?` fail`:` done`:` running`))),e})()}function wn(e){let t=e.e,n=_n(t),r=e.prev&&e.prev.type===t.type&&_n(e.prev).name===n.name&&t.session===e.prev.session&&t.branch===e.prev.branch;if(t.type===`fork`){let e=t.data??{};return(()=>{var n=Kt(),r=n.firstChild.nextSibling;return r.nextSibling,U(n,()=>String(e.fromBranch??`?`),r),U(n,()=>String(e.newBranch??t.branch),null),n})()}if(t.type===`goal`){let e=t.data??{},n=e.event===`status`?`marked ${String(e.status??``)}`:$(String(e.text??``),80);return(()=>{var t=qt(),r=t.firstChild.nextSibling;return r.nextSibling,U(t,()=>String(e.event??``),r),U(t,n,null),t})()}return t.type===`state`?t.data.from===t.data.to?null:(()=>{var e=Jt(),n=e.firstChild;return U(e,()=>t.data.from,n),U(e,()=>t.data.to,null),U(e,(()=>{var e=L(()=>!!t.data.reason);return()=>e()?` — ${t.data.reason}`:``})(),null),y(()=>V(e,`divider-msg`+(t.data.to===`error`?` err`:``))),e})():(()=>{var i=Qt(),a=i.firstChild;return V(i,`msg`+(r?` grouped`:``)),U(i,P(I,{when:!r,get fallback(){return $t()},get children(){var e=Yt();return U(e,()=>n.icon),y(t=>{var r=n.color+`33`,i=`1px solid ${n.color}66`;return r!==t.e&&H(e,`background`,t.e=r),i!==t.t&&H(e,`border`,t.t=i),t},{e:void 0,t:void 0}),e}}),a),U(a,P(I,{when:!r,get children(){var r=Zt(),i=r.firstChild,a=i.nextSibling,o=a.nextSibling;return U(i,()=>n.name),U(a,()=>yn(t.ts)),U(o,()=>t.branch),U(r,P(I,{get when(){return e.onEdit},get children(){var t=Xt();return t.$$click=t=>{t.stopPropagation(),e.onEdit()},t}}),null),y(e=>H(i,`color`,n.color)),r}}),null),U(a,P(Tn,{e:t,get res(){return e.res}}),null),i})()}function Tn(e){let t=e.e;switch(t.type){case`prompt`:return(()=>{var e=Vt();return y(()=>e.innerHTML=we(String(t.data.text??``))),e})();case`message`:return[P(I,{get when(){return L(()=>typeof t.data.reasoning==`string`)()&&t.data.reasoning.trim()},get children(){var e=Le(),n=e.firstChild.nextSibling;return U(n,()=>String(t.data.reasoning)),e}}),(()=>{var e=Vt();return y(()=>e.innerHTML=we(String(t.data.content??``))),e})(),P(I,{get when(){return t.data.interrupted},get children(){return en()}}),P(I,{get when(){return t.data.final},get children(){var e=tn(),n=e.firstChild;return U(e,P(On,{get text(){return String(t.data.content??``)}}),n),e}})];case`tool_call`:return P(Cn,{e:t,get res(){return e.res}});case`tool_result`:{let e=String(t.data.result);return(()=>{var n=nn(),r=n.firstChild,i=r.firstChild,a=r.nextSibling,o=a.nextSibling,s=o.firstChild;return U(i,()=>$(e,120)),U(r,P(On,{text:e}),null),U(a,()=>Q(e,4e3)),U(o,()=>t.data.durationMs,s),U(o,()=>t.data.ok?``:` · FAILED`,null),y(()=>V(n,`embed`+(t.data.ok?``:` fail`))),n})()}case`progress`:return(()=>{var e=on(),n=e.firstChild;return n.firstChild,U(n,()=>String(t.data.doing??``),null),U(e,P(I,{get when(){return t.data.recent},get children(){var e=X();return U(e,()=>String(t.data.recent)),e}}),null),U(e,P(I,{get when(){return t.data.problems},get children(){var e=rn();return e.firstChild,U(e,()=>String(t.data.problems),null),e}}),null),U(e,P(I,{get when(){return t.data.next},get children(){var e=an();return e.firstChild,U(e,()=>String(t.data.next),null),e}}),null),e})();case`error`:return(()=>{var e=sn(),n=e.firstChild;return n.firstChild,U(n,()=>String(t.data.message??``),null),e})();default:return(()=>{var e=cn();return U(e,()=>Q(JSON.stringify(t.data),200)),e})()}}function Q(e,t){return e.length>t?e.slice(0,t)+` …`:e}function En(e){let t=new Date(e).getTime()-Date.now(),n=Math.abs(t),r=n<9e4?`${Math.round(n/1e3)}s`:n<54e5?`${Math.round(n/6e4)}m`:`${(n/36e5).toFixed(1)}h`;return t>=0?`in ${r}`:`${r} ago`}function Dn(e){return e>=1e4?`${Math.round(e/1e3)}k`:e>=1e3?`${(e/1e3).toFixed(1)}k`:String(e)}function $(e,t){return Q(e.replace(/\s+/g,` `).trim(),t)}function On(e){let[t,n]=v(!1);return(()=>{var r=ln();return r.$$click=t=>{t.stopPropagation(),navigator.clipboard.writeText(e.text).then(()=>{n(!0),setTimeout(()=>n(!1),900)})},U(r,()=>t()?`✓`:`⧉`),r})()}function kn(e){return(()=>{var t=un(),n=t.firstChild,r=n.firstChild.firstChild,i=r.nextSibling;return t.$$click=t=>t.target===t.currentTarget&&e.onClose(),U(r,()=>e.title),ye(i,`click`,e.onClose,!0),U(n,()=>e.children,null),t})()}function An(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 Z(`/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 Z(`/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 P(kn,{title:`new agent`,get onClose(){return e.onClose},get children(){var i=fn(),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,ee=C.nextSibling.firstChild.nextSibling,T=b.nextSibling;return i.addEventListener(`submit`,m),h.$$input=e=>n(e.currentTarget.value),g.$$click=()=>p(t()),_.$$click=()=>p(`..`),U(v,P(F,{get each(){return r()},children:e=>(()=>{var n=pn();return n.firstChild,n.$$click=()=>p(`${t()}/${e}`.replace(/\/+/g,`/`)),U(n,e,null),n})()})),S.$$input=e=>o(e.currentTarget.value),w.addEventListener(`change`,e=>c(e.currentTarget.value)),U(w,P(F,{get each(){return e.providers},children:e=>(()=>{var t=ht();return U(t,e),t})()})),ee.$$input=e=>u(e.currentTarget.value),U(i,P(I,{get when(){return d()},get children(){var e=dn();return U(e,d),e}}),T),y(()=>h.value=t()),y(()=>S.value=a()),y(()=>w.value=s()),y(()=>ee.value=l()),i}})}function jn(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 Z(`/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 P(kn,{title:`settings`,get onClose(){return e.onClose},get children(){var u=mn(),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),U(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),U(u,P(I,{get when(){return l()},get children(){var e=dn();return U(e,l),e}}),S),y(()=>m.value=t()),y(()=>_.value=r()),y(()=>v.value=a()),y(()=>x.value=s()),u}})}ve([`click`,`input`,`keydown`]),_e(()=>P(Sn,{}),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-DxB6uahH.js"></script>
8
- <link rel="stylesheet" crossorigin href="/assets/index-BE9Nw_-t.css">
7
+ <script type="module" crossorigin src="/assets/index-CqCUyqTK.js"></script>
8
+ <link rel="stylesheet" crossorigin href="/assets/index-CIc04lSi.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)}.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}
@@ -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[ne.bind(n),e=>(typeof e==`function`&&(e=f&&f.running&&f.sources.has(n)?e(n.tValue):e(n.value)),re(n,e))]}function y(e,t,n){D(O(e,t,!1,c))}function b(e,t,n){s=se;let r=O(e,t,!1,c),i=te&&ee(te);i&&(r.suspense=i),(!n||!n.render)&&(r.user=!0),h?h.push(r):D(r)}function x(e,t,n){n=n?Object.assign({},a,n):a;let r=O(e,t,!0,0);return r.observers=null,r.observerSlots=null,r.comparator=n.equals||void 0,D(r),ne.bind(r)}function S(e){if(p===null)return e();let t=p;p=null;try{return e()}finally{p=t}}function C(e){b(()=>S(e))}function w(e){return d===null||(d.cleanups===null?d.cleanups=[e]:d.cleanups.push(e)),e}var[T,E]=v(!1);function ee(e){let t;return d&&d.context&&(t=d.context[e.id])!==void 0?t:e.defaultValue}var te;function ne(){let e=f&&f.running;if(this.sources&&(e?this.tState:this.state)){if((e?this.tState:this.state)===c)D(this);else{let e=m;m=null,A(()=>j(this),!1),m=e}}if(p){let e=this.observers;if(!e||e[e.length-1]!==p){let t=e?e.length:0;p.sources?(p.sources.push(this),p.sourceSlots.push(t)):(p.sources=[this],p.sourceSlots=[t]),e?(e.push(p),this.observerSlots.push(p.sources.length-1)):(this.observers=[p],this.observerSlots=[p.sources.length-1])}}return e&&f.sources.has(this)?this.tValue:this.value}function re(e,t,n){let r=f&&f.running&&f.sources.has(e)?e.tValue:e.value;if(!e.comparator||!e.comparator(r,t)){if(f){let r=f.running;(r||!n&&f.sources.has(e))&&(f.sources.add(e),e.tValue=t),r||(e.value=t)}else e.value=t;e.observers&&e.observers.length&&A(()=>{for(let t=0;t<e.observers.length;t+=1){let n=e.observers[t],r=f&&f.running;r&&f.disposed.has(n)||((r?!n.tState:!n.state)&&(n.pure?m.push(n):h.push(n),n.observers&&M(n)),r?n.tState=c:n.state=c)}if(m.length>1e6)throw m=[],Error()},!1)}return t}function D(e){if(!e.fn)return;N(e);let t=g;ie(e,f&&f.running&&f.sources.has(e)?e.tValue:e.value,t),f&&!f.running&&f.sources.has(e)&&queueMicrotask(()=>{A(()=>{f&&(f.running=!0),p=d=e,ie(e,e.tValue,t),p=d=null},!1)})}function ie(e,t,n){let r,i=d,a=p;p=d=e;try{r=e.fn(t)}catch(t){return e.pure&&(f&&f.running?(e.tState=c,e.tOwned&&e.tOwned.forEach(N),e.tOwned=void 0):(e.state=c,e.owned&&e.owned.forEach(N),e.owned=null)),e.updatedAt=n+1,I(t)}finally{p=a,d=i}(!e.updatedAt||e.updatedAt<=n)&&(e.updatedAt!=null&&`observers`in e?re(e,r,!0):f&&f.running&&e.pure?(f.sources.has(e)||(e.value=r),f.sources.add(e),e.tValue=r):e.value=r,e.updatedAt=n)}function O(e,t,n,r=c,i){let a={fn:e,state:r,updatedAt:null,owned:null,sources:null,sourceSlots:null,cleanups:null,value:t,owner:d,context:d?d.context:null,pure:n};return f&&f.running&&(a.state=0,a.tState=r),d===null||d!==u&&(f&&f.running&&d.pure?d.tOwned?d.tOwned.push(a):d.tOwned=[a]:d.owned?d.owned.push(a):d.owned=[a]),a}function k(e){let t=f&&f.running;if((t?e.tState:e.state)===0)return;if((t?e.tState:e.state)===l)return j(e);if(e.suspense&&S(e.suspense.inFallback))return e.suspense.effects.push(e);let n=[e];for(;(e=e.owner)&&(!e.updatedAt||e.updatedAt<g);){if(t&&f.disposed.has(e))return;(t?e.tState:e.state)&&n.push(e)}for(let r=n.length-1;r>=0;r--){if(e=n[r],t){let t=e,i=n[r+1];for(;(t=t.owner)&&t!==i;)if(f.disposed.has(t))return}if((t?e.tState:e.state)===c)D(e);else if((t?e.tState:e.state)===l){let t=m;m=null,A(()=>j(e,n[0]),!1),m=t}}}function A(e,t){if(m)return e();let n=!1;t||(m=[]),h?n=!0:h=[],g++;try{let t=e();return ae(n),t}catch(e){n||(h=null),m=null,I(e)}}function ae(e){if(m&&=(oe(m),null),e)return;let t;if(f){if(!f.promises.size&&!f.queue.size){let e=f.sources,n=f.disposed;h.push.apply(h,f.effects),t=f.resolve;for(let e of h)`tState`in e&&(e.state=e.tState),delete e.tState;f=null,A(()=>{for(let e of n)N(e);for(let t of e){if(t.value=t.tValue,t.owned)for(let e=0,n=t.owned.length;e<n;e++)N(t.owned[e]);t.tOwned&&(t.owned=t.tOwned),delete t.tValue,delete t.tOwned,t.tState=0}E(!1)},!1)}else if(f.running){f.running=!1,f.effects.push.apply(f.effects,h),h=null,E(!0);return}}let n=h;h=null,n.length&&A(()=>s(n),!1),t&&t()}function oe(e){for(let t=0;t<e.length;t++)k(e[t])}function se(t){let r,i=0;for(r=0;r<t.length;r++){let e=t[r];e.user?t[i++]=e:k(e)}if(e.context){if(e.count){e.effects||=[],e.effects.push(...t.slice(0,i));return}n()}for(e.effects&&(e.done||!e.count)&&(t=[...e.effects,...t],i+=e.effects.length,delete e.effects),r=0;r<i;r++)k(t[r])}function j(e,t){let n=f&&f.running;n?e.tState=0:e.state=0;for(let r=0;r<e.sources.length;r+=1){let i=e.sources[r];if(i.sources){let e=n?i.tState:i.state;e===c?i!==t&&(!i.updatedAt||i.updatedAt<g)&&k(i):e===l&&j(i,t)}}}function M(e){let t=f&&f.running;for(let n=0;n<e.observers.length;n+=1){let r=e.observers[n];(t?!r.tState:!r.state)&&(t?r.tState=l:r.state=l,r.pure?m.push(r):h.push(r),r.observers&&M(r))}}function N(e){let t;if(e.sources)for(;e.sources.length;){let t=e.sources.pop(),n=e.sourceSlots.pop(),r=t.observers;if(r&&r.length){let e=r.pop(),i=t.observerSlots.pop();n<r.length&&(e.sourceSlots[i]=n,r[n]=e,t.observerSlots[n]=i)}}if(e.tOwned){for(t=e.tOwned.length-1;t>=0;t--)N(e.tOwned[t]);delete e.tOwned}if(f&&f.running&&e.pure)P(e,!0);else if(e.owned){for(t=e.owned.length-1;t>=0;t--)N(e.owned[t]);e.owned=null}if(e.cleanups){for(t=e.cleanups.length-1;t>=0;t--)e.cleanups[t]();e.cleanups=null}f&&f.running?e.tState=0:e.state=0}function P(e,t){if(t||(e.tState=0,f.disposed.add(e)),e.owned)for(let t=0;t<e.owned.length;t++)P(e.owned[t])}function ce(e){return e instanceof Error?e:Error(typeof e==`string`?e:`Unknown error`,{cause:e})}function F(e,t,n){try{for(let n of t)n(e)}catch(e){I(e,n&&n.owner||null)}}function I(e,t=d){let n=o&&t&&t.context&&t.context[o],r=ce(e);if(!n)throw r;h?h.push({fn(){F(r,n,t)},state:c}):F(r,n,t)}var L=Symbol(`fallback`);function R(e){for(let t=0;t<e.length;t++)e[t]()}function z(e,t,n={}){let r=[],a=[],o=[],s=0,c=t.length>1?[]:null;return w(()=>R(o)),()=>{let l=e()||[],u=l.length,d,f;return l[i],S(()=>{let e,t,i,m,h,g,v,y,b;if(u===0)s!==0&&(R(o),o=[],r=[],a=[],s=0,c&&=[]),n.fallback&&(r=[L],a[0]=_(e=>(o[0]=e,n.fallback())),s=1);else if(s===0){for(a=Array(u),f=0;f<u;f++)r[f]=l[f],a[f]=_(p);s=u}else{for(i=Array(u),m=Array(u),c&&(h=Array(u)),g=0,v=Math.min(s,u);g<v&&r[g]===l[g];g++);for(v=s-1,y=u-1;v>=g&&y>=g&&r[v]===l[y];v--,y--)i[y]=a[v],m[y]=o[v],c&&(h[y]=c[v]);for(e=new Map,t=Array(y+1),f=y;f>=g;f--)b=l[f],d=e.get(b),t[f]=d===void 0?-1:d,e.set(b,f);for(d=g;d<=v;d++)b=r[d],f=e.get(b),f!==void 0&&f!==-1?(i[f]=a[d],m[f]=o[d],c&&(h[f]=c[d]),f=t[f],e.set(b,f)):o[d]();for(f=g;f<u;f++)f in i?(a[f]=i[f],o[f]=m[f],c&&(c[f]=h[f],c[f](f))):a[f]=_(p);a=a.slice(0,s=u),r=l.slice(0)}return a});function p(e){if(o[f]=e,c){let[e,n]=v(f);return c[f]=n,t(l[f],e)}return t(l[f])}}}function B(e,t){return S(()=>e(t||{}))}var le=e=>`Stale read from <${e}>.`;function V(e){let t=`fallback`in e&&{fallback:()=>e.fallback};return x(z(()=>e.each,e.children,t||void 0))}function H(e){let t=e.keyed,n=x(()=>e.when,void 0,void 0),r=t?n:x(n,void 0,{equals:(e,t)=>!e==!t});return x(()=>{let i=r();if(i){let a=e.children;return typeof a==`function`&&a.length>0?S(()=>a(t?i:()=>{if(!S(r))throw le(`Show`);return n()})):a}return e.fallback},void 0,void 0)}var U=e=>x(()=>e());function ue(e,t,n){let r=n.length,i=t.length,a=r,o=0,s=0,c=t[i-1].nextSibling,l=null;for(;o<i||s<a;){if(t[o]===n[s]){o++,s++;continue}for(;t[i-1]===n[a-1];)i--,a--;if(i===o){let t=a<r?s?n[s-1].nextSibling:n[a-s]:c;for(;s<a;)e.insertBefore(n[s++],t)}else if(a===s)for(;o<i;)(!l||!l.has(t[o]))&&t[o].remove(),o++;else if(t[o]===n[a-1]&&n[s]===t[i-1]){let r=t[--i].nextSibling;e.insertBefore(n[s++],t[o++].nextSibling),e.insertBefore(n[--a],r),t[i]=n[a]}else{if(!l){l=new Map;let e=s;for(;e<a;)l.set(n[e],e++)}let r=l.get(t[o]);if(r!=null){if(s<r&&r<a){let c=o,u=1,d;for(;++c<i&&c<a&&(d=l.get(t[c]))!=null&&d===r+u;)u++;if(u>r-s){let i=t[o];for(;s<r;)e.insertBefore(n[s++],i)}else e.replaceChild(n[s++],t[o++])}else o++}else t[o++].remove()}}}var de=`_$DX_DELEGATE`;function fe(e,t,n,r={}){let i;return _(r=>{i=r,t===document?e():Y(t,e(),t.firstChild?null:void 0,n)},r.owner),()=>{i(),t.textContent=``}}function W(e,t,n,r){let i,a=()=>{let t=r?document.createElementNS(`http://www.w3.org/1998/Math/MathML`,`template`):document.createElement(`template`);return t.innerHTML=e,n?t.content.firstChild.firstChild:r?t.firstChild:t.content.firstChild},o=t?()=>S(()=>document.importNode(i||=a(),!0)):()=>(i||=a()).cloneNode(!0);return o.cloneNode=o,o}function G(e,t=window.document){let n=t[de]||(t[de]=new Set);for(let r=0,i=e.length;r<i;r++){let i=e[r];n.has(i)||(n.add(i),t.addEventListener(i,X))}}function K(e,t,n){he(e)||(n==null?e.removeAttribute(t):e.setAttribute(t,n))}function q(e,t){he(e)||(t==null?e.removeAttribute(`class`):e.className=t)}function pe(e,t,n,r){if(r)Array.isArray(n)?(e[`$$${t}`]=n[0],e[`$$${t}Data`]=n[1]):e[`$$${t}`]=n;else if(Array.isArray(n)){let r=n[0];e.addEventListener(t,n[0]=t=>r.call(e,n[1],t))}else e.addEventListener(t,n,typeof n!=`function`&&n)}function J(e,t,n){n==null?e.style.removeProperty(t):e.style.setProperty(t,n)}function me(e,t,n){return S(()=>e(t,n))}function Y(e,t,n,r){if(n!==void 0&&!r&&(r=[]),typeof t!=`function`)return Z(e,t,r,n);y(r=>Z(e,t(),r,n),r)}function he(t){return!!e.context&&!e.done&&(!t||t.isConnected)}function X(t){if(e.registry&&e.events&&e.events.find(([e,n])=>n===t))return;let n=t.target,r=`$$${t.type}`,i=t.target,a=t.currentTarget,o=e=>Object.defineProperty(t,"target",{configurable:!0,value:e}),s=()=>{let e=n[r];if(e&&!n.disabled){let i=n[`${r}Data`];if(i===void 0?e.call(n,t):e.call(n,i,t),t.cancelBubble)return}return n.host&&typeof n.host!=`string`&&!n.host._$host&&n.contains(t.target)&&o(n.host),!0},c=()=>{for(;s()&&(n=n._$host||n.parentNode||n.host););};if(Object.defineProperty(t,"currentTarget",{configurable:!0,get(){return n||document}}),e.registry&&!e.done&&(e.done=_$HY.done=!0),t.composedPath){let e=t.composedPath();o(e[0]);for(let t=0;t<e.length-2&&(n=e[t],s());t++){if(n._$host){n=n._$host,c();break}if(n.parentNode===a)break}}else c();o(i)}function Z(e,t,n,r,i){let a=he(e);if(a){!n&&(n=[...e.childNodes]);let t=[];for(let e=0;e<n.length;e++){let r=n[e];r.nodeType===8&&r.data.slice(0,2)===`!$`?r.remove():t.push(r)}n=t}for(;typeof n==`function`;)n=n();if(t===n)return n;let o=typeof t,s=r!==void 0;if(e=s&&n[0]&&n[0].parentNode||e,o===`string`||o===`number`){if(a||o===`number`&&(t=t.toString(),t===n))return n;if(s){let i=n[0];i&&i.nodeType===3?i.data!==t&&(i.data=t):i=document.createTextNode(t),n=Q(e,n,r,i)}else n=n!==``&&typeof n==`string`?e.firstChild.data=t:e.textContent=t}else if(t==null||o===`boolean`){if(a)return n;n=Q(e,n,r)}else if(o===`function`)return y(()=>{let i=t();for(;typeof i==`function`;)i=i();n=Z(e,i,n,r)}),()=>n;else if(Array.isArray(t)){let o=[],c=n&&Array.isArray(n);if(ge(o,t,n,i))return y(()=>n=Z(e,o,n,r,!0)),()=>n;if(a){if(!o.length)return n;if(r===void 0)return n=[...e.childNodes];let t=o[0];if(t.parentNode!==e)return n;let i=[t];for(;(t=t.nextSibling)!==r;)i.push(t);return n=i}if(o.length===0){if(n=Q(e,n,r),s)return n}else c?n.length===0?_e(e,o,r):ue(e,n,o):(n&&Q(e),_e(e,o));n=o}else if(t.nodeType){if(a&&t.parentNode)return n=s?[t]:t;if(Array.isArray(n)){if(s)return n=Q(e,n,r,t);Q(e,n,null,t)}else n==null||n===``||!e.firstChild?e.appendChild(t):e.replaceChild(t,e.firstChild);n=t}return n}function ge(e,t,n,r){let i=!1;for(let a=0,o=t.length;a<o;a++){let o=t[a],s=n&&n[e.length],c;if(o!=null&&o!==!0&&o!==!1){if((c=typeof o)==`object`&&o.nodeType)e.push(o);else if(Array.isArray(o))i=ge(e,o,s)||i;else if(c===`function`){if(r){for(;typeof o==`function`;)o=o();i=ge(e,Array.isArray(o)?o:[o],Array.isArray(s)?s:[s])||i}else e.push(o),i=!0}else{let t=String(o);s&&s.nodeType===3&&s.data===t?e.push(s):e.push(document.createTextNode(t))}}}return i}function _e(e,t,n=null){for(let r=0,i=t.length;r<i;r++)e.insertBefore(t[r],n)}function Q(e,t,n,r){if(n===void 0)return e.textContent=``;let i=r||document.createTextNode(``);if(t.length){let r=!1;for(let a=t.length-1;a>=0;a--){let o=t[a];if(i!==o){let t=o.parentNode===e;!r&&!a?t?e.replaceChild(i,o):e.insertBefore(i,n):t&&o.remove()}else r=!0}}else e.insertBefore(i,n);return[i]}function ve(e){let t=ye(e.replace(/\r\n/g,`
2
- `)).split(`
3
- `),n=[],r=0;for(;r<t.length;){let e=t[r];if(/^```\w*\s*$/.test(e)){let e=[];for(r++;r<t.length&&!/^```\s*$/.test(t[r]);)e.push(t[r++]);r++,n.push(`<pre><code>${e.join(`
4
- `)}</code></pre>`);continue}let a=e.match(/^(#{1,4})\s+(.*)$/);if(a){n.push(`<h${a[1].length}>${i(a[2])}</h${a[1].length}>`),r++;continue}let o=/^\s*\d+[.)]\s+/.test(e);if(o||/^\s*[-*]\s+/.test(e)){let e=[];for(;r<t.length;){let n=t[r].match(/^\s*[-*]\s+(.*)$/)??(o?t[r].match(/^\s*\d+[.)]\s+(.*)$/):null);if(!n)break;e.push(`<li>${i(n[1])}</li>`),r++}n.push(o?`<ol>${e.join(``)}</ol>`:`<ul>${e.join(``)}</ul>`);continue}if(/^\s*$/.test(e)){r++;continue}let s=[];for(;r<t.length&&!/^\s*$/.test(t[r])&&!/^#{1,4}\s/.test(t[r])&&!/^```/.test(t[r])&&!/^\s*([-*]|\d+[.)])\s/.test(t[r]);)s.push(t[r++]);n.push(`<p>${s.map(i).join(`<br>`)}</p>`)}return n.join(`
5
- `);function i(e){return e.replace(/`([^`]+)`/g,`<code>$1</code>`).replace(/\*\*([^*]+)\*\*/g,`<strong>$1</strong>`).replace(/(^|\W)\*([^*]+)\*(?=\W|$)/g,`$1<em>$2</em>`).replace(/\[([^\]]+)\]\((https?:\/\/[^)\s]+)\)/g,`<a href="$2" rel="noopener noreferrer" target="_blank">$1</a>`)}}function ye(e){return e.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`).replace(/"/g,`&quot;`)}var be=`modulepreload`,xe=function(e){return`/`+e},Se={},Ce=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){let e=document.getElementsByTagName(`link`),i=document.querySelector(`meta[property=csp-nonce]`),a=i?.nonce||i?.getAttribute(`nonce`);function o(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}))))}function s(e){return import.meta.resolve?import.meta.resolve(e):new URL(e,import.meta.url).href}r=o(t.map(t=>{if(t=xe(t,n),t=s(t),t in Se)return;Se[t]=!0;let r=t.endsWith(`.css`);for(let n=e.length-1;n>=0;n--){let i=e[n];if(i.href===t&&(!r||i.rel===`stylesheet`))return}let i=document.createElement(`link`);if(i.rel=r?`stylesheet`:be,r||(i.as=`script`),i.crossOrigin=``,i.href=t,a&&i.setAttribute(`nonce`,a),document.head.appendChild(i),r)return new Promise((e,n)=>{i.addEventListener(`load`,e),i.addEventListener(`error`,()=>n(Error(`Unable to preload CSS for ${t}`)))})}))}function i(e){let t=new Event(`vite:preloadError`,{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then(t=>{for(let e of t||[])e.status===`rejected`&&i(e.reason);return e().catch(i)})},we=W(`<br>`),Te=W(`<span class="badge queued">⏳ <!> queued`),Ee=W(`<span class=sub>ℹ`),De=W(`<header class=chan-head><span class=hash>#</span><span class=title></span><span></span><span class=sub> · <!>/<!> · turns <!> · tools </span><span style=margin-left:auto;display:flex;gap:4px><button class=iconbtn title="terminal (t)">⌨</button><button class=iconbtn title="toggle details panel (d)">▤`),Oe=W(`<details class=reasoning><summary>💭 reasoning</summary><div class=mono>`),ke=W(`<div class=content><span class=cursor>▍`),Ae=W(`<div class="msg live"><div class=avatar style="background:#5865f233;border:1px solid #5865f266">🫖</div><div class=msg-body><div class=msg-head><span class=author style=color:var(--acc)>agent</span><span class=ts>streaming…`),je=W(`<div class=feed>`),Me=W(`<button class=jump>↓ `),Ne=W(`<div class=termdrawer><div class=termbar><span>⌨ terminal — <span class=mono></span></span><button class=iconbtn title="close terminal (t)">✕</button></div><div class=termhost>`),Pe=W(`<div class=composer><form><input type=text><label><input type=checkbox>auto-start</label><button type=submit>send</button></form><div class=hint>enter send · ↑↓ sessions · / focus · t terminal · d panel · esc interrupt · messages sent while the agent works are queued and delivered at the next turn boundary`),Fe=W(`<h3>🎛 session`),Ie=W(`<div class="card sesscard"><div class=sessrow><span class=k>agent</span><b></b><span></span></div><div class=sessrow><span class=k>workspace</span><span class="mono ellip"></span></div><div class=sessrow><span class=k>session</span><span class=mono>/`),Le=W(`<h3>🧦 model`),Re=W(`<div class=modelbox><select title="provider (OpenAI-compatible endpoint)"></select><div style=display:flex;gap:4px><input type=text list=model-list style=flex:1;min-width:0><datalist id=model-list></datalist><button title="apply to this session — takes effect from the agent's next turn">apply</button></div><div class=meta>current: `),ze=W(`<h3>⏯ controls`),Be=W(`<div class=btnrow><button title="run toward the goal (starts the loop)">▶ start</button><button title="interrupt: aborts the current LLM call; the running tool finishes first">■ stop</button><button title="branch off the conversation here — try things without disturbing the main line">⑂ fork</button><button title="remove agent from teapot (session log stays on disk)">🗑 remove`),Ve=W(`<h3>🎯 goal <span>`),He=W(`<form style=display:flex;gap:4px;margin-bottom:6px><input id=goal-input type=text placeholder="set new goal…"style="flex:1;background:var(--bg-darkest);border:none;border-radius:6px;padding:6px 8px;color:var(--fg);font:inherit"><button type=submit style="background:var(--acc);border:none;border-radius:6px;color:#fff;padding:0 10px;cursor:pointer">✓`),Ue=W(`<div class=card>`),We=W(`<h3>📈 progress`),Ge=W(`<div class=card>
6
- <!>
7
- <span class=muted>`),Ke=W(`<h3>📊 runtime`),qe=W(`<div class="card muted">turns <!> · tools <!> · compacted <!>
8
- tokens in/out <!>/`),Je=W(`<h3>🌿 branches <span class=muted style=text-transform:none;letter-spacing:0>· click to filter the feed`),Ye=W(`<div><nav class=sidebar><h1>🫖 teapot<span></span><span style=float:right;display:flex;gap:4px><button class=iconbtn title="new agent">+</button><button class=iconbtn title=settings>⚙</button></span></h1><div class=agent-list></div><div class=metrics></div></nav><section class=channel></section><aside>`),Xe=W(`<span title="goal done">✓`),Ze=W(`<div><span></span><span>`),Qe=W(`<div class=muted style=display:grid;place-items:center;height:100%>select an agent`),$e=W(`<div class=muted style=display:grid;place-items:center;height:100%>no events yet — say something or press ▶ start`),et=W(`<div class="content muted">thinking…`),tt=W(`<option>`),nt=W(`<div class=muted>none yet`),rt=W(`<div><span></span><span> events`),it=W(`<div class=divider-msg>⑂ forked from <!> → `),at=W(`<div class=divider-msg>🎯 goal <!>: `),ot=W(`<div> → `),st=W(`<div class=avatar>`),ct=W(`<div class=msg-head><span class=author></span><span class=ts></span><span class=ts>`),lt=W(`<div><div class=msg-body>`),ut=W(`<span style=width:38px>`),dt=W(`<div class=content>`),ft=W(`<div class=msgfoot><span>copy summary`),pt=W(`<details class=embed><summary><b>⚙ </b> <span class=meta></span></summary><div class=mono>`),mt=W(`<details><summary><span class=meta></span></summary><div class=mono></div><div class=meta>ms`),ht=W(`<div class=meta>`),gt=W(`<div class=meta>⚠ `),_t=W(`<div class=meta>→ `),vt=W(`<div class=embed style=border-color:var(--ok)><div>📈 `),yt=W(`<div class="embed fail"><div class=mono>⚠ `),bt=W(`<div class="content muted">`),xt=W(`<button class=copybtn title="copy to clipboard">`),St=W(`<div class=overlay><div class=modal><div class=modal-head><b></b><button class=iconbtn>✕`),Ct=W(`<span style=color:var(--err);font-size:13px>`),wt=W(`<form style=display:flex;flex-direction:column;gap:10px><label>workspace directory<div style=display:flex;gap:6px><input type=text class="w100 mono"><button type=button>go</button><button type=button>↑</button></div></label><div class=dirlist></div><div style=display:flex;gap:10px><label style=flex:1>agent name <input type=text placeholder="(directory name)"></label><label>provider<select></select></label><label style=flex:1>model <input type=text placeholder="(provider default)"></label></div><button type=submit style=align-self:flex-end>create & start`),Tt=W(`<div class=direntry>📁 `),Et=W(`<form style=display:flex;flex-direction:column;gap:10px><label>providers (<!>)<textarea rows=8 class="mono w100"></textarea></label><div style=display:flex;gap:10px><label style=flex:1>default provider <input type=text></label><label>progress interval (min) <input type=number min=1 style=width:90px></label></div><label>scheduled tasks (JSON array)<textarea rows=7 class="mono w100"></textarea></label><button type=submit style=align-self:flex-end>save`),Dt={prompt:{name:`you`,icon:`🟧`,color:`#faa81a`},user:{name:`you`,icon:`🟧`,color:`#faa81a`},message:{name:`agent`,icon:`🫖`,color:`#5865f2`},tool_call:{name:`tool`,icon:`🔧`,color:`#3ba0c9`},progress:{name:`progress`,icon:`📈`,color:`#3ba55d`}},Ot=e=>Dt[e.type]??{name:e.type,icon:`•`,color:`#9298a5`},kt=new Set([`user`,`message`,`prompt`,`tool_call`,`tool_result`,`progress`,`state`,`error`,`fork`,`goal`]),At=e=>kt.has(e.type),jt=e=>{let t=new Date(e);return`${String(t.getHours()).padStart(2,`0`)}:${String(t.getMinutes()).padStart(2,`0`)}`};async function $(e,t){let n=localStorage.getItem(`teapot.token`),r=new Headers(t?.headers);n&&!r.has(`authorization`)&&r.set(`authorization`,`Bearer ${n}`);let i=await fetch(e,{...t,headers:r});if(!i.ok){let t=``;try{t=(await i.json())?.error??``}catch{}throw Error(t||`${e}: HTTP ${i.status}`)}return i.json()}var Mt=location.hash.match(/[#&]token=([^&]+)/);Mt&&(localStorage.setItem(`teapot.token`,decodeURIComponent(Mt[1])),history.replaceState(null,``,location.pathname+location.search));var Nt=()=>{let e=localStorage.getItem(`teapot.token`);return e?`?token=${encodeURIComponent(e)}`:``};function Pt(){let[e,t]=v([]),[n,r]=v(null),[i,a]=v([]),[o,s]=v([]),[c,l]=v(null),[u,d]=v(``),[f,p]=v(!0),[m,h]=v({providers:{}}),[g,_]=v(!1),[S,T]=v(!1),[E,ee]=v(localStorage.getItem(`teapot.panel`)===null?window.innerWidth>1100:localStorage.getItem(`teapot.panel`)===`1`),te=()=>{let e=!E();ee(e),localStorage.setItem(`teapot.panel`,e?`1`:`0`)},[ne,re]=v(``),[D,ie]=v(``),[O,k]=v([]),A=()=>Object.keys(m().providers??{});async function ae(e){if(e)try{let t=await $(`/api/models?provider=${encodeURIComponent(e)}`);k(t.models??[])}catch{k([])}}b(()=>{let e=I();e&&(re(e.provider||m().defaultProvider||A()[0]||``),ie(``),ae(ne()))});let[oe,se]=v(!0),[j,M]=v(0),[N,P]=v(null),ce=x(()=>i().filter(At)),F=()=>$(`/api/config`).then(h).catch(()=>{}),I=x(()=>e().find(e=>e.id===n())),L=()=>$(`/api/agents`).then(e=>t(e.agents)).catch(()=>{}),R=()=>$(`/api/metrics`).then(l).catch(()=>{}),[z,le]=v(null);async function ue(e){try{let t=z(),[n,r]=await Promise.all([$(`/api/agents/${e}/events?limit=300${t?`&branch=${encodeURIComponent(t)}`:``}`),$(`/api/agents/${e}/branches`)]);a(n.events),s(r.branches)}catch{}}function de(){return document.querySelector(`.feed`)}function fe(){let e=de();return!e||e.scrollHeight-e.scrollTop-e.clientHeight<80}function W(e=!1){let t=de();t&&(e||oe())&&(t.scrollTop=t.scrollHeight,M(0))}async function G(e,t=!0){r(e),P(null),le(null),localStorage.setItem(`teapot.session`,e),Q(e,t),await ue(e),requestAnimationFrame(()=>W(!0))}let[J,he]=v(!1),X=null,Z=null;w(()=>X?.close());function ge(){let e=location.protocol===`https:`?`wss://`:`ws://`;X=new WebSocket(`${e}${location.host}/api/ws${Nt()}`),X.onopen=()=>he(!0),X.onclose=()=>{he(!1),setTimeout(ge,1500)},X.onerror=()=>X?.close(),X.onmessage=e=>{let t=JSON.parse(e.data);if(t.kind!==`ping`&&t.kind!==`pong`){if(t.kind===`llm-delta`){t.agentId===n()&&P({text:t.text??``,reasoning:t.reasoning??``});return}Z||=setTimeout(async()=>{if(Z=null,await L(),await R(),n()){let e=i().length;await ue(n()),i().length!==e&&(P(null),fe()?W(!0):M(j()+(i().length-e)))}},400)}}}let _e=()=>decodeURIComponent(location.pathname.split(`/`)[2]??``);function Q(e,t=!0){let n=`/session/${encodeURIComponent(e)}`;t?history.pushState(null,``,n):history.replaceState(null,``,n)}window.addEventListener(`popstate`,()=>{let t=_e();t&&e().some(e=>e.id===t)&&t!==n()&&G(t,!1)}),b(()=>{let e=I();document.title=e?`${e.status===`running`?`▶ `:e.status===`error`?`⚠ `:``}${e.id} · teapot`:`teapot`}),window.addEventListener(`keydown`,t=>{let r=t.target;if(r&&(r.tagName===`INPUT`||r.tagName===`TEXTAREA`||r.isContentEditable)){t.key===`Escape`&&r.blur();return}if(t.key===`Escape`){if(g()){_(!1);return}if(S()){T(!1);return}let e=I();if(e?.status===`running`){$(`/api/agents/${e.id}/stop`,{method:`POST`}).then(L);return}E()&&window.innerWidth<=1100&&ee(!1);return}if(!(g()||S())){if(t.key===`/`)t.preventDefault(),document.querySelector(`.composer input[type=text]`)?.focus();else if(t.key===`d`)te();else if(t.key===`t`)be();else if(t.key===`ArrowDown`||t.key===`ArrowUp`){let r=e();if(r.length===0)return;t.preventDefault();let i=r.findIndex(e=>e.id===n()),a=t.key===`ArrowDown`?Math.min(i+1,r.length-1):Math.max(i-1,0);a!==i&&G(r[a].id)}}});let[ve,ye]=v(localStorage.getItem(`teapot.term`)===`1`),be=()=>{let e=!ve();ye(e),localStorage.setItem(`teapot.term`,e?`1`:`0`)},xe=null,Se=null,it=null,at=null,ot={cols:0,rows:0},st=null;function ct(){at?.disconnect(),at=null,it?.close(),it=null,Se?.dispose(),Se=null}function lt(e){ct(),xe&&Promise.all([Ce(()=>import(`./xterm-C3BHN0de.js`),[]),Ce(()=>import(`./addon-fit-DIOBYJe3.js`),[])]).then(([{Terminal:t},{FitAddon:n}])=>{let r=new t({cursorBlink:!0,fontSize:12.5,fontFamily:`ui-monospace, Menlo, Consolas, monospace`,theme:{background:`#0d0e12`,foreground:`#dcdee4`}}),i=new n;r.loadAddon(i),r.open(xe),i.fit(),Se=r;let a=location.protocol===`https:`?`wss://`:`ws://`,o=new WebSocket(`${a}${location.host}/api/agents/${e}/term${Nt()}`);it=o,o.onmessage=e=>{let t=JSON.parse(e.data);t.kind===`data`?r.write(t.data):t.kind===`exit`&&r.write(`\r\n\x1b[2m[terminal exited ${t.code??``}]\x1b[0m\r\n`)},r.onData(e=>{o.readyState===WebSocket.OPEN&&o.send(JSON.stringify({kind:`input`,data:e}))});let s=()=>{try{i.fit()}catch{}let{cols:e,rows:t}=r;(e!==ot.cols||t!==ot.rows)&&o.readyState===WebSocket.OPEN&&(ot={cols:e,rows:t},o.send(JSON.stringify({kind:`resize`,cols:e,rows:t})))};at=new ResizeObserver(()=>{st&&clearTimeout(st),st=setTimeout(s,300)}),at.observe(xe),setTimeout(s,50)})}b(()=>{let e=n();!ve()||!e?ct():requestAnimationFrame(()=>e&&lt(e))}),w(ct),C(()=>{F(),L().then(()=>{let t=_e()||localStorage.getItem(`teapot.session`)||``,n=e().find(e=>e.id===t)??e()[0];n&&G(n.id,!1)}),R(),ge();let t=setInterval(R,3e4);w(()=>clearInterval(t))});let ut=async e=>{e.preventDefault();let t=n(),r=u().trim();if(!(!t||!r)){d(``);try{await $(`/api/agents/${t}/prompt`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({text:r,start:f()})})}catch(e){d(r),console.error(`send failed:`,e)}}},dt=e=>()=>n()&&$(`/api/agents/${n()}${e}`,{method:`POST`}).then(L),ft=async e=>{e.preventDefault();let t=document.getElementById(`goal-input`);!n()||!t.value.trim()||(await $(`/api/agents/${n()}/goal`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({text:t.value})}),t.value=``,L())};return[(()=>{var i=Ye(),s=i.firstChild,l=s.firstChild,h=l.firstChild.nextSibling,g=h.nextSibling.firstChild,v=g.nextSibling,b=l.nextSibling,x=b.nextSibling,S=s.nextSibling,C=S.nextSibling;return g.$$click=()=>{F(),_(!0)},v.$$click=()=>{F(),T(!0)},Y(b,B(V,{get each(){return e()},children:e=>(()=>{var t=Ze(),r=t.firstChild,i=r.nextSibling;return t.$$click=()=>G(e.id),Y(i,()=>e.id),Y(t,B(H,{get when(){return e.goal.status===`done`},get children(){return Xe()}}),null),y(i=>{var a=`agent-item`+(e.id===n()?` sel`:``),o=`dot ${e.status}`;return a!==i.e&&q(t,i.e=a),o!==i.t&&q(r,i.t=o),i},{e:void 0,t:void 0}),t})()})),Y(x,B(H,{get when(){return c()},get children(){return[`master rss `,U(()=>c().rssMb),`MB · heap `,U(()=>c().heapUsedMb),`MB`,we(),`load1 `,U(()=>c().loadavg1),` · up `,U(()=>Math.floor(c().uptimeSec/60)),`m`]}})),Y(S,B(H,{get when(){return I()},get fallback(){return Qe()},get children(){return[(()=>{var e=De(),t=e.firstChild.nextSibling,n=t.nextSibling,r=n.nextSibling,i=r.firstChild,a=i.nextSibling,o=a.nextSibling.nextSibling,s=o.nextSibling.nextSibling;s.nextSibling;var c=r.nextSibling,l=c.firstChild,u=l.nextSibling;return Y(t,()=>I().id),Y(n,()=>I().status),Y(e,B(H,{get when(){return(I().pendingPrompts??0)>0},get children(){var e=Te(),t=e.firstChild.nextSibling;return t.nextSibling,Y(e,()=>I().pendingPrompts,t),y(()=>K(e,`title`,`${I().pendingPrompts} prompt(s) waiting — the agent picks them up at the next turn boundary`)),e}}),r),Y(r,()=>I().model,i),Y(r,()=>I().session,a),Y(r,()=>I().branch,o),Y(r,()=>I().stats.turns,s),Y(r,()=>I().stats.toolCalls,null),Y(c,B(H,{get when(){return I().statusReason},get children(){var e=Ee();return y(()=>K(e,`title`,I().statusReason)),e}}),l),l.$$click=be,u.$$click=te,y(()=>q(n,`badge ${I().status}`)),e})(),(()=>{var e=je();return e.addEventListener(`scroll`,()=>{let e=fe();e&&j()&&M(0),se(e)}),Y(e,B(H,{get when(){return ce().length>0},get fallback(){return $e()},get children(){return[B(V,{get each(){return ce()},children:(e,t)=>B(Ft,{e,get prev(){return ce()[t()-1]}})}),B(H,{get when(){return N()},get children(){var e=Ae(),t=e.firstChild.nextSibling;return t.firstChild,Y(t,B(H,{get when(){return N().reasoning},get children(){var e=Oe(),t=e.firstChild.nextSibling;return Y(t,()=>N().reasoning),e}}),null),Y(t,B(H,{get when(){return N().text},get fallback(){return et()},get children(){var e=ke(),t=e.firstChild;return Y(e,()=>N().text,t),e}}),null),e}})]}})),e})(),B(H,{get when(){return!oe()||j()>0},get children(){var e=Me();return e.firstChild,e.$$click=()=>W(!0),Y(e,(()=>{var e=U(()=>j()>0);return()=>e()?`${j()} new message${j()>1?`s`:``}`:`jump to present`})(),null),e}}),B(H,{get when(){return U(()=>!!ve())()&&I()},get children(){var e=Ne(),t=e.firstChild,n=t.firstChild,r=n.firstChild.nextSibling,i=n.nextSibling,a=t.nextSibling;return Y(r,()=>I().workspace),i.$$click=be,me(e=>xe=e,a),e}}),(()=>{var e=Pe(),t=e.firstChild,n=t.firstChild,r=n.nextSibling.firstChild;return t.addEventListener(`submit`,ut),n.$$input=e=>d(e.currentTarget.value),r.addEventListener(`change`,e=>p(e.currentTarget.checked)),y(()=>K(n,`placeholder`,`message #${I().id}`)),y(()=>n.value=u()),y(()=>r.checked=f()),e})()]}})),Y(C,B(H,{get when(){return I()},get children(){return[Fe(),(()=>{var e=Ie(),t=e.firstChild,n=t.firstChild.nextSibling,r=n.nextSibling,i=t.nextSibling,a=i.firstChild.nextSibling,o=i.nextSibling.firstChild.nextSibling,s=o.firstChild;return Y(n,()=>I().id),Y(r,()=>I().status),Y(a,()=>I().workspace),Y(o,()=>I().session,s),Y(o,()=>I().branch,null),y(e=>{var t=`badge ${I().status}`,n=I().workspace;return t!==e.e&&q(r,e.e=t),n!==e.t&&K(a,`title`,e.t=n),e},{e:void 0,t:void 0}),e})(),Le(),(()=>{var e=Re(),t=e.firstChild,r=t.nextSibling,i=r.firstChild,a=i.nextSibling,o=a.nextSibling,s=r.nextSibling;return s.firstChild,t.addEventListener(`change`,e=>{re(e.currentTarget.value),ae(e.currentTarget.value)}),Y(t,B(V,{get each(){return A()},children:e=>(()=>{var t=tt();return t.value=e,Y(t,e,null),Y(t,()=>e===m().defaultProvider?` ★`:``,null),t})()})),i.$$input=e=>ie(e.currentTarget.value),Y(a,B(V,{get each(){return O()},children:e=>(()=>{var t=tt();return t.value=e,t})()})),o.$$click=async e=>{if(!n())return;let t=e.currentTarget;t.disabled=!0;try{await $(`/api/agents/${n()}/model`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({provider:ne(),model:D().trim()||void 0})}),t.textContent=`✓ applied`,L()}catch(e){alert(`model switch failed: ${e.message}`)}finally{setTimeout(()=>{t.textContent=`apply`,t.disabled=!1},1200)}},Y(s,()=>I().model,null),Y(s,B(H,{get when(){return O().length},get children(){return[` · `,U(()=>O().length),` models loaded`]}}),null),y(()=>K(i,`placeholder`,I().model)),y(()=>t.value=ne()),y(()=>i.value=D()),e})(),ze(),(()=>{var i=Be(),o=i.firstChild,s=o.nextSibling,c=s.nextSibling,l=c.nextSibling;return pe(o,`click`,dt(`/start`),!0),pe(s,`click`,dt(`/stop`),!0),c.$$click=()=>$(`/api/agents/${I().id}/fork`,{method:`POST`,headers:{"content-type":`application/json`},body:`{}`}).then(()=>G(I().id)),l.$$click=async()=>{let i=n();if(!i||!confirm(`remove agent ${i}? (log is kept)`))return;await $(`/api/agents/${i}`,{method:`DELETE`}).catch(()=>{});let o=e().filter(e=>e.id!==i);t(o),o[0]?G(o[0].id):(r(null),a([]))},i})(),(()=>{var e=Ve(),t=e.firstChild.nextSibling;return Y(t,()=>I().goal.status),y(()=>q(t,`badge ${I().goal.status===`done`?`done`:``}`)),e})(),(()=>{var e=He();return e.addEventListener(`submit`,ft),e})(),(()=>{var e=Ue();return Y(e,()=>I().goal.text||`no goal set`),e})(),We(),B(H,{get when(){return I().latestProgress},get fallback(){return nt()},get children(){var e=Ge(),t=e.firstChild,n=t.nextSibling,r=n.nextSibling.nextSibling;return Y(e,()=>I().latestProgress.doing,t),Y(e,()=>I().latestProgress.recent??``,n),Y(r,()=>I().latestProgress.ts),e}}),Ke(),(()=>{var e=qe(),t=e.firstChild.nextSibling,n=t.nextSibling.nextSibling,r=n.nextSibling.nextSibling,i=r.nextSibling.nextSibling;return i.nextSibling,Y(e,()=>I().stats.turns,t),Y(e,()=>I().stats.toolCalls,n),Y(e,()=>I().stats.compactions??0,r),Y(e,()=>I().stats.inputTokens,i),Y(e,()=>I().stats.outputTokens,null),e})(),Je(),B(V,{get each(){return o()},children:e=>(()=>{var t=rt(),r=t.firstChild,i=r.nextSibling,a=i.firstChild;return t.$$click=()=>{let t=z()===e.branch?null:e.branch;le(t),n()&&ue(n())},Y(r,()=>e.branch,null),Y(r,()=>e.branch===I().branch?` (current)`:``,null),Y(i,()=>e.events,a),y(n=>{var r=`branch-row`+(e.branch===I().branch||e.branch===z()?` cur`:``),i=e.branch===z()?`click to show all branches again`:`show only ${e.branch}`;return r!==n.e&&q(t,n.e=r),i!==n.t&&K(t,`title`,n.t=i),n},{e:void 0,t:void 0}),t})()})]}})),y(e=>{var t=`layout`+(E()?``:` right-hidden`),n=`conn`+(J()?` ok`:``),r=J()?`live (websocket)`:`reconnecting…`,a=`rightbar`+(E()?` open`:``);return t!==e.e&&q(i,e.e=t),n!==e.t&&q(h,e.t=n),r!==e.a&&K(h,`title`,e.a=r),a!==e.o&&q(C,e.o=a),e},{e:void 0,t:void 0,a:void 0,o:void 0}),i})(),B(H,{get when(){return g()},get children(){return B(Vt,{get providers(){return Object.keys(m().providers??{})},onClose:()=>_(!1),onCreated:e=>{_(!1),L(),G(e)}})}}),B(H,{get when(){return S()},get children(){return B(Ht,{get cfg(){return m()},onClose:()=>T(!1),onSaved:F})}})]}function Ft(e){let t=e.e,n=Ot(t),r=e.prev&&e.prev.type===t.type&&t.session===e.prev.session&&t.branch===e.prev.branch;if(t.type===`fork`){let e=t.data??{};return(()=>{var n=it(),r=n.firstChild.nextSibling;return r.nextSibling,Y(n,()=>String(e.fromBranch??`?`),r),Y(n,()=>String(e.newBranch??t.branch),null),n})()}if(t.type===`goal`){let e=t.data??{},n=e.event===`status`?`marked ${String(e.status??``)}`:Rt(String(e.text??``),80);return(()=>{var t=at(),r=t.firstChild.nextSibling;return r.nextSibling,Y(t,()=>String(e.event??``),r),Y(t,n,null),t})()}return t.type===`state`?t.data.from===t.data.to?null:(()=>{var e=ot(),n=e.firstChild;return Y(e,()=>t.data.from,n),Y(e,()=>t.data.to,null),Y(e,(()=>{var e=U(()=>!!t.data.reason);return()=>e()?` — ${t.data.reason}`:``})(),null),y(()=>q(e,`divider-msg`+(t.data.to===`error`?` err`:``))),e})():(()=>{var e=lt(),i=e.firstChild;return q(e,`msg`+(r?` grouped`:``)),Y(e,B(H,{when:!r,get fallback(){return ut()},get children(){var e=st();return Y(e,()=>n.icon),y(t=>{var r=n.color+`33`,i=`1px solid ${n.color}66`;return r!==t.e&&J(e,`background`,t.e=r),i!==t.t&&J(e,`border`,t.t=i),t},{e:void 0,t:void 0}),e}}),i),Y(i,B(H,{when:!r,get children(){var e=ct(),r=e.firstChild,i=r.nextSibling,a=i.nextSibling;return Y(r,()=>n.name),Y(i,()=>jt(t.ts)),Y(a,()=>t.branch),y(e=>J(r,`color`,n.color)),e}}),null),Y(i,B(It,{e:t}),null),e})()}function It(e){let t=e.e;switch(t.type){case`prompt`:return(()=>{var e=dt();return y(()=>e.innerHTML=ve(String(t.data.text??``))),e})();case`message`:return[B(H,{get when(){return U(()=>typeof t.data.reasoning==`string`)()&&t.data.reasoning.trim()},get children(){var e=Oe(),n=e.firstChild.nextSibling;return Y(n,()=>String(t.data.reasoning)),e}}),(()=>{var e=dt();return y(()=>e.innerHTML=ve(String(t.data.content??``))),e})(),B(H,{get when(){return t.data.final},get children(){var e=ft(),n=e.firstChild;return Y(e,B(zt,{get text(){return String(t.data.content??``)}}),n),e}})];case`tool_call`:{let e=JSON.stringify(t.data.args,null,1),n=Rt(JSON.stringify(t.data.args??{}),110);return(()=>{var r=pt(),i=r.firstChild,a=i.firstChild;a.firstChild;var o=a.nextSibling.nextSibling,s=i.nextSibling;return Y(a,()=>String(t.data.name),null),Y(o,n),Y(s,e),r})()}case`tool_result`:{let e=String(t.data.result);return(()=>{var n=mt(),r=n.firstChild,i=r.firstChild,a=r.nextSibling,o=a.nextSibling,s=o.firstChild;return Y(i,()=>Rt(e,120)),Y(r,B(zt,{text:e}),null),Y(a,()=>Lt(e,4e3)),Y(o,()=>t.data.durationMs,s),Y(o,()=>t.data.ok?``:` · FAILED`,null),y(()=>q(n,`embed`+(t.data.ok?``:` fail`))),n})()}case`progress`:return(()=>{var e=vt(),n=e.firstChild;return n.firstChild,Y(n,()=>String(t.data.doing??``),null),Y(e,B(H,{get when(){return t.data.recent},get children(){var e=ht();return Y(e,()=>String(t.data.recent)),e}}),null),Y(e,B(H,{get when(){return t.data.problems},get children(){var e=gt();return e.firstChild,Y(e,()=>String(t.data.problems),null),e}}),null),Y(e,B(H,{get when(){return t.data.next},get children(){var e=_t();return e.firstChild,Y(e,()=>String(t.data.next),null),e}}),null),e})();case`error`:return(()=>{var e=yt(),n=e.firstChild;return n.firstChild,Y(n,()=>String(t.data.message??``),null),e})();default:return(()=>{var e=bt();return Y(e,()=>Lt(JSON.stringify(t.data),200)),e})()}}function Lt(e,t){return e.length>t?e.slice(0,t)+` …`:e}function Rt(e,t){return Lt(e.replace(/\s+/g,` `).trim(),t)}function zt(e){let[t,n]=v(!1);return(()=>{var r=xt();return r.$$click=t=>{t.stopPropagation(),navigator.clipboard.writeText(e.text).then(()=>{n(!0),setTimeout(()=>n(!1),900)})},Y(r,()=>t()?`✓`:`⧉`),r})()}function Bt(e){return(()=>{var t=St(),n=t.firstChild,r=n.firstChild.firstChild,i=r.nextSibling;return t.$$click=t=>t.target===t.currentTarget&&e.onClose(),Y(r,()=>e.title),pe(i,`click`,e.onClose,!0),Y(n,()=>e.children,null),t})()}function Vt(e){let[t,n]=v(`~`),[r,i]=v([]),[a,o]=v(``),[s,c]=v(e.providers[0]??``),[l,u]=v(``),[d,f]=v(``);async function p(e){let t=await $(`/api/fs${e?`?path=${encodeURIComponent(e)}`:``}`);n(t.path),i(t.entries)}C(()=>p(t()));let m=async n=>{n.preventDefault(),f(``);try{let n=await $(`/api/agents`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({workspace:t(),id:a(),provider:s()||void 0,model:l()||void 0})});e.onCreated(n.agent.id)}catch(e){f(String(e.message))}};return B(Bt,{title:`new agent`,get onClose(){return e.onClose},get children(){var i=wt(),f=i.firstChild,h=f.firstChild.nextSibling.firstChild,g=h.nextSibling,_=g.nextSibling,v=f.nextSibling,b=v.nextSibling,x=b.firstChild,S=x.firstChild.nextSibling,C=x.nextSibling,w=C.firstChild.nextSibling,T=C.nextSibling.firstChild.nextSibling,E=b.nextSibling;return i.addEventListener(`submit`,m),h.$$input=e=>n(e.currentTarget.value),g.$$click=()=>p(t()),_.$$click=()=>p(`..`),Y(v,B(V,{get each(){return r()},children:e=>(()=>{var n=Tt();return n.firstChild,n.$$click=()=>p(`${t()}/${e}`.replace(/\/+/g,`/`)),Y(n,e,null),n})()})),S.$$input=e=>o(e.currentTarget.value),w.addEventListener(`change`,e=>c(e.currentTarget.value)),Y(w,B(V,{get each(){return e.providers},children:e=>(()=>{var t=tt();return Y(t,e),t})()})),T.$$input=e=>u(e.currentTarget.value),Y(i,B(H,{get when(){return d()},get children(){var e=Ct();return Y(e,d),e}}),E),y(()=>h.value=t()),y(()=>S.value=a()),y(()=>w.value=s()),y(()=>T.value=l()),i}})}function Ht(e){let[t,n]=v(JSON.stringify(Object.fromEntries(Object.entries(e.cfg.providers??{}).map(([e,t])=>[e,{baseUrl:t.baseUrl,apiKey:t.apiKey??``,model:t.model??``}])),null,2)),[r,i]=v(e.cfg.defaultProvider??Object.keys(e.cfg.providers??{})[0]??``),[a,o]=v(Math.round((e.cfg.progressIntervalMs??6e5)/6e4)),[s,c]=v(JSON.stringify(e.cfg.tasks??[],null,2)),[l,u]=v(``),d=async n=>{n.preventDefault(),u(``);let i,o;try{i=JSON.parse(t())}catch{return u(`providers: invalid JSON`)}try{o=JSON.parse(s())}catch{return u(`tasks: invalid JSON`)}try{await $(`/api/config`,{method:`PUT`,headers:{"content-type":`application/json`},body:JSON.stringify({providers:i,defaultProvider:r(),progressIntervalMs:Math.max(1,a())*6e4,tasks:o})}),e.onSaved(),e.onClose()}catch(e){u(String(e.message))}};return B(Bt,{title:`settings`,get onClose(){return e.onClose},get children(){var u=Et(),f=u.firstChild,p=f.firstChild.nextSibling,m=p.nextSibling.nextSibling,h=f.nextSibling,g=h.firstChild,_=g.firstChild.nextSibling,v=g.nextSibling.firstChild.nextSibling,b=h.nextSibling,x=b.firstChild.nextSibling,S=b.nextSibling;return u.addEventListener(`submit`,d),Y(f,()=>e.cfg.configPath,p),m.$$input=e=>n(e.currentTarget.value),_.$$input=e=>i(e.currentTarget.value),v.$$input=e=>o(Number(e.currentTarget.value)),x.$$input=e=>c(e.currentTarget.value),Y(u,B(H,{get when(){return l()},get children(){var e=Ct();return Y(e,l),e}}),S),y(()=>m.value=t()),y(()=>_.value=r()),y(()=>v.value=a()),y(()=>x.value=s()),u}})}G([`click`,`input`]),fe(()=>B(Pt,{}),document.getElementById(`root`));