antechamber 1.0.41 → 2.0.1

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.
Files changed (52) hide show
  1. package/CHANGELOG.md +97 -0
  2. package/README.md +88 -141
  3. package/bin/opencode-antechamber +14 -4
  4. package/dist/cli.d.ts +1 -1
  5. package/dist/cli.js +1 -1
  6. package/dist/commands/context.d.ts +5 -2
  7. package/dist/commands/context.js +8 -4
  8. package/dist/commands/doctor.js +4 -3
  9. package/dist/commands/setup.js +9 -28
  10. package/dist/config.d.ts +6 -2
  11. package/dist/config.js +18 -4
  12. package/dist/latency.d.ts +10 -0
  13. package/dist/latency.js +115 -0
  14. package/dist/misc-routes.js +2 -10
  15. package/dist/route-services.d.ts +0 -2
  16. package/dist/routes-v1.d.ts +1 -1
  17. package/dist/routes-v1.js +29 -418
  18. package/dist/routes-v2.js +1 -1
  19. package/dist/self-update.d.ts +2 -1
  20. package/dist/self-update.js +5 -1
  21. package/dist/server.d.ts +1 -3
  22. package/dist/server.js +9 -12
  23. package/dist/session-store.d.ts +12 -10
  24. package/dist/session-store.js +238 -128
  25. package/dist/session-tree.js +2 -2
  26. package/dist/sse.d.ts +0 -2
  27. package/dist/sse.js +13 -46
  28. package/dist/tool-map.js +1 -3
  29. package/dist/work-status.js +1 -1
  30. package/extensions/antechamber/README.md +100 -0
  31. package/extensions/antechamber/bin/opencode-antechamber +42 -0
  32. package/extensions/{omo-dag/docs/DESIGN.md → antechamber/docs/GRAPH.md} +5 -5
  33. package/extensions/{omo-work/docs/DESIGN.md → antechamber/docs/WORK.md} +3 -3
  34. package/extensions/antechamber/package.json +60 -0
  35. package/extensions/{omo-dag → antechamber}/panel/index.html +8 -1
  36. package/extensions/antechamber/panel/main.js +261 -0
  37. package/extensions/antechamber/runtime/launcher.js +201 -0
  38. package/extensions/antechamber/service/main.js +884 -0
  39. package/package.json +75 -26
  40. package/extensions/omo-compat/README.md +0 -48
  41. package/extensions/omo-compat/icon.svg +0 -1
  42. package/extensions/omo-compat/package.json +0 -43
  43. package/extensions/omo-dag/README.md +0 -167
  44. package/extensions/omo-dag/package.json +0 -33
  45. package/extensions/omo-dag/panel/main.js +0 -176
  46. package/extensions/omo-dag/service/main.js +0 -457
  47. package/extensions/omo-work/README.md +0 -88
  48. package/extensions/omo-work/package.json +0 -30
  49. package/extensions/omo-work/service/main.js +0 -149
  50. /package/extensions/{omo-dag → antechamber}/icon.svg +0 -0
  51. /package/extensions/{omo-work → antechamber}/status/index.html +0 -0
  52. /package/extensions/{omo-work → antechamber}/status/main.js +0 -0
