@spencerboucher/switchyard 0.4.0 → 0.6.0
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/README.md +8 -5
- package/dist/bridge/pi-model.js +44 -0
- package/dist/bridge/switchyard-bridge.js +24 -2
- package/dist/bridge/switchyard-terminal.js +608 -0
- package/dist/switchyard.mjs +3811 -1811
- package/dist/terminal/holder.js +305 -0
- package/package.json +6 -3
- package/web-dist/assets/{AutomationView-BhEfjAtI.js → AutomationView-DgZn3ltn.js} +2 -2
- package/web-dist/assets/{AutomationView-BhEfjAtI.js.map → AutomationView-DgZn3ltn.js.map} +1 -1
- package/web-dist/assets/{InteractionCard-DxEZUNrD.js → InteractionCard-cvPWKSu1.js} +2 -2
- package/web-dist/assets/{InteractionCard-DxEZUNrD.js.map → InteractionCard-cvPWKSu1.js.map} +1 -1
- package/web-dist/assets/{Menu-C4GUY_ym.js → Menu-GymfuHGP.js} +2 -2
- package/web-dist/assets/Menu-GymfuHGP.js.map +1 -0
- package/web-dist/assets/{Overlay-C-GqmwUn.js → Overlay-oYnnwvFM.js} +2 -2
- package/web-dist/assets/{Overlay-C-GqmwUn.js.map → Overlay-oYnnwvFM.js.map} +1 -1
- package/web-dist/assets/{attention-Dzqdk9Gz.js → attention-Bxg9W15n.js} +2 -2
- package/web-dist/assets/{attention-Dzqdk9Gz.js.map → attention-Bxg9W15n.js.map} +1 -1
- package/web-dist/assets/{automations-DzTTwxBl.js → automations-DdB97dnL.js} +2 -2
- package/web-dist/assets/{automations-DzTTwxBl.js.map → automations-DdB97dnL.js.map} +1 -1
- package/web-dist/assets/{board-C5mG_8rg.js → board-s4LuDPcg.js} +2 -2
- package/web-dist/assets/{board-C5mG_8rg.js.map → board-s4LuDPcg.js.map} +1 -1
- package/web-dist/assets/code-B0KXn7lD.js +8 -0
- package/web-dist/assets/code-B0KXn7lD.js.map +1 -0
- package/web-dist/assets/{describe-BbCZVvJP.js → describe-C_3FJuSs.js} +2 -2
- package/web-dist/assets/{describe-BbCZVvJP.js.map → describe-C_3FJuSs.js.map} +1 -1
- package/web-dist/assets/dist-Bgkh2hc5.js +56 -0
- package/web-dist/assets/dist-Bgkh2hc5.js.map +1 -0
- package/web-dist/assets/{enroll-DWJANJtw.js → enroll-DijmoolY.js} +2 -2
- package/web-dist/assets/{enroll-DWJANJtw.js.map → enroll-DijmoolY.js.map} +1 -1
- package/web-dist/assets/index-C5n2QB-Y.css +2 -0
- package/web-dist/assets/{index-afOJ8NRR.js → index-Cf6ZUCfK.js} +3 -3
- package/web-dist/assets/{index-afOJ8NRR.js.map → index-Cf6ZUCfK.js.map} +1 -1
- package/web-dist/assets/{more-B6qxC6M-.js → more-CRGJsz6E.js} +2 -2
- package/web-dist/assets/{more-B6qxC6M-.js.map → more-CRGJsz6E.js.map} +1 -1
- package/web-dist/assets/{now-BOWxgbt3.js → now-D6lDofYy.js} +2 -2
- package/web-dist/assets/{now-BOWxgbt3.js.map → now-D6lDofYy.js.map} +1 -1
- package/web-dist/assets/{settings-BpkmIv_4.js → settings-Csal1F-W.js} +6 -6
- package/web-dist/assets/settings-Csal1F-W.js.map +1 -0
- package/web-dist/assets/{useNow-D9Zxr5Jb.js → useNow-Bc_NlDY3.js} +2 -2
- package/web-dist/assets/{useNow-D9Zxr5Jb.js.map → useNow-Bc_NlDY3.js.map} +1 -1
- package/web-dist/index.html +2 -2
- package/web-dist/sw.js +1 -1
- package/web-dist/assets/Menu-C4GUY_ym.js.map +0 -1
- package/web-dist/assets/code-9shyh1Gw.js +0 -8
- package/web-dist/assets/code-9shyh1Gw.js.map +0 -1
- package/web-dist/assets/dist-PaQekTP8.js +0 -56
- package/web-dist/assets/dist-PaQekTP8.js.map +0 -1
- package/web-dist/assets/index-ByiuDoG0.css +0 -2
- package/web-dist/assets/settings-BpkmIv_4.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{_ as e,i as t,m as n,n as r,t as i}from"./jsx-runtime-D13aM9HY.js";import{G as a,P as o,U as s,W as c,h as l,l as u,n as d,p as f}from"./states-DrTQuYXw.js";import{n as p}from"./server-SxFxIScj.js";import{t as m}from"./chevron-right-evVLS6hq.js";import{A as h,C as g,I as _,d as v}from"./index-
|
|
1
|
+
import{_ as e,i as t,m as n,n as r,t as i}from"./jsx-runtime-D13aM9HY.js";import{G as a,P as o,U as s,W as c,h as l,l as u,n as d,p as f}from"./states-DrTQuYXw.js";import{n as p}from"./server-SxFxIScj.js";import{t as m}from"./chevron-right-evVLS6hq.js";import{A as h,C as g,I as _,d as v}from"./index-Cf6ZUCfK.js";import{n as y,t as b}from"./TextArea-BsQHOQMe.js";import{i as x,n as S,r as C,t as w}from"./Markdown-jXkvZeRp.js";import{d as T}from"./dist-Bgkh2hc5.js";var E={name:`file-code`,size:24,node:[[`path`,{d:`M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z`,key:`1oefj6`}],[`path`,{d:`M14 2v5a1 1 0 0 0 1 1h5`,key:`wfsgrz`}],[`path`,{d:`M10 12.5 8 15l2 2.5`,key:`1tg20x`}],[`path`,{d:`m14 12.5 2 2.5-2 2.5`,key:`yinavb`}]]};E.node;var D=r(E),O=e(n(),1),k=(0,O.createContext)({}),A=()=>(0,O.useContext)(k),j=i();function M({node:e}){let{onRespond:t,busy:n,disabled:r}=A();return(0,j.jsxs)(`div`,{className:`flex flex-col gap-3`,children:[(0,j.jsx)(w,{text:e.message}),!r&&(0,j.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,j.jsx)(u,{variant:e.destructive?`danger`:`primary`,busy:n,onClick:()=>t?.({kind:`confirm`,confirmed:!0}),children:e.confirmLabel||`Confirm`}),(0,j.jsx)(u,{disabled:n,onClick:()=>t?.({kind:`confirm`,confirmed:!1}),children:e.cancelLabel||`Cancel`})]})]})}function N(e){let t=e.trim().split(` `)[0];return t===`/dev/null`?null:t.replace(/^[ab]\//,``)}var P=/^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/;function F(e){let t=[],n=null,r=0,i=0,a=0,o=0,s=!1,c=()=>{a<=0&&o<=0&&(s=!1)},l=(e=``)=>{let n={path:e,oldPath:null,newPath:null,status:`modified`,additions:0,deletions:0,lines:[]};return t.push(n),s=!1,n},u=e.replace(/\r\n/g,`
|
|
2
2
|
`).split(`
|
|
3
3
|
`);u[u.length-1]===``&&u.pop();for(let e of u){if(e.startsWith(`diff --git `)){let t=/^diff --git a\/(.+?) b\/(.+)$/.exec(e);n=l(t?.[2]??``),t&&(n.oldPath=t[1],n.newPath=t[2]);continue}if(!s&&e.startsWith(`--- `)){(!n||n.lines.some(e=>e.kind!==`meta`))&&(n=l()),n.oldPath=N(e.slice(4)),n.oldPath===null&&(n.status=`added`);continue}if(!s&&e.startsWith(`+++ `)&&n){n.newPath=N(e.slice(4)),n.newPath===null&&(n.status=`deleted`),n.path=n.newPath??n.oldPath??n.path;continue}let t=P.exec(e);t?(n||=l(),r=Number(t[1]),i=Number(t[3]),a=t[2]===void 0?1:Number(t[2]),o=t[4]===void 0?1:Number(t[4]),s=a>0||o>0,n.lines.push({kind:`hunk`,text:e,oldLine:null,newLine:null})):(n||=l(),s&&e.startsWith(`+`)?(n.lines.push({kind:`add`,text:e.slice(1),oldLine:null,newLine:i++}),n.additions++,o--,c()):s&&e.startsWith(`-`)?(n.lines.push({kind:`del`,text:e.slice(1),oldLine:r++,newLine:null}),n.deletions++,a--,c()):s&&(e.startsWith(` `)||e===``)?(n.lines.push({kind:`context`,text:e.slice(1),oldLine:r++,newLine:i++}),a--,o--,c()):(e.startsWith(`\\`)||(s=!1,e.startsWith(`new file mode`)?n.status=`added`:e.startsWith(`deleted file mode`)?n.status=`deleted`:e.startsWith(`rename from `)?(n.status=`renamed`,n.oldPath=e.slice(12)):e.startsWith(`rename to `)?(n.status=`renamed`,n.newPath=e.slice(10),n.path=n.newPath):e.startsWith(`Binary files`)&&(n.status=`binary`)),n.lines.push({kind:`meta`,text:e,oldLine:null,newLine:null})))}return t}var I={add:`+`,del:`-`,context:` `,hunk:``,meta:``},ee={add:`bg-diff-add`,del:`bg-diff-del`,hunk:`bg-diff-hunk`,context:`bg-surface`,meta:`bg-surface`};function L({patch:e,files:t,showFileHeaders:n=!0,onLineClick:r,isLineMarked:i,className:a}){let o=(0,O.useMemo)(()=>t??F(e??``),[t,e]);return o.length===0?(0,j.jsx)(`p`,{className:`text-sm text-muted`,children:`No changes.`}):(0,j.jsx)(`div`,{className:l(`flex min-w-0 flex-col gap-3`,a),children:o.map((e,t)=>(0,j.jsxs)(`section`,{className:`min-w-0 overflow-hidden rounded-md border border-border`,"aria-label":`Diff of ${e.path||`file`}`,children:[n&&(0,j.jsxs)(`header`,{className:`flex min-w-0 items-center gap-2 border-b border-border bg-surface-2 px-3 py-1.5 text-sm`,children:[(0,j.jsx)(`span`,{className:`min-w-0 flex-1 truncate font-mono`,title:e.path,children:e.status===`renamed`&&e.oldPath?`${e.oldPath} → ${e.path}`:e.path}),(0,j.jsxs)(`span`,{className:`shrink-0 font-mono text-xs`,children:[(0,j.jsxs)(`span`,{className:`text-success`,children:[`+`,e.additions,(0,j.jsx)(`span`,{className:`sr-only`,children:` added`})]}),` `,(0,j.jsxs)(`span`,{className:`text-danger`,children:[`-`,e.deletions,(0,j.jsx)(`span`,{className:`sr-only`,children:` deleted`})]})]})]}),e.status===`binary`?(0,j.jsx)(`p`,{className:`px-3 py-2 text-sm text-muted`,children:`Binary file not shown.`}):(0,j.jsx)(`div`,{className:`max-w-full overflow-x-auto overscroll-x-contain`,children:(0,j.jsx)(`table`,{className:`w-full border-collapse font-mono text-xs leading-5`,children:(0,j.jsx)(`tbody`,{children:e.lines.map((t,n)=>{let a={file:e.path,line:t},o=!!r&&(t.kind===`add`||t.kind===`del`||t.kind===`context`),s=i?.(a)??!1;return(0,j.jsxs)(`tr`,{className:l(t.kind===`add`&&`bg-diff-add`,t.kind===`del`&&`bg-diff-del`,t.kind===`hunk`&&`bg-diff-hunk text-muted`,t.kind===`meta`&&`text-muted`,s&&`outline outline-1 -outline-offset-1 outline-warning`),children:[(0,j.jsx)(`td`,{className:l(`sticky left-0 z-[1] w-[6.25rem] min-w-[6.25rem] select-none whitespace-nowrap p-0`,ee[t.kind]),children:(0,j.jsxs)(`span`,{className:`flex`,children:[(0,j.jsx)(`span`,{className:`w-10 shrink-0 border-r border-border px-1.5 text-right text-subtle tabular-nums`,children:t.oldLine??``}),(0,j.jsx)(`span`,{className:`w-10 shrink-0 border-r border-border px-1.5 text-right text-subtle tabular-nums`,children:t.newLine??``}),(0,j.jsx)(`span`,{"aria-hidden":!0,className:l(`w-5 shrink-0 text-center`,t.kind===`add`&&`text-success`,t.kind===`del`&&`text-danger`),children:I[t.kind]}),(t.kind===`add`||t.kind===`del`)&&(0,j.jsx)(`span`,{className:`sr-only`,children:t.kind===`add`?`added`:`deleted`})]})}),(0,j.jsx)(`td`,{className:`whitespace-pre pr-3`,children:o?(0,j.jsx)(`button`,{type:`button`,"data-diff-line":t.newLine??t.oldLine??void 0,className:`block w-full scroll-ml-[6.25rem] cursor-pointer text-left whitespace-pre hover:underline focus-visible:underline`,onMouseDown:e=>e.preventDefault(),onClick:e=>{e.currentTarget.focus({preventScroll:!0}),r?.(a)},"aria-label":`Comment on line ${t.newLine??t.oldLine}`,children:t.text||` `}):t.text})]},n)})})})})]},`${e.path}-${t}`))})}function te(e){let t={};for(let n of e)t[n.name]={selected:[],otherChosen:!1,otherText:``,text:n.kind===`text`?n.prefill??``:``};return t}function R(e,t){if(t)switch(e.kind){case`text`:return t.text;case`select`:return t.otherChosen?{other:t.otherText}:t.selected[0];case`multiselect`:{let e=[...t.selected];return t.otherChosen&&t.otherText.trim()&&e.push(t.otherText.trim()),e}}}function z(e,t){let n={},r=[];for(let i of e)T(i,n)&&(r.push(i),n[i.name]=R(i,t[i.name]));return r}function B(e,t){let n={};for(let r of z(e,t)){let e=R(r,t[r.name]);e!==void 0&&(n[r.name]=e)}return n}function V(e,t){let n={};for(let r of z(e,t)){let e=t[r.name];if(e){if(r.kind===`select`)e.otherChosen?e.otherText.trim()||(n[r.name]=`Enter a value or choose an option`):e.selected.length===0&&(n[r.name]=`Choose an option`);else if(r.kind===`multiselect`){let t=e.selected.length+(e.otherChosen&&e.otherText.trim()?1:0);e.otherChosen&&!e.otherText.trim()?n[r.name]=`Enter a value for Other`:r.min!==void 0&&t<r.min?n[r.name]=`Choose at least ${r.min}`:r.max!==void 0&&t>r.max&&(n[r.name]=`Choose at most ${r.max}`)}}}return n}function ne(e,t){return{...e,selected:[t],otherChosen:!1}}function re(e){return{...e,selected:[],otherChosen:!0}}function ie(e,t,n){if(e.selected.includes(t))return{...e,selected:e.selected.filter(e=>e!==t)};let r=e.selected.length+ +!!e.otherChosen;return n!==void 0&&r>=n?e:{...e,selected:[...e.selected,t]}}function H({node:e,className:t}){let{onRespond:n,busy:r,disabled:i}=A(),[a,o]=(0,O.useState)(()=>te(e.fields)),[s,c]=(0,O.useState)(!1),d=(0,O.useMemo)(()=>z(e.fields,a),[e.fields,a]),f=(0,O.useMemo)(()=>V(e.fields,a),[e.fields,a]),p=i||r,m=(e,t)=>o(n=>({...n,[e]:t}));return(0,j.jsxs)(`form`,{className:l(`flex flex-col gap-4`,t),noValidate:!0,onSubmit:t=>{t.preventDefault(),c(!0),!(Object.keys(f).length>0||p)&&n?.({kind:`form`,values:B(e.fields,a)})},children:[d.map(e=>(0,j.jsx)(U,{field:e,state:a[e.name],onChange:t=>m(e.name,t),error:s?f[e.name]:void 0,disabled:p},e.name)),!i&&(0,j.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,j.jsx)(u,{type:`submit`,variant:`primary`,busy:r,children:e.submitLabel||`Submit`}),(0,j.jsx)(u,{type:`button`,variant:`secondary`,disabled:r,onClick:()=>n?.({kind:`cancel`}),children:e.cancelLabel||`Cancel`}),s&&Object.keys(f).length>0&&(0,j.jsx)(`span`,{role:`alert`,className:`text-sm text-danger`,children:`Complete the highlighted fields.`})]})]})}function U({field:e,state:t,onChange:n,error:r,disabled:i}){let a=(0,O.useId)(),o=`${a}-err`;if(e.kind===`text`){let s={id:a,value:t.text,placeholder:e.placeholder,disabled:i,"aria-invalid":!!r||void 0,"aria-describedby":r?o:void 0};return(0,j.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,j.jsx)(`label`,{htmlFor:a,className:`text-sm font-medium`,children:e.label}),e.multiline?(0,j.jsx)(b,{...s,minRows:3,onChange:e=>n({...t,text:e.target.value})}):(0,j.jsx)(y,{...s,onChange:e=>n({...t,text:e.target.value})}),r&&(0,j.jsx)(`p`,{id:o,className:`text-sm text-danger`,children:r})]})}let s=e.kind===`multiselect`,c=!s&&t.selected[0]?e.options.find(e=>e.value===t.selected[0])?.preview:void 0,l=s&&(e.min!==void 0||e.max!==void 0)?e.min!==void 0&&e.max!==void 0?`Choose ${e.min}–${e.max}`:e.min===void 0?`Choose up to ${e.max}`:`Choose at least ${e.min}`:s?`Choose any`:void 0;return(0,j.jsxs)(`fieldset`,{className:`flex min-w-0 flex-col gap-2`,"aria-describedby":r?o:void 0,"aria-invalid":!!r||void 0,children:[(0,j.jsxs)(`legend`,{className:`mb-2 text-sm font-medium`,children:[e.label,l&&(0,j.jsx)(`span`,{className:`ml-2 font-normal text-muted`,children:l})]}),(0,j.jsxs)(`div`,{className:`grid gap-2`,children:[e.options.map(r=>(0,j.jsx)(W,{name:a,option:r,multi:s,checked:t.selected.includes(r.value),disabled:i,onToggle:()=>n(s?ie(t,r.value,e.kind===`multiselect`?e.max:void 0):ne(t,r.value))},r.value)),e.allowOther&&(0,j.jsx)(W,{name:a,option:{value:`__other__`,label:e.allowOther.label||`Other`},multi:s,checked:t.otherChosen,disabled:i,onToggle:()=>n(s?{...t,otherChosen:!t.otherChosen}:re(t))})]}),e.allowOther&&t.otherChosen&&(0,j.jsx)(y,{"aria-label":e.allowOther.label||`Other`,placeholder:e.allowOther.placeholder??`Type your answer`,value:t.otherText,disabled:i,autoFocus:!0,onChange:e=>n({...t,otherText:e.target.value})}),c&&(0,j.jsx)(`pre`,{className:`max-h-64 max-w-full overflow-auto rounded-md border border-border bg-surface-2 px-3 py-2 text-xs leading-5`,children:c}),r&&(0,j.jsx)(`p`,{id:o,className:`text-sm text-danger`,children:r})]})}function W({name:e,option:t,multi:n,checked:r,disabled:i,onToggle:a}){return(0,j.jsxs)(`label`,{className:l(`tap flex min-w-0 cursor-pointer items-start gap-3 rounded-lg border px-3 py-2.5 text-sm`,`has-[:focus-visible]:outline-2 has-[:focus-visible]:outline-offset-2 has-[:focus-visible]:outline-accent`,r?`border-accent bg-accent-soft`:`border-border bg-surface hover:bg-surface-2`,i&&`cursor-not-allowed opacity-70`),children:[(0,j.jsx)(`input`,{type:n?`checkbox`:`radio`,name:e,value:t.value,checked:r,disabled:i,onChange:a,className:`sr-only`}),(0,j.jsx)(`span`,{"aria-hidden":!0,className:l(`mt-0.5 inline-flex size-4 shrink-0 items-center justify-center border`,n?`rounded`:`rounded-full`,r?`border-accent bg-accent text-accent-fg`:`border-border-strong bg-surface`),children:r&&(n?(0,j.jsx)(p,{className:`size-3`}):(0,j.jsx)(`span`,{className:`size-1.5 rounded-full bg-accent-fg`}))}),(0,j.jsxs)(`span`,{className:`min-w-0 flex-1`,children:[(0,j.jsx)(`span`,{className:`block font-medium break-words`,children:t.label}),t.description&&(0,j.jsx)(`span`,{className:`block text-muted break-words`,children:t.description})]})]})}function G({node:e,className:t,...n}){let r=A(),i=Object.values(n).some(e=>e!==void 0),a=(0,j.jsx)(`div`,{className:l(`flex min-w-0 flex-col gap-3`,t),children:(0,j.jsx)(J,{node:e})});return i?(0,j.jsx)(k.Provider,{value:{...r,...K(n)},children:a}):a}function K(e){return Object.fromEntries(Object.entries(e).filter(([,e])=>e!==void 0))}var q={default:`text-text`,muted:`text-muted`,success:`text-success`,warning:`text-warning`,danger:`text-danger`};function J({node:e}){switch(e.t){case`text`:return(0,j.jsx)(`p`,{className:l(`text-sm break-words whitespace-pre-wrap`,q[e.tone??`default`]),children:e.text});case`markdown`:return(0,j.jsx)(w,{text:e.text});case`code`:return(0,j.jsx)(S,{text:e.text,lang:e.lang,maxHeight:`24rem`});case`diff`:return(0,j.jsx)(L,{patch:e.patch});case`list`:return(0,j.jsx)(X,{node:e});case`table`:return(0,j.jsx)(`div`,{className:`max-w-full overflow-x-auto overscroll-x-contain rounded-md border border-border`,children:(0,j.jsxs)(`table`,{className:`w-full border-collapse text-sm`,children:[(0,j.jsx)(`thead`,{className:`bg-surface-2`,children:(0,j.jsx)(`tr`,{children:e.columns.map((e,t)=>(0,j.jsx)(`th`,{scope:`col`,className:`border-b border-border px-3 py-1.5 text-left font-medium`,children:e},t))})}),(0,j.jsx)(`tbody`,{children:e.rows.map((e,t)=>(0,j.jsx)(`tr`,{className:`border-b border-border last:border-b-0`,children:e.map((e,t)=>(0,j.jsx)(`td`,{className:`px-3 py-1.5 align-top break-words`,children:e},t))},t))})]})});case`section`:return(0,j.jsx)(ae,{node:e});case`tabs`:return(0,j.jsx)(oe,{node:e});case`progress`:return(0,j.jsx)(se,{node:e});case`ref`:return(0,j.jsx)(le,{refValue:e.ref,label:e.label});case`form`:return(0,j.jsx)(H,{node:e});case`confirm`:return(0,j.jsx)(M,{node:e});case`actions`:return(0,j.jsx)(ue,{node:e});default:return null}}function Y({nodes:e}){return(0,j.jsx)(j.Fragment,{children:e.map((e,t)=>(0,j.jsx)(J,{node:e},t))})}function X({node:e}){let t=e.ordered?`ol`:`ul`;return(0,j.jsx)(t,{className:l(`flex flex-col gap-1.5 pl-5 text-sm`,e.ordered?`list-decimal`:`list-disc`),children:e.items.map((e,t)=>(0,j.jsx)(`li`,{className:`min-w-0`,children:(0,j.jsx)(`div`,{className:`flex min-w-0 flex-col gap-2`,children:(0,j.jsx)(J,{node:e})})},t))})}function ae({node:e}){return e.collapsible?(0,j.jsxs)(`details`,{className:`group min-w-0 rounded-md border border-border`,open:!0,children:[(0,j.jsxs)(`summary`,{className:`tap flex cursor-pointer list-none items-center gap-1.5 px-3 py-2 text-sm font-medium [&::-webkit-details-marker]:hidden`,children:[(0,j.jsx)(m,{"aria-hidden":!0,className:`size-4 shrink-0 transition-transform group-open:rotate-90`}),e.title??`Details`]}),(0,j.jsx)(`div`,{className:`flex min-w-0 flex-col gap-3 border-t border-border px-3 py-2`,children:(0,j.jsx)(Y,{nodes:e.children})})]}):(0,j.jsxs)(`section`,{className:`flex min-w-0 flex-col gap-2`,children:[e.title&&(0,j.jsx)(`h3`,{className:`text-sm font-semibold`,children:e.title}),(0,j.jsx)(Y,{nodes:e.children})]})}function oe({node:e}){let t=(0,O.useId)(),[n,r]=(0,O.useState)(e.tabs[0]?.id??``),i=e.tabs.find(e=>e.id===n)??e.tabs[0];return i?(0,j.jsxs)(`div`,{className:`flex min-w-0 flex-col gap-2`,children:[(0,j.jsx)(x,{label:`Sections`,idPrefix:t,tabs:e.tabs.map(e=>({id:e.id,label:e.label})),value:i.id,onChange:r,scrollable:!0}),(0,j.jsx)(C,{idPrefix:t,id:i.id,className:`flex min-w-0 flex-col gap-3`,children:(0,j.jsx)(Y,{nodes:i.children})})]}):null}function se({node:e}){let t=e.status??`running`,n=t===`ok`?_:t===`error`?h:g,r=t===`ok`?`Done`:t===`error`?`Failed`:`In progress`,i=e.value===void 0?null:Math.round(e.value*100);return(0,j.jsxs)(`div`,{className:`flex min-w-0 flex-col gap-1`,children:[(0,j.jsxs)(`div`,{className:`flex items-center gap-2 text-sm`,children:[(0,j.jsx)(n,{"aria-hidden":!0,className:l(`size-4 shrink-0`,t===`ok`&&`text-success`,t===`error`&&`text-danger`,t===`running`&&`animate-spin text-info`)}),(0,j.jsx)(`span`,{className:`min-w-0 flex-1 truncate`,children:e.label}),(0,j.jsxs)(`span`,{className:`shrink-0 text-xs text-muted`,children:[r,i===null?``:` · ${i}%`]})]}),i!==null&&(0,j.jsx)(`div`,{role:`progressbar`,"aria-label":e.label,"aria-valuenow":i,"aria-valuemin":0,"aria-valuemax":100,className:`h-1.5 overflow-hidden rounded-full bg-surface-3`,children:(0,j.jsx)(`div`,{className:l(`h-full rounded-full`,t===`error`?`bg-danger`:t===`ok`?`bg-success`:`bg-accent`),style:{width:`${i}%`}})})]})}function ce(e){switch(e.kind){case`session`:return`/code/${encodeURIComponent(e.sessionId)}`;case`task`:return`/tasks/${encodeURIComponent(e.taskId)}`;default:return null}}function le({refValue:e,label:n}){let{onOpenFile:r}=A(),i=ce(e);return i?(0,j.jsx)(t,{to:i,className:`text-sm text-accent underline underline-offset-2`,children:n}):e.kind===`file`?r?(0,j.jsxs)(`button`,{type:`button`,onClick:()=>r(e.path),className:`inline-flex min-w-0 items-center gap-1 text-left text-sm text-accent underline underline-offset-2`,children:[(0,j.jsx)(D,{"aria-hidden":!0,className:`size-4 shrink-0`}),(0,j.jsx)(`span`,{className:`truncate`,children:n||e.path})]}):(0,j.jsxs)(`span`,{className:`inline-flex min-w-0 items-center gap-1 font-mono text-sm`,title:e.path,children:[(0,j.jsx)(D,{"aria-hidden":!0,className:`size-4 shrink-0 text-muted`}),(0,j.jsx)(`span`,{className:`truncate`,children:n||e.path})]}):e.kind===`native_session`?(0,j.jsxs)(`span`,{className:`text-sm`,title:e.sessionFile,children:[n,` `,(0,j.jsx)(`span`,{className:`text-muted`,children:`(native Pi session, not imported)`})]}):(0,j.jsx)(`span`,{className:`text-sm`,children:n})}function ue({node:e}){let{onRespond:t,onAction:n,busy:r,disabled:i}=A();return i?null:(0,j.jsx)(`div`,{className:`flex flex-wrap gap-2`,children:e.actions.map(e=>(0,j.jsx)(u,{variant:e.tone===`primary`?`primary`:e.tone===`danger`?`danger`:`secondary`,disabled:r||!t&&!n,onClick:()=>{t?t({kind:`action`,actionId:e.id}):n?.(e.id)},children:e.label},e.id))})}var de=`An extension opened a terminal-only dialog. In RPC mode Pi gave it no answer, so the extension continued without one.`,fe=[{id:`abort`,label:`Stop the run`,tone:`danger`},{id:`message`,label:`Send a message to the agent`,tone:`primary`}];function Z(e){if(e.t===`actions`)return e;if(e.t===`section`)for(let t of e.children){let e=Z(t);if(e)return e}return null}function pe(e){return e.state===`unsupported`||e.source.kind===`unsupported_custom`}function me(e){let t=(Z(e.presentation)?.actions??[]).filter(e=>e.id===`abort`||e.id===`message`).map(e=>({id:e.id,label:e.label,tone:e.tone==="default"?`secondary`:e.tone??(e.id===`abort`?`danger`:`primary`)}));return{answerable:e.state===`unsupported`&&e.resolution===null,actions:t.length>0?t:fe,copy:de}}function he(e){return e===`running`||e===`waiting_input`?`followUp`:`prompt`}function Q(e){switch(e.t){case`form`:case`confirm`:case`actions`:return!0;case`list`:return e.items.some(Q);case`section`:return e.children.some(Q);case`tabs`:return e.tabs.some(e=>e.children.some(Q));default:return!1}}function $(e){return e===`host`?`the host`:e===`pi`?`Pi`:`a device`}function ge({interaction:e,readOnlyReason:t,className:n,onAnswered:r,id:i}){let p=o(e=>e.upsertInteraction),[m,h]=(0,O.useState)(!1),[g,_]=(0,O.useState)(null),[y,b]=(0,O.useState)(null),[x,S]=(0,O.useState)(null),[C,w]=(0,O.useState)(null),T=C&&C.id===e.id&&C.revision>e.revision?C:e,E=T.state===`pending`,D=pe(T),k=o(e=>e.sessions[T.sessionId]?.runtime),[A,M]=(0,O.useState)(!1),[N,P]=(0,O.useState)(``),F=async e=>{h(!0),_(null),S(e);try{let t=await s(`/api/interactions/${encodeURIComponent(T.id)}/answer`,{revision:T.revision,response:e});return t?.interaction&&(p(t.interaction),w(t.interaction),r?.(t.interaction)),!0}catch(e){if(a(e,`already_answered`)){let t=e.details?.interaction;t&&(p(t),w(t)),b(t?.resolution?.summary??`answered on another device`)}else _(e);return!1}finally{h(!1)}},I=async()=>{let e=N.trim();if(e){h(!0),_(null);try{await s(`/api/sessions/${encodeURIComponent(T.sessionId)}/prompt`,{text:e,mode:he(k)})}catch(e){_(e),h(!1);return}h(!1),await F({kind:`action`,actionId:`message`})&&(M(!1),P(``))}};return(0,j.jsxs)(`article`,{id:i,"aria-label":`Question: ${T.title}`,className:l(`flex min-w-0 flex-col gap-3 rounded-lg border bg-surface p-3`,E?`border-warning`:`border-border`,n),children:[(0,j.jsxs)(`header`,{className:`flex min-w-0 flex-wrap items-start gap-2`,children:[(0,j.jsx)(`h3`,{className:`min-w-0 flex-1 text-sm font-semibold break-words`,children:T.title}),(0,j.jsx)(v,{kind:`interaction`,value:T.state,size:`sm`})]}),y&&(0,j.jsxs)(`p`,{role:`status`,className:`rounded-md bg-surface-2 px-3 py-2 text-sm`,children:[`Already answered: `,y]}),D?(0,j.jsx)(_e,{interaction:T,readOnlyReason:t??null,busy:m,answered:y!==null,composing:A,message:N,setMessage:P,onAction:e=>{e===`message`?M(!0):F({kind:`action`,actionId:e})},onSend:()=>void I(),onCancelMessage:()=>M(!1)}):E&&!y?(0,j.jsxs)(j.Fragment,{children:[t&&(0,j.jsx)(`p`,{className:`text-sm text-muted`,children:t}),(0,j.jsx)(G,{node:T.presentation,onRespond:e=>void F(e),busy:m,disabled:!!t}),!t&&!Q(T.presentation)&&(0,j.jsx)(`div`,{children:(0,j.jsx)(u,{busy:m,onClick:()=>void F({kind:`cancel`}),children:`Dismiss`})}),m&&(0,j.jsx)(`p`,{role:`status`,className:`text-sm text-muted`,children:`Sending answer… waiting for the host to confirm.`})]}):y?null:T.resolution?(0,j.jsxs)(`p`,{className:`text-sm text-muted`,children:[T.state===`resolved`?`Answered`:`Closed`,` by`,` `,$(T.resolution.by),` `,f(T.resolution.at),`:`,` `,(0,j.jsx)(`span`,{className:`text-text`,children:T.resolution.summary})]}):(0,j.jsx)(`p`,{className:`text-sm text-muted`,children:T.state===`expired`?`This question expired before it was answered (Pi closed the dialog).`:`This question was cancelled.`}),g!==null&&(0,j.jsx)(d,{compact:!0,title:`Answer not delivered`,error:c(g),onRetry:x?()=>void F(x):void 0})]})}function _e({interaction:e,readOnlyReason:t,busy:n,answered:r,composing:i,message:a,setMessage:o,onAction:s,onSend:c,onCancelMessage:l}){let d=me(e);return(0,j.jsxs)(`div`,{className:`flex min-w-0 flex-col gap-2`,children:[(0,j.jsx)(`p`,{className:`text-sm text-muted`,children:d.copy}),e.resolution?(0,j.jsxs)(`p`,{className:`text-sm text-muted`,children:[`Chosen by `,$(e.resolution.by),` `,f(e.resolution.at),`: `,(0,j.jsx)(`span`,{className:`text-text`,children:e.resolution.summary})]}):!d.answerable||r?null:t?(0,j.jsx)(`p`,{className:`text-sm text-muted`,children:t}):i?(0,j.jsxs)(`div`,{className:`flex min-w-0 flex-col gap-2`,children:[(0,j.jsx)(b,{"aria-label":`Message to the agent`,value:a,onChange:e=>o(e.target.value),rows:3,autoFocus:!0,placeholder:`Tell the agent what to do instead`}),(0,j.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,j.jsx)(u,{variant:`primary`,busy:n,disabled:!a.trim(),onClick:c,children:`Send message`}),(0,j.jsx)(u,{disabled:n,onClick:l,children:`Cancel`})]})]}):(0,j.jsx)(`div`,{className:`flex flex-wrap gap-2`,children:d.actions.map(e=>(0,j.jsx)(u,{variant:e.tone,busy:n&&e.id===`abort`,disabled:n,onClick:()=>s(e.id),children:e.label},e.id))})]})}export{F as i,G as n,L as r,ge as t};
|
|
4
|
-
//# sourceMappingURL=InteractionCard-
|
|
4
|
+
//# sourceMappingURL=InteractionCard-cvPWKSu1.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InteractionCard-DxEZUNrD.js","names":["createContext","useContext","useMemo","useState","useMemo","useId","_Fragment","useId","useState","useState","_Fragment","__toESM","Link","require_react","createLucideIcon","require_jsx_runtime","isApiError","useSyncStore","apiPost","errorMessage","cn","Button","ErrorState","formatRelative","Check","ChevronRight","CircleX","LoaderCircle","CircleCheck","StatusChip","TextInput","TextArea","Tabs","CodeBlock","TabPanel","Markdown","isFieldVisible","__iconData","FileCode","import_react","IntentContext","useIntent","import_jsx_runtime","ConfirmRenderer","node","disabled","onRespond","busy","stripPrefix","p","HUNK","parseUnifiedDiff","files","file","oldNo","newNo","oldLeft","newLeft","inHunk","consumed","start","f","lines","patch","line","m","l","h","MARKER","GUTTER_BG","DiffView","given","className","showFileHeaders","ref","selectable","onLineClick","marked","isLineMarked","li","fi","initialFormState","out","fields","fieldValue","st","field","vals","visibleFields","values","state","buildValues","v","validateForm","errors","n","chooseSelect","value","chooseSelectOther","toggleMulti","count","max","FormRenderer","setState","attempted","setAttempted","visible","locked","setField","s","name","fs","e","FieldView","id","errId","common","error","onChange","multi","selectedPreview","o","hint","OptionCard","checked","option","onToggle","UINodeRenderer","handlers","parent","hasOwn","content","NodeView","stripUndefined","TONE_TEXT","ListView","c","i","r","cell","ci","ri","SectionView","TabsView","ProgressView","RefView","ActionsView","Children","nodes","Tag","item","prefix","active","setActive","current","t","status","Icon","statusText","pct","refHref","href","refValue","label","onOpenFile","a","onAction","UNSUPPORTED_COPY","DEFAULT_ACTIONS","findActions","found","isUnsupported","unsupportedView","offered","messageMode","runtime","hasInteractive","byLabel","by","InteractionCard","fromProps","upsert","setBusy","setError","alreadyAnswered","setAlreadyAnswered","lastResponse","setLastResponse","acked","setAcked","interaction","pending","unsupported","sessionRuntime","composing","setComposing","message","setMessage","respond","response","res","onAnswered","other","sendMessage","text","UnsupportedBody","readOnlyReason","actionId","view","answered","onSend","onCancelMessage"],"sources":["../../../../node_modules/.pnpm/lucide-react@1.61.0_@types+react@19.3.0_react@19.3.1/node_modules/lucide-react/dist/esm/icons/file-code.mjs","../../src/components/intent/context.ts","../../src/components/intent/ConfirmRenderer.tsx","../../src/components/intent/diff.ts","../../src/components/intent/DiffView.tsx","../../src/components/intent/formLogic.ts","../../src/components/intent/FormRenderer.tsx","../../src/components/intent/UINodeRenderer.tsx","../../src/components/intent/unsupported.ts","../../src/components/intent/InteractionCard.tsx"],"sourcesContent":["/**\n * @license lucide-react v1.61.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconData = {\n name: \"file-code\",\n size: 24,\n node: [\n [\n \"path\",\n {\n d: \"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\",\n key: \"1oefj6\"\n }\n ],\n [\"path\", { d: \"M14 2v5a1 1 0 0 0 1 1h5\", key: \"wfsgrz\" }],\n [\"path\", { d: \"M10 12.5 8 15l2 2.5\", key: \"1tg20x\" }],\n [\"path\", { d: \"m14 12.5 2 2.5-2 2.5\", key: \"yinavb\" }]\n ]\n};\n__iconData.node;\nconst FileCode = createLucideIcon(__iconData);\n\nexport { __iconData, FileCode as default };\n//# sourceMappingURL=file-code.mjs.map\n","import type { InteractionResponse } from \"@switchyard/protocol\";\nimport { createContext, useContext } from \"react\";\n\n/** Handlers available to a rendered UINode tree. */\nexport interface IntentHandlers {\n /** Interaction context: form submit, confirm, cancel and action buttons respond here. */\n onRespond?: (response: InteractionResponse) => void;\n /** Panel/tool-card context: `actions` buttons call this when there is no `onRespond`. */\n onAction?: (actionId: string) => void;\n /** File refs call this when provided (e.g. open in the inspector); otherwise render as text. */\n onOpenFile?: (path: string) => void;\n /** A response is in flight: inputs stay visible, buttons show busy. */\n busy?: boolean;\n /** Read-only (already answered, expired, read-only session). */\n disabled?: boolean;\n}\n\nexport const IntentContext = createContext<IntentHandlers>({});\nexport const useIntent = () => useContext(IntentContext);\n","import type { UINode } from \"@switchyard/protocol\";\nimport { Button } from \"../ui/Button\";\nimport { useIntent } from \"./context\";\nimport { Markdown } from \"./Markdown\";\n\ntype ConfirmNode = Extract<UINode, { t: \"confirm\" }>;\n\n/** Yes/no question; responds `{kind: \"confirm\", confirmed}`. */\nexport function ConfirmRenderer({ node }: { node: ConfirmNode }) {\n const { onRespond, busy, disabled } = useIntent();\n return (\n <div className=\"flex flex-col gap-3\">\n <Markdown text={node.message} />\n {!disabled && (\n <div className=\"flex flex-wrap gap-2\">\n <Button\n variant={node.destructive ? \"danger\" : \"primary\"}\n busy={busy}\n onClick={() => onRespond?.({ kind: \"confirm\", confirmed: true })}\n >\n {node.confirmLabel || \"Confirm\"}\n </Button>\n <Button\n disabled={busy}\n onClick={() => onRespond?.({ kind: \"confirm\", confirmed: false })}\n >\n {node.cancelLabel || \"Cancel\"}\n </Button>\n </div>\n )}\n </div>\n );\n}\n","/** Unified diff parsing for DiffView (pure; tested without a DOM). */\n\nexport type DiffLineKind = \"add\" | \"del\" | \"context\" | \"hunk\" | \"meta\";\n\nexport interface DiffLine {\n kind: DiffLineKind;\n text: string;\n oldLine: number | null;\n newLine: number | null;\n}\n\nexport interface DiffFile {\n /** Display path (new path, or old path for deletions). */\n path: string;\n oldPath: string | null;\n newPath: string | null;\n status: \"modified\" | \"added\" | \"deleted\" | \"renamed\" | \"binary\";\n additions: number;\n deletions: number;\n lines: DiffLine[];\n}\n\nfunction stripPrefix(p: string): string | null {\n const t = p.trim().split(\"\\t\")[0]!;\n if (t === \"/dev/null\") return null;\n return t.replace(/^[ab]\\//, \"\");\n}\n\nconst HUNK = /^@@ -(\\d+)(?:,(\\d+))? \\+(\\d+)(?:,(\\d+))? @@/;\n\nexport function parseUnifiedDiff(patch: string): DiffFile[] {\n const files: DiffFile[] = [];\n let file: DiffFile | null = null;\n let oldNo = 0;\n let newNo = 0;\n let oldLeft = 0;\n let newLeft = 0;\n let inHunk = false;\n const consumed = () => {\n if (oldLeft <= 0 && newLeft <= 0) inHunk = false;\n };\n const start = (path = \"\"): DiffFile => {\n const f: DiffFile = {\n path,\n oldPath: null,\n newPath: null,\n status: \"modified\",\n additions: 0,\n deletions: 0,\n lines: [],\n };\n files.push(f);\n inHunk = false;\n return f;\n };\n const lines = patch.replace(/\\r\\n/g, \"\\n\").split(\"\\n\");\n if (lines[lines.length - 1] === \"\") lines.pop();\n for (const line of lines) {\n if (line.startsWith(\"diff --git \")) {\n const m = /^diff --git a\\/(.+?) b\\/(.+)$/.exec(line);\n file = start(m?.[2] ?? \"\");\n if (m) {\n file.oldPath = m[1]!;\n file.newPath = m[2]!;\n }\n continue;\n }\n if (!inHunk && line.startsWith(\"--- \")) {\n if (!file || file.lines.some((l) => l.kind !== \"meta\")) file = start();\n file.oldPath = stripPrefix(line.slice(4));\n if (file.oldPath === null) file.status = \"added\";\n continue;\n }\n if (!inHunk && line.startsWith(\"+++ \") && file) {\n file.newPath = stripPrefix(line.slice(4));\n if (file.newPath === null) file.status = \"deleted\";\n file.path = file.newPath ?? file.oldPath ?? file.path;\n continue;\n }\n const h = HUNK.exec(line);\n if (h) {\n if (!file) file = start();\n oldNo = Number(h[1]);\n newNo = Number(h[3]);\n oldLeft = h[2] === undefined ? 1 : Number(h[2]);\n newLeft = h[4] === undefined ? 1 : Number(h[4]);\n inHunk = oldLeft > 0 || newLeft > 0;\n file.lines.push({ kind: \"hunk\", text: line, oldLine: null, newLine: null });\n continue;\n }\n if (!file) file = start();\n if (inHunk && line.startsWith(\"+\")) {\n file.lines.push({ kind: \"add\", text: line.slice(1), oldLine: null, newLine: newNo++ });\n file.additions++;\n newLeft--;\n consumed();\n } else if (inHunk && line.startsWith(\"-\")) {\n file.lines.push({ kind: \"del\", text: line.slice(1), oldLine: oldNo++, newLine: null });\n file.deletions++;\n oldLeft--;\n consumed();\n } else if (inHunk && (line.startsWith(\" \") || line === \"\")) {\n file.lines.push({\n kind: \"context\",\n text: line.slice(1),\n oldLine: oldNo++,\n newLine: newNo++,\n });\n oldLeft--;\n newLeft--;\n consumed();\n } else if (line.startsWith(\"\\\\\")) {\n file.lines.push({ kind: \"meta\", text: line, oldLine: null, newLine: null });\n } else {\n // Header lines (index, mode, rename, Binary files ...).\n inHunk = false;\n if (line.startsWith(\"new file mode\")) file.status = \"added\";\n else if (line.startsWith(\"deleted file mode\")) file.status = \"deleted\";\n else if (line.startsWith(\"rename from \")) {\n file.status = \"renamed\";\n file.oldPath = line.slice(12);\n } else if (line.startsWith(\"rename to \")) {\n file.status = \"renamed\";\n file.newPath = line.slice(10);\n file.path = file.newPath;\n } else if (line.startsWith(\"Binary files\")) file.status = \"binary\";\n file.lines.push({ kind: \"meta\", text: line, oldLine: null, newLine: null });\n }\n }\n return files;\n}\n","import { useMemo } from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport { type DiffFile, type DiffLine, parseUnifiedDiff } from \"./diff\";\n\nexport interface DiffLineRef {\n file: string;\n line: DiffLine;\n}\n\nexport interface DiffViewProps {\n /** Unified diff text (one or more files). */\n patch?: string;\n /** Pre-parsed files (alternative to `patch`). */\n files?: DiffFile[];\n /** Show a header per file (default true). */\n showFileHeaders?: boolean;\n /** Enables line selection (e.g. review comments). Called for add/context/del lines. */\n onLineClick?: (ref: DiffLineRef) => void;\n /** Highlight lines (e.g. lines with comments). */\n isLineMarked?: (ref: DiffLineRef) => boolean;\n className?: string;\n}\n\nconst MARKER: Record<DiffLine[\"kind\"], string> = {\n add: \"+\",\n del: \"-\",\n context: \" \",\n hunk: \"\",\n meta: \"\",\n};\n\n/** Opaque gutter backgrounds (the gutter is sticky, so it must cover scrolled text). */\nconst GUTTER_BG: Record<DiffLine[\"kind\"], string> = {\n add: \"bg-diff-add\",\n del: \"bg-diff-del\",\n hunk: \"bg-diff-hunk\",\n context: \"bg-surface\",\n meta: \"bg-surface\",\n};\n\n/**\n * Unified diff with old/new line numbers, +/- text markers (not color alone)\n * and tinted rows. Horizontal scrolling is confined to the diff block, and the line-number\n * gutter is sticky so it stays visible while a long line is scrolled.\n */\nexport function DiffView({\n patch,\n files: given,\n showFileHeaders = true,\n onLineClick,\n isLineMarked,\n className,\n}: DiffViewProps) {\n const files = useMemo(() => given ?? parseUnifiedDiff(patch ?? \"\"), [given, patch]);\n if (files.length === 0) {\n return <p className=\"text-sm text-muted\">No changes.</p>;\n }\n return (\n <div className={cn(\"flex min-w-0 flex-col gap-3\", className)}>\n {files.map((f, fi) => (\n <section\n // biome-ignore lint/suspicious/noArrayIndexKey: files can repeat paths in odd patches\n key={`${f.path}-${fi}`}\n className=\"min-w-0 overflow-hidden rounded-md border border-border\"\n aria-label={`Diff of ${f.path || \"file\"}`}\n >\n {showFileHeaders && (\n <header className=\"flex min-w-0 items-center gap-2 border-b border-border bg-surface-2 px-3 py-1.5 text-sm\">\n <span className=\"min-w-0 flex-1 truncate font-mono\" title={f.path}>\n {f.status === \"renamed\" && f.oldPath ? `${f.oldPath} → ${f.path}` : f.path}\n </span>\n <span className=\"shrink-0 font-mono text-xs\">\n <span className=\"text-success\">\n +{f.additions}\n <span className=\"sr-only\"> added</span>\n </span>{\" \"}\n <span className=\"text-danger\">\n -{f.deletions}\n <span className=\"sr-only\"> deleted</span>\n </span>\n </span>\n </header>\n )}\n {f.status === \"binary\" ? (\n <p className=\"px-3 py-2 text-sm text-muted\">Binary file not shown.</p>\n ) : (\n <div className=\"max-w-full overflow-x-auto overscroll-x-contain\">\n <table className=\"w-full border-collapse font-mono text-xs leading-5\">\n <tbody>\n {f.lines.map((l, li) => {\n const ref = { file: f.path, line: l };\n const selectable =\n !!onLineClick &&\n (l.kind === \"add\" || l.kind === \"del\" || l.kind === \"context\");\n const marked = isLineMarked?.(ref) ?? false;\n return (\n <tr\n // biome-ignore lint/suspicious/noArrayIndexKey: diff lines are positional\n key={li}\n className={cn(\n l.kind === \"add\" && \"bg-diff-add\",\n l.kind === \"del\" && \"bg-diff-del\",\n l.kind === \"hunk\" && \"bg-diff-hunk text-muted\",\n l.kind === \"meta\" && \"text-muted\",\n marked && \"outline outline-1 -outline-offset-1 outline-warning\",\n )}\n >\n <td\n className={cn(\n \"sticky left-0 z-[1] w-[6.25rem] min-w-[6.25rem] select-none whitespace-nowrap p-0\",\n GUTTER_BG[l.kind],\n )}\n >\n <span className=\"flex\">\n <span className=\"w-10 shrink-0 border-r border-border px-1.5 text-right text-subtle tabular-nums\">\n {l.oldLine ?? \"\"}\n </span>\n <span className=\"w-10 shrink-0 border-r border-border px-1.5 text-right text-subtle tabular-nums\">\n {l.newLine ?? \"\"}\n </span>\n <span\n aria-hidden\n className={cn(\n \"w-5 shrink-0 text-center\",\n l.kind === \"add\" && \"text-success\",\n l.kind === \"del\" && \"text-danger\",\n )}\n >\n {MARKER[l.kind]}\n </span>\n {(l.kind === \"add\" || l.kind === \"del\") && (\n <span className=\"sr-only\">\n {l.kind === \"add\" ? \"added\" : \"deleted\"}\n </span>\n )}\n </span>\n </td>\n <td className=\"whitespace-pre pr-3\">\n {selectable ? (\n <button\n type=\"button\"\n data-diff-line={l.newLine ?? l.oldLine ?? undefined}\n // Keyboard focus scrolls the line into view clear of the sticky gutter.\n className=\"block w-full scroll-ml-[6.25rem] cursor-pointer text-left whitespace-pre hover:underline focus-visible:underline\"\n // A pointer click must not scroll the diff sideways (the button spans\n // the whole long line): skip the focus scroll, then focus in place.\n onMouseDown={(e) => e.preventDefault()}\n onClick={(e) => {\n e.currentTarget.focus({ preventScroll: true });\n onLineClick?.(ref);\n }}\n aria-label={`Comment on line ${l.newLine ?? l.oldLine}`}\n >\n {l.text || \" \"}\n </button>\n ) : (\n l.text\n )}\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n )}\n </section>\n ))}\n </div>\n );\n}\n","import { type Field, type FormValue, isFieldVisible } from \"@switchyard/protocol\";\n\n/**\n * Pure form state logic for FormRenderer (tested without a DOM).\n *\n * Each field keeps its raw UI state; `buildValues` turns it into the\n * submitted `InteractionResponse` values, omitting hidden fields.\n */\n\nexport interface FieldState {\n /** Selected option values (select: at most one). */\n selected: string[];\n /** \"Other\" chosen (select/multiselect with allowOther). */\n otherChosen: boolean;\n otherText: string;\n /** Text field value. */\n text: string;\n}\n\nexport type FormState = Record<string, FieldState>;\n\nexport function initialFormState(fields: Field[]): FormState {\n const out: FormState = {};\n for (const f of fields) {\n out[f.name] = {\n selected: [],\n otherChosen: false,\n otherText: \"\",\n text: f.kind === \"text\" ? (f.prefill ?? \"\") : \"\",\n };\n }\n return out;\n}\n\n/** The value a field contributes, or undefined when nothing is chosen. */\nexport function fieldValue(field: Field, st: FieldState | undefined): FormValue | undefined {\n if (!st) return undefined;\n switch (field.kind) {\n case \"text\":\n return st.text;\n case \"select\":\n if (st.otherChosen) return { other: st.otherText };\n return st.selected[0];\n case \"multiselect\": {\n const vals = [...st.selected];\n // Multiselect \"other\" text is submitted as an extra entry.\n if (st.otherChosen && st.otherText.trim()) vals.push(st.otherText.trim());\n return vals;\n }\n }\n}\n\n/**\n * Visible fields in order. `showIf` refers to an earlier field, so visibility\n * is evaluated against the values of fields that are themselves visible.\n */\nexport function visibleFields(fields: Field[], state: FormState): Field[] {\n const values: Record<string, FormValue | undefined> = {};\n const out: Field[] = [];\n for (const f of fields) {\n if (!isFieldVisible(f, values)) continue;\n out.push(f);\n values[f.name] = fieldValue(f, state[f.name]);\n }\n return out;\n}\n\n/** Submitted values: visible fields only. */\nexport function buildValues(fields: Field[], state: FormState): Record<string, FormValue> {\n const out: Record<string, FormValue> = {};\n for (const f of visibleFields(fields, state)) {\n const v = fieldValue(f, state[f.name]);\n if (v !== undefined) out[f.name] = v;\n }\n return out;\n}\n\n/** Validation errors keyed by field name (visible fields only). Empty when valid. */\nexport function validateForm(fields: Field[], state: FormState): Record<string, string> {\n const errors: Record<string, string> = {};\n for (const f of visibleFields(fields, state)) {\n const st = state[f.name];\n if (!st) continue;\n if (f.kind === \"select\") {\n if (st.otherChosen) {\n if (!st.otherText.trim()) errors[f.name] = \"Enter a value or choose an option\";\n } else if (st.selected.length === 0) errors[f.name] = \"Choose an option\";\n } else if (f.kind === \"multiselect\") {\n const n = st.selected.length + (st.otherChosen && st.otherText.trim() ? 1 : 0);\n if (st.otherChosen && !st.otherText.trim()) errors[f.name] = \"Enter a value for Other\";\n else if (f.min !== undefined && n < f.min) errors[f.name] = `Choose at least ${f.min}`;\n else if (f.max !== undefined && n > f.max) errors[f.name] = `Choose at most ${f.max}`;\n }\n }\n return errors;\n}\n\n/** Choose an option of a select (clears \"other\"). */\nexport function chooseSelect(st: FieldState, value: string): FieldState {\n return { ...st, selected: [value], otherChosen: false };\n}\n\n/** Choose \"other\" on a select. */\nexport function chooseSelectOther(st: FieldState): FieldState {\n return { ...st, selected: [], otherChosen: true };\n}\n\n/** Toggle a multiselect option, respecting `max` (a toggle past max is ignored). */\nexport function toggleMulti(st: FieldState, value: string, max?: number): FieldState {\n if (st.selected.includes(value)) {\n return { ...st, selected: st.selected.filter((v) => v !== value) };\n }\n const count = st.selected.length + (st.otherChosen ? 1 : 0);\n if (max !== undefined && count >= max) return st;\n return { ...st, selected: [...st.selected, value] };\n}\n","import type { Field, FieldOption, UINode } from \"@switchyard/protocol\";\nimport { Check } from \"lucide-react\";\nimport { useId, useMemo, useState } from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport { Button } from \"../ui/Button\";\nimport { TextArea, TextInput } from \"../ui/TextArea\";\nimport { useIntent } from \"./context\";\nimport {\n buildValues,\n chooseSelect,\n chooseSelectOther,\n type FieldState,\n type FormState,\n initialFormState,\n toggleMulti,\n validateForm,\n visibleFields,\n} from \"./formLogic\";\n\ntype FormNode = Extract<UINode, { t: \"form\" }>;\n\nexport interface FormRendererProps {\n node: FormNode;\n className?: string;\n}\n\n/**\n * Structured question form. Selects render as radio cards, multiselects as\n * toggle cards (never comma-separated entry), `allowOther` adds a free-text\n * option, `showIf` hides dependent fields (omitted from the values).\n * Submits `{kind: \"form\", values}` through the IntentContext.\n */\nexport function FormRenderer({ node, className }: FormRendererProps) {\n const { onRespond, busy, disabled } = useIntent();\n const [state, setState] = useState<FormState>(() => initialFormState(node.fields));\n const [attempted, setAttempted] = useState(false);\n const visible = useMemo(() => visibleFields(node.fields, state), [node.fields, state]);\n const errors = useMemo(() => validateForm(node.fields, state), [node.fields, state]);\n const locked = disabled || busy;\n const setField = (name: string, fs: FieldState) => setState((s) => ({ ...s, [name]: fs }));\n\n return (\n <form\n className={cn(\"flex flex-col gap-4\", className)}\n noValidate\n onSubmit={(e) => {\n e.preventDefault();\n setAttempted(true);\n if (Object.keys(errors).length > 0 || locked) return;\n onRespond?.({ kind: \"form\", values: buildValues(node.fields, state) });\n }}\n >\n {visible.map((f) => (\n <FieldView\n key={f.name}\n field={f}\n state={state[f.name]!}\n onChange={(fs) => setField(f.name, fs)}\n error={attempted ? errors[f.name] : undefined}\n disabled={locked}\n />\n ))}\n {!disabled && (\n <div className=\"flex flex-wrap items-center gap-2\">\n <Button type=\"submit\" variant=\"primary\" busy={busy}>\n {node.submitLabel || \"Submit\"}\n </Button>\n <Button\n type=\"button\"\n variant=\"secondary\"\n disabled={busy}\n onClick={() => onRespond?.({ kind: \"cancel\" })}\n >\n {node.cancelLabel || \"Cancel\"}\n </Button>\n {attempted && Object.keys(errors).length > 0 && (\n <span role=\"alert\" className=\"text-sm text-danger\">\n Complete the highlighted fields.\n </span>\n )}\n </div>\n )}\n </form>\n );\n}\n\nfunction FieldView({\n field,\n state,\n onChange,\n error,\n disabled,\n}: {\n field: Field;\n state: FieldState;\n onChange: (s: FieldState) => void;\n error?: string;\n disabled?: boolean;\n}) {\n const id = useId();\n const errId = `${id}-err`;\n if (field.kind === \"text\") {\n const common = {\n id,\n value: state.text,\n placeholder: field.placeholder,\n disabled,\n \"aria-invalid\": !!error || undefined,\n \"aria-describedby\": error ? errId : undefined,\n };\n return (\n <div className=\"flex flex-col gap-1.5\">\n <label htmlFor={id} className=\"text-sm font-medium\">\n {field.label}\n </label>\n {field.multiline ? (\n <TextArea\n {...common}\n minRows={3}\n onChange={(e) => onChange({ ...state, text: e.target.value })}\n />\n ) : (\n <TextInput {...common} onChange={(e) => onChange({ ...state, text: e.target.value })} />\n )}\n {error && (\n <p id={errId} className=\"text-sm text-danger\">\n {error}\n </p>\n )}\n </div>\n );\n }\n\n const multi = field.kind === \"multiselect\";\n const selectedPreview =\n !multi && state.selected[0]\n ? field.options.find((o) => o.value === state.selected[0])?.preview\n : undefined;\n const hint =\n multi && (field.min !== undefined || field.max !== undefined)\n ? field.min !== undefined && field.max !== undefined\n ? `Choose ${field.min}–${field.max}`\n : field.min !== undefined\n ? `Choose at least ${field.min}`\n : `Choose up to ${field.max}`\n : multi\n ? \"Choose any\"\n : undefined;\n\n return (\n <fieldset\n className=\"flex min-w-0 flex-col gap-2\"\n aria-describedby={error ? errId : undefined}\n aria-invalid={!!error || undefined}\n >\n <legend className=\"mb-2 text-sm font-medium\">\n {field.label}\n {hint && <span className=\"ml-2 font-normal text-muted\">{hint}</span>}\n </legend>\n <div className=\"grid gap-2\">\n {field.options.map((o) => (\n <OptionCard\n key={o.value}\n name={id}\n option={o}\n multi={multi}\n checked={state.selected.includes(o.value)}\n disabled={disabled}\n onToggle={() =>\n onChange(\n multi\n ? toggleMulti(\n state,\n o.value,\n field.kind === \"multiselect\" ? field.max : undefined,\n )\n : chooseSelect(state, o.value),\n )\n }\n />\n ))}\n {field.allowOther && (\n <OptionCard\n name={id}\n option={{ value: \"__other__\", label: field.allowOther.label || \"Other\" }}\n multi={multi}\n checked={state.otherChosen}\n disabled={disabled}\n onToggle={() =>\n onChange(\n multi ? { ...state, otherChosen: !state.otherChosen } : chooseSelectOther(state),\n )\n }\n />\n )}\n </div>\n {field.allowOther && state.otherChosen && (\n <TextInput\n aria-label={field.allowOther.label || \"Other\"}\n placeholder={field.allowOther.placeholder ?? \"Type your answer\"}\n value={state.otherText}\n disabled={disabled}\n autoFocus\n onChange={(e) => onChange({ ...state, otherText: e.target.value })}\n />\n )}\n {selectedPreview && (\n <pre className=\"max-h-64 max-w-full overflow-auto rounded-md border border-border bg-surface-2 px-3 py-2 text-xs leading-5\">\n {selectedPreview}\n </pre>\n )}\n {error && (\n <p id={errId} className=\"text-sm text-danger\">\n {error}\n </p>\n )}\n </fieldset>\n );\n}\n\nfunction OptionCard({\n name,\n option,\n multi,\n checked,\n disabled,\n onToggle,\n}: {\n name: string;\n option: FieldOption;\n multi: boolean;\n checked: boolean;\n disabled?: boolean;\n onToggle: () => void;\n}) {\n return (\n <label\n className={cn(\n \"tap flex min-w-0 cursor-pointer items-start gap-3 rounded-lg border px-3 py-2.5 text-sm\",\n \"has-[:focus-visible]:outline-2 has-[:focus-visible]:outline-offset-2 has-[:focus-visible]:outline-accent\",\n checked ? \"border-accent bg-accent-soft\" : \"border-border bg-surface hover:bg-surface-2\",\n disabled && \"cursor-not-allowed opacity-70\",\n )}\n >\n <input\n type={multi ? \"checkbox\" : \"radio\"}\n name={name}\n value={option.value}\n checked={checked}\n disabled={disabled}\n onChange={onToggle}\n className=\"sr-only\"\n />\n <span\n aria-hidden\n className={cn(\n \"mt-0.5 inline-flex size-4 shrink-0 items-center justify-center border\",\n multi ? \"rounded\" : \"rounded-full\",\n checked ? \"border-accent bg-accent text-accent-fg\" : \"border-border-strong bg-surface\",\n )}\n >\n {checked &&\n (multi ? (\n <Check className=\"size-3\" />\n ) : (\n <span className=\"size-1.5 rounded-full bg-accent-fg\" />\n ))}\n </span>\n <span className=\"min-w-0 flex-1\">\n <span className=\"block font-medium break-words\">{option.label}</span>\n {option.description && (\n <span className=\"block text-muted break-words\">{option.description}</span>\n )}\n </span>\n </label>\n );\n}\n","import type { UINode, UIRef } from \"@switchyard/protocol\";\nimport { ChevronRight, CircleCheck, CircleX, FileCode, LoaderCircle } from \"lucide-react\";\nimport { useId, useState } from \"react\";\nimport { Link } from \"react-router\";\nimport { cn } from \"../../lib/cn\";\nimport { Button } from \"../ui/Button\";\nimport { TabPanel, Tabs } from \"../ui/Tabs\";\nimport { CodeBlock } from \"./CodeBlock\";\nimport { ConfirmRenderer } from \"./ConfirmRenderer\";\nimport { IntentContext, type IntentHandlers, useIntent } from \"./context\";\nimport { DiffView } from \"./DiffView\";\nimport { FormRenderer } from \"./FormRenderer\";\nimport { Markdown } from \"./Markdown\";\n\nexport interface UINodeRendererProps extends IntentHandlers {\n node: UINode;\n className?: string;\n}\n\n/**\n * Renders a portable UINode tree. Interactive nodes (form, confirm, actions)\n * respond through the handlers given here (or an enclosing IntentContext).\n */\nexport function UINodeRenderer({ node, className, ...handlers }: UINodeRendererProps) {\n const parent = useIntent();\n const hasOwn = Object.values(handlers).some((v) => v !== undefined);\n const content = (\n <div className={cn(\"flex min-w-0 flex-col gap-3\", className)}>\n <NodeView node={node} />\n </div>\n );\n if (!hasOwn) return content;\n return (\n <IntentContext.Provider value={{ ...parent, ...stripUndefined(handlers) }}>\n {content}\n </IntentContext.Provider>\n );\n}\n\nfunction stripUndefined<T extends object>(o: T): Partial<T> {\n return Object.fromEntries(Object.entries(o).filter(([, v]) => v !== undefined)) as Partial<T>;\n}\n\nconst TONE_TEXT = {\n default: \"text-text\",\n muted: \"text-muted\",\n success: \"text-success\",\n warning: \"text-warning\",\n danger: \"text-danger\",\n} as const;\n\nexport function NodeView({ node }: { node: UINode }) {\n switch (node.t) {\n case \"text\":\n return (\n <p\n className={cn(\n \"text-sm break-words whitespace-pre-wrap\",\n TONE_TEXT[node.tone ?? \"default\"],\n )}\n >\n {node.text}\n </p>\n );\n case \"markdown\":\n return <Markdown text={node.text} />;\n case \"code\":\n return <CodeBlock text={node.text} lang={node.lang} maxHeight=\"24rem\" />;\n case \"diff\":\n return <DiffView patch={node.patch} />;\n case \"list\":\n return <ListView node={node} />;\n case \"table\":\n return (\n <div className=\"max-w-full overflow-x-auto overscroll-x-contain rounded-md border border-border\">\n <table className=\"w-full border-collapse text-sm\">\n <thead className=\"bg-surface-2\">\n <tr>\n {node.columns.map((c, i) => (\n <th\n // biome-ignore lint/suspicious/noArrayIndexKey: columns are positional\n key={i}\n scope=\"col\"\n className=\"border-b border-border px-3 py-1.5 text-left font-medium\"\n >\n {c}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {node.rows.map((r, ri) => (\n // biome-ignore lint/suspicious/noArrayIndexKey: rows are positional\n <tr key={ri} className=\"border-b border-border last:border-b-0\">\n {r.map((cell, ci) => (\n // biome-ignore lint/suspicious/noArrayIndexKey: cells are positional\n <td key={ci} className=\"px-3 py-1.5 align-top break-words\">\n {cell}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n case \"section\":\n return <SectionView node={node} />;\n case \"tabs\":\n return <TabsView node={node} />;\n case \"progress\":\n return <ProgressView node={node} />;\n case \"ref\":\n return <RefView refValue={node.ref} label={node.label} />;\n case \"form\":\n return <FormRenderer node={node} />;\n case \"confirm\":\n return <ConfirmRenderer node={node} />;\n case \"actions\":\n return <ActionsView node={node} />;\n default:\n return null;\n }\n}\n\nfunction Children({ nodes }: { nodes: UINode[] }) {\n return (\n <>\n {nodes.map((n, i) => (\n // biome-ignore lint/suspicious/noArrayIndexKey: UINode trees have no ids\n <NodeView key={i} node={n} />\n ))}\n </>\n );\n}\n\nfunction ListView({ node }: { node: Extract<UINode, { t: \"list\" }> }) {\n const Tag = node.ordered ? \"ol\" : \"ul\";\n return (\n <Tag\n className={cn(\n \"flex flex-col gap-1.5 pl-5 text-sm\",\n node.ordered ? \"list-decimal\" : \"list-disc\",\n )}\n >\n {node.items.map((item, i) => (\n // biome-ignore lint/suspicious/noArrayIndexKey: list items are positional\n <li key={i} className=\"min-w-0\">\n <div className=\"flex min-w-0 flex-col gap-2\">\n <NodeView node={item} />\n </div>\n </li>\n ))}\n </Tag>\n );\n}\n\nfunction SectionView({ node }: { node: Extract<UINode, { t: \"section\" }> }) {\n if (node.collapsible) {\n return (\n <details className=\"group min-w-0 rounded-md border border-border\" open>\n <summary className=\"tap flex cursor-pointer list-none items-center gap-1.5 px-3 py-2 text-sm font-medium [&::-webkit-details-marker]:hidden\">\n <ChevronRight\n aria-hidden\n className=\"size-4 shrink-0 transition-transform group-open:rotate-90\"\n />\n {node.title ?? \"Details\"}\n </summary>\n <div className=\"flex min-w-0 flex-col gap-3 border-t border-border px-3 py-2\">\n <Children nodes={node.children} />\n </div>\n </details>\n );\n }\n return (\n <section className=\"flex min-w-0 flex-col gap-2\">\n {node.title && <h3 className=\"text-sm font-semibold\">{node.title}</h3>}\n <Children nodes={node.children} />\n </section>\n );\n}\n\nfunction TabsView({ node }: { node: Extract<UINode, { t: \"tabs\" }> }) {\n const prefix = useId();\n const [active, setActive] = useState(node.tabs[0]?.id ?? \"\");\n const current = node.tabs.find((t) => t.id === active) ?? node.tabs[0];\n if (!current) return null;\n return (\n <div className=\"flex min-w-0 flex-col gap-2\">\n <Tabs\n label=\"Sections\"\n idPrefix={prefix}\n tabs={node.tabs.map((t) => ({ id: t.id, label: t.label }))}\n value={current.id}\n onChange={setActive}\n scrollable\n />\n <TabPanel idPrefix={prefix} id={current.id} className=\"flex min-w-0 flex-col gap-3\">\n <Children nodes={current.children} />\n </TabPanel>\n </div>\n );\n}\n\nfunction ProgressView({ node }: { node: Extract<UINode, { t: \"progress\" }> }) {\n const status = node.status ?? \"running\";\n const Icon = status === \"ok\" ? CircleCheck : status === \"error\" ? CircleX : LoaderCircle;\n const statusText = status === \"ok\" ? \"Done\" : status === \"error\" ? \"Failed\" : \"In progress\";\n const pct = node.value === undefined ? null : Math.round(node.value * 100);\n return (\n <div className=\"flex min-w-0 flex-col gap-1\">\n <div className=\"flex items-center gap-2 text-sm\">\n <Icon\n aria-hidden\n className={cn(\n \"size-4 shrink-0\",\n status === \"ok\" && \"text-success\",\n status === \"error\" && \"text-danger\",\n status === \"running\" && \"animate-spin text-info\",\n )}\n />\n <span className=\"min-w-0 flex-1 truncate\">{node.label}</span>\n <span className=\"shrink-0 text-xs text-muted\">\n {statusText}\n {pct !== null ? ` · ${pct}%` : \"\"}\n </span>\n </div>\n {pct !== null && (\n <div\n role=\"progressbar\"\n aria-label={node.label}\n aria-valuenow={pct}\n aria-valuemin={0}\n aria-valuemax={100}\n className=\"h-1.5 overflow-hidden rounded-full bg-surface-3\"\n >\n <div\n className={cn(\n \"h-full rounded-full\",\n status === \"error\" ? \"bg-danger\" : status === \"ok\" ? \"bg-success\" : \"bg-accent\",\n )}\n style={{ width: `${pct}%` }}\n />\n </div>\n )}\n </div>\n );\n}\n\nexport function refHref(ref: UIRef): string | null {\n switch (ref.kind) {\n case \"session\":\n return `/code/${encodeURIComponent(ref.sessionId)}`;\n case \"task\":\n return `/tasks/${encodeURIComponent(ref.taskId)}`;\n default:\n return null;\n }\n}\n\nfunction RefView({ refValue, label }: { refValue: UIRef; label: string }) {\n const { onOpenFile } = useIntent();\n const href = refHref(refValue);\n if (href) {\n return (\n <Link to={href} className=\"text-sm text-accent underline underline-offset-2\">\n {label}\n </Link>\n );\n }\n if (refValue.kind === \"file\") {\n if (onOpenFile) {\n return (\n <button\n type=\"button\"\n onClick={() => onOpenFile(refValue.path)}\n className=\"inline-flex min-w-0 items-center gap-1 text-left text-sm text-accent underline underline-offset-2\"\n >\n <FileCode aria-hidden className=\"size-4 shrink-0\" />\n <span className=\"truncate\">{label || refValue.path}</span>\n </button>\n );\n }\n return (\n <span\n className=\"inline-flex min-w-0 items-center gap-1 font-mono text-sm\"\n title={refValue.path}\n >\n <FileCode aria-hidden className=\"size-4 shrink-0 text-muted\" />\n <span className=\"truncate\">{label || refValue.path}</span>\n </span>\n );\n }\n if (refValue.kind !== \"native_session\") return <span className=\"text-sm\">{label}</span>;\n return (\n <span className=\"text-sm\" title={refValue.sessionFile}>\n {label} <span className=\"text-muted\">(native Pi session, not imported)</span>\n </span>\n );\n}\n\nfunction ActionsView({ node }: { node: Extract<UINode, { t: \"actions\" }> }) {\n const { onRespond, onAction, busy, disabled } = useIntent();\n if (disabled) return null;\n return (\n <div className=\"flex flex-wrap gap-2\">\n {node.actions.map((a) => (\n <Button\n key={a.id}\n variant={a.tone === \"primary\" ? \"primary\" : a.tone === \"danger\" ? \"danger\" : \"secondary\"}\n disabled={busy || (!onRespond && !onAction)}\n onClick={() => {\n if (onRespond) onRespond({ kind: \"action\", actionId: a.id });\n else onAction?.(a.id);\n }}\n >\n {a.label}\n </Button>\n ))}\n </div>\n );\n}\n","import type { Interaction, UINode } from \"@switchyard/protocol\";\n\n/** What actually happened when an extension opened a terminal-only `ctx.ui.custom()` dialog. */\nexport const UNSUPPORTED_COPY =\n \"An extension opened a terminal-only dialog. In RPC mode Pi gave it no answer, so the extension continued without one.\";\n\nexport interface UnsupportedAction {\n id: \"abort\" | \"message\";\n label: string;\n tone: \"primary\" | \"secondary\" | \"danger\";\n}\n\nconst DEFAULT_ACTIONS: UnsupportedAction[] = [\n { id: \"abort\", label: \"Stop the run\", tone: \"danger\" },\n { id: \"message\", label: \"Send a message to the agent\", tone: \"primary\" },\n];\n\nfunction findActions(node: UINode): Extract<UINode, { t: \"actions\" }> | null {\n if (node.t === \"actions\") return node;\n if (node.t === \"section\") {\n for (const c of node.children) {\n const found = findActions(c);\n if (found) return found;\n }\n }\n return null;\n}\n\nexport interface UnsupportedView {\n /** True until a person chose one of the alternatives. */\n answerable: boolean;\n actions: UnsupportedAction[];\n copy: string;\n}\n\nexport function isUnsupported(i: Interaction): boolean {\n return i.state === \"unsupported\" || i.source.kind === \"unsupported_custom\";\n}\n\n/** The alternatives the host offers for an unsupported dialog (stop the run, message). */\nexport function unsupportedView(i: Interaction): UnsupportedView {\n const node = findActions(i.presentation);\n const offered = (node?.actions ?? [])\n .filter(\n (a): a is typeof a & { id: \"abort\" | \"message\" } => a.id === \"abort\" || a.id === \"message\",\n )\n .map((a) => ({\n id: a.id,\n label: a.label,\n tone: (a.tone === \"default\"\n ? \"secondary\"\n : (a.tone ?? (a.id === \"abort\" ? \"danger\" : \"primary\"))) as UnsupportedAction[\"tone\"],\n }));\n return {\n answerable: i.state === \"unsupported\" && i.resolution === null,\n actions: offered.length > 0 ? offered : DEFAULT_ACTIONS,\n copy: UNSUPPORTED_COPY,\n };\n}\n\n/** A follow-up while Pi is still working queues behind the current turn. */\nexport function messageMode(runtime: string | undefined): \"prompt\" | \"followUp\" {\n return runtime === \"running\" || runtime === \"waiting_input\" ? \"followUp\" : \"prompt\";\n}\n","import type { Interaction, InteractionResponse, UINode } from \"@switchyard/protocol\";\nimport { useState } from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport { formatRelative } from \"../../lib/time\";\nimport { apiPost, errorMessage, isApiError } from \"../../sync/api\";\nimport { useSyncStore } from \"../../sync/store\";\nimport { Button } from \"../ui/Button\";\nimport { StatusChip } from \"../ui/StatusChip\";\nimport { ErrorState } from \"../ui/states\";\nimport { TextArea } from \"../ui/TextArea\";\nimport { UINodeRenderer } from \"./UINodeRenderer\";\nimport { isUnsupported, messageMode, unsupportedView } from \"./unsupported\";\n\nexport interface InteractionCardProps {\n interaction: Interaction;\n /** Read-only session or host offline: show the question without answer controls. */\n readOnlyReason?: string | null;\n className?: string;\n /** Called after the coordinator acknowledged an answer. */\n onAnswered?: (interaction: Interaction) => void;\n /** DOM id (the \"Needs your answer\" strip scrolls to it). */\n id?: string;\n}\n\nfunction hasInteractive(node: UINode): boolean {\n switch (node.t) {\n case \"form\":\n case \"confirm\":\n case \"actions\":\n return true;\n case \"list\":\n return node.items.some(hasInteractive);\n case \"section\":\n return node.children.some(hasInteractive);\n case \"tabs\":\n return node.tabs.some((t) => t.children.some(hasInteractive));\n default:\n return false;\n }\n}\n\nfunction byLabel(by: string): string {\n if (by === \"host\") return \"the host\";\n if (by === \"pi\") return \"Pi\";\n return \"a device\";\n}\n\n/**\n * A runtime interaction (extension dialog). Posts the answer with the\n * interaction revision and waits for the acknowledgement; there is no\n * optimistic resolution. A 409 shows \"Already answered: <summary>\".\n */\nexport function InteractionCard({\n interaction: fromProps,\n readOnlyReason,\n className,\n onAnswered,\n id,\n}: InteractionCardProps) {\n const upsert = useSyncStore((s) => s.upsertInteraction);\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<unknown>(null);\n const [alreadyAnswered, setAlreadyAnswered] = useState<string | null>(null);\n const [lastResponse, setLastResponse] = useState<InteractionResponse | null>(null);\n // The acknowledged interaction from the answer/409 response, until the prop catches up.\n const [acked, setAcked] = useState<Interaction | null>(null);\n const interaction =\n acked && acked.id === fromProps.id && acked.revision > fromProps.revision ? acked : fromProps;\n\n const pending = interaction.state === \"pending\";\n const unsupported = isUnsupported(interaction);\n const sessionRuntime = useSyncStore((s) => s.sessions[interaction.sessionId]?.runtime);\n const [composing, setComposing] = useState(false);\n const [message, setMessage] = useState(\"\");\n\n const respond = async (response: InteractionResponse): Promise<boolean> => {\n setBusy(true);\n setError(null);\n setLastResponse(response);\n try {\n const res = await apiPost<{ status: string; interaction: Interaction }>(\n `/api/interactions/${encodeURIComponent(interaction.id)}/answer`,\n { revision: interaction.revision, response },\n );\n if (res?.interaction) {\n upsert(res.interaction);\n setAcked(res.interaction);\n onAnswered?.(res.interaction);\n }\n return true;\n } catch (e) {\n if (isApiError(e, \"already_answered\")) {\n const other = (e.details as { interaction?: Interaction } | undefined)?.interaction;\n if (other) {\n upsert(other);\n setAcked(other);\n }\n setAlreadyAnswered(other?.resolution?.summary ?? \"answered on another device\");\n } else {\n setError(e);\n }\n return false;\n } finally {\n setBusy(false);\n }\n };\n\n /** \"Send a message to the agent\": deliver the message first, then record the choice. */\n const sendMessage = async () => {\n const text = message.trim();\n if (!text) return;\n setBusy(true);\n setError(null);\n try {\n await apiPost(`/api/sessions/${encodeURIComponent(interaction.sessionId)}/prompt`, {\n text,\n mode: messageMode(sessionRuntime),\n });\n } catch (e) {\n setError(e);\n setBusy(false);\n return;\n }\n setBusy(false);\n if (await respond({ kind: \"action\", actionId: \"message\" })) {\n setComposing(false);\n setMessage(\"\");\n }\n };\n\n return (\n <article\n id={id}\n aria-label={`Question: ${interaction.title}`}\n className={cn(\n \"flex min-w-0 flex-col gap-3 rounded-lg border bg-surface p-3\",\n pending ? \"border-warning\" : \"border-border\",\n className,\n )}\n >\n <header className=\"flex min-w-0 flex-wrap items-start gap-2\">\n <h3 className=\"min-w-0 flex-1 text-sm font-semibold break-words\">{interaction.title}</h3>\n <StatusChip kind=\"interaction\" value={interaction.state} size=\"sm\" />\n </header>\n\n {alreadyAnswered && (\n <p role=\"status\" className=\"rounded-md bg-surface-2 px-3 py-2 text-sm\">\n Already answered: {alreadyAnswered}\n </p>\n )}\n\n {unsupported ? (\n <UnsupportedBody\n interaction={interaction}\n readOnlyReason={readOnlyReason ?? null}\n busy={busy}\n answered={alreadyAnswered !== null}\n composing={composing}\n message={message}\n setMessage={setMessage}\n onAction={(actionId) => {\n if (actionId === \"message\") setComposing(true);\n else void respond({ kind: \"action\", actionId });\n }}\n onSend={() => void sendMessage()}\n onCancelMessage={() => setComposing(false)}\n />\n ) : pending && !alreadyAnswered ? (\n <>\n {readOnlyReason && <p className=\"text-sm text-muted\">{readOnlyReason}</p>}\n <UINodeRenderer\n node={interaction.presentation}\n onRespond={(r) => void respond(r)}\n busy={busy}\n disabled={!!readOnlyReason}\n />\n {!readOnlyReason && !hasInteractive(interaction.presentation) && (\n <div>\n <Button busy={busy} onClick={() => void respond({ kind: \"cancel\" })}>\n Dismiss\n </Button>\n </div>\n )}\n {busy && (\n <p role=\"status\" className=\"text-sm text-muted\">\n Sending answer… waiting for the host to confirm.\n </p>\n )}\n </>\n ) : alreadyAnswered ? null : interaction.resolution ? (\n <p className=\"text-sm text-muted\">\n {interaction.state === \"resolved\" ? \"Answered\" : \"Closed\"} by{\" \"}\n {byLabel(interaction.resolution.by)} {formatRelative(interaction.resolution.at)}:{\" \"}\n <span className=\"text-text\">{interaction.resolution.summary}</span>\n </p>\n ) : (\n <p className=\"text-sm text-muted\">\n {interaction.state === \"expired\"\n ? \"This question expired before it was answered (Pi closed the dialog).\"\n : \"This question was cancelled.\"}\n </p>\n )}\n\n {error !== null && (\n <ErrorState\n compact\n title=\"Answer not delivered\"\n error={errorMessage(error)}\n onRetry={lastResponse ? () => void respond(lastResponse) : undefined}\n />\n )}\n </article>\n );\n}\n\n/** A terminal-only dialog: what happened, and the alternatives the host offers until one is chosen. */\nfunction UnsupportedBody({\n interaction,\n readOnlyReason,\n busy,\n answered,\n composing,\n message,\n setMessage,\n onAction,\n onSend,\n onCancelMessage,\n}: {\n interaction: Interaction;\n readOnlyReason: string | null;\n busy: boolean;\n answered: boolean;\n composing: boolean;\n message: string;\n setMessage: (t: string) => void;\n onAction: (actionId: \"abort\" | \"message\") => void;\n onSend: () => void;\n onCancelMessage: () => void;\n}) {\n const view = unsupportedView(interaction);\n return (\n <div className=\"flex min-w-0 flex-col gap-2\">\n <p className=\"text-sm text-muted\">{view.copy}</p>\n {interaction.resolution ? (\n <p className=\"text-sm text-muted\">\n Chosen by {byLabel(interaction.resolution.by)} {formatRelative(interaction.resolution.at)}\n : <span className=\"text-text\">{interaction.resolution.summary}</span>\n </p>\n ) : !view.answerable || answered ? null : readOnlyReason ? (\n <p className=\"text-sm text-muted\">{readOnlyReason}</p>\n ) : composing ? (\n <div className=\"flex min-w-0 flex-col gap-2\">\n <TextArea\n aria-label=\"Message to the agent\"\n value={message}\n onChange={(e) => setMessage(e.target.value)}\n rows={3}\n autoFocus\n placeholder=\"Tell the agent what to do instead\"\n />\n <div className=\"flex flex-wrap gap-2\">\n <Button variant=\"primary\" busy={busy} disabled={!message.trim()} onClick={onSend}>\n Send message\n </Button>\n <Button disabled={busy} onClick={onCancelMessage}>\n Cancel\n </Button>\n </div>\n </div>\n ) : (\n <div className=\"flex flex-wrap gap-2\">\n {view.actions.map((a) => (\n <Button\n key={a.id}\n variant={a.tone}\n busy={busy && a.id === \"abort\"}\n disabled={busy}\n onClick={() => onAction(a.id)}\n >\n {a.label}\n </Button>\n ))}\n </div>\n )}\n </div>\n );\n}\n"],"ignoreList":[0],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"InteractionCard-cvPWKSu1.js","names":["createContext","useContext","useMemo","useState","useMemo","useId","_Fragment","useId","useState","useState","_Fragment","__toESM","Link","require_react","createLucideIcon","require_jsx_runtime","isApiError","useSyncStore","apiPost","errorMessage","cn","Button","ErrorState","formatRelative","Check","ChevronRight","CircleX","LoaderCircle","CircleCheck","StatusChip","TextInput","TextArea","Tabs","CodeBlock","TabPanel","Markdown","isFieldVisible","__iconData","FileCode","import_react","IntentContext","useIntent","import_jsx_runtime","ConfirmRenderer","node","disabled","onRespond","busy","stripPrefix","p","HUNK","parseUnifiedDiff","files","file","oldNo","newNo","oldLeft","newLeft","inHunk","consumed","start","f","lines","patch","line","m","l","h","MARKER","GUTTER_BG","DiffView","given","className","showFileHeaders","ref","selectable","onLineClick","marked","isLineMarked","li","fi","initialFormState","out","fields","fieldValue","st","field","vals","visibleFields","values","state","buildValues","v","validateForm","errors","n","chooseSelect","value","chooseSelectOther","toggleMulti","count","max","FormRenderer","setState","attempted","setAttempted","visible","locked","setField","s","name","fs","e","FieldView","id","errId","common","error","onChange","multi","selectedPreview","o","hint","OptionCard","checked","option","onToggle","UINodeRenderer","handlers","parent","hasOwn","content","NodeView","stripUndefined","TONE_TEXT","ListView","c","i","r","cell","ci","ri","SectionView","TabsView","ProgressView","RefView","ActionsView","Children","nodes","Tag","item","prefix","active","setActive","current","t","status","Icon","statusText","pct","refHref","href","refValue","label","onOpenFile","a","onAction","UNSUPPORTED_COPY","DEFAULT_ACTIONS","findActions","found","isUnsupported","unsupportedView","offered","messageMode","runtime","hasInteractive","byLabel","by","InteractionCard","fromProps","upsert","setBusy","setError","alreadyAnswered","setAlreadyAnswered","lastResponse","setLastResponse","acked","setAcked","interaction","pending","unsupported","sessionRuntime","composing","setComposing","message","setMessage","respond","response","res","onAnswered","other","sendMessage","text","UnsupportedBody","readOnlyReason","actionId","view","answered","onSend","onCancelMessage"],"sources":["../../../../node_modules/.pnpm/lucide-react@1.61.0_@types+react@19.3.0_react@19.3.1/node_modules/lucide-react/dist/esm/icons/file-code.mjs","../../src/components/intent/context.ts","../../src/components/intent/ConfirmRenderer.tsx","../../src/components/intent/diff.ts","../../src/components/intent/DiffView.tsx","../../src/components/intent/formLogic.ts","../../src/components/intent/FormRenderer.tsx","../../src/components/intent/UINodeRenderer.tsx","../../src/components/intent/unsupported.ts","../../src/components/intent/InteractionCard.tsx"],"sourcesContent":["/**\n * @license lucide-react v1.61.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconData = {\n name: \"file-code\",\n size: 24,\n node: [\n [\n \"path\",\n {\n d: \"M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z\",\n key: \"1oefj6\"\n }\n ],\n [\"path\", { d: \"M14 2v5a1 1 0 0 0 1 1h5\", key: \"wfsgrz\" }],\n [\"path\", { d: \"M10 12.5 8 15l2 2.5\", key: \"1tg20x\" }],\n [\"path\", { d: \"m14 12.5 2 2.5-2 2.5\", key: \"yinavb\" }]\n ]\n};\n__iconData.node;\nconst FileCode = createLucideIcon(__iconData);\n\nexport { __iconData, FileCode as default };\n//# sourceMappingURL=file-code.mjs.map\n","import type { InteractionResponse } from \"@switchyard/protocol\";\nimport { createContext, useContext } from \"react\";\n\n/** Handlers available to a rendered UINode tree. */\nexport interface IntentHandlers {\n /** Interaction context: form submit, confirm, cancel and action buttons respond here. */\n onRespond?: (response: InteractionResponse) => void;\n /** Panel/tool-card context: `actions` buttons call this when there is no `onRespond`. */\n onAction?: (actionId: string) => void;\n /** File refs call this when provided (e.g. open in the inspector); otherwise render as text. */\n onOpenFile?: (path: string) => void;\n /** A response is in flight: inputs stay visible, buttons show busy. */\n busy?: boolean;\n /** Read-only (already answered, expired, read-only session). */\n disabled?: boolean;\n}\n\nexport const IntentContext = createContext<IntentHandlers>({});\nexport const useIntent = () => useContext(IntentContext);\n","import type { UINode } from \"@switchyard/protocol\";\nimport { Button } from \"../ui/Button\";\nimport { useIntent } from \"./context\";\nimport { Markdown } from \"./Markdown\";\n\ntype ConfirmNode = Extract<UINode, { t: \"confirm\" }>;\n\n/** Yes/no question; responds `{kind: \"confirm\", confirmed}`. */\nexport function ConfirmRenderer({ node }: { node: ConfirmNode }) {\n const { onRespond, busy, disabled } = useIntent();\n return (\n <div className=\"flex flex-col gap-3\">\n <Markdown text={node.message} />\n {!disabled && (\n <div className=\"flex flex-wrap gap-2\">\n <Button\n variant={node.destructive ? \"danger\" : \"primary\"}\n busy={busy}\n onClick={() => onRespond?.({ kind: \"confirm\", confirmed: true })}\n >\n {node.confirmLabel || \"Confirm\"}\n </Button>\n <Button\n disabled={busy}\n onClick={() => onRespond?.({ kind: \"confirm\", confirmed: false })}\n >\n {node.cancelLabel || \"Cancel\"}\n </Button>\n </div>\n )}\n </div>\n );\n}\n","/** Unified diff parsing for DiffView (pure; tested without a DOM). */\n\nexport type DiffLineKind = \"add\" | \"del\" | \"context\" | \"hunk\" | \"meta\";\n\nexport interface DiffLine {\n kind: DiffLineKind;\n text: string;\n oldLine: number | null;\n newLine: number | null;\n}\n\nexport interface DiffFile {\n /** Display path (new path, or old path for deletions). */\n path: string;\n oldPath: string | null;\n newPath: string | null;\n status: \"modified\" | \"added\" | \"deleted\" | \"renamed\" | \"binary\";\n additions: number;\n deletions: number;\n lines: DiffLine[];\n}\n\nfunction stripPrefix(p: string): string | null {\n const t = p.trim().split(\"\\t\")[0]!;\n if (t === \"/dev/null\") return null;\n return t.replace(/^[ab]\\//, \"\");\n}\n\nconst HUNK = /^@@ -(\\d+)(?:,(\\d+))? \\+(\\d+)(?:,(\\d+))? @@/;\n\nexport function parseUnifiedDiff(patch: string): DiffFile[] {\n const files: DiffFile[] = [];\n let file: DiffFile | null = null;\n let oldNo = 0;\n let newNo = 0;\n let oldLeft = 0;\n let newLeft = 0;\n let inHunk = false;\n const consumed = () => {\n if (oldLeft <= 0 && newLeft <= 0) inHunk = false;\n };\n const start = (path = \"\"): DiffFile => {\n const f: DiffFile = {\n path,\n oldPath: null,\n newPath: null,\n status: \"modified\",\n additions: 0,\n deletions: 0,\n lines: [],\n };\n files.push(f);\n inHunk = false;\n return f;\n };\n const lines = patch.replace(/\\r\\n/g, \"\\n\").split(\"\\n\");\n if (lines[lines.length - 1] === \"\") lines.pop();\n for (const line of lines) {\n if (line.startsWith(\"diff --git \")) {\n const m = /^diff --git a\\/(.+?) b\\/(.+)$/.exec(line);\n file = start(m?.[2] ?? \"\");\n if (m) {\n file.oldPath = m[1]!;\n file.newPath = m[2]!;\n }\n continue;\n }\n if (!inHunk && line.startsWith(\"--- \")) {\n if (!file || file.lines.some((l) => l.kind !== \"meta\")) file = start();\n file.oldPath = stripPrefix(line.slice(4));\n if (file.oldPath === null) file.status = \"added\";\n continue;\n }\n if (!inHunk && line.startsWith(\"+++ \") && file) {\n file.newPath = stripPrefix(line.slice(4));\n if (file.newPath === null) file.status = \"deleted\";\n file.path = file.newPath ?? file.oldPath ?? file.path;\n continue;\n }\n const h = HUNK.exec(line);\n if (h) {\n if (!file) file = start();\n oldNo = Number(h[1]);\n newNo = Number(h[3]);\n oldLeft = h[2] === undefined ? 1 : Number(h[2]);\n newLeft = h[4] === undefined ? 1 : Number(h[4]);\n inHunk = oldLeft > 0 || newLeft > 0;\n file.lines.push({ kind: \"hunk\", text: line, oldLine: null, newLine: null });\n continue;\n }\n if (!file) file = start();\n if (inHunk && line.startsWith(\"+\")) {\n file.lines.push({ kind: \"add\", text: line.slice(1), oldLine: null, newLine: newNo++ });\n file.additions++;\n newLeft--;\n consumed();\n } else if (inHunk && line.startsWith(\"-\")) {\n file.lines.push({ kind: \"del\", text: line.slice(1), oldLine: oldNo++, newLine: null });\n file.deletions++;\n oldLeft--;\n consumed();\n } else if (inHunk && (line.startsWith(\" \") || line === \"\")) {\n file.lines.push({\n kind: \"context\",\n text: line.slice(1),\n oldLine: oldNo++,\n newLine: newNo++,\n });\n oldLeft--;\n newLeft--;\n consumed();\n } else if (line.startsWith(\"\\\\\")) {\n file.lines.push({ kind: \"meta\", text: line, oldLine: null, newLine: null });\n } else {\n // Header lines (index, mode, rename, Binary files ...).\n inHunk = false;\n if (line.startsWith(\"new file mode\")) file.status = \"added\";\n else if (line.startsWith(\"deleted file mode\")) file.status = \"deleted\";\n else if (line.startsWith(\"rename from \")) {\n file.status = \"renamed\";\n file.oldPath = line.slice(12);\n } else if (line.startsWith(\"rename to \")) {\n file.status = \"renamed\";\n file.newPath = line.slice(10);\n file.path = file.newPath;\n } else if (line.startsWith(\"Binary files\")) file.status = \"binary\";\n file.lines.push({ kind: \"meta\", text: line, oldLine: null, newLine: null });\n }\n }\n return files;\n}\n","import { useMemo } from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport { type DiffFile, type DiffLine, parseUnifiedDiff } from \"./diff\";\n\nexport interface DiffLineRef {\n file: string;\n line: DiffLine;\n}\n\nexport interface DiffViewProps {\n /** Unified diff text (one or more files). */\n patch?: string;\n /** Pre-parsed files (alternative to `patch`). */\n files?: DiffFile[];\n /** Show a header per file (default true). */\n showFileHeaders?: boolean;\n /** Enables line selection (e.g. review comments). Called for add/context/del lines. */\n onLineClick?: (ref: DiffLineRef) => void;\n /** Highlight lines (e.g. lines with comments). */\n isLineMarked?: (ref: DiffLineRef) => boolean;\n className?: string;\n}\n\nconst MARKER: Record<DiffLine[\"kind\"], string> = {\n add: \"+\",\n del: \"-\",\n context: \" \",\n hunk: \"\",\n meta: \"\",\n};\n\n/** Opaque gutter backgrounds (the gutter is sticky, so it must cover scrolled text). */\nconst GUTTER_BG: Record<DiffLine[\"kind\"], string> = {\n add: \"bg-diff-add\",\n del: \"bg-diff-del\",\n hunk: \"bg-diff-hunk\",\n context: \"bg-surface\",\n meta: \"bg-surface\",\n};\n\n/**\n * Unified diff with old/new line numbers, +/- text markers (not color alone)\n * and tinted rows. Horizontal scrolling is confined to the diff block, and the line-number\n * gutter is sticky so it stays visible while a long line is scrolled.\n */\nexport function DiffView({\n patch,\n files: given,\n showFileHeaders = true,\n onLineClick,\n isLineMarked,\n className,\n}: DiffViewProps) {\n const files = useMemo(() => given ?? parseUnifiedDiff(patch ?? \"\"), [given, patch]);\n if (files.length === 0) {\n return <p className=\"text-sm text-muted\">No changes.</p>;\n }\n return (\n <div className={cn(\"flex min-w-0 flex-col gap-3\", className)}>\n {files.map((f, fi) => (\n <section\n // biome-ignore lint/suspicious/noArrayIndexKey: files can repeat paths in odd patches\n key={`${f.path}-${fi}`}\n className=\"min-w-0 overflow-hidden rounded-md border border-border\"\n aria-label={`Diff of ${f.path || \"file\"}`}\n >\n {showFileHeaders && (\n <header className=\"flex min-w-0 items-center gap-2 border-b border-border bg-surface-2 px-3 py-1.5 text-sm\">\n <span className=\"min-w-0 flex-1 truncate font-mono\" title={f.path}>\n {f.status === \"renamed\" && f.oldPath ? `${f.oldPath} → ${f.path}` : f.path}\n </span>\n <span className=\"shrink-0 font-mono text-xs\">\n <span className=\"text-success\">\n +{f.additions}\n <span className=\"sr-only\"> added</span>\n </span>{\" \"}\n <span className=\"text-danger\">\n -{f.deletions}\n <span className=\"sr-only\"> deleted</span>\n </span>\n </span>\n </header>\n )}\n {f.status === \"binary\" ? (\n <p className=\"px-3 py-2 text-sm text-muted\">Binary file not shown.</p>\n ) : (\n <div className=\"max-w-full overflow-x-auto overscroll-x-contain\">\n <table className=\"w-full border-collapse font-mono text-xs leading-5\">\n <tbody>\n {f.lines.map((l, li) => {\n const ref = { file: f.path, line: l };\n const selectable =\n !!onLineClick &&\n (l.kind === \"add\" || l.kind === \"del\" || l.kind === \"context\");\n const marked = isLineMarked?.(ref) ?? false;\n return (\n <tr\n // biome-ignore lint/suspicious/noArrayIndexKey: diff lines are positional\n key={li}\n className={cn(\n l.kind === \"add\" && \"bg-diff-add\",\n l.kind === \"del\" && \"bg-diff-del\",\n l.kind === \"hunk\" && \"bg-diff-hunk text-muted\",\n l.kind === \"meta\" && \"text-muted\",\n marked && \"outline outline-1 -outline-offset-1 outline-warning\",\n )}\n >\n <td\n className={cn(\n \"sticky left-0 z-[1] w-[6.25rem] min-w-[6.25rem] select-none whitespace-nowrap p-0\",\n GUTTER_BG[l.kind],\n )}\n >\n <span className=\"flex\">\n <span className=\"w-10 shrink-0 border-r border-border px-1.5 text-right text-subtle tabular-nums\">\n {l.oldLine ?? \"\"}\n </span>\n <span className=\"w-10 shrink-0 border-r border-border px-1.5 text-right text-subtle tabular-nums\">\n {l.newLine ?? \"\"}\n </span>\n <span\n aria-hidden\n className={cn(\n \"w-5 shrink-0 text-center\",\n l.kind === \"add\" && \"text-success\",\n l.kind === \"del\" && \"text-danger\",\n )}\n >\n {MARKER[l.kind]}\n </span>\n {(l.kind === \"add\" || l.kind === \"del\") && (\n <span className=\"sr-only\">\n {l.kind === \"add\" ? \"added\" : \"deleted\"}\n </span>\n )}\n </span>\n </td>\n <td className=\"whitespace-pre pr-3\">\n {selectable ? (\n <button\n type=\"button\"\n data-diff-line={l.newLine ?? l.oldLine ?? undefined}\n // Keyboard focus scrolls the line into view clear of the sticky gutter.\n className=\"block w-full scroll-ml-[6.25rem] cursor-pointer text-left whitespace-pre hover:underline focus-visible:underline\"\n // A pointer click must not scroll the diff sideways (the button spans\n // the whole long line): skip the focus scroll, then focus in place.\n onMouseDown={(e) => e.preventDefault()}\n onClick={(e) => {\n e.currentTarget.focus({ preventScroll: true });\n onLineClick?.(ref);\n }}\n aria-label={`Comment on line ${l.newLine ?? l.oldLine}`}\n >\n {l.text || \" \"}\n </button>\n ) : (\n l.text\n )}\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n )}\n </section>\n ))}\n </div>\n );\n}\n","import { type Field, type FormValue, isFieldVisible } from \"@switchyard/protocol\";\n\n/**\n * Pure form state logic for FormRenderer (tested without a DOM).\n *\n * Each field keeps its raw UI state; `buildValues` turns it into the\n * submitted `InteractionResponse` values, omitting hidden fields.\n */\n\nexport interface FieldState {\n /** Selected option values (select: at most one). */\n selected: string[];\n /** \"Other\" chosen (select/multiselect with allowOther). */\n otherChosen: boolean;\n otherText: string;\n /** Text field value. */\n text: string;\n}\n\nexport type FormState = Record<string, FieldState>;\n\nexport function initialFormState(fields: Field[]): FormState {\n const out: FormState = {};\n for (const f of fields) {\n out[f.name] = {\n selected: [],\n otherChosen: false,\n otherText: \"\",\n text: f.kind === \"text\" ? (f.prefill ?? \"\") : \"\",\n };\n }\n return out;\n}\n\n/** The value a field contributes, or undefined when nothing is chosen. */\nexport function fieldValue(field: Field, st: FieldState | undefined): FormValue | undefined {\n if (!st) return undefined;\n switch (field.kind) {\n case \"text\":\n return st.text;\n case \"select\":\n if (st.otherChosen) return { other: st.otherText };\n return st.selected[0];\n case \"multiselect\": {\n const vals = [...st.selected];\n // Multiselect \"other\" text is submitted as an extra entry.\n if (st.otherChosen && st.otherText.trim()) vals.push(st.otherText.trim());\n return vals;\n }\n }\n}\n\n/**\n * Visible fields in order. `showIf` refers to an earlier field, so visibility\n * is evaluated against the values of fields that are themselves visible.\n */\nexport function visibleFields(fields: Field[], state: FormState): Field[] {\n const values: Record<string, FormValue | undefined> = {};\n const out: Field[] = [];\n for (const f of fields) {\n if (!isFieldVisible(f, values)) continue;\n out.push(f);\n values[f.name] = fieldValue(f, state[f.name]);\n }\n return out;\n}\n\n/** Submitted values: visible fields only. */\nexport function buildValues(fields: Field[], state: FormState): Record<string, FormValue> {\n const out: Record<string, FormValue> = {};\n for (const f of visibleFields(fields, state)) {\n const v = fieldValue(f, state[f.name]);\n if (v !== undefined) out[f.name] = v;\n }\n return out;\n}\n\n/** Validation errors keyed by field name (visible fields only). Empty when valid. */\nexport function validateForm(fields: Field[], state: FormState): Record<string, string> {\n const errors: Record<string, string> = {};\n for (const f of visibleFields(fields, state)) {\n const st = state[f.name];\n if (!st) continue;\n if (f.kind === \"select\") {\n if (st.otherChosen) {\n if (!st.otherText.trim()) errors[f.name] = \"Enter a value or choose an option\";\n } else if (st.selected.length === 0) errors[f.name] = \"Choose an option\";\n } else if (f.kind === \"multiselect\") {\n const n = st.selected.length + (st.otherChosen && st.otherText.trim() ? 1 : 0);\n if (st.otherChosen && !st.otherText.trim()) errors[f.name] = \"Enter a value for Other\";\n else if (f.min !== undefined && n < f.min) errors[f.name] = `Choose at least ${f.min}`;\n else if (f.max !== undefined && n > f.max) errors[f.name] = `Choose at most ${f.max}`;\n }\n }\n return errors;\n}\n\n/** Choose an option of a select (clears \"other\"). */\nexport function chooseSelect(st: FieldState, value: string): FieldState {\n return { ...st, selected: [value], otherChosen: false };\n}\n\n/** Choose \"other\" on a select. */\nexport function chooseSelectOther(st: FieldState): FieldState {\n return { ...st, selected: [], otherChosen: true };\n}\n\n/** Toggle a multiselect option, respecting `max` (a toggle past max is ignored). */\nexport function toggleMulti(st: FieldState, value: string, max?: number): FieldState {\n if (st.selected.includes(value)) {\n return { ...st, selected: st.selected.filter((v) => v !== value) };\n }\n const count = st.selected.length + (st.otherChosen ? 1 : 0);\n if (max !== undefined && count >= max) return st;\n return { ...st, selected: [...st.selected, value] };\n}\n","import type { Field, FieldOption, UINode } from \"@switchyard/protocol\";\nimport { Check } from \"lucide-react\";\nimport { useId, useMemo, useState } from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport { Button } from \"../ui/Button\";\nimport { TextArea, TextInput } from \"../ui/TextArea\";\nimport { useIntent } from \"./context\";\nimport {\n buildValues,\n chooseSelect,\n chooseSelectOther,\n type FieldState,\n type FormState,\n initialFormState,\n toggleMulti,\n validateForm,\n visibleFields,\n} from \"./formLogic\";\n\ntype FormNode = Extract<UINode, { t: \"form\" }>;\n\nexport interface FormRendererProps {\n node: FormNode;\n className?: string;\n}\n\n/**\n * Structured question form. Selects render as radio cards, multiselects as\n * toggle cards (never comma-separated entry), `allowOther` adds a free-text\n * option, `showIf` hides dependent fields (omitted from the values).\n * Submits `{kind: \"form\", values}` through the IntentContext.\n */\nexport function FormRenderer({ node, className }: FormRendererProps) {\n const { onRespond, busy, disabled } = useIntent();\n const [state, setState] = useState<FormState>(() => initialFormState(node.fields));\n const [attempted, setAttempted] = useState(false);\n const visible = useMemo(() => visibleFields(node.fields, state), [node.fields, state]);\n const errors = useMemo(() => validateForm(node.fields, state), [node.fields, state]);\n const locked = disabled || busy;\n const setField = (name: string, fs: FieldState) => setState((s) => ({ ...s, [name]: fs }));\n\n return (\n <form\n className={cn(\"flex flex-col gap-4\", className)}\n noValidate\n onSubmit={(e) => {\n e.preventDefault();\n setAttempted(true);\n if (Object.keys(errors).length > 0 || locked) return;\n onRespond?.({ kind: \"form\", values: buildValues(node.fields, state) });\n }}\n >\n {visible.map((f) => (\n <FieldView\n key={f.name}\n field={f}\n state={state[f.name]!}\n onChange={(fs) => setField(f.name, fs)}\n error={attempted ? errors[f.name] : undefined}\n disabled={locked}\n />\n ))}\n {!disabled && (\n <div className=\"flex flex-wrap items-center gap-2\">\n <Button type=\"submit\" variant=\"primary\" busy={busy}>\n {node.submitLabel || \"Submit\"}\n </Button>\n <Button\n type=\"button\"\n variant=\"secondary\"\n disabled={busy}\n onClick={() => onRespond?.({ kind: \"cancel\" })}\n >\n {node.cancelLabel || \"Cancel\"}\n </Button>\n {attempted && Object.keys(errors).length > 0 && (\n <span role=\"alert\" className=\"text-sm text-danger\">\n Complete the highlighted fields.\n </span>\n )}\n </div>\n )}\n </form>\n );\n}\n\nfunction FieldView({\n field,\n state,\n onChange,\n error,\n disabled,\n}: {\n field: Field;\n state: FieldState;\n onChange: (s: FieldState) => void;\n error?: string;\n disabled?: boolean;\n}) {\n const id = useId();\n const errId = `${id}-err`;\n if (field.kind === \"text\") {\n const common = {\n id,\n value: state.text,\n placeholder: field.placeholder,\n disabled,\n \"aria-invalid\": !!error || undefined,\n \"aria-describedby\": error ? errId : undefined,\n };\n return (\n <div className=\"flex flex-col gap-1.5\">\n <label htmlFor={id} className=\"text-sm font-medium\">\n {field.label}\n </label>\n {field.multiline ? (\n <TextArea\n {...common}\n minRows={3}\n onChange={(e) => onChange({ ...state, text: e.target.value })}\n />\n ) : (\n <TextInput {...common} onChange={(e) => onChange({ ...state, text: e.target.value })} />\n )}\n {error && (\n <p id={errId} className=\"text-sm text-danger\">\n {error}\n </p>\n )}\n </div>\n );\n }\n\n const multi = field.kind === \"multiselect\";\n const selectedPreview =\n !multi && state.selected[0]\n ? field.options.find((o) => o.value === state.selected[0])?.preview\n : undefined;\n const hint =\n multi && (field.min !== undefined || field.max !== undefined)\n ? field.min !== undefined && field.max !== undefined\n ? `Choose ${field.min}–${field.max}`\n : field.min !== undefined\n ? `Choose at least ${field.min}`\n : `Choose up to ${field.max}`\n : multi\n ? \"Choose any\"\n : undefined;\n\n return (\n <fieldset\n className=\"flex min-w-0 flex-col gap-2\"\n aria-describedby={error ? errId : undefined}\n aria-invalid={!!error || undefined}\n >\n <legend className=\"mb-2 text-sm font-medium\">\n {field.label}\n {hint && <span className=\"ml-2 font-normal text-muted\">{hint}</span>}\n </legend>\n <div className=\"grid gap-2\">\n {field.options.map((o) => (\n <OptionCard\n key={o.value}\n name={id}\n option={o}\n multi={multi}\n checked={state.selected.includes(o.value)}\n disabled={disabled}\n onToggle={() =>\n onChange(\n multi\n ? toggleMulti(\n state,\n o.value,\n field.kind === \"multiselect\" ? field.max : undefined,\n )\n : chooseSelect(state, o.value),\n )\n }\n />\n ))}\n {field.allowOther && (\n <OptionCard\n name={id}\n option={{ value: \"__other__\", label: field.allowOther.label || \"Other\" }}\n multi={multi}\n checked={state.otherChosen}\n disabled={disabled}\n onToggle={() =>\n onChange(\n multi ? { ...state, otherChosen: !state.otherChosen } : chooseSelectOther(state),\n )\n }\n />\n )}\n </div>\n {field.allowOther && state.otherChosen && (\n <TextInput\n aria-label={field.allowOther.label || \"Other\"}\n placeholder={field.allowOther.placeholder ?? \"Type your answer\"}\n value={state.otherText}\n disabled={disabled}\n autoFocus\n onChange={(e) => onChange({ ...state, otherText: e.target.value })}\n />\n )}\n {selectedPreview && (\n <pre className=\"max-h-64 max-w-full overflow-auto rounded-md border border-border bg-surface-2 px-3 py-2 text-xs leading-5\">\n {selectedPreview}\n </pre>\n )}\n {error && (\n <p id={errId} className=\"text-sm text-danger\">\n {error}\n </p>\n )}\n </fieldset>\n );\n}\n\nfunction OptionCard({\n name,\n option,\n multi,\n checked,\n disabled,\n onToggle,\n}: {\n name: string;\n option: FieldOption;\n multi: boolean;\n checked: boolean;\n disabled?: boolean;\n onToggle: () => void;\n}) {\n return (\n <label\n className={cn(\n \"tap flex min-w-0 cursor-pointer items-start gap-3 rounded-lg border px-3 py-2.5 text-sm\",\n \"has-[:focus-visible]:outline-2 has-[:focus-visible]:outline-offset-2 has-[:focus-visible]:outline-accent\",\n checked ? \"border-accent bg-accent-soft\" : \"border-border bg-surface hover:bg-surface-2\",\n disabled && \"cursor-not-allowed opacity-70\",\n )}\n >\n <input\n type={multi ? \"checkbox\" : \"radio\"}\n name={name}\n value={option.value}\n checked={checked}\n disabled={disabled}\n onChange={onToggle}\n className=\"sr-only\"\n />\n <span\n aria-hidden\n className={cn(\n \"mt-0.5 inline-flex size-4 shrink-0 items-center justify-center border\",\n multi ? \"rounded\" : \"rounded-full\",\n checked ? \"border-accent bg-accent text-accent-fg\" : \"border-border-strong bg-surface\",\n )}\n >\n {checked &&\n (multi ? (\n <Check className=\"size-3\" />\n ) : (\n <span className=\"size-1.5 rounded-full bg-accent-fg\" />\n ))}\n </span>\n <span className=\"min-w-0 flex-1\">\n <span className=\"block font-medium break-words\">{option.label}</span>\n {option.description && (\n <span className=\"block text-muted break-words\">{option.description}</span>\n )}\n </span>\n </label>\n );\n}\n","import type { UINode, UIRef } from \"@switchyard/protocol\";\nimport { ChevronRight, CircleCheck, CircleX, FileCode, LoaderCircle } from \"lucide-react\";\nimport { useId, useState } from \"react\";\nimport { Link } from \"react-router\";\nimport { cn } from \"../../lib/cn\";\nimport { Button } from \"../ui/Button\";\nimport { TabPanel, Tabs } from \"../ui/Tabs\";\nimport { CodeBlock } from \"./CodeBlock\";\nimport { ConfirmRenderer } from \"./ConfirmRenderer\";\nimport { IntentContext, type IntentHandlers, useIntent } from \"./context\";\nimport { DiffView } from \"./DiffView\";\nimport { FormRenderer } from \"./FormRenderer\";\nimport { Markdown } from \"./Markdown\";\n\nexport interface UINodeRendererProps extends IntentHandlers {\n node: UINode;\n className?: string;\n}\n\n/**\n * Renders a portable UINode tree. Interactive nodes (form, confirm, actions)\n * respond through the handlers given here (or an enclosing IntentContext).\n */\nexport function UINodeRenderer({ node, className, ...handlers }: UINodeRendererProps) {\n const parent = useIntent();\n const hasOwn = Object.values(handlers).some((v) => v !== undefined);\n const content = (\n <div className={cn(\"flex min-w-0 flex-col gap-3\", className)}>\n <NodeView node={node} />\n </div>\n );\n if (!hasOwn) return content;\n return (\n <IntentContext.Provider value={{ ...parent, ...stripUndefined(handlers) }}>\n {content}\n </IntentContext.Provider>\n );\n}\n\nfunction stripUndefined<T extends object>(o: T): Partial<T> {\n return Object.fromEntries(Object.entries(o).filter(([, v]) => v !== undefined)) as Partial<T>;\n}\n\nconst TONE_TEXT = {\n default: \"text-text\",\n muted: \"text-muted\",\n success: \"text-success\",\n warning: \"text-warning\",\n danger: \"text-danger\",\n} as const;\n\nexport function NodeView({ node }: { node: UINode }) {\n switch (node.t) {\n case \"text\":\n return (\n <p\n className={cn(\n \"text-sm break-words whitespace-pre-wrap\",\n TONE_TEXT[node.tone ?? \"default\"],\n )}\n >\n {node.text}\n </p>\n );\n case \"markdown\":\n return <Markdown text={node.text} />;\n case \"code\":\n return <CodeBlock text={node.text} lang={node.lang} maxHeight=\"24rem\" />;\n case \"diff\":\n return <DiffView patch={node.patch} />;\n case \"list\":\n return <ListView node={node} />;\n case \"table\":\n return (\n <div className=\"max-w-full overflow-x-auto overscroll-x-contain rounded-md border border-border\">\n <table className=\"w-full border-collapse text-sm\">\n <thead className=\"bg-surface-2\">\n <tr>\n {node.columns.map((c, i) => (\n <th\n // biome-ignore lint/suspicious/noArrayIndexKey: columns are positional\n key={i}\n scope=\"col\"\n className=\"border-b border-border px-3 py-1.5 text-left font-medium\"\n >\n {c}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {node.rows.map((r, ri) => (\n // biome-ignore lint/suspicious/noArrayIndexKey: rows are positional\n <tr key={ri} className=\"border-b border-border last:border-b-0\">\n {r.map((cell, ci) => (\n // biome-ignore lint/suspicious/noArrayIndexKey: cells are positional\n <td key={ci} className=\"px-3 py-1.5 align-top break-words\">\n {cell}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n case \"section\":\n return <SectionView node={node} />;\n case \"tabs\":\n return <TabsView node={node} />;\n case \"progress\":\n return <ProgressView node={node} />;\n case \"ref\":\n return <RefView refValue={node.ref} label={node.label} />;\n case \"form\":\n return <FormRenderer node={node} />;\n case \"confirm\":\n return <ConfirmRenderer node={node} />;\n case \"actions\":\n return <ActionsView node={node} />;\n default:\n return null;\n }\n}\n\nfunction Children({ nodes }: { nodes: UINode[] }) {\n return (\n <>\n {nodes.map((n, i) => (\n // biome-ignore lint/suspicious/noArrayIndexKey: UINode trees have no ids\n <NodeView key={i} node={n} />\n ))}\n </>\n );\n}\n\nfunction ListView({ node }: { node: Extract<UINode, { t: \"list\" }> }) {\n const Tag = node.ordered ? \"ol\" : \"ul\";\n return (\n <Tag\n className={cn(\n \"flex flex-col gap-1.5 pl-5 text-sm\",\n node.ordered ? \"list-decimal\" : \"list-disc\",\n )}\n >\n {node.items.map((item, i) => (\n // biome-ignore lint/suspicious/noArrayIndexKey: list items are positional\n <li key={i} className=\"min-w-0\">\n <div className=\"flex min-w-0 flex-col gap-2\">\n <NodeView node={item} />\n </div>\n </li>\n ))}\n </Tag>\n );\n}\n\nfunction SectionView({ node }: { node: Extract<UINode, { t: \"section\" }> }) {\n if (node.collapsible) {\n return (\n <details className=\"group min-w-0 rounded-md border border-border\" open>\n <summary className=\"tap flex cursor-pointer list-none items-center gap-1.5 px-3 py-2 text-sm font-medium [&::-webkit-details-marker]:hidden\">\n <ChevronRight\n aria-hidden\n className=\"size-4 shrink-0 transition-transform group-open:rotate-90\"\n />\n {node.title ?? \"Details\"}\n </summary>\n <div className=\"flex min-w-0 flex-col gap-3 border-t border-border px-3 py-2\">\n <Children nodes={node.children} />\n </div>\n </details>\n );\n }\n return (\n <section className=\"flex min-w-0 flex-col gap-2\">\n {node.title && <h3 className=\"text-sm font-semibold\">{node.title}</h3>}\n <Children nodes={node.children} />\n </section>\n );\n}\n\nfunction TabsView({ node }: { node: Extract<UINode, { t: \"tabs\" }> }) {\n const prefix = useId();\n const [active, setActive] = useState(node.tabs[0]?.id ?? \"\");\n const current = node.tabs.find((t) => t.id === active) ?? node.tabs[0];\n if (!current) return null;\n return (\n <div className=\"flex min-w-0 flex-col gap-2\">\n <Tabs\n label=\"Sections\"\n idPrefix={prefix}\n tabs={node.tabs.map((t) => ({ id: t.id, label: t.label }))}\n value={current.id}\n onChange={setActive}\n scrollable\n />\n <TabPanel idPrefix={prefix} id={current.id} className=\"flex min-w-0 flex-col gap-3\">\n <Children nodes={current.children} />\n </TabPanel>\n </div>\n );\n}\n\nfunction ProgressView({ node }: { node: Extract<UINode, { t: \"progress\" }> }) {\n const status = node.status ?? \"running\";\n const Icon = status === \"ok\" ? CircleCheck : status === \"error\" ? CircleX : LoaderCircle;\n const statusText = status === \"ok\" ? \"Done\" : status === \"error\" ? \"Failed\" : \"In progress\";\n const pct = node.value === undefined ? null : Math.round(node.value * 100);\n return (\n <div className=\"flex min-w-0 flex-col gap-1\">\n <div className=\"flex items-center gap-2 text-sm\">\n <Icon\n aria-hidden\n className={cn(\n \"size-4 shrink-0\",\n status === \"ok\" && \"text-success\",\n status === \"error\" && \"text-danger\",\n status === \"running\" && \"animate-spin text-info\",\n )}\n />\n <span className=\"min-w-0 flex-1 truncate\">{node.label}</span>\n <span className=\"shrink-0 text-xs text-muted\">\n {statusText}\n {pct !== null ? ` · ${pct}%` : \"\"}\n </span>\n </div>\n {pct !== null && (\n <div\n role=\"progressbar\"\n aria-label={node.label}\n aria-valuenow={pct}\n aria-valuemin={0}\n aria-valuemax={100}\n className=\"h-1.5 overflow-hidden rounded-full bg-surface-3\"\n >\n <div\n className={cn(\n \"h-full rounded-full\",\n status === \"error\" ? \"bg-danger\" : status === \"ok\" ? \"bg-success\" : \"bg-accent\",\n )}\n style={{ width: `${pct}%` }}\n />\n </div>\n )}\n </div>\n );\n}\n\nexport function refHref(ref: UIRef): string | null {\n switch (ref.kind) {\n case \"session\":\n return `/code/${encodeURIComponent(ref.sessionId)}`;\n case \"task\":\n return `/tasks/${encodeURIComponent(ref.taskId)}`;\n default:\n return null;\n }\n}\n\nfunction RefView({ refValue, label }: { refValue: UIRef; label: string }) {\n const { onOpenFile } = useIntent();\n const href = refHref(refValue);\n if (href) {\n return (\n <Link to={href} className=\"text-sm text-accent underline underline-offset-2\">\n {label}\n </Link>\n );\n }\n if (refValue.kind === \"file\") {\n if (onOpenFile) {\n return (\n <button\n type=\"button\"\n onClick={() => onOpenFile(refValue.path)}\n className=\"inline-flex min-w-0 items-center gap-1 text-left text-sm text-accent underline underline-offset-2\"\n >\n <FileCode aria-hidden className=\"size-4 shrink-0\" />\n <span className=\"truncate\">{label || refValue.path}</span>\n </button>\n );\n }\n return (\n <span\n className=\"inline-flex min-w-0 items-center gap-1 font-mono text-sm\"\n title={refValue.path}\n >\n <FileCode aria-hidden className=\"size-4 shrink-0 text-muted\" />\n <span className=\"truncate\">{label || refValue.path}</span>\n </span>\n );\n }\n if (refValue.kind !== \"native_session\") return <span className=\"text-sm\">{label}</span>;\n return (\n <span className=\"text-sm\" title={refValue.sessionFile}>\n {label} <span className=\"text-muted\">(native Pi session, not imported)</span>\n </span>\n );\n}\n\nfunction ActionsView({ node }: { node: Extract<UINode, { t: \"actions\" }> }) {\n const { onRespond, onAction, busy, disabled } = useIntent();\n if (disabled) return null;\n return (\n <div className=\"flex flex-wrap gap-2\">\n {node.actions.map((a) => (\n <Button\n key={a.id}\n variant={a.tone === \"primary\" ? \"primary\" : a.tone === \"danger\" ? \"danger\" : \"secondary\"}\n disabled={busy || (!onRespond && !onAction)}\n onClick={() => {\n if (onRespond) onRespond({ kind: \"action\", actionId: a.id });\n else onAction?.(a.id);\n }}\n >\n {a.label}\n </Button>\n ))}\n </div>\n );\n}\n","import type { Interaction, UINode } from \"@switchyard/protocol\";\n\n/** What actually happened when an extension opened a terminal-only `ctx.ui.custom()` dialog. */\nexport const UNSUPPORTED_COPY =\n \"An extension opened a terminal-only dialog. In RPC mode Pi gave it no answer, so the extension continued without one.\";\n\nexport interface UnsupportedAction {\n id: \"abort\" | \"message\";\n label: string;\n tone: \"primary\" | \"secondary\" | \"danger\";\n}\n\nconst DEFAULT_ACTIONS: UnsupportedAction[] = [\n { id: \"abort\", label: \"Stop the run\", tone: \"danger\" },\n { id: \"message\", label: \"Send a message to the agent\", tone: \"primary\" },\n];\n\nfunction findActions(node: UINode): Extract<UINode, { t: \"actions\" }> | null {\n if (node.t === \"actions\") return node;\n if (node.t === \"section\") {\n for (const c of node.children) {\n const found = findActions(c);\n if (found) return found;\n }\n }\n return null;\n}\n\nexport interface UnsupportedView {\n /** True until a person chose one of the alternatives. */\n answerable: boolean;\n actions: UnsupportedAction[];\n copy: string;\n}\n\nexport function isUnsupported(i: Interaction): boolean {\n return i.state === \"unsupported\" || i.source.kind === \"unsupported_custom\";\n}\n\n/** The alternatives the host offers for an unsupported dialog (stop the run, message). */\nexport function unsupportedView(i: Interaction): UnsupportedView {\n const node = findActions(i.presentation);\n const offered = (node?.actions ?? [])\n .filter(\n (a): a is typeof a & { id: \"abort\" | \"message\" } => a.id === \"abort\" || a.id === \"message\",\n )\n .map((a) => ({\n id: a.id,\n label: a.label,\n tone: (a.tone === \"default\"\n ? \"secondary\"\n : (a.tone ?? (a.id === \"abort\" ? \"danger\" : \"primary\"))) as UnsupportedAction[\"tone\"],\n }));\n return {\n answerable: i.state === \"unsupported\" && i.resolution === null,\n actions: offered.length > 0 ? offered : DEFAULT_ACTIONS,\n copy: UNSUPPORTED_COPY,\n };\n}\n\n/** A follow-up while Pi is still working queues behind the current turn. */\nexport function messageMode(runtime: string | undefined): \"prompt\" | \"followUp\" {\n return runtime === \"running\" || runtime === \"waiting_input\" ? \"followUp\" : \"prompt\";\n}\n","import type { Interaction, InteractionResponse, UINode } from \"@switchyard/protocol\";\nimport { useState } from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport { formatRelative } from \"../../lib/time\";\nimport { apiPost, errorMessage, isApiError } from \"../../sync/api\";\nimport { useSyncStore } from \"../../sync/store\";\nimport { Button } from \"../ui/Button\";\nimport { StatusChip } from \"../ui/StatusChip\";\nimport { ErrorState } from \"../ui/states\";\nimport { TextArea } from \"../ui/TextArea\";\nimport { UINodeRenderer } from \"./UINodeRenderer\";\nimport { isUnsupported, messageMode, unsupportedView } from \"./unsupported\";\n\nexport interface InteractionCardProps {\n interaction: Interaction;\n /** Read-only session or host offline: show the question without answer controls. */\n readOnlyReason?: string | null;\n className?: string;\n /** Called after the coordinator acknowledged an answer. */\n onAnswered?: (interaction: Interaction) => void;\n /** DOM id (the \"Needs your answer\" strip scrolls to it). */\n id?: string;\n}\n\nfunction hasInteractive(node: UINode): boolean {\n switch (node.t) {\n case \"form\":\n case \"confirm\":\n case \"actions\":\n return true;\n case \"list\":\n return node.items.some(hasInteractive);\n case \"section\":\n return node.children.some(hasInteractive);\n case \"tabs\":\n return node.tabs.some((t) => t.children.some(hasInteractive));\n default:\n return false;\n }\n}\n\nfunction byLabel(by: string): string {\n if (by === \"host\") return \"the host\";\n if (by === \"pi\") return \"Pi\";\n return \"a device\";\n}\n\n/**\n * A runtime interaction (extension dialog). Posts the answer with the\n * interaction revision and waits for the acknowledgement; there is no\n * optimistic resolution. A 409 shows \"Already answered: <summary>\".\n */\nexport function InteractionCard({\n interaction: fromProps,\n readOnlyReason,\n className,\n onAnswered,\n id,\n}: InteractionCardProps) {\n const upsert = useSyncStore((s) => s.upsertInteraction);\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<unknown>(null);\n const [alreadyAnswered, setAlreadyAnswered] = useState<string | null>(null);\n const [lastResponse, setLastResponse] = useState<InteractionResponse | null>(null);\n // The acknowledged interaction from the answer/409 response, until the prop catches up.\n const [acked, setAcked] = useState<Interaction | null>(null);\n const interaction =\n acked && acked.id === fromProps.id && acked.revision > fromProps.revision ? acked : fromProps;\n\n const pending = interaction.state === \"pending\";\n const unsupported = isUnsupported(interaction);\n const sessionRuntime = useSyncStore((s) => s.sessions[interaction.sessionId]?.runtime);\n const [composing, setComposing] = useState(false);\n const [message, setMessage] = useState(\"\");\n\n const respond = async (response: InteractionResponse): Promise<boolean> => {\n setBusy(true);\n setError(null);\n setLastResponse(response);\n try {\n const res = await apiPost<{ status: string; interaction: Interaction }>(\n `/api/interactions/${encodeURIComponent(interaction.id)}/answer`,\n { revision: interaction.revision, response },\n );\n if (res?.interaction) {\n upsert(res.interaction);\n setAcked(res.interaction);\n onAnswered?.(res.interaction);\n }\n return true;\n } catch (e) {\n if (isApiError(e, \"already_answered\")) {\n const other = (e.details as { interaction?: Interaction } | undefined)?.interaction;\n if (other) {\n upsert(other);\n setAcked(other);\n }\n setAlreadyAnswered(other?.resolution?.summary ?? \"answered on another device\");\n } else {\n setError(e);\n }\n return false;\n } finally {\n setBusy(false);\n }\n };\n\n /** \"Send a message to the agent\": deliver the message first, then record the choice. */\n const sendMessage = async () => {\n const text = message.trim();\n if (!text) return;\n setBusy(true);\n setError(null);\n try {\n await apiPost(`/api/sessions/${encodeURIComponent(interaction.sessionId)}/prompt`, {\n text,\n mode: messageMode(sessionRuntime),\n });\n } catch (e) {\n setError(e);\n setBusy(false);\n return;\n }\n setBusy(false);\n if (await respond({ kind: \"action\", actionId: \"message\" })) {\n setComposing(false);\n setMessage(\"\");\n }\n };\n\n return (\n <article\n id={id}\n aria-label={`Question: ${interaction.title}`}\n className={cn(\n \"flex min-w-0 flex-col gap-3 rounded-lg border bg-surface p-3\",\n pending ? \"border-warning\" : \"border-border\",\n className,\n )}\n >\n <header className=\"flex min-w-0 flex-wrap items-start gap-2\">\n <h3 className=\"min-w-0 flex-1 text-sm font-semibold break-words\">{interaction.title}</h3>\n <StatusChip kind=\"interaction\" value={interaction.state} size=\"sm\" />\n </header>\n\n {alreadyAnswered && (\n <p role=\"status\" className=\"rounded-md bg-surface-2 px-3 py-2 text-sm\">\n Already answered: {alreadyAnswered}\n </p>\n )}\n\n {unsupported ? (\n <UnsupportedBody\n interaction={interaction}\n readOnlyReason={readOnlyReason ?? null}\n busy={busy}\n answered={alreadyAnswered !== null}\n composing={composing}\n message={message}\n setMessage={setMessage}\n onAction={(actionId) => {\n if (actionId === \"message\") setComposing(true);\n else void respond({ kind: \"action\", actionId });\n }}\n onSend={() => void sendMessage()}\n onCancelMessage={() => setComposing(false)}\n />\n ) : pending && !alreadyAnswered ? (\n <>\n {readOnlyReason && <p className=\"text-sm text-muted\">{readOnlyReason}</p>}\n <UINodeRenderer\n node={interaction.presentation}\n onRespond={(r) => void respond(r)}\n busy={busy}\n disabled={!!readOnlyReason}\n />\n {!readOnlyReason && !hasInteractive(interaction.presentation) && (\n <div>\n <Button busy={busy} onClick={() => void respond({ kind: \"cancel\" })}>\n Dismiss\n </Button>\n </div>\n )}\n {busy && (\n <p role=\"status\" className=\"text-sm text-muted\">\n Sending answer… waiting for the host to confirm.\n </p>\n )}\n </>\n ) : alreadyAnswered ? null : interaction.resolution ? (\n <p className=\"text-sm text-muted\">\n {interaction.state === \"resolved\" ? \"Answered\" : \"Closed\"} by{\" \"}\n {byLabel(interaction.resolution.by)} {formatRelative(interaction.resolution.at)}:{\" \"}\n <span className=\"text-text\">{interaction.resolution.summary}</span>\n </p>\n ) : (\n <p className=\"text-sm text-muted\">\n {interaction.state === \"expired\"\n ? \"This question expired before it was answered (Pi closed the dialog).\"\n : \"This question was cancelled.\"}\n </p>\n )}\n\n {error !== null && (\n <ErrorState\n compact\n title=\"Answer not delivered\"\n error={errorMessage(error)}\n onRetry={lastResponse ? () => void respond(lastResponse) : undefined}\n />\n )}\n </article>\n );\n}\n\n/** A terminal-only dialog: what happened, and the alternatives the host offers until one is chosen. */\nfunction UnsupportedBody({\n interaction,\n readOnlyReason,\n busy,\n answered,\n composing,\n message,\n setMessage,\n onAction,\n onSend,\n onCancelMessage,\n}: {\n interaction: Interaction;\n readOnlyReason: string | null;\n busy: boolean;\n answered: boolean;\n composing: boolean;\n message: string;\n setMessage: (t: string) => void;\n onAction: (actionId: \"abort\" | \"message\") => void;\n onSend: () => void;\n onCancelMessage: () => void;\n}) {\n const view = unsupportedView(interaction);\n return (\n <div className=\"flex min-w-0 flex-col gap-2\">\n <p className=\"text-sm text-muted\">{view.copy}</p>\n {interaction.resolution ? (\n <p className=\"text-sm text-muted\">\n Chosen by {byLabel(interaction.resolution.by)} {formatRelative(interaction.resolution.at)}\n : <span className=\"text-text\">{interaction.resolution.summary}</span>\n </p>\n ) : !view.answerable || answered ? null : readOnlyReason ? (\n <p className=\"text-sm text-muted\">{readOnlyReason}</p>\n ) : composing ? (\n <div className=\"flex min-w-0 flex-col gap-2\">\n <TextArea\n aria-label=\"Message to the agent\"\n value={message}\n onChange={(e) => setMessage(e.target.value)}\n rows={3}\n autoFocus\n placeholder=\"Tell the agent what to do instead\"\n />\n <div className=\"flex flex-wrap gap-2\">\n <Button variant=\"primary\" busy={busy} disabled={!message.trim()} onClick={onSend}>\n Send message\n </Button>\n <Button disabled={busy} onClick={onCancelMessage}>\n Cancel\n </Button>\n </div>\n </div>\n ) : (\n <div className=\"flex flex-wrap gap-2\">\n {view.actions.map((a) => (\n <Button\n key={a.id}\n variant={a.tone}\n busy={busy && a.id === \"abort\"}\n disabled={busy}\n onClick={() => onAction(a.id)}\n >\n {a.label}\n </Button>\n ))}\n </div>\n )}\n </div>\n );\n}\n"],"ignoreList":[0],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{_ as e,m as t,n,t as r}from"./jsx-runtime-D13aM9HY.js";import{h as i}from"./states-DrTQuYXw.js";import{n as a}from"./server-SxFxIScj.js";var o={name:`arrow-down`,size:24,node:[[`path`,{d:`M12 5v14`,key:`s699le`}],[`path`,{d:`m19 12-7 7-7-7`,key:`1idqje`}]]};o.node;var s=n(o),c={name:`chevron-down`,size:24,node:[[`path`,{d:`m6 9 6 6 6-6`,key:`qrunsl`}]]};c.node;var l=n(c),u={name:`panel-right-open`,size:24,node:[[`rect`,{width:`18`,height:`18`,x:`3`,y:`3`,rx:`2`,key:`afitv7`}],[`path`,{d:`M15 3v18`,key:`14nvp0`}],[`path`,{d:`m10 15-3-3 3-3`,key:`1pgupc`}]]};u.node;var d=n(u),f=e(t(),1),p=r();function m({trigger:e,items:t,align:n=`end`,label:
|
|
2
|
-
//# sourceMappingURL=Menu-
|
|
1
|
+
import{_ as e,m as t,n,t as r}from"./jsx-runtime-D13aM9HY.js";import{h as i}from"./states-DrTQuYXw.js";import{n as a}from"./server-SxFxIScj.js";var o={name:`arrow-down`,size:24,node:[[`path`,{d:`M12 5v14`,key:`s699le`}],[`path`,{d:`m19 12-7 7-7-7`,key:`1idqje`}]]};o.node;var s=n(o),c={name:`chevron-down`,size:24,node:[[`path`,{d:`m6 9 6 6 6-6`,key:`qrunsl`}]]};c.node;var l=n(c),u={name:`panel-right-open`,size:24,node:[[`rect`,{width:`18`,height:`18`,x:`3`,y:`3`,rx:`2`,key:`afitv7`}],[`path`,{d:`M15 3v18`,key:`14nvp0`}],[`path`,{d:`m10 15-3-3 3-3`,key:`1pgupc`}]]};u.node;var d=n(u),f=e(t(),1),p=r();function m({trigger:e,items:t,align:n=`end`,side:r=`bottom`,label:o,className:s}){let[c,l]=(0,f.useState)(!1),u=(0,f.useId)(),d=(0,f.useRef)(null),m=(0,f.useRef)(null),g=e=>h(m.current,e);(0,f.useEffect)(()=>{if(!c)return;requestAnimationFrame(()=>h(m.current,`first`));let e=e=>{!m.current?.contains(e.target)&&!d.current?.contains(e.target)&&l(!1)};return document.addEventListener(`pointerdown`,e),()=>document.removeEventListener(`pointerdown`,e)},[c]);let _=(e=!0)=>{l(!1),e&&d.current?.focus()};return(0,p.jsxs)(`div`,{className:i(`relative inline-flex`,s),children:[e({ref:d,onClick:()=>l(e=>!e),onKeyDown:e=>{(e.key===`ArrowDown`||e.key===`ArrowUp`)&&(e.preventDefault(),l(!0))},"aria-haspopup":`menu`,"aria-expanded":c,"aria-controls":u}),c&&(0,p.jsx)(`div`,{ref:m,id:u,role:`menu`,"aria-label":o,tabIndex:-1,className:i(`absolute z-40 min-w-48 max-w-[min(20rem,calc(100vw-1rem))] rounded-lg border border-border bg-surface py-1 shadow-pop`,r===`top`?`bottom-full mb-1`:`top-full mt-1`,n===`end`?`right-0`:`left-0`),onKeyDown:e=>{e.key===`ArrowDown`?(e.preventDefault(),g(1)):e.key===`ArrowUp`?(e.preventDefault(),g(-1)):e.key===`Home`?(e.preventDefault(),g(`first`)):e.key===`End`?(e.preventDefault(),g(`last`)):e.key===`Escape`?(e.preventDefault(),e.stopPropagation(),_()):e.key===`Tab`&&_(!1)},children:t.map((e,t)=>e===`separator`?(0,p.jsx)(`hr`,{className:`my-1 border-t border-border`},`sep-${t}`):`heading`in e?(0,p.jsx)(`div`,{role:`presentation`,className:`px-3 pt-1.5 pb-1 text-xs font-medium text-muted`,children:e.heading},e.id):(0,p.jsxs)(`button`,{type:`button`,role:e.kind===`radio`?`menuitemradio`:e.kind===`checkbox`?`menuitemcheckbox`:`menuitem`,"aria-checked":e.kind?!!e.checked:void 0,disabled:e.disabled,className:i(`tap flex w-full items-start gap-2 px-3 py-2 text-left text-sm hover:bg-surface-2 focus:bg-surface-2 focus:outline-none disabled:opacity-55`,e.danger?`text-danger`:`text-text`),onClick:()=>{_(),e.onSelect()},children:[e.kind?(0,p.jsx)(`span`,{"aria-hidden":!0,className:`mt-0.5 size-4 shrink-0`,children:e.checked&&(0,p.jsx)(a,{className:`size-4`})}):e.icon&&(0,p.jsx)(`span`,{className:`mt-0.5 shrink-0`,children:e.icon}),(0,p.jsxs)(`span`,{className:`min-w-0`,children:[(0,p.jsx)(`span`,{className:`block`,children:e.label}),e.hint&&(0,p.jsx)(`span`,{className:`block text-xs text-muted`,children:e.hint})]})]},e.id))})]})}function h(e,t){let n=[...e?.querySelectorAll(`[role^="menuitem"]:not([disabled])`)??[]];if(n.length===0)return;let r=n.indexOf(document.activeElement),i=0;i=t===`first`?0:t===`last`?n.length-1:(r+t+n.length)%n.length,n[i].focus()}export{s as i,d as n,l as r,m as t};
|
|
2
|
+
//# sourceMappingURL=Menu-GymfuHGP.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Menu-GymfuHGP.js","names":["__iconData","__iconData","useState","useId","useRef","__toESM","require_react","require_jsx_runtime","cn","Check","__iconData$2","ArrowDown","createLucideIcon","__iconData$1","ChevronDown","__iconData","PanelRightOpen","import_react","import_jsx_runtime","Menu","open","setOpen","id","btnRef","menuRef","focusItem","focusMenuItem","dir","onDoc","close","refocus","className","trigger","o","label","side","align","items","item","i","els","menu","idx","next"],"sources":["../../../../node_modules/.pnpm/lucide-react@1.61.0_@types+react@19.3.0_react@19.3.1/node_modules/lucide-react/dist/esm/icons/arrow-down.mjs","../../../../node_modules/.pnpm/lucide-react@1.61.0_@types+react@19.3.0_react@19.3.1/node_modules/lucide-react/dist/esm/icons/chevron-down.mjs","../../../../node_modules/.pnpm/lucide-react@1.61.0_@types+react@19.3.0_react@19.3.1/node_modules/lucide-react/dist/esm/icons/panel-right-open.mjs","../../src/components/ui/Menu.tsx"],"sourcesContent":["/**\n * @license lucide-react v1.61.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconData = {\n name: \"arrow-down\",\n size: 24,\n node: [\n [\"path\", { d: \"M12 5v14\", key: \"s699le\" }],\n [\"path\", { d: \"m19 12-7 7-7-7\", key: \"1idqje\" }]\n ]\n};\n__iconData.node;\nconst ArrowDown = createLucideIcon(__iconData);\n\nexport { __iconData, ArrowDown as default };\n//# sourceMappingURL=arrow-down.mjs.map\n","/**\n * @license lucide-react v1.61.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconData = {\n name: \"chevron-down\",\n size: 24,\n node: [[\"path\", { d: \"m6 9 6 6 6-6\", key: \"qrunsl\" }]]\n};\n__iconData.node;\nconst ChevronDown = createLucideIcon(__iconData);\n\nexport { __iconData, ChevronDown as default };\n//# sourceMappingURL=chevron-down.mjs.map\n","/**\n * @license lucide-react v1.61.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconData = {\n name: \"panel-right-open\",\n size: 24,\n node: [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }],\n [\"path\", { d: \"M15 3v18\", key: \"14nvp0\" }],\n [\"path\", { d: \"m10 15-3-3 3-3\", key: \"1pgupc\" }]\n ]\n};\n__iconData.node;\nconst PanelRightOpen = createLucideIcon(__iconData);\n\nexport { __iconData, PanelRightOpen as default };\n//# sourceMappingURL=panel-right-open.mjs.map\n","import { Check } from \"lucide-react\";\nimport { type ReactNode, useEffect, useId, useRef, useState } from \"react\";\nimport { cn } from \"../../lib/cn\";\n\nexport interface MenuItem {\n id: string;\n label: string;\n icon?: ReactNode;\n onSelect: () => void;\n danger?: boolean;\n disabled?: boolean;\n /** Short explanation shown under the label (e.g. why it is disabled). */\n hint?: string;\n /** A radio or checkbox item shows a check mark when `checked`. */\n kind?: \"radio\" | \"checkbox\";\n checked?: boolean;\n}\n\n/** A non-interactive label above a group of items. */\nexport interface MenuHeading {\n id: string;\n heading: string;\n}\n\nexport interface MenuProps {\n /** Render the trigger; spread the given props onto a button. */\n trigger: (props: {\n ref: React.Ref<HTMLButtonElement>;\n onClick: () => void;\n onKeyDown: (e: React.KeyboardEvent) => void;\n \"aria-haspopup\": \"menu\";\n \"aria-expanded\": boolean;\n \"aria-controls\": string;\n }) => ReactNode;\n items: (MenuItem | MenuHeading | \"separator\")[];\n align?: \"start\" | \"end\";\n /** Open below (default) or above the trigger. */\n side?: \"bottom\" | \"top\";\n /** Extra classes for the wrapper (e.g. `w-full`). */\n className?: string;\n /** Accessible name of the menu. */\n label: string;\n}\n\n/** Popup menu with arrow-key navigation, Escape and outside click to close. */\nexport function Menu({\n trigger,\n items,\n align = \"end\",\n side = \"bottom\",\n label,\n className,\n}: MenuProps) {\n const [open, setOpen] = useState(false);\n const id = useId();\n const btnRef = useRef<HTMLButtonElement>(null);\n const menuRef = useRef<HTMLDivElement>(null);\n\n const focusItem = (dir: 1 | -1 | \"first\" | \"last\") => focusMenuItem(menuRef.current, dir);\n\n useEffect(() => {\n if (!open) return;\n requestAnimationFrame(() => focusMenuItem(menuRef.current, \"first\"));\n const onDoc = (e: PointerEvent) => {\n if (\n !menuRef.current?.contains(e.target as Node) &&\n !btnRef.current?.contains(e.target as Node)\n ) {\n setOpen(false);\n }\n };\n document.addEventListener(\"pointerdown\", onDoc);\n return () => document.removeEventListener(\"pointerdown\", onDoc);\n }, [open]);\n\n const close = (refocus = true) => {\n setOpen(false);\n if (refocus) btnRef.current?.focus();\n };\n\n return (\n <div className={cn(\"relative inline-flex\", className)}>\n {trigger({\n ref: btnRef,\n onClick: () => setOpen((o) => !o),\n onKeyDown: (e) => {\n if (e.key === \"ArrowDown\" || e.key === \"ArrowUp\") {\n e.preventDefault();\n setOpen(true);\n }\n },\n \"aria-haspopup\": \"menu\",\n \"aria-expanded\": open,\n \"aria-controls\": id,\n })}\n {open && (\n <div\n ref={menuRef}\n id={id}\n role=\"menu\"\n aria-label={label}\n tabIndex={-1}\n className={cn(\n \"absolute z-40 min-w-48 max-w-[min(20rem,calc(100vw-1rem))] rounded-lg border border-border bg-surface py-1 shadow-pop\",\n side === \"top\" ? \"bottom-full mb-1\" : \"top-full mt-1\",\n align === \"end\" ? \"right-0\" : \"left-0\",\n )}\n onKeyDown={(e) => {\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n focusItem(1);\n } else if (e.key === \"ArrowUp\") {\n e.preventDefault();\n focusItem(-1);\n } else if (e.key === \"Home\") {\n e.preventDefault();\n focusItem(\"first\");\n } else if (e.key === \"End\") {\n e.preventDefault();\n focusItem(\"last\");\n } else if (e.key === \"Escape\") {\n e.preventDefault();\n e.stopPropagation();\n close();\n } else if (e.key === \"Tab\") {\n close(false);\n }\n }}\n >\n {items.map((item, i) =>\n item === \"separator\" ? (\n // biome-ignore lint/suspicious/noArrayIndexKey: separators have no identity\n <hr key={`sep-${i}`} className=\"my-1 border-t border-border\" />\n ) : \"heading\" in item ? (\n <div\n key={item.id}\n role=\"presentation\"\n className=\"px-3 pt-1.5 pb-1 text-xs font-medium text-muted\"\n >\n {item.heading}\n </div>\n ) : (\n // biome-ignore lint/a11y/useAriaPropsSupportedByRole: aria-checked is only set with the menuitemradio/menuitemcheckbox roles\n <button\n key={item.id}\n type=\"button\"\n role={\n item.kind === \"radio\"\n ? \"menuitemradio\"\n : item.kind === \"checkbox\"\n ? \"menuitemcheckbox\"\n : \"menuitem\"\n }\n aria-checked={item.kind ? !!item.checked : undefined}\n disabled={item.disabled}\n className={cn(\n \"tap flex w-full items-start gap-2 px-3 py-2 text-left text-sm hover:bg-surface-2 focus:bg-surface-2 focus:outline-none disabled:opacity-55\",\n item.danger ? \"text-danger\" : \"text-text\",\n )}\n onClick={() => {\n close();\n item.onSelect();\n }}\n >\n {item.kind ? (\n <span aria-hidden className=\"mt-0.5 size-4 shrink-0\">\n {item.checked && <Check className=\"size-4\" />}\n </span>\n ) : (\n item.icon && <span className=\"mt-0.5 shrink-0\">{item.icon}</span>\n )}\n <span className=\"min-w-0\">\n <span className=\"block\">{item.label}</span>\n {item.hint && <span className=\"block text-xs text-muted\">{item.hint}</span>}\n </span>\n </button>\n ),\n )}\n </div>\n )}\n </div>\n );\n}\n\nfunction focusMenuItem(menu: HTMLElement | null, dir: 1 | -1 | \"first\" | \"last\"): void {\n const els = [\n ...(menu?.querySelectorAll<HTMLElement>('[role^=\"menuitem\"]:not([disabled])') ?? []),\n ];\n if (els.length === 0) return;\n const idx = els.indexOf(document.activeElement as HTMLElement);\n let next = 0;\n if (dir === \"first\") next = 0;\n else if (dir === \"last\") next = els.length - 1;\n else next = (idx + dir + els.length) % els.length;\n els[next]!.focus();\n}\n"],"ignoreList":[0,1,2],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{_ as e,m as t,t as n}from"./jsx-runtime-D13aM9HY.js";import{h as r}from"./states-DrTQuYXw.js";import{U as i,g as a}from"./index-
|
|
2
|
-
//# sourceMappingURL=Overlay-
|
|
1
|
+
import{_ as e,m as t,t as n}from"./jsx-runtime-D13aM9HY.js";import{h as r}from"./states-DrTQuYXw.js";import{U as i,g as a}from"./index-Cf6ZUCfK.js";var o=i(),s=e(t(),1),c=n(),l=(0,s.forwardRef)(function({label:e,icon:t,variant:n=`ghost`,size:i=`md`,className:a,type:o,...s},l){return(0,c.jsx)(`button`,{ref:l,type:o??`button`,"aria-label":e,title:e,className:r(`tap inline-flex shrink-0 items-center justify-center rounded-md border transition-colors`,`disabled:opacity-55 disabled:pointer-events-none`,i===`sm`?`size-8`:`size-9`,n===`ghost`&&`border-transparent text-muted hover:bg-surface-2 hover:text-text`,n===`secondary`&&`border-border bg-surface text-text hover:bg-surface-2`,n===`danger`&&`border-transparent text-danger hover:bg-danger-soft`,a),...s,children:t})}),u=`a[href], area[href], button:not([disabled]), input:not([disabled]):not([type="hidden"]), select:not([disabled]), textarea:not([disabled]), iframe, [tabindex]:not([tabindex="-1"]), [contenteditable="true"]`;function d(e){return[...e.querySelectorAll(u)].filter(e=>!e.hasAttribute(`inert`)&&e.getClientRects().length>0)}function f(e,t,n,r){let i=(0,s.useRef)(n);i.current=n;let a=(0,s.useRef)(null),o=(0,s.useRef)(!1);t&&!o.current&&typeof document<`u`&&(a.current=document.activeElement),o.current=t,(0,s.useEffect)(()=>{if(!t)return;let n=e.current;if(!n)return;let o=a.current,s=o&&!n.contains(o)?o:document.activeElement,c=r?.current??d(n)[0]??n,l=requestAnimationFrame(()=>{(r?.current||!n.contains(document.activeElement))&&c.focus({preventScroll:!0})}),u=e=>{if(e.key===`Escape`&&i.current){e.stopPropagation(),i.current();return}if(e.key!==`Tab`)return;let t=d(n);if(t.length===0){e.preventDefault(),n.focus();return}let r=t[0],a=t[t.length-1],o=document.activeElement;e.shiftKey&&(o===r||!n.contains(o))?(e.preventDefault(),a.focus()):e.shiftKey||o!==a&&n.contains(o)||(e.preventDefault(),r.focus())};return n.addEventListener(`keydown`,u),()=>{cancelAnimationFrame(l),n.removeEventListener(`keydown`,u),s&&document.contains(s)&&s.focus({preventScroll:!0})}},[t,e,r])}function p(e){(0,s.useEffect)(()=>{if(!e)return;let t=document.body.style.overflow;return document.body.style.overflow=`hidden`,()=>{document.body.style.overflow=t}},[e])}function m({placement:e,open:t,onClose:n,title:i,description:u,children:d,footer:m,initialFocus:h,dismissOnBackdrop:g=!0,headerActions:_,className:v,style:y}){let b=(0,s.useRef)(null),x=(0,s.useId)(),S=(0,s.useId)();return f(b,t,n,h),p(t),t?(0,o.createPortal)((0,c.jsxs)(`div`,{className:r(`fixed inset-0 z-50 flex`,e===`right`&&`justify-end`,e===`bottom`&&`items-end`,e===`center`&&`items-center justify-center p-4`),children:[(0,c.jsx)(`div`,{className:`absolute inset-0 bg-overlay`,"aria-hidden":!0,onClick:g?n:void 0}),(0,c.jsxs)(`div`,{ref:b,role:`dialog`,"aria-modal":`true`,"aria-labelledby":x,"aria-describedby":u?S:void 0,tabIndex:-1,style:y,className:r(`relative flex flex-col bg-surface text-text shadow-pop outline-none`,e===`right`&&`h-full max-w-full border-l border-border safe-pt safe-pb`,e===`bottom`&&`max-h-[90dvh] w-full rounded-t-xl border-t border-border safe-pb`,e===`center`&&`max-h-[min(90dvh,720px)] w-full max-w-lg rounded-xl border border-border`,v),children:[e===`bottom`&&(0,c.jsx)(`div`,{className:`flex justify-center pt-2`,"aria-hidden":!0,children:(0,c.jsx)(`div`,{className:`h-1 w-10 rounded-full bg-border-strong`})}),(0,c.jsxs)(`div`,{className:`flex items-start gap-2 border-b border-border px-4 py-3`,children:[(0,c.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,c.jsx)(`h2`,{id:x,className:`text-base font-semibold leading-6`,children:i}),u&&(0,c.jsx)(`p`,{id:S,className:`text-sm text-muted`,children:u})]}),_,(0,c.jsx)(l,{label:`Close`,icon:(0,c.jsx)(a,{className:`size-4`}),onClick:n})]}),(0,c.jsx)(`div`,{className:`min-h-0 flex-1 overflow-y-auto overscroll-contain px-4 py-3`,children:d}),m&&(0,c.jsx)(`div`,{className:`flex flex-wrap items-center justify-end gap-2 border-t border-border px-4 py-3`,children:m})]})]}),document.body):null}function h({width:e=520,...t}){return(0,c.jsx)(m,{...t,placement:`right`,style:{width:`min(${e}px, 100vw)`}})}function g(e){return(0,c.jsx)(m,{...e,placement:`bottom`})}function _(e){return(0,c.jsx)(m,{...e,placement:`center`})}export{l as a,f as i,h as n,g as r,_ as t};
|
|
2
|
+
//# sourceMappingURL=Overlay-oYnnwvFM.js.map
|