@sapiom/harness 0.8.1 → 0.8.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # @sapiom/harness
2
2
 
3
+ ## 0.8.3
4
+
5
+ ### Patch Changes
6
+
7
+ - 5a8eeea: `DEFAULT_SYSTEM_PROMPT` gains a compact "Calling LLMs from agent code"
8
+ section — the same LLM call-surface rule taught in the MCP instructions and
9
+ the `sapiom-agent-authoring` skill, kept to ~8 lines since the prompt is
10
+ injected fresh into every Studio session's context. Also corrects the
11
+ adjacent "sapiom (remote, HTTP)" bullet's vague "models" capability mention
12
+ to point at the new section.
13
+ - Updated dependencies [00b8814]
14
+ - Updated dependencies [5a8eeea]
15
+ - Updated dependencies [5a8eeea]
16
+ - @sapiom/agent-core@0.12.0
17
+ - @sapiom/mcp@0.12.8
18
+ - @sapiom/agent@0.10.1
19
+
20
+ ## 0.8.2
21
+
22
+ ### Patch Changes
23
+
24
+ - Updated dependencies [af764cd]
25
+ - @sapiom/agent@0.10.0
26
+ - @sapiom/agent-core@0.11.4
27
+ - @sapiom/mcp@0.12.7
28
+
3
29
  ## 0.8.1
4
30
 
5
31
  ### Patch Changes