@@ -0,0 +1,261 @@
1
+ "use strict";(()=>{var S="openchamber.sdk";var Ne="data-oc-scrolling",it=`
2
+ :root {
3
+ /* Quiet at rest like the app's own thumbs; hover gives a clear grab target. */
4
+ --oc-scrollbar-thumb: color-mix(in srgb, var(--oc-muted, currentColor) 18%, transparent);
5
+ --oc-scrollbar-thumb-hover: color-mix(in srgb, var(--oc-muted, currentColor) 36%, transparent);
6
+ scrollbar-gutter: stable;
7
+ }
8
+ * {
9
+ scrollbar-width: thin;
10
+ scrollbar-color: transparent transparent;
11
+ }
12
+ :hover, [${Ne}] {
13
+ scrollbar-color: var(--oc-scrollbar-thumb) transparent;
14
+ }
15
+ /* Chromium's standard scrollbar properties otherwise override its pseudo-elements. */
16
+ @supports selector(::-webkit-scrollbar) {
17
+ *, :hover, [${Ne}] { scrollbar-width: auto; scrollbar-color: auto; }
18
+ ::-webkit-scrollbar { width: 6px; height: 6px; background: transparent; }
19
+ ::-webkit-scrollbar-track { background: transparent; }
20
+ ::-webkit-scrollbar-thumb {
21
+ background: transparent;
22
+ border-radius: 999px;
23
+ min-width: 24px;
24
+ min-height: 24px;
25
+ }
26
+ :hover::-webkit-scrollbar-thumb, [${Ne}]::-webkit-scrollbar-thumb { background: var(--oc-scrollbar-thumb); }
27
+ ::-webkit-scrollbar-thumb:hover { background: var(--oc-scrollbar-thumb-hover); }
28
+ ::-webkit-scrollbar-corner { background: transparent; }
29
+ ::-webkit-scrollbar-button { display: none; width: 0; height: 0; }
30
+ }
31
+ @media (forced-colors: active) {
32
+ *, :hover, [${Ne}] { scrollbar-color: auto; }
33
+ ::-webkit-scrollbar-thumb, ::-webkit-scrollbar-thumb:hover { background: CanvasText; }
34
+ }
35
+ `;function fo(e){let t=e.documentElement;if(t.hasAttribute("data-oc-scrollbar-activity"))return;t.setAttribute("data-oc-scrollbar-activity","");let r=new WeakMap;e.addEventListener("scroll",s=>{let c=s.target===e?t:s.target;if(!(c instanceof Element))return;c.hasAttribute("data-oc-scrolling")||c.setAttribute("data-oc-scrolling","");let u=r.get(c);u!==void 0&&clearTimeout(u),r.set(c,setTimeout(()=>{r.delete(c),c.removeAttribute("data-oc-scrolling")},1e3))},{capture:!0,passive:!0})}var En=`(${fo.toString()})(document);`;var _o=/^[a-z][a-z0-9-]{0,39}$/;var Eo=e=>Object(e)===e&&!Array.isArray(e),at=(e,t)=>Object.keys(e).every(r=>t.includes(r)),ho=e=>String(e)===e&&e.length>=1&&e.length<=60,mo=e=>String(e)===e&&e.length>=1&&e.length<=80,So=e=>{if(!Array.isArray(e)||e.length>4)return!1;let t=new Set;for(let r of e){if(!Eo(r)||!_o.test(r.id)||!ho(r.label)||r.disabled!==void 0&&r.disabled!==!0&&r.disabled!==!1||t.has(r.id))return!1;if(t.add(r.id),r.kind==="button"){if(!at(r,["kind","id","label","disabled"]))return!1;continue}if(r.kind!=="select"||!at(r,["kind","id","label","value","options","disabled"])||!mo(r.value)||!Array.isArray(r.options)||r.options.length<1||r.options.length>16)return!1;let s=new Set;for(let c of r.options){if(!Eo(c)||!at(c,["value","label"])||!mo(c.value)||!ho(c.label)||s.has(c.value))return!1;s.add(c.value)}if(!s.has(r.value))return!1}return!0};var ct=e=>"bytes"in e?e.bytes.byteLength:e.content.length,To=(e,t)=>{if(e.path!==t.path||e.readOnly!==t.readOnly)return!1;if(e.encoding==="text"||t.encoding==="text")return e.encoding==="text"&&t.encoding==="text"&&e.content===t.content;if(e.bytes.byteLength!==t.bytes.byteLength)return!1;for(let r=0;r<e.bytes.byteLength;r+=1)if(e.bytes[r]!==t.bytes[r])return!1;return!0};var go=/^[A-Za-z0-9_-]{1,80}$/;var xo=["left","right","top","bottom"];var bo=(e,t=0,r={remaining:16e3})=>{if(--r.remaining<0||t>=32)return!1;if(e===null)return!0;let s=Array.isArray(e)?e:Object(e)===e?Object.values(e):[];for(let c of s)if(!bo(c,t+1,r))return!1;return!0},dt=e=>{if(e===null||e===!0||e===!1)return!0;if(Array.isArray(e))return Object.keys(e).every(t=>/^(0|[1-9]\d*)$/.test(t)&&Number(t)<e.length)&&e.every(dt);if(Object(e)===e){let t=Object.getPrototypeOf(e);return(t===null||t===Object.prototype)&&Object.values(e).every(dt)}return String(e)===e||Number.isFinite(e)},lt=e=>{try{return String(e.id)!==e.id||!go.test(e.id)||!Number.isFinite(e.anchor.x)||Math.abs(e.anchor.x)>1e5||!Number.isFinite(e.anchor.y)||Math.abs(e.anchor.y)>1e5||!Number.isFinite(e.anchor.width)||!Number.isFinite(e.anchor.height)||e.anchor.width<=0||e.anchor.height<=0||e.anchor.width>1e5||e.anchor.height>1e5||!Number.isInteger(e.width)||e.width<160||e.width>640||!Number.isInteger(e.height)||e.height<48||e.height>480||e.side!==void 0&&!xo.includes(e.side)||e.focus!==void 0&&e.focus!==!0&&e.focus!==!1||!bo(e.data)||!dt(e.data)?!1:JSON.stringify(e.data).length<=16e3}catch{return!1}};var ko=["file","directory","other","missing"],ut=e=>!!(e&&"sessionId"in e),ft=e=>!!(e&&"sent"in e&&!("sessionId"in e));var yo=/^[0-9a-f]{7,64}$/i,Et=e=>yo.test(e),Pe=500,De=32e3,Oo=16e3,vo=128,wo=200,Ro=2e3,Lo=16e3,Mo=80,Io=200,Co=16e3;var Uo=2e3;var ht=2e4,He=1024,$e=2e6;var Fe=64e3,Xe=8e3,mt=4e3;var _t=96e4,hn=60*6e4;var Go=999,No=1e4,be=500,Po=["HOST_UNAVAILABLE","HOST_TIMEOUT","HOST_REJECTED","DISCONNECTED","DISABLED","BAD_PATH","NO_INTEGRATION","NO_SERVICE","SERVICE_FAILED","REQUEST_FAILED","RESPONSE_TOO_LARGE","NO_SESSION","SESSION_BUSY","NOT_GRANTED","NO_DIRECTORY","NOT_FOUND","FILE_TOO_LARGE","DENIED","NO_MODEL","MODEL_FAILED","UNSUPPORTED"],Do=["stopped","starting","ready","failed"],mn=new Set(Po),Ho=e=>mn.has(e),$o=e=>e&&Ho(e)?e:"HOST_REJECTED",le=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(le):Object(e)===e?Object.values(e).every(le):!1,Fo=e=>le(e)&&JSON.stringify(e).length<=Co,Ao=e=>e?.trim().slice(0,Io)??"",pe=e=>{let t=e.id.trim().slice(0,vo),r=e.title.trim().slice(0,wo),s=e.url.trim().slice(0,Ro),c=e.text?.trim().slice(0,Lo),u=e.author?.trim().slice(0,Mo),i=e.kind==="pull"?"pull":"issue",f={providerId:e.providerId.trim(),id:t,title:r||t,url:s,kind:i};if(c&&(f.text=c),u&&(f.author=u),i==="pull"){let x=Ao(e.branches?.head),w=Ao(e.branches?.base);x&&w&&(f.branches={head:x,base:w})}return Fo(e.data)&&(f.data=e.data),f},St=e=>{let t=pe(e);return e.projectId&&(t.projectId=e.projectId),e.navigation&&(t.navigation=e.navigation),e.worktree&&(t.worktree=e.worktree),t},Tt=e=>{let t={text:e.text.trim().slice(0,Oo)};return e.send&&(t.send=!0),t},gt=e=>e===null||!Number.isFinite(e)?null:Math.min(Go,Math.max(0,Math.round(e))),xt=e=>Number.isFinite(e)?Math.min(No,Math.max(0,Math.ceil(e))):0;var ue=e=>e.length>0&&e.length<=He&&!e.includes("\0")&&!e.includes("\\");var Be=e=>!e.startsWith("/")||e.includes("\0")||e.includes("\\")||e.includes("://")||e.length>Uo?!1:!e.split("/").some(r=>r==="."||r===".."),_n=new Set(Do),bt=e=>!!(e&&"status"in e&&_n.has(String(e.status))&&!("body"in e)),Ve=e=>!!(e&&"status"in e&&"body"in e&&Number.isInteger(e.status)),At=e=>!!(e&&"content"in e&&String(e.content)===e.content),kt=e=>!!(e&&"written"in e&&e.written===!0),yt=e=>!!(e&&"entries"in e&&Array.isArray(e.entries)),Sn=new Set(ko),Ot=e=>!!(e&&"kind"in e&&"size"in e&&Sn.has(String(e.kind))&&Number.isFinite(e.size)),vt=e=>!!(e&&"text"in e&&String(e.text)===e.text&&!("status"in e)),Tn=new Set(["workspace","shells","ready","directory","session","connection","settings","session-lifecycle","item","resolve","action","status-control-event","popover-closed","file-open","file-snapshot","file-saved","generate-late"]),gn=e=>Object(e)===e?e:null,pt=e=>String(e)===e&&e.length>0,xn=e=>{if(!pt(e.id))return null;if(e.ok===!0){let t={channel:S,v:1,type:"result",id:e.id,ok:!0};return Object(e.payload)===e.payload&&(t.payload=e.payload),t}return e.ok===!1&&pt(e.error)?{channel:S,v:1,type:"result",id:e.id,ok:!1,error:e.error,code:$o(pt(e.code)?e.code:void 0)}:null},wt=e=>{let t=gn(e);return!t||t.channel!==S||t.v!==1?null:t.type==="result"?xn(t):!Tn.has(String(t.type))||Object(t.payload)!==t.payload?null:t};var Xo=e=>"key"in e&&"metaKey"in e&&"ctrlKey"in e,bn=e=>(e.metaKey||e.ctrlKey)&&!e.altKey&&!e.shiftKey&&e.key.toLowerCase()==="s",p=class extends Error{code;constructor(t,r){super(r),this.name="HostRequestError",this.code=t}},Bo=()=>Promise.reject(new p("BAD_PATH",'Request path must start with "/" and stay on the declared origin.')),ze=()=>Promise.reject(new p("BAD_PATH",`File path must be 1 to ${He} characters without NUL or backslash.`)),je=e=>{if(e!==void 0){if(Object(e)!==e||Array.isArray(e)||e.scope!==void 0&&e.scope!=="instance"&&e.scope!=="device")throw new p("HOST_REJECTED",'Storage scope must be "instance" or "device".');return e.scope==="device"?"device":void 0}},_=e=>(e.value+=1,`oc-${e.value}`),Ct=(e={})=>{let t=e.target??("window"in globalThis?window:null);if(!t)throw new p("HOST_UNAVAILABLE","No window. connectHost runs in a browser frame.");let r=e.acceptSource??(o=>o===t.parent),s=e.requestTimeoutMs??ht,c=new Set,u=new Set,i=new Set,f=new Set,x=new Set,w=new Set,a=new Set,b=new Set,g=new Set,A=new Set,z=[],oe=null,re=null,Me=new Set,Ie=new Set,Se=null,Te=null,ot=!1,ae=new Map,ce=new Map,de=new Map,J=!1,m={value:0},E=null,q=null,ge=!1,xe=!1,eo=null,to=o=>o?{sessionId:o.id,phase:o.busy?"started":"completed"}:null,V=o=>{t.parent.postMessage(o,"*")},oo=()=>{J||t.parent===t||A.size===0||E?.features?.lateGenerateResults!==!0||V({channel:S,v:1,type:"generate-late-listen"})},I=(o,n)=>{for(let d of o)try{d(n)}catch(l){console.error(l)}},no=o=>{if(!(o instanceof MessageEvent)||!r(o.source))return;let n=wt(o.data);if(!n)return;if(n.type==="workspace"){let l=ce.get(n.payload.subscriptionId);l&&I([l],n.payload.snapshot);return}if(n.type==="shells"){let l=de.get(n.payload.subscriptionId);l&&I([l],n.payload.snapshot);return}if(n.type==="ready"){E=n.payload,q=to(n.payload.session),I(c,n.payload),I(u,n.payload.directory),I(i,n.payload.session),q&&I(f,q),I(x,n.payload.connection),I(w,n.payload.settings),I(a,n.payload.item),oo();return}if(n.type==="generate-late"){A.size===0?z.push(n.payload):I(A,n.payload);return}if(n.type==="directory"){E&&(E={...E,directory:n.payload.directory}),I(u,n.payload.directory);return}if(n.type==="session"){E&&(E={...E,session:n.payload.session}),n.payload.session?q?.sessionId!==n.payload.session.id&&(q=to(n.payload.session)):q=null,I(i,n.payload.session);return}if(n.type==="session-lifecycle"){q=n.payload,I(f,n.payload);return}if(n.type==="connection"){E&&(E={...E,connection:n.payload.connection}),I(x,n.payload.connection);return}if(n.type==="settings"){E&&(E={...E,settings:n.payload.settings}),I(w,n.payload.settings);return}if(n.type==="item"){E&&(E={...E,item:n.payload.item}),I(a,n.payload.item);return}if(n.type==="status-control-event"){I(b,n.payload);return}if(n.type==="popover-closed"){I(g,n.payload);return}if(n.type==="action"){let l=O=>{J||V({channel:S,v:1,type:"action-result",id:n.id,payload:O})},v=re;if(!v){l({ok:!1,error:"This extension does not handle background actions."});return}Promise.resolve().then(()=>v(n.payload)).then(()=>l({ok:!0}),O=>{let N=(O instanceof Error?O.message:String(O)).trim();l({ok:!1,error:(N||"Action failed.").slice(0,be)})});return}if(n.type==="file-open"){let l=n.payload;if(Te&&To(Te,l))return;Te=l,I(Me,n.payload);return}if(n.type==="file-saved"){I(Ie,n.payload.version);return}if(n.type==="file-snapshot"){let l=N=>{J||V({channel:S,v:1,type:"file-snapshot-result",id:n.id,payload:N})},v=N=>l({error:(N.trim()||"Could not read the edited file.").slice(0,be)}),O=Se;if(!O){v("This extension does not edit files.");return}Promise.resolve().then(()=>O(n.payload.purpose)).then(N=>{if(ct(N)>2e7){v(`The file is over ${2e7} ${"bytes"in N?"bytes":"characters"}.`);return}if(N.version.length>256){v(`The snapshot version is over ${256} characters.`);return}l({snapshot:"bytes"in N?{bytes:N.bytes,version:N.version}:{content:N.content,version:N.version}})},N=>v(N instanceof Error?N.message:String(N)));return}if(n.type==="resolve"){let l=O=>{V({channel:S,v:1,type:"resolve-result",id:n.id,payload:O})},v=oe;if(!v){l({error:"This extension does not resolve commands."});return}Promise.resolve().then(()=>v(n.payload)).then(O=>l({item:O?pe(O):null}),O=>{let N=(O instanceof Error?O.message:String(O)).trim();l({error:(N||"Command failed.").slice(0,be)})});return}let d=ae.get(n.id);if(d){if(clearTimeout(d.timer),ae.delete(n.id),n.ok){d.resolve(n.payload);return}d.reject(new p(n.code,n.error))}};t.addEventListener("message",no),V({channel:S,v:1,type:"hello"});let H=(o,n=s)=>J||t.parent===t?Promise.reject(new p("HOST_UNAVAILABLE","No host frame. This page is not in an iframe.")):new Promise((d,l)=>{let v=setTimeout(()=>{ae.delete(o.id),l(new p("HOST_TIMEOUT","Host did not answer in time."))},n);ae.set(o.id,{resolve:d,reject:l,timer:v}),V(o)}),U=o=>H(o).then(()=>{}),G={channel:S,v:1},nt=o=>{!J&&t.parent!==t&&V(o)},ro=()=>nt({...G,type:"file-save"}),so=o=>{!Xo(o)||!bn(o)||(o.preventDefault(),ro())},io=o=>{!Xo(o)||o.key!=="Escape"||E?.surface!=="popover"||!E.popover||(o.preventDefault(),po(E.popover.id,"escape").catch(()=>{}))},Ce=()=>{let o=E?.surface==="popover"?E.popover:void 0;if(!o)return;let n=ge||xe;eo!==n&&(eo=n,uo(o.id,n).catch(()=>{}))},Ue=()=>{E?.surface!=="popover"||ge||(ge=!0,Ce())},ao=o=>{E?.surface!=="popover"||o.relatedTarget!==null||!ge||(ge=!1,Ce())},co=()=>{E?.surface!=="popover"||xe||(xe=!0,Ce())},lo=()=>{E?.surface!=="popover"||!xe||(xe=!1,Ce())},K=(o,n=1024)=>{if(!o.trim()||o.length>n)throw new p("HOST_REJECTED",`Identity must contain 1 to ${n} characters.`)},rt=async o=>{o.kind!=="projects"&&K(o.projectId);let n=await H({...G,type:"workspace-read",id:_(m),payload:o});if(!n||!("kind"in n)||!("state"in n)||n.kind!==o.kind)throw new p("HOST_REJECTED","Host did not return workspace data.");return n},st=async(o,n)=>{o.kind!=="projects"&&K(o.projectId);let d=_(m);ce.set(d,n);try{await U({...G,type:"workspace-subscribe",id:_(m),payload:{subscriptionId:d,query:o}})}catch(l){throw ce.delete(d),J||V({...G,type:"workspace-unsubscribe",id:_(m),payload:{subscriptionId:d}}),l}return()=>{!ce.delete(d)||J||V({...G,type:"workspace-unsubscribe",id:_(m),payload:{subscriptionId:d}})}},fn=async(o,n)=>{o.kind==="session"&&K(o.sessionId),o.kind==="project"&&K(o.projectId);let d=_(m);de.set(d,n);try{await U({...G,type:"shells-subscribe",id:_(m),payload:{subscriptionId:d,scope:o}})}catch(l){throw de.delete(d),J||V({...G,type:"shells-unsubscribe",id:_(m),payload:{subscriptionId:d}}),l}return()=>{!de.delete(d)||J||V({...G,type:"shells-unsubscribe",id:_(m),payload:{subscriptionId:d}})}},Ge=async o=>{if("key"in o&&(o.key.length===0||o.key.length>128))throw new p("HOST_REJECTED","Storage key must contain 1 to 128 characters.");if(o.op==="set"&&!le(o.value))throw new p("HOST_REJECTED","Storage values must be JSON.");if(o.op==="set"&&new TextEncoder().encode(JSON.stringify(o.value)).length>65536)throw new p("HOST_REJECTED","Storage value exceeds 64 KiB.");if(o.scope==="device"&&E?.features?.deviceStorage!==!0)throw new p("UNSUPPORTED","This host does not support device storage.");let n=await H({...G,type:"storage",id:_(m),payload:o});if(!n||!("storage"in n)||n.op!==o.op)throw new p("HOST_REJECTED","Host did not return storage data.");return n},po=(o,n)=>E?.features?.popovers!==!0&&!(E?.surface==="popover"&&E.popover?.id===o)?Promise.reject(new p("UNSUPPORTED","This host does not support popovers.")):U({...G,type:"popover-close",id:_(m),payload:n?{id:o,reason:n}:{id:o}}),uo=(o,n)=>E?.features?.popovers!==!0&&!(E?.surface==="popover"&&E.popover?.id===o)?Promise.reject(new p("UNSUPPORTED","This host does not support popovers.")):U({...G,type:"popover-anchor",id:_(m),payload:{id:o,active:n}});return t.addEventListener("keydown",io,!0),t.addEventListener("pointerover",Ue),t.addEventListener("pointermove",Ue),t.addEventListener("pointerout",ao),t.addEventListener("focus",co),t.addEventListener("blur",lo),{onAction:o=>(re=o,()=>{re===o&&(re=null)}),listProjects:async()=>{let o=await rt({kind:"projects"});if(o.kind!=="projects")throw new p("HOST_REJECTED","Expected projects.");return o},listWorktrees:async o=>{let n=await rt({kind:"worktrees",projectId:o});if(n.kind!=="worktrees")throw new p("HOST_REJECTED","Expected worktrees.");return n},listSessions:async o=>{let n=await rt({kind:"sessions",projectId:o});if(n.kind!=="sessions")throw new p("HOST_REJECTED","Expected sessions.");return n},onProjects:o=>st({kind:"projects"},n=>{n.kind==="projects"&&o(n)}),onWorktrees:(o,n)=>st({kind:"worktrees",projectId:o},d=>{d.kind==="worktrees"&&n(d)}),onSessions:(o,n)=>st({kind:"sessions",projectId:o},d=>{d.kind==="sessions"&&n(d)}),onRunningShells:(o,n)=>fn(o,n),readShellOutput:async(o,n)=>{K(o,128);let d=n?.cursor;if(d!==void 0&&(!Number.isInteger(d)||d<0))throw new p("HOST_REJECTED","Shell output cursor must be a non-negative integer.");let l=n?.tailBytes;if(l!==void 0&&(!Number.isInteger(l)||l<1||l>65536))throw new p("HOST_REJECTED",`Shell output tailBytes must be an integer between 1 and ${65536}.`);let O=await H({...G,type:"shell-output",id:_(m),payload:{shellId:o,cursor:d,tailBytes:l}});if(!O||typeof O.output!="string"||!Number.isFinite(O.cursor))throw new p("HOST_REJECTED","Host did not return shell output.");return O},stopShell:async o=>{if(K(o,128),(await H({...G,type:"shell-stop",id:_(m),payload:{shellId:o}}))?.stopped!==!0)throw new p("HOST_REJECTED","Host did not stop the shell.");return{stopped:!0}},openSession:async o=>{K(o),await U({...G,type:"open-session",id:_(m),payload:{sessionId:o}})},storage:{get:async(o,n)=>{let d=je(n),l={op:"get",key:o};d&&(l.scope=d);let v=await Ge(l);return v.op==="get"&&v.found?v.value:void 0},set:async(o,n,d)=>{let l=je(d),v={op:"set",key:o,value:n};l&&(v.scope=l),await Ge(v)},delete:async(o,n)=>{let d=je(n),l={op:"delete",key:o};d&&(l.scope=d),await Ge(l)},keys:async o=>{let n=je(o),d={op:"keys"};n&&(d.scope=n);let l=await Ge(d);if(l.op!=="keys")throw new p("HOST_REJECTED","Expected storage keys.");return l.keys}},onReady:o=>(c.add(o),E&&o(E),()=>{c.delete(o)}),onDirectory:o=>(u.add(o),E&&o(E.directory),()=>{u.delete(o)}),onSession:o=>(i.add(o),E&&o(E.session),()=>{i.delete(o)}),onSessionLifecycle:o=>(f.add(o),q&&o(q),()=>{f.delete(o)}),onConnection:o=>(x.add(o),E&&o(E.connection),()=>{x.delete(o)}),onSettings:o=>(w.add(o),E&&o(E.settings),()=>{w.delete(o)}),onItem:o=>(a.add(o),E&&o(E.item),()=>{a.delete(o)}),onStatusControl:o=>(b.add(o),()=>{b.delete(o)}),onPopoverClosed:o=>(g.add(o),()=>{g.delete(o)}),setStatusControls:o=>E?.features?.statusControls!==!0?Promise.reject(new p("UNSUPPORTED","This host does not support status controls.")):So(o)?U({...G,type:"status-controls",id:_(m),payload:{controls:o}}):Promise.reject(new p("HOST_REJECTED","Status controls must have unique bounded ids and valid selected options.")),openPopover:o=>E?.features?.popovers!==!0?Promise.reject(new p("UNSUPPORTED","This host does not support popovers.")):lt(o)?U({...G,type:"popover-open",id:_(m),payload:o}):Promise.reject(new p("HOST_REJECTED","Popover requests need bounded geometry and JSON data.")),closePopover:po,setPopoverAnchorActive:uo,onResolve:o=>(oe=o,()=>{oe===o&&(oe=null)}),toast:o=>{let n=o.message.trim();return!n||n.length>Pe?Promise.reject(new p("HOST_REJECTED",`Toast message must contain 1 to ${Pe} characters.`)):o.copy&&o.copy!==!0&&(!o.copy.text.length||o.copy.text.length>De)?Promise.reject(new p("HOST_REJECTED",`Toast copy text must contain 1 to ${De} characters.`)):U({channel:S,v:1,type:"toast",id:_(m),payload:{...o,message:n}})},openUrl:o=>U({channel:S,v:1,type:"open-url",id:_(m),payload:{url:o}}),openCommit:o=>Et(o)?U({channel:S,v:1,type:"open-commit",id:_(m),payload:{sha:o}}):Promise.reject(new p("HOST_REJECTED","Commit id must be 7 to 64 hex characters.")),openSurface:o=>U({channel:S,v:1,type:"open-surface",id:_(m),payload:{surfaceId:o}}),writeClipboard:o=>U({channel:S,v:1,type:"clipboard-write",id:_(m),payload:{text:o}}),compose:o=>U({channel:S,v:1,type:"compose",id:_(m),payload:o}),attach:o=>U({channel:S,v:1,type:"attach",id:_(m),payload:pe(o)}),startSession:async o=>{o.projectId!==void 0&&K(o.projectId);let n=o.worktree;n&&n!==!0&&(n.kind==="existing"?K(n.directory):(n.name!==void 0&&K(n.name,200),n.baseBranch!==void 0&&K(n.baseBranch,200)));let d=await H({channel:S,v:1,type:"start-session",id:_(m),payload:St(o)},e.requestTimeoutMs??18e4);if(!ut(d))throw new p("HOST_REJECTED","Host did not return a session.");return d},prompt:o=>H({channel:S,v:1,type:"prompt",id:_(m),payload:Tt(o)}).then(n=>{if(!ft(n))throw new p("HOST_REJECTED","Host did not return a prompt result.");return n}),sessionLink:o=>U({channel:S,v:1,type:"session-link",id:_(m),payload:pe(o)}),close:()=>U({channel:S,v:1,type:"close",id:_(m)}),oauthStart:()=>U({channel:S,v:1,type:"oauth-start",id:_(m)}),oauthDisconnect:()=>U({channel:S,v:1,type:"oauth-disconnect",id:_(m)}),request:o=>(Be(o.path)?H({channel:S,v:1,type:"request",id:_(m),payload:o}):Bo()).then(n=>{if(!Ve(n))throw new p("HOST_REJECTED","Host request result was empty.");return n}),serviceRequest:o=>(Be(o.path)?H({channel:S,v:1,type:"service-request",id:_(m),payload:o}):Bo()).then(n=>{if(!Ve(n))throw new p("HOST_REJECTED","Host service request result was empty.");return n}),serviceStatus:()=>H({channel:S,v:1,type:"service-status",id:_(m)}).then(o=>{if(!bt(o))throw new p("HOST_REJECTED","Host did not return service status.");return o}),readFile:o=>(ue(o)?H({channel:S,v:1,type:"file-read",id:_(m),payload:{path:o}}):ze()).then(n=>{if(!At(n))throw new p("HOST_REJECTED","Host did not return file content.");return n}),writeFile:(o,n)=>ue(o)?n.length>$e?Promise.reject(new p("FILE_TOO_LARGE",`Content is over ${$e} characters.`)):H({channel:S,v:1,type:"file-write",id:_(m),payload:{path:o,content:n}}).then(d=>{if(!kt(d))throw new p("HOST_REJECTED","Host did not confirm the write.");return d}):ze(),listDir:o=>(ue(o)?H({channel:S,v:1,type:"file-list",id:_(m),payload:{path:o}}):ze()).then(n=>{if(!yt(n))throw new p("HOST_REJECTED","Host did not return directory entries.");return n}),stat:o=>(ue(o)?H({channel:S,v:1,type:"file-stat",id:_(m),payload:{path:o}}):ze()).then(n=>{if(!Ot(n))throw new p("HOST_REJECTED","Host did not return file status.");return n}),generate:o=>{let n=o.prompt.trim(),d=o.system?.trim();if(n.length===0||n.length>Fe)return Promise.reject(new p("HOST_REJECTED",`Prompt must be 1 to ${Fe} characters.`));if(d!==void 0&&(d.length===0||d.length>Xe))return Promise.reject(new p("HOST_REJECTED",`System prompt must be 1 to ${Xe} characters.`));let l=o.maxOutputTokens===void 0?void 0:Math.min(mt,Math.max(1,Math.floor(o.maxOutputTokens)));if(l!==void 0&&!Number.isFinite(l))return Promise.reject(new p("HOST_REJECTED","maxOutputTokens must be a number."));let v={prompt:n};return d!==void 0&&(v.system=d),l!==void 0&&(v.maxOutputTokens=l),H({channel:S,v:1,type:"generate",id:_(m),payload:v},e.requestTimeoutMs??_t).then(O=>{if(!vt(O))throw new p("HOST_REJECTED","Host did not return generated text.");return O})},onLateGenerateResult:o=>{A.add(o);for(let n of z.splice(0))I([o],n);return oo(),()=>{A.delete(o)}},setBadge:o=>U({channel:S,v:1,type:"badge",id:_(m),payload:{count:gt(o)}}),setHeight:o=>U({channel:S,v:1,type:"resize",id:_(m),payload:{height:xt(o)}}),onFileOpen:o=>(Me.add(o),ot||(ot=!0,t.addEventListener("keydown",so,!0)),Te&&o(Te),()=>{Me.delete(o)}),onFileSnapshot:o=>(Se=o,()=>{Se===o&&(Se=null)}),onFileSaved:o=>(Ie.add(o),()=>{Ie.delete(o)}),reportFileChange:o=>nt({...G,type:"file-change",payload:{dirty:o.dirty,edited:o.edited}}),requestFileSave:ro,reportFileUnsupported:()=>nt({...G,type:"file-unsupported"}),dispose:()=>{for(let o of ce.keys())V({...G,type:"workspace-unsubscribe",id:_(m),payload:{subscriptionId:o}});ce.clear();for(let o of de.keys())V({...G,type:"shells-unsubscribe",id:_(m),payload:{subscriptionId:o}});de.clear(),J=!0,oe=null,re=null,Se=null,Me.clear(),Ie.clear(),ot&&t.removeEventListener("keydown",so,!0),t.removeEventListener("message",no),t.removeEventListener("keydown",io,!0),t.removeEventListener("pointerover",Ue),t.removeEventListener("pointermove",Ue),t.removeEventListener("pointerout",ao),t.removeEventListener("focus",co),t.removeEventListener("blur",lo);for(let o of ae.values())clearTimeout(o.timer),o.reject(new p("HOST_UNAVAILABLE","Host client was disposed."));ae.clear(),c.clear(),u.clear(),i.clear(),f.clear(),x.clear(),w.clear(),a.clear(),b.clear(),g.clear(),A.clear(),z.length=0}}};var jo=["browser.open","browser.snapshot","browser.click","browser.type","browser.scroll","browser.back","browser.forward","browser.inspect","browser.capture","browser.resize","browser.close"];var Tr=new Set(jo);var Ko=["none","agent","user"];var xr=new Set(Ko);var An=[["--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"]],kn=[["--oc-syntax-keyword","--syntax-keyword","syntaxKeyword"],["--oc-syntax-string","--syntax-string","syntaxString"],["--oc-syntax-number","--syntax-number","syntaxNumber"],["--oc-syntax-function","--syntax-function","syntaxFunction"],["--oc-syntax-type","--syntax-type","syntaxType"],["--oc-syntax-comment","--syntax-comment","syntaxComment"],["--oc-syntax-variable","--syntax-variable","syntaxVariable"],["--oc-syntax-operator","--syntax-operator","syntaxOperator"]],Wo=(e,t)=>{t.style.colorScheme=e.mode;for(let[r,s]of An)t.style.setProperty(r,e.tokens[s]);for(let[r,s,c]of kn){let u=e.tokens[c]??"";t.style.setProperty(r,u),t.style.setProperty(s,u)}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)},Ut=(e,t)=>{Wo(e.theme,t),t.dataset&&(t.dataset.ocSurface=e.surface,t.dataset.ocTheme=e.theme.mode)};var yn={"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"},L=(e,t)=>`var(--${e}, var(--oc-${yn[e]}, ${t}))`,Z=L("surface-background","transparent"),We=L("surface-elevated","transparent"),fe=L("surface-elevated-foreground","inherit"),j=L("surface-foreground","inherit"),R=L("surface-muted-foreground","gray"),On=L("surface-muted","transparent"),ne=L("interactive-border","currentColor"),$=L("interactive-hover","transparent"),se=L("interactive-active","transparent"),Gt=L("interactive-selection","transparent"),Nt=L("interactive-selection-foreground","inherit"),Q=L("primary","currentColor"),Pt=L("primary-text","inherit"),Dt=L("error-text","inherit"),vn=L("font-sans","inherit"),Ht=L("font-mono","monospace"),Zo=L("radius","9px"),$t=`calc(${Zo} - 2px)`,Jo=`calc(${Zo} - 4px)`,C=(e,t,r="transparent")=>`color-mix(in srgb, ${e} ${t}%, ${r})`,Yo=`background-image: linear-gradient(${$}, ${$});`,Ft=e=>`box-shadow: inset 0 0 0 1px ${e}, var(--oc-sdk-field-lift);`,Xt="box-shadow: inset 0 0 0 1px var(--oc-sdk-edge), var(--oc-sdk-raised-lift);",qo="box-shadow: var(--oc-sdk-lit);",Qo=`inset 0 1px 0 0 ${C(j,1.5)}, 0 1px 1px 0 rgb(0 0 0 / 0.28), 0 2px 3px -2px rgb(0 0 0 / 0.2)`,wn=`
36
+ :root {
37
+ --oc-sdk-edge: ${C(j,10)};
38
+ --oc-sdk-field-bg: ${We};
39
+ --oc-sdk-raised-bg: ${Z};
40
+ --oc-sdk-field-lift: inset 0 1px 2px 0 rgb(0 0 0 / 0.04);
41
+ --oc-sdk-raised-lift: 0 1px 2px 0 rgb(0 0 0 / 0.06);
42
+ --oc-sdk-lit: inset 0 1px 0 0 rgb(255 255 255 / 0.45), 0 1px 2px 0 rgb(0 0 0 / 0.08);
43
+ --oc-sdk-float: inset 0 1px 0 0 rgb(255 255 255 / 0.8), inset 0 0 0 1px rgb(0 0 0 / 0.04), 0 0 0 1px rgb(0 0 0 / 0.1), 0 1px 2px -0.5px rgb(0 0 0 / 0.08), 0 4px 8px -2px rgb(0 0 0 / 0.08), 0 12px 20px -4px rgb(0 0 0 / 0.08);
44
+ }
45
+ :root[data-oc-theme="dark"] {
46
+ --oc-sdk-edge: ${C(j,6)};
47
+ --oc-sdk-field-bg: ${C(Z,50,We)};
48
+ --oc-sdk-raised-bg: ${We};
49
+ --oc-sdk-field-lift: ${Qo};
50
+ --oc-sdk-raised-lift: ${Qo};
51
+ --oc-sdk-lit: inset 0 1px 0 0 ${C(j,1.5)}, 0 1px 1px 0 rgb(0 0 0 / 0.28), 0 2px 3px -2px rgb(0 0 0 / 0.2);
52
+ --oc-sdk-float: inset 0 1px 0 0 rgb(255 255 255 / 0.06), inset 0 0 0 1px rgb(255 255 255 / 0.08), 0 0 0 1px rgb(0 0 0 / 0.36), 0 1px 1px -0.5px rgb(0 0 0 / 0.22), 0 3px 3px -1.5px rgb(0 0 0 / 0.2), 0 6px 6px -3px rgb(0 0 0 / 0.16);
53
+ }`,Ke=e=>{let t=L(`status-${e}`,"currentColor");return`
54
+ .oc-sdk[data-tone="${e}"], .oc-sdk [data-tone="${e}"] { --oc-sdk-tone: ${t}; --oc-sdk-tone-text: ${L(`${e}-text`,"inherit")}; }`},Rn=`
55
+ .oc-sdk { box-sizing: border-box; font-size: 0.875rem; line-height: 1.45; }
56
+ .oc-sdk *, .oc-sdk *::before, .oc-sdk *::after { box-sizing: border-box; }
57
+ /* :where() keeps the reset at zero specificity so every primitive class below overrides it. */
58
+ :where(.oc-sdk) :where(button, input, textarea), :where(button.oc-sdk, input.oc-sdk, textarea.oc-sdk) { font: inherit; color: inherit; margin: 0; }
59
+ :where(.oc-sdk) :where(button), :where(button.oc-sdk) { cursor: pointer; background: none; border: 0; padding: 0; }
60
+ .oc-sdk button:disabled, button.oc-sdk:disabled, .oc-sdk[aria-disabled="true"], .oc-sdk [aria-disabled="true"] { opacity: .5; pointer-events: none; }
61
+
62
+ .oc-sdk-btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; height: 32px; padding: 0 12px; border: 1px solid transparent; font-size: 0.875rem; font-weight: 500; line-height: 1; white-space: nowrap; }
63
+ .oc-sdk-btn[data-size="sm"] { gap: 6px; height: 28px; padding: 0 10px; font-size: 0.8125rem; }
64
+ .oc-sdk-btn[data-size="xs"] { gap: 4px; height: 24px; padding: 0 8px; font-size: 0.75rem; }
65
+ .oc-sdk-btn[data-loading="true"] { opacity: .5; pointer-events: none; }
66
+ .oc-sdk-btn > .oc-sdk-spinner-ring { width: 14px; height: 14px; }
67
+
68
+ .oc-sdk-field { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
69
+ .oc-sdk-field-label { font-size: 0.8125rem; font-weight: 500; }
70
+ .oc-sdk-field-note { font-size: 0.75rem; }
71
+ .oc-sdk-input { display: block; width: 100%; min-width: 0; height: 32px; padding: 0 10px; border: 0; font-size: 0.875rem; line-height: 1.45; appearance: none; }
72
+ textarea.oc-sdk-input { height: auto; padding: 8px 10px; resize: vertical; }
73
+
74
+ .oc-sdk-search { position: relative; min-width: 0; }
75
+ .oc-sdk-search .oc-sdk-input { padding-left: 34px; padding-right: 34px; }
76
+ .oc-sdk-search-icon { position: absolute; left: 11px; top: 50%; transform: translateY(-50%); pointer-events: none; }
77
+ .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; }
78
+ .oc-sdk-search[data-active="true"] .oc-sdk-search-clear { display: inline-flex; }
79
+
80
+ .oc-sdk-select { position: relative; display: flex; flex-direction: column; gap: 4px; min-width: 0; }
81
+ .oc-sdk-trigger { display: inline-flex; align-items: center; gap: 6px; align-self: flex-start; width: auto; max-width: 100%; min-width: 0; height: 28px; padding: 0 10px; border: 1px solid transparent; font-size: 0.8125rem; text-align: left; }
82
+ .oc-sdk-trigger-value { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
83
+ .oc-sdk-trigger-chevron { flex: 0 0 auto; }
84
+ .oc-sdk-popup { 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 transparent; }
85
+ .oc-sdk-popup-search { flex: 0 0 auto; padding: 2px 2px 4px; }
86
+ .oc-sdk-popup-search .oc-sdk-input { height: 28px; font-size: 0.8125rem; }
87
+ .oc-sdk-option { display: flex; align-items: center; gap: 8px; width: 100%; padding: 6px 8px; font-size: 0.8125rem; text-align: left; }
88
+ .oc-sdk-option-label { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
89
+ .oc-sdk-option-hint { flex: 0 0 auto; font-size: 0.75rem; }
90
+ .oc-sdk-option-check { flex: 0 0 auto; display: inline-flex; width: 14px; visibility: hidden; }
91
+ .oc-sdk-option[aria-selected="true"] > .oc-sdk-option-check { visibility: visible; }
92
+ .oc-sdk-popup-empty { padding: 8px; font-size: 0.8125rem; }
93
+
94
+ .oc-sdk-check { display: inline-flex; align-items: flex-start; gap: 8px; width: 100%; text-align: left; }
95
+ .oc-sdk-check-box { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; width: 14px; height: 14px; margin-top: 3px; border: 1px solid transparent; }
96
+ .oc-sdk-check-box > svg { display: none; }
97
+ .oc-sdk-check[aria-checked="true"] .oc-sdk-check-box > svg { display: block; }
98
+ .oc-sdk-check-thumb { flex: 0 0 auto; position: relative; width: 36px; height: 20px; }
99
+ .oc-sdk-check-thumb::after { content: ""; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; }
100
+ .oc-sdk-check-text { display: flex; flex-direction: column; min-width: 0; }
101
+ .oc-sdk-check-label { font-size: 0.875rem; }
102
+ .oc-sdk-check-desc { font-size: 0.75rem; }
103
+
104
+ .oc-sdk-tabs { display: inline-flex; gap: 2px; padding: 2px; max-width: 100%; overflow: auto; }
105
+ .oc-sdk-tab { display: inline-flex; align-items: center; gap: 6px; height: 28px; padding: 0 10px; border: 1px solid transparent; font-size: 0.8125rem; font-weight: 500; white-space: nowrap; }
106
+ .oc-sdk-tab-count { font-size: 0.75rem; font-variant-numeric: tabular-nums; }
107
+
108
+ .oc-sdk-badge { display: inline-flex; align-items: center; padding: 1px 6px; font-size: 11px; font-weight: 500; line-height: 16px; white-space: nowrap; }
109
+
110
+ .oc-sdk-list { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
111
+ .oc-sdk-row { display: flex; align-items: center; gap: 8px; width: 100%; padding: 6px 8px; text-align: left; }
112
+ .oc-sdk-row-lead { flex: 0 0 auto; width: 64px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 0.75rem; }
113
+ .oc-sdk-row-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
114
+ .oc-sdk-row-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
115
+ .oc-sdk-row-sub { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 0.75rem; }
116
+ .oc-sdk-row-meta { flex: 0 0 auto; font-size: 0.75rem; font-variant-numeric: tabular-nums; }
117
+ .oc-sdk-list-empty { padding: 16px 8px; text-align: center; font-size: 0.8125rem; }
118
+
119
+ .oc-sdk-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px; padding: 40px 16px; text-align: center; }
120
+ .oc-sdk-empty-title { margin: 0; font-size: 0.8125rem; font-weight: 600; }
121
+ .oc-sdk-empty-body { margin: 0; max-width: 32rem; font-size: 0.8125rem; }
122
+ .oc-sdk-empty-action { margin-top: 12px; }
123
+
124
+ @keyframes oc-sdk-spin { to { transform: rotate(360deg); } }
125
+ .oc-sdk-spinner { display: inline-flex; align-items: center; gap: 8px; font-size: 0.8125rem; }
126
+ .oc-sdk-spinner-ring { width: 16px; height: 16px; border: 2px solid transparent; animation: oc-sdk-spin .8s linear infinite; }
127
+ .oc-sdk-spinner[data-size="sm"] .oc-sdk-spinner-ring { width: 12px; height: 12px; }
128
+
129
+ .oc-sdk-banner { display: flex; align-items: flex-start; gap: 12px; padding: 8px 12px; border: 1px solid transparent; }
130
+ .oc-sdk-banner-text { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
131
+ .oc-sdk-banner-title { font-size: 0.8125rem; font-weight: 500; }
132
+ .oc-sdk-banner-body { font-size: 0.8125rem; }
133
+ .oc-sdk-banner-action { flex: 0 0 auto; }
134
+
135
+ .oc-sdk-separator { display: flex; align-items: center; gap: 8px; width: 100%; margin: 8px 0; font-size: 0.75rem; }
136
+ .oc-sdk-separator::before, .oc-sdk-separator::after { content: ""; flex: 1 1 auto; height: 1px; }
137
+ .oc-sdk-separator[data-labeled="false"]::after { display: none; }
138
+ .oc-sdk-popup > .oc-sdk-separator { margin: 4px 0; }
139
+
140
+ .oc-sdk-progress { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
141
+ .oc-sdk-progress-label { display: flex; justify-content: space-between; font-size: 0.75rem; font-variant-numeric: tabular-nums; }
142
+ .oc-sdk-progress-track { height: 6px; overflow: hidden; }
143
+ .oc-sdk-progress-fill { height: 100%; transform-origin: left; transition: transform 200ms ease-out; }
144
+
145
+ .oc-sdk-menu { position: relative; display: inline-flex; }
146
+
147
+ .oc-sdk-text { white-space: pre-wrap; overflow-wrap: anywhere; }
148
+ .oc-sdk-text img { display: block; max-width: 100%; margin: 8px 0; }
149
+ `,en=`${wn}
150
+ .oc-sdk { color: ${j}; font-family: ${vn}; }
151
+ .oc-sdk :focus-visible, .oc-sdk:focus-visible { outline: none; }
152
+ .oc-sdk :where(button, a[href], [role="button"], [role="tab"], [role="option"]):focus-visible, button.oc-sdk:focus-visible { ${Yo} }
153
+ .oc-sdk-mono { font-family: ${Ht}; }
154
+ .oc-sdk-muted { color: ${R}; }
155
+ ${Ke("success")}${Ke("warning")}${Ke("error")}${Ke("info")}
156
+ .oc-sdk[data-tone="primary"], .oc-sdk [data-tone="primary"] { --oc-sdk-tone: ${Q}; --oc-sdk-tone-text: ${Pt}; }
157
+
158
+ .oc-sdk-btn { border-radius: ${$t}; transition: background 150ms ease-out, color 150ms ease-out; }
159
+ .oc-sdk-btn[data-size="xs"] { border-radius: ${Jo}; }
160
+ .oc-sdk-btn[data-variant="default"] { color: ${Pt}; background: ${C(Q,10,Z)}; border-color: ${C(Q,12)}; ${qo} }
161
+ .oc-sdk-btn[data-variant="default"]:hover { background: ${C(Q,16,Z)}; }
162
+ .oc-sdk-btn[data-variant="default"]:active { background: ${C(Q,22,Z)}; box-shadow: none; }
163
+ .oc-sdk-btn[data-variant="secondary"] { background: ${On}; color: var(--oc-fg); }
164
+ .oc-sdk-btn[data-variant="secondary"]:hover { background-image: linear-gradient(${$}, ${$}); }
165
+ .oc-sdk-btn[data-variant="secondary"]:active { background-image: linear-gradient(${se}, ${se}); }
166
+ .oc-sdk-btn[data-variant="outline"] { background: var(--oc-sdk-raised-bg); color: ${fe}; border-color: transparent; ${Xt} }
167
+ .oc-sdk-btn[data-variant="outline"]:hover { background-image: linear-gradient(${$}, ${$}); }
168
+ .oc-sdk-btn[data-variant="outline"]:active { background-image: linear-gradient(${se}, ${se}); box-shadow: inset 0 0 0 1px var(--oc-sdk-edge); }
169
+ .oc-sdk-btn[data-variant="ghost"] { background: transparent; }
170
+ .oc-sdk-btn[data-variant="ghost"]:hover { background: ${$}; }
171
+ .oc-sdk-btn[data-variant="ghost"]:active { background: ${se}; }
172
+ .oc-sdk-btn[data-variant="destructive"] { --oc-sdk-tone: ${L("status-error","red")}; color: ${Dt}; background: ${C("var(--oc-sdk-tone)",7,Z)}; border-color: ${C("var(--oc-sdk-tone)",12)}; ${qo} }
173
+ .oc-sdk-btn[data-variant="destructive"]:hover { background: ${C("var(--oc-sdk-tone)",9,Z)}; }
174
+ .oc-sdk-btn[data-variant="destructive"]:active { background: ${C("var(--oc-sdk-tone)",11,Z)}; box-shadow: none; }
175
+
176
+ .oc-sdk-field-note { color: ${R}; }
177
+ .oc-sdk-field[data-invalid="true"] .oc-sdk-field-note { color: ${Dt}; }
178
+ .oc-sdk-input { border-radius: ${$t}; background: var(--oc-sdk-field-bg); color: ${fe}; ${Ft("var(--oc-sdk-edge)")} transition: background 150ms ease-out; }
179
+ .oc-sdk-input::placeholder { color: ${R}; }
180
+ .oc-sdk-input:hover:not(:focus) { background-image: linear-gradient(${$}, ${$}); }
181
+ .oc-sdk-input:focus, .oc-sdk-input:focus-visible { ${Ft(C(j,26))} }
182
+ .oc-sdk-field[data-invalid="true"] .oc-sdk-input, .oc-sdk-field[data-invalid="true"] .oc-sdk-input:focus { ${Ft(L("status-error","red"))} }
183
+ .oc-sdk-input[data-mono="true"] { font-family: ${Ht}; }
184
+
185
+ .oc-sdk-search-icon { color: ${R}; }
186
+ .oc-sdk-search[data-active="true"] .oc-sdk-search-icon { color: ${Q}; }
187
+ .oc-sdk-search-clear { border-radius: ${Jo}; color: ${R}; }
188
+ .oc-sdk-search-clear:hover { background: ${$}; color: ${j}; }
189
+
190
+ .oc-sdk-trigger { border-color: transparent; border-radius: ${$t}; background: var(--oc-sdk-raised-bg); color: ${fe}; ${Xt} transition: background 150ms ease-out; }
191
+ .oc-sdk-trigger:hover { background-image: linear-gradient(${$}, ${$}); }
192
+ .oc-sdk-trigger[aria-expanded="true"] { background-image: linear-gradient(${se}, ${se}); }
193
+ .oc-sdk-trigger-value[data-empty="true"] { color: ${R}; }
194
+ .oc-sdk-trigger-chevron { color: ${R}; }
195
+ /* The app's dropdown light: lit top, hairline rings and a layered shadow, no border. */
196
+ .oc-sdk-popup { --surface-foreground: ${fe}; border-color: transparent; border-radius: 12px; background: ${We}; color: ${fe}; box-shadow: var(--oc-sdk-float); }
197
+ .oc-sdk-option { border-radius: 8px; }
198
+ .oc-sdk-option[data-active="true"] { background: ${$}; }
199
+ /* A selected option shows a check mark in the text colour, like the app's own pickers. Options without the mark come
200
+ from bundles built before it existed and keep the selection fill as their only sign of the choice. */
201
+ .oc-sdk-option[aria-selected="true"]:not([data-mark]) { background: ${Gt}; color: ${Nt}; }
202
+ .oc-sdk-option-check { color: ${j}; }
203
+ .oc-sdk-option[data-destructive="true"] { color: ${Dt}; }
204
+ .oc-sdk-option[data-destructive="true"][data-active="true"] { background: ${C(L("status-error","red"),10)}; }
205
+ .oc-sdk-option-hint { color: ${R}; }
206
+ .oc-sdk-popup-empty { color: ${R}; }
207
+
208
+ /* Checked stays neutral: the mark carries the state, and the primary colour stays with primary actions. */
209
+ .oc-sdk-check-box { border-color: ${ne}; border-radius: 4px; color: ${j}; transition: border-color 150ms ease-out; }
210
+ .oc-sdk-check[aria-checked="true"] .oc-sdk-check-box { border-color: ${C(j,60,ne)}; }
211
+ .oc-sdk-check-thumb { border-radius: 9999px; background: ${ne}; transition: background 150ms ease-out; }
212
+ .oc-sdk-check-thumb::after { border-radius: 9999px; background: ${Z}; transition: transform 150ms ease-out; }
213
+ .oc-sdk-check[aria-checked="true"] .oc-sdk-check-thumb { background: ${Q}; }
214
+ .oc-sdk-check[aria-checked="true"] .oc-sdk-check-thumb::after { transform: translateX(16px); }
215
+ .oc-sdk-check:focus-visible { box-shadow: none; }
216
+ .oc-sdk-check:focus-visible .oc-sdk-check-box, .oc-sdk-check:focus-visible .oc-sdk-check-thumb { ${Yo} }
217
+ .oc-sdk-check-desc { color: ${R}; }
218
+
219
+ .oc-sdk-tabs { border-radius: 10px; }
220
+ .oc-sdk-tabs[data-track="true"] { background: ${C(j,4)}; box-shadow: inset 0 1px 2px 0 rgb(0 0 0 / 0.16); }
221
+ .oc-sdk-tab { border-radius: 8px; color: ${R}; transition: color 150ms ease-out, background 150ms ease-out; }
222
+ .oc-sdk-tab:hover { color: ${j}; }
223
+ .oc-sdk-tab[aria-selected="true"] { color: ${Nt}; background: ${Gt}; border-color: ${ne}; }
224
+ .oc-sdk-tabs[data-track="true"] .oc-sdk-tab[aria-selected="true"] { color: ${fe}; background: var(--oc-sdk-raised-bg); border-color: transparent; ${Xt} }
225
+ .oc-sdk-tab-count { color: ${R}; }
226
+
227
+ .oc-sdk-badge { border-radius: 9999px; background: ${$}; color: ${R}; }
228
+ .oc-sdk-badge[data-tone] { color: var(--oc-sdk-tone-text, var(--oc-sdk-tone)); background: ${C("var(--oc-sdk-tone)",15)}; }
229
+
230
+ .oc-sdk-row { border-radius: 6px; transition: background 120ms ease-out; }
231
+ .oc-sdk-row:hover, .oc-sdk-row[data-active="true"] { background: ${$}; }
232
+ .oc-sdk-row[aria-selected="true"] { background: ${Gt}; color: ${Nt}; }
233
+ .oc-sdk-row-lead { font-family: ${Ht}; color: ${R}; }
234
+ .oc-sdk-row-sub { color: ${R}; }
235
+ .oc-sdk-row-meta { color: ${R}; }
236
+ .oc-sdk-row[aria-selected="true"] .oc-sdk-row-lead, .oc-sdk-row[aria-selected="true"] .oc-sdk-row-sub, .oc-sdk-row[aria-selected="true"] .oc-sdk-row-meta { color: inherit; opacity: .75; }
237
+ .oc-sdk-list-empty { color: ${R}; }
238
+
239
+ .oc-sdk-empty-body { color: ${R}; }
240
+
241
+ .oc-sdk-spinner { color: ${R}; }
242
+ .oc-sdk-spinner-ring { border-color: ${ne}; border-top-color: ${Q}; border-radius: 9999px; }
243
+
244
+ /* Set apart by its tint alone, like the app's banners. */
245
+ .oc-sdk-banner { border-color: transparent; border-radius: 8px; background: ${C("var(--oc-sdk-tone)",10)}; }
246
+ .oc-sdk-banner-title { color: var(--oc-sdk-tone-text, var(--oc-sdk-tone)); }
247
+ .oc-sdk-banner-body { color: ${R}; }
248
+
249
+ .oc-sdk-separator { color: ${R}; }
250
+ .oc-sdk-separator::before, .oc-sdk-separator::after { background: ${C(ne,40)}; }
251
+
252
+ .oc-sdk-progress-label { color: ${R}; }
253
+ .oc-sdk-progress-track { border-radius: 9999px; background: ${ne}; }
254
+ .oc-sdk-progress-fill { border-radius: 9999px; background: var(--oc-sdk-tone, ${Q}); }
255
+
256
+ .oc-sdk-text a { color: ${Pt}; text-decoration: underline; text-underline-offset: 2px; }
257
+ .oc-sdk-text img { border-radius: 8px; border: 1px solid ${C(ne,60)}; }
258
+ `,F=`
259
+ ${it}
260
+ ${Rn}
261
+ ${en}`;var Un=e=>24+e*308;function on(e){let t=new Map,r=new Map;for(let a of e.nodes)r.set(a.column,[...r.get(a.column)??[],a]);let s=[...r.keys()].sort((a,b)=>a-b),c=new Map(s.map(a=>[a,Un(a)])),u=new Map,i=0;for(let a of s)(r.get(a)??[]).slice().sort((g,A)=>(u.get(g.parentId??"")??-1)-(u.get(A.parentId??"")??-1)||(g.createdAt??0)-(A.createdAt??0)||g.id.localeCompare(A.id)).forEach((g,A)=>{let z=58+A*94;t.set(g.id,{x:c.get(a)??0,y:z}),u.set(g.id,u.size),i=Math.max(i,z+80+24)});let f=t.get(e.rootId),x=e.nodes.filter(a=>a.parentId===e.rootId).map(a=>t.get(a.id)).filter(a=>a!==void 0);if(f&&x.length>0&&(r.get(0)?.length??0)===1){let a=Math.min(...x.map(g=>g.y)),b=Math.max(...x.map(g=>g.y));f.y=Math.round((a+b)/2)}let w=24+(Math.max(0,...s)+1)*308-76+24;return{boxes:t,edges:Gn(e.edges,t),columnX:c,width:w,height:Math.max(i,162)}}function tn(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 Gn(e,t){let r=e.filter(i=>t.has(i.from)&&t.has(i.to)),s=i=>(t.get(i)?.y??0)+80/2,c=new Map,u=new Map;for(let i of r)c.set(i.from,[...c.get(i.from)??[],i]),u.set(i.to,[...u.get(i.to)??[],i]);for(let i of c.values())i.sort((f,x)=>s(f.to)-s(x.to));for(let i of u.values())i.sort((f,x)=>s(f.from)-s(x.from));return r.map(i=>{let f=t.get(i.from),x=t.get(i.to),w=c.get(i.from)??[],a=u.get(i.to)??[],b=f.x+232,g=f.y+tn(w.indexOf(i),w.length),A=x.x,z=x.y+tn(a.indexOf(i),a.length),oe=A>b?Math.max(32,(A-b)*.5):90,re=`M ${b} ${g} C ${b+oe} ${g}, ${A-oe} ${z}, ${A} ${z}`;return{...i,d:re,sx:b,sy:g,tx:A,ty:z}})}function zt(e,t,r){let s=new Set,c=[t];for(;c.length>0;){let u=c.pop();for(let i of e){let f=r==="down"?i.from===u?i.to:void 0:i.to===u?i.from:void 0;f!==void 0&&!s.has(f)&&f!==t&&(s.add(f),c.push(f))}}return s}function nn(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 jt(e){if(e)return e.includes("/")?e.slice(e.indexOf("/")+1):e}function rn(e){return e>=1e6?`${(e/1e6).toFixed(1)}M`:e>=1e3?`${(e/1e3).toFixed(e>=1e4?0:1)}k`:String(e)}var Nn={running:"running",queued:"queued",completed:"completed",failed:"failed",cancelled:"cancelled",idle:"idle"};function Ae(e,t){if(e.kind==="root")return e.rawStatus;let r=e.rawStatus===e.state?Nn[e.state]:e.rawStatus,s=e.startedAt;return s===void 0?r:e.state==="running"?`${r} \xB7 ${nn(t-s)}`:e.endedAt!==void 0?`${r} \xB7 ${nn(e.endedAt-s)}`:r}var Ze=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 s=t.clientX-r.x,c=t.clientY-r.y;if(!r.moved&&Math.hypot(s,c)<4)return;let u=!r.moved;return r.moved=!0,{x:r.vx+s,y:r.vy+c,started:u}}end(t){let r=this.drag;return!r||t!==void 0&&t!==r.id?!1:(this.drag=void 0,r.moved)}};var Pn=new Set(["running","queued","completed","failed","cancelled","idle"]),ye=e=>e!==null&&typeof e=="object"&&!Array.isArray(e),te=e=>typeof e=="number"&&Number.isFinite(e),ke=e=>e===void 0||typeof e=="string",he=e=>e===void 0||te(e),Dn=e=>typeof e=="string"&&Pn.has(e);function Hn(e){return ye(e)?typeof e.id=="string"&&(e.kind==="root"||e.kind==="task")&&typeof e.sessionId=="string"&&typeof e.title=="string"&&Dn(e.state)&&typeof e.rawStatus=="string"&&ke(e.agent)&&ke(e.model)&&he(e.createdAt)&&he(e.startedAt)&&he(e.endedAt)&&ke(e.summary)&&ke(e.error)&&he(e.tokens)&&he(e.costUsd)&&he(e.toolCalls)&&ke(e.parentId)&&te(e.column)&&te(e.wave):!1}function $n(e){return ye(e)&&typeof e.id=="string"&&typeof e.from=="string"&&typeof e.to=="string"&&(e.kind==="spawn"||e.kind==="uses")}function Fn(e){return ye(e)&&te(e.column)&&te(e.total)&&te(e.done)&&te(e.running)}function Xn(e){return ye(e)&&te(e.omittedNodes)&&Number.isInteger(e.omittedNodes)&&e.omittedNodes>=0}function Bn(e){return ye(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(Hn)&&Array.isArray(e.edges)&&e.edges.every($n)&&Array.isArray(e.columns)&&e.columns.every(Fn)&&te(e.models)&&(e.truncated===void 0||Xn(e.truncated))}function Vn(e){let t=JSON.parse(e);if(!Bn(t))throw new Error("service answered with an unexpected graph shape");return t}var et=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 s=await this.deps.fetch(t);if(r!==this.generation)return;if(s.status!==200)throw new Error(`service answered HTTP ${s.status}: ${s.body.slice(0,200)}`);let c=Vn(s.body);c.status!=="ok"||c.nodes.length<=1?(this.signature="",this.deps.show({kind:"empty"})):s.body!==this.signature&&(this.signature=s.body,this.deps.show({kind:"graph",graph:c}));let u=c.nodes.some(i=>i.state==="running"||i.state==="queued");this.deps.schedule(u?1500:5e3,()=>{this.refresh()})}catch(s){if(r!==this.generation)return;this.signature="",this.deps.show({kind:"error",error:s}),this.deps.schedule(1e4,()=>{this.refresh()})}finally{this.inFlight=!1,(this.pending||r!==this.generation)&&(this.pending=!1,this.refresh())}}};var sn="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 W=Ct(),P=e=>document.querySelector(e),h={app:P("#app"),title:P("#title"),titleDot:P("#title-dot"),meta:P("#meta"),viewport:P("#viewport"),world:P("#world"),edges:P("#edges"),bands:P("#bands"),nodes:P("#nodes"),empty:P("#empty"),inspector:P("#inspector"),settings:P("#settings")},ve=null,pn=!1,M,D,an="",Y,ie={},Kt,y={x:0,y:0,k:1},me=new Map;function k(e,t="",r=""){let s=document.createElement(e);return t&&(s.className=t),r&&(s.textContent=r),s}function Wt(e,t=""){h.empty.replaceChildren(k("strong","",e),...t?[k("p","",t)]:[]),h.empty.hidden=!1,h.world.hidden=!0,h.inspector.hidden=!0}function Qt(e){return e instanceof p?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 _e(){h.world.style.transform=`translate(${y.x}px, ${y.y}px) scale(${y.k})`,h.app.style.setProperty("--zoom",String(y.k))}function tt(){if(!D)return;let e=h.viewport.clientWidth,t=h.viewport.clientHeight,r=Math.min(1,Math.max(.62,Math.min((e-16)/D.width,(t-16)/D.height)));y.k=r,y.x=Math.round(D.width*r<=e?(e-D.width*r)/2:8),y.y=Math.round(Math.max(8,(t-D.height*r)/2)),_e()}function un(e){let t=e?D?.boxes.get(e):void 0;if(!t)return tt();y.k=Math.max(y.k,.8),y.x=Math.round(h.viewport.clientWidth/2-(t.x+232/2)*y.k),y.y=Math.round(h.viewport.clientHeight/2-(t.y+80/2)*y.k),_e()}function Re(e,t=h.viewport.clientWidth/2,r=h.viewport.clientHeight/2){let s=Math.min(2,Math.max(.2,y.k*e));y.x=t-(t-y.x)*s/y.k,y.y=r-(r-y.y)*s/y.k,y.k=s,_e()}var we=new Ze,Jt=!1;function Zt(e,t=!1){if(!we.active)return;let r=we.end(e);we.active||(r&&t&&(Jt=!0,setTimeout(()=>{Jt=!1},0)),h.app.classList.remove("is-panning"))}h.viewport.addEventListener("pointerdown",e=>we.down(e,y));window.addEventListener("pointermove",e=>{let t=we.move(e);if(t==="end")return Zt(e.pointerId);t&&(t.started&&(h.viewport.setPointerCapture?.(e.pointerId),h.app.classList.add("is-panning")),y.x=t.x,y.y=t.y,_e())});window.addEventListener("pointerup",e=>Zt(e.pointerId,!0));window.addEventListener("pointercancel",e=>Zt(e.pointerId));h.viewport.addEventListener("dragstart",e=>e.preventDefault());h.viewport.addEventListener("wheel",e=>{e.preventDefault();let t=h.viewport.getBoundingClientRect();e.ctrlKey||e.metaKey||Math.abs(e.deltaY)>Math.abs(e.deltaX)*2&&!e.shiftKey?Re(Math.exp(-e.deltaY*(e.ctrlKey?.01:.0015)),e.clientX-t.left,e.clientY-t.top):(y.x-=e.deltaX||(e.shiftKey?e.deltaY:0),y.y-=e.shiftKey?0:e.deltaY,_e())},{passive:!1});P("#btn-fit").addEventListener("click",tt);P("#btn-locate").addEventListener("click",()=>{let e=M?.nodes.find(t=>t.kind==="task"&&t.state==="running");un(M?.focusId!==M?.rootId?M?.focusId:e?.id??M?.rootId)});P("#btn-in").addEventListener("click",()=>Re(1.2));P("#btn-out").addEventListener("click",()=>Re(1/1.2));window.addEventListener("keydown",e=>{e.target instanceof HTMLInputElement||(e.key==="0"?tt():e.key==="+"||e.key==="="?Re(1.2):e.key==="-"&&Re(1/1.2))});function Oe(e){if(Y=e,!M)return;let t=M.edges,r=new Set(e?t.filter(i=>i.to===e).map(i=>i.from):[]),s=new Set(e?t.filter(i=>i.from===e).map(i=>i.to):[]),c=e?zt(t,e,"up"):new Set,u=e?zt(t,e,"down"):new Set;h.app.classList.toggle("has-hover",e!==void 0);for(let[i,f]of me)f.classList.toggle("is-hover",i===e),f.classList.toggle("is-input",r.has(i)),f.classList.toggle("is-output",s.has(i)),f.classList.toggle("is-reach",c.has(i)||u.has(i));for(let i of h.edges.querySelectorAll("path[data-edge]")){let f=i.dataset.from??"",x=i.dataset.to??"";i.classList.toggle("is-in",e!==void 0&&x===e),i.classList.toggle("is-out",e!==void 0&&f===e),i.classList.toggle("is-reach",e!==void 0&&(c.has(f)&&(c.has(x)||x===e)||u.has(x)&&(u.has(f)||f===e)))}zn()}function zn(){let e=M?.nodes.find(w=>w.id===(Y??(M?.focusId!==M?.rootId?M?.focusId:void 0)));if(!e||!M){h.inspector.hidden=!0;return}let t=M.edges.filter(w=>w.to===e.id).length,r=M.edges.filter(w=>w.from===e.id).length,s=[Ae(e,Date.now())];e.agent&&s.push(e.agent);let c=jt(e.model);c&&s.push(c),e.toolCalls!==void 0&&s.push(`${e.toolCalls} tools`),e.tokens!==void 0&&s.push(`${rn(e.tokens)} tok`),e.costUsd!==void 0&&s.push(`$${e.costUsd.toFixed(2)}`);let u=k("div","i-head");u.append(k("span",`dot s-${e.state}`),k("strong","",e.title));let i=k("div","i-flow");i.append(k("span","i-in",`\u2190 ${t} input${t===1?"":"s"}`),k("span","i-out",`${r} output${r===1?"":"s"} \u2192`));let f=[u,k("div","i-facts",s.join(" \xB7 ")),i],x=e.error??e.summary;x&&f.push(k("p",e.error?"i-text is-error":"i-text",x)),f.push(k("div","i-hint",e.kind==="root"?"Click to open the orchestrating session":"Click to open this sub-agent's session")),h.inspector.replaceChildren(...f),h.inspector.hidden=!1}function jn(e){let t=me.get(e.id);return t||(t=k("button","node"),t.type="button",t.dataset.id=e.id,t.append(k("div","n-head"),k("div","n-status"),k("div","n-meta"),k("div","n-sub")),t.querySelector(".n-head")?.append(k("span","dot"),k("span","n-title")),t.addEventListener("pointerenter",()=>Oe(e.id)),t.addEventListener("pointerleave",()=>{Y===e.id&&Oe(void 0)}),t.addEventListener("focus",()=>Oe(e.id)),t.addEventListener("blur",()=>{Y===e.id&&Oe(void 0)}),t.addEventListener("click",()=>{Jt||Yn(e.id)}),me.set(e.id,t),h.nodes.append(t)),t}function Kn(e,t,r){e.className=`node k-${t.kind} s-${t.state}${M?.focusId===t.id&&t.kind==="task"?" is-current":""}`,Y===t.id&&e.classList.add("is-hover"),e.setAttribute("aria-label",`${t.title}, ${Ae(t,r)}. Open session.`);let s=(c,u)=>{let i=e.querySelector(c);i&&i.textContent!==u&&(i.textContent=u)};s(".n-title",t.title),s(".n-status",Ae(t,r)),s(".n-meta",t.kind==="root"?`${M?.nodes.length?M.nodes.length-1:0} sub-agents`:[t.agent,jt(t.model)].filter(Boolean).join(" \xB7 ")),s(".n-sub",t.error??t.summary??""),e.querySelector(".dot")?.setAttribute("class",`dot s-${t.state}`)}function Wn(e){M=e,D=on(e),h.world.hidden=!1,h.empty.hidden=!0,h.world.style.width=`${D.width}px`,h.world.style.height=`${D.height}px`,h.edges.setAttribute("width",String(D.width)),h.edges.setAttribute("height",String(D.height)),h.edges.setAttribute("viewBox",`0 0 ${D.width} ${D.height}`);let t=new Map(e.nodes.map(a=>[a.id,a.state])),r=document.createDocumentFragment();for(let a of D.edges){let b=document.createElementNS(sn,"path");b.setAttribute("d",a.d),b.dataset.edge=a.id,b.dataset.from=a.from,b.dataset.to=a.to;let g=t.get(a.to)==="running"||t.get(a.to)==="queued";if(b.setAttribute("class",`edge k-${a.kind}${g?" is-live":""}`),b.setAttribute("marker-end","url(#arrow)"),r.append(b),g){let A=document.createElementNS(sn,"path");A.setAttribute("d",a.d),A.setAttribute("class","flow"),A.setAttribute("pathLength","1"),r.append(A)}}h.edges.querySelectorAll("path.edge, path.flow").forEach(a=>a.remove()),h.edges.append(r),h.bands.replaceChildren(...[...D.columnX].map(([a,b])=>{let g=k("div","band");g.style.left=`${b}px`,g.style.width=`${232}px`;let A=e.columns.find(z=>z.column===a);return a===0?g.textContent="Orchestrator":A&&(g.textContent=`Wave ${a} \xB7 ${A.done}/${A.total} done${A.running?` \xB7 ${A.running} running`:""}`),A?.running&&g.classList.add("is-live"),g}));let s=Date.now(),c=new Set;for(let a of e.nodes){let b=jn(a),g=D.boxes.get(a.id);g&&(b.style.transform=`translate(${g.x}px, ${g.y}px)`),Kn(b,a,s),c.add(a.id)}for(let[a,b]of me)c.has(a)||(b.remove(),me.delete(a));let u=e.nodes.filter(a=>a.kind==="task"),i=u.filter(a=>a.state==="completed"||a.state==="failed"||a.state==="cancelled").length,f=u.filter(a=>a.state==="running").length,x=e.columns.length,w=e.columns.find(a=>a.running>0||a.done<a.total)?.column;h.title.textContent=e.title,h.titleDot.className=`dot s-${f>0?"running":u.some(a=>a.state==="failed")?"failed":i===u.length?"completed":"idle"}`,h.meta.textContent=[w!==void 0?`wave ${w}/${x}`:`${x} wave${x===1?"":"s"}`,`${i}/${u.length} done`,...f?[`${f} running`]:[],...e.models?[`${e.models} model${e.models===1?"":"s"}`]:[],...e.truncated?[`${e.truncated.omittedNodes} omitted`]:[]].join(" \xB7 "),W.setBadge(f>0?f:null).catch(()=>{}),an!==e.rootId&&(an=e.rootId,requestAnimationFrame(()=>e.focusId!==e.rootId?un(e.focusId):tt())),Y&&!e.nodes.some(a=>a.id===Y)&&(Y=void 0),Oe(Y)}function Jn(){if(!M)return;let e=Date.now();for(let t of M.nodes){if(t.state!=="running")continue;let s=me.get(t.id)?.querySelector(".n-status");s&&(s.textContent=Ae(t,e))}}setInterval(Jn,1e3);async function Yn(e){let t=M?.nodes.find(r=>r.id===e);if(t)try{await W.openSession(t.sessionId)}catch(r){let[s,c]=Qt(r);await W.toast({kind:"error",message:`${s}: ${c}`}).catch(()=>{})}}var Le=new et({fetch:e=>{let t={session:e};return ie.agentDir&&(t.agentDir=ie.agentDir),ie.stateDir&&(t.stateDir=ie.stateDir),W.serviceRequest({method:"GET",path:"/graph",query:t})},show:e=>{if(e.kind==="graph"){Wn(e.graph);return}M=void 0,W.setBadge(null).catch(()=>{}),e.kind==="no-session"?Wt("No session open","Open a chat to see the OmO agents working behind it."):e.kind==="empty"?Wt("No sub-agents yet","When this session launches OmO tasks or workflows, they appear here as a live graph."):Wt(...Qt(e.error))},schedule:(e,t)=>{Kt&&clearTimeout(Kt),Kt=setTimeout(t,e)},isHidden:()=>document.hidden});function qn(e){return e.state==="ready"?`antechamber ${e.antechamber}${e.omo?` with OmO ${e.omo}`:""} is installed.`:e.state==="installing"?`Installing antechamber ${e.spec} and its OmO with Bun\u2026`:e.state==="failed"?`Install failed: ${e.error??"unknown error"}`:`antechamber ${e.spec} is not installed yet.`}async function Yt(e=!1){let t=P("#runtime");try{let r=await W.serviceRequest({method:e?"POST":"GET",path:e?"/runtime/install":"/runtime"}),s=JSON.parse(r.body);t.dataset.state=s.state;let c=k("button","",s.state==="failed"?"Retry install":"Install now");c.type="button",c.addEventListener("click",()=>{Yt(!0)});let u=[k("strong","","Runtime"),k("span","",qn(s)),k("span","","OpenCode CLI path for Settings \u2192 OpenCode CLI:"),k("code","",s.launcher)];if(s.state==="missing"||s.state==="failed"){let i=k("div","row");i.append(c),u.push(i)}t.replaceChildren(...u),s.state==="installing"&&setTimeout(()=>{Yt()},2e3)}catch(r){t.dataset.state="failed",t.replaceChildren(k("strong","","Runtime"),k("span","",Qt(r).join(": ")))}}var cn=P("#btn-settings");cn.addEventListener("click",()=>{h.settings.hidden=!h.settings.hidden,cn.setAttribute("aria-expanded",String(!h.settings.hidden)),h.settings.hidden||(Yt(),h.settings.querySelector("input")?.focus())});P("#btn-save").addEventListener("click",()=>{let e=new FormData(h.settings),t={},r=String(e.get("agentDir")??"").trim(),s=String(e.get("stateDir")??"").trim();r&&(t.agentDir=r),s&&(t.stateDir=s),ie=t,h.settings.hidden=!0,W.storage.set("paths",t).catch(()=>{}),Le.invalidate()});function Qn(){for(let e of["agentDir","stateDir"]){let t=h.settings.querySelector(`input[name="${e}"]`);t&&(t.value=ie[e]??"")}}var dn=!1;W.onReady(e=>{Ut(e,document.documentElement),h.app.dataset.surface=e.surface,!dn&&(dn=!0,ve=e.session?.id??ve,W.storage.get("paths").then(t=>{if(t&&typeof t=="object"&&!Array.isArray(t)){let r=t;ie={...typeof r.agentDir=="string"?{agentDir:r.agentDir}:{},...typeof r.stateDir=="string"?{stateDir:r.stateDir}:{}}}Qn()}).catch(()=>{}).finally(()=>{pn=!0,Le.setSession(ve)}))});W.onSession(e=>{let t=e?.id??null;t!==ve&&(Y=void 0),ve=t,pn&&Le.setSession(t)});W.onSessionLifecycle(()=>{Le.refresh()});document.addEventListener("visibilitychange",()=>{document.hidden||Le.refresh()});window.addEventListener("resize",()=>{D&&y.k<=1&&_e()});})();
@@ -0,0 +1,201 @@
1
+ // extensions/antechamber/src/runtime/launcher.ts
2
+ import { readFileSync as readFileSync2 } from "node:fs";
3
+ import { dirname, join as join2, resolve as resolve2 } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+
6
+ // extensions/antechamber/src/runtime/runtime.ts
7
+ import { spawn } from "node:child_process";
8
+ import { createHash } from "node:crypto";
9
+ import { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
10
+ import { homedir } from "node:os";
11
+ import { delimiter, isAbsolute, join, resolve } from "node:path";
12
+ var STALE_LOCK_MS = 15 * 6e4;
13
+ var INSTALL_TIMEOUT_MS = 10 * 6e4;
14
+ var READY = ".ready.json";
15
+ var ERROR_TAIL_CHARS = 2e3;
16
+ function defaultEnv() {
17
+ return { env: process.env, home: homedir() };
18
+ }
19
+ function runtimeRoot({ env, home }) {
20
+ const configured = env.ANTECHAMBER_RUNTIME_DIR?.trim();
21
+ return configured ? resolve(configured) : join(home, ".antechamber", "runtime");
22
+ }
23
+ function runtimePaths(version, runtime) {
24
+ const root = runtimeRoot(runtime);
25
+ const override = runtime.env.ANTECHAMBER_RUNTIME_SPEC?.trim();
26
+ if (!override) return { root, spec: version, key: version, dir: join(root, version) };
27
+ const spec = isAbsolute(override) ? override : resolve(override);
28
+ const stamp = existsSync(spec) ? `${statSync(spec).mtimeMs}:${statSync(spec).size}` : "";
29
+ const key = `local-${createHash("sha256").update(`${spec}
30
+ ${stamp}`).digest("hex").slice(0, 12)}`;
31
+ return { root, spec: `file:${spec}`, key, dir: join(root, key) };
32
+ }
33
+ function findBun({ env, home }, exists = existsSync) {
34
+ for (const dir of (env.PATH ?? "").split(delimiter)) {
35
+ if (dir && exists(join(dir, "bun"))) return join(dir, "bun");
36
+ }
37
+ for (const candidate of [
38
+ join(env.BUN_INSTALL ?? join(home, ".bun"), "bin", "bun"),
39
+ join(home, ".bun", "bin", "bun")
40
+ ]) {
41
+ if (exists(candidate)) return candidate;
42
+ }
43
+ return void 0;
44
+ }
45
+ function readJson(path) {
46
+ try {
47
+ const value = JSON.parse(readFileSync(path, "utf8"));
48
+ return typeof value === "object" && value !== null ? value : void 0;
49
+ } catch {
50
+ return void 0;
51
+ }
52
+ }
53
+ function installed(dir) {
54
+ if (!existsSync(join(dir, READY))) return void 0;
55
+ const cli = join(dir, "node_modules", "antechamber", "dist", "cli.js");
56
+ const antechamber = readJson(join(dir, "node_modules", "antechamber", "package.json"))?.version;
57
+ if (!existsSync(cli) || typeof antechamber !== "string") return void 0;
58
+ const omo = readJson(join(dir, "node_modules", "omo-ai", "package.json"))?.version;
59
+ return { dir, cli, antechamber, omo: typeof omo === "string" ? omo : void 0 };
60
+ }
61
+ function lockHeld(lock, deps) {
62
+ let mtime;
63
+ try {
64
+ mtime = statSync(lock).mtimeMs;
65
+ } catch {
66
+ return false;
67
+ }
68
+ const pid = Number.parseInt(readFileSync(join(lock, "pid"), { encoding: "utf8", flag: "a+" }), 10);
69
+ if (deps.now() - mtime > STALE_LOCK_MS) return false;
70
+ return !Number.isInteger(pid) || deps.pidAlive(pid);
71
+ }
72
+ function tryLock(lock, deps) {
73
+ try {
74
+ mkdirSync(lock);
75
+ } catch (error) {
76
+ if (error.code !== "EEXIST") throw error;
77
+ if (lockHeld(lock, deps)) return false;
78
+ rmSync(lock, { recursive: true, force: true });
79
+ return tryLock(lock, deps);
80
+ }
81
+ writeFileSync(join(lock, "pid"), String(process.pid));
82
+ return true;
83
+ }
84
+ function prune(paths) {
85
+ const others = readdirSync(paths.root, { withFileTypes: true }).filter((entry) => entry.isDirectory() && entry.name !== paths.key && !/\.(lock|tmp-.*)$/.test(entry.name)).map((entry) => join(paths.root, entry.name)).filter((dir) => existsSync(join(dir, READY)) && !existsSync(`${dir}.lock`)).map((dir) => ({ dir, at: Number(readJson(join(dir, READY))?.installedAt ?? 0) })).sort((a, b) => b.at - a.at);
86
+ for (const { dir } of others.slice(1)) rmSync(dir, { recursive: true, force: true });
87
+ }
88
+ async function installOnce(paths, bun, deps) {
89
+ const staging = `${paths.dir}.tmp-${process.pid}-${deps.now()}`;
90
+ mkdirSync(staging, { recursive: true });
91
+ try {
92
+ const manifest = {
93
+ name: "antechamber-runtime",
94
+ private: true,
95
+ dependencies: { antechamber: paths.spec },
96
+ // omo-ai's postinstall prepares its engine; Bun skips dependency scripts unless trusted.
97
+ trustedDependencies: ["omo-ai"]
98
+ };
99
+ writeFileSync(join(staging, "package.json"), `${JSON.stringify(manifest, null, 2)}
100
+ `);
101
+ await deps.install(bun, staging);
102
+ writeFileSync(join(staging, READY), `${JSON.stringify({ spec: paths.spec, installedAt: deps.now() })}
103
+ `);
104
+ if (!installed(staging)) throw new Error(`bun install did not produce node_modules/antechamber/dist/cli.js`);
105
+ rmSync(paths.dir, { recursive: true, force: true });
106
+ renameSync(staging, paths.dir);
107
+ } catch (error) {
108
+ rmSync(staging, { recursive: true, force: true });
109
+ throw error;
110
+ }
111
+ const runtime = installed(paths.dir);
112
+ if (!runtime) throw new Error(`runtime vanished from ${paths.dir}`);
113
+ return runtime;
114
+ }
115
+ async function ensureRuntime(paths, bun, deps = defaultDeps()) {
116
+ const lock = `${paths.dir}.lock`;
117
+ for (; ; ) {
118
+ const ready = installed(paths.dir);
119
+ if (ready) return ready;
120
+ if (!bun) throw new Error("bun not found on PATH or in ~/.bun/bin; install it from https://bun.sh");
121
+ mkdirSync(paths.root, { recursive: true });
122
+ if (!tryLock(lock, deps)) {
123
+ await deps.pause();
124
+ continue;
125
+ }
126
+ try {
127
+ const raced = installed(paths.dir);
128
+ if (raced) return raced;
129
+ const runtime = await installOnce(paths, bun, deps);
130
+ rmSync(`${paths.dir}.error`, { force: true });
131
+ prune(paths);
132
+ return runtime;
133
+ } catch (error) {
134
+ const message = error instanceof Error ? error.message : String(error);
135
+ writeFileSync(`${paths.dir}.error`, message.slice(-ERROR_TAIL_CHARS));
136
+ throw error;
137
+ } finally {
138
+ rmSync(lock, { recursive: true, force: true });
139
+ }
140
+ }
141
+ }
142
+ function bunInstall(bun, cwd) {
143
+ return new Promise((resolvePromise, reject) => {
144
+ const child = spawn(bun, ["install", "--production", "--no-progress"], {
145
+ cwd,
146
+ env: process.env,
147
+ stdio: ["ignore", "pipe", "pipe"]
148
+ });
149
+ let output = "";
150
+ const keep = (chunk) => {
151
+ output = (output + chunk.toString("utf8")).slice(-ERROR_TAIL_CHARS);
152
+ };
153
+ child.stdout.on("data", keep);
154
+ child.stderr.on("data", keep);
155
+ const timer = setTimeout(() => child.kill("SIGTERM"), INSTALL_TIMEOUT_MS);
156
+ child.on("error", (error) => {
157
+ clearTimeout(timer);
158
+ reject(error);
159
+ });
160
+ child.on("close", (code, signal) => {
161
+ clearTimeout(timer);
162
+ if (code === 0) resolvePromise();
163
+ else reject(new Error(`bun install failed (${signal ?? `exit ${code}`}): ${output.trim()}`));
164
+ });
165
+ });
166
+ }
167
+ function defaultDeps() {
168
+ return {
169
+ install: bunInstall,
170
+ pause: () => new Promise((done) => setTimeout(done, 500)),
171
+ now: Date.now,
172
+ pidAlive: (pid) => {
173
+ try {
174
+ process.kill(pid, 0);
175
+ return true;
176
+ } catch (error) {
177
+ return error.code === "EPERM";
178
+ }
179
+ }
180
+ };
181
+ }
182
+
183
+ // extensions/antechamber/src/runtime/launcher.ts
184
+ var extensionDir = resolve2(dirname(fileURLToPath(import.meta.url)), "..");
185
+ var command = process.argv[2];
186
+ if (command === "version") {
187
+ console.log(`opencode v${"2.999.0"}`);
188
+ } else if (command === "resolve") {
189
+ const { version } = JSON.parse(readFileSync2(join2(extensionDir, "package.json"), "utf8"));
190
+ const env = defaultEnv();
191
+ try {
192
+ const runtime = await ensureRuntime(runtimePaths(version, env), findBun(env) ?? process.execPath);
193
+ console.log(runtime.cli);
194
+ } catch (error) {
195
+ console.error(`opencode-antechamber: ${error instanceof Error ? error.message : String(error)}`);
196
+ process.exit(1);
197
+ }
198
+ } else {
199
+ console.error(`opencode-antechamber: unknown launcher command '${command ?? ""}'`);
200
+ process.exit(2);
201
+ }