antechamber 0.2.6 → 0.2.7
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,6 +7,15 @@ and this project uses [Semantic Versioning](https://semver.org/).
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.2.7] - 2026-10-15
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- OmO Graph: panning no longer selects the wave labels, so pressing near the
|
|
15
|
+
graph can no longer start a native text drag. That drag cancelled the pan
|
|
16
|
+
after a few pixels, and before 0.2.3 it left the graph following the mouse
|
|
17
|
+
with the button released.
|
|
18
|
+
|
|
10
19
|
## [0.2.6] - 2026-10-15
|
|
11
20
|
|
|
12
21
|
- fix(omo-graph): stop ending the pan on blur and lost capture
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
#settings button { padding: 5px 12px; border-radius: 6px; border: 1px solid var(--border); background: var(--surface-2); cursor: pointer; }
|
|
53
53
|
#settings #btn-save { background: var(--accent); color: var(--oc-primary-fg, #001); border-color: transparent; }
|
|
54
54
|
|
|
55
|
-
#viewport { position: relative; flex: 1; overflow: hidden; cursor: grab; touch-action: none;
|
|
55
|
+
#viewport { position: relative; flex: 1; overflow: hidden; cursor: grab; touch-action: none; -webkit-user-select: none; user-select: none;
|
|
56
56
|
background-image: radial-gradient(color-mix(in srgb, var(--muted) 22%, transparent) 1px, transparent 1px);
|
|
57
57
|
background-size: 18px 18px; }
|
|
58
58
|
.is-panning #viewport { cursor: grabbing; }
|
|
@@ -109,6 +109,7 @@
|
|
|
109
109
|
@keyframes pulse { 0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--run) 60%, transparent); } 50% { box-shadow: 0 0 0 4px transparent; } }
|
|
110
110
|
|
|
111
111
|
#empty { position: absolute; inset: 0; display: grid; place-content: center; text-align: center; gap: 6px; padding: 24px; color: var(--muted); }
|
|
112
|
+
#empty { -webkit-user-select: text; user-select: text; cursor: auto; }
|
|
112
113
|
#empty strong { color: var(--fg); font-size: 14px; }
|
|
113
114
|
#empty p { margin: 0; max-width: 34ch; font-size: 12px; }
|
|
114
115
|
|
|
@@ -173,4 +173,4 @@ textarea.oc-sdk-input { height: auto; padding: 8px 12px; resize: vertical; }
|
|
|
173
173
|
.oc-sdk-text { white-space: pre-wrap; overflow-wrap: anywhere; }
|
|
174
174
|
.oc-sdk-text a { color: ${lt}; 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 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 mt(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 ht(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 Ue=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 De=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=it(),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={},gt,_={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 Et(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 He(){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 He();_.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 Ue,xt=!1;function bt(e,t=!1){if(!Ee.active)return;let r=Ee.end(e);Ee.active||(r&&t&&(xt=!0,setTimeout(()=>{xt=!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 bt(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=>bt(e.pointerId,!0));window.addEventListener("pointercancel",e=>bt(e.pointerId));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",He);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"?He():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?mt(t,e,"up"):new Set,p=e?mt(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=ht(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",()=>{xt||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,ht(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):He())),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 ke=new De({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"?Et("No session open","Open a chat to see the OmO agents working behind it."):e.kind==="empty"?Et("No sub-agents yet","When this session launches OmO tasks or workflows, they appear here as a live graph."):Et(...ro(e.error))},schedule:(e,t)=>{gt&&clearTimeout(gt),gt=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(()=>{}),ke.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=>{at(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,ke.setSession(ge)}))});V.onSession(e=>{let t=e?.id??null;t!==ge&&(K=void 0),ge=t,no&&ke.setSession(t)});V.onSessionLifecycle(()=>{ke.refresh()});document.addEventListener("visibilitychange",()=>{document.hidden||ke.refresh()});window.addEventListener("resize",()=>{R&&_.k<=1&&de()});})();
|
|
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 mt(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 ht(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 Ue=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 De=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=it(),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={},gt,_={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 Et(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 He(){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 He();_.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 Ue,xt=!1;function bt(e,t=!1){if(!Ee.active)return;let r=Ee.end(e);Ee.active||(r&&t&&(xt=!0,setTimeout(()=>{xt=!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 bt(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=>bt(e.pointerId,!0));window.addEventListener("pointercancel",e=>bt(e.pointerId));d.viewport.addEventListener("dragstart",e=>e.preventDefault());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",He);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"?He():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?mt(t,e,"up"):new Set,p=e?mt(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=ht(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",()=>{xt||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,ht(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):He())),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 ke=new De({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"?Et("No session open","Open a chat to see the OmO agents working behind it."):e.kind==="empty"?Et("No sub-agents yet","When this session launches OmO tasks or workflows, they appear here as a live graph."):Et(...ro(e.error))},schedule:(e,t)=>{gt&&clearTimeout(gt),gt=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(()=>{}),ke.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=>{at(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,ke.setSession(ge)}))});V.onSession(e=>{let t=e?.id??null;t!==ge&&(K=void 0),ge=t,no&&ke.setSession(t)});V.onSessionLifecycle(()=>{ke.refresh()});document.addEventListener("visibilitychange",()=>{document.hidden||ke.refresh()});window.addEventListener("resize",()=>{R&&_.k<=1&&de()});})();
|