@@ -1 +1 @@
1
- {"version":3,"file":"default.d.ts","sourceRoot":"","sources":["../../src/profiles/default.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,QAkE1B,CAAC"}
1
+ {"version":3,"file":"default.d.ts","sourceRoot":"","sources":["../../src/profiles/default.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,QA6E1B,CAAC"}
@@ -14,14 +14,25 @@ active for the whole session. Follow them.
14
14
  **The two MCPs, and when to use each:**
15
15
  - **sapiom** (remote, HTTP) — the paid capability surface an agent calls at
16
16
  *runtime* from inside a deployed agent's step code (ctx.sapiom.*):
17
- repositories, sandboxes, models, and so on. You don't call this directly
18
- while authoring.
17
+ repositories, sandboxes, LLM calls (see below), and so on. You don't call
18
+ this directly while authoring.
19
19
  - **sapiom-dev** (local, stdio) — the developer surface for this session. Its
20
20
  scaffold, check, and Local Run path uses no Sapiom capability spend; Deploy
21
21
  and Prod Run are authenticated cloud operations. Use its sapiom_dev_agents_*
22
22
  tools to author and ship agents, and sapiom_authenticate / sapiom_status if
23
23
  you need to sign in.
24
24
 
25
+ **Calling LLMs from agent code:** one-shot call → \`ctx.sapiom.llm.run\`; a
26
+ platform-driven multi-turn loop → \`ctx.sapiom.models.run\` (never for a
27
+ one-shot — it overthinks); dispatching a deployed agent by slug →
28
+ \`ctx.sapiom.agents.run\`. Structured output = tool-use/schema output — read
29
+ the \`tool_use\` block's input, never string-parse; a plain-text reply reads
30
+ only \`type === 'text'\` blocks. Omit \`model\`
31
+ (recommended) or pin the \`smart\` label; raw provider ids are never
32
+ honored. Results disclose the served class + lane. Debugging a run: the
33
+ Run Inspector, or the per-step I/O endpoint documented in the guide.
34
+ Guide: https://docs.sapiom.ai/guides/choose-a-call-surface.
35
+
25
36
  **When something about Sapiom is wrong, send it upstream.** If the user hits a
26
37
  bug, calls something confusing or broken, or wishes it worked differently,
27
38
  offer to pass it on — sapiom_send_feedback puts their words in front of the
@@ -1 +1 @@
1
- {"version":3,"file":"default.js","sourceRoot":"","sources":["../../src/profiles/default.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkEpC,CAAC,IAAI,EAAE,CAAC"}
1
+ {"version":3,"file":"default.js","sourceRoot":"","sources":["../../src/profiles/default.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6EpC,CAAC,IAAI,EAAE,CAAC"}
@@ -491,4 +491,4 @@ ${o}`:o}function $m(e){return Zl(e)}async function C$(e,t,i){const r=$m(e.trim()
491
491
  `)}const $6={entries:[],index:-1};function L6(e,t){return e.kind!==t.kind?!1:e.kind==="session"&&t.kind==="session"?e.sessionId===t.sessionId:e.kind==="agent"&&t.kind==="agent"?e.agentPath===t.agentPath:e.kind==="review"&&t.kind==="review"?e.summary.agentSessionId===t.summary.agentSessionId:e.kind===t.kind}function O2(e){return e.index>0}function $2(e){return e.index>=0&&e.index<e.entries.length-1}function I6(e,t){const i=e.index>=0?e.entries[e.index]:null;if(i&&L6(i,t)){if(JSON.stringify(i)===JSON.stringify(t))return e;const c=[...e.entries];return c[e.index]=t,{...e,entries:c}}const o=[...e.entries.slice(0,e.index+1),t].slice(-50);return{entries:o,index:o.length-1}}function P6(e,t){if(!(t==="back"?O2(e):$2(e)))return{state:e,visit:null};const r=t==="back"?e.index-1:e.index+1;return{state:{...e,index:r},visit:e.entries[r]??null}}function B6(){const[e,t]=z.useState($6),i=z.useRef(e);i.current=e;const r=z.useCallback(c=>{const f=I6(i.current,c);f!==i.current&&(i.current=f,t(f))},[]),o=z.useCallback(c=>{const f=P6(i.current,c);return f.visit?(i.current=f.state,t(f.state),f.visit):null},[]);return{canGoBack:O2(e),canGoForward:$2(e),record:r,goBack:()=>o("back"),goForward:()=>o("forward")}}const L2="(max-width: 768px)";function Iv(){return typeof window<"u"&&window.matchMedia(L2).matches}function H6(e){const t=window.matchMedia(L2);return t.addEventListener("change",e),()=>t.removeEventListener("change",e)}function z6(){return z.useSyncExternalStore(H6,Iv,()=>!1)}const I2="sapiom-harness-pane-widths",Eg=180,P2=480,Pv=320,ec=320,B2=720;function Bv(e,t,i){return Math.min(Math.max(e,t),i)}function U6(){const e={rail:Pv,canvas:null};if(typeof window>"u")return e;try{const t=window.localStorage.getItem(I2);if(!t)return e;const i=JSON.parse(t);return{rail:Bv(typeof i.rail=="number"?i.rail:Pv,Eg,P2),canvas:typeof i.canvas=="number"?Bv(i.canvas,ec,B2):null}}catch{return e}}function Hw(e){window.localStorage.setItem(I2,JSON.stringify(e))}function q6(){const[e,t]=z.useState(U6),[i,r]=z.useState(!1),[o,c]=z.useState(!1),f=(d,m,y,v,S,w)=>R=>{const x=R.currentTarget;x.setPointerCapture(R.pointerId),w==null||w(!0);const g=R.clientX,b=S(),p=k=>{const A=Bv(b+(k.clientX-g)*m,y,v);t(C=>C[d]===A?C:{...C,[d]:A})},_=()=>{x.removeEventListener("pointermove",p),x.removeEventListener("pointerup",_),w==null||w(!1),t(k=>(Hw(k),k))};x.addEventListener("pointermove",p),x.addEventListener("pointerup",_)},l=(d,m)=>{t(y=>{const v={...y,[d]:m};return Hw(v),v})};return{widths:e,canvasResizing:i,railResizing:o,startRailDrag:f("rail",1,Eg,P2,()=>e.rail,c),startCanvasDrag:f("canvas",-1,ec,B2,()=>{if(e.canvas!=null)return e.canvas;const d=document.querySelector(".canvas-pane");return d?d.getBoundingClientRect().width:ec},r),resetRail:()=>{c(!0),l("rail",Pv),window.setTimeout(()=>c(!1),0)},resetCanvas:()=>{r(!0),l("canvas",null),window.setTimeout(()=>r(!1),0)}}}function Fs(e,t="error"){return{message:e,tone:t}}const F6=2e3;function V6(e){const t=new URL("/ws/events",window.location.href);t.protocol=t.protocol==="https:"?"wss:":"ws:",t.searchParams.set("token",lo());let i=null,r=null,o=!1;const c=()=>{i=new WebSocket(t),i.addEventListener("message",f=>{try{e(JSON.parse(f.data))}catch{}}),i.addEventListener("close",()=>{o||(r=setTimeout(c,F6))})};return c(),()=>{o=!0,r&&clearTimeout(r),i==null||i.close()}}function jd(e){const t=e.split(/[\\/]/).filter(Boolean);return t[t.length-1]??e}function W6(e,t){const i=[];for(const r of t)e.has(r.path)||i.push(r.path);return i}function zw(e,t){return t?"exception":e==="linking"?"link_failed":"build_failed"}function G6(e){return e==="cancelled"?"cancelled":"failed"}function K6(e){return e==="completed"?"succeeded":e==="failed"?"failed":"pending"}const Y6=5;function X6(){return{started:!1,settled:!1,observed:!1,failures:0}}const Rd={event:null};function J6(e,t,i=Y6){if(t.kind==="announced")return t.duplicate||e.started?{state:e,emit:Rd}:{state:{...e,started:!0},emit:{event:"agent.run_started"}};if(t.kind==="polled"){const c={...e,observed:!0,failures:0};if(t.status==="running")return{state:c,emit:Rd};if(e.settled)return{state:c,emit:Rd};const f={...c,settled:!0};return t.status==="completed"?{state:f,emit:{event:"agent.run_succeeded"}}:{state:f,emit:{event:"agent.run_failed",error_kind:G6(t.status)}}}const r=e.failures+1,o={...e,failures:r};return r<i||e.settled?{state:o,emit:Rd}:{state:{...o,settled:!0},emit:{event:"agent.run_failed",error_kind:e.observed?"exception":"unobservable"}}}function Fl(e){return typeof e=="string"&&e!==""?e:void 0}function Z6(e){if(Fl(e.templateId))return"template";const t=Fl(e.starterId);return t&&t!=="default"?"starter":Fl(e.forkId)?"fork":"scratch"}function Uw(e){if(!e)return{};const t=Z6(e);return t==="template"?{source:t,template_id:Fl(e.templateId)}:t==="starter"?{source:t,template_id:Fl(e.starterId)}:{source:t}}const qw=4e3;function Q6(e){if(typeof e=="string")return e;if(e!==null&&typeof e=="object"){const t=e,i=[t.ts,t.level,t.msg??t.message].filter(r=>typeof r=="string"||typeof r=="number");if(i.length>0)return i.map(String).join(" ")}return String(e)}function eL(e){if(!Array.isArray(e)||e.length===0)return;const t=e.map(Q6).join(`
492
492
  `).trim();if(t!=="")return t.length>qw?t.slice(t.length-qw):t}function tL(e){return e==="running"?"running":e==="succeeded"?"passed":e==="threw"?"failed":"pending"}function sL(e){return e==="completed"?"completed":e==="failed"?"failed":"running"}function iL(e){var r;const t={id:`${e.step}-${e.attempt}`,name:e.step,attempt:e.attempt,status:tL(e.status)};if(e.startedAt&&(t.startedAt=e.startedAt),e.finishedAt&&(t.finishedAt=e.finishedAt),e.startedAt&&e.finishedAt){const o=Date.parse(e.startedAt),c=Date.parse(e.finishedAt);Number.isFinite(o)&&Number.isFinite(c)&&c>=o&&(t.latencyMs=c-o)}e.input!==void 0&&(t.input=e.input),e.output!==void 0&&(t.output=e.output),e.sharedStateAfter!==void 0&&(t.sharedState=e.sharedStateAfter),e.directive!==void 0&&(t.directive=e.directive),(r=e.error)!=null&&r.message&&(t.error=e.error.message);const i=eL(e.logs);return i!==void 0&&(t.logSlice=i),e.calls&&e.calls.length>0&&(t.calls=e.calls.map(o=>({capability:o.capability,stubUsed:o.stubUsed,args:o.args,result:o.result}))),t}function nL(e,t={}){const i={executionId:t.executionId??"",status:sL(t.outcome),steps:e.map(iL),stubbed:!0};return t.unusedStubs&&t.unusedStubs.length>0&&(i.unusedStubs=t.unusedStubs),t.stubWarnings&&t.stubWarnings.length>0&&(i.stubWarnings=t.stubWarnings),t.input!==void 0&&(i.input=t.input),t.output!==void 0&&(i.output=t.output),t.error!==void 0&&(i.error=t.error),t.startedAt&&(i.startedAt=t.startedAt),t.finishedAt&&(i.finishedAt=t.finishedAt),i}const It=Kw(),rL=3e3,aL=8,oL=500;function lL(){const[e,t]=z.useState(null),[i,r]=z.useState(null),o=z.useRef(null);o.current=i;const c=z.useRef([]);c.current=(e==null?void 0:e.workflows)??[];const[f,l]=z.useState(!0),[d,m]=z.useState(null),[y,v]=z.useState(null),[S,w]=z.useState(0),[R,x]=z.useState(null),[g,b]=z.useState(null),[p,_]=z.useState([]),[k,A]=z.useState(null),[C,T]=z.useState(!1),j=z.useRef(new Map),M=z.useRef(0),$=z.useRef(new Map),[B,q]=z.useState(null),[F,J]=z.useState(new Set),[te,W]=z.useState([]),ie=z.useRef(new Map),[Q,H]=z.useState(new Map),[I,D]=z.useState(new Map),[P,U]=z.useState(new Map),L=z.useRef(new Map),G=z.useRef(new Set),[se,Y]=z.useState(new Map),[V,le]=z.useState(new Map),[ae,X]=z.useState(new Map),Z=z.useCallback((oe,de)=>{X(be=>{if(de===null){if(!be.has(oe))return be;const xe=new Map(be);return xe.delete(oe),xe}return new Map(be).set(oe,de)})},[]),[ue,Se]=z.useState([]),Re=z.useCallback(oe=>{Se(de=>de.some(be=>be.cwd===oe)?de:[{cwd:oe,sessionSeen:!1},...de])},[]),Le=z.useCallback(oe=>{Se(de=>de.some(be=>be.cwd===oe)?de.filter(be=>be.cwd!==oe):de)},[]);z.useEffect(()=>{if(ue.length===0)return;const oe=(e==null?void 0:e.sessions)??[],de=(e==null?void 0:e.workflows)??[],be=(xe,Oe)=>hg(Oe,xe);Se(xe=>{let Oe=!1;const ct=[];for(const jt of xe){if(de.some(Tt=>be(Tt.path,jt.cwd))){Oe=!0;continue}const Ht=oe.some(Tt=>Tt.status!=="exited"&&be(Tt.cwd,jt.cwd));if(jt.sessionSeen&&!Ht){Oe=!0;continue}if(Ht&&!jt.sessionSeen){ct.push({...jt,sessionSeen:!0}),Oe=!0;continue}ct.push(jt)}return Oe?ct:xe})},[e==null?void 0:e.sessions,e==null?void 0:e.workflows,ue]);const[$e,lt]=z.useState(0),Ee=z.useCallback(()=>{lt(oe=>oe+1)},[]),ze=z.useRef(0),qe=z.useCallback(oe=>{ze.current+=1,b(oe)},[]),tt=z.useRef([]),Ye=z.useCallback(oe=>{It.getRunState(oe).then(de=>H(be=>{const xe=be.get(oe);return xe?new Map(be).set(oe,{...xe,run:de}):be})).catch(()=>{})},[]),Ge=z.useCallback((oe,de,be)=>{const xe=L.current.get(oe);xe&&clearInterval(xe);const Oe=oo(tt.current.find(We=>We.id===oe)),ct=Date.now();D(We=>{const st=We.get(oe)??[];return st.includes(de)?We:new Map(We).set(oe,[...st,de])}),U(We=>{if(!We.has(oe))return We;const st=new Map(We);return st.delete(oe),st});const vt={workflow_slug:Oe?jd(Oe):void 0,session_id:oe,target:be};let Ht=X6();const Tt=We=>{const{state:st,emit:us}=J6(Ht,We);if(Ht=st,us.event===null)return;if(us.event==="agent.run_started"){Ms("agent.run_started",vt);return}const Xe=Date.now()-ct;if(us.event==="agent.run_succeeded"){Ms("agent.run_succeeded",{...vt,duration_ms:Xe});return}Ms("agent.run_failed",{...vt,duration_ms:Xe,error_kind:us.error_kind})},ve=G.current.has(de);if(G.current.size>=oL){const We=G.current.values().next().value;We!==void 0&&G.current.delete(We)}G.current.add(de),Tt({kind:"announced",duplicate:ve});const Te=()=>{const We=L.current.get(oe);We&&clearInterval(We),L.current.delete(oe)},Pe=async()=>{try{const We=await It.getRunState(de);H(st=>new Map(st).set(de,{run:We,target:be,workflowPath:Oe,observedAt:ct})),Tt({kind:"polled",status:We.status}),We.status!=="running"&&Te()}catch{Tt({kind:"poll_failed"}),Ht.settled&&Te()}};Pe(),L.current.set(oe,setInterval(()=>void Pe(),2e3))},[]),Ct=z.useRef(0),yt=z.useCallback(async(oe,de,be)=>{Ct.current+=1;const xe=`local-${Date.now()}-${Ct.current}`,Oe=oo(tt.current.find(Je=>Je.id===oe)),ct=Date.now(),jt=new Date(ct).toISOString(),vt=[];let Ht,Tt,ve,Te,Pe,We;D(Je=>{const ft=Je.get(oe)??[];return ft.includes(xe)?Je:new Map(Je).set(oe,[...ft,xe])}),U(Je=>{if(!Je.has(oe))return Je;const ft=new Map(Je);return ft.delete(oe),ft});const st=()=>{const Je=nL(vt,{executionId:xe,outcome:Ht,unusedStubs:Pe,stubWarnings:We,input:be,output:Tt,error:ve,startedAt:jt,finishedAt:Te});H(ft=>new Map(ft).set(xe,{run:Je,target:"local",workflowPath:Oe,observedAt:ct}))};st();const us={workflow_slug:Oe?jd(Oe):void 0,session_id:oe,target:"local"};let Xe=!1;Ms("agent.run_started",us);const ss=Je=>{if(Je.kind==="summary")Ht=Je.outcome,Tt=Je.output,ve=Je.error,Te=new Date().toISOString(),Pe=Je.unusedStubs,We=Je.stubWarnings;else if(Je.kind==="error"){Ht="failed",ve=Je.error,Te=new Date().toISOString();const ft={step:"run-local",attempt:1,input:be,status:"threw",startedAt:jt,finishedAt:Te,error:{name:"RunLocalError",message:Je.error},logs:[]},Lt=vt.findIndex(Ps=>Ps.step===ft.step&&Ps.attempt===ft.attempt);Lt>=0?vt[Lt]=ft:vt.push(ft)}else if(Je.kind==="step"){const ft=Je.trace,Lt=vt.findIndex(Ps=>Ps.step===ft.step&&Ps.attempt===ft.attempt);Lt>=0?vt[Lt]=ft:vt.push(ft)}else{const ft=vt.findIndex(Lt=>Lt.step===Je.step&&Lt.attempt===Je.attempt);ft>=0?vt[ft]=Je:vt.push(Je)}st()};try{await It.runLocal({sourceDir:de,input:be},ss)}catch(Je){const ft=Je instanceof Ai&&Je.reason?Je.reason:Je instanceof Error?Je.message:"Local execution failed.";Ht="failed",Xe=!0,ve=ft,Te=new Date().toISOString();const Lt={step:"run-local",attempt:1,input:be,status:"threw",startedAt:jt,finishedAt:Te,error:{name:"RunLocalError",message:ft},logs:[{level:"error",msg:ft}]},Ps=vt.findIndex(pn=>pn.step===Lt.step&&pn.attempt===Lt.attempt);Ps>=0?vt[Ps]=Lt:vt.push(Lt),st(),A(Fs(ft))}finally{const Je=K6(Ht),ft=Date.now()-ct;Je==="succeeded"?Ms("agent.run_succeeded",{...us,duration_ms:ft}):Je==="failed"&&Ms("agent.run_failed",{...us,duration_ms:ft,error_kind:Xe?"exception":"failed"}),Ee()}},[Ee]),ts=z.useCallback((oe,de)=>{U(be=>new Map(be).set(oe,de)),Ye(de)},[Ye]),Dt=z.useMemo(()=>{const oe=new Map;return I.forEach((de,be)=>{const xe=P.get(be),Oe=xe&&de.includes(xe)?xe:de[de.length-1],ct=Oe?Q.get(Oe):void 0;ct&&oe.set(be,ct)}),oe},[I,P,Q]);z.useEffect(()=>{tt.current=(e==null?void 0:e.sessions)??[]},[e]),z.useEffect(()=>{const oe=L.current;return()=>{oe.forEach(de=>clearInterval(de)),oe.clear()}},[]),z.useEffect(()=>{const oe=ie.current;return()=>{oe.forEach(de=>clearTimeout(de)),oe.clear()}},[]);const Et=z.useRef(null);z.useEffect(()=>{let oe=!1;return S>0&&(l(!0),m(null),v(null)),Promise.all([It.getState(),It.getSettings()]).then(([de,be])=>{if(oe)return;t(de);const xe=Et.current??(Et.current=new Set);for(const ct of de.workflows)xe.add(ct.path);r(be),v(null),de.tasks&&W(de.tasks);const Oe=de.sessions.find(ct=>ct.status!=="exited");Oe&&b(Oe.id),de.workflows[0]&&x(de.workflows[0].path)}).catch(de=>{oe||(m(de.message),v(de instanceof Ai?{status:de.status}:{networkError:!0}))}).finally(()=>!oe&&l(!1)),()=>{oe=!0}},[S]);const gs=z.useCallback(()=>w(oe=>oe+1),[]);z.useEffect(()=>{if(!g)return;const oe=e==null?void 0:e.sessions.find(de=>de.id===g);x(oo(oe)??null)},[g]);const $t=z.useCallback(async()=>{const oe=await It.listWorkflows();return t(de=>de&&{...de,workflows:oe}),oe},[]);z.useEffect(()=>V6(oe=>{if(q(oe),oe.type==="session.status"){if(t(de=>{if(!de)return de;const xe=de.sessions.some(Oe=>Oe.id===oe.session.id)?de.sessions.map(Oe=>Oe.id===oe.session.id?oe.session:Oe):[...de.sessions,oe.session];return{...de,sessions:xe}}),oe.session.status==="exited"){const de=oe.session.id,be=ie.current.get(de);be&&(clearTimeout(be),ie.current.delete(de)),J(xe=>{if(!xe.has(de))return xe;const Oe=new Set(xe);return Oe.delete(de),Oe})}}else if(oe.type==="workflows.changed")$t().then(de=>{const be=Et.current;if(be===null){Et.current=new Set(de.map(xe=>xe.path));return}for(const xe of W6(be,de))be.add(xe),Ms("agent.created",{workflow_slug:jd(xe),...Uw(de.find(Oe=>Oe.path===xe))})});else if(oe.type==="execution.started")Ge(oe.harnessSessionId,oe.executionId,oe.target);else if(oe.type==="port.detected")Y(de=>new Map(de).set(oe.harnessSessionId,{port:oe.port,url:oe.url}));else if(oe.type==="task.status")W(de=>de.some(xe=>xe.id===oe.task.id)?de.map(xe=>xe.id===oe.task.id?oe.task:xe):[...de,oe.task]);else if(oe.type==="session.activity"){const de=oe.harnessSessionId;J(xe=>xe.has(de)?xe:new Set(xe).add(de));const be=ie.current.get(de);be&&clearTimeout(be),ie.current.set(de,setTimeout(()=>{ie.current.delete(de),J(xe=>{if(!xe.has(de))return xe;const Oe=new Set(xe);return Oe.delete(de),Oe})},rL))}else oe.type==="auth.changed"&&(t(de=>de&&{...de,authenticated:oe.authenticated,organizationName:oe.organizationName}),$t())}),[$t,Ge]);const bt=z.useCallback(async oe=>{const de=Array.from(new Set(oe)),be=de.map(xe=>{const Oe=j.current.get(xe);if(Oe)return Oe;const ct=It.sessionHistory(xe).finally(()=>{j.current.delete(xe)});return j.current.set(xe,ct),ct});M.current+=1,T(!0);try{const xe=await Promise.allSettled(be),Oe=[],ct=new Set;xe.forEach((jt,vt)=>{jt.status==="fulfilled"&&(ct.add(de[vt]),Oe.push(...jt.value))}),_(jt=>E5(jt,Oe,ct))}finally{M.current-=1,M.current===0&&T(!1)}},[]),_s=z.useCallback(async oe=>{var xe;const de=await It.createSession(oe);t(Oe=>Oe&&!Oe.sessions.some(ct=>ct.id===de.id)?{...Oe,sessions:[...Oe.sessions,de]}:Oe),qe(de.id);const be=[oe.cwd,...(((xe=o.current)==null?void 0:xe.recentDirs)??[]).filter(Oe=>Oe!==oe.cwd)].slice(0,aL);r(Oe=>Oe&&{...Oe,recentDirs:be});try{const Oe=await It.updateSettings({recentDirs:be});r(ct=>ct&&{...ct,recentDirs:Oe.recentDirs})}catch{}return de},[qe]),Ze=z.useCallback((oe,de)=>It.attachFile(oe,de),[]),Rs=z.useCallback(()=>It.listTemplates(),[]),es=z.useCallback(oe=>It.getTemplate(oe),[]),Wi=z.useCallback(oe=>It.sessionRecord(oe),[]),ps=z.useCallback(async oe=>{const de=ze.current;try{const be=await It.resumeSession(oe);return t(xe=>xe&&{...xe,sessions:xe.sessions.map(Oe=>Oe.id===be.id?be:Oe)}),ze.current===de&&qe(be.id),be}catch(be){throw A(Fs(be instanceof Ai&&be.reason?be.reason:be.message)),be}},[qe]),Ds=z.useCallback(async({cwd:oe,harness:de,from:be})=>{const xe=await _s({cwd:oe,harness:de,rehydrateFrom:be});return xe.rehydratedFrom||A(Fs("Nothing was recorded for that session, so this one starts fresh.","info")),xe},[_s]),ai=z.useCallback(async oe=>{var be;const de=oe.harnessSessionId??((be=e==null?void 0:e.sessions.find(xe=>xe.agentSessionId===oe.agentSessionId))==null?void 0:be.id);if(oe.resumeMode==="rehydrate")return Ds({cwd:oe.cwd,harness:oe.harness,from:de??oe.agentSessionId});if(de)return ps(de);try{const xe=await It.adoptSession({agentSessionId:oe.agentSessionId,harness:oe.harness,cwd:oe.cwd,title:oe.title,lastActiveAt:oe.lastActiveAt});return t(Oe=>{if(!Oe)return Oe;const ct=Oe.sessions.some(jt=>jt.id===xe.id)?Oe.sessions.map(jt=>jt.id===xe.id?xe:jt):[...Oe.sessions,xe];return{...Oe,sessions:ct}}),qe(xe.id),xe}catch(xe){throw A(Fs(xe instanceof Ai&&xe.reason?xe.reason:xe.message)),xe}},[e,ps,Ds,qe]),Zs=z.useCallback(async oe=>{try{await It.killSession(oe)}catch(be){throw A(Fs(be instanceof Ai&&be.reason?be.reason:be.message)),be}const de=((e==null?void 0:e.sessions)??[]).filter(be=>be.id!==oe);if(t(be=>be&&{...be,sessions:de}),g===oe){const be=de.find(xe=>xe.status!=="exited");qe(be?be.id:null)}},[e,g,qe]),ys=z.useCallback(async oe=>{const de=await It.connectWorkflow(oe);return t(be=>be&&{...be,workflows:[...be.workflows.filter(xe=>xe.path!==de.path),de]}),(Et.current??(Et.current=new Set)).add(de.path),de},[]),Os=z.useCallback(async oe=>{const de=await It.scanWorkflows(oe),be=await $t(),xe=Et.current??(Et.current=new Set);for(const Oe of be)xe.add(Oe.path);return de},[$t]),oi=z.useCallback(()=>It.listHarnesses(),[]),Is=z.useCallback(async(oe,de)=>{const be=await It.bindWorkflow(oe,de);t(xe=>xe&&{...xe,sessions:xe.sessions.map(Oe=>Oe.id===be.id?be:Oe)})},[]),$s=z.useCallback(async oe=>{const de=await It.updateSettings(oe);return r(de),oe.telemetryOptIn!==void 0&&t(be=>be&&{...be,telemetryOptIn:de.telemetryOptIn}),oe.productAnalyticsOptIn!==void 0&&t(be=>be&&{...be,productAnalyticsOptIn:de.productAnalyticsOptIn!==!1}),de},[]),rt=z.useCallback(async(oe,de)=>{try{await It.runMacro(oe,de)}catch(be){A(Fs(be instanceof Ai&&be.reason?be.reason:be.message))}},[]),et=z.useCallback(oe=>{const de=$.current.get(oe);if(de)return de;const be=(async()=>{A(Fs("Deploying…","info"));const xe=jd(oe),Oe=Uw(c.current.find(Tt=>Tt.path===oe)),ct=performance.now();Ms("agent.deploy_started",{workflow_slug:xe,...Oe});let jt=null,vt=null,Ht=!1;try{const Tt=await It.deploy(oe,ve=>{ve.phase==="linking"?(jt="linking",Z(oe,{phase:"linking"}),A(Fs(`Deploying — creating the agent "${ve.name}" on Sapiom…`,"info"))):ve.phase==="warning"?(vt=ve.message,A(Fs(ve.message))):ve.phase==="building"&&(jt="building",Z(oe,{phase:"building"}),A(Fs("Deploying — building on Sapiom…","info")),$t())});if(Tt.phase==="ready")Z(oe,{phase:"ready"}),Ms("agent.deploy_succeeded",{workflow_slug:xe,duration_ms:Math.round(performance.now()-ct),...Oe}),Ht=!0,A(vt?Fs(`Deployed to Sapiom. ${vt}`):Fs("Deployed to Sapiom.","success")),le(ve=>{if(!ve.has(oe))return ve;const Te=new Map(ve);return Te.delete(oe),Te}),await $t();else if(Tt.phase==="error"){const ve=jt==="linking"?"Couldn't create the agent":"Deploy failed",Te=Tt.hint?`${ve}: ${Tt.message} (${Tt.hint})`:`${ve}: ${Tt.message}`;Z(oe,{phase:"error",message:Te}),Ms("agent.deploy_failed",{workflow_slug:xe,error_kind:zw(jt,!1),...Oe}),Ht=!0,A(Fs(Te)),le(Pe=>new Map(Pe).set(oe,Te)),await $t()}}catch(Tt){const ve=Tt instanceof Ai&&Tt.reason?Tt.reason:Tt.message;Z(oe,{phase:"error",message:ve}),Ht||Ms("agent.deploy_failed",{workflow_slug:xe,error_kind:zw(jt,!0),...Oe}),A(Fs(ve)),le(Te=>new Map(Te).set(oe,ve))}finally{Ee(),$.current.delete(oe)}})();return $.current.set(oe,be),be},[$t,Ee,Z]),Ae=z.useCallback(async(oe,de,be)=>{try{const{executionId:xe}=await It.run({definitionId:de,input:be});Ge(oe,xe,"prod")}catch(xe){A(Fs(xe instanceof Ai&&xe.reason?xe.reason:xe.message))}finally{Ee()}},[Ge,Ee]),nt=z.useCallback(async()=>It.startAuth(),[]),Vt=z.useCallback(async()=>{try{await It.disconnect()}catch(oe){A(Fs(oe instanceof Ai&&oe.reason?oe.reason:oe.message))}},[]),Ts=z.useCallback(()=>A(null),[]),gi=z.useCallback(async(oe,de)=>{await It.injectInput(oe,{text:de,submit:!0})},[]),Ks=z.useCallback((oe,de="error")=>{A(Fs(oe,de))},[]),_i=z.useCallback(oe=>V.get(oe)??null,[V]),Mi=z.useCallback(oe=>It.listDir(oe),[]),li=z.useCallback(oe=>It.getWorkflowInputContract(oe),[]);return{state:e,loading:f,error:d,errorKind:y,reload:gs,settings:i,bootToken:lo(),selectedWorkflowPath:R,setSelectedWorkflowPath:x,activeSessionId:g,setActiveSessionId:qe,history:p,historyLoading:C,loadHistory:bt,createSession:_s,attachFile:Ze,listTemplates:Rs,getTemplate:es,getWorkflowInputContract:li,sessionRecord:Wi,resumeSession:ps,rehydrateSession:Ds,resumeFromHistory:ai,closeSession:Zs,connectWorkflow:ys,scanWorkflows:Os,listHarnesses:oi,bindWorkflow:Is,updateSettings:$s,runMacro:rt,deploy:et,startProdRun:Ae,runLocal:yt,injectInput:gi,showToast:Ks,lastDeployErrorFor:_i,deployStateByPath:ae,dismissDeployState:oe=>Z(oe,null),pendingWorkspaces:ue,addPendingWorkspace:Re,removePendingWorkspace:Le,directActionSettleSeq:$e,listDir:Mi,lastMessage:B,runsBySession:Dt,runsByExecution:Q,runIdsBySession:I,selectRun:ts,previewBySession:se,toast:k,dismissToast:Ts,busySessionIds:F,tasks:te,api:It,startAuth:nt,disconnect:Vt}}const cL=10*6e4,uL=4e3;function Tl(e,t){return t?e.filter(i=>i.status!=="exited"&&(O1(i.boundWorkflowPath??"",t)||i.boundWorkflowPath==null&&O1(i.cwd,t))).sort((i,r)=>i.createdAt.localeCompare(r.createdAt)||i.id.localeCompare(r.id)):[]}const dL=()=>{var nc,ei,da,xo,ha,vn,Co,Eo,gn,rc,ko,Ao,fa,ac,oc,kr,Di,pa,ma,_n,yn;const e=lL(),t=h6(),[i,r]=z.useState(!1),[o,c]=z.useState(null),f=z.useRef(new Map),l=z.useCallback(async ee=>{const _e=f.current.get(ee);try{const Me=await e.getWorkflowInputContract(ee);return Me.status==="unavailable"&&_e?_e:Me}catch(Me){if(_e)return _e;throw Me}},[e.getWorkflowInputContract]),[d,m]=z.useState(!1),[y,v]=z.useState(null),S=z.useRef(null),w=z.useRef(null),R=z.useRef(f6()),x=z.useRef(!1),g=z.useRef(null),[b,p]=z.useState(null),[_,k]=z.useState(null),[A,C]=z.useState(!1),[T,j]=z.useState(()=>{const ee=dn().rightTab;return ee==="canvas"||ee==="steps"||ee==="code"?ee:"canvas"}),[M,$]=z.useState(T==="code"),[B,q]=z.useState(null),[F,J]=z.useState(!1),[te,W]=z.useState(!1),[ie,Q]=z.useState(()=>dn().sessionNames??{}),H=(ee,_e)=>{Q(Me=>{const Ue={...Me},gt=_e.trim();return gt?Ue[ee]=gt:delete Ue[ee],Kn({sessionNames:Ue}),Ue})},I=z.useRef(new Map),D=z.useRef([]),P=z.useCallback(ee=>{const _e=I.current.get(ee);if(_e)return window.clearTimeout(_e.timer),window.clearTimeout(_e.hintTimer),I.current.delete(ee),_e},[]),U=z.useCallback(ee=>{const _e=I.current.get(ee);if(!_e)return;const Me=D.current.find(Ue=>Ue.id===ee);Me&&(Me.ready?(P(ee),e.injectInput(ee,_e.prompt).catch(()=>e.showToast(_e.failMessage))):Me.status==="exited"&&(P(ee),e.showToast(_e.failMessage)))},[P,e.injectInput,e.showToast]),L=z.useCallback((ee,_e,Me)=>{P(ee);const Ue=window.setTimeout(()=>{P(ee)&&e.showToast(Me)},cL),gt=window.setTimeout(()=>{I.current.has(ee)&&e.showToast("Sign in to Claude in the terminal — your prompt sends automatically once you're signed in.")},uL);I.current.set(ee,{prompt:_e,failMessage:Me,timer:Ue,hintTimer:gt}),U(ee)},[P,e.showToast,U]);z.useEffect(()=>{var ee;if(D.current=((ee=e.state)==null?void 0:ee.sessions)??[],I.current.size!==0)for(const _e of[...I.current.keys()])U(_e)},[(nc=e.state)==null?void 0:nc.sessions,U]);const[G,se]=z.useState(()=>Iv()||(dn().railCollapsed??!1)),[Y,V]=z.useState(()=>Iv()||(dn().rightCollapsed??!1)),[le,ae]=z.useState(!1),X=z6(),Z=B6(),{widths:ue,canvasResizing:Se,railResizing:Re,startRailDrag:Le,startCanvasDrag:$e,resetRail:lt,resetCanvas:Ee}=q6(),[ze,qe]=z.useState(!1),tt=z.useRef(!1),Ye=z.useRef(null),Ge=z.useRef(null),Ct=z.useRef(!1),yt=z.useRef(!1),ts=z.useRef(null),Dt=z.useRef(null),Et=z.useCallback(ee=>{ee&&!tt.current&&ee.style.setProperty("--rp-w",`${ee.offsetWidth}px`)},[]),gs=z.useCallback(ee=>{var Me;if((Me=Dt.current)==null||Me.disconnect(),ts.current=ee,!ee){Dt.current=null;return}const _e=new ResizeObserver(()=>{yt.current||Et(ee)});_e.observe(ee),Dt.current=_e},[Et]);tt.current=Y,yt.current=ze,z.useLayoutEffect(()=>{if(X)return;qe(!0);const ee=window.setTimeout(()=>{qe(!1),Et(ts.current)},260);return()=>window.clearTimeout(ee)},[Y,X,Et]),z.useEffect(()=>{const ee=_e=>{var Ue;const Me=_e.key.toLowerCase();if((_e.metaKey||_e.ctrlKey)&&(Me==="k"||Me==="p")){_e.preventDefault(),r(!0);return}if((_e.metaKey||_e.ctrlKey)&&/^[1-9]$/.test(_e.key)){const xs=Tl(((Ue=e.state)==null?void 0:Ue.sessions)??[],y)[Number(_e.key)-1];xs&&(_e.preventDefault(),m(!1),q(null),J(!1),W(!1),e.setActiveSessionId(xs.id))}};return window.addEventListener("keydown",ee),()=>window.removeEventListener("keydown",ee)},[(ei=e.state)==null?void 0:ei.sessions,y]);const $t=o5({settingsRoot:(da=e.settings)==null?void 0:da.projectRoot,defaultProjectRoot:(xo=e.state)==null?void 0:xo.defaultProjectRoot,launchDir:(ha=e.state)==null?void 0:ha.launchDir}),bt=async ee=>{await e.updateSettings({projectRoot:ee})};z.useEffect(()=>{var _e;if(!i||!e.state)return;const ee=ZC(e.state.sessions,((_e=e.settings)==null?void 0:_e.recentDirs)??[],e.activeSessionId);ee.length>0&&e.loadHistory(ee)},[i]);const _s=z.useRef(!1);z.useEffect(()=>{var _e;if(_s.current||!e.state)return;_s.current=!0;const ee=e.state.sessions.find(Me=>Me.id===e.activeSessionId);v(oo(ee)??((_e=e.state.workflows[0])==null?void 0:_e.path)??null)},[e.state,e.activeSessionId]);const Ze=e.state;z.useEffect(()=>{Ze&&M6(Ze)},[Ze,Ze==null?void 0:Ze.authenticated,Ze==null?void 0:Ze.userId,Ze==null?void 0:Ze.tenantId,Ze==null?void 0:Ze.consentSource,Ze==null?void 0:Ze.productAnalyticsOptIn,Ze==null?void 0:Ze.version]),z.useEffect(()=>{if(!Ze)return;const ee=Ze.sessions.find(Me=>Me.id===e.activeSessionId),_e={firstRun:Ze.firstRun===!0,settingsOpen:A,templatesOpen:F,hasLiveSession:Ze.sessions.some(Me=>Me.status!=="exited"),inspectingDeadSession:(ee==null?void 0:ee.status)==="exited",rightTab:T};d4(_e),D6((ee==null?void 0:ee.harness)??null)},[Ze,e.activeSessionId,A,F,T]);const Rs=z.useRef(X);z.useEffect(()=>{Rs.current!==X&&(Rs.current=X,se(X),V(X))},[X]),z.useEffect(()=>{X||Kn({railCollapsed:G,rightCollapsed:Y})},[G,Y,X]),z.useEffect(()=>{Kn({rightTab:T})},[T]);const es=Z.record,Wi=e.activeSessionId,ps=y!=null&&Tl(((vn=e.state)==null?void 0:vn.sessions)??[],y).length>0,Ds=z.useRef(!1);z.useEffect(()=>{if(Ds.current){Ds.current=!1;return}F?es({kind:"templates"}):B?es({kind:"review",summary:B}):d?es({kind:"composer"}):Wi&&(y==null||ps)?es({kind:"session",sessionId:Wi,agentPath:y}):y&&es({kind:"agent",agentPath:y})},[es,F,B,d,Wi,y,ps]);const ai=e.setActiveSessionId,Zs=z.useCallback(ee=>{ee&&(Ds.current=!0,W(!1),J(ee.kind==="templates"),m(ee.kind==="composer"),q(ee.kind==="review"?ee.summary:null),ee.kind==="session"?(v(ee.agentPath),ai(ee.sessionId)):ee.kind==="agent"&&v(ee.agentPath))},[ai]),ys=((Co=e.state)==null?void 0:Co.sessions.find(ee=>ee.id===e.activeSessionId&&ee.status==="exited"))??null,Os=ys!=null&&ys.agentSessionId?(Eo=e.history.find(ee=>ee.agentSessionId===ys.agentSessionId))==null?void 0:Eo.resumeMode:"rehydrate",oi=(ys==null?void 0:ys.agentSessionId)!=null&&Os===void 0?ys.cwd:null,Is=e.loadHistory;z.useEffect(()=>{oi&&Is([oi])},[oi,Is]);const $s=z.useRef(new Map);if(z.useEffect(()=>{for(const ee of e.tasks){if(ee.macroId!=="describe")continue;$s.current.get(ee.id)==="running"&&ee.status!=="running"&&e.showToast(ee.status==="failed"?"Couldn't generate descriptions — check the agent terminal for details.":"Describe run finished — the canvas updates if the agent changed the source.",ee.status==="failed"?"error":"success"),$s.current.set(ee.id,ee.status)}},[e.tasks,e.showToast]),z.useEffect(()=>{const ee=Xn();if(ee!=null&&ee.onDeepLink)return ee.onDeepLink(_e=>{var Me;return(Me=S.current)==null?void 0:Me.call(S,_e)})},[]),z.useEffect(()=>{var _e;if(e.loading)return;const ee=R.current;!ee||x.current||(x.current=!0,(_e=S.current)==null||_e.call(S,ee))},[e.loading]),z.useEffect(()=>{var _e;const ee=g.current;ee&&((_e=w.current)!=null&&_e.call(w,ee))&&(g.current=null)},[(gn=e.state)==null?void 0:gn.workflows]),e.loading)return h.jsx("div",{className:"app-status",children:"Loading Agent Studio…"});if(e.error||!e.state){const ee=d6({online:t,error:e.errorKind});return h.jsx(x5,{status:ee==="online"?"error":ee,onRetry:e.reload,detail:e.error,onStartAuth:ee==="auth"?e.startAuth:void 0})}const{state:rt}=e,et=rt.sessions.find(ee=>ee.id===e.activeSessionId)??null,Ae=oo(et),nt=rt.workflows.find(ee=>ee.path===Ae)??null,Vt=rt.workflows.find(ee=>ee.path===y)??null,Ts=Tl(rt.sessions,y),gi=B!=null,Ks=!gi&&(et==null?void 0:et.status)==="exited",_i=!gi&&!Ks&&!d&&Vt!=null&&Ts.length===0,Mi=!gi&&!Ks&&!d&&!_i&&et!=null&&et.status!=="exited",li=!gi&&!Ks&&(d||!_i&&!Mi),oe=d&&et!=null&&et.status!=="exited",de=_i?null:nt,be=_i?(Vt==null?void 0:Vt.name)??null:null,xe=`${e.activeSessionId??""}::${(de==null?void 0:de.path)??""}`,Oe=()=>{Ge.current=e.activeSessionId??null,Ct.current=e.activeSessionId==null,V(!1)},ct=de?So(de,e.lastDeployErrorFor(de.path)):null,jt=e.activeSessionId?e.runsBySession.get(e.activeSessionId)??null:null,vt=Iw(jt,Ae)?jt:null,Ht=e.activeSessionId?(e.runIdsBySession.get(e.activeSessionId)??[]).map(ee=>e.runsByExecution.get(ee)).filter(ee=>ee!==void 0).filter(ee=>Iw(ee,Ae)):[],Tt=(vt==null?void 0:vt.run.status)==="running"?vt.target:null,ve=()=>{X&&se(!0)},Te=async(ee,_e,Me={})=>{Me.keepComposerOpen||m(!1),q(null),W(!1),v(ee),e.addPendingWorkspace(ee),ve();try{const Ue=await e.createSession({cwd:ee,harness:_e});return Ql("session.created"),Ms("session.started",{harness_kind:_e,origin:"user"}),Ue}catch(Ue){throw e.removePendingWorkspace(ee),Ue}},Pe=async(ee,_e)=>{await Te(ee,_e)},We=(ee,_e,Me)=>{const Ue=`Scaffold a new Sapiom agent project in this directory: ${Nv(_e,"default")}, then run npm install, read AGENTS.md, and use the sapiom-agent-authoring skill to`,gt=Me==null?void 0:Me.trim();L(ee.id,gt?`${Ue} build this:
493
493
 
494
- ${gt}`:`${Ue} define the first agent.`,"Couldn't send the scaffold prompt. Ask the coding agent to call sapiom_dev_agents_scaffold.")},st=async(ee,_e,Me)=>{const Ue=await Te(ee,_e);We(Ue,ee,Me)},us=ee=>{(async()=>{const _e=Tl(rt.sessions,ee.path)[0],Me=(_e==null?void 0:_e.cwd)??ee.path;try{const Ue=await Te(Me,"claude-code");await e.bindWorkflow(Ue.id,ee.path),v(ee.path)}catch(Ue){e.showToast(Ue.message||"Couldn't start the session.")}})()},Xe=ee=>{var Me;const _e=((Me=rt.sessions.find(Ue=>Ue.id===ee))==null?void 0:Me.cwd)??".";L(ee,`Scaffold a new Sapiom agent project in this directory: ${Nv(_e,"default")}, then run npm install, read AGENTS.md, and use the sapiom-agent-authoring skill to define the first agent.`,"Couldn't send the scaffold prompt. Ask the coding agent to call sapiom_dev_agents_scaffold.")},ss=async(ee,_e,Me="template_gallery")=>{const Ue=await Te(ee,"claude-code");Ms("agent.template_cloned",{template_slug:_e.id,template_id:_e.id,surface:Me}),L(Ue.id,f5(_e,ee),_e.kind==="gallery"?"Couldn't send the clone prompt. Ask the coding agent to run sapiom_dev_agents_clone.":"Couldn't send the starter prompt. Ask the coding agent to call sapiom_dev_agents_scaffold.")},Je=ee=>{const _e=new Set;for(const Me of rt.sessions){const Ue=wr(Me.cwd);Ue&&_e.add(Ue)}for(const Me of rt.workflows){const Ue=wr(Me.path);Ue&&_e.add(Ue)}return XC(c5(ee,_e),$t||null)},ft=async(ee,_e,Me)=>{const Ue=Je(ee.trim()?a5(ee):fg);if(!Ue)throw new Error("Set a project folder first — use the + to open one.");V(!0);const gt=await Te(Ue,_e,{keepComposerOpen:!0});try{const xs=await w$(gt.id,Me,e.attachFile);We(gt,Ue,x$(ee,xs)),m(!1)}catch(xs){throw await e.closeSession(gt.id).catch(is=>{console.error("[harness] attachment rollback failed:",is)}),e.removePendingWorkspace(Ue),xs}},Lt=ee=>{const _e=Je(ee.id);if(!_e){e.showToast("Set a project folder first — use the + to open one.");return}V(!0),ss(_e,ee,"welcome")},Ps=async ee=>{const _e=await e.scanWorkflows(ee);return e.showToast(_e.length===0?"No agent projects found under this folder.":_e.length===1?"Found 1 agent project.":`Found ${_e.length} agent projects.`,_e.length===0?"info":"success"),_e.length},pn=ee=>{m(!1),q(null),J(!1),W(!1),ve();const _e=rt.sessions.find(Me=>Me.id===ee);_e&&v(oo(_e)??_e.cwd),e.setActiveSessionId(ee)},mn=ee=>{m(!1),q(null),J(!1),W(!1),e.setActiveSessionId(ee)},Er=ee=>{m(!1),q(ee),J(!1),W(!1),ve()},Gi=ee=>{var Me;const _e=(Me=e.settings)==null?void 0:Me.editor;e.showToast(`Opening in ${Dw(_e)}… Pick a different editor in Settings.`,"info"),window.location.href=Y$(_e,ee)},Qs=ee=>{var Ue;m(!1),q(null),J(!1),W(!1),v(ee),ve();const _e=Tl(rt.sessions,ee),Me=_e.some(gt=>gt.id===e.activeSessionId)?e.activeSessionId:((Ue=_e[_e.length-1])==null?void 0:Ue.id)??null;Me!==e.activeSessionId&&e.setActiveSessionId(Me)};w.current=ee=>{const _e=rt.workflows.find(Me=>Me.definitionId!=null&&String(Me.definitionId)===ee);return _e?(Qs(_e.path),!0):!1},S.current=ee=>{var _e;if(ee.kind==="template"){k(ee.templateId),J(!0),W(!1);return}(_e=w.current)!=null&&_e.call(w,ee.definitionId)||p(ee)};const sc=async ee=>{var Me;p(null);const _e=Je(((Me=ee.slug)==null?void 0:Me.trim())||`agent-${ee.definitionId}`);if(!_e){e.showToast("Set a project folder first — use the + to open one.");return}g.current=ee.definitionId,V(!0);try{const Ue=await Te(_e,"claude-code");L(Ue.id,p5(ee.definitionId,_e),"Couldn't send the clone prompt. Ask the coding agent to run sapiom_dev_agents_clone.")}catch(Ue){g.current=null,e.showToast(Ue.message||"Couldn't start a session to clone the agent.")}},la=async ee=>{ve();const _e=rt.sessions.filter(is=>is.status!=="exited"),Me=is=>is.boundWorkflowPath===ee||hg(is.cwd,ee),Ue=_e.find(is=>is.id===e.activeSessionId),gt=Ue&&Me(Ue)?Ue:_e.filter(Me).sort((is,Ki)=>Ki.cwd.length-is.cwd.length||Ki.createdAt.localeCompare(is.createdAt))[0];let xs;if(gt)m(!1),q(null),W(!1),gt.id!==e.activeSessionId&&e.setActiveSessionId(gt.id),xs=gt.id;else try{xs=(await Te(ee,"claude-code")).id}catch(is){return e.showToast(is.message||"Couldn't start a session in this folder."),null}return await e.bindWorkflow(xs,ee),v(ee),xs},ca=(ee,_e)=>{(async()=>{const Me=i2(_e.id);((Me==="deploy"||Me==="run-local")&&ee!=null||Me==="prod-run"&&(ee==null?void 0:ee.definitionId)!=null&&Pd(ee))&&(j("steps"),V(!1));let gt=e.activeSessionId;if(ee&&(gt=await la(ee.path)??gt),_e.action.kind==="open-url"){window.open(q5(_e.action.url,ee),"_blank","noopener,noreferrer");return}if(gt){if(Me!==null){if(Me==="deploy")ee?e.deploy(ee.path):e.showToast("Select an agent first.");else if(Me==="prod-run")if((ee==null?void 0:ee.definitionId)!=null&&Pd(ee))e.startProdRun(gt,String(ee.definitionId));else{const xs=ee?e.lastDeployErrorFor(ee.path):null,is=ee?So(ee,xs):"draft";e.showToast(is==="failed"?"Last deploy failed — retry Deploy.":is==="building"?"The cloud build is still in progress.":is==="linked"?"No ready deployment yet — deploy it first.":"This agent isn't deployed yet — deploy it first.")}else Me==="run-local"&&(ee?e.runLocal(gt,ee.path):e.showToast("Select an agent first."));return}e.runMacro(_e.id,{harnessSessionId:gt,workflowPath:ee==null?void 0:ee.path})}})()},ic=ee=>{const _e=o;_e&&(c(null),j("steps"),V(!1),(async()=>{const Me=await la(_e.workflow.path)??e.activeSessionId;if(Me)if(_e.target==="prod"){if(_e.workflow.definitionId==null||!Pd(_e.workflow)){e.showToast("This agent needs a ready cloud deployment first.");return}await e.startProdRun(Me,String(_e.workflow.definitionId),ee)}else await e.runLocal(Me,_e.workflow.path,ee)})())},ua=ee=>{(async()=>{const _e=await la(ee.path)??e.activeSessionId;_e&&e.runMacro("describe",{harnessSessionId:_e,workflowPath:ee.path,subject:O6(ee)})})()};return h.jsxs("div",{className:"app-shell","data-rail-collapsed":G||void 0,children:[X&&!G&&h.jsx("div",{className:"shell-scrim","data-testid":"rail-drawer-scrim","aria-hidden":"true",onClick:()=>se(!0)}),(!X||!G)&&h.jsx("div",{className:"rail-slot"+(Re?" is-resizing":"")+(!X&&G?" is-collapsed":""),inert:!X&&G?!0:void 0,style:X?void 0:{width:G?0:ue.rail},children:h.jsx(a6,{projectRoot:$t||null,onSaveProjectRoot:bt,width:ue.rail,minWidth:Eg,workflows:rt.workflows,sessions:rt.sessions,pendingWorkspaces:e.pendingWorkspaces,activeSessionId:e.activeSessionId,focusedAgentPath:y,onFocusAgent:Qs,onOpenPalette:()=>r(!0),onConnect:async ee=>{await e.connectWorkflow(ee)},onCollapse:()=>se(!0),canGoBack:Z.canGoBack,canGoForward:Z.canGoForward,onGoBack:()=>Zs(Z.goBack()),onGoForward:()=>Zs(Z.goForward()),onSelectSession:pn,overviewSelected:te,onSelectOverview:()=>{W(!0),m(!1),q(null),J(!1),ve()},onNewSession:()=>{m(!0),J(!1),W(!1)},onReviewSummary:Er,history:e.history,historyLoading:e.historyLoading,onOpenHistory:ee=>void e.loadHistory(ee),recentDirs:((rc=e.settings)==null?void 0:rc.recentDirs)??[],launchDir:rt.launchDir??null,listDir:e.listDir,onCreateSession:Pe,listHarnesses:e.listHarnesses,onScaffoldSession:st,onScaffoldInSession:Xe,onBrowseTemplates:()=>{J(!0),W(!1)},templatesActive:F,onScanWorkflows:Ps,onToast:e.showToast,telemetryOptIn:((ko=e.settings)==null?void 0:ko.telemetryOptIn)??rt.telemetryOptIn,consentSource:rt.consentSource,consentEnvReason:rt.consentEnvReason,authenticated:rt.authenticated,organizationName:rt.organizationName,onToggleTelemetry:async ee=>{await e.updateSettings({telemetryOptIn:ee})},productAnalyticsOptIn:rt.productAnalyticsOptIn,onToggleProductAnalytics:async ee=>{await e.updateSettings({productAnalyticsOptIn:ee})},rollingSummary:((Ao=e.settings)==null?void 0:Ao.rollingSummary)===!0,onToggleRollingSummary:async ee=>{await e.updateSettings({rollingSummary:ee})},editor:Mh((fa=e.settings)==null?void 0:fa.editor),onSelectEditor:async ee=>{await e.updateSettings({editor:ee})},onStartAuth:e.startAuth,onDisconnect:e.disconnect,settingsOpen:A,onSetSettingsOpen:C})}),!G&&!X&&h.jsx("div",{className:"pane-resize-handle pane-resize-handle-rail",style:{left:ue.rail},onPointerDown:Le,onDoubleClick:lt,role:"separator","aria-orientation":"vertical","aria-label":"Resize workspace rail","data-testid":"resize-handle-rail"}),h.jsxs("div",{className:"workspace-main",children:[!t&&h.jsx(C5,{}),rt.consentSource==="default-silent"&&!((ac=e.settings)!=null&&ac.telemetryNoticeDismissed)&&h.jsx(jO,{onDismiss:()=>{e.updateSettings({telemetryNoticeDismissed:!0})},onOpenSettings:()=>C(!0)}),h.jsxs("div",{className:"app"+(F?" is-browsing":"")+(!F&&!X&&!li?" canvas-animated":"")+(ze?" canvas-sliding":"")+(Se?" canvas-dragging":""),style:{gridTemplateColumns:F||X||li?"minmax(0, 1fr)":`minmax(${ec}px, 1fr) ${Y?ue.canvas==null?"0fr":"0px":ue.canvas==null?"1fr":`${ue.canvas}px`}`},children:[F&&h.jsx(UO,{projectRoot:$t||null,recentDirs:((oc=e.settings)==null?void 0:oc.recentDirs)??[],listDir:e.listDir,onExit:()=>J(!1),onUse:ss,listTemplates:e.listTemplates,getTemplate:e.getTemplate,openTemplateId:_}),h.jsxs("div",{className:"center-pane",children:[h.jsx(H5,{openedAgentName:be,reviewTitle:B?B.title:null,composing:li,onBack:oe?()=>m(!1):null,activeSession:Mi||Ks?et:null,sessionName:et?hh(et,rt.sessions,ie):null,onRenameSession:H,boundWorkflowName:(nt==null?void 0:nt.name)??null,sessions:Mi?Ts:[],onSelectSession:mn,labelOf:ee=>{const _e=hh(ee,rt.sessions,ie),Me=wr(ee.cwd),Ue=_e.startsWith(`${Me} `)?_e.slice(Me.length+1):"";if(!(_e===Me||/^\d+$/.test(Ue))||!Vt)return _e;const xs=Ts.findIndex(is=>is.id===ee.id);return xs>0?`${Vt.name} ${xs+1}`:Vt.name},busy:et!=null&&e.busySessionIds.has(et.id),onCloseSession:ee=>void e.closeSession(ee),onOpenInEditor:Gi,editorLabel:Dw((kr=e.settings)==null?void 0:kr.editor),onToast:e.showToast,onExpandRail:G?()=>se(!1):null,onExpandRight:Y?Oe:null,onNewSession:()=>m(!0),actions:Mi&&et&&nt?h.jsx(wO,{workflow:nt,activeSessionId:e.activeSessionId,sessionReady:et.ready===!0&&et.status!=="exited",macros:rt.macros,onRunMacro:ee=>ca(nt,ee),onRequestRun:(ee,_e)=>c({workflow:nt,target:ee,returnFocus:_e}),preview:e.previewBySession.get(et.id)??null,lastDeployError:e.lastDeployErrorFor(nt.path),authenticated:rt.authenticated,directActionSettleSeq:e.directActionSettleSeq,runningTarget:Tt}):null}),h.jsx("div",{className:"terminal-slot",children:gi&&B?h.jsx(I5,{summary:B,loadRecord:e.sessionRecord,onStart:()=>{const ee=B;q(null),e.resumeFromHistory(ee)},onClose:()=>q(null)}):Ks&&et?h.jsx(L5,{session:et,resumeMode:Os,loadRecord:e.sessionRecord,onResume:()=>void e.resumeSession(et.id),onContinue:()=>void e.rehydrateSession({cwd:et.cwd,harness:et.harness,from:et.id}),onClose:()=>void e.closeSession(et.id)}):_i&&Vt?h.jsx(en,{className:"terminal-empty",testId:"open-agent-empty",icon:"Radio",title:`No running session for ${Vt.name}`,body:"Start a session to map, run, and inspect this agent.",cta:h.jsxs("button",{className:"btn-primary","data-testid":"open-agent-start-session",onClick:()=>us(Vt),children:[h.jsx(he,{name:"Plus",size:14})," Start session"]})}):Mi&&e.activeSessionId?h.jsx("div",{className:"agent-view","data-testid":"agent-view",children:h.jsx("div",{className:"agent-view-panel",id:"agent-panel-terminal",children:h.jsx(n$,{sessionId:e.activeSessionId,token:e.bootToken,cwd:(et==null?void 0:et.cwd)??null})})}):h.jsx(L$,{firstRun:rt.firstRun===!0,onSubmitIdea:ft,onAttachmentError:e.showToast,onUseTemplate:Lt,onBrowseTemplates:()=>J(!0),listHarnesses:e.listHarnesses,listTemplates:e.listTemplates,telemetryOptIn:((Di=e.settings)==null?void 0:Di.telemetryOptIn)??rt.telemetryOptIn,onToggleTelemetry:async ee=>{await e.updateSettings({telemetryOptIn:ee})},recentDirs:((pa=e.settings)==null?void 0:pa.recentDirs)??[],projectRoot:$t||null,listDir:e.listDir,onConnect:async ee=>{await e.connectWorkflow(ee)},onScan:Ps,onScaffold:st,onSaveProjectRoot:bt})})]}),!Y&&!X&&!li&&h.jsx("div",{className:"pane-resize-handle pane-resize-handle-canvas",style:{right:ue.canvas==null?"50%":`min(${ue.canvas}px, calc(100% - ${ec}px))`},onPointerDown:$e,onDoubleClick:Ee,role:"separator","aria-orientation":"vertical","aria-label":"Resize canvas pane","data-testid":"resize-handle-canvas"}),X&&!Y&&h.jsx("div",{className:"shell-scrim","data-testid":"right-sheet-scrim","aria-hidden":"true",onClick:()=>V(!0)}),h.jsxs("div",{ref:gs,className:"right-pane"+(Y||li?" is-collapsed":""),children:[h.jsxs("div",{className:"right-pane-tabs",role:"tablist","aria-label":"Right pane",children:[h.jsxs("button",{role:"tab","aria-selected":T==="canvas",className:"right-pane-tab"+(T==="canvas"?" is-active":""),onClick:()=>j("canvas"),"data-testid":"right-tab-canvas",children:[h.jsx(he,{name:"Workflow",size:14}),"Canvas"]}),h.jsxs("button",{role:"tab","aria-selected":T==="steps",className:"right-pane-tab"+(T==="steps"?" is-active":""),onClick:()=>j("steps"),"data-testid":"right-tab-steps",children:[h.jsx(he,{name:"List",size:14}),"Steps"]}),h.jsxs("button",{role:"tab","aria-selected":T==="code",className:"right-pane-tab"+(T==="code"?" is-active":""),onClick:()=>{j("code"),$(!0)},"data-testid":"right-tab-code",children:[h.jsx(he,{name:"Code",size:14}),"Code"]}),h.jsxs("div",{className:"right-pane-corner",children:[T==="canvas"&&(de==null?void 0:de.definitionId)!=null&&h.jsxs("a",{className:"status-tag status-tag-action workflow-deployed-tag right-pane-deployed","data-testid":"workflow-dashboard-link","data-deployment-state":ct??void 0,href:bh(de.definitionId),target:"_blank",rel:"noreferrer","aria-label":`${ct} — open in the Sapiom dashboard`,"data-tooltip":"Open this agent in the Sapiom dashboard",children:[h.jsx(he,{name:"Cloud",size:12}),ct==="ready"?"deployed":ct==="building"?"building":ct==="failed"?"deploy failed":"linked"]}),(T==="canvas"||T==="steps")&&h.jsx("button",{className:"theme-toggle","data-testid":"canvas-expand",hidden:le,"aria-label":T==="steps"?"Open Focus mode":"Expand canvas",title:T==="steps"?"Open Focus mode":"Expand canvas",onClick:()=>ae(ee=>!ee),children:h.jsx(he,{name:"Maximize2",size:15})}),h.jsx("button",{className:"theme-toggle right-pane-collapse","data-testid":"right-collapse","aria-label":"Collapse canvas panel",title:"Collapse canvas panel",onClick:()=>V(!0),children:h.jsx(he,{name:"PanelRightClose",size:15})})]})]}),h.jsx("div",{className:"right-pane-panel"+(T==="canvas"||T==="steps"?"":" is-hidden"),"data-testid":"right-panel-canvas",children:h.jsx(m4,{sessionId:e.activeSessionId,lastMessage:e.lastMessage,boundWorkflow:de,noSessionAgent:be,overviewActive:li,sessionExited:Ks,onCanvasState:ee=>{var Ue;if(X)return;const _e=((Ue=rt.sessions.find(gt=>gt.id===e.activeSessionId))==null?void 0:Ue.status)==="exited";if(ee||_e){Ye.current=null,V(!1);return}if(Ct.current){Ct.current=!1,Ge.current=e.activeSessionId??null;return}const Me=Ge.current;Me!=null&&Me===e.activeSessionId||Ye.current!==xe&&(Ye.current=xe,V(!0))},onGraphChange:(ee,_e)=>{const Me=_O(_e);Me&&f.current.set(ee,Me)},expanded:le,onToggleExpanded:()=>ae(ee=>!ee),macros:rt.macros,tasks:e.tasks,surface:T==="steps"?"steps":"board",onOpenSteps:()=>j("steps"),run:(vt==null?void 0:vt.run)??null,runTarget:(vt==null?void 0:vt.target)??null,runs:Ht,onSelectRun:ee=>{e.activeSessionId&&e.selectRun(e.activeSessionId,ee)},preview:e.activeSessionId?e.previewBySession.get(e.activeSessionId)??null:null,deployState:de?e.deployStateByPath.get(de.path)??null:null,onDismissDeploy:()=>{de&&e.dismissDeployState(de.path)},onOpenCode:()=>{j("code"),$(!0)},workflows:rt.workflows,onOpenWorkflow:ee=>void la(ee),onRunMacro:ee=>ca(nt,ee),onInjectPrompt:ee=>{e.activeSessionId&&e.injectInput(e.activeSessionId,ee)},onDescribeWorkflow:ua})}),(T==="code"||M)&&h.jsx("div",{className:"right-pane-panel"+(T==="code"?"":" is-hidden"),"data-testid":"right-panel-code",children:h.jsx(T4,{boundWorkflow:de,noSessionAgent:be,agentsBaseUrl:rt.agentsBaseUrl,lastDeployError:de?e.lastDeployErrorFor(de.path):null})})]})]})]}),te&&h.jsx(I$,{firstRun:rt.firstRun===!0,appVersion:((ma=Xn())==null?void 0:ma.appVersion)||"0.8.1",recentDirs:((_n=e.settings)==null?void 0:_n.recentDirs)??[],projectRoot:$t||null,listDir:e.listDir,onConnect:async ee=>{await e.connectWorkflow(ee),W(!1)},onScan:Ps,onBrowseTemplates:()=>{W(!1),J(!0)},onDismiss:()=>W(!1)}),i&&h.jsx(S5,{sessions:rt.sessions,workflows:rt.workflows,recentDirs:((yn=e.settings)==null?void 0:yn.recentDirs)??[],history:e.history,sessionNames:ie,activeSessionId:e.activeSessionId,listDir:e.listDir,listTemplates:e.listTemplates,onSelectSession:pn,onReviewSummary:Er,onOpenPath:ee=>void Pe(ee,"claude-code"),onOpenTemplate:ee=>{k(ee),J(!0),W(!1)},actions:[{id:"browse-templates",label:"Browse templates",meta:"Gallery and starters",icon:"LayoutTemplate",run:()=>{J(!0),W(!1)}},{id:"toggle-theme",label:"Toggle theme",meta:"Light and dark",icon:"Sun",run:Ww},{id:"toggle-rail",label:G?"Show workspace panel":"Hide workspace panel",meta:"Left pane",icon:"Menu",run:()=>se(ee=>!ee)},{id:"toggle-right",label:Y?"Show canvas panel":"Hide canvas panel",meta:"Right pane",icon:Y?"PanelRightOpen":"PanelRightClose",run:()=>V(ee=>!ee)},...et?[{id:"new-session-here",label:"New session in this folder",meta:et.cwd,icon:"Plus",run:()=>void Pe(et.cwd,"claude-code")}]:[]],onClose:()=>r(!1)}),b&&h.jsx(p6,{agentLabel:b.slug?`“${b.slug}”`:`Agent ${b.definitionId}`,onCancel:()=>p(null),onConfirm:()=>void sc(b)}),o&&h.jsx(AO,{workflow:o.workflow,target:o.target,loadContract:l,returnFocus:o.returnFocus,onClose:()=>c(null),onRun:ic}),e.toast&&h.jsx(l$,{message:e.toast.message,tone:e.toast.tone,onDismiss:e.dismissToast}),h.jsx(c$,{})]})};function hL(e=document.documentElement,t=window){const i=c=>{e.dataset.windowFocused=c?"true":"false"};i(t.document.hasFocus());const r=()=>i(!0),o=()=>i(!1);return t.addEventListener("focus",r),t.addEventListener("blur",o),()=>{t.removeEventListener("focus",r),t.removeEventListener("blur",o)}}function fL(e=typeof window>"u"?"":window.location.search){return new URLSearchParams(e).get("frame")==="macos"?"macos":"web"}document.documentElement.dataset.windowFrame=fL();hL();window.addEventListener("scroll",()=>{(window.scrollX!==0||window.scrollY!==0)&&window.scrollTo(0,0)},{passive:!0});window.addEventListener("dragover",e=>{var t;(t=e.dataTransfer)!=null&&t.types.includes("Files")&&e.preventDefault()});window.addEventListener("drop",e=>{var t;(t=e.dataTransfer)!=null&&t.types.includes("Files")&&e.preventDefault()});Qk.createRoot(document.getElementById("root")).render(h.jsx(z.StrictMode,{children:h.jsx(dL,{})}));
494
+ ${gt}`:`${Ue} define the first agent.`,"Couldn't send the scaffold prompt. Ask the coding agent to call sapiom_dev_agents_scaffold.")},st=async(ee,_e,Me)=>{const Ue=await Te(ee,_e);We(Ue,ee,Me)},us=ee=>{(async()=>{const _e=Tl(rt.sessions,ee.path)[0],Me=(_e==null?void 0:_e.cwd)??ee.path;try{const Ue=await Te(Me,"claude-code");await e.bindWorkflow(Ue.id,ee.path),v(ee.path)}catch(Ue){e.showToast(Ue.message||"Couldn't start the session.")}})()},Xe=ee=>{var Me;const _e=((Me=rt.sessions.find(Ue=>Ue.id===ee))==null?void 0:Me.cwd)??".";L(ee,`Scaffold a new Sapiom agent project in this directory: ${Nv(_e,"default")}, then run npm install, read AGENTS.md, and use the sapiom-agent-authoring skill to define the first agent.`,"Couldn't send the scaffold prompt. Ask the coding agent to call sapiom_dev_agents_scaffold.")},ss=async(ee,_e,Me="template_gallery")=>{const Ue=await Te(ee,"claude-code");Ms("agent.template_cloned",{template_slug:_e.id,template_id:_e.id,surface:Me}),L(Ue.id,f5(_e,ee),_e.kind==="gallery"?"Couldn't send the clone prompt. Ask the coding agent to run sapiom_dev_agents_clone.":"Couldn't send the starter prompt. Ask the coding agent to call sapiom_dev_agents_scaffold.")},Je=ee=>{const _e=new Set;for(const Me of rt.sessions){const Ue=wr(Me.cwd);Ue&&_e.add(Ue)}for(const Me of rt.workflows){const Ue=wr(Me.path);Ue&&_e.add(Ue)}return XC(c5(ee,_e),$t||null)},ft=async(ee,_e,Me)=>{const Ue=Je(ee.trim()?a5(ee):fg);if(!Ue)throw new Error("Set a project folder first — use the + to open one.");V(!0);const gt=await Te(Ue,_e,{keepComposerOpen:!0});try{const xs=await w$(gt.id,Me,e.attachFile);We(gt,Ue,x$(ee,xs)),m(!1)}catch(xs){throw await e.closeSession(gt.id).catch(is=>{console.error("[harness] attachment rollback failed:",is)}),e.removePendingWorkspace(Ue),xs}},Lt=ee=>{const _e=Je(ee.id);if(!_e){e.showToast("Set a project folder first — use the + to open one.");return}V(!0),ss(_e,ee,"welcome")},Ps=async ee=>{const _e=await e.scanWorkflows(ee);return e.showToast(_e.length===0?"No agent projects found under this folder.":_e.length===1?"Found 1 agent project.":`Found ${_e.length} agent projects.`,_e.length===0?"info":"success"),_e.length},pn=ee=>{m(!1),q(null),J(!1),W(!1),ve();const _e=rt.sessions.find(Me=>Me.id===ee);_e&&v(oo(_e)??_e.cwd),e.setActiveSessionId(ee)},mn=ee=>{m(!1),q(null),J(!1),W(!1),e.setActiveSessionId(ee)},Er=ee=>{m(!1),q(ee),J(!1),W(!1),ve()},Gi=ee=>{var Me;const _e=(Me=e.settings)==null?void 0:Me.editor;e.showToast(`Opening in ${Dw(_e)}… Pick a different editor in Settings.`,"info"),window.location.href=Y$(_e,ee)},Qs=ee=>{var Ue;m(!1),q(null),J(!1),W(!1),v(ee),ve();const _e=Tl(rt.sessions,ee),Me=_e.some(gt=>gt.id===e.activeSessionId)?e.activeSessionId:((Ue=_e[_e.length-1])==null?void 0:Ue.id)??null;Me!==e.activeSessionId&&e.setActiveSessionId(Me)};w.current=ee=>{const _e=rt.workflows.find(Me=>Me.definitionId!=null&&String(Me.definitionId)===ee);return _e?(Qs(_e.path),!0):!1},S.current=ee=>{var _e;if(ee.kind==="template"){k(ee.templateId),J(!0),W(!1);return}(_e=w.current)!=null&&_e.call(w,ee.definitionId)||p(ee)};const sc=async ee=>{var Me;p(null);const _e=Je(((Me=ee.slug)==null?void 0:Me.trim())||`agent-${ee.definitionId}`);if(!_e){e.showToast("Set a project folder first — use the + to open one.");return}g.current=ee.definitionId,V(!0);try{const Ue=await Te(_e,"claude-code");L(Ue.id,p5(ee.definitionId,_e),"Couldn't send the clone prompt. Ask the coding agent to run sapiom_dev_agents_clone.")}catch(Ue){g.current=null,e.showToast(Ue.message||"Couldn't start a session to clone the agent.")}},la=async ee=>{ve();const _e=rt.sessions.filter(is=>is.status!=="exited"),Me=is=>is.boundWorkflowPath===ee||hg(is.cwd,ee),Ue=_e.find(is=>is.id===e.activeSessionId),gt=Ue&&Me(Ue)?Ue:_e.filter(Me).sort((is,Ki)=>Ki.cwd.length-is.cwd.length||Ki.createdAt.localeCompare(is.createdAt))[0];let xs;if(gt)m(!1),q(null),W(!1),gt.id!==e.activeSessionId&&e.setActiveSessionId(gt.id),xs=gt.id;else try{xs=(await Te(ee,"claude-code")).id}catch(is){return e.showToast(is.message||"Couldn't start a session in this folder."),null}return await e.bindWorkflow(xs,ee),v(ee),xs},ca=(ee,_e)=>{(async()=>{const Me=i2(_e.id);((Me==="deploy"||Me==="run-local")&&ee!=null||Me==="prod-run"&&(ee==null?void 0:ee.definitionId)!=null&&Pd(ee))&&(j("steps"),V(!1));let gt=e.activeSessionId;if(ee&&(gt=await la(ee.path)??gt),_e.action.kind==="open-url"){window.open(q5(_e.action.url,ee),"_blank","noopener,noreferrer");return}if(gt){if(Me!==null){if(Me==="deploy")ee?e.deploy(ee.path):e.showToast("Select an agent first.");else if(Me==="prod-run")if((ee==null?void 0:ee.definitionId)!=null&&Pd(ee))e.startProdRun(gt,String(ee.definitionId));else{const xs=ee?e.lastDeployErrorFor(ee.path):null,is=ee?So(ee,xs):"draft";e.showToast(is==="failed"?"Last deploy failed — retry Deploy.":is==="building"?"The cloud build is still in progress.":is==="linked"?"No ready deployment yet — deploy it first.":"This agent isn't deployed yet — deploy it first.")}else Me==="run-local"&&(ee?e.runLocal(gt,ee.path):e.showToast("Select an agent first."));return}e.runMacro(_e.id,{harnessSessionId:gt,workflowPath:ee==null?void 0:ee.path})}})()},ic=ee=>{const _e=o;_e&&(c(null),j("steps"),V(!1),(async()=>{const Me=await la(_e.workflow.path)??e.activeSessionId;if(Me)if(_e.target==="prod"){if(_e.workflow.definitionId==null||!Pd(_e.workflow)){e.showToast("This agent needs a ready cloud deployment first.");return}await e.startProdRun(Me,String(_e.workflow.definitionId),ee)}else await e.runLocal(Me,_e.workflow.path,ee)})())},ua=ee=>{(async()=>{const _e=await la(ee.path)??e.activeSessionId;_e&&e.runMacro("describe",{harnessSessionId:_e,workflowPath:ee.path,subject:O6(ee)})})()};return h.jsxs("div",{className:"app-shell","data-rail-collapsed":G||void 0,children:[X&&!G&&h.jsx("div",{className:"shell-scrim","data-testid":"rail-drawer-scrim","aria-hidden":"true",onClick:()=>se(!0)}),(!X||!G)&&h.jsx("div",{className:"rail-slot"+(Re?" is-resizing":"")+(!X&&G?" is-collapsed":""),inert:!X&&G?!0:void 0,style:X?void 0:{width:G?0:ue.rail},children:h.jsx(a6,{projectRoot:$t||null,onSaveProjectRoot:bt,width:ue.rail,minWidth:Eg,workflows:rt.workflows,sessions:rt.sessions,pendingWorkspaces:e.pendingWorkspaces,activeSessionId:e.activeSessionId,focusedAgentPath:y,onFocusAgent:Qs,onOpenPalette:()=>r(!0),onConnect:async ee=>{await e.connectWorkflow(ee)},onCollapse:()=>se(!0),canGoBack:Z.canGoBack,canGoForward:Z.canGoForward,onGoBack:()=>Zs(Z.goBack()),onGoForward:()=>Zs(Z.goForward()),onSelectSession:pn,overviewSelected:te,onSelectOverview:()=>{W(!0),m(!1),q(null),J(!1),ve()},onNewSession:()=>{m(!0),J(!1),W(!1)},onReviewSummary:Er,history:e.history,historyLoading:e.historyLoading,onOpenHistory:ee=>void e.loadHistory(ee),recentDirs:((rc=e.settings)==null?void 0:rc.recentDirs)??[],launchDir:rt.launchDir??null,listDir:e.listDir,onCreateSession:Pe,listHarnesses:e.listHarnesses,onScaffoldSession:st,onScaffoldInSession:Xe,onBrowseTemplates:()=>{J(!0),W(!1)},templatesActive:F,onScanWorkflows:Ps,onToast:e.showToast,telemetryOptIn:((ko=e.settings)==null?void 0:ko.telemetryOptIn)??rt.telemetryOptIn,consentSource:rt.consentSource,consentEnvReason:rt.consentEnvReason,authenticated:rt.authenticated,organizationName:rt.organizationName,onToggleTelemetry:async ee=>{await e.updateSettings({telemetryOptIn:ee})},productAnalyticsOptIn:rt.productAnalyticsOptIn,onToggleProductAnalytics:async ee=>{await e.updateSettings({productAnalyticsOptIn:ee})},rollingSummary:((Ao=e.settings)==null?void 0:Ao.rollingSummary)===!0,onToggleRollingSummary:async ee=>{await e.updateSettings({rollingSummary:ee})},editor:Mh((fa=e.settings)==null?void 0:fa.editor),onSelectEditor:async ee=>{await e.updateSettings({editor:ee})},onStartAuth:e.startAuth,onDisconnect:e.disconnect,settingsOpen:A,onSetSettingsOpen:C})}),!G&&!X&&h.jsx("div",{className:"pane-resize-handle pane-resize-handle-rail",style:{left:ue.rail},onPointerDown:Le,onDoubleClick:lt,role:"separator","aria-orientation":"vertical","aria-label":"Resize workspace rail","data-testid":"resize-handle-rail"}),h.jsxs("div",{className:"workspace-main",children:[!t&&h.jsx(C5,{}),rt.consentSource==="default-silent"&&!((ac=e.settings)!=null&&ac.telemetryNoticeDismissed)&&h.jsx(jO,{onDismiss:()=>{e.updateSettings({telemetryNoticeDismissed:!0})},onOpenSettings:()=>C(!0)}),h.jsxs("div",{className:"app"+(F?" is-browsing":"")+(!F&&!X&&!li?" canvas-animated":"")+(ze?" canvas-sliding":"")+(Se?" canvas-dragging":""),style:{gridTemplateColumns:F||X||li?"minmax(0, 1fr)":`minmax(${ec}px, 1fr) ${Y?ue.canvas==null?"0fr":"0px":ue.canvas==null?"1fr":`${ue.canvas}px`}`},children:[F&&h.jsx(UO,{projectRoot:$t||null,recentDirs:((oc=e.settings)==null?void 0:oc.recentDirs)??[],listDir:e.listDir,onExit:()=>J(!1),onUse:ss,listTemplates:e.listTemplates,getTemplate:e.getTemplate,openTemplateId:_}),h.jsxs("div",{className:"center-pane",children:[h.jsx(H5,{openedAgentName:be,reviewTitle:B?B.title:null,composing:li,onBack:oe?()=>m(!1):null,activeSession:Mi||Ks?et:null,sessionName:et?hh(et,rt.sessions,ie):null,onRenameSession:H,boundWorkflowName:(nt==null?void 0:nt.name)??null,sessions:Mi?Ts:[],onSelectSession:mn,labelOf:ee=>{const _e=hh(ee,rt.sessions,ie),Me=wr(ee.cwd),Ue=_e.startsWith(`${Me} `)?_e.slice(Me.length+1):"";if(!(_e===Me||/^\d+$/.test(Ue))||!Vt)return _e;const xs=Ts.findIndex(is=>is.id===ee.id);return xs>0?`${Vt.name} ${xs+1}`:Vt.name},busy:et!=null&&e.busySessionIds.has(et.id),onCloseSession:ee=>void e.closeSession(ee),onOpenInEditor:Gi,editorLabel:Dw((kr=e.settings)==null?void 0:kr.editor),onToast:e.showToast,onExpandRail:G?()=>se(!1):null,onExpandRight:Y?Oe:null,onNewSession:()=>m(!0),actions:Mi&&et&&nt?h.jsx(wO,{workflow:nt,activeSessionId:e.activeSessionId,sessionReady:et.ready===!0&&et.status!=="exited",macros:rt.macros,onRunMacro:ee=>ca(nt,ee),onRequestRun:(ee,_e)=>c({workflow:nt,target:ee,returnFocus:_e}),preview:e.previewBySession.get(et.id)??null,lastDeployError:e.lastDeployErrorFor(nt.path),authenticated:rt.authenticated,directActionSettleSeq:e.directActionSettleSeq,runningTarget:Tt}):null}),h.jsx("div",{className:"terminal-slot",children:gi&&B?h.jsx(I5,{summary:B,loadRecord:e.sessionRecord,onStart:()=>{const ee=B;q(null),e.resumeFromHistory(ee)},onClose:()=>q(null)}):Ks&&et?h.jsx(L5,{session:et,resumeMode:Os,loadRecord:e.sessionRecord,onResume:()=>void e.resumeSession(et.id),onContinue:()=>void e.rehydrateSession({cwd:et.cwd,harness:et.harness,from:et.id}),onClose:()=>void e.closeSession(et.id)}):_i&&Vt?h.jsx(en,{className:"terminal-empty",testId:"open-agent-empty",icon:"Radio",title:`No running session for ${Vt.name}`,body:"Start a session to map, run, and inspect this agent.",cta:h.jsxs("button",{className:"btn-primary","data-testid":"open-agent-start-session",onClick:()=>us(Vt),children:[h.jsx(he,{name:"Plus",size:14})," Start session"]})}):Mi&&e.activeSessionId?h.jsx("div",{className:"agent-view","data-testid":"agent-view",children:h.jsx("div",{className:"agent-view-panel",id:"agent-panel-terminal",children:h.jsx(n$,{sessionId:e.activeSessionId,token:e.bootToken,cwd:(et==null?void 0:et.cwd)??null})})}):h.jsx(L$,{firstRun:rt.firstRun===!0,onSubmitIdea:ft,onAttachmentError:e.showToast,onUseTemplate:Lt,onBrowseTemplates:()=>J(!0),listHarnesses:e.listHarnesses,listTemplates:e.listTemplates,telemetryOptIn:((Di=e.settings)==null?void 0:Di.telemetryOptIn)??rt.telemetryOptIn,onToggleTelemetry:async ee=>{await e.updateSettings({telemetryOptIn:ee})},recentDirs:((pa=e.settings)==null?void 0:pa.recentDirs)??[],projectRoot:$t||null,listDir:e.listDir,onConnect:async ee=>{await e.connectWorkflow(ee)},onScan:Ps,onScaffold:st,onSaveProjectRoot:bt})})]}),!Y&&!X&&!li&&h.jsx("div",{className:"pane-resize-handle pane-resize-handle-canvas",style:{right:ue.canvas==null?"50%":`min(${ue.canvas}px, calc(100% - ${ec}px))`},onPointerDown:$e,onDoubleClick:Ee,role:"separator","aria-orientation":"vertical","aria-label":"Resize canvas pane","data-testid":"resize-handle-canvas"}),X&&!Y&&h.jsx("div",{className:"shell-scrim","data-testid":"right-sheet-scrim","aria-hidden":"true",onClick:()=>V(!0)}),h.jsxs("div",{ref:gs,className:"right-pane"+(Y||li?" is-collapsed":""),children:[h.jsxs("div",{className:"right-pane-tabs",role:"tablist","aria-label":"Right pane",children:[h.jsxs("button",{role:"tab","aria-selected":T==="canvas",className:"right-pane-tab"+(T==="canvas"?" is-active":""),onClick:()=>j("canvas"),"data-testid":"right-tab-canvas",children:[h.jsx(he,{name:"Workflow",size:14}),"Canvas"]}),h.jsxs("button",{role:"tab","aria-selected":T==="steps",className:"right-pane-tab"+(T==="steps"?" is-active":""),onClick:()=>j("steps"),"data-testid":"right-tab-steps",children:[h.jsx(he,{name:"List",size:14}),"Steps"]}),h.jsxs("button",{role:"tab","aria-selected":T==="code",className:"right-pane-tab"+(T==="code"?" is-active":""),onClick:()=>{j("code"),$(!0)},"data-testid":"right-tab-code",children:[h.jsx(he,{name:"Code",size:14}),"Code"]}),h.jsxs("div",{className:"right-pane-corner",children:[T==="canvas"&&(de==null?void 0:de.definitionId)!=null&&h.jsxs("a",{className:"status-tag status-tag-action workflow-deployed-tag right-pane-deployed","data-testid":"workflow-dashboard-link","data-deployment-state":ct??void 0,href:bh(de.definitionId),target:"_blank",rel:"noreferrer","aria-label":`${ct} — open in the Sapiom dashboard`,"data-tooltip":"Open this agent in the Sapiom dashboard",children:[h.jsx(he,{name:"Cloud",size:12}),ct==="ready"?"deployed":ct==="building"?"building":ct==="failed"?"deploy failed":"linked"]}),(T==="canvas"||T==="steps")&&h.jsx("button",{className:"theme-toggle","data-testid":"canvas-expand",hidden:le,"aria-label":T==="steps"?"Open Focus mode":"Expand canvas",title:T==="steps"?"Open Focus mode":"Expand canvas",onClick:()=>ae(ee=>!ee),children:h.jsx(he,{name:"Maximize2",size:15})}),h.jsx("button",{className:"theme-toggle right-pane-collapse","data-testid":"right-collapse","aria-label":"Collapse canvas panel",title:"Collapse canvas panel",onClick:()=>V(!0),children:h.jsx(he,{name:"PanelRightClose",size:15})})]})]}),h.jsx("div",{className:"right-pane-panel"+(T==="canvas"||T==="steps"?"":" is-hidden"),"data-testid":"right-panel-canvas",children:h.jsx(m4,{sessionId:e.activeSessionId,lastMessage:e.lastMessage,boundWorkflow:de,noSessionAgent:be,overviewActive:li,sessionExited:Ks,onCanvasState:ee=>{var Ue;if(X)return;const _e=((Ue=rt.sessions.find(gt=>gt.id===e.activeSessionId))==null?void 0:Ue.status)==="exited";if(ee||_e){Ye.current=null,V(!1);return}if(Ct.current){Ct.current=!1,Ge.current=e.activeSessionId??null;return}const Me=Ge.current;Me!=null&&Me===e.activeSessionId||Ye.current!==xe&&(Ye.current=xe,V(!0))},onGraphChange:(ee,_e)=>{const Me=_O(_e);Me&&f.current.set(ee,Me)},expanded:le,onToggleExpanded:()=>ae(ee=>!ee),macros:rt.macros,tasks:e.tasks,surface:T==="steps"?"steps":"board",onOpenSteps:()=>j("steps"),run:(vt==null?void 0:vt.run)??null,runTarget:(vt==null?void 0:vt.target)??null,runs:Ht,onSelectRun:ee=>{e.activeSessionId&&e.selectRun(e.activeSessionId,ee)},preview:e.activeSessionId?e.previewBySession.get(e.activeSessionId)??null:null,deployState:de?e.deployStateByPath.get(de.path)??null:null,onDismissDeploy:()=>{de&&e.dismissDeployState(de.path)},onOpenCode:()=>{j("code"),$(!0)},workflows:rt.workflows,onOpenWorkflow:ee=>void la(ee),onRunMacro:ee=>ca(nt,ee),onInjectPrompt:ee=>{e.activeSessionId&&e.injectInput(e.activeSessionId,ee)},onDescribeWorkflow:ua})}),(T==="code"||M)&&h.jsx("div",{className:"right-pane-panel"+(T==="code"?"":" is-hidden"),"data-testid":"right-panel-code",children:h.jsx(T4,{boundWorkflow:de,noSessionAgent:be,agentsBaseUrl:rt.agentsBaseUrl,lastDeployError:de?e.lastDeployErrorFor(de.path):null})})]})]})]}),te&&h.jsx(I$,{firstRun:rt.firstRun===!0,appVersion:((ma=Xn())==null?void 0:ma.appVersion)||"0.8.3",recentDirs:((_n=e.settings)==null?void 0:_n.recentDirs)??[],projectRoot:$t||null,listDir:e.listDir,onConnect:async ee=>{await e.connectWorkflow(ee),W(!1)},onScan:Ps,onBrowseTemplates:()=>{W(!1),J(!0)},onDismiss:()=>W(!1)}),i&&h.jsx(S5,{sessions:rt.sessions,workflows:rt.workflows,recentDirs:((yn=e.settings)==null?void 0:yn.recentDirs)??[],history:e.history,sessionNames:ie,activeSessionId:e.activeSessionId,listDir:e.listDir,listTemplates:e.listTemplates,onSelectSession:pn,onReviewSummary:Er,onOpenPath:ee=>void Pe(ee,"claude-code"),onOpenTemplate:ee=>{k(ee),J(!0),W(!1)},actions:[{id:"browse-templates",label:"Browse templates",meta:"Gallery and starters",icon:"LayoutTemplate",run:()=>{J(!0),W(!1)}},{id:"toggle-theme",label:"Toggle theme",meta:"Light and dark",icon:"Sun",run:Ww},{id:"toggle-rail",label:G?"Show workspace panel":"Hide workspace panel",meta:"Left pane",icon:"Menu",run:()=>se(ee=>!ee)},{id:"toggle-right",label:Y?"Show canvas panel":"Hide canvas panel",meta:"Right pane",icon:Y?"PanelRightOpen":"PanelRightClose",run:()=>V(ee=>!ee)},...et?[{id:"new-session-here",label:"New session in this folder",meta:et.cwd,icon:"Plus",run:()=>void Pe(et.cwd,"claude-code")}]:[]],onClose:()=>r(!1)}),b&&h.jsx(p6,{agentLabel:b.slug?`“${b.slug}”`:`Agent ${b.definitionId}`,onCancel:()=>p(null),onConfirm:()=>void sc(b)}),o&&h.jsx(AO,{workflow:o.workflow,target:o.target,loadContract:l,returnFocus:o.returnFocus,onClose:()=>c(null),onRun:ic}),e.toast&&h.jsx(l$,{message:e.toast.message,tone:e.toast.tone,onDismiss:e.dismissToast}),h.jsx(c$,{})]})};function hL(e=document.documentElement,t=window){const i=c=>{e.dataset.windowFocused=c?"true":"false"};i(t.document.hasFocus());const r=()=>i(!0),o=()=>i(!1);return t.addEventListener("focus",r),t.addEventListener("blur",o),()=>{t.removeEventListener("focus",r),t.removeEventListener("blur",o)}}function fL(e=typeof window>"u"?"":window.location.search){return new URLSearchParams(e).get("frame")==="macos"?"macos":"web"}document.documentElement.dataset.windowFrame=fL();hL();window.addEventListener("scroll",()=>{(window.scrollX!==0||window.scrollY!==0)&&window.scrollTo(0,0)},{passive:!0});window.addEventListener("dragover",e=>{var t;(t=e.dataTransfer)!=null&&t.types.includes("Files")&&e.preventDefault()});window.addEventListener("drop",e=>{var t;(t=e.dataTransfer)!=null&&t.types.includes("Files")&&e.preventDefault()});Qk.createRoot(document.getElementById("root")).render(h.jsx(z.StrictMode,{children:h.jsx(dL,{})}));
@@ -19,7 +19,7 @@
19
19
  document.documentElement.dataset.theme = theme;
