antechamber 0.2.1 → 0.2.3

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/CHANGELOG.md CHANGED
@@ -7,10 +7,33 @@ and this project uses [Semantic Versioning](https://semver.org/).
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.2.3] - 2026-10-15
11
+
12
+ ### Fixed
13
+
14
+ - OmO Graph: panning no longer gets stuck following the mouse after the button
15
+ is released outside the panel (or the pointer is cancelled, capture is lost
16
+ or the window loses focus); a move without the primary button held now ends
17
+ the drag.
18
+
19
+ ## [0.2.2] - 2026-10-15
20
+
21
+ ### Fixed
22
+
23
+ - Sub-agent sessions spawned without a `task` tool call (for example `agent()`
24
+ inside an `eval` cell) now open from their OmO task record instead of
25
+ returning `session not found`, and appear in the session list as soon as
26
+ they exist or complete, so their OmO Graph cards are clickable.
27
+
28
+ ### Changed
29
+
30
+ - ci(release): every push to `main` now ships a patch release automatically; CI bumps the package and OmO Graph extension versions (now kept equal), rolls the CHANGELOG, tags, publishes to npm and attaches the extension zip to the GitHub release. The release guide moved to `RELEASE.md`
31
+
10
32
  ## [0.2.1] - 2026-10-15
11
33
 
12
34
  ### Fixed
13
35
 
36
+ - fix(extension): save OmO Graph data paths without form submission, which OpenChamber's iframe sandbox blocks
14
37
  - fix(session): accept OmO messages stored as plain-string content when titling, binding and restoring sessions instead of crashing
15
38
  - fix(api): answer OpenChamber's location eviction (`DELETE /api/debug/location`) with OpenCode's empty 204
16
39
  - fix(api): answer the v2 routes OpenChamber 2.3.2 calls instead of a generic 404/501. Plugin list and check return an empty inventory, `/api/experimental/generate` returns OpenCode's typed 503, and plugin update, credential update/activate, integration connections and session generate/background/move return `UnsupportedError`
