agent-canvas 0.1.2 → 0.1.4
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/bin/agent-canvas.ts +11 -8
- package/daemon/client/App.tsx +13 -6
- package/daemon/client/SessionSwitcher.tsx +14 -4
- package/daemon/client/components/Mermaid.tsx +288 -1
- package/daemon/dist/client.css +1 -1
- package/daemon/dist/client.js +15 -15
- package/daemon/dist/components.js +5 -5
- package/daemon/src/server.ts +11 -2
- package/hooks/session-start.sh +6 -4
- package/package.json +5 -2
- package/skills/canvas/SKILL.md +14 -12
- package/skills/canvas/components.md +9 -0
- package/skills/canvas/flows.md +2 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{useState as
|
|
2
|
-
`).slice(
|
|
3
|
-
`);B(Y),W(M.language||"text")}}).catch(()=>P("Failed to fetch file")).finally(()=>F(!1))},[m,y,$?.[0],$?.[1],b]),n(()=>{let M=O.current,Y=window.hljs;if(!M||!Y||!g)return;M.removeAttribute("data-highlighted"),M.className=k?`language-${k}`:"",M.textContent=g,Y.highlightElement(M)},[g,k]),L)return h("div",{className:"text-text-tertiary text-body mt-3 bg-bg-code rounded-md p-4",children:["Loading ",y,"..."]},void 0,!0,void 0,this);if(N)return h("div",{className:"text-accent-red text-body mt-3 bg-accent-red-muted rounded-md p-4",children:[y,": ",N]},void 0,!0,void 0,this);return h("div",{className:"mt-3 bg-bg-code rounded-md overflow-hidden","data-md":"filepreview","data-md-path":y,...$?{"data-md-lines":`${$[0]}-${$[1]}`}:{},children:[h("div",{className:"px-4 py-2 flex items-center justify-between",children:[h("button",{className:"font-mono text-meta text-text-tertiary hover:text-text-secondary hover:underline cursor-pointer text-left",onClick:()=>f({type:"file",path:y}),title:`Open ${y}`,children:y},void 0,!1,void 0,this),$&&h("span",{className:"font-mono text-meta text-text-tertiary opacity-60",children:["L",$[0],"–",$[1]]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),h("pre",{className:"px-4 pb-3 overflow-x-auto text-code font-mono !bg-transparent",style:{background:"transparent"},children:h("code",{ref:O,className:k?`language-${k}`:"",children:g},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}import{useEffect as gy,useRef as l,useState as $y,useCallback as py}from"react";import{useAnnotations as dy}from"#canvas/runtime";import{useEffect as a,useRef as o,useState as E,useCallback as yy,useMemo as my}from"react";import{createPortal as uy}from"react-dom";function e(y,$){let f=$||document.body,g=y.getBoundingClientRect(),B=f.getBoundingClientRect(),k=f===document.body?window.scrollY:f.scrollTop,W=g.bottom-B.top+k+8,N=Math.max(0,Math.min(g.left-B.left,B.width-280-12));return f.style.position="relative",{style:{position:"absolute",top:`${W}px`,left:`${N}px`},parent:f}}import{jsxDEV as v}from"react/jsx-dev-runtime";function iy({anchorEl:y,scrollContainer:$,onClose:b,ignoreSelector:m,zIndex:f="50",padding:g="12px",width:B="280px",children:k}){let W=o(null),N=o(b);N.current=b;let{style:P,parent:L}=e(y,$);return a(()=>{let F=setTimeout(()=>{let O=(M)=>{if(W.current&&!W.current.contains(M.target)){if(m&&M.target.closest?.(m))return;N.current(),document.removeEventListener("mousedown",O)}};return document.addEventListener("mousedown",O),()=>document.removeEventListener("mousedown",O)},0);return()=>clearTimeout(F)},[m]),uy(v("div",{ref:W,style:{...P,zIndex:f,width:B,background:"var(--color-bg-elevated)",border:"1px solid var(--color-border-hover)",borderRadius:"8px",boxShadow:"0 4px 12px var(--color-shadow)",padding:g,fontFamily:"'Inter', sans-serif"},children:k},void 0,!1,void 0,this),L)}var by=[{label:"Clarity",items:["Unclear","Why?","Needs example","Missing context"]},{label:"Scope",items:["Overkill","Out of scope","Important","Risky"]},{label:"Action",items:["Simplify","Rethink","Expand on this","Skip this"]}],fy=by.flatMap((y)=>y.items);function ky({anchorEl:y,scrollContainer:$,snippet:b,truncateAt:m=100,header:f,onAdd:g,onCancel:B}){let[k,W]=E(""),[N,P]=E(null),[L,F]=E(!1),O=o(null);a(()=>{O.current?.focus()},[]);let M=yy(()=>{if(k.trim())g(k.trim());else B()},[k,g,B]),Y=k.trim().length>0?fy.filter((J)=>J.toLowerCase().startsWith(k.trim().toLowerCase())):fy,Q=L?[]:Y.length===1&&Y[0].toLowerCase()===k.trim().toLowerCase()?[]:Y,G=new Set(Q),z=by.map((J)=>({label:J.label,items:J.items.filter((Z)=>G.has(Z))})).filter((J)=>J.items.length>0),X=z.map((J)=>J.items),T=X.flat(),_=my(()=>{if(N===null)return 0;let J=0;for(let Z=0;Z<X.length;Z++){if(N<J+X[Z].length)return Z;J+=X[Z].length}return 0},[N,X]),U=my(()=>{if(N===null)return 0;let J=0;for(let Z=0;Z<_;Z++)J+=X[Z].length;return N-J},[N,_,X]),q=(J,Z)=>{let A=0;for(let S=0;S<J;S++)A+=X[S].length;return A+Z};a(()=>{P(null),F(!1)},[k]);let w=yy((J)=>{W(J)},[]),d=b.length>m?b.slice(0,m)+"...":b;return v(iy,{anchorEl:y,scrollContainer:$,onClose:B,width:"420px",children:[f??v("div",{style:{fontSize:"11px",color:"var(--color-text-tertiary)",fontStyle:"italic",marginBottom:"8px",lineHeight:"1.4",display:"-webkit-box",WebkitLineClamp:2,WebkitBoxOrient:"vertical",overflow:"hidden"},children:["“",d,"”"]},void 0,!0,void 0,this),v("textarea",{ref:O,value:k,onChange:(J)=>W(J.target.value),onKeyDown:(J)=>{if(T.length>0&&(J.key==="ArrowDown"||J.key==="ArrowUp"||J.key==="ArrowLeft"||J.key==="ArrowRight")){if(J.preventDefault(),N===null){P(0);return}if(J.key==="ArrowDown"){let Z=Math.min(U+1,X[_].length-1);P(q(_,Z))}else if(J.key==="ArrowUp"){let Z=Math.max(U-1,0);P(q(_,Z))}else if(J.key==="ArrowRight"){let Z=Math.min(_+1,X.length-1),A=Math.min(U,X[Z].length-1);P(q(Z,A))}else if(J.key==="ArrowLeft"){let Z=Math.max(_-1,0),A=Math.min(U,X[Z].length-1);P(q(Z,A))}return}if(N!==null&&T.length>0){if(J.key==="Tab"){J.preventDefault(),w(T[N]);return}if(J.key==="Enter"&&!J.shiftKey){J.preventDefault(),g(T[N]);return}}if(J.key==="Enter"&&!J.shiftKey){J.preventDefault(),M();return}if(J.key==="Escape")if(T.length>0&&!L)F(!0);else B()},style:{width:"100%",minHeight:"60px",background:"transparent",border:"none",color:"var(--color-text-primary)",fontFamily:"'Inter', sans-serif",fontSize:"13px",lineHeight:"1.5",resize:"vertical",outline:"none"},placeholder:"Add your note..."},void 0,!1,void 0,this),v("div",{style:{display:"flex",justifyContent:"flex-end",gap:"8px",marginTop:"8px"},children:[v("button",{onClick:B,style:{fontSize:"11px",color:"var(--color-text-tertiary)",background:"none",border:"none",cursor:"pointer",padding:"4px 12px",fontFamily:"'Inter', sans-serif"},children:"Cancel"},void 0,!1,void 0,this),v("button",{onClick:M,style:{fontSize:"11px",fontWeight:500,padding:"4px 12px",borderRadius:"6px",background:"var(--color-highlight-bg)",color:"var(--color-text-primary)",border:"1px solid var(--color-highlight-border)",cursor:"pointer",fontFamily:"'Inter', sans-serif"},children:"Add"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),T.length>0&&v("div",{style:{marginTop:"6px",borderTop:"1px solid var(--color-border-subtle)",paddingTop:"8px",display:"flex",gap:"4px"},children:z.map((J)=>v("div",{style:{flex:1},children:[v("div",{style:{fontSize:"10px",fontWeight:600,color:"var(--color-text-disabled)",textTransform:"uppercase",letterSpacing:"0.05em",padding:"2px 6px",marginBottom:"2px",fontFamily:"'Inter', sans-serif"},children:J.label},void 0,!1,void 0,this),J.items.map((Z)=>{let A=T.indexOf(Z);return v("div",{onMouseDown:(S)=>{S.preventDefault(),S.stopPropagation(),w(Z)},onMouseEnter:()=>P(A),style:{padding:"3px 6px",fontSize:"12px",borderRadius:"4px",fontFamily:"'Inter', sans-serif",color:A===N?"var(--color-text-primary)":"var(--color-text-secondary)",background:A===N?"var(--color-highlight-selected)":"transparent",cursor:"pointer"},children:[v("span",{style:{fontWeight:500},children:Z.slice(0,k.trim().length)},void 0,!1,void 0,this),Z.slice(k.trim().length)]},Z,!0,void 0,this)})]},J.label,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}import{jsxDEV as R,Fragment as jy}from"react/jsx-dev-runtime";function xy({children:y}){let $=l(null),[b,m]=$y(null),f=typeof y==="string"?y:String(y??""),{annotations:g,addAnnotationWithId:B,activeAnnotationId:k,setActiveAnnotationId:W}=dy(),[N,P]=$y(null),L=l(g);L.current=g;let F=py((Y,Q,G)=>{let z=`[Diagram ${G.toLowerCase()}] ${Q}`,X=L.current.find((T)=>T.snippet===z);if(X)W(X.id);else P({anchorEl:Y,snippet:Q,prefix:G})},[W]),O=l(F);if(O.current=F,gy(()=>{let Y=!1,Q=async()=>{try{let z=window.mermaid;if(!z){m("Mermaid library not loaded");return}let X=document.documentElement.dataset.theme==="light"?"default":"dark";z.initialize({startOnLoad:!1,theme:X});let T=`mermaid-${Math.random().toString(36).slice(2)}`,{svg:_}=await z.render(T,f.trim());if(!Y&&$.current)$.current.innerHTML=_,Dy($.current,(U,q,w)=>O.current(U,q,w)),By($.current,L.current);m(null)}catch(z){if(!Y)m(z.message||"Invalid diagram")}};Q();let G=new MutationObserver((z)=>{for(let X of z)if(X.attributeName==="data-theme")Q()});return G.observe(document.documentElement,{attributes:!0,attributeFilter:["data-theme"]}),()=>{Y=!0,G.disconnect()}},[f]),gy(()=>{if($.current)By($.current,g,k)},[g,k]),b)return R("div",{className:"bg-accent-red-muted rounded-md p-4 mt-3 text-body text-accent-red",children:["Mermaid error: ",b,R("pre",{className:"mt-2 text-tiny text-text-tertiary whitespace-pre-wrap",children:f},void 0,!1,void 0,this)]},void 0,!0,void 0,this);let M=$.current?.closest("#plan-scroll-container");return R(jy,{children:[R("div",{ref:$,className:"mt-3 flex justify-center overflow-x-auto mermaid-container","data-md":"mermaid","data-md-source":f.trim()},void 0,!1,void 0,this),N&&R(ky,{anchorEl:N.anchorEl,scrollContainer:M,snippet:N.snippet,header:R("div",{style:{fontSize:"12px",color:"var(--color-text-tertiary)",marginBottom:"8px",lineHeight:"1.4",display:"flex",alignItems:"center",gap:"6px"},children:[R("span",{style:{width:"8px",height:"8px",borderRadius:"50%",background:"var(--color-accent-amber)",flexShrink:0}},void 0,!1,void 0,this),N.snippet]},void 0,!0,void 0,this),onAdd:(Y)=>{let Q=`ann-${Date.now()}-${Math.random().toString(36).slice(2,6)}`;B(Q,`[Diagram ${N.prefix.toLowerCase()}] ${N.snippet}`,Y),P(null)},onCancel:()=>P(null)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function Dy(y,$){let b=(m,f,g)=>{m.style.cursor="pointer",m.addEventListener("mouseenter",()=>{m.style.filter="brightness(1.2)"}),m.addEventListener("mouseleave",()=>{m.style.filter=""}),m.addEventListener("click",(B)=>{B.stopPropagation(),B.preventDefault(),$(m,f(),g)})};for(let m of y.querySelectorAll(".node"))b(m,()=>{return(m.querySelector(".nodeLabel")||m.querySelector("foreignObject span")||m.querySelector("text"))?.textContent?.trim()||"Node"},"Node");for(let m of y.querySelectorAll(".edgePath")){let f=m,g=f.querySelector("path");if(g){g.style.strokeWidth=Math.max(parseFloat(g.style.strokeWidth||"1"),8)+"px",g.style.strokeOpacity="0";let k=g.cloneNode(!0);k.style.strokeWidth="",k.style.strokeOpacity="",f.insertBefore(k,g)}let B=f.id||"";b(f,()=>{let k=y.querySelectorAll(".edgeLabel");for(let W of k)if(W.id&&B&&W.id.replace("label","").includes(B.replace("L-","").replace("edge",""))){let N=W.textContent?.trim();if(N)return N}return"Connection"},"Edge")}for(let m of y.querySelectorAll(".edgeLabel")){let f=m.textContent?.trim();if(!f)continue;b(m,()=>f,"Edge")}for(let m of y.querySelectorAll(".actor")){let f=m.closest("g")?.querySelector("text")||m.parentElement?.querySelector("text");if(!f)continue;let g=m.closest("g");if(!g||g.hasAttribute("data-clickable"))continue;g.setAttribute("data-clickable","true"),b(g,()=>f.textContent?.trim()||"Participant","Node")}for(let m of y.querySelectorAll(".messageText")){let f=m.textContent?.trim();if(!f)continue;b(m,()=>f,"Edge")}}function By(y,$,b){let m=new Map;for(let f of $){let g=f.snippet.match(/^\[Diagram (?:node|edge)\] (.+)$/);if(g)m.set(g[1],f.id)}for(let f of y.querySelectorAll("[data-annotated]"))f.style.outline="",f.style.outlineOffset="",f.style.borderRadius="",f.removeAttribute("data-annotated");if(m.size===0)return;for(let f of y.querySelectorAll(".node")){let B=(f.querySelector(".nodeLabel")||f.querySelector("foreignObject span")||f.querySelector("text"))?.textContent?.trim();if(!B||!m.has(B))continue;let k=m.get(B),W=f;W.setAttribute("data-annotated",k);let N=k===b;W.style.outline=N?"2px solid var(--color-highlight-border)":"2px solid var(--color-highlight-annotation)",W.style.outlineOffset="2px",W.style.borderRadius="4px"}for(let f of y.querySelectorAll(".edgeLabel")){let g=f.textContent?.trim();if(!g||!m.has(g))continue;let B=m.get(g),k=f;k.setAttribute("data-annotated",B);let W=B===b;k.style.outline=W?"2px solid var(--color-highlight-border)":"2px solid var(--color-highlight-annotation)",k.style.outlineOffset="2px",k.style.borderRadius="4px"}for(let f of y.querySelectorAll(".actor")){let g=f.closest("g");if(!g)continue;let k=g.querySelector("text")?.textContent?.trim();if(!k||!m.has(k))continue;if(g.hasAttribute("data-annotated"))continue;let W=m.get(k);g.setAttribute("data-annotated",W);let N=W===b,P=g.querySelector("rect");if(P)P.style.outline=N?"2px solid var(--color-highlight-border)":"2px solid var(--color-highlight-annotation)",P.style.outlineOffset="2px",P.style.borderRadius="4px"}for(let f of y.querySelectorAll(".messageText")){let g=f.textContent?.trim();if(!g||!m.has(g))continue;let B=m.get(g),k=f;k.setAttribute("data-annotated",B);let W=B===b;k.style.outline=W?"2px solid var(--color-highlight-border)":"2px solid var(--color-highlight-annotation)",k.style.outlineOffset="2px",k.style.borderRadius="4px"}}import{jsxDEV as i}from"react/jsx-dev-runtime";function Vy({before:y,after:$,language:b}){let m=y.split(`
|
|
4
|
-
`),
|
|
5
|
-
`),g=Ey(m,f),B=[],k=0,W=0,N=0;while(k<m.length||W<f.length)if(N<g.length&&k<m.length&&W<f.length&&m[k]===g[N]&&f[W]===g[N])B.push({type:"same",line:m[k]}),k++,W++,N++;else if(k<m.length&&(N>=g.length||m[k]!==g[N]))B.push({type:"removed",line:m[k]}),k++;else if(W<f.length)B.push({type:"added",line:f[W]}),W++;return i("div",{className:"mt-3 bg-bg-code rounded-md overflow-hidden group/diff","data-md":"diff","data-md-language":b||"",children:[b&&i("div",{className:"px-4 py-2 text-meta font-mono text-text-tertiary opacity-0 group-hover/diff:opacity-60 transition-opacity",children:["diff (",b,")"]},void 0,!0,void 0,this),i("pre",{className:"px-4 pb-3 overflow-x-auto text-code font-mono",children:B.map((P,L)=>i("div",{className:P.type==="removed"?"bg-accent-red-muted text-accent-red":P.type==="added"?"bg-accent-green-muted text-accent-green":"text-text-tertiary",children:[i("span",{className:"select-none w-6 inline-block text-center opacity-60",children:P.type==="removed"?"-":P.type==="added"?"+":" "},void 0,!1,void 0,this),P.line]},L,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function Ey(y,$){let b=y.length,m=$.length,f=Array.from({length:b+1},()=>Array(m+1).fill(0));for(let W=1;W<=b;W++)for(let N=1;N<=m;N++)f[W][N]=y[W-1]===$[N-1]?f[W-1][N-1]+1:Math.max(f[W-1][N],f[W][N-1]);let g=[],B=b,k=m;while(B>0&&k>0)if(y[B-1]===$[k-1])g.unshift(y[B-1]),B--,k--;else if(f[B-1][k]>f[B][k-1])B--;else k--;return g}import{useEffect as j,useRef as My,useState as Wy}from"react";import{useAnnotations as Jy}from"#canvas/runtime";import{jsxDEV as Ny}from"react/jsx-dev-runtime";function u({note:y,onChange:$}){return Ny("div",{className:"mt-1.5",children:Ny("textarea",{value:y,onChange:(b)=>$(b.target.value),className:"w-full bg-transparent text-[12px] font-body text-text-primary resize-none focus:outline-none border-none placeholder:text-text-disabled transition-colors min-h-[20px] p-0 leading-relaxed",placeholder:"Add a note...",rows:1,onInput:(b)=>{let m=b.target;m.style.height="auto",m.style.height=m.scrollHeight+"px"},ref:(b)=>{if(b)b.style.height="auto",b.style.height=b.scrollHeight+"px"}},void 0,!1,void 0,this)},void 0,!1,void 0,this)}import{jsxDEV as H}from"react/jsx-dev-runtime";function ay({id:y,label:$,options:b,required:m}){let{responses:f,setResponse:g}=Jy(),B=f.get(y),k=B?.value,W=B?.note||"",[N,P]=Wy(!1),L=My(null);j(()=>{if(!f.has(y))g(y,{id:y,type:"radio",label:$,value:null,options:b,required:m})},[y]);let F=(M)=>{g(y,{...B,value:M})};j(()=>{let M=L.current;if(!M)return;let Y=(Q)=>{let z=Q.target.closest("[data-md-label]")?.getAttribute("data-md-label");if(z&&b.includes(z))F(z)};return M.addEventListener("kb-select",Y),()=>M.removeEventListener("kb-select",Y)});let O=B?.required&&!k;return H("div",{ref:L,"data-md":"choice","data-md-label":$,className:"-mx-4 px-4 py-3 my-1 rounded-lg transition-colors duration-150 hover:bg-bg-input",children:[H("div",{className:"flex items-baseline gap-2 mb-2",children:[H("span",{className:"text-[13px] font-body font-medium text-text-primary",children:$},void 0,!1,void 0,this),m&&H("span",{className:"text-[10px] text-accent-red font-body",children:"*"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),H("div",{className:"space-y-1",children:b.map((M)=>H("label",{"data-md":"choice-option","data-md-label":M,onClick:()=>F(M),className:`flex items-center gap-2.5 px-3 py-2 rounded-lg cursor-pointer transition-all duration-150 ${k===M?"bg-highlight-selected":"hover:bg-bg-elevated"}`,children:[H("span",{className:`w-4 h-4 rounded-full border-[1.5px] flex items-center justify-center flex-shrink-0 transition-all ${k===M?"border-accent-amber bg-accent-amber":"border-border-strong"}`,children:k===M&&H("span",{className:"w-1.5 h-1.5 rounded-full bg-text-inverse"},void 0,!1,void 0,this)},void 0,!1,void 0,this),H("span",{className:"text-[13px] font-body text-text-secondary",children:M},void 0,!1,void 0,this)]},M,!0,void 0,this))},void 0,!1,void 0,this),H(u,{show:N,note:W,onToggle:()=>P(!N),onChange:(M)=>g(y,{...B,note:M})},void 0,!1,void 0,this),O&&H("p",{className:"text-[11px] text-accent-red font-body mt-1",children:"Please select an option."},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function oy({id:y,label:$,options:b,required:m}){let{responses:f,setResponse:g}=Jy(),B=f.get(y),k=B?.value||[],W=B?.note||"",[N,P]=Wy(!1),L=My(null);j(()=>{if(!f.has(y))g(y,{id:y,type:"checkbox",label:$,value:[],options:b,required:m})},[y]);let F=(M)=>{let Y=k.includes(M)?k.filter((Q)=>Q!==M):[...k,M];g(y,{...B,value:Y})};j(()=>{let M=L.current;if(!M)return;let Y=(Q)=>{let z=Q.target.closest("[data-md-label]")?.getAttribute("data-md-label");if(z&&b.includes(z))F(z)};return M.addEventListener("kb-select",Y),()=>M.removeEventListener("kb-select",Y)});let O=B?.required&&k.length===0;return H("div",{ref:L,"data-md":"multichoice","data-md-label":$,className:"-mx-4 px-4 py-3 my-1 rounded-lg transition-colors duration-150 hover:bg-bg-input",children:[H("div",{className:"flex items-baseline gap-2 mb-2",children:[H("span",{className:"text-[13px] font-body font-medium text-text-primary",children:$},void 0,!1,void 0,this),m&&H("span",{className:"text-[10px] text-accent-red font-body",children:"*"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),H("div",{className:"space-y-1",children:b.map((M)=>{let Y=k.includes(M);return H("label",{"data-md":"multichoice-option","data-md-label":M,onClick:()=>F(M),className:`flex items-center gap-2.5 px-3 py-2 rounded-lg cursor-pointer transition-all duration-150 ${Y?"bg-highlight-selected":"hover:bg-bg-elevated"}`,children:[H("span",{className:`w-4 h-4 rounded flex items-center justify-center flex-shrink-0 transition-all ${Y?"bg-accent-amber":"border-[1.5px] border-border-strong"}`,children:Y&&H("svg",{width:"10",height:"10",viewBox:"0 0 10 10",fill:"none",children:H("path",{d:"M2.5 5L4.5 7L7.5 3",style:{stroke:"var(--color-text-inverse)"},strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this),H("span",{className:"text-[13px] font-body text-text-secondary",children:M},void 0,!1,void 0,this)]},M,!0,void 0,this)})},void 0,!1,void 0,this),H(u,{show:N,note:W,onToggle:()=>P(!N),onChange:(M)=>g(y,{...B,note:M})},void 0,!1,void 0,this),O&&H("p",{className:"text-[11px] text-accent-red font-body mt-1",children:"Please select at least one option."},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}import{useEffect as Py,useRef as ly,useState as Qy}from"react";import{useAnnotations as Yy}from"#canvas/runtime";import{jsxDEV as K}from"react/jsx-dev-runtime";function ty({id:y,label:$,placeholder:b,multiline:m,required:f}){let{responses:g,setResponse:B}=Yy(),k=g.get(y),W=k?.value??"",N=k?.note||"",[P,L]=Qy(!1),F=ly(null);Py(()=>{if(!g.has(y))B(y,{id:y,type:"text",label:$,value:"",required:f})},[y]);let O=(Q)=>{B(y,{...k,value:Q})},M=(Q)=>{Q.style.height="auto",Q.style.height=Math.max(m?60:32,Q.scrollHeight)+"px"},Y=k?.required&&!W.trim();return K("div",{"data-md":"userinput","data-md-label":$,className:"-mx-4 px-4 py-3 my-1 rounded-lg transition-colors duration-150 hover:bg-bg-input",children:[K("div",{className:"flex items-baseline gap-2 mb-2",children:[K("span",{className:"text-[13px] font-body font-medium text-text-primary",children:$},void 0,!1,void 0,this),f&&K("span",{className:"text-[10px] text-accent-red font-body",children:"*"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),K("textarea",{ref:F,value:W,onChange:(Q)=>{O(Q.target.value),M(Q.target)},placeholder:b||"Type your response...",rows:m?3:1,className:"w-full bg-bg-input text-[13px] font-body text-text-primary rounded-lg px-3 py-2 resize-none focus:outline-none border border-border-subtle focus:border-border-hover placeholder:text-text-tertiary transition-colors",onInput:(Q)=>M(Q.target),onFocus:(Q)=>M(Q.target)},void 0,!1,void 0,this),K(u,{show:P,note:N,onToggle:()=>L(!P),onChange:(Q)=>B(y,{...k,note:Q})},void 0,!1,void 0,this),Y&&K("p",{className:"text-[11px] text-accent-red font-body mt-1",children:"This field is required."},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function ny({id:y,label:$,min:b=1,max:m=10,step:f=1,required:g,minLabel:B,maxLabel:k}){let{responses:W,setResponse:N}=Yy(),P=W.get(y),L=P?.value,F=P?.note||"",[O,M]=Qy(!1);Py(()=>{if(!W.has(y))N(y,{id:y,type:"range",label:$,value:null,required:g})},[y]);let Y=(U)=>{N(y,{...P,value:U})},Q=L!==null&&L!==void 0,G=Q?L:Math.round((b+m)/2),z=(G-b)/(m-b)*100,X=Math.round((m-b)/f),T=X<=20,_=P?.required&&!Q;return K("div",{"data-md":"rangeinput","data-md-label":$,className:"-mx-4 px-4 py-3 my-1 rounded-lg transition-colors duration-150 hover:bg-bg-input",children:[K("div",{className:"flex items-baseline justify-between mb-1",children:[K("div",{className:"flex items-baseline gap-2",children:[K("span",{className:"text-[13px] font-body font-medium text-text-primary",children:$},void 0,!1,void 0,this),g&&K("span",{className:"text-[10px] text-accent-red font-body",children:"*"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),K("span",{className:"flex items-center gap-1.5",children:[K("span",{className:`text-[13px] font-mono ${Q?"text-accent-amber":"text-text-disabled"}`,children:Q?L:"—"},void 0,!1,void 0,this),Q&&K("button",{onClick:()=>N(y,{...P,value:null}),className:"text-text-disabled hover:text-text-tertiary transition-colors text-[10px] leading-none",title:"Clear",children:"✕"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),K("div",{className:"relative h-6 flex items-center",children:[K("div",{className:"absolute left-0 right-0 h-1.5 rounded-full bg-border-medium",children:Q&&K("div",{className:"h-full rounded-full bg-accent-amber transition-all duration-150",style:{width:`${z}%`}},void 0,!1,void 0,this)},void 0,!1,void 0,this),T&&Array.from({length:X+1},(U,q)=>{let w=b+q*f,d=(w-b)/(m-b)*100,J=Q&&w<=L;return K("div",{className:`absolute rounded-full pointer-events-none transition-all duration-150 ${Q&&w===L?"w-2.5 h-2.5 bg-accent-amber":J?"w-1.5 h-1.5 bg-accent-amber":"w-1.5 h-1.5 bg-border-hover"}`,style:{left:`${d}%`,transform:"translate(-50%, -50%)",top:"50%"}},q,!1,void 0,this)}),Q?K("div",{className:"absolute h-5 w-5 rounded-full bg-accent-amber shadow-md pointer-events-none transition-all duration-150",style:{left:`calc(${z}% - 10px)`,borderWidth:"2px",borderStyle:"solid",borderColor:"var(--color-bg-base)"}},void 0,!1,void 0,this):K("div",{className:"absolute h-4 w-4 rounded-full bg-border-hover pointer-events-none opacity-50",style:{left:"calc(50% - 8px)",borderWidth:"2px",borderStyle:"solid",borderColor:"var(--color-bg-base)"}},void 0,!1,void 0,this),K("input",{type:"range",min:b,max:m,step:f,value:G,onChange:(U)=>Y(Number(U.target.value)),className:"absolute inset-0 w-full opacity-0 cursor-pointer"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),T&&X<=10?K("div",{className:"flex justify-between -mt-0.5 px-0",children:Array.from({length:X+1},(U,q)=>{let w=b+q*f;return K("span",{className:`text-[10px] font-mono transition-colors ${Q&&w===L?"text-accent-amber font-medium":"text-text-disabled"}`,style:{minWidth:"1ch",textAlign:"center"},children:w},q,!1,void 0,this)})},void 0,!1,void 0,this):K("div",{className:"flex justify-between -mt-0.5",children:[K("span",{className:"text-[11px] text-text-tertiary font-body",children:B||b},void 0,!1,void 0,this),K("span",{className:"text-[11px] text-text-tertiary font-body",children:k||m},void 0,!1,void 0,this)]},void 0,!0,void 0,this),K(u,{show:O,note:F,onToggle:()=>M(!O),onChange:(U)=>N(y,{...P,note:U})},void 0,!1,void 0,this),_&&K("p",{className:"text-[11px] text-accent-red font-body mt-1",children:"Please select a value."},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}import{useContext as sy,useState as ey}from"react";import{SessionContext as ym}from"#canvas/runtime";import{jsxDEV as p}from"react/jsx-dev-runtime";function mm({src:y,alt:$,caption:b,width:m,height:f}){let g=sy(ym),[B,k]=ey(!1),W=`/api/image?session=${encodeURIComponent(g)}&path=${encodeURIComponent(y)}`;if(B)return p("div",{className:"mt-3 text-accent-red text-body bg-accent-red-muted rounded-md p-4",children:[y,": Failed to load image"]},void 0,!0,void 0,this);return p("figure",{className:"mt-3 relative","data-md":"image","data-md-src":y,children:[p("div",{className:"rounded-md overflow-hidden border border-border-subtle bg-bg-code inline-block",children:p("img",{src:W,alt:$||y,onError:()=>k(!0),className:"block max-w-full h-auto",...m?{width:m}:{},...f?{height:f}:{}},void 0,!1,void 0,this)},void 0,!1,void 0,this),b&&p("figcaption",{className:"mt-1.5 text-meta text-text-tertiary font-body",children:b},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}import{useFeedback as U1}from"#canvas/runtime";export{U1 as useFeedback,ty as UserInput,Hy as Task,_y as Table,Ky as Section,ny as RangeInput,Cy as Priority,qy as Note,oy as MultiChoice,xy as Mermaid,t as Item,mm as ImageView,cy as FilePreview,Vy as Diff,Ty as CodeBlock,ay as Choice,wy as Checklist,Gy as Callout};
|
|
1
|
+
import{useState as _y}from"react";import{jsxDEV as u}from"react/jsx-dev-runtime";function Ay({title:y,children:W}){let[B,f]=_y(!1);return u("div",{className:"relative mb-8 p-4 group/section","data-md":"section","data-md-title":y,children:[u("div",{className:"relative mb-2",children:[u("button",{onClick:()=>f(!B),className:`absolute -left-8 top-1/2 -translate-y-1/2 text-text-tertiary opacity-0 group-hover/section:opacity-50 hover:!opacity-100 transition-all duration-150 p-0.5 ${B?"-rotate-90":""}`,children:u("svg",{width:"14",height:"14",viewBox:"0 0 12 12",fill:"none",children:u("path",{d:"M3 4.5L6 7.5L9 4.5",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this),u("h2",{className:"font-heading text-section text-text-primary",style:{fontWeight:400},children:y},void 0,!1,void 0,this)]},void 0,!0,void 0,this),u("div",{className:B?"mt-6 hidden":"mt-6",children:W},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}import{jsxDEV as h}from"react/jsx-dev-runtime";var Oy={todo:"bg-border-hover",done:"bg-accent-green",blocked:"bg-accent-red","in-progress":"bg-accent-blue"},gy={todo:"Todo",done:"Done",blocked:"Blocked","in-progress":"In progress"},Cy={info:"bg-accent-blue-muted text-accent-blue",success:"bg-accent-green-muted text-accent-green",warning:"bg-accent-amber-muted text-accent-amber",danger:"bg-accent-red-muted text-accent-red",neutral:"bg-border-subtle text-text-tertiary"};function Ny({id:y,label:W,status:B,badge:f,badgeVariant:N="neutral",children:$}){return h("div",{className:"group/task relative -mx-4 px-4 py-3 rounded-md transition-colors duration-150 hover:bg-bg-input","data-task-id":y,"data-md":"item","data-md-label":W,...B?{"data-md-status":B}:{},...f?{"data-md-badge":f}:{},children:h("div",{className:"flex items-start gap-3",children:[B&&h("span",{className:`w-2 h-2 rounded-full mt-[7px] flex-shrink-0 ${Oy[B]}`},void 0,!1,void 0,this),h("div",{className:"flex-1 min-w-0",children:[h("div",{className:"flex items-baseline gap-2",children:[h("span",{className:"font-body text-task-label font-semibold text-text-primary",children:W},void 0,!1,void 0,this),B&&h("span",{className:"font-body text-tiny uppercase tracking-wider text-text-tertiary opacity-0 group-hover/task:opacity-100 transition-opacity duration-150",children:gy[B]},void 0,!1,void 0,this),f&&h("span",{className:`font-body text-tiny font-medium px-1.5 py-px rounded-full ${Cy[N]}`,children:f},void 0,!1,void 0,this)]},void 0,!0,void 0,this),$&&h("div",{className:"text-body text-text-secondary mt-1 leading-relaxed",children:$},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}function Ry(y){return h(Ny,{...y},void 0,!1,void 0,this)}import{useEffect as Iy,useRef as hy}from"react";import{jsxDEV as E}from"react/jsx-dev-runtime";function Sy({language:y,children:W}){let B=typeof W==="string"?W:String(W??""),f=hy(null);return Iy(()=>{let N=f.current,$=window.hljs;if(!N||!$)return;N.removeAttribute("data-highlighted"),N.className=y?`language-${y}`:"",N.textContent=B,$.highlightElement(N)},[B,y]),E("div",{className:"relative mt-3 group/code","data-md":"codeblock","data-md-language":y||"",children:[y&&E("span",{className:"absolute top-2 right-3 text-tiny text-text-tertiary opacity-0 group-hover/code:opacity-60 transition-opacity duration-150 z-10 font-mono",children:y},void 0,!1,void 0,this),E("pre",{className:"bg-bg-code rounded-md p-4 overflow-x-auto text-code font-mono leading-relaxed",children:E("code",{ref:f,className:y?`language-${y}`:"",children:B},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}import{jsxDEV as s}from"react/jsx-dev-runtime";var ry={info:{bg:"bg-accent-blue-muted",icon:"i",iconColor:"text-accent-blue"},warning:{bg:"bg-accent-amber-muted",icon:"!",iconColor:"text-accent-amber"},danger:{bg:"bg-accent-red-muted",icon:"✕",iconColor:"text-accent-red"},tip:{bg:"bg-accent-green-muted",icon:"✓",iconColor:"text-accent-green"}};function cy({type:y="info",children:W}){let B=ry[y];return s("div",{className:`${B.bg} relative rounded-lg px-5 py-4 mt-3 flex gap-3 items-start`,"data-md":"callout","data-md-type":y,children:[s("span",{className:`${B.iconColor} opacity-70 text-base leading-relaxed flex-shrink-0 mt-px`,children:B.icon},void 0,!1,void 0,this),s("div",{className:"text-body text-text-secondary leading-relaxed",children:W},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}import{jsxDEV as py}from"react/jsx-dev-runtime";function uy({children:y}){return py("div",{className:"relative bg-bg-elevated rounded-lg px-5 py-4 mt-3 text-body text-text-secondary italic leading-relaxed","data-md":"note",children:y},void 0,!1,void 0,this)}import{jsxDEV as r}from"react/jsx-dev-runtime";function iy({headers:y,rows:W}){return r("div",{className:"overflow-x-auto mt-3","data-md":"table",children:r("table",{className:"w-full text-body",children:[r("thead",{children:r("tr",{className:"border-b border-border-subtle",children:y.map((B,f)=>r("th",{className:"text-left px-4 py-2.5 text-meta font-medium uppercase tracking-wider text-text-tertiary font-body",children:B},f,!1,void 0,this))},void 0,!1,void 0,this)},void 0,!1,void 0,this),r("tbody",{children:W.map((B,f)=>r("tr",{className:`relative border-b border-border-subtle last:border-b-0 transition-colors hover:bg-bg-surface/50 ${f%2===1?"bg-bg-surface/30":""}`,children:B.map((N,$)=>r("td",{className:"px-4 py-2.5 text-text-secondary font-body",children:N},$,!1,void 0,this))},f,!1,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)}import{jsxDEV as p}from"react/jsx-dev-runtime";function dy({items:y}){return p("ul",{className:"space-y-1 mt-3","data-md":"checklist",children:y.map((W,B)=>p("li",{"data-md":"checklist-item","data-md-label":W.label,className:"relative flex items-start gap-2.5 py-1",children:[p("span",{className:`w-4 h-4 rounded-full flex items-center justify-center flex-shrink-0 mt-0.5 transition-all ${W.checked?"bg-accent-green":"border-[1.5px] border-border-hover"}`,children:W.checked&&p("svg",{width:"10",height:"10",viewBox:"0 0 10 10",fill:"none",children:p("path",{d:"M2.5 5L4.5 7L7.5 3",style:{stroke:"var(--color-text-inverse)"},strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this),p("span",{className:`text-body font-body ${W.checked?"text-text-tertiary line-through decoration-border-hover":"text-text-secondary"}`,children:W.label},void 0,!1,void 0,this)]},B,!0,void 0,this))},void 0,!1,void 0,this)}import{jsxDEV as jy}from"react/jsx-dev-runtime";var xy={high:"text-accent-red bg-accent-red-muted",medium:"text-accent-amber bg-accent-amber-muted",low:"text-text-tertiary bg-border-subtle"};function Dy({level:y}){return jy("span",{className:`inline text-tiny font-medium font-body ml-2 px-1.5 py-0.5 rounded ${xy[y]}`,"data-md":"priority","data-md-level":y,children:y},void 0,!1,void 0,this)}import{useEffect as my,useState as a,useContext as Jy,useRef as Vy}from"react";import{SessionContext as Ey,ActiveViewCtx as ay}from"#canvas/runtime";import{jsxDEV as c}from"react/jsx-dev-runtime";var oy={ts:"typescript",tsx:"typescript",js:"javascript",jsx:"javascript",py:"python",rs:"rust",go:"go",rb:"ruby",java:"java",json:"json",yaml:"yaml",yml:"yaml",md:"markdown",css:"css",html:"html",sh:"bash",bash:"bash",toml:"toml",sql:"sql",xml:"xml",c:"c",cpp:"cpp",h:"c"};function ly({path:y,lines:W,__content:B}){let f=Jy(Ey),{setActiveView:N}=Jy(ay),[$,J]=a(B??null),[m,Y]=a(()=>{let k=y.split(".").pop()||"";return oy[k]||"text"}),[Q,K]=a(null),[b,F]=a(!B),q=Vy(null);if(my(()=>{if(B!==void 0)return;F(!0),K(null),fetch(`/api/file?session=${f}&path=${encodeURIComponent(y)}`).then((k)=>k.json()).then((k)=>{if(k.error)K(k.error);else{let U=k.content;if(W)U=U.split(`
|
|
2
|
+
`).slice(W[0]-1,W[1]).join(`
|
|
3
|
+
`);J(U),Y(k.language||"text")}}).catch(()=>K("Failed to fetch file")).finally(()=>F(!1))},[f,y,W?.[0],W?.[1],B]),my(()=>{let k=q.current,U=window.hljs;if(!k||!U||!$)return;k.removeAttribute("data-highlighted"),k.className=m?`language-${m}`:"",k.textContent=$,U.highlightElement(k)},[$,m]),b)return c("div",{className:"text-text-tertiary text-body mt-3 bg-bg-code rounded-md p-4",children:["Loading ",y,"..."]},void 0,!0,void 0,this);if(Q)return c("div",{className:"text-accent-red text-body mt-3 bg-accent-red-muted rounded-md p-4",children:[y,": ",Q]},void 0,!0,void 0,this);return c("div",{className:"mt-3 bg-bg-code rounded-md overflow-hidden","data-md":"filepreview","data-md-path":y,...W?{"data-md-lines":`${W[0]}-${W[1]}`}:{},children:[c("div",{className:"px-4 py-2 flex items-center justify-between",children:[c("button",{className:"font-mono text-meta text-text-tertiary hover:text-text-secondary hover:underline cursor-pointer text-left",onClick:()=>N({type:"file",path:y}),title:`Open ${y}`,children:y},void 0,!1,void 0,this),W&&c("span",{className:"font-mono text-meta text-text-tertiary opacity-60",children:["L",W[0],"–",W[1]]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),c("pre",{className:"px-4 pb-3 overflow-x-auto text-code font-mono !bg-transparent",style:{background:"transparent"},children:c("code",{ref:q,className:m?`language-${m}`:"",children:$},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}import{useEffect as $y,useRef as D,useState as i,useCallback as S}from"react";import sy from"react-dom";import{useAnnotations as ey}from"#canvas/runtime";import{useEffect as yy,useRef as fy,useState as e,useCallback as Wy,useMemo as Yy}from"react";import{createPortal as ty}from"react-dom";function Qy(y,W){let N=W||document.body,$=y.getBoundingClientRect(),J=N.getBoundingClientRect(),m=N===document.body?window.scrollY:N.scrollTop,Y=$.bottom-J.top+m+8,Q=Math.max(0,Math.min($.left-J.left,J.width-280-12));return N.style.position="relative",{style:{position:"absolute",top:`${Y}px`,left:`${Q}px`},parent:N}}import{jsxDEV as R}from"react/jsx-dev-runtime";function ny({anchorEl:y,scrollContainer:W,onClose:B,ignoreSelector:f,zIndex:N="50",padding:$="12px",width:J="280px",children:m}){let Y=fy(null),Q=fy(B);Q.current=B;let{style:K,parent:b}=Qy(y,W);return yy(()=>{let F=setTimeout(()=>{let q=(k)=>{if(Y.current&&!Y.current.contains(k.target)){if(f&&k.target.closest?.(f))return;Q.current(),document.removeEventListener("mousedown",q)}};return document.addEventListener("mousedown",q),()=>document.removeEventListener("mousedown",q)},0);return()=>clearTimeout(F)},[f]),ty(R("div",{ref:Y,style:{...K,zIndex:N,width:J,background:"var(--color-bg-elevated)",border:"1px solid var(--color-border-hover)",borderRadius:"8px",boxShadow:"0 4px 12px var(--color-shadow)",padding:$,fontFamily:"'Inter', sans-serif"},children:m},void 0,!1,void 0,this),b)}var Ly=[{label:"Clarity",items:["Unclear","Why?","Needs example","Missing context"]},{label:"Scope",items:["Overkill","Out of scope","Important","Risky"]},{label:"Action",items:["Simplify","Rethink","Expand on this","Skip this"]}],ky=Ly.flatMap((y)=>y.items);function by({anchorEl:y,scrollContainer:W,snippet:B,truncateAt:f=100,header:N,onAdd:$,onCancel:J}){let[m,Y]=e(""),[Q,K]=e(null),[b,F]=e(!1),q=fy(null);yy(()=>{q.current?.focus()},[]);let k=Wy(()=>{if(m.trim())$(m.trim());else J()},[m,$,J]),U=m.trim().length>0?ky.filter((L)=>L.toLowerCase().startsWith(m.trim().toLowerCase())):ky,P=b?[]:U.length===1&&U[0].toLowerCase()===m.trim().toLowerCase()?[]:U,M=new Set(P),w=Ly.map((L)=>({label:L.label,items:L.items.filter((H)=>M.has(H))})).filter((L)=>L.items.length>0),v=w.map((L)=>L.items),A=v.flat(),g=Yy(()=>{if(Q===null)return 0;let L=0;for(let H=0;H<v.length;H++){if(Q<L+v[H].length)return H;L+=v[H].length}return 0},[Q,v]),_=Yy(()=>{if(Q===null)return 0;let L=0;for(let H=0;H<g;H++)L+=v[H].length;return Q-L},[Q,g,v]),C=(L,H)=>{let Z=0;for(let O=0;O<L;O++)Z+=v[O].length;return Z+H};yy(()=>{K(null),F(!1)},[m]);let I=Wy((L)=>{Y(L)},[]),z=B.length>f?B.slice(0,f)+"...":B;return R(ny,{anchorEl:y,scrollContainer:W,onClose:J,width:"420px",children:[N??R("div",{style:{fontSize:"11px",color:"var(--color-text-tertiary)",fontStyle:"italic",marginBottom:"8px",lineHeight:"1.4",display:"-webkit-box",WebkitLineClamp:2,WebkitBoxOrient:"vertical",overflow:"hidden"},children:["“",z,"”"]},void 0,!0,void 0,this),R("textarea",{ref:q,value:m,onChange:(L)=>Y(L.target.value),onKeyDown:(L)=>{if(A.length>0&&(L.key==="ArrowDown"||L.key==="ArrowUp"||L.key==="ArrowLeft"||L.key==="ArrowRight")){if(L.preventDefault(),Q===null){K(0);return}if(L.key==="ArrowDown"){let H=Math.min(_+1,v[g].length-1);K(C(g,H))}else if(L.key==="ArrowUp"){let H=Math.max(_-1,0);K(C(g,H))}else if(L.key==="ArrowRight"){let H=Math.min(g+1,v.length-1),Z=Math.min(_,v[H].length-1);K(C(H,Z))}else if(L.key==="ArrowLeft"){let H=Math.max(g-1,0),Z=Math.min(_,v[H].length-1);K(C(H,Z))}return}if(Q!==null&&A.length>0){if(L.key==="Tab"){L.preventDefault(),I(A[Q]);return}if(L.key==="Enter"&&!L.shiftKey){L.preventDefault(),$(A[Q]);return}}if(L.key==="Enter"&&!L.shiftKey){L.preventDefault(),k();return}if(L.key==="Escape")if(A.length>0&&!b)F(!0);else J()},style:{width:"100%",minHeight:"60px",background:"transparent",border:"none",color:"var(--color-text-primary)",fontFamily:"'Inter', sans-serif",fontSize:"13px",lineHeight:"1.5",resize:"vertical",outline:"none"},placeholder:"Add your note..."},void 0,!1,void 0,this),R("div",{style:{display:"flex",justifyContent:"flex-end",gap:"8px",marginTop:"8px"},children:[R("button",{onClick:J,style:{fontSize:"11px",color:"var(--color-text-tertiary)",background:"none",border:"none",cursor:"pointer",padding:"4px 12px",fontFamily:"'Inter', sans-serif"},children:"Cancel"},void 0,!1,void 0,this),R("button",{onClick:k,style:{fontSize:"11px",fontWeight:500,padding:"4px 12px",borderRadius:"6px",background:"var(--color-highlight-bg)",color:"var(--color-text-primary)",border:"1px solid var(--color-highlight-border)",cursor:"pointer",fontFamily:"'Inter', sans-serif"},children:"Add"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A.length>0&&R("div",{style:{marginTop:"6px",borderTop:"1px solid var(--color-border-subtle)",paddingTop:"8px",display:"flex",gap:"4px"},children:w.map((L)=>R("div",{style:{flex:1},children:[R("div",{style:{fontSize:"10px",fontWeight:600,color:"var(--color-text-disabled)",textTransform:"uppercase",letterSpacing:"0.05em",padding:"2px 6px",marginBottom:"2px",fontFamily:"'Inter', sans-serif"},children:L.label},void 0,!1,void 0,this),L.items.map((H)=>{let Z=A.indexOf(H);return R("div",{onMouseDown:(O)=>{O.preventDefault(),O.stopPropagation(),I(H)},onMouseEnter:()=>K(Z),style:{padding:"3px 6px",fontSize:"12px",borderRadius:"4px",fontFamily:"'Inter', sans-serif",color:Z===Q?"var(--color-text-primary)":"var(--color-text-secondary)",background:Z===Q?"var(--color-highlight-selected)":"transparent",cursor:"pointer"},children:[R("span",{style:{fontWeight:500},children:H.slice(0,m.trim().length)},void 0,!1,void 0,this),H.slice(m.trim().length)]},H,!0,void 0,this)})]},L.label,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}import{jsxDEV as X,Fragment as Hy}from"react/jsx-dev-runtime";var d=0.2,o=0.25,l=4;function Xy({zoom:y,onZoomIn:W,onZoomOut:B,onZoomReset:f,onFullscreen:N}){return X("div",{className:"flex items-center gap-0.5 bg-bg-surface border border-border-subtle rounded-md px-1 py-0.5",style:{fontSize:"12px"},children:[X("button",{className:"flex items-center justify-center w-7 h-7 rounded hover:bg-bg-elevated text-text-secondary hover:text-text-primary transition-colors",onClick:B,title:"Zoom out",disabled:y<=o,children:X("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",children:X("line",{x1:"5",y1:"12",x2:"19",y2:"12"},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this),X("button",{className:"px-1.5 h-7 rounded hover:bg-bg-elevated text-text-tertiary hover:text-text-primary transition-colors tabular-nums",onClick:f,title:"Reset zoom",children:[Math.round(y*100),"%"]},void 0,!0,void 0,this),X("button",{className:"flex items-center justify-center w-7 h-7 rounded hover:bg-bg-elevated text-text-secondary hover:text-text-primary transition-colors",onClick:W,title:"Zoom in",disabled:y>=l,children:X("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",children:[X("line",{x1:"12",y1:"5",x2:"12",y2:"19"},void 0,!1,void 0,this),X("line",{x1:"5",y1:"12",x2:"19",y2:"12"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this),N&&X(Hy,{children:[X("div",{className:"w-px h-4 bg-border-subtle mx-0.5"},void 0,!1,void 0,this),X("button",{className:"flex items-center justify-center w-7 h-7 rounded hover:bg-bg-elevated text-text-secondary hover:text-text-primary transition-colors",onClick:N,title:"Fullscreen",children:X("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",children:[X("polyline",{points:"15 3 21 3 21 9"},void 0,!1,void 0,this),X("polyline",{points:"9 21 3 21 3 15"},void 0,!1,void 0,this),X("line",{x1:"21",y1:"3",x2:"14",y2:"10"},void 0,!1,void 0,this),X("line",{x1:"3",y1:"21",x2:"10",y2:"14"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this)}function Py(y=1){let[W,B]=i(y),f=S(()=>B((J)=>Math.min(l,+(J+d).toFixed(2))),[]),N=S(()=>B((J)=>Math.max(o,+(J-d).toFixed(2))),[]),$=S(()=>B(1),[]);return{zoom:W,zoomIn:f,zoomOut:N,zoomReset:$,setZoom:B}}function y1({svgHtml:y,source:W,onClose:B}){let f=D(null),{zoom:N,zoomIn:$,zoomOut:J,zoomReset:m,setZoom:Y}=Py(1),[Q,K]=i({x:0,y:0}),b=D(null);$y(()=>{let M=(w)=>{if(w.key==="Escape")B()};return window.addEventListener("keydown",M),()=>window.removeEventListener("keydown",M)},[B]);let F=S((M)=>{M.preventDefault();let w=M.deltaY>0?-d:d;Y((v)=>Math.max(o,Math.min(l,+(v+w).toFixed(2))))},[Y]),q=S((M)=>{if(M.button!==0)return;b.current={startX:M.clientX,startY:M.clientY,panX:Q.x,panY:Q.y},M.preventDefault()},[Q]),k=S((M)=>{if(!b.current)return;K({x:b.current.panX+(M.clientX-b.current.startX),y:b.current.panY+(M.clientY-b.current.startY)})},[]),U=S(()=>{b.current=null},[]),P=S(()=>{m(),K({x:0,y:0})},[m]);return sy.createPortal(X("div",{style:{position:"fixed",inset:0,zIndex:9999,background:"var(--color-bg-base)",display:"flex",flexDirection:"column"},onMouseMove:k,onMouseUp:U,onMouseLeave:U,children:[X("div",{className:"flex items-center justify-between px-4 py-2 border-b border-border-subtle",style:{flexShrink:0,background:"var(--color-bg-surface)"},children:[X("span",{className:"text-body text-text-secondary",style:{fontSize:"13px"},children:"Mermaid Diagram"},void 0,!1,void 0,this),X("div",{className:"flex items-center gap-2",children:[X(Xy,{zoom:N,onZoomIn:$,onZoomOut:J,onZoomReset:P},void 0,!1,void 0,this),X("button",{className:"flex items-center justify-center w-8 h-8 rounded hover:bg-bg-elevated text-text-secondary hover:text-text-primary transition-colors",onClick:B,title:"Close (Esc)",children:X("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",children:[X("line",{x1:"18",y1:"6",x2:"6",y2:"18"},void 0,!1,void 0,this),X("line",{x1:"6",y1:"6",x2:"18",y2:"18"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),X("div",{style:{flex:1,overflow:"hidden",cursor:b.current?"grabbing":"grab"},onWheel:F,onMouseDown:q,children:X("div",{ref:f,style:{width:"100%",height:"100%",display:"flex",alignItems:"center",justifyContent:"center",transform:`translate(${Q.x}px, ${Q.y}px) scale(${N})`,transformOrigin:"center center",transition:b.current?"none":"transform 0.1s ease-out"},dangerouslySetInnerHTML:{__html:y}},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),document.body)}function f1({children:y}){let W=D(null),[B,f]=i(null),[N,$]=i(!1),[J,m]=i(""),Y=typeof y==="string"?y:String(y??""),{annotations:Q,addAnnotationWithId:K,activeAnnotationId:b,setActiveAnnotationId:F}=ey(),[q,k]=i(null),{zoom:U,zoomIn:P,zoomOut:M,zoomReset:w,setZoom:v}=Py(1),A=D(Q);A.current=Q;let g=S((z,L,H)=>{let Z=`[Diagram ${H.toLowerCase()}] ${L}`,O=A.current.find((n)=>n.snippet===Z);if(O)F(O.id);else k({anchorEl:z,snippet:L,prefix:H})},[F]),_=D(g);_.current=g,$y(()=>{let z=!1,L=async()=>{try{let Z=window.mermaid;if(!Z){f("Mermaid library not loaded");return}let O=document.documentElement.dataset.theme==="light"?"default":"dark";Z.initialize({startOnLoad:!1,theme:O});let n=`mermaid-${Math.random().toString(36).slice(2)}`,{svg:By}=await Z.render(n,Y.trim());if(!z&&W.current)W.current.innerHTML=By,m(By),$1(W.current,(Zy,wy,zy)=>_.current(Zy,wy,zy)),Ky(W.current,A.current);f(null)}catch(Z){if(!z)f(Z.message||"Invalid diagram")}};L();let H=new MutationObserver((Z)=>{for(let O of Z)if(O.attributeName==="data-theme")L()});return H.observe(document.documentElement,{attributes:!0,attributeFilter:["data-theme"]}),()=>{z=!0,H.disconnect()}},[Y]),$y(()=>{if(W.current)Ky(W.current,Q,b)},[Q,b]);let C=S((z)=>{if(!z.ctrlKey&&!z.metaKey)return;z.preventDefault();let L=z.deltaY>0?-d:d;v((H)=>Math.max(o,Math.min(l,+(H+L).toFixed(2))))},[v]);if(B)return X("div",{className:"bg-accent-red-muted rounded-md p-4 mt-3 text-body text-accent-red",children:["Mermaid error: ",B,X("pre",{className:"mt-2 text-tiny text-text-tertiary whitespace-pre-wrap",children:Y},void 0,!1,void 0,this)]},void 0,!0,void 0,this);let I=W.current?.closest("#plan-scroll-container");return X(Hy,{children:[X("div",{className:"mt-3 mermaid-container","data-md":"mermaid","data-md-source":Y.trim(),children:[X("div",{className:"flex justify-end mb-1",children:X(Xy,{zoom:U,onZoomIn:P,onZoomOut:M,onZoomReset:w,onFullscreen:()=>$(!0)},void 0,!1,void 0,this)},void 0,!1,void 0,this),X("div",{style:{overflow:"auto",maxHeight:"70vh"},onWheel:C,children:X("div",{ref:W,className:"flex justify-center",style:{transform:`scale(${U})`,transformOrigin:"top center",transition:"transform 0.1s ease-out",minHeight:U<1?void 0:void 0}},void 0,!1,void 0,this)},void 0,!1,void 0,this)]},void 0,!0,void 0,this),q&&X(by,{anchorEl:q.anchorEl,scrollContainer:I,snippet:q.snippet,header:X("div",{style:{fontSize:"12px",color:"var(--color-text-tertiary)",marginBottom:"8px",lineHeight:"1.4",display:"flex",alignItems:"center",gap:"6px"},children:[X("span",{style:{width:"8px",height:"8px",borderRadius:"50%",background:"var(--color-accent-amber)",flexShrink:0}},void 0,!1,void 0,this),q.snippet]},void 0,!0,void 0,this),onAdd:(z)=>{let L=`ann-${Date.now()}-${Math.random().toString(36).slice(2,6)}`;K(L,`[Diagram ${q.prefix.toLowerCase()}] ${q.snippet}`,z),k(null)},onCancel:()=>k(null)},void 0,!1,void 0,this),N&&J&&X(y1,{svgHtml:J,source:Y,onClose:()=>$(!1)},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function $1(y,W){let B=(f,N,$)=>{f.style.cursor="pointer",f.addEventListener("mouseenter",()=>{f.style.filter="brightness(1.2)"}),f.addEventListener("mouseleave",()=>{f.style.filter=""}),f.addEventListener("click",(J)=>{J.stopPropagation(),J.preventDefault(),W(f,N(),$)})};for(let f of y.querySelectorAll(".node"))B(f,()=>{return(f.querySelector(".nodeLabel")||f.querySelector("foreignObject span")||f.querySelector("text"))?.textContent?.trim()||"Node"},"Node");for(let f of y.querySelectorAll(".edgePath")){let N=f,$=N.querySelector("path");if($){$.style.strokeWidth=Math.max(parseFloat($.style.strokeWidth||"1"),8)+"px",$.style.strokeOpacity="0";let m=$.cloneNode(!0);m.style.strokeWidth="",m.style.strokeOpacity="",N.insertBefore(m,$)}let J=N.id||"";B(N,()=>{let m=y.querySelectorAll(".edgeLabel");for(let Y of m)if(Y.id&&J&&Y.id.replace("label","").includes(J.replace("L-","").replace("edge",""))){let Q=Y.textContent?.trim();if(Q)return Q}return"Connection"},"Edge")}for(let f of y.querySelectorAll(".edgeLabel")){let N=f.textContent?.trim();if(!N)continue;B(f,()=>N,"Edge")}for(let f of y.querySelectorAll(".actor")){let N=f.closest("g")?.querySelector("text")||f.parentElement?.querySelector("text");if(!N)continue;let $=f.closest("g");if(!$||$.hasAttribute("data-clickable"))continue;$.setAttribute("data-clickable","true"),B($,()=>N.textContent?.trim()||"Participant","Node")}for(let f of y.querySelectorAll(".messageText")){let N=f.textContent?.trim();if(!N)continue;B(f,()=>N,"Edge")}for(let f of y.querySelectorAll(".entityBox")){let N=f.closest("g");if(!N||N.hasAttribute("data-clickable"))continue;let $=N.querySelector(".entityLabel");if(!$)continue;N.setAttribute("data-clickable","true"),B(N,()=>$.textContent?.trim()||"Entity","Node")}for(let f of y.querySelectorAll(".relationshipLabel")){let N=f.textContent?.trim();if(!N)continue;let J=f.closest("g")||f;if(J.hasAttribute("data-clickable"))continue;J.setAttribute("data-clickable","true"),B(J,()=>N,"Edge")}for(let f of y.querySelectorAll(".classGroup")){let N=f;if(N.hasAttribute("data-clickable"))continue;let $=N.querySelector(".classTitle, .classTitleText, text");if(!$)continue;N.setAttribute("data-clickable","true"),B(N,()=>$.textContent?.trim()||"Class","Node")}for(let f of y.querySelectorAll(".statediagram-state")){let N=f;if(N.hasAttribute("data-clickable"))continue;let $=N.querySelector(".state-title, text");if(!$)continue;N.setAttribute("data-clickable","true"),B(N,()=>$.textContent?.trim()||"State","Node")}for(let f of y.querySelectorAll(".mindmap-node")){let N=f;if(N.hasAttribute("data-clickable"))continue;let $=N.querySelector(".mindmap-node-label, text");if(!$)continue;N.setAttribute("data-clickable","true"),B(N,()=>$.textContent?.trim()||"Node","Node")}}function Ky(y,W,B){let f=new Map;for(let $ of W){let J=$.snippet.match(/^\[Diagram (?:node|edge)\] (.+)$/);if(J)f.set(J[1],$.id)}for(let $ of y.querySelectorAll("[data-annotated]"))$.style.outline="",$.style.outlineOffset="",$.style.borderRadius="",$.removeAttribute("data-annotated");if(f.size===0)return;for(let $ of y.querySelectorAll(".node")){let m=($.querySelector(".nodeLabel")||$.querySelector("foreignObject span")||$.querySelector("text"))?.textContent?.trim();if(!m||!f.has(m))continue;let Y=f.get(m),Q=$;Q.setAttribute("data-annotated",Y);let K=Y===B;Q.style.outline=K?"2px solid var(--color-highlight-border)":"2px solid var(--color-highlight-annotation)",Q.style.outlineOffset="2px",Q.style.borderRadius="4px"}for(let $ of y.querySelectorAll(".edgeLabel")){let J=$.textContent?.trim();if(!J||!f.has(J))continue;let m=f.get(J),Y=$;Y.setAttribute("data-annotated",m);let Q=m===B;Y.style.outline=Q?"2px solid var(--color-highlight-border)":"2px solid var(--color-highlight-annotation)",Y.style.outlineOffset="2px",Y.style.borderRadius="4px"}for(let $ of y.querySelectorAll(".actor")){let J=$.closest("g");if(!J)continue;let Y=J.querySelector("text")?.textContent?.trim();if(!Y||!f.has(Y))continue;if(J.hasAttribute("data-annotated"))continue;let Q=f.get(Y);J.setAttribute("data-annotated",Q);let K=Q===B,b=J.querySelector("rect");if(b)b.style.outline=K?"2px solid var(--color-highlight-border)":"2px solid var(--color-highlight-annotation)",b.style.outlineOffset="2px",b.style.borderRadius="4px"}for(let $ of y.querySelectorAll(".messageText")){let J=$.textContent?.trim();if(!J||!f.has(J))continue;let m=f.get(J),Y=$;Y.setAttribute("data-annotated",m);let Q=m===B;Y.style.outline=Q?"2px solid var(--color-highlight-border)":"2px solid var(--color-highlight-annotation)",Y.style.outlineOffset="2px",Y.style.borderRadius="4px"}let N=($,J,m)=>{for(let Y of y.querySelectorAll($)){let Q=m(Y);if(!Q||Q.hasAttribute("data-annotated"))continue;let b=Q.querySelector(J)?.textContent?.trim();if(!b||!f.has(b))continue;let F=f.get(b);Q.setAttribute("data-annotated",F);let q=F===B,k=Q.querySelector("rect, circle, ellipse, polygon")||Q;k.style.outline=q?"2px solid var(--color-highlight-border)":"2px solid var(--color-highlight-annotation)",k.style.outlineOffset="2px",k.style.borderRadius="4px"}};N(".entityBox",".entityLabel",($)=>$.closest("g"));for(let $ of y.querySelectorAll(".relationshipLabel")){let m=$.closest("g")||$;if(m.hasAttribute("data-annotated"))continue;let Y=$.textContent?.trim();if(!Y||!f.has(Y))continue;let Q=f.get(Y);m.setAttribute("data-annotated",Q);let K=Q===B;m.style.outline=K?"2px solid var(--color-highlight-border)":"2px solid var(--color-highlight-annotation)",m.style.outlineOffset="2px",m.style.borderRadius="4px"}N(".classGroup",".classTitle, .classTitleText, text",($)=>$),N(".statediagram-state",".state-title, text",($)=>$),N(".mindmap-node",".mindmap-node-label, text",($)=>$)}import{jsxDEV as j}from"react/jsx-dev-runtime";function B1({before:y,after:W,language:B}){let f=y.split(`
|
|
4
|
+
`),N=W.split(`
|
|
5
|
+
`),$=N1(f,N),J=[],m=0,Y=0,Q=0;while(m<f.length||Y<N.length)if(Q<$.length&&m<f.length&&Y<N.length&&f[m]===$[Q]&&N[Y]===$[Q])J.push({type:"same",line:f[m]}),m++,Y++,Q++;else if(m<f.length&&(Q>=$.length||f[m]!==$[Q]))J.push({type:"removed",line:f[m]}),m++;else if(Y<N.length)J.push({type:"added",line:N[Y]}),Y++;return j("div",{className:"mt-3 bg-bg-code rounded-md overflow-hidden group/diff","data-md":"diff","data-md-language":B||"",children:[B&&j("div",{className:"px-4 py-2 text-meta font-mono text-text-tertiary opacity-0 group-hover/diff:opacity-60 transition-opacity",children:["diff (",B,")"]},void 0,!0,void 0,this),j("pre",{className:"px-4 pb-3 overflow-x-auto text-code font-mono",children:J.map((K,b)=>j("div",{className:K.type==="removed"?"bg-accent-red-muted text-accent-red":K.type==="added"?"bg-accent-green-muted text-accent-green":"text-text-tertiary",children:[j("span",{className:"select-none w-6 inline-block text-center opacity-60",children:K.type==="removed"?"-":K.type==="added"?"+":" "},void 0,!1,void 0,this),K.line]},b,!0,void 0,this))},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function N1(y,W){let B=y.length,f=W.length,N=Array.from({length:B+1},()=>Array(f+1).fill(0));for(let Y=1;Y<=B;Y++)for(let Q=1;Q<=f;Q++)N[Y][Q]=y[Y-1]===W[Q-1]?N[Y-1][Q-1]+1:Math.max(N[Y-1][Q],N[Y][Q-1]);let $=[],J=B,m=f;while(J>0&&m>0)if(y[J-1]===W[m-1])$.unshift(y[J-1]),J--,m--;else if(N[J-1][m]>N[J][m-1])J--;else m--;return $}import{useEffect as t,useRef as qy,useState as Ty}from"react";import{useAnnotations as Fy}from"#canvas/runtime";import{jsxDEV as Uy}from"react/jsx-dev-runtime";function x({note:y,onChange:W}){return Uy("div",{className:"mt-1.5",children:Uy("textarea",{value:y,onChange:(B)=>W(B.target.value),className:"w-full bg-transparent text-[12px] font-body text-text-primary resize-none focus:outline-none border-none placeholder:text-text-disabled transition-colors min-h-[20px] p-0 leading-relaxed",placeholder:"Add a note...",rows:1,onInput:(B)=>{let f=B.target;f.style.height="auto",f.style.height=f.scrollHeight+"px"},ref:(B)=>{if(B)B.style.height="auto",B.style.height=B.scrollHeight+"px"}},void 0,!1,void 0,this)},void 0,!1,void 0,this)}import{jsxDEV as G}from"react/jsx-dev-runtime";function m1({id:y,label:W,options:B,required:f}){let{responses:N,setResponse:$}=Fy(),J=N.get(y),m=J?.value,Y=J?.note||"",[Q,K]=Ty(!1),b=qy(null);t(()=>{if(!N.has(y))$(y,{id:y,type:"radio",label:W,value:null,options:B,required:f})},[y]);let F=(k)=>{$(y,{...J,value:k})};t(()=>{let k=b.current;if(!k)return;let U=(P)=>{let w=P.target.closest("[data-md-label]")?.getAttribute("data-md-label");if(w&&B.includes(w))F(w)};return k.addEventListener("kb-select",U),()=>k.removeEventListener("kb-select",U)});let q=J?.required&&!m;return G("div",{ref:b,"data-md":"choice","data-md-label":W,className:"-mx-4 px-4 py-3 my-1 rounded-lg transition-colors duration-150 hover:bg-bg-input",children:[G("div",{className:"flex items-baseline gap-2 mb-2",children:[G("span",{className:"text-[13px] font-body font-medium text-text-primary",children:W},void 0,!1,void 0,this),f&&G("span",{className:"text-[10px] text-accent-red font-body",children:"*"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),G("div",{className:"space-y-1",children:B.map((k)=>G("label",{"data-md":"choice-option","data-md-label":k,onClick:()=>F(k),className:`flex items-center gap-2.5 px-3 py-2 rounded-lg cursor-pointer transition-all duration-150 ${m===k?"bg-highlight-selected":"hover:bg-bg-elevated"}`,children:[G("span",{className:`w-4 h-4 rounded-full border-[1.5px] flex items-center justify-center flex-shrink-0 transition-all ${m===k?"border-accent-amber bg-accent-amber":"border-border-strong"}`,children:m===k&&G("span",{className:"w-1.5 h-1.5 rounded-full bg-text-inverse"},void 0,!1,void 0,this)},void 0,!1,void 0,this),G("span",{className:"text-[13px] font-body text-text-secondary",children:k},void 0,!1,void 0,this)]},k,!0,void 0,this))},void 0,!1,void 0,this),G(x,{show:Q,note:Y,onToggle:()=>K(!Q),onChange:(k)=>$(y,{...J,note:k})},void 0,!1,void 0,this),q&&G("p",{className:"text-[11px] text-accent-red font-body mt-1",children:"Please select an option."},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function J1({id:y,label:W,options:B,required:f}){let{responses:N,setResponse:$}=Fy(),J=N.get(y),m=J?.value||[],Y=J?.note||"",[Q,K]=Ty(!1),b=qy(null);t(()=>{if(!N.has(y))$(y,{id:y,type:"checkbox",label:W,value:[],options:B,required:f})},[y]);let F=(k)=>{let U=m.includes(k)?m.filter((P)=>P!==k):[...m,k];$(y,{...J,value:U})};t(()=>{let k=b.current;if(!k)return;let U=(P)=>{let w=P.target.closest("[data-md-label]")?.getAttribute("data-md-label");if(w&&B.includes(w))F(w)};return k.addEventListener("kb-select",U),()=>k.removeEventListener("kb-select",U)});let q=J?.required&&m.length===0;return G("div",{ref:b,"data-md":"multichoice","data-md-label":W,className:"-mx-4 px-4 py-3 my-1 rounded-lg transition-colors duration-150 hover:bg-bg-input",children:[G("div",{className:"flex items-baseline gap-2 mb-2",children:[G("span",{className:"text-[13px] font-body font-medium text-text-primary",children:W},void 0,!1,void 0,this),f&&G("span",{className:"text-[10px] text-accent-red font-body",children:"*"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),G("div",{className:"space-y-1",children:B.map((k)=>{let U=m.includes(k);return G("label",{"data-md":"multichoice-option","data-md-label":k,onClick:()=>F(k),className:`flex items-center gap-2.5 px-3 py-2 rounded-lg cursor-pointer transition-all duration-150 ${U?"bg-highlight-selected":"hover:bg-bg-elevated"}`,children:[G("span",{className:`w-4 h-4 rounded flex items-center justify-center flex-shrink-0 transition-all ${U?"bg-accent-amber":"border-[1.5px] border-border-strong"}`,children:U&&G("svg",{width:"10",height:"10",viewBox:"0 0 10 10",fill:"none",children:G("path",{d:"M2.5 5L4.5 7L7.5 3",style:{stroke:"var(--color-text-inverse)"},strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"},void 0,!1,void 0,this)},void 0,!1,void 0,this)},void 0,!1,void 0,this),G("span",{className:"text-[13px] font-body text-text-secondary",children:k},void 0,!1,void 0,this)]},k,!0,void 0,this)})},void 0,!1,void 0,this),G(x,{show:Q,note:Y,onToggle:()=>K(!Q),onChange:(k)=>$(y,{...J,note:k})},void 0,!1,void 0,this),q&&G("p",{className:"text-[11px] text-accent-red font-body mt-1",children:"Please select at least one option."},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}import{useEffect as Gy,useRef as Q1,useState as My}from"react";import{useAnnotations as vy}from"#canvas/runtime";import{jsxDEV as T}from"react/jsx-dev-runtime";function W1({id:y,label:W,placeholder:B,multiline:f,required:N}){let{responses:$,setResponse:J}=vy(),m=$.get(y),Y=m?.value??"",Q=m?.note||"",[K,b]=My(!1),F=Q1(null);Gy(()=>{if(!$.has(y))J(y,{id:y,type:"text",label:W,value:"",required:N})},[y]);let q=(P)=>{J(y,{...m,value:P})},k=(P)=>{P.style.height="auto",P.style.height=Math.max(f?60:32,P.scrollHeight)+"px"},U=m?.required&&!Y.trim();return T("div",{"data-md":"userinput","data-md-label":W,className:"-mx-4 px-4 py-3 my-1 rounded-lg transition-colors duration-150 hover:bg-bg-input",children:[T("div",{className:"flex items-baseline gap-2 mb-2",children:[T("span",{className:"text-[13px] font-body font-medium text-text-primary",children:W},void 0,!1,void 0,this),N&&T("span",{className:"text-[10px] text-accent-red font-body",children:"*"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),T("textarea",{ref:F,value:Y,onChange:(P)=>{q(P.target.value),k(P.target)},placeholder:B||"Type your response...",rows:f?3:1,className:"w-full bg-bg-input text-[13px] font-body text-text-primary rounded-lg px-3 py-2 resize-none focus:outline-none border border-border-subtle focus:border-border-hover placeholder:text-text-tertiary transition-colors",onInput:(P)=>k(P.target),onFocus:(P)=>k(P.target)},void 0,!1,void 0,this),T(x,{show:K,note:Q,onToggle:()=>b(!K),onChange:(P)=>J(y,{...m,note:P})},void 0,!1,void 0,this),U&&T("p",{className:"text-[11px] text-accent-red font-body mt-1",children:"This field is required."},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}function Y1({id:y,label:W,min:B=1,max:f=10,step:N=1,required:$,minLabel:J,maxLabel:m}){let{responses:Y,setResponse:Q}=vy(),K=Y.get(y),b=K?.value,F=K?.note||"",[q,k]=My(!1);Gy(()=>{if(!Y.has(y))Q(y,{id:y,type:"range",label:W,value:null,required:$})},[y]);let U=(_)=>{Q(y,{...K,value:_})},P=b!==null&&b!==void 0,M=P?b:Math.round((B+f)/2),w=(M-B)/(f-B)*100,v=Math.round((f-B)/N),A=v<=20,g=K?.required&&!P;return T("div",{"data-md":"rangeinput","data-md-label":W,className:"-mx-4 px-4 py-3 my-1 rounded-lg transition-colors duration-150 hover:bg-bg-input",children:[T("div",{className:"flex items-baseline justify-between mb-1",children:[T("div",{className:"flex items-baseline gap-2",children:[T("span",{className:"text-[13px] font-body font-medium text-text-primary",children:W},void 0,!1,void 0,this),$&&T("span",{className:"text-[10px] text-accent-red font-body",children:"*"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),T("span",{className:"flex items-center gap-1.5",children:[T("span",{className:`text-[13px] font-mono ${P?"text-accent-amber":"text-text-disabled"}`,children:P?b:"—"},void 0,!1,void 0,this),P&&T("button",{onClick:()=>Q(y,{...K,value:null}),className:"text-text-disabled hover:text-text-tertiary transition-colors text-[10px] leading-none",title:"Clear",children:"✕"},void 0,!1,void 0,this)]},void 0,!0,void 0,this)]},void 0,!0,void 0,this),T("div",{className:"relative h-6 flex items-center",children:[T("div",{className:"absolute left-0 right-0 h-1.5 rounded-full bg-border-medium",children:P&&T("div",{className:"h-full rounded-full bg-accent-amber transition-all duration-150",style:{width:`${w}%`}},void 0,!1,void 0,this)},void 0,!1,void 0,this),A&&Array.from({length:v+1},(_,C)=>{let I=B+C*N,z=(I-B)/(f-B)*100,L=P&&I<=b;return T("div",{className:`absolute rounded-full pointer-events-none transition-all duration-150 ${P&&I===b?"w-2.5 h-2.5 bg-accent-amber":L?"w-1.5 h-1.5 bg-accent-amber":"w-1.5 h-1.5 bg-border-hover"}`,style:{left:`${z}%`,transform:"translate(-50%, -50%)",top:"50%"}},C,!1,void 0,this)}),P?T("div",{className:"absolute h-5 w-5 rounded-full bg-accent-amber shadow-md pointer-events-none transition-all duration-150",style:{left:`calc(${w}% - 10px)`,borderWidth:"2px",borderStyle:"solid",borderColor:"var(--color-bg-base)"}},void 0,!1,void 0,this):T("div",{className:"absolute h-4 w-4 rounded-full bg-border-hover pointer-events-none opacity-50",style:{left:"calc(50% - 8px)",borderWidth:"2px",borderStyle:"solid",borderColor:"var(--color-bg-base)"}},void 0,!1,void 0,this),T("input",{type:"range",min:B,max:f,step:N,value:M,onChange:(_)=>U(Number(_.target.value)),className:"absolute inset-0 w-full opacity-0 cursor-pointer"},void 0,!1,void 0,this)]},void 0,!0,void 0,this),A&&v<=10?T("div",{className:"flex justify-between -mt-0.5 px-0",children:Array.from({length:v+1},(_,C)=>{let I=B+C*N;return T("span",{className:`text-[10px] font-mono transition-colors ${P&&I===b?"text-accent-amber font-medium":"text-text-disabled"}`,style:{minWidth:"1ch",textAlign:"center"},children:I},C,!1,void 0,this)})},void 0,!1,void 0,this):T("div",{className:"flex justify-between -mt-0.5",children:[T("span",{className:"text-[11px] text-text-tertiary font-body",children:J||B},void 0,!1,void 0,this),T("span",{className:"text-[11px] text-text-tertiary font-body",children:m||f},void 0,!1,void 0,this)]},void 0,!0,void 0,this),T(x,{show:q,note:F,onToggle:()=>k(!q),onChange:(_)=>Q(y,{...K,note:_})},void 0,!1,void 0,this),g&&T("p",{className:"text-[11px] text-accent-red font-body mt-1",children:"Please select a value."},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}import{useContext as k1,useState as L1}from"react";import{SessionContext as b1}from"#canvas/runtime";import{jsxDEV as V}from"react/jsx-dev-runtime";function K1({src:y,alt:W,caption:B,width:f,height:N}){let $=k1(b1),[J,m]=L1(!1),Y=`/api/image?session=${encodeURIComponent($)}&path=${encodeURIComponent(y)}`;if(J)return V("div",{className:"mt-3 text-accent-red text-body bg-accent-red-muted rounded-md p-4",children:[y,": Failed to load image"]},void 0,!0,void 0,this);return V("figure",{className:"mt-3 relative","data-md":"image","data-md-src":y,children:[V("div",{className:"rounded-md overflow-hidden border border-border-subtle bg-bg-code inline-block",children:V("img",{src:Y,alt:W||y,onError:()=>m(!0),className:"block max-w-full h-auto",...f?{width:f}:{},...N?{height:N}:{}},void 0,!1,void 0,this)},void 0,!1,void 0,this),B&&V("figcaption",{className:"mt-1.5 text-meta text-text-tertiary font-body",children:B},void 0,!1,void 0,this)]},void 0,!0,void 0,this)}import{useFeedback as c0}from"#canvas/runtime";export{c0 as useFeedback,W1 as UserInput,Ry as Task,iy as Table,Ay as Section,Y1 as RangeInput,Dy as Priority,uy as Note,J1 as MultiChoice,f1 as Mermaid,Ny as Item,K1 as ImageView,ly as FilePreview,B1 as Diff,Sy as CodeBlock,m1 as Choice,dy as Checklist,cy as Callout};
|
package/daemon/src/server.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { join, resolve, dirname } from "path";
|
|
2
2
|
import { readdir } from "fs/promises";
|
|
3
|
+
import { writeFileSync, mkdirSync } from "fs";
|
|
4
|
+
import { tmpdir } from "os";
|
|
3
5
|
import { DATA_DIR } from "./paths";
|
|
4
6
|
import { SessionManager } from "./session";
|
|
5
7
|
import { compilePlan } from "./compiler";
|
|
@@ -7,6 +9,11 @@ import { watchSession } from "./watcher";
|
|
|
7
9
|
import { LANG_MAP } from "../langMap";
|
|
8
10
|
|
|
9
11
|
const PORT = parseInt(process.env.CANVAS_PORT || "19400", 10);
|
|
12
|
+
|
|
13
|
+
// Write PID file so CLI can find and stop us
|
|
14
|
+
const pidDir = join(tmpdir(), "agent-canvas");
|
|
15
|
+
mkdirSync(pidDir, { recursive: true });
|
|
16
|
+
writeFileSync(join(pidDir, "daemon.pid"), String(process.pid));
|
|
10
17
|
const sessionManager = new SessionManager();
|
|
11
18
|
|
|
12
19
|
function jsonResponse(data: unknown, status = 200): Response {
|
|
@@ -26,8 +33,9 @@ function corsHeaders(headers: Record<string, string> = {}): Record<string, strin
|
|
|
26
33
|
}
|
|
27
34
|
|
|
28
35
|
// WebSocket connections
|
|
29
|
-
|
|
30
|
-
const
|
|
36
|
+
type WS<T = undefined> = import("bun").ServerWebSocket<T>;
|
|
37
|
+
const browserSockets = new Map<string, Set<WS<{ type: string; sessionId: string }>>>();
|
|
38
|
+
const waitSockets = new Map<string, Set<WS<{ type: string; sessionId: string }>>>();
|
|
31
39
|
|
|
32
40
|
type WSData = { type: "browser" | "wait"; sessionId: string };
|
|
33
41
|
|
|
@@ -94,6 +102,7 @@ const server = Bun.serve<WSData>({
|
|
|
94
102
|
if (path === "/api/sessions" && req.method === "GET") {
|
|
95
103
|
return jsonResponse(sessionManager.list().map((s) => ({
|
|
96
104
|
id: s.id,
|
|
105
|
+
projectRoot: s.projectRoot,
|
|
97
106
|
currentRevision: s.currentRevision,
|
|
98
107
|
updatedAt: s.updatedAt,
|
|
99
108
|
})));
|
package/hooks/session-start.sh
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
# Injects CANVAS_SESSION_ID and CANVAS_PROJECT_ROOT into Claude Code environment.
|
|
3
3
|
# Called by Claude Code's SessionStart hook.
|
|
4
|
-
INPUT=$(cat /dev/stdin)
|
|
5
|
-
SESSION_ID=$(echo "$INPUT" | grep -o '"session_id":"[^"]*"' | cut -d'"' -f4)
|
|
6
|
-
CWD=$(echo "$INPUT" | grep -o '"cwd":"[^"]*"' | cut -d'"' -f4)
|
|
7
4
|
|
|
8
|
-
if [ -n "$
|
|
5
|
+
if [ -n "$CLAUDE_ENV_FILE" ]; then
|
|
6
|
+
# Extract session ID from CLAUDE_ENV_FILE path:
|
|
7
|
+
# /home/.../.claude/session-env/<SESSION_ID>/sessionstart-hook-0.sh
|
|
8
|
+
SESSION_ID=$(basename "$(dirname "$CLAUDE_ENV_FILE")")
|
|
9
|
+
CWD="${CLAUDE_PROJECT_DIR:-$(pwd)}"
|
|
10
|
+
|
|
9
11
|
echo "export CANVAS_SESSION_ID=$SESSION_ID" >> "$CLAUDE_ENV_FILE"
|
|
10
12
|
echo "export CANVAS_PROJECT_ROOT=$CWD" >> "$CLAUDE_ENV_FILE"
|
|
11
13
|
fi
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-canvas",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Interactive visual canvas for Claude Code — rich annotatable documents in the browser",
|
|
5
5
|
"bin": {
|
|
6
6
|
"agent-canvas": "bin/agent-canvas.js"
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
],
|
|
18
18
|
"scripts": {
|
|
19
19
|
"build": "bun daemon/build.ts",
|
|
20
|
+
"typecheck": "tsc --noEmit && tsc --noEmit -p daemon/tsconfig.json",
|
|
20
21
|
"prepublishOnly": "bun daemon/build.ts"
|
|
21
22
|
},
|
|
22
23
|
"dependencies": {
|
|
@@ -25,9 +26,11 @@
|
|
|
25
26
|
},
|
|
26
27
|
"devDependencies": {
|
|
27
28
|
"@tailwindcss/cli": "4",
|
|
29
|
+
"@types/bun": "^1.3.10",
|
|
28
30
|
"@types/react": "^18.3.12",
|
|
29
31
|
"@types/react-dom": "^18.3.1",
|
|
30
|
-
"tailwindcss": "4"
|
|
32
|
+
"tailwindcss": "4",
|
|
33
|
+
"typescript": "^5.9.3"
|
|
31
34
|
},
|
|
32
35
|
"repository": {
|
|
33
36
|
"type": "git",
|
package/skills/canvas/SKILL.md
CHANGED
|
@@ -23,10 +23,10 @@ Canvas opens a rich, annotatable document in the user's browser. You write JSX,
|
|
|
23
23
|
|
|
24
24
|
### Writing a Canvas
|
|
25
25
|
|
|
26
|
-
Use the **Write** tool to create a `.jsx` file in `.claude/canvas/`:
|
|
26
|
+
Use the **Write** tool to create a `.jsx` file in `.claude/agent-canvas/`:
|
|
27
27
|
|
|
28
28
|
```jsx
|
|
29
|
-
// Write to: .claude/canvas/plan.jsx
|
|
29
|
+
// Write to: .claude/agent-canvas/plan.jsx
|
|
30
30
|
|
|
31
31
|
<Section title="Authentication Redesign">
|
|
32
32
|
A proposal to replace session-based auth with JWT tokens.
|
|
@@ -50,10 +50,10 @@ Components are auto-available — no imports needed. The file is a JSX fragment
|
|
|
50
50
|
After writing the file, push it to open the canvas in the browser:
|
|
51
51
|
|
|
52
52
|
```bash
|
|
53
|
-
bunx agent-canvas push .claude/canvas/plan.jsx --label "Implementation Plan"
|
|
53
|
+
bunx agent-canvas push .claude/agent-canvas/plan.jsx --label "Implementation Plan"
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
-
This opens the canvas in the user's browser (first time) and exits immediately. The round label defaults to the filename if `--label` is omitted.
|
|
56
|
+
This opens the canvas in the user's browser (first time) and exits immediately. The round label defaults to the filename if `--label` is omitted. **Always show the `browserUrl` from the push output to the user** so they can open the canvas manually if auto-open didn't work.
|
|
57
57
|
|
|
58
58
|
### Waiting for feedback
|
|
59
59
|
|
|
@@ -65,12 +65,14 @@ bunx agent-canvas wait
|
|
|
65
65
|
|
|
66
66
|
This **blocks until the user submits feedback**, then prints feedback markdown to stdout. If feedback was already submitted (e.g. retrying after a disconnect), it returns immediately with the existing feedback.
|
|
67
67
|
|
|
68
|
+
> **Note:** If `push` outputs a warning "CANVAS_SESSION_ID not set, using generated ID: ...", you must pass that ID to wait: `bunx agent-canvas wait --session <id>`
|
|
69
|
+
|
|
68
70
|
### Iterating
|
|
69
71
|
|
|
70
72
|
Use the **Edit** tool to modify the existing JSX based on feedback — targeted edits, not full rewrites. Then push and wait again:
|
|
71
73
|
|
|
72
74
|
```bash
|
|
73
|
-
bunx agent-canvas push .claude/canvas/plan.jsx --label "Implementation Plan (revised)"
|
|
75
|
+
bunx agent-canvas push .claude/agent-canvas/plan.jsx --label "Implementation Plan (revised)"
|
|
74
76
|
bunx agent-canvas wait
|
|
75
77
|
```
|
|
76
78
|
|
|
@@ -81,19 +83,19 @@ Each push creates a new **round** — the user sees previous rounds and their fe
|
|
|
81
83
|
Maintain separate files for different phases:
|
|
82
84
|
|
|
83
85
|
```bash
|
|
84
|
-
bunx agent-canvas push .claude/canvas/discovery.jsx --label "Discovery"
|
|
86
|
+
bunx agent-canvas push .claude/agent-canvas/discovery.jsx --label "Discovery"
|
|
85
87
|
bunx agent-canvas wait
|
|
86
88
|
# ... process feedback ...
|
|
87
|
-
bunx agent-canvas push .claude/canvas/requirements.jsx --label "Requirements"
|
|
89
|
+
bunx agent-canvas push .claude/agent-canvas/requirements.jsx --label "Requirements"
|
|
88
90
|
bunx agent-canvas wait
|
|
89
91
|
# ... process feedback ...
|
|
90
|
-
bunx agent-canvas push .claude/canvas/plan.jsx --label "Implementation Plan"
|
|
92
|
+
bunx agent-canvas push .claude/agent-canvas/plan.jsx --label "Implementation Plan"
|
|
91
93
|
bunx agent-canvas wait
|
|
92
94
|
```
|
|
93
95
|
|
|
94
96
|
### File Location
|
|
95
97
|
|
|
96
|
-
All canvas files go in `.claude/canvas/` within the project root. Add `.claude/canvas/` to `.gitignore` — these are ephemeral working files.
|
|
98
|
+
All canvas files go in `.claude/agent-canvas/` within the project root. Add `.claude/agent-canvas/` to `.gitignore` — these are ephemeral working files.
|
|
97
99
|
|
|
98
100
|
## Choosing a Flow
|
|
99
101
|
|
|
@@ -127,8 +129,8 @@ User wants to make a decision?
|
|
|
127
129
|
|
|
128
130
|
1. **Determine flow** from user intent
|
|
129
131
|
2. **Announce** briefly: "I'll start with discovery, then create a detailed plan."
|
|
130
|
-
3. **Write canvas JSX** with the Write tool to `.claude/canvas/<name>.jsx`
|
|
131
|
-
4. **Push**: `bunx agent-canvas push .claude/canvas/<name>.jsx --label "<Label>"`
|
|
132
|
+
3. **Write canvas JSX** with the Write tool to `.claude/agent-canvas/<name>.jsx`
|
|
133
|
+
4. **Push**: `bunx agent-canvas push .claude/agent-canvas/<name>.jsx --label "<Label>"`
|
|
132
134
|
5. **Tell the user** the canvas is ready for review (they see it in their browser)
|
|
133
135
|
6. **Wait**: `bunx agent-canvas wait` — this blocks until the user submits feedback
|
|
134
136
|
7. **Read feedback** — check for annotations, answers, added context files, approval
|
|
@@ -163,7 +165,7 @@ Then interview deeply in each selected area across subsequent rounds. Or ask in
|
|
|
163
165
|
|
|
164
166
|
## Important Rules
|
|
165
167
|
|
|
166
|
-
- **Write** canvas files to `.claude/canvas/` using the Write tool. Never use bash heredocs or cat.
|
|
168
|
+
- **Write** canvas files to `.claude/agent-canvas/` using the Write tool. Never use bash heredocs or cat.
|
|
167
169
|
- **Edit** canvas files using the Edit tool. Never rewrite entire files — make targeted edits.
|
|
168
170
|
- JSX can be a fragment (just tags) or a full module with `export default function Canvas()`.
|
|
169
171
|
- Every `<Item>` and interactive component needs a unique `id`.
|
|
@@ -100,6 +100,15 @@ Inline code block with syntax highlighting. For code that's part of the narrativ
|
|
|
100
100
|
**Props:**
|
|
101
101
|
- `language` (string) — syntax highlighting language
|
|
102
102
|
|
|
103
|
+
### `<ImageView src="string">`
|
|
104
|
+
|
|
105
|
+
Displays an image from the project directory.
|
|
106
|
+
|
|
107
|
+
```jsx
|
|
108
|
+
<ImageView src="docs/architecture.png" />
|
|
109
|
+
<ImageView src="screenshots/before.png" alt="Before refactor" caption="Current state" width={600} />
|
|
110
|
+
```
|
|
111
|
+
|
|
103
112
|
### `<Diff before="string" after="string">`
|
|
104
113
|
|
|
105
114
|
Shows a diff view between two code snippets.
|
package/skills/canvas/flows.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Each flow is a sequence of canvas rounds. Phases can be skipped or combined based on context.
|
|
4
4
|
|
|
5
|
-
**Tooling reminder**: Write all `.jsx` files using the **Write** tool to `.claude/canvas/`. Edit them with the **Edit** tool. Push with `bunx agent-canvas push .claude/canvas/<file>.jsx --label "<Label>"`, then `bunx agent-canvas wait` to block for feedback. The JSX blocks below show what to write — they are the file content, not bash commands.
|
|
5
|
+
**Tooling reminder**: Write all `.jsx` files using the **Write** tool to `.claude/agent-canvas/`. Edit them with the **Edit** tool. Push with `bunx agent-canvas push .claude/agent-canvas/<file>.jsx --label "<Label>"`, then `bunx agent-canvas wait` to block for feedback. The JSX blocks below show what to write — they are the file content, not bash commands.
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -16,7 +16,7 @@ Each flow is a sequence of canvas rounds. Phases can be skipped or combined base
|
|
|
16
16
|
|
|
17
17
|
Goal: understand scope, constraints, and user expectations. Start broad, go deep.
|
|
18
18
|
|
|
19
|
-
Write to `.claude/canvas/discovery.jsx`, then push and wait:
|
|
19
|
+
Write to `.claude/agent-canvas/discovery.jsx`, then push and wait:
|
|
20
20
|
|
|
21
21
|
```jsx
|
|
22
22
|
<Section title="Discovery: [Feature Name]">
|