20
20
  })();
21
21
  </script>
22
- <script type="module" crossorigin src="/assets/index-Dxe3NPwI.js"></script>
22
+ <script type="module" crossorigin src="/assets/index-TBJ2A_wf.js"></script>
23
23
  <link rel="stylesheet" crossorigin href="/assets/index-BuY7sGHa.css">
24
24
  </head>
25
25
  <body>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sapiom/harness",
3
- "version": "0.8.1",
3
+ "version": "0.8.3",
4
4
  "description": "Agent Studio — a CLI-launched local web app that runs your coding agent (Claude Code or Codex) in a Sapiom-configured environment: MCP pre-wired, agents tracked, one-click deploy/run, and a live canvas for previews.",
5
5
  "keywords": [
6
6
  "sapiom",
@@ -48,10 +48,10 @@
48
48
  "open": "^10.1.0",
49
49
  "ws": "^8.18.0",
50
50
  "zod": "^3.25.0",
51
- "@sapiom/analytics-core": "^0.2.1",
52
- "@sapiom/agent-core": "^0.11.1",
53
- "@sapiom/mcp": "^0.12.6",
54
- "@sapiom/agent": "^0.9.4"
51
+ "@sapiom/agent": "^0.10.1",
52
+ "@sapiom/agent-core": "^0.12.0",
53
+ "@sapiom/mcp": "^0.12.8",
54
+ "@sapiom/analytics-core": "^0.2.1"
55
55
  },
56
56
  "devDependencies": {
57
57
  "@playwright/test": "^1.61.0",