package/README.md CHANGED
@@ -293,9 +293,10 @@ The smoke scripts (`npm run smoke`, `npm run omo-smoke`, `npm run probe`,
293
293
  process end to end and cost model tokens; they are not part of `npm test`
294
294
  and are not run in CI. See [docs/development.md](docs/development.md).
295
295
 
296
- Releases are cut by pushing a `vX.Y.Z` tag; CI then runs the checks,
297
- publishes to npm with provenance and creates the GitHub release from the
298
- CHANGELOG. See [docs/releasing.md](docs/releasing.md).
296
+ Every commit on `main` is released as a new patch version: CI runs the checks,
297
+ bumps the package and extension versions, tags, publishes to npm with
298
+ provenance and creates the GitHub release from the CHANGELOG. See
299
+ [RELEASE.md](RELEASE.md).
299
300
 
300
301
  ## Docs
301
302
 
@@ -304,7 +305,7 @@ CHANGELOG. See [docs/releasing.md](docs/releasing.md).
304
305
  - [docs/configuration.md](docs/configuration.md) - full environment variable reference
305
306
  - [docs/development.md](docs/development.md) - source layout, testing, smoke scripts
306
307
  - [docs/backends/omo.md](docs/backends/omo.md) - OmO backend details (agent name, task hosts, transcripts)
307
- - [docs/releasing.md](docs/releasing.md) - versioning, tag-driven npm and GitHub releases
308
+ - [RELEASE.md](RELEASE.md) - automatic patch releases to npm and GitHub on every push to `main`
308
309
 
309
310
  - [extensions/omo-dag/README.md](extensions/omo-dag/README.md) - the OmO Graph OpenChamber extension ([design](extensions/omo-dag/docs/DESIGN.md))
310
311
 
@@ -9,6 +9,11 @@ export declare function taskParts(template: OCToolPart, args: Record<string, unk
9
9
  export declare function updateTaskParts(parts: OCToolPart[], result: ToolResult, ended: boolean, now: number): void;
10
10
  /** Wake messages carry arrays of completion envelopes, not a flat details object. */
11
11
  export declare function taskCompletions(value: unknown): Record<string, unknown>[];
12
+ /** Reverse lookup of a child session id, for tasks whose spawn never surfaced as a `task` tool call. */
13
+ export declare function findTaskBySession(sessionId: string): {
14
+ path: string;
15
+ data: Record<string, unknown>;
16
+ } | undefined;
12
17
  export declare function findTask(id: string, parentPiId: string): {
13
18
  path: string;
14
19
  data: Record<string, unknown>;
@@ -36,6 +41,9 @@ export declare class SubagentBridge {
36
41
  private readonly parse;
37
42
  private readonly children;
38
43
  private readonly calls;
44
+ private readonly removed;
45
+ /** Parent pi session of each task record already read; a record's parent never changes. */
46
+ private readonly taskParents;
39
47
  constructor(store: SessionStore, sessions: Map<string, ManagedSession>, emit: (directory: string, event: OCEvent) => void, parse: ParseHistory);
40
48
  private archive;
41
49
  wire(parent: ManagedSession): void;
@@ -46,6 +54,18 @@ export declare class SubagentBridge {
46
54
  private discoverParts;
47
55
  private create;
48
56
  restore(id: string): ManagedSession | undefined;
57
+ /**
58
+ * Tasks spawned outside a `task` tool call (e.g. `agent()` inside an `eval`
59
+ * cell) never produce a card, so their session is built from the task record.
60
+ */
61
+ private adopt;
62
+ /**
63
+ * Root sessions are keyed by the md5 of their pi session id, but a nested child
64
+ * is keyed by its task id, so its pi session id is matched through the registry.
65
+ */
66
+ private parentFor;
67
+ private childIdsByPi;
68
+ private detachedParent;
49
69
  private managedSession;
50
70
  restoreAll(): void;
51
71
  owns(id: string): boolean;
package/dist/subagents.js CHANGED
@@ -147,16 +147,53 @@ function directories(path) {
147
147
  throw error;
148
148
  }
149
149
  }
150
- export function findTask(id, parentPiId) {
151
- if (!taskId(id))
152
- return undefined;
150
+ function taskStores() {
153
151
  const agent = piAgentDir();
154
152
  const registry = jsonObject(join(agent, "rpc", "task-stores.json"));
155
- const stores = new Set([
153
+ return new Set([
156
154
  ...Object.keys(record(registry?.stores) ? registry.stores : {}),
157
155
  ...directories(join(agent, "projects")).map((project) => join(project, "senpi-task")),
158
156
  ]);
159
- for (const store of stores) {
157
+ }
158
+ function taskFiles() {
159
+ const files = [];
160
+ for (const store of taskStores()) {
161
+ let names;
162
+ try {
163
+ names = readdirSync(join(store, "tasks"));
164
+ }
165
+ catch (error) {
166
+ if (error instanceof Error && "code" in error && ["ENOENT", "ENOTDIR", "EACCES"].includes(String(error.code)))
167
+ continue;
168
+ throw error;
169
+ }
170
+ for (const name of names) {
171
+ const id = name.endsWith(".json") ? name.slice(0, -5) : "";
172
+ if (taskId(id))
173
+ files.push({ id, path: join(store, "tasks", name) });
174
+ }
175
+ }
176
+ return files;
177
+ }
178
+ function childRecord(id, path) {
179
+ const data = jsonObject(path);
180
+ return data?.task_id === id && typeof data.parent_session_id === "string" ? data : undefined;
181
+ }
182
+ /** Reverse lookup of a child session id, for tasks whose spawn never surfaced as a `task` tool call. */
183
+ export function findTaskBySession(sessionId) {
184
+ for (const { id, path } of taskFiles()) {
185
+ if (ocIdFor(id) !== sessionId)
186
+ continue;
187
+ const data = childRecord(id, path);
188
+ if (data)
189
+ return { path, data };
190
+ }
191
+ return undefined;
192
+ }
193
+ export function findTask(id, parentPiId) {
194
+ if (!taskId(id))
195
+ return undefined;
196
+ for (const store of taskStores()) {
160
197
  const path = join(store, "tasks", `${id}.json`);
161
198
  const data = jsonObject(path);
162
199
  if (data?.task_id === id && data.parent_session_id === parentPiId)
@@ -211,6 +248,9 @@ export class SubagentBridge {
211
248
  parse;
212
249
  children = new Map();
213
250
  calls = new Map();
251
+ removed = new Set();
252
+ /** Parent pi session of each task record already read; a record's parent never changes. */
253
+ taskParents = new Map();
214
254
  constructor(store, sessions, emit, parse) {
215
255
  this.store = store;
216
256
  this.sessions = sessions;
@@ -251,7 +291,12 @@ export class SubagentBridge {
251
291
  if (message.customType !== "omo-senpi:wake")
252
292
  return;
253
293
  for (const data of taskCompletions(message.details)) {
254
- const child = this.children.get(ocIdFor(String(data.task_id)));
294
+ const id = ocIdFor(String(data.task_id));
295
+ // A registry-only child (after a restart) or a task with no card (spawned from
296
+ // `eval`) is not loaded yet; restore() covers both.
297
+ if (!this.children.has(id))
298
+ this.restore(id);
299
+ const child = this.children.get(id);
255
300
  if (child?.session.info.parentID !== parent.info.id)
256
301
  continue;
257
302
  child.task.details = { ...child.task.details, ...data };
@@ -326,19 +371,74 @@ export class SubagentBridge {
326
371
  if (known)
327
372
  return known.session;
328
373
  const entry = this.store.get(id);
329
- if (!entry?.task || !entry.parentID)
374
+ if (!entry)
375
+ return this.removed.has(id) ? undefined : this.adopt(id);
376
+ if (!entry.task || !entry.parentID)
330
377
  return undefined;
331
- const parent = this.managedSession({
332
- id: entry.parentID,
333
- projectID: entry.directory,
334
- directory: entry.directory,
378
+ const child = this.create(this.detachedParent(entry.parentID, entry.directory, entry), entry.task);
379
+ child.session.info.title = entry.title ?? child.session.info.title;
380
+ return child.session;
381
+ }
382
+ /**
383
+ * Tasks spawned outside a `task` tool call (e.g. `agent()` inside an `eval`
384
+ * cell) never produce a card, so their session is built from the task record.
385
+ */
386
+ adopt(id, found = findTaskBySession(id)) {
387
+ if (!found)
388
+ return undefined;
389
+ const parentPi = String(found.data.parent_session_id);
390
+ const parent = this.parentFor(parentPi);
391
+ if (!parent)
392
+ return undefined;
393
+ this.wire(parent);
394
+ const spec = record(found.data.spawn_spec) ? found.data.spawn_spec : {};
395
+ const name = found.data.name ?? found.data.description;
396
+ const child = this.create(parent, {
397
+ id: String(found.data.task_id),
398
+ parentPiId: parentPi,
399
+ input: {
400
+ ...(typeof name === "string" ? { description: name } : {}),
401
+ ...(typeof spec.prompt === "string" ? { prompt: spec.prompt } : {}),
402
+ ...(typeof found.data.agent_type === "string" ? { subagent_type: found.data.agent_type } : {}),
403
+ },
404
+ details: found.data,
405
+ });
406
+ this.refresh(child, false);
407
+ return child.session;
408
+ }
409
+ /**
410
+ * Root sessions are keyed by the md5 of their pi session id, but a nested child
411
+ * is keyed by its task id, so its pi session id is matched through the registry.
412
+ */
413
+ parentFor(parentPi, childByPi = this.childIdsByPi()) {
414
+ const rootID = ocIdFor(parentPi);
415
+ const loaded = [...this.sessions.values()].find((s) => s.info.id === rootID || s.piSessionId === parentPi || s.restored?.piSessionId === parentPi);
416
+ if (loaded)
417
+ return loaded;
418
+ const id = this.store.get(rootID) ? rootID : childByPi.get(parentPi);
419
+ if (id === undefined)
420
+ return undefined;
421
+ const entry = this.store.get(id);
422
+ return this.sessions.get(id) ?? (entry ? this.detachedParent(id, entry.directory, entry) : undefined);
423
+ }
424
+ childIdsByPi() {
425
+ const byPi = new Map();
426
+ for (const id of this.store.childIds()) {
427
+ const piSessionId = this.store.get(id)?.piSessionId;
428
+ if (piSessionId)
429
+ byPi.set(piSessionId, id);
430
+ }
431
+ return byPi;
432
+ }
433
+ detachedParent(id, directory, times) {
434
+ return this.managedSession({
435
+ id,
436
+ projectID: directory,
437
+ directory,
335
438
  title: "",
336
439
  version: ADAPTER_VERSION,
337
- time: { created: entry.created, updated: entry.updated },
440
+ time: { created: times.created, updated: times.updated },
338
441
  });
339
- const child = this.create(parent, entry.task);
340
- child.session.info.title = entry.title ?? child.session.info.title;
341
- return child.session;
342
442
  }
343
443
  managedSession(info) {
344
444
  return {
@@ -357,6 +457,24 @@ export class SubagentBridge {
357
457
  restoreAll() {
358
458
  for (const id of this.store.childIds())
359
459
  this.restore(id);
460
+ const childByPi = this.childIdsByPi();
461
+ for (const { id, path } of taskFiles()) {
462
+ const sessionId = ocIdFor(id);
463
+ if (this.children.has(sessionId) || this.removed.has(sessionId) || this.store.get(sessionId))
464
+ continue;
465
+ let parentPi = this.taskParents.get(id);
466
+ if (parentPi === undefined) {
467
+ const parent = childRecord(id, path)?.parent_session_id;
468
+ if (typeof parent !== "string")
469
+ continue;
470
+ this.taskParents.set(id, (parentPi = parent));
471
+ }
472
+ if (!this.parentFor(parentPi, childByPi))
473
+ continue;
474
+ const data = childRecord(id, path);
475
+ if (data)
476
+ this.adopt(sessionId, { path, data });
477
+ }
360
478
  }
361
479
  owns(id) {
362
480
  return this.children.has(id);
@@ -628,6 +746,7 @@ export class SubagentBridge {
628
746
  this.closeWatchers(child);
629
747
  child.parts.clear();
630
748
  this.children.delete(id);
749
+ this.removed.add(id);
631
750
  }
632
751
  dispose() {
633
752
  for (const child of this.children.values()) {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "antechamber-omo-graph",
3
- "version": "0.1.0",
3
+ "version": "0.2.3",
4
4
  "description": "OpenChamber extension: live, interactive graph of the OmO sub-agents behind the current session",
5
5
  "private": true,
6
6
  "type": "module",
@@ -50,7 +50,7 @@
50
50
  #settings input { padding: 6px 8px; border: 1px solid var(--border); border-radius: 6px; background: var(--bg); font: 12px var(--mono); }
51
51
  #settings .row { display: flex; justify-content: flex-end; gap: 6px; }
52
52
  #settings button { padding: 5px 12px; border-radius: 6px; border: 1px solid var(--border); background: var(--surface-2); cursor: pointer; }
53
- #settings button[type="submit"] { background: var(--accent); color: var(--oc-primary-fg, #001); border-color: transparent; }
53
+ #settings #btn-save { background: var(--accent); color: var(--oc-primary-fg, #001); border-color: transparent; }
54
54
 
55
55
  #viewport { position: relative; flex: 1; overflow: hidden; cursor: grab; touch-action: none;
56
56
  background-image: radial-gradient(color-mix(in srgb, var(--muted) 22%, transparent) 1px, transparent 1px);
@@ -158,7 +158,7 @@
158
158
  <form id="settings" hidden>
159
159
  <label>OmO agent directory <input name="agentDir" placeholder="~/.omo/agent (default, then ~/.pi/agent)" autocomplete="off" spellcheck="false" /></label>
160
160
  <label>Connector state directory <input name="stateDir" placeholder="~/.config/antechamber (default)" autocomplete="off" spellcheck="false" /></label>
161
- <div class="row"><button type="submit">Save</button></div>
161
+ <div class="row"><button id="btn-save" type="button">Save</button></div>
162
162
  </form>
163
163
  <div id="viewport">
164
164
  <div id="world" hidden>
@@ -1,4 +1,4 @@
1
- "use strict";(()=>{var k="openchamber.sdk";var Be=`
1
+ "use strict";(()=>{var x="openchamber.sdk";var ze=`
2
2
  :root {
3
3
  --oc-scrollbar-thumb: color-mix(in srgb, var(--oc-muted, currentColor) 40%, transparent);
4
4
  --oc-scrollbar-thumb-hover: color-mix(in srgb, var(--oc-muted, currentColor) 65%, transparent);
@@ -28,54 +28,54 @@
28
28
  * { scrollbar-color: auto; }
29
29
  ::-webkit-scrollbar-thumb, ::-webkit-scrollbar-thumb:hover { background: CanvasText; }
30
30
  }
31
- `;var Tt=["file","directory","other","missing"],ze=e=>!!(e&&"sessionId"in e),Ke=e=>!!(e&&"sent"in e&&!("sessionId"in e));var Se=500,Te=32e3,_t=16e3,yt=128,At=200,wt=2e3,vt=16e3,Mt=80,Ot=200,Lt=16e3;var Ct=2e3;var Ve=2e4,_e=1024,ye=2e6;var Ae=64e3,we=8e3,je=4e3;var qe=9e4;var Rt=999,ve=500,Gt=["HOST_UNAVAILABLE","HOST_TIMEOUT","HOST_REJECTED","DISCONNECTED","DISABLED","BAD_PATH","NO_INTEGRATION","NO_SERVICE","SERVICE_FAILED","NO_SESSION","SESSION_BUSY","NOT_GRANTED","NO_DIRECTORY","NOT_FOUND","FILE_TOO_LARGE","DENIED","NO_MODEL","MODEL_FAILED"],It=["stopped","starting","ready","failed"],ro=new Set(Gt),$t=e=>ro.has(e),Nt=e=>e&&$t(e)?e:"HOST_REJECTED",re=e=>e===void 0?!1:e===null||e===!0||e===!1||String(e)===e?!0:Number(e)===e?Number.isFinite(e):Array.isArray(e)?e.every(re):Object(e)===e?Object.values(e).every(re):!1,Ut=e=>re(e)&&JSON.stringify(e).length<=Lt,St=e=>e?.trim().slice(0,Ot)??"",se=e=>{let t=e.id.trim().slice(0,yt),r=e.title.trim().slice(0,At),a=e.url.trim().slice(0,wt),l=e.text?.trim().slice(0,vt),p=e.author?.trim().slice(0,Mt),s=e.kind==="pull"?"pull":"issue",c={providerId:e.providerId.trim(),id:t,title:r||t,url:a,kind:s};if(l&&(c.text=l),p&&(c.author=p),s==="pull"){let h=St(e.branches?.head),A=St(e.branches?.base);h&&A&&(c.branches={head:h,base:A})}return Ut(e.data)&&(c.data=e.data),c},Ye=e=>{let t=se(e);return e.projectId&&(t.projectId=e.projectId),e.navigation&&(t.navigation=e.navigation),e.worktree&&(t.worktree=e.worktree),t},Je=e=>{let t={text:e.text.trim().slice(0,_t)};return e.send&&(t.send=!0),t},We=e=>e===null||!Number.isFinite(e)?null:Math.min(Rt,Math.max(0,Math.round(e)));var ie=e=>e.length>0&&e.length<=_e&&!e.includes("\0")&&!e.includes("\\");var Me=e=>!e.startsWith("/")||e.includes("\0")||e.includes("\\")||e.includes("://")||e.length>Ct?!1:!e.split("/").some(r=>r==="."||r===".."),so=new Set(It),Qe=e=>!!(e&&"status"in e&&so.has(String(e.status))&&!("body"in e)),Oe=e=>!!(e&&"status"in e&&"body"in e&&Number.isInteger(e.status)),Ze=e=>!!(e&&"content"in e&&String(e.content)===e.content),et=e=>!!(e&&"written"in e&&e.written===!0),tt=e=>!!(e&&"entries"in e&&Array.isArray(e.entries)),io=new Set(Tt),ot=e=>!!(e&&"kind"in e&&"size"in e&&io.has(String(e.kind))&&Number.isFinite(e.size)),nt=e=>!!(e&&"text"in e&&String(e.text)===e.text&&!("status"in e)),ao=new Set(["workspace","ready","directory","session","connection","settings","session-lifecycle","item","resolve","action"]),co=e=>Object(e)===e?e:null,Fe=e=>String(e)===e&&e.length>0,lo=e=>{if(!Fe(e.id))return null;if(e.ok===!0){let t={channel:k,v:1,type:"result",id:e.id,ok:!0};return Object(e.payload)===e.payload&&(t.payload=e.payload),t}return e.ok===!1&&Fe(e.error)?{channel:k,v:1,type:"result",id:e.id,ok:!1,error:e.error,code:Nt(Fe(e.code)?e.code:void 0)}:null},rt=e=>{let t=co(e);return!t||t.channel!==k||t.v!==1?null:t.type==="result"?lo(t):!ao.has(String(t.type))||Object(t.payload)!==t.payload?null:t};var u=class extends Error{code;constructor(t,r){super(r),this.name="HostRequestError",this.code=t}},Dt=()=>Promise.reject(new u("BAD_PATH",'Request path must start with "/" and stay on the declared origin.')),Le=()=>Promise.reject(new u("BAD_PATH",`File path must be 1 to ${_e} characters without NUL or backslash.`)),S=e=>(e.value+=1,`oc-${e.value}`),st=(e={})=>{let t=e.target??("window"in globalThis?window:null);if(!t)throw new u("HOST_UNAVAILABLE","No window. connectHost runs in a browser frame.");let r=e.acceptSource??(o=>o===t.parent),a=e.requestTimeoutMs??Ve,l=new Set,p=new Set,s=new Set,c=new Set,h=new Set,A=new Set,i=new Set,g=null,f=null,x=new Map,I=new Map,W=!1,E={value:0},T=null,q=null,xt=o=>o?{sessionId:o.id,phase:o.busy?"started":"completed"}:null,Q=o=>{t.parent.postMessage(o,"*")},N=(o,n)=>{for(let m of o)try{m(n)}catch(w){console.error(w)}},bt=o=>{if(!(o instanceof MessageEvent)||!r(o.source))return;let n=rt(o.data);if(!n)return;if(n.type==="workspace"){let w=I.get(n.payload.subscriptionId);w&&N([w],n.payload.snapshot);return}if(n.type==="ready"){T=n.payload,q=xt(n.payload.session),N(l,n.payload),N(p,n.payload.directory),N(s,n.payload.session),q&&N(c,q),N(h,n.payload.connection),N(A,n.payload.settings),N(i,n.payload.item);return}if(n.type==="directory"){T&&(T={...T,directory:n.payload.directory}),N(p,n.payload.directory);return}if(n.type==="session"){T&&(T={...T,session:n.payload.session}),n.payload.session?q?.sessionId!==n.payload.session.id&&(q=xt(n.payload.session)):q=null,N(s,n.payload.session);return}if(n.type==="session-lifecycle"){q=n.payload,N(c,n.payload);return}if(n.type==="connection"){T&&(T={...T,connection:n.payload.connection}),N(h,n.payload.connection);return}if(n.type==="settings"){T&&(T={...T,settings:n.payload.settings}),N(A,n.payload.settings);return}if(n.type==="item"){T&&(T={...T,item:n.payload.item}),N(i,n.payload.item);return}if(n.type==="action"){let w=R=>{W||Q({channel:k,v:1,type:"action-result",id:n.id,payload:R})},F=f;if(!F){w({ok:!1,error:"This extension does not handle background actions."});return}Promise.resolve().then(()=>F(n.payload)).then(()=>w({ok:!0}),R=>{let Xe=(R instanceof Error?R.message:String(R)).trim();w({ok:!1,error:(Xe||"Action failed.").slice(0,ve)})});return}if(n.type==="resolve"){let w=R=>{Q({channel:k,v:1,type:"resolve-result",id:n.id,payload:R})},F=g;if(!F){w({error:"This extension does not resolve commands."});return}Promise.resolve().then(()=>F(n.payload)).then(R=>w({item:R?se(R):null}),R=>{let Xe=(R instanceof Error?R.message:String(R)).trim();w({error:(Xe||"Command failed.").slice(0,ve)})});return}let m=x.get(n.id);if(m){if(clearTimeout(m.timer),x.delete(n.id),n.ok){m.resolve(n.payload);return}m.reject(new u(n.code,n.error))}};t.addEventListener("message",bt),Q({channel:k,v:1,type:"hello"});let H=(o,n=a)=>W||t.parent===t?Promise.reject(new u("HOST_UNAVAILABLE","No host frame. This page is not in an iframe.")):new Promise((m,w)=>{let F=setTimeout(()=>{x.delete(o.id),w(new u("HOST_TIMEOUT","Host did not answer in time."))},n);x.set(o.id,{resolve:m,reject:w,timer:F}),Q(o)}),P=o=>H(o).then(()=>{}),Z={channel:k,v:1},ee=(o,n=1024)=>{if(!o.trim()||o.length>n)throw new u("HOST_REJECTED",`Identity must contain 1 to ${n} characters.`)},He=async o=>{o.kind!=="projects"&&ee(o.projectId);let n=await H({...Z,type:"workspace-read",id:S(E),payload:o});if(!n||!("kind"in n)||!("state"in n)||n.kind!==o.kind)throw new u("HOST_REJECTED","Host did not return workspace data.");return n},Pe=async(o,n)=>{o.kind!=="projects"&&ee(o.projectId);let m=S(E);I.set(m,n);try{await P({...Z,type:"workspace-subscribe",id:S(E),payload:{subscriptionId:m,query:o}})}catch(w){throw I.delete(m),W||Q({...Z,type:"workspace-unsubscribe",id:S(E),payload:{subscriptionId:m}}),w}return()=>{!I.delete(m)||W||Q({...Z,type:"workspace-unsubscribe",id:S(E),payload:{subscriptionId:m}})}},be=async o=>{if("key"in o&&(o.key.length===0||o.key.length>128))throw new u("HOST_REJECTED","Storage key must contain 1 to 128 characters.");if(o.op==="set"&&!re(o.value))throw new u("HOST_REJECTED","Storage values must be JSON.");if(o.op==="set"&&new TextEncoder().encode(JSON.stringify(o.value)).length>65536)throw new u("HOST_REJECTED","Storage value exceeds 64 KiB.");let n=await H({...Z,type:"storage",id:S(E),payload:o});if(!n||!("storage"in n)||n.op!==o.op)throw new u("HOST_REJECTED","Host did not return storage data.");return n};return{onAction:o=>(f=o,()=>{f===o&&(f=null)}),listProjects:async()=>{let o=await He({kind:"projects"});if(o.kind!=="projects")throw new u("HOST_REJECTED","Expected projects.");return o},listWorktrees:async o=>{let n=await He({kind:"worktrees",projectId:o});if(n.kind!=="worktrees")throw new u("HOST_REJECTED","Expected worktrees.");return n},listSessions:async o=>{let n=await He({kind:"sessions",projectId:o});if(n.kind!=="sessions")throw new u("HOST_REJECTED","Expected sessions.");return n},onProjects:o=>Pe({kind:"projects"},n=>{n.kind==="projects"&&o(n)}),onWorktrees:(o,n)=>Pe({kind:"worktrees",projectId:o},m=>{m.kind==="worktrees"&&n(m)}),onSessions:(o,n)=>Pe({kind:"sessions",projectId:o},m=>{m.kind==="sessions"&&n(m)}),openSession:async o=>{ee(o),await P({...Z,type:"open-session",id:S(E),payload:{sessionId:o}})},storage:{get:async o=>{let n=await be({op:"get",key:o});return n.op==="get"&&n.found?n.value:void 0},set:async(o,n)=>{await be({op:"set",key:o,value:n})},delete:async o=>{await be({op:"delete",key:o})},keys:async()=>{let o=await be({op:"keys"});if(o.op!=="keys")throw new u("HOST_REJECTED","Expected storage keys.");return o.keys}},onReady:o=>(l.add(o),T&&o(T),()=>{l.delete(o)}),onDirectory:o=>(p.add(o),T&&o(T.directory),()=>{p.delete(o)}),onSession:o=>(s.add(o),T&&o(T.session),()=>{s.delete(o)}),onSessionLifecycle:o=>(c.add(o),q&&o(q),()=>{c.delete(o)}),onConnection:o=>(h.add(o),T&&o(T.connection),()=>{h.delete(o)}),onSettings:o=>(A.add(o),T&&o(T.settings),()=>{A.delete(o)}),onItem:o=>(i.add(o),T&&o(T.item),()=>{i.delete(o)}),onResolve:o=>(g=o,()=>{g===o&&(g=null)}),toast:o=>{let n=o.message.trim();return!n||n.length>Se?Promise.reject(new u("HOST_REJECTED",`Toast message must contain 1 to ${Se} characters.`)):o.copy&&o.copy!==!0&&(!o.copy.text.length||o.copy.text.length>Te)?Promise.reject(new u("HOST_REJECTED",`Toast copy text must contain 1 to ${Te} characters.`)):P({channel:k,v:1,type:"toast",id:S(E),payload:{...o,message:n}})},openUrl:o=>P({channel:k,v:1,type:"open-url",id:S(E),payload:{url:o}}),openSurface:o=>P({channel:k,v:1,type:"open-surface",id:S(E),payload:{surfaceId:o}}),writeClipboard:o=>P({channel:k,v:1,type:"clipboard-write",id:S(E),payload:{text:o}}),compose:o=>P({channel:k,v:1,type:"compose",id:S(E),payload:o}),attach:o=>P({channel:k,v:1,type:"attach",id:S(E),payload:se(o)}),startSession:async o=>{o.projectId!==void 0&&ee(o.projectId);let n=o.worktree;n&&n!==!0&&(n.kind==="existing"?ee(n.directory):(n.name!==void 0&&ee(n.name,200),n.baseBranch!==void 0&&ee(n.baseBranch,200)));let m=await H({channel:k,v:1,type:"start-session",id:S(E),payload:Ye(o)},e.requestTimeoutMs??18e4);if(!ze(m))throw new u("HOST_REJECTED","Host did not return a session.");return m},prompt:o=>H({channel:k,v:1,type:"prompt",id:S(E),payload:Je(o)}).then(n=>{if(!Ke(n))throw new u("HOST_REJECTED","Host did not return a prompt result.");return n}),sessionLink:o=>P({channel:k,v:1,type:"session-link",id:S(E),payload:se(o)}),close:()=>P({channel:k,v:1,type:"close",id:S(E)}),oauthStart:()=>P({channel:k,v:1,type:"oauth-start",id:S(E)}),oauthDisconnect:()=>P({channel:k,v:1,type:"oauth-disconnect",id:S(E)}),request:o=>(Me(o.path)?H({channel:k,v:1,type:"request",id:S(E),payload:o}):Dt()).then(n=>{if(!Oe(n))throw new u("HOST_REJECTED","Host request result was empty.");return n}),serviceRequest:o=>(Me(o.path)?H({channel:k,v:1,type:"service-request",id:S(E),payload:o}):Dt()).then(n=>{if(!Oe(n))throw new u("HOST_REJECTED","Host service request result was empty.");return n}),serviceStatus:()=>H({channel:k,v:1,type:"service-status",id:S(E)}).then(o=>{if(!Qe(o))throw new u("HOST_REJECTED","Host did not return service status.");return o}),readFile:o=>(ie(o)?H({channel:k,v:1,type:"file-read",id:S(E),payload:{path:o}}):Le()).then(n=>{if(!Ze(n))throw new u("HOST_REJECTED","Host did not return file content.");return n}),writeFile:(o,n)=>ie(o)?n.length>ye?Promise.reject(new u("FILE_TOO_LARGE",`Content is over ${ye} characters.`)):H({channel:k,v:1,type:"file-write",id:S(E),payload:{path:o,content:n}}).then(m=>{if(!et(m))throw new u("HOST_REJECTED","Host did not confirm the write.");return m}):Le(),listDir:o=>(ie(o)?H({channel:k,v:1,type:"file-list",id:S(E),payload:{path:o}}):Le()).then(n=>{if(!tt(n))throw new u("HOST_REJECTED","Host did not return directory entries.");return n}),stat:o=>(ie(o)?H({channel:k,v:1,type:"file-stat",id:S(E),payload:{path:o}}):Le()).then(n=>{if(!ot(n))throw new u("HOST_REJECTED","Host did not return file status.");return n}),generate:o=>{let n=o.prompt.trim(),m=o.system?.trim();if(n.length===0||n.length>Ae)return Promise.reject(new u("HOST_REJECTED",`Prompt must be 1 to ${Ae} characters.`));if(m!==void 0&&(m.length===0||m.length>we))return Promise.reject(new u("HOST_REJECTED",`System prompt must be 1 to ${we} characters.`));let w=o.maxOutputTokens===void 0?void 0:Math.min(je,Math.max(1,Math.floor(o.maxOutputTokens)));if(w!==void 0&&!Number.isFinite(w))return Promise.reject(new u("HOST_REJECTED","maxOutputTokens must be a number."));let F={prompt:n};return m!==void 0&&(F.system=m),w!==void 0&&(F.maxOutputTokens=w),H({channel:k,v:1,type:"generate",id:S(E),payload:F},e.requestTimeoutMs??qe).then(R=>{if(!nt(R))throw new u("HOST_REJECTED","Host did not return generated text.");return R})},setBadge:o=>P({channel:k,v:1,type:"badge",id:S(E),payload:{count:We(o)}}),dispose:()=>{for(let o of I.keys())Q({...Z,type:"workspace-unsubscribe",id:S(E),payload:{subscriptionId:o}});I.clear(),W=!0,g=null,f=null,t.removeEventListener("message",bt);for(let o of x.values())clearTimeout(o.timer),o.reject(new u("HOST_UNAVAILABLE","Host client was disposed."));x.clear(),l.clear(),p.clear(),s.clear(),c.clear(),h.clear(),A.clear(),i.clear()}}};var po=[["--oc-bg","background"],["--oc-elevated","elevated"],["--oc-fg","foreground"],["--oc-muted","muted"],["--oc-subtle","subtle"],["--oc-border","border"],["--oc-hover","hover"],["--oc-selection","selection"],["--oc-focus","focus"],["--oc-primary","primary"],["--oc-muted-surface","mutedSurface"],["--oc-elevated-fg","elevatedForeground"],["--oc-active","active"],["--oc-selection-fg","selectionForeground"],["--oc-primary-fg","primaryForeground"],["--oc-primary-text","primaryText"],["--oc-success-text","successText"],["--oc-warning-text","warningText"],["--oc-error-text","errorText"],["--oc-info-text","infoText"],["--oc-success","success"],["--oc-warning","warning"],["--oc-error","error"],["--oc-info","info"],["--oc-font","font"],["--oc-mono","mono"],["--oc-radius","radius"],["--surface-background","background"],["--surface-elevated","elevated"],["--surface-foreground","foreground"],["--surface-muted-foreground","muted"],["--surface-subtle","subtle"],["--interactive-border","border"],["--interactive-hover","hover"],["--interactive-selection","selection"],["--interactive-focus-ring","focus"],["--primary","primary"],["--surface-muted","mutedSurface"],["--surface-elevated-foreground","elevatedForeground"],["--interactive-active","active"],["--interactive-selection-foreground","selectionForeground"],["--primary-foreground","primaryForeground"],["--primary-text","primaryText"],["--success-text","successText"],["--warning-text","warningText"],["--error-text","errorText"],["--info-text","infoText"],["--status-success","success"],["--status-warning","warning"],["--status-error","error"],["--status-info","info"],["--font-sans","font"],["--font-mono","mono"],["--radius","radius"]],Xt=(e,t)=>{t.style.colorScheme=e.mode;for(let[r,a]of po)t.style.setProperty(r,e.tokens[a]);t.style.setProperty("font-family",e.tokens.font),t.style.setProperty("font-size","0.875rem"),t.style.setProperty("line-height","1.45"),t.style.setProperty("color",e.tokens.foreground)},it=(e,t)=>{Xt(e.theme,t),t.dataset&&(t.dataset.ocSurface=e.surface,t.dataset.ocTheme=e.theme.mode)};var uo={"surface-background":"bg","surface-elevated":"elevated","surface-elevated-foreground":"elevated-fg","surface-foreground":"fg","surface-muted-foreground":"muted","surface-muted":"muted-surface","surface-subtle":"subtle","interactive-border":"border","interactive-hover":"hover","interactive-active":"active","interactive-selection":"selection","interactive-selection-foreground":"selection-fg","interactive-focus-ring":"focus",primary:"primary","primary-foreground":"primary-fg","primary-text":"primary-text","success-text":"success-text","warning-text":"warning-text","error-text":"error-text","info-text":"info-text","status-success":"success","status-warning":"warning","status-error":"error","status-info":"info","font-sans":"font","font-mono":"mono",radius:"radius"},y=(e,t)=>`var(--${e}, var(--oc-${uo[e]}, ${t}))`,te=y("surface-background","transparent"),Ce=y("surface-elevated","transparent"),pe=y("surface-elevated-foreground","inherit"),ue=y("surface-foreground","inherit"),v=y("surface-muted-foreground","gray"),fo=y("surface-muted","transparent"),B=y("interactive-border","currentColor"),X=y("interactive-hover","transparent"),oe=y("interactive-active","transparent"),at=y("interactive-selection","transparent"),ct=y("interactive-selection-foreground","inherit"),zt=y("interactive-focus-ring","currentColor"),z=y("primary","currentColor"),dt=y("primary-text","inherit"),lt=y("error-text","inherit"),mo=y("font-sans","inherit"),pt=y("font-mono","monospace"),Bt=y("radius","9px"),O=(e,t,r="transparent")=>`color-mix(in srgb, ${e} ${t}%, ${r})`,Ft=`box-shadow: 0 0 0 2px ${zt};`,Re=e=>{let t=y(`status-${e}`,"currentColor");return`
31
+ `;var yt=["file","directory","other","missing"],Ve=e=>!!(e&&"sessionId"in e),je=e=>!!(e&&"sent"in e&&!("sessionId"in e));var Te=500,_e=32e3,At=16e3,wt=128,vt=200,Mt=2e3,Ot=16e3,Lt=80,Ct=200,Rt=16e3;var Gt=2e3;var Ye=2e4,ye=1024,Ae=2e6;var we=64e3,ve=8e3,qe=4e3;var Je=9e4;var It=999,Me=500,$t=["HOST_UNAVAILABLE","HOST_TIMEOUT","HOST_REJECTED","DISCONNECTED","DISABLED","BAD_PATH","NO_INTEGRATION","NO_SERVICE","SERVICE_FAILED","NO_SESSION","SESSION_BUSY","NOT_GRANTED","NO_DIRECTORY","NOT_FOUND","FILE_TOO_LARGE","DENIED","NO_MODEL","MODEL_FAILED"],Nt=["stopped","starting","ready","failed"],io=new Set($t),Ut=e=>io.has(e),Dt=e=>e&&Ut(e)?e:"HOST_REJECTED",ne=e=>e===void 0?!1:e===null||e===!0||e===!1||String(e)===e?!0:Number(e)===e?Number.isFinite(e):Array.isArray(e)?e.every(ne):Object(e)===e?Object.values(e).every(ne):!1,Ht=e=>ne(e)&&JSON.stringify(e).length<=Rt,_t=e=>e?.trim().slice(0,Ct)??"",re=e=>{let t=e.id.trim().slice(0,wt),r=e.title.trim().slice(0,vt),a=e.url.trim().slice(0,Mt),l=e.text?.trim().slice(0,Ot),p=e.author?.trim().slice(0,Lt),s=e.kind==="pull"?"pull":"issue",c={providerId:e.providerId.trim(),id:t,title:r||t,url:a,kind:s};if(l&&(c.text=l),p&&(c.author=p),s==="pull"){let h=_t(e.branches?.head),A=_t(e.branches?.base);h&&A&&(c.branches={head:h,base:A})}return Ht(e.data)&&(c.data=e.data),c},We=e=>{let t=re(e);return e.projectId&&(t.projectId=e.projectId),e.navigation&&(t.navigation=e.navigation),e.worktree&&(t.worktree=e.worktree),t},Qe=e=>{let t={text:e.text.trim().slice(0,At)};return e.send&&(t.send=!0),t},Ze=e=>e===null||!Number.isFinite(e)?null:Math.min(It,Math.max(0,Math.round(e)));var se=e=>e.length>0&&e.length<=ye&&!e.includes("\0")&&!e.includes("\\");var Oe=e=>!e.startsWith("/")||e.includes("\0")||e.includes("\\")||e.includes("://")||e.length>Gt?!1:!e.split("/").some(r=>r==="."||r===".."),ao=new Set(Nt),et=e=>!!(e&&"status"in e&&ao.has(String(e.status))&&!("body"in e)),Le=e=>!!(e&&"status"in e&&"body"in e&&Number.isInteger(e.status)),tt=e=>!!(e&&"content"in e&&String(e.content)===e.content),ot=e=>!!(e&&"written"in e&&e.written===!0),nt=e=>!!(e&&"entries"in e&&Array.isArray(e.entries)),co=new Set(yt),rt=e=>!!(e&&"kind"in e&&"size"in e&&co.has(String(e.kind))&&Number.isFinite(e.size)),st=e=>!!(e&&"text"in e&&String(e.text)===e.text&&!("status"in e)),lo=new Set(["workspace","ready","directory","session","connection","settings","session-lifecycle","item","resolve","action"]),po=e=>Object(e)===e?e:null,Ke=e=>String(e)===e&&e.length>0,uo=e=>{if(!Ke(e.id))return null;if(e.ok===!0){let t={channel:x,v:1,type:"result",id:e.id,ok:!0};return Object(e.payload)===e.payload&&(t.payload=e.payload),t}return e.ok===!1&&Ke(e.error)?{channel:x,v:1,type:"result",id:e.id,ok:!1,error:e.error,code:Dt(Ke(e.code)?e.code:void 0)}:null},it=e=>{let t=po(e);return!t||t.channel!==x||t.v!==1?null:t.type==="result"?uo(t):!lo.has(String(t.type))||Object(t.payload)!==t.payload?null:t};var u=class extends Error{code;constructor(t,r){super(r),this.name="HostRequestError",this.code=t}},Pt=()=>Promise.reject(new u("BAD_PATH",'Request path must start with "/" and stay on the declared origin.')),Ce=()=>Promise.reject(new u("BAD_PATH",`File path must be 1 to ${ye} characters without NUL or backslash.`)),S=e=>(e.value+=1,`oc-${e.value}`),at=(e={})=>{let t=e.target??("window"in globalThis?window:null);if(!t)throw new u("HOST_UNAVAILABLE","No window. connectHost runs in a browser frame.");let r=e.acceptSource??(o=>o===t.parent),a=e.requestTimeoutMs??Ye,l=new Set,p=new Set,s=new Set,c=new Set,h=new Set,A=new Set,i=new Set,g=null,f=null,k=new Map,I=new Map,J=!1,E={value:0},T=null,j=null,St=o=>o?{sessionId:o.id,phase:o.busy?"started":"completed"}:null,W=o=>{t.parent.postMessage(o,"*")},N=(o,n)=>{for(let m of o)try{m(n)}catch(w){console.error(w)}},Tt=o=>{if(!(o instanceof MessageEvent)||!r(o.source))return;let n=it(o.data);if(!n)return;if(n.type==="workspace"){let w=I.get(n.payload.subscriptionId);w&&N([w],n.payload.snapshot);return}if(n.type==="ready"){T=n.payload,j=St(n.payload.session),N(l,n.payload),N(p,n.payload.directory),N(s,n.payload.session),j&&N(c,j),N(h,n.payload.connection),N(A,n.payload.settings),N(i,n.payload.item);return}if(n.type==="directory"){T&&(T={...T,directory:n.payload.directory}),N(p,n.payload.directory);return}if(n.type==="session"){T&&(T={...T,session:n.payload.session}),n.payload.session?j?.sessionId!==n.payload.session.id&&(j=St(n.payload.session)):j=null,N(s,n.payload.session);return}if(n.type==="session-lifecycle"){j=n.payload,N(c,n.payload);return}if(n.type==="connection"){T&&(T={...T,connection:n.payload.connection}),N(h,n.payload.connection);return}if(n.type==="settings"){T&&(T={...T,settings:n.payload.settings}),N(A,n.payload.settings);return}if(n.type==="item"){T&&(T={...T,item:n.payload.item}),N(i,n.payload.item);return}if(n.type==="action"){let w=G=>{J||W({channel:x,v:1,type:"action-result",id:n.id,payload:G})},F=f;if(!F){w({ok:!1,error:"This extension does not handle background actions."});return}Promise.resolve().then(()=>F(n.payload)).then(()=>w({ok:!0}),G=>{let Fe=(G instanceof Error?G.message:String(G)).trim();w({ok:!1,error:(Fe||"Action failed.").slice(0,Me)})});return}if(n.type==="resolve"){let w=G=>{W({channel:x,v:1,type:"resolve-result",id:n.id,payload:G})},F=g;if(!F){w({error:"This extension does not resolve commands."});return}Promise.resolve().then(()=>F(n.payload)).then(G=>w({item:G?re(G):null}),G=>{let Fe=(G instanceof Error?G.message:String(G)).trim();w({error:(Fe||"Command failed.").slice(0,Me)})});return}let m=k.get(n.id);if(m){if(clearTimeout(m.timer),k.delete(n.id),n.ok){m.resolve(n.payload);return}m.reject(new u(n.code,n.error))}};t.addEventListener("message",Tt),W({channel:x,v:1,type:"hello"});let H=(o,n=a)=>J||t.parent===t?Promise.reject(new u("HOST_UNAVAILABLE","No host frame. This page is not in an iframe.")):new Promise((m,w)=>{let F=setTimeout(()=>{k.delete(o.id),w(new u("HOST_TIMEOUT","Host did not answer in time."))},n);k.set(o.id,{resolve:m,reject:w,timer:F}),W(o)}),P=o=>H(o).then(()=>{}),Q={channel:x,v:1},Z=(o,n=1024)=>{if(!o.trim()||o.length>n)throw new u("HOST_REJECTED",`Identity must contain 1 to ${n} characters.`)},Xe=async o=>{o.kind!=="projects"&&Z(o.projectId);let n=await H({...Q,type:"workspace-read",id:S(E),payload:o});if(!n||!("kind"in n)||!("state"in n)||n.kind!==o.kind)throw new u("HOST_REJECTED","Host did not return workspace data.");return n},Be=async(o,n)=>{o.kind!=="projects"&&Z(o.projectId);let m=S(E);I.set(m,n);try{await P({...Q,type:"workspace-subscribe",id:S(E),payload:{subscriptionId:m,query:o}})}catch(w){throw I.delete(m),J||W({...Q,type:"workspace-unsubscribe",id:S(E),payload:{subscriptionId:m}}),w}return()=>{!I.delete(m)||J||W({...Q,type:"workspace-unsubscribe",id:S(E),payload:{subscriptionId:m}})}},Se=async o=>{if("key"in o&&(o.key.length===0||o.key.length>128))throw new u("HOST_REJECTED","Storage key must contain 1 to 128 characters.");if(o.op==="set"&&!ne(o.value))throw new u("HOST_REJECTED","Storage values must be JSON.");if(o.op==="set"&&new TextEncoder().encode(JSON.stringify(o.value)).length>65536)throw new u("HOST_REJECTED","Storage value exceeds 64 KiB.");let n=await H({...Q,type:"storage",id:S(E),payload:o});if(!n||!("storage"in n)||n.op!==o.op)throw new u("HOST_REJECTED","Host did not return storage data.");return n};return{onAction:o=>(f=o,()=>{f===o&&(f=null)}),listProjects:async()=>{let o=await Xe({kind:"projects"});if(o.kind!=="projects")throw new u("HOST_REJECTED","Expected projects.");return o},listWorktrees:async o=>{let n=await Xe({kind:"worktrees",projectId:o});if(n.kind!=="worktrees")throw new u("HOST_REJECTED","Expected worktrees.");return n},listSessions:async o=>{let n=await Xe({kind:"sessions",projectId:o});if(n.kind!=="sessions")throw new u("HOST_REJECTED","Expected sessions.");return n},onProjects:o=>Be({kind:"projects"},n=>{n.kind==="projects"&&o(n)}),onWorktrees:(o,n)=>Be({kind:"worktrees",projectId:o},m=>{m.kind==="worktrees"&&n(m)}),onSessions:(o,n)=>Be({kind:"sessions",projectId:o},m=>{m.kind==="sessions"&&n(m)}),openSession:async o=>{Z(o),await P({...Q,type:"open-session",id:S(E),payload:{sessionId:o}})},storage:{get:async o=>{let n=await Se({op:"get",key:o});return n.op==="get"&&n.found?n.value:void 0},set:async(o,n)=>{await Se({op:"set",key:o,value:n})},delete:async o=>{await Se({op:"delete",key:o})},keys:async()=>{let o=await Se({op:"keys"});if(o.op!=="keys")throw new u("HOST_REJECTED","Expected storage keys.");return o.keys}},onReady:o=>(l.add(o),T&&o(T),()=>{l.delete(o)}),onDirectory:o=>(p.add(o),T&&o(T.directory),()=>{p.delete(o)}),onSession:o=>(s.add(o),T&&o(T.session),()=>{s.delete(o)}),onSessionLifecycle:o=>(c.add(o),j&&o(j),()=>{c.delete(o)}),onConnection:o=>(h.add(o),T&&o(T.connection),()=>{h.delete(o)}),onSettings:o=>(A.add(o),T&&o(T.settings),()=>{A.delete(o)}),onItem:o=>(i.add(o),T&&o(T.item),()=>{i.delete(o)}),onResolve:o=>(g=o,()=>{g===o&&(g=null)}),toast:o=>{let n=o.message.trim();return!n||n.length>Te?Promise.reject(new u("HOST_REJECTED",`Toast message must contain 1 to ${Te} characters.`)):o.copy&&o.copy!==!0&&(!o.copy.text.length||o.copy.text.length>_e)?Promise.reject(new u("HOST_REJECTED",`Toast copy text must contain 1 to ${_e} characters.`)):P({channel:x,v:1,type:"toast",id:S(E),payload:{...o,message:n}})},openUrl:o=>P({channel:x,v:1,type:"open-url",id:S(E),payload:{url:o}}),openSurface:o=>P({channel:x,v:1,type:"open-surface",id:S(E),payload:{surfaceId:o}}),writeClipboard:o=>P({channel:x,v:1,type:"clipboard-write",id:S(E),payload:{text:o}}),compose:o=>P({channel:x,v:1,type:"compose",id:S(E),payload:o}),attach:o=>P({channel:x,v:1,type:"attach",id:S(E),payload:re(o)}),startSession:async o=>{o.projectId!==void 0&&Z(o.projectId);let n=o.worktree;n&&n!==!0&&(n.kind==="existing"?Z(n.directory):(n.name!==void 0&&Z(n.name,200),n.baseBranch!==void 0&&Z(n.baseBranch,200)));let m=await H({channel:x,v:1,type:"start-session",id:S(E),payload:We(o)},e.requestTimeoutMs??18e4);if(!Ve(m))throw new u("HOST_REJECTED","Host did not return a session.");return m},prompt:o=>H({channel:x,v:1,type:"prompt",id:S(E),payload:Qe(o)}).then(n=>{if(!je(n))throw new u("HOST_REJECTED","Host did not return a prompt result.");return n}),sessionLink:o=>P({channel:x,v:1,type:"session-link",id:S(E),payload:re(o)}),close:()=>P({channel:x,v:1,type:"close",id:S(E)}),oauthStart:()=>P({channel:x,v:1,type:"oauth-start",id:S(E)}),oauthDisconnect:()=>P({channel:x,v:1,type:"oauth-disconnect",id:S(E)}),request:o=>(Oe(o.path)?H({channel:x,v:1,type:"request",id:S(E),payload:o}):Pt()).then(n=>{if(!Le(n))throw new u("HOST_REJECTED","Host request result was empty.");return n}),serviceRequest:o=>(Oe(o.path)?H({channel:x,v:1,type:"service-request",id:S(E),payload:o}):Pt()).then(n=>{if(!Le(n))throw new u("HOST_REJECTED","Host service request result was empty.");return n}),serviceStatus:()=>H({channel:x,v:1,type:"service-status",id:S(E)}).then(o=>{if(!et(o))throw new u("HOST_REJECTED","Host did not return service status.");return o}),readFile:o=>(se(o)?H({channel:x,v:1,type:"file-read",id:S(E),payload:{path:o}}):Ce()).then(n=>{if(!tt(n))throw new u("HOST_REJECTED","Host did not return file content.");return n}),writeFile:(o,n)=>se(o)?n.length>Ae?Promise.reject(new u("FILE_TOO_LARGE",`Content is over ${Ae} characters.`)):H({channel:x,v:1,type:"file-write",id:S(E),payload:{path:o,content:n}}).then(m=>{if(!ot(m))throw new u("HOST_REJECTED","Host did not confirm the write.");return m}):Ce(),listDir:o=>(se(o)?H({channel:x,v:1,type:"file-list",id:S(E),payload:{path:o}}):Ce()).then(n=>{if(!nt(n))throw new u("HOST_REJECTED","Host did not return directory entries.");return n}),stat:o=>(se(o)?H({channel:x,v:1,type:"file-stat",id:S(E),payload:{path:o}}):Ce()).then(n=>{if(!rt(n))throw new u("HOST_REJECTED","Host did not return file status.");return n}),generate:o=>{let n=o.prompt.trim(),m=o.system?.trim();if(n.length===0||n.length>we)return Promise.reject(new u("HOST_REJECTED",`Prompt must be 1 to ${we} characters.`));if(m!==void 0&&(m.length===0||m.length>ve))return Promise.reject(new u("HOST_REJECTED",`System prompt must be 1 to ${ve} characters.`));let w=o.maxOutputTokens===void 0?void 0:Math.min(qe,Math.max(1,Math.floor(o.maxOutputTokens)));if(w!==void 0&&!Number.isFinite(w))return Promise.reject(new u("HOST_REJECTED","maxOutputTokens must be a number."));let F={prompt:n};return m!==void 0&&(F.system=m),w!==void 0&&(F.maxOutputTokens=w),H({channel:x,v:1,type:"generate",id:S(E),payload:F},e.requestTimeoutMs??Je).then(G=>{if(!st(G))throw new u("HOST_REJECTED","Host did not return generated text.");return G})},setBadge:o=>P({channel:x,v:1,type:"badge",id:S(E),payload:{count:Ze(o)}}),dispose:()=>{for(let o of I.keys())W({...Q,type:"workspace-unsubscribe",id:S(E),payload:{subscriptionId:o}});I.clear(),J=!0,g=null,f=null,t.removeEventListener("message",Tt);for(let o of k.values())clearTimeout(o.timer),o.reject(new u("HOST_UNAVAILABLE","Host client was disposed."));k.clear(),l.clear(),p.clear(),s.clear(),c.clear(),h.clear(),A.clear(),i.clear()}}};var fo=[["--oc-bg","background"],["--oc-elevated","elevated"],["--oc-fg","foreground"],["--oc-muted","muted"],["--oc-subtle","subtle"],["--oc-border","border"],["--oc-hover","hover"],["--oc-selection","selection"],["--oc-focus","focus"],["--oc-primary","primary"],["--oc-muted-surface","mutedSurface"],["--oc-elevated-fg","elevatedForeground"],["--oc-active","active"],["--oc-selection-fg","selectionForeground"],["--oc-primary-fg","primaryForeground"],["--oc-primary-text","primaryText"],["--oc-success-text","successText"],["--oc-warning-text","warningText"],["--oc-error-text","errorText"],["--oc-info-text","infoText"],["--oc-success","success"],["--oc-warning","warning"],["--oc-error","error"],["--oc-info","info"],["--oc-font","font"],["--oc-mono","mono"],["--oc-radius","radius"],["--surface-background","background"],["--surface-elevated","elevated"],["--surface-foreground","foreground"],["--surface-muted-foreground","muted"],["--surface-subtle","subtle"],["--interactive-border","border"],["--interactive-hover","hover"],["--interactive-selection","selection"],["--interactive-focus-ring","focus"],["--primary","primary"],["--surface-muted","mutedSurface"],["--surface-elevated-foreground","elevatedForeground"],["--interactive-active","active"],["--interactive-selection-foreground","selectionForeground"],["--primary-foreground","primaryForeground"],["--primary-text","primaryText"],["--success-text","successText"],["--warning-text","warningText"],["--error-text","errorText"],["--info-text","infoText"],["--status-success","success"],["--status-warning","warning"],["--status-error","error"],["--status-info","info"],["--font-sans","font"],["--font-mono","mono"],["--radius","radius"]],Ft=(e,t)=>{t.style.colorScheme=e.mode;for(let[r,a]of fo)t.style.setProperty(r,e.tokens[a]);t.style.setProperty("font-family",e.tokens.font),t.style.setProperty("font-size","0.875rem"),t.style.setProperty("line-height","1.45"),t.style.setProperty("color",e.tokens.foreground)},ct=(e,t)=>{Ft(e.theme,t),t.dataset&&(t.dataset.ocSurface=e.surface,t.dataset.ocTheme=e.theme.mode)};var mo={"surface-background":"bg","surface-elevated":"elevated","surface-elevated-foreground":"elevated-fg","surface-foreground":"fg","surface-muted-foreground":"muted","surface-muted":"muted-surface","surface-subtle":"subtle","interactive-border":"border","interactive-hover":"hover","interactive-active":"active","interactive-selection":"selection","interactive-selection-foreground":"selection-fg","interactive-focus-ring":"focus",primary:"primary","primary-foreground":"primary-fg","primary-text":"primary-text","success-text":"success-text","warning-text":"warning-text","error-text":"error-text","info-text":"info-text","status-success":"success","status-warning":"warning","status-error":"error","status-info":"info","font-sans":"font","font-mono":"mono",radius:"radius"},y=(e,t)=>`var(--${e}, var(--oc-${mo[e]}, ${t}))`,ee=y("surface-background","transparent"),Re=y("surface-elevated","transparent"),le=y("surface-elevated-foreground","inherit"),pe=y("surface-foreground","inherit"),v=y("surface-muted-foreground","gray"),ho=y("surface-muted","transparent"),B=y("interactive-border","currentColor"),X=y("interactive-hover","transparent"),te=y("interactive-active","transparent"),dt=y("interactive-selection","transparent"),lt=y("interactive-selection-foreground","inherit"),Vt=y("interactive-focus-ring","currentColor"),z=y("primary","currentColor"),pt=y("primary-text","inherit"),ut=y("error-text","inherit"),go=y("font-sans","inherit"),ft=y("font-mono","monospace"),zt=y("radius","9px"),O=(e,t,r="transparent")=>`color-mix(in srgb, ${e} ${t}%, ${r})`,Kt=`box-shadow: 0 0 0 2px ${Vt};`,Ge=e=>{let t=y(`status-${e}`,"currentColor");return`
32
32
  .oc-sdk[data-tone="${e}"], .oc-sdk [data-tone="${e}"] { --oc-sdk-tone: ${t}; --oc-sdk-tone-text: ${y(`${e}-text`,"inherit")}; }`},$=`
33
- ${Be}
34
- .oc-sdk { box-sizing: border-box; color: ${ue}; font-family: ${mo}; font-size: 0.875rem; line-height: 1.45; }
33
+ ${ze}
34
+ .oc-sdk { box-sizing: border-box; color: ${pe}; font-family: ${go}; font-size: 0.875rem; line-height: 1.45; }
35
35
  .oc-sdk *, .oc-sdk *::before, .oc-sdk *::after { box-sizing: border-box; }
36
36
  /* :where() keeps the reset at zero specificity so every primitive class below overrides it. */
37
37
  :where(.oc-sdk) :where(button, input, textarea), :where(button.oc-sdk, input.oc-sdk, textarea.oc-sdk) { font: inherit; color: inherit; margin: 0; }
38
38
  :where(.oc-sdk) :where(button), :where(button.oc-sdk) { cursor: pointer; background: none; border: 0; padding: 0; }
39
39
  .oc-sdk button:disabled, button.oc-sdk:disabled, .oc-sdk[aria-disabled="true"], .oc-sdk [aria-disabled="true"] { opacity: .5; pointer-events: none; }
40
- .oc-sdk :focus-visible { outline: none; ${Ft} }
41
- .oc-sdk-mono { font-family: ${pt}; }
40
+ .oc-sdk :focus-visible { outline: none; ${Kt} }
41
+ .oc-sdk-mono { font-family: ${ft}; }
42
42
  .oc-sdk-muted { color: ${v}; }
43
- ${Re("success")}${Re("warning")}${Re("error")}${Re("info")}
44
- .oc-sdk[data-tone="primary"], .oc-sdk [data-tone="primary"] { --oc-sdk-tone: ${z}; --oc-sdk-tone-text: ${dt}; }
43
+ ${Ge("success")}${Ge("warning")}${Ge("error")}${Ge("info")}
44
+ .oc-sdk[data-tone="primary"], .oc-sdk [data-tone="primary"] { --oc-sdk-tone: ${z}; --oc-sdk-tone-text: ${pt}; }
45
45
 
46
- .oc-sdk-btn { display: inline-flex; align-items: center; justify-content: center; gap: 6px; height: 36px; padding: 0 14px; border: 1px solid transparent; border-radius: ${Bt}; font-size: 0.875rem; font-weight: 500; line-height: 1; white-space: nowrap; transition: background 150ms ease-out, color 150ms ease-out; }
46
+ .oc-sdk-btn { display: inline-flex; align-items: center; justify-content: center; gap: 6px; height: 36px; padding: 0 14px; border: 1px solid transparent; border-radius: ${zt}; font-size: 0.875rem; font-weight: 500; line-height: 1; white-space: nowrap; transition: background 150ms ease-out, color 150ms ease-out; }
47
47
  .oc-sdk-btn[data-size="sm"] { height: 32px; padding: 0 10px; font-size: 0.8125rem; }
48
48
  .oc-sdk-btn[data-size="xs"] { height: 24px; padding: 0 8px; font-size: 0.75rem; border-radius: 6px; }
49
- .oc-sdk-btn[data-variant="default"] { color: ${dt}; background: ${O(z,10,te)}; border-color: ${O(z,12)}; }
50
- .oc-sdk-btn[data-variant="default"]:hover { background: ${O(z,16,te)}; }
51
- .oc-sdk-btn[data-variant="default"]:active { background: ${O(z,22,te)}; }
52
- .oc-sdk-btn[data-variant="secondary"] { background: ${fo}; color: var(--oc-fg); }
49
+ .oc-sdk-btn[data-variant="default"] { color: ${pt}; background: ${O(z,10,ee)}; border-color: ${O(z,12)}; }
50
+ .oc-sdk-btn[data-variant="default"]:hover { background: ${O(z,16,ee)}; }
51
+ .oc-sdk-btn[data-variant="default"]:active { background: ${O(z,22,ee)}; }
52
+ .oc-sdk-btn[data-variant="secondary"] { background: ${ho}; color: var(--oc-fg); }
53
53
  .oc-sdk-btn[data-variant="secondary"]:hover { background-image: linear-gradient(${X}, ${X}); }
54
- .oc-sdk-btn[data-variant="secondary"]:active { background-image: linear-gradient(${oe}, ${oe}); }
55
- .oc-sdk-btn[data-variant="outline"] { background: ${Ce}; color: ${pe}; border-color: ${B}; }
54
+ .oc-sdk-btn[data-variant="secondary"]:active { background-image: linear-gradient(${te}, ${te}); }
55
+ .oc-sdk-btn[data-variant="outline"] { background: ${Re}; color: ${le}; border-color: ${B}; }
56
56
  .oc-sdk-btn[data-variant="outline"]:hover { background-image: linear-gradient(${X}, ${X}); }
57
- .oc-sdk-btn[data-variant="outline"]:active { background-image: linear-gradient(${oe}, ${oe}); }
57
+ .oc-sdk-btn[data-variant="outline"]:active { background-image: linear-gradient(${te}, ${te}); }
58
58
  .oc-sdk-btn[data-variant="ghost"] { background: transparent; }
59
59
  .oc-sdk-btn[data-variant="ghost"]:hover { background: ${X}; }
60
- .oc-sdk-btn[data-variant="ghost"]:active { background: ${oe}; }
61
- .oc-sdk-btn[data-variant="destructive"] { --oc-sdk-tone: ${y("status-error","red")}; color: ${lt}; background: ${O("var(--oc-sdk-tone)",7,te)}; border-color: ${O("var(--oc-sdk-tone)",12)}; }
62
- .oc-sdk-btn[data-variant="destructive"]:hover { background: ${O("var(--oc-sdk-tone)",9,te)}; }
63
- .oc-sdk-btn[data-variant="destructive"]:active { background: ${O("var(--oc-sdk-tone)",11,te)}; }
60
+ .oc-sdk-btn[data-variant="ghost"]:active { background: ${te}; }
61
+ .oc-sdk-btn[data-variant="destructive"] { --oc-sdk-tone: ${y("status-error","red")}; color: ${ut}; background: ${O("var(--oc-sdk-tone)",7,ee)}; border-color: ${O("var(--oc-sdk-tone)",12)}; }
62
+ .oc-sdk-btn[data-variant="destructive"]:hover { background: ${O("var(--oc-sdk-tone)",9,ee)}; }
63
+ .oc-sdk-btn[data-variant="destructive"]:active { background: ${O("var(--oc-sdk-tone)",11,ee)}; }
64
64
  .oc-sdk-btn[data-loading="true"] { opacity: .5; pointer-events: none; }
65
65
  .oc-sdk-btn > .oc-sdk-spinner-ring { width: 14px; height: 14px; }
66
66
 
67
67
  .oc-sdk-field { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
68
68
  .oc-sdk-field-label { font-size: 0.8125rem; font-weight: 500; }
69
69
  .oc-sdk-field-note { font-size: 0.75rem; color: ${v}; }
70
- .oc-sdk-field[data-invalid="true"] .oc-sdk-field-note { color: ${lt}; }
71
- .oc-sdk-input { display: block; width: 100%; min-width: 0; height: 36px; padding: 0 12px; border: 0; border-radius: ${Bt}; background: ${Ce}; color: ${pe}; font-size: 0.875rem; line-height: 1.45; appearance: none; box-shadow: inset 0 0 0 1px ${O(B,60)}; transition: background 150ms ease-out, box-shadow 150ms ease-out; }
70
+ .oc-sdk-field[data-invalid="true"] .oc-sdk-field-note { color: ${ut}; }
71
+ .oc-sdk-input { display: block; width: 100%; min-width: 0; height: 36px; padding: 0 12px; border: 0; border-radius: ${zt}; background: ${Re}; color: ${le}; font-size: 0.875rem; line-height: 1.45; appearance: none; box-shadow: inset 0 0 0 1px ${O(B,60)}; transition: background 150ms ease-out, box-shadow 150ms ease-out; }
72
72
  textarea.oc-sdk-input { height: auto; padding: 8px 12px; resize: vertical; }
73
73
  .oc-sdk-input::placeholder { color: ${v}; }
74
74
  .oc-sdk-input:hover:not(:focus) { background-image: linear-gradient(${X}, ${X}); }
75
- .oc-sdk-input:focus, .oc-sdk-input:focus-visible { box-shadow: inset 0 0 0 2px ${zt}; }
75
+ .oc-sdk-input:focus, .oc-sdk-input:focus-visible { box-shadow: inset 0 0 0 2px ${Vt}; }
76
76
  .oc-sdk-field[data-invalid="true"] .oc-sdk-input { box-shadow: inset 0 0 0 1px ${y("status-error","red")}; }
77
77
  .oc-sdk-field[data-invalid="true"] .oc-sdk-input:focus { box-shadow: inset 0 0 0 2px ${y("status-error","red")}; }
78
- .oc-sdk-input[data-mono="true"] { font-family: ${pt}; }
78
+ .oc-sdk-input[data-mono="true"] { font-family: ${ft}; }
79
79
 
80
80
  .oc-sdk-search { position: relative; min-width: 0; }
81
81
  .oc-sdk-search .oc-sdk-input { padding-left: 34px; padding-right: 34px; }
@@ -83,22 +83,22 @@ textarea.oc-sdk-input { height: auto; padding: 8px 12px; resize: vertical; }
83
83
  .oc-sdk-search[data-active="true"] .oc-sdk-search-icon { color: ${z}; }
84
84
  .oc-sdk-search-clear { position: absolute; right: 6px; top: 50%; transform: translateY(-50%); display: none; align-items: center; justify-content: center; width: 24px; height: 24px; border-radius: 6px; color: ${v}; }
85
85
  .oc-sdk-search[data-active="true"] .oc-sdk-search-clear { display: inline-flex; }
86
- .oc-sdk-search-clear:hover { background: ${X}; color: ${ue}; }
86
+ .oc-sdk-search-clear:hover { background: ${X}; color: ${pe}; }
87
87
 
88
88
  .oc-sdk-select { position: relative; display: flex; flex-direction: column; gap: 4px; min-width: 0; }
89
- .oc-sdk-trigger { display: inline-flex; align-items: center; gap: 6px; width: 100%; min-width: 0; height: 32px; padding: 0 8px 0 10px; border: 1px solid ${B}; border-radius: 6px; background: ${Ce}; color: ${pe}; font-size: 0.8125rem; text-align: left; transition: background 150ms ease-out; }
89
+ .oc-sdk-trigger { display: inline-flex; align-items: center; gap: 6px; width: 100%; min-width: 0; height: 32px; padding: 0 8px 0 10px; border: 1px solid ${B}; border-radius: 6px; background: ${Re}; color: ${le}; font-size: 0.8125rem; text-align: left; transition: background 150ms ease-out; }
90
90
  .oc-sdk-trigger:hover { background-image: linear-gradient(${X}, ${X}); }
91
- .oc-sdk-trigger[aria-expanded="true"] { background-image: linear-gradient(${oe}, ${oe}); }
91
+ .oc-sdk-trigger[aria-expanded="true"] { background-image: linear-gradient(${te}, ${te}); }
92
92
  .oc-sdk-trigger-value { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
93
93
  .oc-sdk-trigger-value[data-empty="true"] { color: ${v}; }
94
94
  .oc-sdk-trigger-chevron { flex: 0 0 auto; color: ${v}; }
95
- .oc-sdk-popup { --surface-foreground: ${pe}; position: fixed; z-index: 50; display: flex; flex-direction: column; gap: 2px; min-width: 160px; max-width: calc(100vw - 16px); max-height: min(320px, calc(100vh - 16px)); overflow: auto; padding: 4px; border: 1px solid ${O(B,60)}; border-radius: 12px; background: ${Ce}; color: ${pe}; box-shadow: 0 8px 24px ${O(ue,12)}; }
95
+ .oc-sdk-popup { --surface-foreground: ${le}; position: fixed; z-index: 50; display: flex; flex-direction: column; gap: 2px; min-width: 160px; max-width: calc(100vw - 16px); max-height: min(320px, calc(100vh - 16px)); overflow: auto; padding: 4px; border: 1px solid ${O(B,60)}; border-radius: 12px; background: ${Re}; color: ${le}; box-shadow: 0 8px 24px ${O(pe,12)}; }
96
96
  .oc-sdk-popup-search { flex: 0 0 auto; padding: 2px 2px 4px; }
97
97
  .oc-sdk-popup-search .oc-sdk-input { height: 32px; font-size: 0.8125rem; }
98
98
  .oc-sdk-option { display: flex; align-items: center; gap: 8px; width: 100%; padding: 6px 8px; border-radius: 8px; font-size: 0.8125rem; text-align: left; }
99
99
  .oc-sdk-option[data-active="true"] { background: ${X}; }
100
- .oc-sdk-option[aria-selected="true"] { background: ${at}; color: ${ct}; }
101
- .oc-sdk-option[data-destructive="true"] { color: ${lt}; }
100
+ .oc-sdk-option[aria-selected="true"] { background: ${dt}; color: ${lt}; }
101
+ .oc-sdk-option[data-destructive="true"] { color: ${ut}; }
102
102
  .oc-sdk-option[data-destructive="true"][data-active="true"] { background: ${O(y("status-error","red"),10)}; }
103
103
  .oc-sdk-option-label { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
104
104
  .oc-sdk-option-hint { flex: 0 0 auto; font-size: 0.75rem; color: ${v}; }
@@ -111,20 +111,20 @@ textarea.oc-sdk-input { height: auto; padding: 8px 12px; resize: vertical; }
111
111
  .oc-sdk-check-box > svg { display: none; }
112
112
  .oc-sdk-check[aria-checked="true"] .oc-sdk-check-box > svg { display: block; }
113
113
  .oc-sdk-check-thumb { flex: 0 0 auto; position: relative; width: 36px; height: 20px; border-radius: 9999px; background: ${B}; transition: background 150ms ease-out; }
114
- .oc-sdk-check-thumb::after { content: ""; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; border-radius: 9999px; background: ${te}; transition: transform 150ms ease-out; }
114
+ .oc-sdk-check-thumb::after { content: ""; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; border-radius: 9999px; background: ${ee}; transition: transform 150ms ease-out; }
115
115
  .oc-sdk-check[aria-checked="true"] .oc-sdk-check-thumb { background: ${z}; }
116
116
  .oc-sdk-check[aria-checked="true"] .oc-sdk-check-thumb::after { transform: translateX(16px); }
117
117
  .oc-sdk-check:focus-visible { box-shadow: none; }
118
- .oc-sdk-check:focus-visible .oc-sdk-check-box, .oc-sdk-check:focus-visible .oc-sdk-check-thumb { ${Ft} }
118
+ .oc-sdk-check:focus-visible .oc-sdk-check-box, .oc-sdk-check:focus-visible .oc-sdk-check-thumb { ${Kt} }
119
119
  .oc-sdk-check-text { display: flex; flex-direction: column; min-width: 0; }
120
120
  .oc-sdk-check-label { font-size: 0.875rem; }
121
121
  .oc-sdk-check-desc { font-size: 0.75rem; color: ${v}; }
122
122
 
123
123
  .oc-sdk-tabs { display: inline-flex; gap: 2px; padding: 2px; border-radius: 10px; max-width: 100%; overflow: auto; }
124
- .oc-sdk-tabs[data-track="true"] { background: ${O(ue,4)}; }
124
+ .oc-sdk-tabs[data-track="true"] { background: ${O(pe,4)}; }
125
125
  .oc-sdk-tab { display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 10px; border: 1px solid transparent; border-radius: 8px; font-size: 0.8125rem; font-weight: 500; color: ${v}; white-space: nowrap; transition: color 150ms ease-out, background 150ms ease-out; }
126
- .oc-sdk-tab:hover { color: ${ue}; }
127
- .oc-sdk-tab[aria-selected="true"] { color: ${ct}; background: ${at}; border-color: ${B}; }
126
+ .oc-sdk-tab:hover { color: ${pe}; }
127
+ .oc-sdk-tab[aria-selected="true"] { color: ${lt}; background: ${dt}; border-color: ${B}; }
128
128
  .oc-sdk-tab-count { font-size: 0.75rem; font-variant-numeric: tabular-nums; color: ${v}; }
129
129
 
130
130
  .oc-sdk-badge { display: inline-flex; align-items: center; padding: 1px 6px; border-radius: 9999px; font-size: 11px; font-weight: 500; line-height: 16px; white-space: nowrap; background: ${X}; color: ${v}; }
@@ -133,8 +133,8 @@ textarea.oc-sdk-input { height: auto; padding: 8px 12px; resize: vertical; }
133
133
  .oc-sdk-list { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
134
134
  .oc-sdk-row { display: flex; align-items: center; gap: 8px; width: 100%; padding: 6px 8px; border-radius: 6px; text-align: left; transition: background 120ms ease-out; }
135
135
  .oc-sdk-row:hover, .oc-sdk-row[data-active="true"] { background: ${X}; }
136
- .oc-sdk-row[aria-selected="true"] { background: ${at}; color: ${ct}; }
137
- .oc-sdk-row-lead { flex: 0 0 auto; width: 64px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: ${pt}; font-size: 0.75rem; color: ${v}; }
136
+ .oc-sdk-row[aria-selected="true"] { background: ${dt}; color: ${lt}; }
137
+ .oc-sdk-row-lead { flex: 0 0 auto; width: 64px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: ${ft}; font-size: 0.75rem; color: ${v}; }
138
138
  .oc-sdk-row-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
139
139
  .oc-sdk-row-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
140
140
  .oc-sdk-row-sub { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 0.75rem; color: ${v}; }
@@ -171,6 +171,6 @@ textarea.oc-sdk-input { height: auto; padding: 8px 12px; resize: vertical; }
171
171
  .oc-sdk-menu { position: relative; display: inline-flex; }
172
172
 
173
173
  .oc-sdk-text { white-space: pre-wrap; overflow-wrap: anywhere; }
174
- .oc-sdk-text a { color: ${dt}; text-decoration: underline; text-underline-offset: 2px; }
174
+ .oc-sdk-text a { color: ${pt}; text-decoration: underline; text-underline-offset: 2px; }
175
175
  .oc-sdk-text img { display: block; max-width: 100%; margin: 8px 0; border-radius: 8px; border: 1px solid ${O(B,60)}; }
176
- `;var xo=e=>24+e*308;function jt(e){let t=new Map,r=new Map;for(let i of e.nodes)r.set(i.column,[...r.get(i.column)??[],i]);let a=[...r.keys()].sort((i,g)=>i-g),l=new Map(a.map(i=>[i,xo(i)])),p=new Map,s=0;for(let i of a)(r.get(i)??[]).slice().sort((f,x)=>(p.get(f.parentId??"")??-1)-(p.get(x.parentId??"")??-1)||(f.createdAt??0)-(x.createdAt??0)||f.id.localeCompare(x.id)).forEach((f,x)=>{let I=58+x*94;t.set(f.id,{x:l.get(i)??0,y:I}),p.set(f.id,p.size),s=Math.max(s,I+80+24)});let c=t.get(e.rootId),h=e.nodes.filter(i=>i.parentId===e.rootId).map(i=>t.get(i.id)).filter(i=>i!==void 0);if(c&&h.length>0&&(r.get(0)?.length??0)===1){let i=Math.min(...h.map(f=>f.y)),g=Math.max(...h.map(f=>f.y));c.y=Math.round((i+g)/2)}let A=24+(Math.max(0,...a)+1)*308-76+24;return{boxes:t,edges:bo(e.edges,t),columnX:l,width:A,height:Math.max(s,162)}}function Vt(e,t){if(t<=1)return 80/2;let r=Math.min(12,80*.44/(t-1));return 80/2+(e-(t-1)/2)*r}function bo(e,t){let r=e.filter(s=>t.has(s.from)&&t.has(s.to)),a=s=>(t.get(s)?.y??0)+80/2,l=new Map,p=new Map;for(let s of r)l.set(s.from,[...l.get(s.from)??[],s]),p.set(s.to,[...p.get(s.to)??[],s]);for(let s of l.values())s.sort((c,h)=>a(c.to)-a(h.to));for(let s of p.values())s.sort((c,h)=>a(c.from)-a(h.from));return r.map(s=>{let c=t.get(s.from),h=t.get(s.to),A=l.get(s.from)??[],i=p.get(s.to)??[],g=c.x+232,f=c.y+Vt(A.indexOf(s),A.length),x=h.x,I=h.y+Vt(i.indexOf(s),i.length),W=x>g?Math.max(32,(x-g)*.5):90,E=`M ${g} ${f} C ${g+W} ${f}, ${x-W} ${I}, ${x} ${I}`;return{...s,d:E,sx:g,sy:f,tx:x,ty:I}})}function ft(e,t,r){let a=new Set,l=[t];for(;l.length>0;){let p=l.pop();for(let s of e){let c=r==="down"?s.from===p?s.to:void 0:s.to===p?s.from:void 0;c!==void 0&&!a.has(c)&&c!==t&&(a.add(c),l.push(c))}}return a}function qt(e){let t=Math.max(0,Math.round(e/1e3));if(t<60)return`${t}s`;let r=Math.floor(t/60);return r<60?`${r}m ${String(t%60).padStart(2,"0")}s`:`${Math.floor(r/60)}h ${String(r%60).padStart(2,"0")}m`}function mt(e){if(e)return e.includes("/")?e.slice(e.indexOf("/")+1):e}function Yt(e){return e>=1e6?`${(e/1e6).toFixed(1)}M`:e>=1e3?`${(e/1e3).toFixed(e>=1e4?0:1)}k`:String(e)}var So={running:"running",queued:"queued",completed:"completed",failed:"failed",cancelled:"cancelled",idle:"idle"};function fe(e,t){if(e.kind==="root")return e.rawStatus;let r=e.rawStatus===e.state?So[e.state]:e.rawStatus,a=e.startedAt;return a===void 0?r:e.state==="running"?`${r} \xB7 ${qt(t-a)}`:e.endedAt!==void 0?`${r} \xB7 ${qt(e.endedAt-a)}`:r}var To=new Set(["running","queued","completed","failed","cancelled","idle"]),he=e=>e!==null&&typeof e=="object"&&!Array.isArray(e),J=e=>typeof e=="number"&&Number.isFinite(e),me=e=>e===void 0||typeof e=="string",ce=e=>e===void 0||J(e),_o=e=>typeof e=="string"&&To.has(e);function yo(e){return he(e)?typeof e.id=="string"&&(e.kind==="root"||e.kind==="task")&&typeof e.sessionId=="string"&&typeof e.title=="string"&&_o(e.state)&&typeof e.rawStatus=="string"&&me(e.agent)&&me(e.model)&&ce(e.createdAt)&&ce(e.startedAt)&&ce(e.endedAt)&&me(e.summary)&&me(e.error)&&ce(e.tokens)&&ce(e.costUsd)&&ce(e.toolCalls)&&me(e.parentId)&&J(e.column)&&J(e.wave):!1}function Ao(e){return he(e)&&typeof e.id=="string"&&typeof e.from=="string"&&typeof e.to=="string"&&(e.kind==="spawn"||e.kind==="uses")}function wo(e){return he(e)&&J(e.column)&&J(e.total)&&J(e.done)&&J(e.running)}function vo(e){return he(e)&&J(e.omittedNodes)&&Number.isInteger(e.omittedNodes)&&e.omittedNodes>=0}function Mo(e){return he(e)&&(e.status==="ok"||e.status==="unknown-session")&&typeof e.rootId=="string"&&typeof e.focusId=="string"&&typeof e.title=="string"&&Array.isArray(e.nodes)&&e.nodes.every(yo)&&Array.isArray(e.edges)&&e.edges.every(Ao)&&Array.isArray(e.columns)&&e.columns.every(wo)&&J(e.models)&&(e.truncated===void 0||vo(e.truncated))}function Oo(e){let t=JSON.parse(e);if(!Mo(t))throw new Error("service answered with an unexpected graph shape");return t}var Ue=class{constructor(t){this.deps=t}deps;session=void 0;generation=0;inFlight=!1;pending=!1;signature="";setSession(t){t!==this.session&&(this.session=t,this.invalidate())}invalidate(){this.generation++,this.signature="",this.refresh()}async refresh(){let t=this.session;if(t===void 0)return;if(t===null){this.signature="",this.deps.show({kind:"no-session"});return}if(this.deps.isHidden()){this.deps.schedule(5e3,()=>{this.refresh()});return}if(this.inFlight){this.pending=!0;return}this.inFlight=!0;let r=this.generation;try{let a=await this.deps.fetch(t);if(r!==this.generation)return;if(a.status!==200)throw new Error(`service answered HTTP ${a.status}: ${a.body.slice(0,200)}`);let l=Oo(a.body);l.status!=="ok"||l.nodes.length<=1?(this.signature="",this.deps.show({kind:"empty"})):a.body!==this.signature&&(this.signature=a.body,this.deps.show({kind:"graph",graph:l}));let p=l.nodes.some(s=>s.state==="running"||s.state==="queued");this.deps.schedule(p?1500:5e3,()=>{this.refresh()})}catch(a){if(r!==this.generation)return;this.signature="",this.deps.show({kind:"error",error:a}),this.deps.schedule(1e4,()=>{this.refresh()})}finally{this.inFlight=!1,(this.pending||r!==this.generation)&&(this.pending=!1,this.refresh())}}};var Jt="http://www.w3.org/2000/svg";document.documentElement.style.setProperty("--node-card-width",`${232}px`);document.documentElement.style.setProperty("--node-card-height",`${80}px`);var j=st(),G=e=>document.querySelector(e),d={app:G("#app"),title:G("#title"),titleDot:G("#title-dot"),meta:G("#meta"),viewport:G("#viewport"),world:G("#world"),edges:G("#edges"),bands:G("#bands"),nodes:G("#nodes"),empty:G("#empty"),inspector:G("#inspector"),settings:G("#settings")},Ee=null,to=!1,M,C,Wt="",V,ne={},ht,_={x:0,y:0,k:1},de=new Map;function L(e,t="",r=""){let a=document.createElement(e);return t&&(a.className=t),r&&(a.textContent=r),a}function gt(e,t=""){d.empty.replaceChildren(L("strong","",e),...t?[L("p","",t)]:[]),d.empty.hidden=!1,d.world.hidden=!0,d.inspector.hidden=!0}function oo(e){return e instanceof u?e.code==="NO_SERVICE"?["Local service not allowed yet","Approve OmO Graph in Settings \u2192 Extensions so it can read the OmO task store."]:e.code==="SERVICE_FAILED"?["The local service did not start","Check Settings \u2192 Extensions; the next refresh retries it."]:e.code==="DISABLED"?["OmO Graph is paused","Resume it in Settings \u2192 Extensions."]:[`Request failed (${e.code})`,e.message]:["Request failed",e instanceof Error?e.message:String(e)]}function le(){d.world.style.transform=`translate(${_.x}px, ${_.y}px) scale(${_.k})`,d.app.style.setProperty("--zoom",String(_.k))}function De(){if(!C)return;let e=d.viewport.clientWidth,t=d.viewport.clientHeight,r=Math.min(1,Math.max(.62,Math.min((e-16)/C.width,(t-16)/C.height)));_.k=r,_.x=Math.round(C.width*r<=e?(e-C.width*r)/2:8),_.y=Math.round(Math.max(8,(t-C.height*r)/2)),le()}function no(e){let t=e?C?.boxes.get(e):void 0;if(!t)return De();_.k=Math.max(_.k,.8),_.x=Math.round(d.viewport.clientWidth/2-(t.x+232/2)*_.k),_.y=Math.round(d.viewport.clientHeight/2-(t.y+80/2)*_.k),le()}function ke(e,t=d.viewport.clientWidth/2,r=d.viewport.clientHeight/2){let a=Math.min(2,Math.max(.2,_.k*e));_.x=t-(t-_.x)*a/_.k,_.y=r-(r-_.y)*a/_.k,_.k=a,le()}var K,Et=!1;d.viewport.addEventListener("pointerdown",e=>{e.button===0&&(K={x:e.clientX,y:e.clientY,vx:_.x,vy:_.y,moved:!1})});window.addEventListener("pointermove",e=>{if(!K)return;let t=e.clientX-K.x,r=e.clientY-K.y;!K.moved&&Math.hypot(t,r)<4||(K.moved||(K.moved=!0,d.viewport.setPointerCapture?.(e.pointerId),d.app.classList.add("is-panning")),_.x=K.vx+t,_.y=K.vy+r,le())});window.addEventListener("pointerup",()=>{K?.moved&&(Et=!0,setTimeout(()=>{Et=!1},0)),K=void 0,d.app.classList.remove("is-panning")});d.viewport.addEventListener("wheel",e=>{e.preventDefault();let t=d.viewport.getBoundingClientRect();e.ctrlKey||e.metaKey||Math.abs(e.deltaY)>Math.abs(e.deltaX)*2&&!e.shiftKey?ke(Math.exp(-e.deltaY*(e.ctrlKey?.01:.0015)),e.clientX-t.left,e.clientY-t.top):(_.x-=e.deltaX||(e.shiftKey?e.deltaY:0),_.y-=e.shiftKey?0:e.deltaY,le())},{passive:!1});G("#btn-fit").addEventListener("click",De);G("#btn-locate").addEventListener("click",()=>{let e=M?.nodes.find(t=>t.kind==="task"&&t.state==="running");no(M?.focusId!==M?.rootId?M?.focusId:e?.id??M?.rootId)});G("#btn-in").addEventListener("click",()=>ke(1.2));G("#btn-out").addEventListener("click",()=>ke(1/1.2));window.addEventListener("keydown",e=>{e.target instanceof HTMLInputElement||(e.key==="0"?De():e.key==="+"||e.key==="="?ke(1.2):e.key==="-"&&ke(1/1.2))});function ge(e){if(V=e,!M)return;let t=M.edges,r=new Set(e?t.filter(s=>s.to===e).map(s=>s.from):[]),a=new Set(e?t.filter(s=>s.from===e).map(s=>s.to):[]),l=e?ft(t,e,"up"):new Set,p=e?ft(t,e,"down"):new Set;d.app.classList.toggle("has-hover",e!==void 0);for(let[s,c]of de)c.classList.toggle("is-hover",s===e),c.classList.toggle("is-input",r.has(s)),c.classList.toggle("is-output",a.has(s)),c.classList.toggle("is-reach",l.has(s)||p.has(s));for(let s of d.edges.querySelectorAll("path[data-edge]")){let c=s.dataset.from??"",h=s.dataset.to??"";s.classList.toggle("is-in",e!==void 0&&h===e),s.classList.toggle("is-out",e!==void 0&&c===e),s.classList.toggle("is-reach",e!==void 0&&(l.has(c)&&(l.has(h)||h===e)||p.has(h)&&(p.has(c)||c===e)))}Lo()}function Lo(){let e=M?.nodes.find(A=>A.id===(V??(M?.focusId!==M?.rootId?M?.focusId:void 0)));if(!e||!M){d.inspector.hidden=!0;return}let t=M.edges.filter(A=>A.to===e.id).length,r=M.edges.filter(A=>A.from===e.id).length,a=[fe(e,Date.now())];e.agent&&a.push(e.agent);let l=mt(e.model);l&&a.push(l),e.toolCalls!==void 0&&a.push(`${e.toolCalls} tools`),e.tokens!==void 0&&a.push(`${Yt(e.tokens)} tok`),e.costUsd!==void 0&&a.push(`$${e.costUsd.toFixed(2)}`);let p=L("div","i-head");p.append(L("span",`dot s-${e.state}`),L("strong","",e.title));let s=L("div","i-flow");s.append(L("span","i-in",`\u2190 ${t} input${t===1?"":"s"}`),L("span","i-out",`${r} output${r===1?"":"s"} \u2192`));let c=[p,L("div","i-facts",a.join(" \xB7 ")),s],h=e.error??e.summary;h&&c.push(L("p",e.error?"i-text is-error":"i-text",h)),c.push(L("div","i-hint",e.kind==="root"?"Click to open the orchestrating session":"Click to open this sub-agent's session")),d.inspector.replaceChildren(...c),d.inspector.hidden=!1}function Co(e){let t=de.get(e.id);return t||(t=L("button","node"),t.type="button",t.dataset.id=e.id,t.append(L("div","n-head"),L("div","n-status"),L("div","n-meta"),L("div","n-sub")),t.querySelector(".n-head")?.append(L("span","dot"),L("span","n-title")),t.addEventListener("pointerenter",()=>ge(e.id)),t.addEventListener("pointerleave",()=>{V===e.id&&ge(void 0)}),t.addEventListener("focus",()=>ge(e.id)),t.addEventListener("blur",()=>{V===e.id&&ge(void 0)}),t.addEventListener("click",()=>{Et||$o(e.id)}),de.set(e.id,t),d.nodes.append(t)),t}function Ro(e,t,r){e.className=`node k-${t.kind} s-${t.state}${M?.focusId===t.id&&t.kind==="task"?" is-current":""}`,V===t.id&&e.classList.add("is-hover"),e.setAttribute("aria-label",`${t.title}, ${fe(t,r)}. Open session.`);let a=(l,p)=>{let s=e.querySelector(l);s&&s.textContent!==p&&(s.textContent=p)};a(".n-title",t.title),a(".n-status",fe(t,r)),a(".n-meta",t.kind==="root"?`${M?.nodes.length?M.nodes.length-1:0} sub-agents`:[t.agent,mt(t.model)].filter(Boolean).join(" \xB7 ")),a(".n-sub",t.error??t.summary??""),e.querySelector(".dot")?.setAttribute("class",`dot s-${t.state}`)}function Go(e){M=e,C=jt(e),d.world.hidden=!1,d.empty.hidden=!0,d.world.style.width=`${C.width}px`,d.world.style.height=`${C.height}px`,d.edges.setAttribute("width",String(C.width)),d.edges.setAttribute("height",String(C.height)),d.edges.setAttribute("viewBox",`0 0 ${C.width} ${C.height}`);let t=new Map(e.nodes.map(i=>[i.id,i.state])),r=document.createDocumentFragment();for(let i of C.edges){let g=document.createElementNS(Jt,"path");g.setAttribute("d",i.d),g.dataset.edge=i.id,g.dataset.from=i.from,g.dataset.to=i.to;let f=t.get(i.to)==="running"||t.get(i.to)==="queued";if(g.setAttribute("class",`edge k-${i.kind}${f?" is-live":""}`),g.setAttribute("marker-end","url(#arrow)"),r.append(g),f){let x=document.createElementNS(Jt,"path");x.setAttribute("d",i.d),x.setAttribute("class","flow"),x.setAttribute("pathLength","1"),r.append(x)}}d.edges.querySelectorAll("path.edge, path.flow").forEach(i=>i.remove()),d.edges.append(r),d.bands.replaceChildren(...[...C.columnX].map(([i,g])=>{let f=L("div","band");f.style.left=`${g}px`,f.style.width=`${232}px`;let x=e.columns.find(I=>I.column===i);return i===0?f.textContent="Orchestrator":x&&(f.textContent=`Wave ${i} \xB7 ${x.done}/${x.total} done${x.running?` \xB7 ${x.running} running`:""}`),x?.running&&f.classList.add("is-live"),f}));let a=Date.now(),l=new Set;for(let i of e.nodes){let g=Co(i),f=C.boxes.get(i.id);f&&(g.style.transform=`translate(${f.x}px, ${f.y}px)`),Ro(g,i,a),l.add(i.id)}for(let[i,g]of de)l.has(i)||(g.remove(),de.delete(i));let p=e.nodes.filter(i=>i.kind==="task"),s=p.filter(i=>i.state==="completed"||i.state==="failed"||i.state==="cancelled").length,c=p.filter(i=>i.state==="running").length,h=e.columns.length,A=e.columns.find(i=>i.running>0||i.done<i.total)?.column;d.title.textContent=e.title,d.titleDot.className=`dot s-${c>0?"running":p.some(i=>i.state==="failed")?"failed":s===p.length?"completed":"idle"}`,d.meta.textContent=[A!==void 0?`wave ${A}/${h}`:`${h} wave${h===1?"":"s"}`,`${s}/${p.length} done`,...c?[`${c} running`]:[],...e.models?[`${e.models} model${e.models===1?"":"s"}`]:[],...e.truncated?[`${e.truncated.omittedNodes} omitted`]:[]].join(" \xB7 "),j.setBadge(c>0?c:null).catch(()=>{}),Wt!==e.rootId&&(Wt=e.rootId,requestAnimationFrame(()=>e.focusId!==e.rootId?no(e.focusId):De())),V&&!e.nodes.some(i=>i.id===V)&&(V=void 0),ge(V)}function Io(){if(!M)return;let e=Date.now();for(let t of M.nodes){if(t.state!=="running")continue;let a=de.get(t.id)?.querySelector(".n-status");a&&(a.textContent=fe(t,e))}}setInterval(Io,1e3);async function $o(e){let t=M?.nodes.find(r=>r.id===e);if(t)try{await j.openSession(t.sessionId)}catch(r){let[a,l]=oo(r);await j.toast({kind:"error",message:`${a}: ${l}`}).catch(()=>{})}}var xe=new Ue({fetch:e=>{let t={session:e};return ne.agentDir&&(t.agentDir=ne.agentDir),ne.stateDir&&(t.stateDir=ne.stateDir),j.serviceRequest({method:"GET",path:"/graph",query:t})},show:e=>{if(e.kind==="graph"){Go(e.graph);return}M=void 0,j.setBadge(null).catch(()=>{}),e.kind==="no-session"?gt("No session open","Open a chat to see the OmO agents working behind it."):e.kind==="empty"?gt("No sub-agents yet","When this session launches OmO tasks or workflows, they appear here as a live graph."):gt(...oo(e.error))},schedule:(e,t)=>{ht&&clearTimeout(ht),ht=setTimeout(t,e)},isHidden:()=>document.hidden}),Qt=G("#btn-settings");Qt.addEventListener("click",()=>{d.settings.hidden=!d.settings.hidden,Qt.setAttribute("aria-expanded",String(!d.settings.hidden)),d.settings.hidden||d.settings.querySelector("input")?.focus()});d.settings.addEventListener("submit",e=>{e.preventDefault();let t=new FormData(d.settings),r={},a=String(t.get("agentDir")??"").trim(),l=String(t.get("stateDir")??"").trim();a&&(r.agentDir=a),l&&(r.stateDir=l),ne=r,d.settings.hidden=!0,j.storage.set("paths",r).catch(()=>{}),xe.invalidate()});function No(){for(let e of["agentDir","stateDir"]){let t=d.settings.querySelector(`input[name="${e}"]`);t&&(t.value=ne[e]??"")}}var Zt=!1;j.onReady(e=>{it(e,document.documentElement),d.app.dataset.surface=e.surface,!Zt&&(Zt=!0,Ee=e.session?.id??Ee,j.storage.get("paths").then(t=>{if(t&&typeof t=="object"&&!Array.isArray(t)){let r=t;ne={...typeof r.agentDir=="string"?{agentDir:r.agentDir}:{},...typeof r.stateDir=="string"?{stateDir:r.stateDir}:{}}}No()}).catch(()=>{}).finally(()=>{to=!0,xe.setSession(Ee)}))});j.onSession(e=>{let t=e?.id??null;t!==Ee&&(V=void 0),Ee=t,to&&xe.setSession(t)});j.onSessionLifecycle(()=>{xe.refresh()});document.addEventListener("visibilitychange",()=>{document.hidden||xe.refresh()});window.addEventListener("resize",()=>{C&&_.k<=1&&le()});})();
176
+ `;var So=e=>24+e*308;function qt(e){let t=new Map,r=new Map;for(let i of e.nodes)r.set(i.column,[...r.get(i.column)??[],i]);let a=[...r.keys()].sort((i,g)=>i-g),l=new Map(a.map(i=>[i,So(i)])),p=new Map,s=0;for(let i of a)(r.get(i)??[]).slice().sort((f,k)=>(p.get(f.parentId??"")??-1)-(p.get(k.parentId??"")??-1)||(f.createdAt??0)-(k.createdAt??0)||f.id.localeCompare(k.id)).forEach((f,k)=>{let I=58+k*94;t.set(f.id,{x:l.get(i)??0,y:I}),p.set(f.id,p.size),s=Math.max(s,I+80+24)});let c=t.get(e.rootId),h=e.nodes.filter(i=>i.parentId===e.rootId).map(i=>t.get(i.id)).filter(i=>i!==void 0);if(c&&h.length>0&&(r.get(0)?.length??0)===1){let i=Math.min(...h.map(f=>f.y)),g=Math.max(...h.map(f=>f.y));c.y=Math.round((i+g)/2)}let A=24+(Math.max(0,...a)+1)*308-76+24;return{boxes:t,edges:To(e.edges,t),columnX:l,width:A,height:Math.max(s,162)}}function Yt(e,t){if(t<=1)return 80/2;let r=Math.min(12,80*.44/(t-1));return 80/2+(e-(t-1)/2)*r}function To(e,t){let r=e.filter(s=>t.has(s.from)&&t.has(s.to)),a=s=>(t.get(s)?.y??0)+80/2,l=new Map,p=new Map;for(let s of r)l.set(s.from,[...l.get(s.from)??[],s]),p.set(s.to,[...p.get(s.to)??[],s]);for(let s of l.values())s.sort((c,h)=>a(c.to)-a(h.to));for(let s of p.values())s.sort((c,h)=>a(c.from)-a(h.from));return r.map(s=>{let c=t.get(s.from),h=t.get(s.to),A=l.get(s.from)??[],i=p.get(s.to)??[],g=c.x+232,f=c.y+Yt(A.indexOf(s),A.length),k=h.x,I=h.y+Yt(i.indexOf(s),i.length),J=k>g?Math.max(32,(k-g)*.5):90,E=`M ${g} ${f} C ${g+J} ${f}, ${k-J} ${I}, ${k} ${I}`;return{...s,d:E,sx:g,sy:f,tx:k,ty:I}})}function ht(e,t,r){let a=new Set,l=[t];for(;l.length>0;){let p=l.pop();for(let s of e){let c=r==="down"?s.from===p?s.to:void 0:s.to===p?s.from:void 0;c!==void 0&&!a.has(c)&&c!==t&&(a.add(c),l.push(c))}}return a}function Jt(e){let t=Math.max(0,Math.round(e/1e3));if(t<60)return`${t}s`;let r=Math.floor(t/60);return r<60?`${r}m ${String(t%60).padStart(2,"0")}s`:`${Math.floor(r/60)}h ${String(r%60).padStart(2,"0")}m`}function gt(e){if(e)return e.includes("/")?e.slice(e.indexOf("/")+1):e}function Wt(e){return e>=1e6?`${(e/1e6).toFixed(1)}M`:e>=1e3?`${(e/1e3).toFixed(e>=1e4?0:1)}k`:String(e)}var _o={running:"running",queued:"queued",completed:"completed",failed:"failed",cancelled:"cancelled",idle:"idle"};function ue(e,t){if(e.kind==="root")return e.rawStatus;let r=e.rawStatus===e.state?_o[e.state]:e.rawStatus,a=e.startedAt;return a===void 0?r:e.state==="running"?`${r} \xB7 ${Jt(t-a)}`:e.endedAt!==void 0?`${r} \xB7 ${Jt(e.endedAt-a)}`:r}var De=class{drag;get active(){return this.drag!==void 0}down(t,r){t.button===0&&(this.drag={id:t.pointerId,x:t.clientX,y:t.clientY,vx:r.x,vy:r.y,moved:!1})}move(t){let r=this.drag;if(!r||t.pointerId!==r.id)return;if((t.buttons&1)===0)return"end";let a=t.clientX-r.x,l=t.clientY-r.y;if(!r.moved&&Math.hypot(a,l)<4)return;let p=!r.moved;return r.moved=!0,{x:r.vx+a,y:r.vy+l,started:p}}end(t){let r=this.drag;return!r||t!==void 0&&t!==r.id?!1:(this.drag=void 0,r.moved)}};var yo=new Set(["running","queued","completed","failed","cancelled","idle"]),me=e=>e!==null&&typeof e=="object"&&!Array.isArray(e),q=e=>typeof e=="number"&&Number.isFinite(e),fe=e=>e===void 0||typeof e=="string",ae=e=>e===void 0||q(e),Ao=e=>typeof e=="string"&&yo.has(e);function wo(e){return me(e)?typeof e.id=="string"&&(e.kind==="root"||e.kind==="task")&&typeof e.sessionId=="string"&&typeof e.title=="string"&&Ao(e.state)&&typeof e.rawStatus=="string"&&fe(e.agent)&&fe(e.model)&&ae(e.createdAt)&&ae(e.startedAt)&&ae(e.endedAt)&&fe(e.summary)&&fe(e.error)&&ae(e.tokens)&&ae(e.costUsd)&&ae(e.toolCalls)&&fe(e.parentId)&&q(e.column)&&q(e.wave):!1}function vo(e){return me(e)&&typeof e.id=="string"&&typeof e.from=="string"&&typeof e.to=="string"&&(e.kind==="spawn"||e.kind==="uses")}function Mo(e){return me(e)&&q(e.column)&&q(e.total)&&q(e.done)&&q(e.running)}function Oo(e){return me(e)&&q(e.omittedNodes)&&Number.isInteger(e.omittedNodes)&&e.omittedNodes>=0}function Lo(e){return me(e)&&(e.status==="ok"||e.status==="unknown-session")&&typeof e.rootId=="string"&&typeof e.focusId=="string"&&typeof e.title=="string"&&Array.isArray(e.nodes)&&e.nodes.every(wo)&&Array.isArray(e.edges)&&e.edges.every(vo)&&Array.isArray(e.columns)&&e.columns.every(Mo)&&q(e.models)&&(e.truncated===void 0||Oo(e.truncated))}function Co(e){let t=JSON.parse(e);if(!Lo(t))throw new Error("service answered with an unexpected graph shape");return t}var He=class{constructor(t){this.deps=t}deps;session=void 0;generation=0;inFlight=!1;pending=!1;signature="";setSession(t){t!==this.session&&(this.session=t,this.invalidate())}invalidate(){this.generation++,this.signature="",this.refresh()}async refresh(){let t=this.session;if(t===void 0)return;if(t===null){this.signature="",this.deps.show({kind:"no-session"});return}if(this.deps.isHidden()){this.deps.schedule(5e3,()=>{this.refresh()});return}if(this.inFlight){this.pending=!0;return}this.inFlight=!0;let r=this.generation;try{let a=await this.deps.fetch(t);if(r!==this.generation)return;if(a.status!==200)throw new Error(`service answered HTTP ${a.status}: ${a.body.slice(0,200)}`);let l=Co(a.body);l.status!=="ok"||l.nodes.length<=1?(this.signature="",this.deps.show({kind:"empty"})):a.body!==this.signature&&(this.signature=a.body,this.deps.show({kind:"graph",graph:l}));let p=l.nodes.some(s=>s.state==="running"||s.state==="queued");this.deps.schedule(p?1500:5e3,()=>{this.refresh()})}catch(a){if(r!==this.generation)return;this.signature="",this.deps.show({kind:"error",error:a}),this.deps.schedule(1e4,()=>{this.refresh()})}finally{this.inFlight=!1,(this.pending||r!==this.generation)&&(this.pending=!1,this.refresh())}}};var Qt="http://www.w3.org/2000/svg";document.documentElement.style.setProperty("--node-card-width",`${232}px`);document.documentElement.style.setProperty("--node-card-height",`${80}px`);var V=at(),C=e=>document.querySelector(e),d={app:C("#app"),title:C("#title"),titleDot:C("#title-dot"),meta:C("#meta"),viewport:C("#viewport"),world:C("#world"),edges:C("#edges"),bands:C("#bands"),nodes:C("#nodes"),empty:C("#empty"),inspector:C("#inspector"),settings:C("#settings")},ge=null,no=!1,M,R,Zt="",K,oe={},Et,_={x:0,y:0,k:1},ce=new Map;function L(e,t="",r=""){let a=document.createElement(e);return t&&(a.className=t),r&&(a.textContent=r),a}function xt(e,t=""){d.empty.replaceChildren(L("strong","",e),...t?[L("p","",t)]:[]),d.empty.hidden=!1,d.world.hidden=!0,d.inspector.hidden=!0}function ro(e){return e instanceof u?e.code==="NO_SERVICE"?["Local service not allowed yet","Approve OmO Graph in Settings \u2192 Extensions so it can read the OmO task store."]:e.code==="SERVICE_FAILED"?["The local service did not start","Check Settings \u2192 Extensions; the next refresh retries it."]:e.code==="DISABLED"?["OmO Graph is paused","Resume it in Settings \u2192 Extensions."]:[`Request failed (${e.code})`,e.message]:["Request failed",e instanceof Error?e.message:String(e)]}function de(){d.world.style.transform=`translate(${_.x}px, ${_.y}px) scale(${_.k})`,d.app.style.setProperty("--zoom",String(_.k))}function Pe(){if(!R)return;let e=d.viewport.clientWidth,t=d.viewport.clientHeight,r=Math.min(1,Math.max(.62,Math.min((e-16)/R.width,(t-16)/R.height)));_.k=r,_.x=Math.round(R.width*r<=e?(e-R.width*r)/2:8),_.y=Math.round(Math.max(8,(t-R.height*r)/2)),de()}function so(e){let t=e?R?.boxes.get(e):void 0;if(!t)return Pe();_.k=Math.max(_.k,.8),_.x=Math.round(d.viewport.clientWidth/2-(t.x+232/2)*_.k),_.y=Math.round(d.viewport.clientHeight/2-(t.y+80/2)*_.k),de()}function xe(e,t=d.viewport.clientWidth/2,r=d.viewport.clientHeight/2){let a=Math.min(2,Math.max(.2,_.k*e));_.x=t-(t-_.x)*a/_.k,_.y=r-(r-_.y)*a/_.k,_.k=a,de()}var Ee=new De,kt=!1;function ke(e,t=!1){if(!Ee.active)return;let r=Ee.end(e);Ee.active||(r&&t&&(kt=!0,setTimeout(()=>{kt=!1},0)),d.app.classList.remove("is-panning"))}d.viewport.addEventListener("pointerdown",e=>Ee.down(e,_));window.addEventListener("pointermove",e=>{let t=Ee.move(e);if(t==="end")return ke(e.pointerId);t&&(t.started&&(d.viewport.setPointerCapture?.(e.pointerId),d.app.classList.add("is-panning")),_.x=t.x,_.y=t.y,de())});window.addEventListener("pointerup",e=>ke(e.pointerId,!0));window.addEventListener("pointercancel",e=>ke(e.pointerId));d.viewport.addEventListener("lostpointercapture",e=>ke(e.pointerId));window.addEventListener("blur",()=>ke());d.viewport.addEventListener("wheel",e=>{e.preventDefault();let t=d.viewport.getBoundingClientRect();e.ctrlKey||e.metaKey||Math.abs(e.deltaY)>Math.abs(e.deltaX)*2&&!e.shiftKey?xe(Math.exp(-e.deltaY*(e.ctrlKey?.01:.0015)),e.clientX-t.left,e.clientY-t.top):(_.x-=e.deltaX||(e.shiftKey?e.deltaY:0),_.y-=e.shiftKey?0:e.deltaY,de())},{passive:!1});C("#btn-fit").addEventListener("click",Pe);C("#btn-locate").addEventListener("click",()=>{let e=M?.nodes.find(t=>t.kind==="task"&&t.state==="running");so(M?.focusId!==M?.rootId?M?.focusId:e?.id??M?.rootId)});C("#btn-in").addEventListener("click",()=>xe(1.2));C("#btn-out").addEventListener("click",()=>xe(1/1.2));window.addEventListener("keydown",e=>{e.target instanceof HTMLInputElement||(e.key==="0"?Pe():e.key==="+"||e.key==="="?xe(1.2):e.key==="-"&&xe(1/1.2))});function he(e){if(K=e,!M)return;let t=M.edges,r=new Set(e?t.filter(s=>s.to===e).map(s=>s.from):[]),a=new Set(e?t.filter(s=>s.from===e).map(s=>s.to):[]),l=e?ht(t,e,"up"):new Set,p=e?ht(t,e,"down"):new Set;d.app.classList.toggle("has-hover",e!==void 0);for(let[s,c]of ce)c.classList.toggle("is-hover",s===e),c.classList.toggle("is-input",r.has(s)),c.classList.toggle("is-output",a.has(s)),c.classList.toggle("is-reach",l.has(s)||p.has(s));for(let s of d.edges.querySelectorAll("path[data-edge]")){let c=s.dataset.from??"",h=s.dataset.to??"";s.classList.toggle("is-in",e!==void 0&&h===e),s.classList.toggle("is-out",e!==void 0&&c===e),s.classList.toggle("is-reach",e!==void 0&&(l.has(c)&&(l.has(h)||h===e)||p.has(h)&&(p.has(c)||c===e)))}Ro()}function Ro(){let e=M?.nodes.find(A=>A.id===(K??(M?.focusId!==M?.rootId?M?.focusId:void 0)));if(!e||!M){d.inspector.hidden=!0;return}let t=M.edges.filter(A=>A.to===e.id).length,r=M.edges.filter(A=>A.from===e.id).length,a=[ue(e,Date.now())];e.agent&&a.push(e.agent);let l=gt(e.model);l&&a.push(l),e.toolCalls!==void 0&&a.push(`${e.toolCalls} tools`),e.tokens!==void 0&&a.push(`${Wt(e.tokens)} tok`),e.costUsd!==void 0&&a.push(`$${e.costUsd.toFixed(2)}`);let p=L("div","i-head");p.append(L("span",`dot s-${e.state}`),L("strong","",e.title));let s=L("div","i-flow");s.append(L("span","i-in",`\u2190 ${t} input${t===1?"":"s"}`),L("span","i-out",`${r} output${r===1?"":"s"} \u2192`));let c=[p,L("div","i-facts",a.join(" \xB7 ")),s],h=e.error??e.summary;h&&c.push(L("p",e.error?"i-text is-error":"i-text",h)),c.push(L("div","i-hint",e.kind==="root"?"Click to open the orchestrating session":"Click to open this sub-agent's session")),d.inspector.replaceChildren(...c),d.inspector.hidden=!1}function Go(e){let t=ce.get(e.id);return t||(t=L("button","node"),t.type="button",t.dataset.id=e.id,t.append(L("div","n-head"),L("div","n-status"),L("div","n-meta"),L("div","n-sub")),t.querySelector(".n-head")?.append(L("span","dot"),L("span","n-title")),t.addEventListener("pointerenter",()=>he(e.id)),t.addEventListener("pointerleave",()=>{K===e.id&&he(void 0)}),t.addEventListener("focus",()=>he(e.id)),t.addEventListener("blur",()=>{K===e.id&&he(void 0)}),t.addEventListener("click",()=>{kt||Uo(e.id)}),ce.set(e.id,t),d.nodes.append(t)),t}function Io(e,t,r){e.className=`node k-${t.kind} s-${t.state}${M?.focusId===t.id&&t.kind==="task"?" is-current":""}`,K===t.id&&e.classList.add("is-hover"),e.setAttribute("aria-label",`${t.title}, ${ue(t,r)}. Open session.`);let a=(l,p)=>{let s=e.querySelector(l);s&&s.textContent!==p&&(s.textContent=p)};a(".n-title",t.title),a(".n-status",ue(t,r)),a(".n-meta",t.kind==="root"?`${M?.nodes.length?M.nodes.length-1:0} sub-agents`:[t.agent,gt(t.model)].filter(Boolean).join(" \xB7 ")),a(".n-sub",t.error??t.summary??""),e.querySelector(".dot")?.setAttribute("class",`dot s-${t.state}`)}function $o(e){M=e,R=qt(e),d.world.hidden=!1,d.empty.hidden=!0,d.world.style.width=`${R.width}px`,d.world.style.height=`${R.height}px`,d.edges.setAttribute("width",String(R.width)),d.edges.setAttribute("height",String(R.height)),d.edges.setAttribute("viewBox",`0 0 ${R.width} ${R.height}`);let t=new Map(e.nodes.map(i=>[i.id,i.state])),r=document.createDocumentFragment();for(let i of R.edges){let g=document.createElementNS(Qt,"path");g.setAttribute("d",i.d),g.dataset.edge=i.id,g.dataset.from=i.from,g.dataset.to=i.to;let f=t.get(i.to)==="running"||t.get(i.to)==="queued";if(g.setAttribute("class",`edge k-${i.kind}${f?" is-live":""}`),g.setAttribute("marker-end","url(#arrow)"),r.append(g),f){let k=document.createElementNS(Qt,"path");k.setAttribute("d",i.d),k.setAttribute("class","flow"),k.setAttribute("pathLength","1"),r.append(k)}}d.edges.querySelectorAll("path.edge, path.flow").forEach(i=>i.remove()),d.edges.append(r),d.bands.replaceChildren(...[...R.columnX].map(([i,g])=>{let f=L("div","band");f.style.left=`${g}px`,f.style.width=`${232}px`;let k=e.columns.find(I=>I.column===i);return i===0?f.textContent="Orchestrator":k&&(f.textContent=`Wave ${i} \xB7 ${k.done}/${k.total} done${k.running?` \xB7 ${k.running} running`:""}`),k?.running&&f.classList.add("is-live"),f}));let a=Date.now(),l=new Set;for(let i of e.nodes){let g=Go(i),f=R.boxes.get(i.id);f&&(g.style.transform=`translate(${f.x}px, ${f.y}px)`),Io(g,i,a),l.add(i.id)}for(let[i,g]of ce)l.has(i)||(g.remove(),ce.delete(i));let p=e.nodes.filter(i=>i.kind==="task"),s=p.filter(i=>i.state==="completed"||i.state==="failed"||i.state==="cancelled").length,c=p.filter(i=>i.state==="running").length,h=e.columns.length,A=e.columns.find(i=>i.running>0||i.done<i.total)?.column;d.title.textContent=e.title,d.titleDot.className=`dot s-${c>0?"running":p.some(i=>i.state==="failed")?"failed":s===p.length?"completed":"idle"}`,d.meta.textContent=[A!==void 0?`wave ${A}/${h}`:`${h} wave${h===1?"":"s"}`,`${s}/${p.length} done`,...c?[`${c} running`]:[],...e.models?[`${e.models} model${e.models===1?"":"s"}`]:[],...e.truncated?[`${e.truncated.omittedNodes} omitted`]:[]].join(" \xB7 "),V.setBadge(c>0?c:null).catch(()=>{}),Zt!==e.rootId&&(Zt=e.rootId,requestAnimationFrame(()=>e.focusId!==e.rootId?so(e.focusId):Pe())),K&&!e.nodes.some(i=>i.id===K)&&(K=void 0),he(K)}function No(){if(!M)return;let e=Date.now();for(let t of M.nodes){if(t.state!=="running")continue;let a=ce.get(t.id)?.querySelector(".n-status");a&&(a.textContent=ue(t,e))}}setInterval(No,1e3);async function Uo(e){let t=M?.nodes.find(r=>r.id===e);if(t)try{await V.openSession(t.sessionId)}catch(r){let[a,l]=ro(r);await V.toast({kind:"error",message:`${a}: ${l}`}).catch(()=>{})}}var be=new He({fetch:e=>{let t={session:e};return oe.agentDir&&(t.agentDir=oe.agentDir),oe.stateDir&&(t.stateDir=oe.stateDir),V.serviceRequest({method:"GET",path:"/graph",query:t})},show:e=>{if(e.kind==="graph"){$o(e.graph);return}M=void 0,V.setBadge(null).catch(()=>{}),e.kind==="no-session"?xt("No session open","Open a chat to see the OmO agents working behind it."):e.kind==="empty"?xt("No sub-agents yet","When this session launches OmO tasks or workflows, they appear here as a live graph."):xt(...ro(e.error))},schedule:(e,t)=>{Et&&clearTimeout(Et),Et=setTimeout(t,e)},isHidden:()=>document.hidden}),eo=C("#btn-settings");eo.addEventListener("click",()=>{d.settings.hidden=!d.settings.hidden,eo.setAttribute("aria-expanded",String(!d.settings.hidden)),d.settings.hidden||d.settings.querySelector("input")?.focus()});C("#btn-save").addEventListener("click",()=>{let e=new FormData(d.settings),t={},r=String(e.get("agentDir")??"").trim(),a=String(e.get("stateDir")??"").trim();r&&(t.agentDir=r),a&&(t.stateDir=a),oe=t,d.settings.hidden=!0,V.storage.set("paths",t).catch(()=>{}),be.invalidate()});function Do(){for(let e of["agentDir","stateDir"]){let t=d.settings.querySelector(`input[name="${e}"]`);t&&(t.value=oe[e]??"")}}var to=!1;V.onReady(e=>{ct(e,document.documentElement),d.app.dataset.surface=e.surface,!to&&(to=!0,ge=e.session?.id??ge,V.storage.get("paths").then(t=>{if(t&&typeof t=="object"&&!Array.isArray(t)){let r=t;oe={...typeof r.agentDir=="string"?{agentDir:r.agentDir}:{},...typeof r.stateDir=="string"?{stateDir:r.stateDir}:{}}}Do()}).catch(()=>{}).finally(()=>{no=!0,be.setSession(ge)}))});V.onSession(e=>{let t=e?.id??null;t!==ge&&(K=void 0),ge=t,no&&be.setSession(t)});V.onSessionLifecycle(()=>{be.refresh()});document.addEventListener("visibilitychange",()=>{document.hidden||be.refresh()});window.addEventListener("resize",()=>{R&&_.k<=1&&de()});})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "antechamber",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "OpenCode-compatible HTTP/SSE server that lets OpenChamber drive the pi coding agent (and OmO) over RPC",
5
5
  "type": "module",
6
6
  "license": "MIT",