teapot-coding-agent 0.9.0 → 0.11.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/dist/agent/llm.js CHANGED
@@ -76,7 +76,13 @@ export async function chat(cfg, messages, tools, signal) {
76
76
  message,
77
77
  reasoning,
78
78
  usage: res.usage
79
- ? { inputTokens: res.usage.prompt_tokens, outputTokens: res.usage.completion_tokens }
79
+ ? {
80
+ inputTokens: res.usage.prompt_tokens,
81
+ outputTokens: res.usage.completion_tokens,
82
+ // OpenAI-compatible providers attach cache details here (OpenRouter included)
83
+ cachedInputTokens: res.usage
84
+ .prompt_tokens_details?.cached_tokens ?? undefined,
85
+ }
80
86
  : undefined,
81
87
  };
82
88
  }
@@ -96,6 +102,9 @@ export async function chat(cfg, messages, tools, signal) {
96
102
  */
97
103
  export async function chatStream(cfg, messages, tools, signal, onDelta) {
98
104
  let gotChunk = false;
105
+ // hoisted so the abort handler below can attach whatever streamed so far
106
+ let text = "";
107
+ let reasoning = "";
99
108
  try {
100
109
  const stream = await client(cfg).chat.completions.create({
101
110
  model: cfg.model,
@@ -103,8 +112,6 @@ export async function chatStream(cfg, messages, tools, signal, onDelta) {
103
112
  ...(tools.length ? { tools } : {}),
104
113
  stream: true,
105
114
  }, { signal });
106
- let text = "";
107
- let reasoning = "";
108
115
  const calls = {};
109
116
  let finishReason;
110
117
  let usage;
@@ -130,7 +137,11 @@ export async function chatStream(cfg, messages, tools, signal, onDelta) {
130
137
  if (c?.finish_reason)
131
138
  finishReason = c.finish_reason;
132
139
  if (ch.usage)
133
- usage = { inputTokens: ch.usage.prompt_tokens, outputTokens: ch.usage.completion_tokens };
140
+ usage = {
141
+ inputTokens: ch.usage.prompt_tokens,
142
+ outputTokens: ch.usage.completion_tokens,
143
+ cachedInputTokens: ch.usage.prompt_tokens_details?.cached_tokens ?? undefined,
144
+ };
134
145
  if (onDelta)
135
146
  onDelta({ text, reasoning });
136
147
  }
@@ -155,6 +166,11 @@ export async function chatStream(cfg, messages, tools, signal, onDelta) {
155
166
  // provider may not support streaming at all — one clean fallback
156
167
  if (!gotChunk && !signal?.aborted)
157
168
  return chat(cfg, messages, tools, signal);
169
+ // user interrupt: hand back whatever streamed so far so the harness can
170
+ // keep the partial output visible instead of losing it
171
+ if (signal?.aborted && (text || reasoning)) {
172
+ err.partial = { text, reasoning };
173
+ }
158
174
  throw err;
159
175
  }
160
176
  }
@@ -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
@@ -181,7 +190,14 @@ export class Master {
181
190
  async start() {
182
191
  mkdirSync(this.config.dataDir, { recursive: true });
183
192
  for (const ac of this.config.agents) {
184
- await this.addAgent(ac);
193
+ try {
194
+ await this.addAgent(ac);
195
+ }
196
+ catch (err) {
197
+ // one bad entry (duplicate id, unknown provider, …) must not take the
198
+ // whole master down — skip it loudly and keep serving the rest
199
+ console.error(`[teapot] skipping agent "${ac.id}": ${err.message}`);
200
+ }
185
201
  }
186
202
  for (const t of this.config.tasks ?? []) {
187
203
  this.tasks.push({
@@ -225,12 +241,22 @@ export class Master {
225
241
  llm,
226
242
  sessionDir,
227
243
  progressIntervalMs: this.config.progressIntervalMs,
244
+ ...(this.config.progressMinChars ? { progressMinChars: this.config.progressMinChars } : {}),
228
245
  autoContinue: true,
229
246
  ...(this.config.contextTokenBudget ? { contextTokenBudget: this.config.contextTokenBudget } : {}),
247
+ ...(ac.contextWindowTokens || this.config.contextWindowTokens
248
+ ? { contextWindowTokens: (ac.contextWindowTokens ?? this.config.contextWindowTokens) }
249
+ : {}),
230
250
  globalSkillsDir: path.join(CONFIG_DIR, "skills"),
231
251
  provider: provName,
232
252
  });
233
- agent.log.onEvent = (e) => printAgentEvent(e);
253
+ // console line + broadcast: the web UI only refreshes on bus traffic, so
254
+ // every appended event must reach it (otherwise messages sit invisible
255
+ // until an unrelated status change happens to fire)
256
+ agent.log.onEvent = (e) => {
257
+ printAgentEvent(e);
258
+ bus.emit("update", { kind: "event", agentId: e.agent, event: e });
259
+ };
234
260
  await agent.init();
235
261
  this.agents.set(ac.id, agent);
236
262
  if (opts.persist) {
@@ -363,6 +389,7 @@ export class Master {
363
389
  if (t.lastRunMin === minuteKey)
364
390
  continue; // dedupe within the same minute
365
391
  t.lastRunMin = minuteKey;
392
+ t.lastRunAt = Date.now();
366
393
  const agent = this.agents.get(t.task.agent);
367
394
  if (!agent)
368
395
  continue;
@@ -380,6 +407,18 @@ export class Master {
380
407
  }
381
408
  }
382
409
  }
410
+ /** Everything the UI needs to make cron schedules legible. */
411
+ tasksView() {
412
+ return this.tasks.map((t) => ({
413
+ id: t.task.id,
414
+ agent: t.task.agent,
415
+ schedule: t.schedule.raw,
416
+ forked: !!t.task.forked,
417
+ prompt: t.task.prompt,
418
+ next: nextFireAt(t.schedule),
419
+ last: t.lastRunAt ? new Date(t.lastRunAt).toISOString() : null,
420
+ }));
421
+ }
383
422
  metrics() {
384
423
  const mu = process.memoryUsage();
385
424
  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
+ }
@@ -166,7 +166,13 @@ export function buildApp(master) {
166
166
  catch {
167
167
  return c.json({ error: `directory not found: ${ws}` }, 400);
168
168
  }
169
- const id = (body.id?.trim() || path.basename(ws)).replace(/[^\w.-]/g, "-").slice(0, 40);
169
+ const base = (body.id?.trim() || path.basename(ws)).replace(/[^\w.-]/g, "-").slice(0, 40);
170
+ // agent ids are unique among running agents (they key the URL) — on a
171
+ // collision, auto-suffix so creating ~/a/proj and ~/b/proj just works
172
+ let id = base;
173
+ let n = 2;
174
+ while (master.agents.has(id))
175
+ id = `${base.slice(0, 38)}-${n++}`;
170
176
  try {
171
177
  const agent = await master.addAgent({ id, workspace: ws, provider: body.provider, model: body.model }, { persist: true, fresh: true });
172
178
  if (body.start !== false)
@@ -257,6 +263,14 @@ export function buildApp(master) {
257
263
  const a = master.agents.get(c.req.param("id"));
258
264
  return a ? c.json(a.snapshot()) : c.json({ error: "not found" }, 404);
259
265
  });
266
+ // lazy session load: stopped (not restored) → idle, history rebuilt from the log
267
+ app.post("/api/agents/:id/load", async (c) => {
268
+ const a = master.agents.get(c.req.param("id"));
269
+ if (!a)
270
+ return c.json({ error: "not found" }, 404);
271
+ await a.load();
272
+ return c.json({ ok: true, agent: a.snapshot() });
273
+ });
260
274
  app.post("/api/agents/:id/prompt", async (c) => {
261
275
  const a = master.agents.get(c.req.param("id"));
262
276
  if (!a)
@@ -334,14 +348,50 @@ export function buildApp(master) {
334
348
  if (!a)
335
349
  return c.json({ error: "not found" }, 404);
336
350
  const body = await c.req.json();
337
- if (body.text)
351
+ if (body.text) {
338
352
  await a.setGoal(body.text);
353
+ // goals live behind get_goal(), so a silent save would go unnoticed —
354
+ // queue a harness prompt unless the caller explicitly declines
355
+ if (body.notify !== false)
356
+ a.enqueuePrompt(`[harness] The operator set a new goal:\n\n${body.text}\n\nAlign your work with it.`, "harness");
357
+ }
339
358
  else if (body.status)
340
359
  await a.setGoalStatus(body.status);
341
360
  else
342
361
  return c.json({ error: "text or status required" }, 400);
343
362
  return c.json({ ok: true });
344
363
  });
364
+ // operator-maintained task list (todo.md) with optional agent notification
365
+ app.post("/api/agents/:id/todo", async (c) => {
366
+ const a = master.agents.get(c.req.param("id"));
367
+ if (!a)
368
+ return c.json({ error: "not found" }, 404);
369
+ const body = await c.req.json().catch(() => null);
370
+ if (!body)
371
+ return c.json({ error: "invalid JSON" }, 400);
372
+ await a.setTodo(body.text ?? "");
373
+ if (body.notify !== false && body.text?.trim())
374
+ a.enqueuePrompt(`[harness] The operator updated the task list:\n\n${body.text}\n\nWork through it (get_todo() always has the latest).`, "harness");
375
+ return c.json({ ok: true });
376
+ });
377
+ // edit a previously-sent prompt: forks there, optionally summarizes the tail
378
+ app.post("/api/agents/:id/edit-prompt", async (c) => {
379
+ const a = master.agents.get(c.req.param("id"));
380
+ if (!a)
381
+ return c.json({ error: "not found" }, 404);
382
+ const body = await c.req
383
+ .json()
384
+ .catch(() => null);
385
+ if (!body?.eventId || !body.text?.trim())
386
+ return c.json({ error: "eventId and text required" }, 400);
387
+ try {
388
+ const r = await a.editPromptAt(body.eventId, body.text, body.tail === "summarize" ? "summarize" : "discard");
389
+ return c.json({ ok: true, ...r });
390
+ }
391
+ catch (err) {
392
+ return c.json({ error: err.message }, 409);
393
+ }
394
+ });
345
395
  app.post("/api/agents/:id/fork", async (c) => {
346
396
  const a = master.agents.get(c.req.param("id"));
347
397
  if (!a)
@@ -382,6 +432,8 @@ export function buildApp(master) {
382
432
  });
383
433
  // ---- metrics / SSE ----
384
434
  app.get("/api/metrics", (c) => c.json(master.metrics()));
435
+ // scheduled tasks with computed next-fire times (cron visibility for the UI)
436
+ app.get("/api/tasks", (c) => c.json({ tasks: master.tasksView() }));
385
437
  app.get("/api/events", (c) => {
386
438
  c.header("content-type", "text/event-stream");
387
439
  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.11.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,14 @@
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=le,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(()=>k(o)));d=o,p=null;try{return D(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[ie.bind(n),e=>(typeof e==`function`&&(e=f&&f.running&&f.sources.has(n)?e(n.tValue):e(n.value)),ae(n,e))]}function y(e,t,n){T(se(e,t,!1,c))}function b(e,t,n){s=ue;let r=se(e,t,!1,c),i=re&&ne(re);i&&(r.suspense=i),(!n||!n.render)&&(r.user=!0),h?h.push(r):T(r)}function x(e,t,n){n=n?Object.assign({},a,n):a;let r=se(e,t,!0,0);return r.observers=null,r.observerSlots=null,r.comparator=n.equals||void 0,T(r),ie.bind(r)}function S(e){if(p===null)return e();let t=p;p=null;try{return e()}finally{p=t}}function ee(e){b(()=>S(e))}function C(e){return d===null||(d.cleanups===null?d.cleanups=[e]:d.cleanups.push(e)),e}var[te,w]=v(!1);function ne(e){let t;return d&&d.context&&(t=d.context[e.id])!==void 0?t:e.defaultValue}var re;function ie(){let e=f&&f.running;if(this.sources&&(e?this.tState:this.state)){if((e?this.tState:this.state)===c)T(this);else{let e=m;m=null,D(()=>O(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 ae(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&&D(()=>{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&&de(n)),r?n.tState=c:n.state=c)}if(m.length>1e6)throw m=[],Error()},!1)}return t}function T(e){if(!e.fn)return;k(e);let t=g;oe(e,f&&f.running&&f.sources.has(e)?e.tValue:e.value,t),f&&!f.running&&f.sources.has(e)&&queueMicrotask(()=>{D(()=>{f&&(f.running=!0),p=d=e,oe(e,e.tValue,t),p=d=null},!1)})}function oe(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(k),e.tOwned=void 0):(e.state=c,e.owned&&e.owned.forEach(k),e.owned=null)),e.updatedAt=n+1,pe(t)}finally{p=a,d=i}(!e.updatedAt||e.updatedAt<=n)&&(e.updatedAt!=null&&`observers`in e?ae(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 se(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 E(e){let t=f&&f.running;if((t?e.tState:e.state)===0)return;if((t?e.tState:e.state)===l)return O(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)T(e);else if((t?e.tState:e.state)===l){let t=m;m=null,D(()=>O(e,n[0]),!1),m=t}}}function D(e,t){if(m)return e();let n=!1;t||(m=[]),h?n=!0:h=[],g++;try{let t=e();return ce(n),t}catch(e){n||(h=null),m=null,pe(e)}}function ce(e){if(m&&=(le(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,D(()=>{for(let e of n)k(e);for(let t of e){if(t.value=t.tValue,t.owned)for(let e=0,n=t.owned.length;e<n;e++)k(t.owned[e]);t.tOwned&&(t.owned=t.tOwned),delete t.tValue,delete t.tOwned,t.tState=0}w(!1)},!1)}else if(f.running){f.running=!1,f.effects.push.apply(f.effects,h),h=null,w(!0);return}}let n=h;h=null,n.length&&D(()=>s(n),!1),t&&t()}function le(e){for(let t=0;t<e.length;t++)E(e[t])}function ue(t){let r,i=0;for(r=0;r<t.length;r++){let e=t[r];e.user?t[i++]=e:E(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++)E(t[r])}function O(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)&&E(i):e===l&&O(i,t)}}}function de(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&&de(r))}}function k(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--)k(e.tOwned[t]);delete e.tOwned}if(f&&f.running&&e.pure)A(e,!0);else if(e.owned){for(t=e.owned.length-1;t>=0;t--)k(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 A(e,t){if(t||(e.tState=0,f.disposed.add(e)),e.owned)for(let t=0;t<e.owned.length;t++)A(e.owned[t])}function fe(e){return e instanceof Error?e:Error(typeof e==`string`?e:`Unknown error`,{cause:e})}function j(e,t,n){try{for(let n of t)n(e)}catch(e){pe(e,n&&n.owner||null)}}function pe(e,t=d){let n=o&&t&&t.context&&t.context[o],r=fe(e);if(!n)throw r;h?h.push({fn(){j(r,n,t)},state:c}):j(r,n,t)}var me=Symbol(`fallback`);function he(e){for(let t=0;t<e.length;t++)e[t]()}function ge(e,t,n={}){let r=[],a=[],o=[],s=0,c=t.length>1?[]:null;return C(()=>he(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&&(he(o),o=[],r=[],a=[],s=0,c&&=[]),n.fallback&&(r=[me],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 M(e,t){return S(()=>e(t||{}))}var _e=e=>`Stale read from <${e}>.`;function N(e){let t=`fallback`in e&&{fallback:()=>e.fallback};return x(ge(()=>e.each,e.children,t||void 0))}function P(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 _e(`Show`);return n()})):a}return e.fallback},void 0,void 0)}var F=e=>x(()=>e());function ve(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 I=`_$DX_DELEGATE`;function L(e,t,n,r={}){let i;return _(r=>{i=r,t===document?e():V(t,e(),t.firstChild?null:void 0,n)},r.owner),()=>{i(),t.textContent=``}}function R(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 ye(e,t=window.document){let n=t[I]||(t[I]=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,we))}}function z(e,t,n){Ce(e)||(n==null?e.removeAttribute(t):e.setAttribute(t,n))}function B(e,t){Ce(e)||(t==null?e.removeAttribute(`class`):e.className=t)}function be(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 xe(e,t,n){n==null?e.style.removeProperty(t):e.style.setProperty(t,n)}function Se(e,t,n){return S(()=>e(t,n))}function V(e,t,n,r){if(n!==void 0&&!r&&(r=[]),typeof t!=`function`)return H(e,t,r,n);y(r=>H(e,t(),r,n),r)}function Ce(t){return!!e.context&&!e.done&&(!t||t.isConnected)}function we(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 H(e,t,n,r,i){let a=Ce(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=U(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=U(e,n,r)}else if(o===`function`)return y(()=>{let i=t();for(;typeof i==`function`;)i=i();n=H(e,i,n,r)}),()=>n;else if(Array.isArray(t)){let o=[],c=n&&Array.isArray(n);if(Te(o,t,n,i))return y(()=>n=H(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=U(e,n,r),s)return n}else c?n.length===0?Ee(e,o,r):ve(e,n,o):(n&&U(e),Ee(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=U(e,n,r,t);U(e,n,null,t)}else n==null||n===``||!e.firstChild?e.appendChild(t):e.replaceChild(t,e.firstChild);n=t}return n}function Te(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=Te(e,o,s)||i;else if(c===`function`){if(r){for(;typeof o==`function`;)o=o();i=Te(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 Ee(e,t,n=null){for(let r=0,i=t.length;r<i;r++)e.insertBefore(t[r],n)}function U(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 W=/^(\s*)([-*+]|\d+[.)])\s+(.*)$/;function De(e){return G(ke(e.replace(/\r\n/g,`
2
+ `)).split(`
3
+ `))}function G(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>${G(r)}</blockquote>`);continue}if(o.includes(`|`)&&n+1<e.length&&Oe(e[n+1])){let r=K(e[n+1]).map(e=>e.startsWith(`:`)&&e.endsWith(`:`)?`center`:e.endsWith(`:`)?`right`:`left`),i=K(o);n+=2;let s=[];for(;n<e.length&&/\S/.test(e[n])&&e[n].includes(`|`);)s.push(K(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(W.test(o)){t.push(i(r(o.match(W)[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])&&!W.test(e[n])&&!(e[n].includes(`|`)&&n+1<e.length&&Oe(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(W);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])&&!W.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(W);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 K(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 Oe(e){let t=e.trim();if(!t.includes(`|`)||!t.includes(`-`))return!1;let n=K(t);return n.every(e=>/^:?-+:?$/.test(e))&&n.some(e=>e!==``)}function ke(e){return e.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`).replace(/"/g,`&quot;`)}var Ae=`modulepreload`,je=function(e){return`/`+e},Me={},Ne=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=je(t,n),t=s(t),t in Me)return;Me[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`:Ae,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)})},Pe=R(`<br>`),Fe=R(`<span class="badge queued">⏳ <!> queued`),Ie=R(`<span class="badge cron">⏰ `),Le=R(`<span class=sub>ℹ`),Re=R(`<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)">▤`),ze=R(`<details class=reasoning><summary>💭 reasoning</summary><div class=mono>`),Be=R(`<div class=content>`),Ve=R(`<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…`),He=R(`<div class=feed>`),Ue=R(`<button class=jump>↓ `),We=R(`<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>`),Ge=R(`<div class=cmds>`),Ke=R(`<div class=composer><form><textarea rows=1></textarea><button type=submit>send</button></form><div class=hint>`),qe=R(`<h3>🎛 session`),Je=R(`<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>/`),Ye=R(`<h3>🧦 model`),Xe=R(`<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=R(`<h3>⏯ controls`),Qe=R(`<button class=danger title="interrupt: aborts the current LLM call; the running tool finishes first">■ stop`),$e=R(`<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`),et=R(`<div class=ctrlrow><label title="after each round the agent keeps working toward its goal without waiting for input; sending a prompt also starts an idle agent"><input type=checkbox>auto-continue</label><span class=muted>loops while the goal is active`),tt=R(`<h3>🎯 goal <span>`),nt=R(`<form style=display:flex;flex-direction:column;gap:6px;margin-bottom:6px><textarea id=goal-input rows=3 placeholder="set new goal…"style="background:var(--bg-darkest);border:none;border-radius:6px;padding:6px 8px;color:var(--fg);font:inherit;width:100%;resize:vertical"></textarea><div style=display:flex;justify-content:flex-end;align-items:center;gap:10px><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:4px;font-size:11.5px;white-space:nowrap;cursor:pointer><input id=goal-notify type=checkbox checked> notify agent</label><button type=submit style="background:var(--acc);border:none;border-radius:6px;color:#fff;padding:4px 12px;cursor:pointer">✓ save`),rt=R(`<div class=card>`),it=R(`<div class=muted style=font-size:11px;margin-top:4px>stored with the session · the model reads it via get_goal() ·`),at=R(`<h3>✅ tasks <span class=muted style=text-transform:none;letter-spacing:0>· todo.md, editable by you and the agent`),ot=R(`<textarea id=todo-input class=mono rows=5 placeholder="- task one
6
+ - task two"title="shared with the agent — it may check items off via set_todo; your unsaved edits win until you save"style="width:100%;background:var(--bg-darkest);border:none;border-radius:6px;padding:6px 8px;color:var(--fg);font-family:ui-monospace,Menlo,monospace;font-size:12.5px;resize:vertical">`),st=R(`<div style=display:flex;justify-content:flex-end;align-items:center;gap:10px;margin-top:4px><label class=muted title="queue a harness prompt telling the agent the task list changed"style=display:flex;align-items:center;gap:4px;font-size:11.5px;white-space:nowrap;cursor:pointer><input id=todo-notify type=checkbox checked> notify agent</label><button style="background:var(--ok);border:none;border-radius:6px;color:#fff;padding:4px 12px;cursor:pointer">✓ save tasks`),ct=R(`<h3>📈 progress`),lt=R(`<h3>📊 runtime`),ut=R(`<div class="card muted">turns <!> · tools <!> · compacted <!>
7
+ tokens in/out <!>/`),dt=R(`<h3>🌿 branches <span class=muted style=text-transform:none;letter-spacing:0>· click to filter the feed`),ft=R(`<h3>⏰ schedule <span class=muted style=text-transform:none;letter-spacing:0>· cron tasks, all agents · edit in settings`),pt=R(`<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>`),mt=R(`<span class=mini-cron>⏰`),ht=R(`<span title="goal done">✓`),gt=R(`<div><span></span><span>`),_t=R(`<div class=muted style=display:grid;place-items:center;height:100%>select an agent`),vt=R(`<div class=muted style=display:grid;place-items:center;height:100%>no events yet — say something or press ▶ start`),yt=R(`<div class="content muted">thinking…`),bt=R(`<div class=cmdrow><b></b><span class=muted>`),xt=R(`<option>`),St=R(`<button class=runbtn title="run toward the goal (starts the loop)">▶ start`),Ct=R(`<div class=muted>none yet — the harness asks for a report after real activity, and the agent can report_progress anytime`),wt=R(`<div class=progrow><b>recent</b><span>`),Tt=R(`<div class="progrow warn"><b>⚠ problems</b><span>`),Et=R(`<div class=progrow><b>next</b><span>`),Dt=R(`<div class=progrow><b>goal</b><span>`),Ot=R(`<div class="card prog"><div class=progrow><b>doing</b><span></span></div><div class="meta muted">`),kt=R(`<div><span></span><span> events`),At=R(`<div class=muted>no scheduled tasks — add them in ⚙ settings ("scheduled tasks")`),jt=R(`<span title="runs on a forked branch so chatter stays off the main line">⑂`),Mt=R(`<div><div class=sched-top><b></b><span class=muted>@</span></div><div class="sched-meta mono"> → next </div><div class="sched-prompt muted">`),Nt=R(`<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)`),Pt=R(`<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`),Ft=R(`<div class=mono>`),It=R(`<pre class="mono toolbody">`),Lt=R(`<div class=meta>ms`),Rt=R(`<div class=meta>waiting for output…`),zt=R(`<div class=meta>`),q=R(`<div class=meta>writing…`),Bt=R(`<pre class="mono toolbody del">`),Vt=R(`<pre class="mono toolbody add">`),J=R(`<div class=meta> · <!>ms`),Ht=R(`<div class=meta>applying…`),Ut=R(`<pre class="mono toolbody patch">`),Wt=R(`<div>`),Gt=R(`<div class=meta>validating…`),Kt=R(`<div class=meta><a target=_blank rel="noopener noreferrer">open ↗`),qt=R(`<div class=meta>loading…`),Jt=R(`<div class=meta>bundled: `),Yt=R(`<div class=meta>saving…`),Xt=R(`<details><summary><b>⚙ </b><span class=meta>`),Zt=R(`<div class=divider-msg>⑂ forked from <!> → `),Qt=R(`<div class=divider-msg>🎯 goal <!>: `),$t=R(`<div class=divider-msg>✅ tasks updated (<!>)`),en=R(`<div> → `),tn=R(`<div class=avatar>`),nn=R(`<button class=editbtn title="edit this prompt — forks the conversation here (later events are dropped or summarized)">✎ edit`),rn=R(`<div class=msg-head><span class=author></span><span class=ts></span><span class=ts>`),an=R(`<div><div class=msg-body>`),on=R(`<span style=width:38px>`),Y=R(`<div class=interrupted>⚠ interrupted — partial output kept`),sn=R(`<div class=msgfoot><span>copy summary`),cn=R(`<details><summary><span class=meta></span></summary><div class=mono></div><div class=meta>ms`),X=R(`<div class=meta>⚠ `),ln=R(`<div class=meta>→ `),un=R(`<div class=embed style=border-color:var(--ok)><div>📈 `),dn=R(`<div class="embed fail"><div class=mono>⚠ `),fn=R(`<div class="content muted">`),pn=R(`<button class=copybtn title="copy to clipboard">`),mn=R(`<div class=overlay><div class=modal><div class=modal-head><b></b><button class=iconbtn>✕`),hn=R(`<span style=color:var(--err);font-size:13px>`),gn=R(`<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`),_n=R(`<div class=direntry>📁 `),vn=R(`<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`),yn={prompt:{name:`you`,icon:`🟧`,color:`#faa81a`},user:{name:`you`,icon:`🟧`,color:`#faa81a`},message:{name:`agent`,icon:`🫖`,color:`#5865f2`},progress:{name:`progress`,icon:`📈`,color:`#3ba55d`}},bn={name:`harness`,icon:`📣`,color:`#3ba55d`},xn=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`?yn.prompt:t.startsWith(`scheduler:`)?{name:t.slice(10),icon:`📣`,color:`#3ba55d`}:bn}return yn[e.type]??{name:e.type,icon:`•`,color:`#9298a5`}},Sn=new Set([`user`,`message`,`prompt`,`tool_call`,`tool_result`,`progress`,`state`,`error`,`fork`,`goal`,`todo`]),Cn=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 wn=location.hash.match(/[#&]token=([^&]+)/);wn&&(localStorage.setItem(`teapot.token`,decodeURIComponent(wn[1])),history.replaceState(null,``,location.pathname+location.search));var Tn=()=>{let e=localStorage.getItem(`teapot.token`);return e?`?token=${encodeURIComponent(e)}`:``};function En(){let[e,t]=v([]),[n,r]=v(null),[i,a]=v([]),[o,s]=v(0),[c,l]=v([]),[u,d]=v(null),[f,p]=v(``),[m,h]=v(localStorage.getItem(`teapot.autostart`)!==`0`),g=e=>{h(e),localStorage.setItem(`teapot.autostart`,e?`1`:`0`)},[_,S]=v({providers:{}}),[te,w]=v(!1),[ne,re]=v(!1),[ie,ae]=v(localStorage.getItem(`teapot.panel`)===null?window.innerWidth>1100:localStorage.getItem(`teapot.panel`)===`1`),T=()=>{let e=!ie();ae(e),localStorage.setItem(`teapot.panel`,e?`1`:`0`)},[oe,se]=v(``),[E,D]=v(``),[ce,le]=v([]),ue=()=>Object.keys(_().providers??{});async function O(e){if(e)try{let t=await Z(`/api/models?provider=${encodeURIComponent(e)}`);le(t.models??[])}catch{le([])}}b(()=>{let e=L();e&&(se(e.provider||_().defaultProvider||ue()[0]||``),D(``),O(oe()))});let[de,k]=v(!0),[A,fe]=v(0),[j,pe]=v(null),[me,he]=v(``),ge;b(()=>{if(!j()){clearTimeout(ge),ge=void 0,he(``);return}ge||=setTimeout(()=>{ge=void 0,he(j()?.text??``)},60)}),C(()=>clearTimeout(ge));let _e=x(()=>{let e=new Map,t=new Set,n=new Map;for(let r of i())if(Sn.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}}),ve=x(()=>{let{consumed:e}=_e(),t=i().filter(t=>Sn.has(t.type)?t.type===`tool_result`?!e.has(t.id):t.type!==`message`||String(t.data?.content??``).trim()!==``||String(t.data?.reasoning??``).trim()!==``||!!t.data?.final:!1),n=xe().filter(e=>!t.some(t=>t.type===`prompt`&&t.data?.source===`user`&&t.data?.text===e.text&&new Date(t.ts).getTime()>=e.at-1e3)).map(e=>({id:e.id,seq:0,ts:new Date(e.at).toISOString(),session:L()?.session??``,branch:L()?.branch??`br0`,parent:null,type:`prompt`,data:{source:`user`,text:e.text,pending:!0}}));return[...t,...n]}),I=()=>Z(`/api/config`).then(S).catch(()=>{}),L=x(()=>e().find(e=>e.id===n())),[R,ye]=v(null),[xe,Ce]=v([]),[we,H]=v(``),[Te,Ee]=v(!1),U=``;b(()=>{let t=n(),r=e().find(e=>e.id===t)?.todo??``;t&&t!==U?(U=t,Ee(!1),H(r)):t&&!Te()&&H(r)});let W=async()=>{let e=document.getElementById(`todo-notify`)?.checked??!0;if(n())try{await Z(`/api/agents/${n()}/todo`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({text:we(),notify:e})}),Ee(!1),Y(`tasks saved${e&&we().trim()?` & notification queued`:``}`),G()}catch(e){Y(`save failed: ${e.message}`)}},G=()=>Z(`/api/agents`).then(e=>t(e.agents)).catch(()=>{}),K=()=>Z(`/api/metrics`).then(d).catch(()=>{}),[Oe,ke]=v([]),Ae=()=>Z(`/api/tasks`).then(e=>ke(e.tasks)).catch(()=>{}),je=e=>Oe().filter(t=>t.agent===e),[Me,Ft]=v(null);async function It(e){try{let t=Me(),[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(n.total??n.events.length),l(r.branches)}catch{}}function Lt(){return document.querySelector(`.feed`)}function Rt(){let e=Lt();return!e||e.scrollHeight-e.scrollTop-e.clientHeight<80}function zt(e=!1){let t=Lt();t&&(e||de())&&(t.scrollTop=t.scrollHeight,fe(0))}async function q(e,t=!0){r(e),pe(null),Ft(null),Ce([]),localStorage.setItem(`teapot.session`,e),Gt(e,t),Z(`/api/agents/${e}/load`,{method:`POST`}).then(G).catch(()=>{}),await It(e),requestAnimationFrame(()=>zt(!0))}let[Bt,Vt]=v(!1),J=null,Ht=null;C(()=>J?.close());function Ut(){let e=location.protocol===`https:`?`wss://`:`ws://`;J=new WebSocket(`${e}${location.host}/api/ws${Tn()}`),J.onopen=()=>Vt(!0),J.onclose=()=>{Vt(!1),setTimeout(Ut,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()&&pe({text:a.text??``,reasoning:a.reasoning??``});return}a.kind===`event`&&t.has(a.event?.type)||(Ht||=setTimeout(async()=>{if(Ht=null,await G(),await K(),n()){let e=i().at(-1)?.id,t=o(),a=Date.now();await It(n()),i().at(-1)?.id!==e&&(r?.id===n()&&r.at>=a||pe(null),Rt()?zt(!0):fe(A()+Math.max(0,o()-t))),Ce(e=>e.filter(e=>!i().some(t=>t.type===`prompt`&&t.data?.text===e.text&&new Date(t.ts).getTime()>=e.at-1e3)))}},400))}}}let Wt=()=>decodeURIComponent(location.pathname.split(`/`)[2]??``);function Gt(e,t=!0){let n=`/session/${encodeURIComponent(e)}`;t?history.pushState(null,``,n):history.replaceState(null,``,n)}window.addEventListener(`popstate`,()=>{let t=Wt();t&&e().some(e=>e.id===t)&&t!==n()&&q(t,!1)}),b(()=>{let e=L();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(te()){w(!1);return}if(ne()){re(!1);return}let e=L();if(e?.status===`running`){Z(`/api/agents/${e.id}/stop`,{method:`POST`}).then(G);return}ie()&&window.innerWidth<=1100&&ae(!1);return}if(!(te()||ne())){if(t.key===`/`)t.preventDefault(),document.querySelector(`.composer textarea`)?.focus();else if(t.key===`d`)T();else if(t.key===`t`)Jt();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[Kt,qt]=v(localStorage.getItem(`teapot.term`)===`1`),Jt=()=>{let e=!Kt();qt(e),localStorage.setItem(`teapot.term`,e?`1`:`0`)},Yt=null,Xt=null,Zt=null,Qt=null,$t={cols:0,rows:0},en=null;function tn(){Qt?.disconnect(),Qt=null,Zt?.close(),Zt=null,Xt?.dispose(),Xt=null}function nn(e){tn(),Yt&&Promise.all([Ne(()=>import(`./xterm-C3BHN0de.js`),[]),Ne(()=>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(Yt),i.fit(),Xt=r;let a=location.protocol===`https:`?`wss://`:`ws://`,o=new WebSocket(`${a}${location.host}/api/agents/${e}/term${Tn()}`);Zt=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!==$t.cols||t!==$t.rows)&&o.readyState===WebSocket.OPEN&&($t={cols:e,rows:t},o.send(JSON.stringify({kind:`resize`,cols:e,rows:t})))};Qt=new ResizeObserver(()=>{en&&clearTimeout(en),en=setTimeout(s,300)}),Qt.observe(Yt),setTimeout(s,50)})}b(()=>{let e=n();!Kt()||!e?tn():requestAnimationFrame(()=>e&&nn(e))}),C(tn),ee(()=>{I(),G().then(()=>{let t=Wt()||localStorage.getItem(`teapot.session`)||``,n=e().find(e=>e.id===t)??e()[0];n&&q(n.id,!1)}),K(),Ae(),Ut();let t=setInterval(()=>{K(),Ae()},3e4);C(()=>clearInterval(t))});let[rn,an]=v(``),on,Y=e=>{an(e),clearTimeout(on),on=setTimeout(()=>an(``),3200)},sn=[{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`}],cn=()=>{let e=f();return!e.startsWith(`/`)||e.includes(` `)||e.includes(`
8
+ `)?[]:sn.filter(t=>t.cmd.slice(1).startsWith(e.slice(1).toLowerCase()))},X,ln=()=>{X&&(X.style.height=`auto`,X.style.height=`${Math.min(X.scrollHeight,160)}px`)};b(()=>{f(),ln()});let un=async e=>{e.preventDefault();let t=n(),r=f().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(G);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){Y(`usage: /goal <text>`);return}await a(`/goal`,{text:i,notify:!0}),Y(`goal saved & notification queued`)}else{Y(`unknown command "${n}" — /start /stop /fork /goal`);return}p(``)}catch(e){Y(`/${n} failed: ${e.message}`)}return}p(``);try{await Z(`/api/agents/${t}/prompt`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({text:r,start:m()})}),Ce(e=>[...e,{id:`@p${Date.now()}${Math.random().toString(36).slice(2,6)}`,text:r,at:Date.now()}])}catch(e){p(r),console.error(`send failed:`,e)}}},dn=e=>()=>n()&&Z(`/api/agents/${n()}${e}`,{method:`POST`}).then(G),fn=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=``,G())};return[(()=>{var i=pt(),o=i.firstChild,s=o.firstChild,l=s.firstChild.nextSibling,d=l.nextSibling.firstChild,h=d.nextSibling,v=s.nextSibling,b=v.nextSibling,x=o.nextSibling,S=x.nextSibling;return d.$$click=()=>{I(),w(!0)},h.$$click=()=>{I(),re(!0)},V(v,M(N,{get each(){return e()},children:e=>(()=>{var t=gt(),r=t.firstChild,i=r.nextSibling;return t.$$click=()=>q(e.id),V(i,()=>e.id),V(t,M(P,{get when(){return je(e.id).length>0},get children(){var t=mt();return y(()=>z(t,`title`,je(e.id).map(e=>`${e.id}: ${e.schedule}`).join(`
9
+ `))),t}}),null),V(t,M(P,{get when(){return e.goal.status===`done`},get children(){return ht()}}),null),y(i=>{var a=`agent-item`+(e.id===n()?` sel`:``),o=`dot ${e.status}`;return a!==i.e&&B(t,i.e=a),o!==i.t&&B(r,i.t=o),i},{e:void 0,t:void 0}),t})()})),V(b,M(P,{get when(){return u()},get children(){return[`master rss `,F(()=>u().rssMb),`MB · heap `,F(()=>u().heapUsedMb),`MB`,Pe(),`load1 `,F(()=>u().loadavg1),` · up `,F(()=>Math.floor(u().uptimeSec/60)),`m`]}})),V(x,M(P,{get when(){return L()},get fallback(){return _t()},get children(){return[(()=>{var e=Re(),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 V(t,()=>L().id),V(n,()=>L().status),V(e,M(P,{get when(){return(L().pendingPrompts??0)>0},get children(){var e=Fe(),t=e.firstChild.nextSibling;return t.nextSibling,V(e,()=>L().pendingPrompts,t),y(()=>z(e,`title`,`${L().pendingPrompts} prompt(s) waiting — the agent picks them up at the next turn boundary`)),e}}),r),V(e,M(P,{get when(){return je(L().id).length>0},get children(){var e=Ie();return e.firstChild,V(e,()=>je(L().id).length,null),y(()=>z(e,`title`,`scheduled tasks:\n${je(L().id).map(e=>`${e.schedule} · ${e.id}${e.forked?` (forked)`:``}`).join(`
10
+ `)}`)),e}}),r),V(r,()=>L().model,i),V(r,()=>L().session,a),V(r,()=>L().branch,o),V(r,()=>L().stats.turns,s),V(r,()=>L().stats.toolCalls,null),V(c,M(P,{get when(){return L().statusReason},get children(){var e=Le();return y(()=>z(e,`title`,L().statusReason)),e}}),l),l.$$click=Jt,u.$$click=T,y(()=>B(n,`badge ${L().status}`)),e})(),(()=>{var e=He();return e.addEventListener(`scroll`,()=>{let e=Rt();e&&A()&&fe(0),k(e)}),V(e,M(P,{get when(){return ve().length>0},get fallback(){return vt()},get children(){return[M(N,{get each(){return ve()},children:(e,t)=>M(On,{e,get prev(){return ve()[t()-1]},get res(){return _e().resFor.get(e.id)},get onEdit(){return e.type===`prompt`&&e.data?.source===`user`?()=>ye({eventId:e.id,text:String(e.data?.text??``)}):void 0}})}),M(P,{get when(){return j()},get children(){var e=Ve(),t=e.firstChild.nextSibling;return t.firstChild,V(t,M(P,{get when(){return j().reasoning},get children(){var e=ze(),t=e.firstChild.nextSibling;return V(t,()=>j().reasoning),e}}),null),V(t,M(P,{get when(){return me()},get fallback(){return yt()},get children(){var e=Be();return y(()=>e.innerHTML=De(me()+`▍`)),e}}),null),e}})]}})),e})(),M(P,{get when(){return!de()||A()>0},get children(){var e=Ue();return e.firstChild,e.$$click=()=>zt(!0),V(e,(()=>{var e=F(()=>A()>0);return()=>e()?`${A()} new message${A()>1?`s`:``}`:`jump to present`})(),null),e}}),M(P,{get when(){return F(()=>!!Kt())()&&L()},get children(){var e=We(),t=e.firstChild,n=t.firstChild,r=n.firstChild.nextSibling,i=n.nextSibling,a=t.nextSibling;return V(r,()=>L().workspace),i.$$click=Jt,Se(e=>Yt=e,a),e}}),(()=>{var e=Ke(),t=e.firstChild,n=t.firstChild,r=t.nextSibling;V(e,M(P,{get when(){return cn().length>0},get children(){var e=Ge();return V(e,M(N,{get each(){return cn()},children:e=>(()=>{var t=bt(),n=t.firstChild,r=n.nextSibling;return t.$$click=()=>p(e.cmd+` `),V(n,()=>e.cmd),V(r,()=>e.desc),y(()=>z(t,`title`,e.desc)),t})()})),e}}),t),t.addEventListener(`submit`,un),n.$$keydown=e=>{e.key===`Enter`&&!e.shiftKey&&(e.preventDefault(),un(e))},n.$$input=e=>{p(e.currentTarget.value),ln()};var i=X;return typeof i==`function`?Se(i,n):X=n,V(r,()=>rn()||`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(()=>z(n,`placeholder`,`message #${L().id} — / for commands`)),y(()=>n.value=f()),e})()]}})),V(S,M(P,{get when(){return L()},get children(){return[qe(),(()=>{var e=Je(),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 V(n,()=>L().id),V(r,()=>L().status),V(a,()=>L().workspace),V(o,()=>L().session,s),V(o,()=>L().branch,null),y(e=>{var t=`badge ${L().status}`,n=L().workspace;return t!==e.e&&B(r,e.e=t),n!==e.t&&z(a,`title`,e.t=n),e},{e:void 0,t:void 0}),e})(),Ye(),(()=>{var e=Xe(),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=>{se(e.currentTarget.value),O(e.currentTarget.value)}),V(t,M(N,{get each(){return ue()},children:e=>(()=>{var t=xt();return t.value=e,V(t,e,null),V(t,()=>e===_().defaultProvider?` ★`:``,null),t})()})),i.$$input=e=>D(e.currentTarget.value),V(a,M(N,{get each(){return ce()},children:e=>(()=>{var t=xt();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:oe(),model:E().trim()||void 0})}),t.textContent=`✓ applied`,G()}catch(e){alert(`model switch failed: ${e.message}`)}finally{setTimeout(()=>{t.textContent=`apply`,t.disabled=!1},1200)}},V(s,()=>L().model,null),V(s,M(P,{get when(){return ce().length},get children(){return[` · `,F(()=>ce().length),` models loaded`]}}),null),y(()=>z(i,`placeholder`,L().model)),y(()=>t.value=oe()),y(()=>i.value=E()),e})(),Ze(),(()=>{var i=$e(),o=i.firstChild,s=o.nextSibling;return V(i,M(P,{get when(){return L().status===`running`},get fallback(){return(()=>{var e=St();return be(e,`click`,dn(`/start`),!0),e})()},get children(){var e=Qe();return be(e,`click`,dn(`/stop`),!0),e}}),o),o.$$click=()=>Z(`/api/agents/${L().id}/fork`,{method:`POST`,headers:{"content-type":`application/json`},body:`{}`}).then(()=>q(L().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=et(),t=e.firstChild.firstChild;return t.addEventListener(`change`,e=>g(e.currentTarget.checked)),y(()=>t.checked=m()),e})(),(()=>{var e=tt(),t=e.firstChild.nextSibling;return V(t,()=>L().goal.status),y(()=>B(t,`badge ${L().goal.status===`done`?`done`:``}`)),e})(),(()=>{var e=nt();return e.addEventListener(`submit`,fn),e})(),(()=>{var e=rt();return V(e,()=>L().goal.text||`no goal set — the agent has nothing to auto-continue toward`),e})(),(()=>{var e=it();return e.firstChild,V(e,M(P,{get when(){return F(()=>!!L().goal.text)()&&L().goal.status===`active`},children:` auto-continue keeps it working until this is done`}),null),V(e,M(P,{get when(){return!L().goal.text},children:` set one and tick ▶ start to begin`}),null),e})(),at(),(()=>{var e=ot();return e.$$input=e=>{H(e.currentTarget.value),Ee(!0)},y(()=>e.value=we()),e})(),(()=>{var e=st(),t=e.firstChild.nextSibling;return t.$$click=W,e})(),ct(),M(P,{get when(){return L().latestProgress},get fallback(){return Ct()},children:e=>(()=>{var t=Ot(),n=t.firstChild,r=n.firstChild.nextSibling,i=n.nextSibling;return V(r,()=>e().doing),V(t,M(P,{get when(){return e().recent},get children(){var t=wt(),n=t.firstChild.nextSibling;return V(n,()=>e().recent),t}}),i),V(t,M(P,{get when(){return e().problems},get children(){var t=Tt(),n=t.firstChild.nextSibling;return V(n,()=>e().problems),t}}),i),V(t,M(P,{get when(){return e().next},get children(){var t=Et(),n=t.firstChild.nextSibling;return V(n,()=>e().next),t}}),i),V(t,M(P,{get when(){return e().goalStatus},get children(){var t=Dt(),n=t.firstChild.nextSibling;return V(n,()=>e().goalStatus),t}}),i),V(i,()=>An(e().ts)),t})()}),lt(),(()=>{var e=ut(),t=e.firstChild.nextSibling,n=t.nextSibling.nextSibling,r=n.nextSibling.nextSibling,i=r.nextSibling.nextSibling;return i.nextSibling,V(e,()=>L().stats.turns,t),V(e,()=>L().stats.toolCalls,n),V(e,()=>L().stats.compactions??0,r),V(e,()=>jn(L().stats.inputTokens),i),V(e,()=>jn(L().stats.outputTokens),null),V(e,M(P,{get when(){return L().stats.cachedInputTokens>0},get children(){return[` · `,`cached `,F(()=>Math.round(L().stats.cachedInputTokens/Math.max(1,L().stats.inputTokens)*100)),`% (`,F(()=>jn(L().stats.cachedInputTokens)),`)`]}}),null),V(e,M(P,{get when(){return L().ctx},children:e=>[`
11
+ `,`context ~`,F(()=>jn(e().usedTokens)),` tok`,M(P,{get when(){return e().window},get children(){return[` · `,F(()=>Math.min(999,Math.round(e().usedTokens/e().window*100))),`% of `,F(()=>jn(e().window))]}}),`
12
+ `,`compaction at ~`,F(()=>jn(e().compactAt)),` tok (older turns summarized)`]}),null),e})(),dt(),M(N,{get each(){return c()},children:e=>(()=>{var t=kt(),r=t.firstChild,i=r.nextSibling,a=i.firstChild;return t.$$click=()=>{let t=Me()===e.branch?null:e.branch;Ft(t),n()&&It(n())},V(r,()=>e.branch,null),V(r,()=>e.branch===L().branch?` (current)`:``,null),V(i,()=>e.events,a),y(n=>{var r=`branch-row`+(e.branch===L().branch||e.branch===Me()?` cur`:``),i=e.branch===Me()?`click to show all branches again`:`show only ${e.branch}`;return r!==n.e&&B(t,n.e=r),i!==n.t&&z(t,`title`,n.t=i),n},{e:void 0,t:void 0}),t})()}),ft(),M(P,{get when(){return Oe().length>0},get fallback(){return At()},get children(){return M(N,{get each(){return Oe()},children:e=>(()=>{var t=Mt(),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),V(i,()=>e.id),V(a,()=>e.agent,null),V(r,M(P,{get when(){return e.forked},get children(){return jt()}}),null),V(o,()=>e.schedule,s),V(o,(()=>{var t=F(()=>!!e.next);return()=>t()?An(e.next):`—`})(),null),V(o,(()=>{var t=F(()=>!!e.last);return()=>t()?` · last ${An(e.last)}`:` · never ran`})(),null),V(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&&B(t,r.e=i),a!==r.t&&z(t,`title`,r.t=a),r},{e:void 0,t:void 0}),t})()})}})]}})),y(e=>{var t=`layout`+(ie()?``:` right-hidden`),n=`conn`+(Bt()?` ok`:``),r=Bt()?`live (websocket)`:`reconnecting…`,a=`rightbar`+(ie()?` open`:``);return t!==e.e&&B(i,e.e=t),n!==e.t&&B(l,e.t=n),r!==e.a&&z(l,`title`,e.a=r),a!==e.o&&B(S,e.o=a),e},{e:void 0,t:void 0,a:void 0,o:void 0}),i})(),M(P,{get when(){return te()},get children(){return M(Pn,{get providers(){return Object.keys(_().providers??{})},onClose:()=>w(!1),onCreated:e=>{w(!1),G(),q(e)}})}}),M(P,{get when(){return ne()},get children(){return M(Fn,{get cfg(){return _()},onClose:()=>re(!1),onSaved:()=>{I(),Ae()}})}}),M(P,{get when(){return R()},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 M(Nn,{title:`edit prompt — forks the conversation`,onClose:()=>ye(null),get children(){var t=Pt(),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()})}),ye(null),G(),n()&&await q(n())}catch(e){alert(`edit failed: ${e.message}`)}}),V(t,M(P,{get when(){return r()>0},get children(){var e=Nt(),t=e.firstChild,n=t.firstChild,i=t.nextSibling,s=i.firstChild,c=i.nextSibling.firstChild;return V(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=()=>ye(null),y(()=>i.value=e().text),t}})}})]}function Dn(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=Ft();return V(e,()=>Q(JSON.stringify(r.args??{},null,1),2e3)),e})(),l=e=>String(r.args?.[e]??``),u=(e,t=1500)=>(()=>{var n=It();return V(n,()=>Q(e,t)),n})(),d=(e=4e3)=>n?[F(()=>u(a(),e)),(()=>{var e=Lt(),t=e.firstChild;return V(e,()=>n.data?.durationMs,t),V(e,()=>n.data?.ok===!1?` · FAILED`:``,null),V(e,M(Mn,{get text(){return a()}}),null),e})()]:Rt();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=[F(()=>F(()=>e!==o.slice(2))()?u(e,800):null),F(()=>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=[F(()=>u(e)),n?(()=>{var e=zt();return V(e,()=>$(a(),160)),e})():q()];break}case`edit_file`:o=l(`path`)||`(no path)`,s=r.args?.replace_all===!0?`replace all`:`unique spot`,c=[(()=>{var e=Bt();return V(e,()=>Q(`- `+l(`old_text`),900)),e})(),(()=>{var e=Vt();return V(e,()=>`+ `+Q(l(`new_text`),900)),e})(),n?(()=>{var e=J(),t=e.firstChild,r=t.nextSibling;return r.nextSibling,V(e,()=>$(a(),120),t),V(e,()=>n.data?.durationMs,r),e})():Ht()];break;case`apply_patch`:{let e=l(`patch`).split(`
13
+ `).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=Ut();return V(t,()=>e.map(e=>{let t=e.startsWith(`+`)?` add`:e.startsWith(`-`)?` del`:/^\*\*\*|^@@/.test(e)?` meta`:``;return(()=>{var n=Wt();return B(n,`pline`+t),V(n,(()=>{var t=F(()=>e.length>240);return()=>t()?e.slice(0,240)+`…`:e})()),n})()})),t})(),n?(()=>{var e=zt();return V(e,()=>$(a().split(`
14
+ `)[0]??``,140),null),V(e,()=>n.data?.ok===!1?` · FAILED`:``,null),e})():Gt()];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=Kt(),t=e.firstChild;return y(()=>z(t,`href`,l(`url`))),e})(),F(()=>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=Be();return y(()=>t.innerHTML=De(e)),t})(),(()=>{var e=Lt(),t=e.firstChild;return V(e,()=>n.data?.durationMs,t),e})()]:qt();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=[F(()=>F(()=>!!e.length)()?(()=>{var t=Jt();return t.firstChild,V(t,()=>e.join(`, `),null),t})():null),n?(()=>{var e=J(),t=e.firstChild,r=t.nextSibling;return r.nextSibling,V(e,()=>$(a(),160),t),V(e,()=>n.data?.durationMs,r),e})():Yt()];break}}}catch{}return(()=>{var e=Xt(),t=e.firstChild.firstChild;t.firstChild;var r=t.nextSibling;return z(e,`title`,`${i}${s?` — `+s:``}`),V(t,o,null),V(r,n?s||``:`running…`),V(e,c,null),y(()=>B(e,`embed`+(n?n.data?.ok===!1?` fail`:` done`:` running`))),e})()}function On(e){let t=e.e,n=xn(t),r=e.prev&&e.prev.type===t.type&&xn(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=Zt(),r=n.firstChild.nextSibling;return r.nextSibling,V(n,()=>String(e.fromBranch??`?`),r),V(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,V(t,()=>String(e.event??``),r),V(t,n,null),t})()}return t.type===`todo`?(()=>{var e=$t(),n=e.firstChild.nextSibling;return n.nextSibling,V(e,()=>String(t.data?.by??`human`),n),e})():t.type===`state`?t.data.from===t.data.to?null:(()=>{var e=en(),n=e.firstChild;return V(e,()=>t.data.from,n),V(e,()=>t.data.to,null),V(e,(()=>{var e=F(()=>!!t.data.reason);return()=>e()?` — ${t.data.reason}`:``})(),null),y(()=>B(e,`divider-msg`+(t.data.to===`error`?` err`:``))),e})():(()=>{var i=an(),a=i.firstChild;return V(i,M(P,{when:!r,get fallback(){return on()},get children(){var e=tn();return V(e,()=>n.icon),y(t=>{var r=n.color+`33`,i=`1px solid ${n.color}66`;return r!==t.e&&xe(e,`background`,t.e=r),i!==t.t&&xe(e,`border`,t.t=i),t},{e:void 0,t:void 0}),e}}),a),V(a,M(P,{when:!r,get children(){var r=rn(),i=r.firstChild,a=i.nextSibling,o=a.nextSibling;return V(i,()=>n.name),V(a,(()=>{var e=F(()=>!!t.data?.pending);return()=>e()?`pending…`:Cn(t.ts)})()),V(o,()=>t.branch),V(r,M(P,{get when(){return e.onEdit},get children(){var t=nn();return t.$$click=t=>{t.stopPropagation(),e.onEdit()},t}}),null),y(e=>xe(i,`color`,n.color)),r}}),null),V(a,M(kn,{e:t,get res(){return e.res}}),null),y(()=>B(i,`msg`+(r?` grouped`:``)+(t.data?.pending?` pending`:``))),i})()}function kn(e){let t=e.e;switch(t.type){case`prompt`:return(()=>{var e=Be();return y(()=>e.innerHTML=De(String(t.data.text??``))),e})();case`message`:return[M(P,{get when(){return F(()=>typeof t.data.reasoning==`string`)()&&t.data.reasoning.trim()},get children(){var e=ze(),n=e.firstChild.nextSibling;return V(n,()=>String(t.data.reasoning)),e}}),(()=>{var e=Be();return y(()=>e.innerHTML=De(String(t.data.content??``))),e})(),M(P,{get when(){return t.data.interrupted},get children(){return Y()}}),M(P,{get when(){return t.data.final},get children(){var e=sn(),n=e.firstChild;return V(e,M(Mn,{get text(){return String(t.data.content??``)}}),n),e}})];case`tool_call`:return M(Dn,{e:t,get res(){return e.res}});case`tool_result`:{let e=String(t.data.result);return(()=>{var n=cn(),r=n.firstChild,i=r.firstChild,a=r.nextSibling,o=a.nextSibling,s=o.firstChild;return V(i,()=>$(e,120)),V(r,M(Mn,{text:e}),null),V(a,()=>Q(e,4e3)),V(o,()=>t.data.durationMs,s),V(o,()=>t.data.ok?``:` · FAILED`,null),y(()=>B(n,`embed`+(t.data.ok?``:` fail`))),n})()}case`progress`:return(()=>{var e=un(),n=e.firstChild;return n.firstChild,V(n,()=>String(t.data.doing??``),null),V(e,M(P,{get when(){return t.data.recent},get children(){var e=zt();return V(e,()=>String(t.data.recent)),e}}),null),V(e,M(P,{get when(){return t.data.problems},get children(){var e=X();return e.firstChild,V(e,()=>String(t.data.problems),null),e}}),null),V(e,M(P,{get when(){return t.data.next},get children(){var e=ln();return e.firstChild,V(e,()=>String(t.data.next),null),e}}),null),e})();case`error`:return(()=>{var e=dn(),n=e.firstChild;return n.firstChild,V(n,()=>String(t.data.message??``),null),e})();default:return(()=>{var e=fn();return V(e,()=>Q(JSON.stringify(t.data),200)),e})()}}function Q(e,t){return e.length>t?e.slice(0,t)+` …`:e}function An(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 jn(e){return e>=1e9?`${+(e/1e9).toFixed(1)}b`:e>=1e6?`${+(e/1e6).toFixed(1)}m`: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 Mn(e){let[t,n]=v(!1);return(()=>{var r=pn();return r.$$click=t=>{t.stopPropagation(),navigator.clipboard.writeText(e.text).then(()=>{n(!0),setTimeout(()=>n(!1),900)})},V(r,()=>t()?`✓`:`⧉`),r})()}function Nn(e){return(()=>{var t=mn(),n=t.firstChild,r=n.firstChild.firstChild,i=r.nextSibling;return t.$$click=t=>t.target===t.currentTarget&&e.onClose(),V(r,()=>e.title),be(i,`click`,e.onClose,!0),V(n,()=>e.children,null),t})()}function Pn(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)}ee(()=>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 M(Nn,{title:`new agent`,get onClose(){return e.onClose},get children(){var i=gn(),f=i.firstChild,h=f.firstChild.nextSibling.firstChild,g=h.nextSibling,_=g.nextSibling,v=f.nextSibling,b=v.nextSibling,x=b.firstChild,S=x.firstChild.nextSibling,ee=x.nextSibling,C=ee.firstChild.nextSibling,te=ee.nextSibling.firstChild.nextSibling,w=b.nextSibling;return i.addEventListener(`submit`,m),h.$$input=e=>n(e.currentTarget.value),g.$$click=()=>p(t()),_.$$click=()=>p(`..`),V(v,M(N,{get each(){return r()},children:e=>(()=>{var n=_n();return n.firstChild,n.$$click=()=>p(`${t()}/${e}`.replace(/\/+/g,`/`)),V(n,e,null),n})()})),S.$$input=e=>o(e.currentTarget.value),C.addEventListener(`change`,e=>c(e.currentTarget.value)),V(C,M(N,{get each(){return e.providers},children:e=>(()=>{var t=xt();return V(t,e),t})()})),te.$$input=e=>u(e.currentTarget.value),V(i,M(P,{get when(){return d()},get children(){var e=hn();return V(e,d),e}}),w),y(()=>h.value=t()),y(()=>S.value=a()),y(()=>C.value=s()),y(()=>te.value=l()),i}})}function Fn(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 M(Nn,{title:`settings`,get onClose(){return e.onClose},get children(){var u=vn(),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),V(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),V(u,M(P,{get when(){return l()},get children(){var e=hn();return V(e,l),e}}),S),y(()=>m.value=t()),y(()=>_.value=r()),y(()=>v.value=a()),y(()=>x.value=s()),u}})}ye([`click`,`input`,`keydown`]),L(()=>M(En,{}),document.getElementById(`root`));
@@ -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.pending{opacity:.55}.msg.pending .ts{color:var(--warn)}.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}.ctrlrow{align-items:center;gap:8px;margin-top:6px;font-size:12.5px;display:flex}.ctrlrow label{cursor:pointer;color:var(--fg);white-space:nowrap;align-items:center;gap:5px;display:flex}.ctrlrow .muted{font-size:11.5px}.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}
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-BJB4iFSq.js"></script>
8
+ <link rel="stylesheet" crossorigin href="/assets/index-C4cJD5q_.css">
9
9
  </head>
10
10
  <body>
11
11
  <div id="root"></div>