@anvia/studio 1.1.2 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/README.md +52 -0
  2. package/dist/index.d.ts +31 -4
  3. package/dist/index.js +19806 -626
  4. package/dist/index.js.map +1 -1
  5. package/dist/ui/assets/ArrowClockwise.es-Dn4lp0ac.js +2 -0
  6. package/dist/ui/assets/{ArrowClockwise.es-5vr4h4OH.js.map → ArrowClockwise.es-Dn4lp0ac.js.map} +1 -1
  7. package/dist/ui/assets/Check.es-BaQZo8Jl.js +2 -0
  8. package/dist/ui/assets/{Check.es-DgvuCllR.js.map → Check.es-BaQZo8Jl.js.map} +1 -1
  9. package/dist/ui/assets/Combination-Cj4UR5tg.js +42 -0
  10. package/dist/ui/assets/Combination-Cj4UR5tg.js.map +1 -0
  11. package/dist/ui/assets/Copy.es-CU5v9Pav.js +2 -0
  12. package/dist/ui/assets/{Copy.es-DV7tb_eC.js.map → Copy.es-CU5v9Pav.js.map} +1 -1
  13. package/dist/ui/assets/MagnifyingGlass.es-C72UX0bz.js +2 -0
  14. package/dist/ui/assets/{MagnifyingGlass.es-yzEp9c89.js.map → MagnifyingGlass.es-C72UX0bz.js.map} +1 -1
  15. package/dist/ui/assets/Wrench.es-Q3fLRWow.js +2 -0
  16. package/dist/ui/assets/{Wrench.es-rRuP3Mrh.js.map → Wrench.es-Q3fLRWow.js.map} +1 -1
  17. package/dist/ui/assets/agents-page-6DCSMWnZ.js +2 -0
  18. package/dist/ui/assets/{agents-page-ByhvVYOx.js.map → agents-page-6DCSMWnZ.js.map} +1 -1
  19. package/dist/ui/assets/badge-DUs0RCHV.js +2 -0
  20. package/dist/ui/assets/{badge-C3fkxijh.js.map → badge-DUs0RCHV.js.map} +1 -1
  21. package/dist/ui/assets/button-BWxpVW85.js +2 -0
  22. package/dist/ui/assets/{button-B_AoswCu.js.map → button-BWxpVW85.js.map} +1 -1
  23. package/dist/ui/assets/dialog-DauYXFnG.js +2 -0
  24. package/dist/ui/assets/{dialog-BfKpnby4.js.map → dialog-DauYXFnG.js.map} +1 -1
  25. package/dist/ui/assets/dist-BmLOFYIW.js +2 -0
  26. package/dist/ui/assets/{dist-Dr6EWOhl.js.map → dist-BmLOFYIW.js.map} +1 -1
  27. package/dist/ui/assets/dist-CHLp-Np4.js +2 -0
  28. package/dist/ui/assets/dist-CHLp-Np4.js.map +1 -0
  29. package/dist/ui/assets/dist-DD97Shn_.js +2 -0
  30. package/dist/ui/assets/{dist-CUv0NHNl.js.map → dist-DD97Shn_.js.map} +1 -1
  31. package/dist/ui/assets/graphs-page-BA0jzknS.js +2 -0
  32. package/dist/ui/assets/{graphs-page-vBCjLEva.js.map → graphs-page-BA0jzknS.js.map} +1 -1
  33. package/dist/ui/assets/icon-ksPSRwE8.js +2 -0
  34. package/dist/ui/assets/{icon-DyadsXLr.js.map → icon-ksPSRwE8.js.map} +1 -1
  35. package/dist/ui/assets/index-DDzW7QMd.css +2 -0
  36. package/dist/ui/assets/{index-D7rMlAzl.js → index-Dyjst4Yt.js} +5 -5
  37. package/dist/ui/assets/index-Dyjst4Yt.js.map +1 -0
  38. package/dist/ui/assets/input-DdUxz9c8.js +2 -0
  39. package/dist/ui/assets/{input-DuERdYTl.js.map → input-DdUxz9c8.js.map} +1 -1
  40. package/dist/ui/assets/knowledge-page-BVVc4w3w.js +2 -0
  41. package/dist/ui/assets/{knowledge-page-ZeAUXg01.js.map → knowledge-page-BVVc4w3w.js.map} +1 -1
  42. package/dist/ui/assets/mcps-page-BfF4B22U.js +2 -0
  43. package/dist/ui/assets/{mcps-page-BSkygYJM.js.map → mcps-page-BfF4B22U.js.map} +1 -1
  44. package/dist/ui/assets/{memory-page-B2pWZ4in.js → memory-page-BQkt2BAW.js} +2 -2
  45. package/dist/ui/assets/memory-page-BQkt2BAW.js.map +1 -0
  46. package/dist/ui/assets/pipelines-page-Xx2kQNCI.js +2 -0
  47. package/dist/ui/assets/pipelines-page-Xx2kQNCI.js.map +1 -0
  48. package/dist/ui/assets/{renderers-DRD34eUr.js → renderers-CrjMPAR2.js} +5 -5
  49. package/dist/ui/assets/{renderers-DRD34eUr.js.map → renderers-CrjMPAR2.js.map} +1 -1
  50. package/dist/ui/assets/{request-DbgMKweq.js → request-DYxy87Kp.js} +3 -3
  51. package/dist/ui/assets/{request-DbgMKweq.js.map → request-DYxy87Kp.js.map} +1 -1
  52. package/dist/ui/assets/sandboxes-page-BwidNA5G.js +2 -0
  53. package/dist/ui/assets/{sandboxes-page-Bo4S4ILL.js.map → sandboxes-page-BwidNA5G.js.map} +1 -1
  54. package/dist/ui/assets/select-C4MbvpHr.js +2 -0
  55. package/dist/ui/assets/{select-BdCBnmXx.js.map → select-C4MbvpHr.js.map} +1 -1
  56. package/dist/ui/assets/sessions-page-C3dJDjJb.js +2 -0
  57. package/dist/ui/assets/{sessions-page-BMnR-r_F.js.map → sessions-page-C3dJDjJb.js.map} +1 -1
  58. package/dist/ui/assets/status-page-92JD9Hj8.js +2 -0
  59. package/dist/ui/assets/{status-page-CqmMMSo2.js.map → status-page-92JD9Hj8.js.map} +1 -1
  60. package/dist/ui/assets/studio-CtQdOoHK.js +2 -0
  61. package/dist/ui/assets/{studio-DzEdCFsX.js.map → studio-CtQdOoHK.js.map} +1 -1
  62. package/dist/ui/assets/style-CrHHNFw2.js +8 -0
  63. package/dist/ui/assets/{style-FGiH1LIC.js.map → style-CrHHNFw2.js.map} +1 -1
  64. package/dist/ui/assets/team-playground-GcG3j0Hl.js +2 -0
  65. package/dist/ui/assets/team-playground-GcG3j0Hl.js.map +1 -0
  66. package/dist/ui/assets/textarea-gPj9-ALc.js +2 -0
  67. package/dist/ui/assets/{textarea-fAtCF2cf.js.map → textarea-gPj9-ALc.js.map} +1 -1
  68. package/dist/ui/assets/tool-runner-xLspgGPa.js +2 -0
  69. package/dist/ui/assets/{tool-runner-CExWna8k.js.map → tool-runner-xLspgGPa.js.map} +1 -1
  70. package/dist/ui/assets/tools-page-BMyx2xRT.js +2 -0
  71. package/dist/ui/assets/{tools-page-CdkExqNd.js.map → tools-page-BMyx2xRT.js.map} +1 -1
  72. package/dist/ui/assets/trace-browser-Axd-aif6.js +4 -0
  73. package/dist/ui/assets/{trace-browser-Co9iS9HR.js.map → trace-browser-Axd-aif6.js.map} +1 -1
  74. package/dist/ui/assets/transcript-item-Bl3Yl-NT.js +3 -0
  75. package/dist/ui/assets/{transcript-item-D9NWsnsD.js.map → transcript-item-Bl3Yl-NT.js.map} +1 -1
  76. package/dist/ui/assets/with-selector-BIQdjRiO.js +2 -0
  77. package/dist/ui/assets/{with-selector-B8ah9Wvu.js.map → with-selector-BIQdjRiO.js.map} +1 -1
  78. package/dist/ui/index.html +17 -17
  79. package/package.json +8 -8
  80. package/dist/ui/assets/ArrowClockwise.es-5vr4h4OH.js +0 -2
  81. package/dist/ui/assets/Check.es-DgvuCllR.js +0 -2
  82. package/dist/ui/assets/Copy.es-DV7tb_eC.js +0 -2
  83. package/dist/ui/assets/MagnifyingGlass.es-yzEp9c89.js +0 -2
  84. package/dist/ui/assets/Wrench.es-rRuP3Mrh.js +0 -2
  85. package/dist/ui/assets/agents-page-ByhvVYOx.js +0 -2
  86. package/dist/ui/assets/badge-C3fkxijh.js +0 -2
  87. package/dist/ui/assets/button-B_AoswCu.js +0 -2
  88. package/dist/ui/assets/dialog-BfKpnby4.js +0 -2
  89. package/dist/ui/assets/dist-CUv0NHNl.js +0 -2
  90. package/dist/ui/assets/dist-Dr6EWOhl.js +0 -2
  91. package/dist/ui/assets/es2015-DGcxtKLK.js +0 -42
  92. package/dist/ui/assets/es2015-DGcxtKLK.js.map +0 -1
  93. package/dist/ui/assets/graphs-page-vBCjLEva.js +0 -2
  94. package/dist/ui/assets/icon-DyadsXLr.js +0 -2
  95. package/dist/ui/assets/index-BGl7eOVR.css +0 -2
  96. package/dist/ui/assets/index-D7rMlAzl.js.map +0 -1
  97. package/dist/ui/assets/input-DuERdYTl.js +0 -2
  98. package/dist/ui/assets/knowledge-page-ZeAUXg01.js +0 -2
  99. package/dist/ui/assets/mcps-page-BSkygYJM.js +0 -2
  100. package/dist/ui/assets/memory-page-B2pWZ4in.js.map +0 -1
  101. package/dist/ui/assets/pipelines-page-DAqa699J.js +0 -2
  102. package/dist/ui/assets/pipelines-page-DAqa699J.js.map +0 -1
  103. package/dist/ui/assets/sandboxes-page-Bo4S4ILL.js +0 -2
  104. package/dist/ui/assets/select-BdCBnmXx.js +0 -2
  105. package/dist/ui/assets/sessions-page-BMnR-r_F.js +0 -2
  106. package/dist/ui/assets/status-page-CqmMMSo2.js +0 -2
  107. package/dist/ui/assets/studio-DzEdCFsX.js +0 -2
  108. package/dist/ui/assets/style-FGiH1LIC.js +0 -8
  109. package/dist/ui/assets/textarea-fAtCF2cf.js +0 -2
  110. package/dist/ui/assets/tool-runner-CExWna8k.js +0 -2
  111. package/dist/ui/assets/tools-page-CdkExqNd.js +0 -2
  112. package/dist/ui/assets/trace-browser-Co9iS9HR.js +0 -4
  113. package/dist/ui/assets/transcript-item-D9NWsnsD.js +0 -3
  114. package/dist/ui/assets/utils-DzstcfqT.js +0 -2
  115. package/dist/ui/assets/utils-DzstcfqT.js.map +0 -1
  116. package/dist/ui/assets/with-selector-B8ah9Wvu.js +0 -2
@@ -0,0 +1,2 @@
1
+ import{i as e,n as t,r as n,s as r}from"./dist-CHLp-Np4.js";import{s as i,t as a}from"./button-BWxpVW85.js";import{c as o,i as s,t as c}from"./request-DYxy87Kp.js";import{t as l}from"./textarea-gPj9-ALc.js";import{r as u}from"./renderers-CrjMPAR2.js";var d=r(e(),1),f=n();function p(e){let[t,n]=(0,d.useState)({}),{request:r,status:i}=e.item,o=e.busy||i!==`pending`;return(0,f.jsxs)(`section`,{className:`space-y-3 rounded-xl border border-hair bg-card p-4`,"aria-label":`${e.name}: ${r.toolName}`,children:[(0,f.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-2 text-sm`,children:[(0,f.jsxs)(`strong`,{children:[e.name,` · `,r.toolName]}),(0,f.jsx)(`span`,{className:`text-muted-foreground`,children:e.busy?`Submitting…`:i===`pending`?`Needs your input`:i})]}),(0,f.jsxs)(`p`,{className:`break-all text-xs text-muted-foreground`,children:[`Instance `,e.item.instanceId]}),r.type===`tool-approval`?(0,f.jsxs)(f.Fragment,{children:[r.reason&&(0,f.jsx)(`p`,{className:`text-sm`,children:r.reason}),(0,f.jsx)(`pre`,{className:`max-h-48 overflow-auto whitespace-pre-wrap break-all text-xs`,children:JSON.stringify(r.input,null,2)}),(0,f.jsxs)(`div`,{className:`flex gap-2`,children:[(0,f.jsx)(a,{size:`sm`,disabled:o,onClick:()=>void e.respond(r.id,{type:`tool-approval`,approved:!0}),children:`Approve`}),(0,f.jsx)(a,{size:`sm`,variant:`secondary`,disabled:o,onClick:()=>void e.respond(r.id,{type:`tool-approval`,approved:!1}),children:`Deny`})]})]}):(0,f.jsxs)(`form`,{className:`space-y-3`,onSubmit:n=>{n.preventDefault(),e.respond(r.id,{type:`tool-question`,answers:r.questions.map(e=>({questionId:e.id,value:t[e.id]??``}))})},children:[r.questions.map(e=>(0,f.jsxs)(`fieldset`,{disabled:o,className:`space-y-2`,children:[(0,f.jsx)(`legend`,{className:`mb-2 text-sm`,children:e.text}),e.choices?.map(i=>(0,f.jsxs)(`label`,{className:`flex items-center gap-2 text-sm`,children:[(0,f.jsx)(`input`,{type:`radio`,name:`${r.id}:${e.id}`,value:i.value,checked:t[e.id]===i.value,onChange:()=>n(t=>({...t,[e.id]:i.value}))}),i.label]},i.value)),(!e.choices?.length||e.allowCustom)&&(0,f.jsx)(l,{"aria-label":e.text,placeholder:`Your answer`,value:t[e.id]??``,onChange:t=>n(n=>({...n,[e.id]:t.target.value}))})]},e.id)),(0,f.jsx)(a,{size:`sm`,disabled:o||r.questions.some(e=>!t[e.id]?.trim()),children:`Send answers`})]})]})}function m(e){let n=Object.values(e.state.members),r=e.state.members[e.selected]??n.find(e=>e.depth===0);function a(i){return(0,f.jsxs)(`li`,{children:[(0,f.jsxs)(`button`,{type:`button`,onClick:()=>e.select(i.instanceId),title:i.instanceId,"aria-pressed":r?.instanceId===i.instanceId,className:t(`flex w-full items-center justify-between gap-3 rounded-lg px-3 py-2 text-left text-sm hover:bg-muted`,r?.instanceId===i.instanceId&&`bg-muted`),style:{paddingLeft:12+i.depth*16},children:[(0,f.jsxs)(`span`,{className:`min-w-0 truncate`,children:[i.depth>0?`↳ `:``,i.name]}),(0,f.jsx)(`span`,{className:`shrink-0 text-xs text-muted-foreground`,children:i.status.replaceAll(`_`,` `)})]}),(0,f.jsx)(`ul`,{children:n.filter(e=>e.parentInstanceId===i.instanceId).map(a)})]},i.instanceId)}return(0,f.jsxs)(`div`,{className:`space-y-5`,children:[(0,f.jsxs)(`div`,{children:[(0,f.jsxs)(`h2`,{className:`mb-3 text-sm font-medium`,children:[`Members `,(0,f.jsx)(`span`,{className:`text-muted-foreground`,children:n.length})]}),n.length?(0,f.jsx)(`ul`,{"aria-label":`Team members`,children:n.filter(e=>!e.parentInstanceId).map(a)}):(0,f.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`Spawned agents will appear here as the team works.`})]}),r&&(0,f.jsxs)(`section`,{className:`space-y-4 border-t border-hair pt-4`,"aria-label":`Member details`,children:[(0,f.jsxs)(`div`,{children:[(0,f.jsx)(`h3`,{className:`text-sm font-medium`,children:r.name}),(0,f.jsxs)(`p`,{className:`break-all text-xs text-muted-foreground`,children:[r.agentId,` · `,r.instanceId]})]}),r.error!==void 0&&(0,f.jsx)(`p`,{role:`alert`,className:`text-sm text-status-danger-ink`,children:i(r.error)}),(0,f.jsxs)(`details`,{className:`text-xs`,children:[(0,f.jsx)(`summary`,{className:`cursor-pointer text-muted-foreground`,children:`Token usage`}),(0,f.jsx)(`pre`,{className:`overflow-auto p-2`,children:JSON.stringify(r.usage,null,2)})]}),e.state.turns.filter(e=>e.instanceId===r.instanceId).map(t=>(0,f.jsxs)(`div`,{className:`space-y-3`,children:[t.text&&(0,f.jsx)(u,{text:t.text,live:e.state.status===`running`}),t.tools.length>0&&(0,f.jsxs)(`details`,{children:[(0,f.jsxs)(`summary`,{className:`cursor-pointer text-xs text-muted-foreground`,children:[`Tool activity (`,t.tools.length,`)`]}),t.tools.map((e,t)=>(0,f.jsx)(`pre`,{className:`my-2 max-h-60 overflow-auto whitespace-pre-wrap break-all rounded-lg bg-muted p-3 text-xs`,children:e},t))]}),t.messages&&(0,f.jsxs)(`details`,{children:[(0,f.jsx)(`summary`,{className:`cursor-pointer text-xs text-muted-foreground`,children:`Run messages`}),(0,f.jsx)(`pre`,{className:`max-h-96 overflow-auto whitespace-pre-wrap break-all text-xs`,children:JSON.stringify(t.messages,null,2)})]})]},t.key))]})]})}function h({state:e}){let t=t=>e.members[t]?.name??t;return(0,f.jsxs)(`section`,{className:`space-y-3`,"aria-label":`Messages between agents`,children:[(0,f.jsxs)(`h2`,{className:`text-sm font-medium`,children:[`Messages `,(0,f.jsx)(`span`,{className:`text-muted-foreground`,children:e.messages.length})]}),!e.messages.length&&(0,f.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`Messages between agents will appear here.`}),e.messages.map(({message:e,delivered:n})=>(0,f.jsxs)(`article`,{className:`space-y-2 rounded-lg border border-hair p-3`,children:[(0,f.jsxs)(`div`,{className:`text-xs font-medium`,children:[t(e.fromInstanceId),` → `,t(e.toInstanceId)]}),(0,f.jsx)(`p`,{className:`whitespace-pre-wrap break-words text-sm`,children:e.content}),(0,f.jsxs)(`p`,{className:`text-xs text-muted-foreground`,children:[n?`Delivered`:`Queued`,` ·`,` `,new Date(e.createdAt).toLocaleTimeString()]})]},e.id))]})}var g={status:`idle`,members:{},turns:[],messages:[],interactions:{},conversation:[]};function _(e,t){return Object.fromEntries(Object.entries(e.interactions).map(([e,n])=>[e,n.status===`pending`&&(t===void 0||n.instanceId===t)?{...n,status:`cancelled`}:n]))}function v(e,t){switch(t.type){case`reset`:return g;case`start`:return{...g,status:`running`,conversation:[{type:`prompt`,text:t.prompt}]};case`prompt`:return{...e,conversation:[...e.conversation,{type:`prompt`,text:t.prompt}]};case`stop`:return{...e,status:t.error?`failed`:`cancelled`,...t.error?{error:t.error}:{},interactions:_(e),members:Object.fromEntries(Object.entries(e.members).map(([e,t])=>[e,[`queued`,`running`,`waiting`,`awaiting_interaction`].includes(t.status)?{...t,status:`cancelled`}:t]))};case`answered`:{let n=e.interactions[t.id];return n===void 0?e:{...e,interactions:{...e.interactions,[t.id]:{...n,status:`answered`}}}}}let n=t.event;if(n.type===`team_run_started`)return{...e,runId:n.runId};if(n.type===`error`)return v(e,{type:`stop`,error:i(n.error)});if(n.type===`response`||n.type===`blocked`)return{...e,status:n.type===`response`?`completed`:`blocked`,members:{...e.members,...Object.fromEntries(n.members.map(e=>[e.instanceId,e]))},interactions:_(e)};if(`member`in n)return{...e,members:{...e.members,[n.instanceId]:n.member},...n.type===`agent_cancelled`||n.type===`agent_failed`?{interactions:_(e,n.instanceId)}:{}};if(n.type===`interaction`)return{...e,interactions:{...e.interactions,[n.interaction.id]:{instanceId:n.instanceId,request:n.interaction,status:`pending`}}};if(n.type===`message_queued`||n.type===`message_delivered`){let t=e.messages.find(e=>e.message.id===n.message.id),r={message:n.message,delivered:t?.delivered===!0||n.type===`message_delivered`};return{...e,messages:t?e.messages.map(e=>e.message.id===r.message.id?r:e):[...e.messages,r].slice(-500)}}if(n.type!==`agent_event`)return e;let r=`${n.instanceId}:${n.runId??`initial`}`,a=e.turns.find(e=>e.key===r)??{key:r,instanceId:n.instanceId,coordinator:n.coordinator,text:``,tools:[]},o=n.event,s;switch(o.type){case`text_delta`:s={...a,text:a.text+o.delta};break;case`tool_call`:s={...a,tools:[...a.tools,JSON.stringify(o.toolCall)].slice(-100)};break;case`tool_result`:s={...a,tools:[...a.tools,`${o.toolName}: ${JSON.stringify(o.output,null,2)}`].slice(-100)};break;case`response`:case`blocked`:s={...a,text:o.text,messages:o.messages,tools:o.messages.flatMap(e=>typeof e.content==`string`?[]:e.content.filter(e=>e.type===`tool-call`||e.type===`tool-result`).map(e=>JSON.stringify(e,null,2))).slice(-100)};break;default:return e}return{...e,conversation:s.coordinator&&!e.turns.some(e=>e.key===r)?[...e.conversation,{type:`turn`,key:r}].slice(-500):e.conversation,turns:e.turns.some(e=>e.key===r)?e.turns.map(e=>e.key===r?s:e):[...e.turns,s].slice(-500)}}function y(e){!e||e.controller.signal.aborted||(e.runId&&fetch(`${e.base}/${encodeURIComponent(e.runId)}/cancel`,{method:`POST`,headers:{"Content-Type":`application/json`},body:`{}`,keepalive:!0,signal:AbortSignal.timeout(5e3)}).catch(()=>{}),e.controller.abort())}function b(e){let[t,n]=(0,d.useReducer)(v,g),[r,a]=(0,d.useState)(``),[l,u]=(0,d.useState)(new Set),f=(0,d.useRef)(void 0),p=(0,d.useRef)(0),m=`/teams/${encodeURIComponent(e)}/runs`;(0,d.useEffect)(()=>()=>{y(f.current),f.current=void 0,p.current++},[e]);async function h(e){if(f.current)return;let t={controller:new AbortController,base:m,runId:void 0,pending:new Set,epoch:++p.current};f.current=t,u(new Set),a(``),n({type:`start`,prompt:e});try{let r=await fetch(m,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({prompt:e}),signal:t.controller.signal});if(!r.ok)throw Error(await s(r,`Start team`));if(!r.body)throw Error(`Team response has no stream`);t.runId=r.headers.get(`x-anvia-team-run-id`)??void 0;for await(let e of o(r.body)){if(f.current!==t||t.controller.signal.aborted)break;e.type===`team_run_started`&&(t.runId=e.runId);let r=e.type===`response`||e.type===`blocked`||e.type===`error`;if(r&&(f.current=void 0),n({type:`event`,event:e}),r)return}if(!t.controller.signal.aborted)throw Error(`Team stream ended before a result arrived`)}catch(e){f.current===t&&n({type:`stop`,...t.controller.signal.aborted?{}:{error:i(e)}})}finally{f.current===t&&(f.current=void 0)}}async function _(e,t,n,r){let o=f.current;if(!o?.runId||o.pending.has(e))return!1;o.pending.add(e),u(new Set(o.pending)),a(``);try{return await c(`${m}/${encodeURIComponent(o.runId)}${t}`,`Update team`,o.controller.signal,`default`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(n)}),p.current===o.epoch&&!o.controller.signal.aborted&&r(),!0}catch(e){return f.current===o&&!o.controller.signal.aborted&&a(i(e)),!1}finally{o.pending.delete(e),p.current===o.epoch&&u(new Set(o.pending))}}function b(){f.current&&(y(f.current),n({type:`stop`}))}return{state:t,busy:l,controlError:r,start:h,stop:b,reset:()=>{f.current||(p.current++,n({type:`reset`}),a(``))},steer:e=>_(`steer`,`/steer`,{prompt:e},()=>n({type:`prompt`,prompt:e})),respond:(e,t)=>_(e,`/interactions/${encodeURIComponent(e)}`,t,()=>n({type:`answered`,id:e}))}}function x({team:e,targetSelector:t}){let n=b(e.id),[r,i]=(0,d.useState)(``),[o,s]=(0,d.useState)(``),[c,g]=(0,d.useState)(`members`),_=(0,d.useRef)(null),v=(0,d.useRef)(!0),y=n.state.status===`running`,x=n.state.status!==`idle`;(0,d.useEffect)(()=>{let e=_.current;e&&v.current&&(e.scrollTop=e.scrollHeight)},[n.state]);async function S(){let e=r.trim();e&&(y?await n.steer(e)&&i(``):(i(``),v.current=!0,n.start(e)))}return(0,f.jsxs)(`div`,{className:`flex min-h-0 min-w-0 flex-col overflow-auto lg:overflow-hidden`,children:[(0,f.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-3 border-b border-hair px-5 py-3`,children:[(0,f.jsx)(`div`,{className:`flex items-center gap-3`,children:t(y)}),(0,f.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,f.jsx)(`span`,{role:`status`,className:`text-xs text-muted-foreground`,children:n.state.status}),(0,f.jsx)(a,{variant:`secondary`,size:`sm`,disabled:y,onClick:()=>{n.reset(),i(``),s(``)},children:`New task`})]})]}),(0,f.jsxs)(`div`,{className:`grid min-h-0 min-w-0 flex-1 grid-cols-1 lg:grid-cols-[minmax(0,1fr)_360px] xl:grid-cols-[minmax(0,1fr)_420px]`,children:[(0,f.jsxs)(`div`,{className:`flex min-h-[480px] min-w-0 flex-col lg:min-h-0`,children:[(0,f.jsx)(`div`,{ref:_,className:`min-h-0 flex-1 overflow-auto px-5 py-6`,onScroll:()=>{let e=_.current;e&&(v.current=e.scrollHeight-e.scrollTop-e.clientHeight<80)},children:(0,f.jsxs)(`div`,{className:`mx-auto max-w-3xl space-y-6`,children:[!x&&(0,f.jsxs)(`div`,{className:`py-16`,children:[(0,f.jsxs)(`h1`,{className:`text-2xl font-medium`,children:[`Work with `,e.id]}),(0,f.jsx)(`p`,{className:`mt-3 text-sm text-muted-foreground`,children:`Give the coordinator a task. Follow its agents, messages, and requests as they work.`}),(0,f.jsxs)(`p`,{className:`mt-4 text-xs text-muted-foreground`,children:[`Available members:`,` `,e.members.map(e=>e.name??e.id).join(`, `)||`None`]})]}),n.state.conversation.map((e,t)=>{if(e.type===`prompt`)return(0,f.jsxs)(`article`,{className:`rounded-xl bg-muted p-4`,children:[(0,f.jsx)(`div`,{className:`mb-2 text-xs text-muted-foreground`,children:`You`}),(0,f.jsx)(`p`,{className:`whitespace-pre-wrap break-words text-sm`,children:e.text})]},`prompt:${t}`);let r=n.state.turns.find(t=>t.key===e.key);return r?.text?(0,f.jsxs)(`article`,{children:[(0,f.jsx)(`div`,{className:`mb-2 text-xs text-muted-foreground`,children:`Coordinator`}),(0,f.jsx)(u,{text:r.text,live:y,size:`base`})]},e.key):null}),Object.values(n.state.interactions).map(e=>(0,f.jsx)(p,{item:e,name:n.state.members[e.instanceId]?.name??e.instanceId,busy:n.busy.has(e.request.id),respond:n.respond},e.request.id)),n.state.error&&(0,f.jsx)(`p`,{role:`alert`,className:`text-sm text-status-danger-ink`,children:n.state.error}),n.controlError&&(0,f.jsx)(`p`,{role:`alert`,className:`text-sm text-status-danger-ink`,children:n.controlError})]})}),(0,f.jsxs)(`form`,{className:`mx-auto w-full max-w-3xl space-y-3 px-5 pb-5 pt-3`,onSubmit:e=>{e.preventDefault(),S()},children:[(0,f.jsx)(l,{"aria-label":y?`Message coordinator`:`Team task`,placeholder:y?`Send a follow-up to the coordinator…`:`Give this team a task…`,value:r,maxLength:32768,onChange:e=>i(e.target.value),disabled:x&&!y,onKeyDown:e=>{e.key===`Enter`&&!e.shiftKey&&!e.nativeEvent.isComposing&&(e.preventDefault(),(!x||y)&&!n.busy.has(`steer`)&&S())}}),(0,f.jsxs)(`div`,{className:`flex items-center justify-between gap-2`,children:[(0,f.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`This run stays in this page. Leaving stops active work.`}),y&&(0,f.jsx)(a,{type:`button`,variant:`secondary`,size:`sm`,onClick:n.stop,children:`Stop team`}),(0,f.jsx)(a,{size:`sm`,disabled:!r.trim()||x&&!y||y&&(!n.state.runId||n.busy.has(`steer`)),children:y?`Send follow-up`:`Run team`})]})]})]}),(0,f.jsxs)(`aside`,{className:`min-h-64 min-w-0 space-y-5 overflow-auto border-t border-hair p-5 lg:border-t-0 lg:border-l`,"aria-label":`Team activity`,children:[(0,f.jsxs)(`div`,{className:`flex gap-2`,children:[(0,f.jsx)(a,{variant:c===`members`?`secondary`:`ghost`,size:`sm`,onClick:()=>g(`members`),children:`Members`}),(0,f.jsx)(a,{variant:c===`messages`?`secondary`:`ghost`,size:`sm`,onClick:()=>g(`messages`),children:`Messages`})]}),c===`members`?(0,f.jsx)(m,{state:n.state,selected:o,select:s}):(0,f.jsx)(h,{state:n.state})]})]})]})}export{x as TeamPlayground};
2
+ //# sourceMappingURL=team-playground-GcG3j0Hl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"team-playground-GcG3j0Hl.js","names":[],"sources":["../../../src/ui/app/modules/teams/team-interactions.tsx","../../../src/ui/app/modules/teams/team-members.tsx","../../../src/ui/app/modules/teams/team-state.ts","../../../src/ui/app/modules/teams/use-team-run.ts","../../../src/ui/app/modules/teams/team-playground.tsx"],"sourcesContent":["import type { AgentInteractionResponse } from \"@anvia/core/agent/interactions\";\nimport { useState } from \"react\";\nimport { Button } from \"../../components/ui/button\";\nimport { Textarea } from \"../../components/ui/textarea\";\nimport type { TeamInteraction } from \"./team-state\";\n\nexport function TeamInteractionCard(props: {\n item: TeamInteraction;\n name: string;\n busy: boolean;\n respond: (id: string, response: AgentInteractionResponse) => Promise<boolean>;\n}) {\n const [answers, setAnswers] = useState<Record<string, string>>({});\n const { request, status } = props.item;\n const disabled = props.busy || status !== \"pending\";\n return (\n <section\n className=\"space-y-3 rounded-xl border border-hair bg-card p-4\"\n aria-label={`${props.name}: ${request.toolName}`}\n >\n <div className=\"flex flex-wrap items-center justify-between gap-2 text-sm\">\n <strong>\n {props.name} · {request.toolName}\n </strong>\n <span className=\"text-muted-foreground\">\n {props.busy ? \"Submitting…\" : status === \"pending\" ? \"Needs your input\" : status}\n </span>\n </div>\n <p className=\"break-all text-xs text-muted-foreground\">Instance {props.item.instanceId}</p>\n {request.type === \"tool-approval\" ? (\n <>\n {request.reason && <p className=\"text-sm\">{request.reason}</p>}\n <pre className=\"max-h-48 overflow-auto whitespace-pre-wrap break-all text-xs\">\n {JSON.stringify(request.input, null, 2)}\n </pre>\n <div className=\"flex gap-2\">\n <Button\n size=\"sm\"\n disabled={disabled}\n onClick={() =>\n void props.respond(request.id, { type: \"tool-approval\", approved: true })\n }\n >\n Approve\n </Button>\n <Button\n size=\"sm\"\n variant=\"secondary\"\n disabled={disabled}\n onClick={() =>\n void props.respond(request.id, { type: \"tool-approval\", approved: false })\n }\n >\n Deny\n </Button>\n </div>\n </>\n ) : (\n <form\n className=\"space-y-3\"\n onSubmit={(event) => {\n event.preventDefault();\n void props.respond(request.id, {\n type: \"tool-question\",\n answers: request.questions.map((question) => ({\n questionId: question.id,\n value: answers[question.id] ?? \"\",\n })),\n });\n }}\n >\n {request.questions.map((question) => (\n <fieldset key={question.id} disabled={disabled} className=\"space-y-2\">\n <legend className=\"mb-2 text-sm\">{question.text}</legend>\n {question.choices?.map((choice) => (\n <label key={choice.value} className=\"flex items-center gap-2 text-sm\">\n <input\n type=\"radio\"\n name={`${request.id}:${question.id}`}\n value={choice.value}\n checked={answers[question.id] === choice.value}\n onChange={() =>\n setAnswers((previous) => ({ ...previous, [question.id]: choice.value }))\n }\n />\n {choice.label}\n </label>\n ))}\n {(!question.choices?.length || question.allowCustom) && (\n <Textarea\n aria-label={question.text}\n placeholder=\"Your answer\"\n value={answers[question.id] ?? \"\"}\n onChange={(event) =>\n setAnswers((previous) => ({ ...previous, [question.id]: event.target.value }))\n }\n />\n )}\n </fieldset>\n ))}\n <Button\n size=\"sm\"\n disabled={\n disabled || request.questions.some((question) => !answers[question.id]?.trim())\n }\n >\n Send answers\n </Button>\n </form>\n )}\n </section>\n );\n}\n","import type { AgentTeamMemberSummary } from \"@anvia/core/agent\";\nimport { MarkdownText } from \"../shared/renderers\";\nimport { errorMessage } from \"../shared/format\";\nimport { cn } from \"../../lib/utils\";\nimport type { TeamState } from \"./team-state\";\n\nexport function TeamMembers(props: {\n state: TeamState;\n selected: string;\n select: (id: string) => void;\n}) {\n const members = Object.values(props.state.members);\n const selected =\n props.state.members[props.selected] ?? members.find((member) => member.depth === 0);\n function node(member: AgentTeamMemberSummary) {\n return (\n <li key={member.instanceId}>\n <button\n type=\"button\"\n onClick={() => props.select(member.instanceId)}\n title={member.instanceId}\n aria-pressed={selected?.instanceId === member.instanceId}\n className={cn(\n \"flex w-full items-center justify-between gap-3 rounded-lg px-3 py-2 text-left text-sm hover:bg-muted\",\n selected?.instanceId === member.instanceId && \"bg-muted\",\n )}\n style={{ paddingLeft: 12 + member.depth * 16 }}\n >\n <span className=\"min-w-0 truncate\">\n {member.depth > 0 ? \"↳ \" : \"\"}\n {member.name}\n </span>\n <span className=\"shrink-0 text-xs text-muted-foreground\">\n {member.status.replaceAll(\"_\", \" \")}\n </span>\n </button>\n <ul>{members.filter((child) => child.parentInstanceId === member.instanceId).map(node)}</ul>\n </li>\n );\n }\n return (\n <div className=\"space-y-5\">\n <div>\n <h2 className=\"mb-3 text-sm font-medium\">\n Members <span className=\"text-muted-foreground\">{members.length}</span>\n </h2>\n {members.length ? (\n <ul aria-label=\"Team members\">\n {members.filter((member) => !member.parentInstanceId).map(node)}\n </ul>\n ) : (\n <p className=\"text-sm text-muted-foreground\">\n Spawned agents will appear here as the team works.\n </p>\n )}\n </div>\n {selected && (\n <section className=\"space-y-4 border-t border-hair pt-4\" aria-label=\"Member details\">\n <div>\n <h3 className=\"text-sm font-medium\">{selected.name}</h3>\n <p className=\"break-all text-xs text-muted-foreground\">\n {selected.agentId} · {selected.instanceId}\n </p>\n </div>\n {selected.error !== undefined && (\n <p role=\"alert\" className=\"text-sm text-status-danger-ink\">\n {errorMessage(selected.error)}\n </p>\n )}\n <details className=\"text-xs\">\n <summary className=\"cursor-pointer text-muted-foreground\">Token usage</summary>\n <pre className=\"overflow-auto p-2\">{JSON.stringify(selected.usage, null, 2)}</pre>\n </details>\n {props.state.turns\n .filter((turn) => turn.instanceId === selected.instanceId)\n .map((turn) => (\n <div key={turn.key} className=\"space-y-3\">\n {turn.text && (\n <MarkdownText text={turn.text} live={props.state.status === \"running\"} />\n )}\n {turn.tools.length > 0 && (\n <details>\n <summary className=\"cursor-pointer text-xs text-muted-foreground\">\n Tool activity ({turn.tools.length})\n </summary>\n {turn.tools.map((tool, index) => (\n <pre\n key={index}\n className=\"my-2 max-h-60 overflow-auto whitespace-pre-wrap break-all rounded-lg bg-muted p-3 text-xs\"\n >\n {tool}\n </pre>\n ))}\n </details>\n )}\n {turn.messages && (\n <details>\n <summary className=\"cursor-pointer text-xs text-muted-foreground\">\n Run messages\n </summary>\n <pre className=\"max-h-96 overflow-auto whitespace-pre-wrap break-all text-xs\">\n {JSON.stringify(turn.messages, null, 2)}\n </pre>\n </details>\n )}\n </div>\n ))}\n </section>\n )}\n </div>\n );\n}\n\nexport function TeamMessages({ state }: { state: TeamState }) {\n const name = (id: string) => state.members[id]?.name ?? id;\n return (\n <section className=\"space-y-3\" aria-label=\"Messages between agents\">\n <h2 className=\"text-sm font-medium\">\n Messages <span className=\"text-muted-foreground\">{state.messages.length}</span>\n </h2>\n {!state.messages.length && (\n <p className=\"text-sm text-muted-foreground\">Messages between agents will appear here.</p>\n )}\n {state.messages.map(({ message, delivered }) => (\n <article key={message.id} className=\"space-y-2 rounded-lg border border-hair p-3\">\n <div className=\"text-xs font-medium\">\n {name(message.fromInstanceId)} → {name(message.toInstanceId)}\n </div>\n <p className=\"whitespace-pre-wrap break-words text-sm\">{message.content}</p>\n <p className=\"text-xs text-muted-foreground\">\n {delivered ? \"Delivered\" : \"Queued\"} ·{\" \"}\n {new Date(message.createdAt).toLocaleTimeString()}\n </p>\n </article>\n ))}\n </section>\n );\n}\n","import type { AgentTeamMemberSummary, AgentTeamMessage } from \"@anvia/core/agent\";\nimport type { AgentInteractionRequest } from \"@anvia/core/agent/interactions\";\nimport type { Message } from \"@anvia/core/completion\";\nimport type { StudioTeamRunEvent } from \"../../../../team-types\";\nimport { errorMessage } from \"../shared/format\";\n\nexport type TeamInteraction = {\n instanceId: string;\n request: AgentInteractionRequest;\n status: \"pending\" | \"answered\" | \"cancelled\";\n};\nexport type TeamTurn = {\n key: string;\n instanceId: string;\n coordinator: boolean;\n text: string;\n tools: string[];\n messages?: readonly Message[];\n};\nexport type TeamState = {\n status: \"idle\" | \"running\" | \"completed\" | \"blocked\" | \"cancelled\" | \"failed\";\n runId?: string;\n error?: string;\n members: Record<string, AgentTeamMemberSummary>;\n turns: TeamTurn[];\n messages: { message: AgentTeamMessage; delivered: boolean }[];\n interactions: Record<string, TeamInteraction>;\n conversation: ({ type: \"prompt\"; text: string } | { type: \"turn\"; key: string })[];\n};\nexport const initialTeamState: TeamState = {\n status: \"idle\",\n members: {},\n turns: [],\n messages: [],\n interactions: {},\n conversation: [],\n};\nexport type TeamAction =\n | { type: \"start\"; prompt: string }\n | { type: \"prompt\"; prompt: string }\n | { type: \"event\"; event: StudioTeamRunEvent }\n | { type: \"answered\"; id: string }\n | { type: \"stop\"; error?: string }\n | { type: \"reset\" };\n\nfunction closeInteractions(state: TeamState, instanceId?: string) {\n return Object.fromEntries(\n Object.entries(state.interactions).map(([id, item]) => [\n id,\n item.status === \"pending\" && (instanceId === undefined || item.instanceId === instanceId)\n ? { ...item, status: \"cancelled\" as const }\n : item,\n ]),\n );\n}\n\nexport function teamReducer(state: TeamState, action: TeamAction): TeamState {\n switch (action.type) {\n case \"reset\":\n return initialTeamState;\n case \"start\":\n return {\n ...initialTeamState,\n status: \"running\",\n conversation: [{ type: \"prompt\", text: action.prompt }],\n };\n case \"prompt\":\n return {\n ...state,\n conversation: [...state.conversation, { type: \"prompt\", text: action.prompt }],\n };\n case \"stop\":\n return {\n ...state,\n status: action.error ? \"failed\" : \"cancelled\",\n ...(action.error ? { error: action.error } : {}),\n interactions: closeInteractions(state),\n members: Object.fromEntries(\n Object.entries(state.members).map(([id, member]) => [\n id,\n [\"queued\", \"running\", \"waiting\", \"awaiting_interaction\"].includes(member.status)\n ? { ...member, status: \"cancelled\" }\n : member,\n ]),\n ),\n };\n case \"answered\": {\n const item = state.interactions[action.id];\n return item !== undefined\n ? {\n ...state,\n interactions: { ...state.interactions, [action.id]: { ...item, status: \"answered\" } },\n }\n : state;\n }\n case \"event\":\n break;\n }\n const event = action.event;\n if (event.type === \"team_run_started\") return { ...state, runId: event.runId };\n if (event.type === \"error\")\n return teamReducer(state, { type: \"stop\", error: errorMessage(event.error) });\n if (event.type === \"response\" || event.type === \"blocked\")\n return {\n ...state,\n status: event.type === \"response\" ? \"completed\" : \"blocked\",\n // Terminal outcomes contain descendants only; retain the coordinator as the tree root.\n members: {\n ...state.members,\n ...Object.fromEntries(event.members.map((member) => [member.instanceId, member])),\n },\n interactions: closeInteractions(state),\n };\n if (\"member\" in event)\n return {\n ...state,\n members: { ...state.members, [event.instanceId]: event.member },\n ...(event.type === \"agent_cancelled\" || event.type === \"agent_failed\"\n ? { interactions: closeInteractions(state, event.instanceId) }\n : {}),\n };\n if (event.type === \"interaction\")\n return {\n ...state,\n interactions: {\n ...state.interactions,\n [event.interaction.id]: {\n instanceId: event.instanceId,\n request: event.interaction,\n status: \"pending\",\n },\n },\n };\n if (event.type === \"message_queued\" || event.type === \"message_delivered\") {\n const previous = state.messages.find((item) => item.message.id === event.message.id);\n const item = {\n message: event.message,\n delivered: previous?.delivered === true || event.type === \"message_delivered\",\n };\n return {\n ...state,\n messages: previous\n ? state.messages.map((old) => (old.message.id === item.message.id ? item : old))\n : [...state.messages, item].slice(-500),\n };\n }\n if (event.type !== \"agent_event\") return state;\n const key = `${event.instanceId}:${event.runId ?? \"initial\"}`;\n const turn = state.turns.find((item) => item.key === key) ?? {\n key,\n instanceId: event.instanceId,\n coordinator: event.coordinator,\n text: \"\",\n tools: [],\n };\n const inner = event.event;\n let updated: TeamTurn;\n switch (inner.type) {\n case \"text_delta\":\n updated = { ...turn, text: turn.text + inner.delta };\n break;\n case \"tool_call\":\n updated = { ...turn, tools: [...turn.tools, JSON.stringify(inner.toolCall)].slice(-100) };\n break;\n case \"tool_result\":\n updated = {\n ...turn,\n tools: [...turn.tools, `${inner.toolName}: ${JSON.stringify(inner.output, null, 2)}`].slice(\n -100,\n ),\n };\n break;\n case \"response\":\n case \"blocked\":\n updated = {\n ...turn,\n text: inner.text,\n messages: inner.messages,\n tools: inner.messages\n .flatMap((message) => {\n if (typeof message.content === \"string\") return [];\n return message.content\n .filter((part) => part.type === \"tool-call\" || part.type === \"tool-result\")\n .map((part) => JSON.stringify(part, null, 2));\n })\n .slice(-100),\n };\n break;\n default:\n return state;\n }\n return {\n ...state,\n conversation:\n updated.coordinator && !state.turns.some((item) => item.key === key)\n ? [...state.conversation, { type: \"turn\" as const, key }].slice(-500)\n : state.conversation,\n turns: state.turns.some((item) => item.key === key)\n ? state.turns.map((item) => (item.key === key ? updated : item))\n : [...state.turns, updated].slice(-500),\n };\n}\n","import type { AgentInteractionResponse } from \"@anvia/core/agent/interactions\";\nimport { readJsonlStream } from \"@anvia/client/transport\";\nimport { useEffect, useReducer, useRef, useState } from \"react\";\nimport type { StudioTeamRunEvent } from \"../../../../team-types\";\nimport { responseErrorMessage } from \"../../app-errors\";\nimport { errorMessage } from \"../shared/format\";\nimport { requestJson } from \"../shared/request\";\nimport { initialTeamState, teamReducer } from \"./team-state\";\n\ntype ActiveTeamRun = {\n controller: AbortController;\n base: string;\n runId: string | undefined;\n pending: Set<string>;\n epoch: number;\n};\n\nfunction cancelTeamRun(run: ActiveTeamRun | undefined) {\n if (!run || run.controller.signal.aborted) return;\n if (run.runId) {\n // Keep server cancellation independent of stream teardown, including page navigation.\n void fetch(`${run.base}/${encodeURIComponent(run.runId)}/cancel`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: \"{}\",\n keepalive: true,\n signal: AbortSignal.timeout(5_000),\n }).catch(() => {\n // Teardown cannot wait for the server; disconnect remains the fallback on network failure.\n });\n }\n run.controller.abort();\n}\n\nexport function useTeamRun(teamId: string) {\n const [state, dispatch] = useReducer(teamReducer, initialTeamState);\n const [controlError, setControlError] = useState(\"\");\n const [busy, setBusy] = useState<ReadonlySet<string>>(new Set());\n const active = useRef<ActiveTeamRun | undefined>(undefined);\n const epoch = useRef(0);\n const base = `/teams/${encodeURIComponent(teamId)}/runs`;\n useEffect(\n () => () => {\n cancelTeamRun(active.current);\n active.current = undefined;\n epoch.current++;\n },\n [teamId],\n );\n\n async function start(prompt: string) {\n if (active.current) return;\n const run: ActiveTeamRun = {\n controller: new AbortController(),\n base,\n runId: undefined,\n pending: new Set(),\n epoch: ++epoch.current,\n };\n active.current = run;\n setBusy(new Set());\n setControlError(\"\");\n dispatch({ type: \"start\", prompt });\n try {\n const response = await fetch(base, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ prompt }),\n signal: run.controller.signal,\n });\n if (!response.ok) throw new Error(await responseErrorMessage(response, \"Start team\"));\n if (!response.body) throw new Error(\"Team response has no stream\");\n run.runId = response.headers.get(\"x-anvia-team-run-id\") ?? undefined;\n for await (const event of readJsonlStream<StudioTeamRunEvent>(response.body)) {\n if (active.current !== run || run.controller.signal.aborted) break;\n if (event.type === \"team_run_started\") run.runId = event.runId;\n const terminal =\n event.type === \"response\" || event.type === \"blocked\" || event.type === \"error\";\n // Finish before rendering the result; closing the response body may still be pending.\n if (terminal) active.current = undefined;\n dispatch({ type: \"event\", event });\n if (terminal) return;\n }\n if (!run.controller.signal.aborted)\n throw new Error(\"Team stream ended before a result arrived\");\n } catch (error) {\n if (active.current === run)\n dispatch({\n type: \"stop\",\n ...(run.controller.signal.aborted ? {} : { error: errorMessage(error) }),\n });\n } finally {\n if (active.current === run) active.current = undefined;\n }\n }\n\n async function control(key: string, path: string, body: unknown, onSuccess: () => void) {\n const run = active.current;\n if (!run?.runId || run.pending.has(key)) return false;\n run.pending.add(key);\n setBusy(new Set(run.pending));\n setControlError(\"\");\n try {\n await requestJson(\n `${base}/${encodeURIComponent(run.runId)}${path}`,\n \"Update team\",\n run.controller.signal,\n \"default\",\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n },\n );\n if (epoch.current === run.epoch && !run.controller.signal.aborted) onSuccess();\n return true;\n } catch (error) {\n if (active.current === run && !run.controller.signal.aborted)\n setControlError(errorMessage(error));\n return false;\n } finally {\n run.pending.delete(key);\n if (epoch.current === run.epoch) setBusy(new Set(run.pending));\n }\n }\n\n function stop() {\n if (!active.current) return;\n cancelTeamRun(active.current);\n dispatch({ type: \"stop\" });\n }\n return {\n state,\n busy,\n controlError,\n start,\n stop,\n reset: () => {\n if (!active.current) {\n epoch.current++;\n dispatch({ type: \"reset\" });\n setControlError(\"\");\n }\n },\n steer: (prompt: string) =>\n control(\"steer\", \"/steer\", { prompt }, () => dispatch({ type: \"prompt\", prompt })),\n respond: (id: string, response: AgentInteractionResponse) =>\n control(id, `/interactions/${encodeURIComponent(id)}`, response, () =>\n dispatch({ type: \"answered\", id }),\n ),\n };\n}\n","import { useEffect, useRef, useState, type ReactNode } from \"react\";\nimport type { StudioTeamConfig } from \"../../../../team-types\";\nimport { Button } from \"../../components/ui/button\";\nimport { Textarea } from \"../../components/ui/textarea\";\nimport { MarkdownText } from \"../shared/renderers\";\nimport { TeamInteractionCard } from \"./team-interactions\";\nimport { TeamMembers, TeamMessages } from \"./team-members\";\nimport { useTeamRun } from \"./use-team-run\";\n\nexport function TeamPlayground({\n team,\n targetSelector,\n}: {\n team: StudioTeamConfig;\n targetSelector: (running: boolean) => ReactNode;\n}) {\n const run = useTeamRun(team.id);\n const [prompt, setPrompt] = useState(\"\");\n const [selected, select] = useState(\"\");\n const [tab, setTab] = useState<\"members\" | \"messages\">(\"members\");\n const scrollRef = useRef<HTMLDivElement>(null);\n const stick = useRef(true);\n const running = run.state.status === \"running\";\n const started = run.state.status !== \"idle\";\n useEffect(() => {\n const element = scrollRef.current;\n if (element && stick.current) element.scrollTop = element.scrollHeight;\n }, [run.state]);\n async function send() {\n const value = prompt.trim();\n if (!value) return;\n if (running) {\n if (await run.steer(value)) setPrompt(\"\");\n } else {\n setPrompt(\"\");\n stick.current = true;\n void run.start(value);\n }\n }\n return (\n <div className=\"flex min-h-0 min-w-0 flex-col overflow-auto lg:overflow-hidden\">\n <div className=\"flex flex-wrap items-center justify-between gap-3 border-b border-hair px-5 py-3\">\n <div className=\"flex items-center gap-3\">{targetSelector(running)}</div>\n <div className=\"flex items-center gap-3\">\n <span role=\"status\" className=\"text-xs text-muted-foreground\">\n {run.state.status}\n </span>\n <Button\n variant=\"secondary\"\n size=\"sm\"\n disabled={running}\n onClick={() => {\n run.reset();\n setPrompt(\"\");\n select(\"\");\n }}\n >\n New task\n </Button>\n </div>\n </div>\n <div className=\"grid min-h-0 min-w-0 flex-1 grid-cols-1 lg:grid-cols-[minmax(0,1fr)_360px] xl:grid-cols-[minmax(0,1fr)_420px]\">\n <div className=\"flex min-h-[480px] min-w-0 flex-col lg:min-h-0\">\n <div\n ref={scrollRef}\n className=\"min-h-0 flex-1 overflow-auto px-5 py-6\"\n onScroll={() => {\n const element = scrollRef.current;\n if (element)\n stick.current =\n element.scrollHeight - element.scrollTop - element.clientHeight < 80;\n }}\n >\n <div className=\"mx-auto max-w-3xl space-y-6\">\n {!started && (\n <div className=\"py-16\">\n <h1 className=\"text-2xl font-medium\">Work with {team.id}</h1>\n <p className=\"mt-3 text-sm text-muted-foreground\">\n Give the coordinator a task. Follow its agents, messages, and requests as they\n work.\n </p>\n <p className=\"mt-4 text-xs text-muted-foreground\">\n Available members:{\" \"}\n {team.members.map((member) => member.name ?? member.id).join(\", \") || \"None\"}\n </p>\n </div>\n )}\n {run.state.conversation.map((entry, index) => {\n if (entry.type === \"prompt\")\n return (\n <article key={`prompt:${index}`} className=\"rounded-xl bg-muted p-4\">\n <div className=\"mb-2 text-xs text-muted-foreground\">You</div>\n <p className=\"whitespace-pre-wrap break-words text-sm\">{entry.text}</p>\n </article>\n );\n const turn = run.state.turns.find((item) => item.key === entry.key);\n return turn?.text ? (\n <article key={entry.key}>\n <div className=\"mb-2 text-xs text-muted-foreground\">Coordinator</div>\n <MarkdownText text={turn.text} live={running} size=\"base\" />\n </article>\n ) : null;\n })}\n {Object.values(run.state.interactions).map((item) => (\n <TeamInteractionCard\n key={item.request.id}\n item={item}\n name={run.state.members[item.instanceId]?.name ?? item.instanceId}\n busy={run.busy.has(item.request.id)}\n respond={run.respond}\n />\n ))}\n {run.state.error && (\n <p role=\"alert\" className=\"text-sm text-status-danger-ink\">\n {run.state.error}\n </p>\n )}\n {run.controlError && (\n <p role=\"alert\" className=\"text-sm text-status-danger-ink\">\n {run.controlError}\n </p>\n )}\n </div>\n </div>\n <form\n className=\"mx-auto w-full max-w-3xl space-y-3 px-5 pb-5 pt-3\"\n onSubmit={(event) => {\n event.preventDefault();\n void send();\n }}\n >\n <Textarea\n aria-label={running ? \"Message coordinator\" : \"Team task\"}\n placeholder={\n running ? \"Send a follow-up to the coordinator…\" : \"Give this team a task…\"\n }\n value={prompt}\n maxLength={32768}\n onChange={(event) => setPrompt(event.target.value)}\n disabled={started && !running}\n onKeyDown={(event) => {\n if (event.key === \"Enter\" && !event.shiftKey && !event.nativeEvent.isComposing) {\n event.preventDefault();\n if ((!started || running) && !run.busy.has(\"steer\")) void send();\n }\n }}\n />\n <div className=\"flex items-center justify-between gap-2\">\n <p className=\"text-xs text-muted-foreground\">\n This run stays in this page. Leaving stops active work.\n </p>\n {running && (\n <Button type=\"button\" variant=\"secondary\" size=\"sm\" onClick={run.stop}>\n Stop team\n </Button>\n )}\n <Button\n size=\"sm\"\n disabled={\n !prompt.trim() ||\n (started && !running) ||\n (running && (!run.state.runId || run.busy.has(\"steer\")))\n }\n >\n {running ? \"Send follow-up\" : \"Run team\"}\n </Button>\n </div>\n </form>\n </div>\n <aside\n className=\"min-h-64 min-w-0 space-y-5 overflow-auto border-t border-hair p-5 lg:border-t-0 lg:border-l\"\n aria-label=\"Team activity\"\n >\n <div className=\"flex gap-2\">\n <Button\n variant={tab === \"members\" ? \"secondary\" : \"ghost\"}\n size=\"sm\"\n onClick={() => setTab(\"members\")}\n >\n Members\n </Button>\n <Button\n variant={tab === \"messages\" ? \"secondary\" : \"ghost\"}\n size=\"sm\"\n onClick={() => setTab(\"messages\")}\n >\n Messages\n </Button>\n </div>\n {tab === \"members\" ? (\n <TeamMembers state={run.state} selected={selected} select={select} />\n ) : (\n <TeamMessages state={run.state} />\n )}\n </aside>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{n as e,r as t}from"./dist-CHLp-Np4.js";var n=t();function r({className:t,...r}){return(0,n.jsx)(`textarea`,{className:e(`min-h-16 w-full resize-none rounded-lg border border-input bg-transparent px-2.5 py-2 text-base leading-6 text-foreground outline-none transition-colors placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring disabled:cursor-not-allowed disabled:bg-muted disabled:opacity-50 dark:bg-transparent dark:disabled:bg-muted`,t),...r})}export{r as t};
2
+ //# sourceMappingURL=textarea-gPj9-ALc.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"textarea-fAtCF2cf.js","names":[],"sources":["../../../src/ui/app/components/ui/textarea.tsx"],"sourcesContent":["import type * as React from \"react\";\nimport { cn } from \"@/lib/utils\";\n\nexport function Textarea({ className, ...props }: React.ComponentProps<\"textarea\">) {\n return (\n <textarea\n className={cn(\n \"min-h-16 w-full resize-none rounded-lg border border-input bg-transparent px-2.5 py-2 text-base leading-6 text-foreground outline-none transition-colors placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring disabled:cursor-not-allowed disabled:bg-muted disabled:opacity-50 dark:bg-transparent dark:disabled:bg-muted\",\n className,\n )}\n {...props}\n />\n );\n}\n"],"mappings":"oDAGA,SAAgB,EAAS,CAAE,YAAW,GAAG,GAA2C,CAClF,OACE,EAAA,EAAA,IAAA,CAAC,WAAD,CACE,UAAW,EACT,iXACA,CACF,EACA,GAAI,CACL,CAAA,CAEL"}
1
+ {"version":3,"file":"textarea-gPj9-ALc.js","names":[],"sources":["../../../src/ui/app/components/ui/textarea.tsx"],"sourcesContent":["import type * as React from \"react\";\nimport { cn } from \"@/lib/utils\";\n\nexport function Textarea({ className, ...props }: React.ComponentProps<\"textarea\">) {\n return (\n <textarea\n className={cn(\n \"min-h-16 w-full resize-none rounded-lg border border-input bg-transparent px-2.5 py-2 text-base leading-6 text-foreground outline-none transition-colors placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring disabled:cursor-not-allowed disabled:bg-muted disabled:opacity-50 dark:bg-transparent dark:disabled:bg-muted\",\n className,\n )}\n {...props}\n />\n );\n}\n"],"mappings":"wDAGA,SAAgB,EAAS,CAAE,YAAW,GAAG,GAA2C,CAClF,OACE,EAAA,EAAA,IAAA,CAAC,WAAD,CACE,UAAW,EACT,iXACA,CACF,EACA,GAAI,CACL,CAAA,CAEL"}
@@ -0,0 +1,2 @@
1
+ import{i as e,r as t,s as n}from"./dist-CHLp-Np4.js";import{h as r,t as i,v as a}from"./button-BWxpVW85.js";import{a as o,i as s,n as c,r as l,t as u}from"./select-C4MbvpHr.js";import{t as d}from"./textarea-gPj9-ALc.js";import{t as f}from"./badge-DUs0RCHV.js";import{t as ee}from"./renderers-CrjMPAR2.js";import{t as p}from"./input-DdUxz9c8.js";var m=n(e(),1),h=t();function g(e){let[t,n]=(0,m.useState)(`form`),r=(0,m.useMemo)(()=>T(e.schema),[e.schema]),i=(0,m.useMemo)(()=>F(e.value),[e.value]),o=e.disabled===!0,s=r.length>0,c=s?t:`json`,l=i.ok&&a(i.value)?i.value:void 0;function u(t,n){let r=l??{};e.onChange(z(P(r,t,n)))}function d(t,n){let r=l??{},i=N(r,t);Array.isArray(i)&&e.onChange(z(P(r,t,i.filter((e,t)=>t!==n))))}return(0,h.jsxs)(`div`,{className:`grid min-w-0 gap-3`,children:[(0,h.jsxs)(`div`,{className:`flex min-w-0 items-center justify-between gap-3`,children:[(0,h.jsx)(`span`,{className:`text-xs font-semibold uppercase tracking-[0.16em] text-muted-foreground`,children:`Arguments`}),s?(0,h.jsxs)(`div`,{className:`inline-grid h-8 grid-cols-2 overflow-hidden rounded-md border border-hair bg-background p-0.5`,children:[(0,h.jsx)(_,{active:c===`form`,onClick:()=>n(`form`),children:`Form`}),(0,h.jsx)(_,{active:c===`json`,onClick:()=>n(`json`),children:`JSON`})]}):(0,h.jsx)(`span`,{className:`text-xs font-medium text-muted-foreground`,children:`JSON`})]}),c===`json`||l===void 0?(0,h.jsx)(v,{disabled:o,error:i.ok?``:i.error,value:e.value,onChange:e.onChange}):(0,h.jsx)(`div`,{className:`grid gap-3`,children:r.map(e=>(0,h.jsx)(y,{disabled:o,field:e,path:[e.name],rootValue:l,onChange:u,onRemoveArrayItem:d},e.name))})]})}function _(e){return(0,h.jsx)(`button`,{className:e.active?`rounded-[5px] bg-muted px-3 text-xs font-semibold text-foreground`:`rounded-[5px] px-3 text-xs font-medium text-muted-foreground transition hover:text-foreground`,type:`button`,onClick:e.onClick,children:e.children})}function v(e){return(0,h.jsxs)(`div`,{className:`grid gap-2`,children:[(0,h.jsx)(d,{className:`min-h-36 resize-y rounded-md border-border bg-background p-3 text-xs leading-5`,disabled:e.disabled,value:e.value,spellCheck:!1,onChange:t=>e.onChange(t.target.value)}),e.error.length===0?null:(0,h.jsx)(`div`,{className:`rounded-md border border-status-danger-ink bg-status-danger-fill px-3 py-2 text-xs leading-5 text-destructive`,children:e.error})]})}function y(e){let t=N(e.rootValue,e.path),n=k(e.field.schema,e.field.name),r=A(e.field.schema),i=E(e.field.schema);if(i===`object`){let i=T(e.field.schema);return(0,h.jsxs)(`fieldset`,{className:`grid min-w-0 gap-3 border-b border-hair pb-3 last:border-b-0`,children:[(0,h.jsxs)(`div`,{className:`flex min-w-0 items-center justify-between gap-3`,children:[(0,h.jsx)(`legend`,{className:`min-w-0 truncate text-sm font-semibold text-foreground`,children:n}),e.field.required?(0,h.jsx)(S,{}):null]}),r===void 0?null:(0,h.jsx)(`p`,{className:`m-0 text-xs leading-5 text-muted-foreground`,children:r}),i.length===0?(0,h.jsx)(w,{disabled:e.disabled,path:e.path,value:t,onChange:e.onChange}):(0,h.jsx)(`div`,{className:`grid gap-3 border-l border-hair pl-3`,children:i.map(t=>(0,h.jsx)(y,{disabled:e.disabled,field:t,path:[...e.path,t.name],rootValue:e.rootValue,onChange:e.onChange,onRemoveArrayItem:e.onRemoveArrayItem},t.name))})]})}return i===`array`?(0,h.jsx)(b,{description:r,disabled:e.disabled,field:e.field,label:n,path:e.path,rootValue:e.rootValue,value:t,onChange:e.onChange,onRemoveArrayItem:e.onRemoveArrayItem}):(0,h.jsxs)(`div`,{className:`grid min-w-0 gap-2 border-b border-hair pb-3 last:border-b-0`,children:[(0,h.jsx)(x,{label:n,required:e.field.required}),r===void 0?null:(0,h.jsx)(`p`,{className:`m-0 text-xs leading-5 text-muted-foreground`,children:r}),(0,h.jsx)(te,{disabled:e.disabled,path:e.path,required:e.field.required,schema:e.field.schema,value:t,onChange:e.onChange})]})}function b(e){let t=D(e.field.schema),n=Array.isArray(e.value)?e.value:[],r=n.map((t,n)=>({index:n,key:`${H(e.path)}:${n}:${V(t)}`}));return(0,h.jsxs)(`div`,{className:`grid min-w-0 gap-3 border-b border-hair pb-3 last:border-b-0`,children:[(0,h.jsxs)(`div`,{className:`flex min-w-0 items-center justify-between gap-3`,children:[(0,h.jsx)(x,{label:e.label,required:e.field.required}),t===void 0?null:(0,h.jsx)(i,{className:`h-8 min-h-8 rounded-md px-3 text-xs`,disabled:e.disabled,type:`button`,variant:`secondary`,onClick:()=>e.onChange(e.path,[...n,M(t)]),children:`Add`})]}),e.description===void 0?null:(0,h.jsx)(`p`,{className:`m-0 text-xs leading-5 text-muted-foreground`,children:e.description}),t===void 0?(0,h.jsx)(w,{disabled:e.disabled,path:e.path,value:e.value,onChange:e.onChange}):n.length===0?(0,h.jsx)(`div`,{className:`rounded-md border border-dashed border-hair px-3 py-2 text-xs text-muted-foreground`,children:`Empty array`}):(0,h.jsx)(`div`,{className:`grid gap-3 border-l border-hair pl-3`,children:r.map(n=>(0,h.jsxs)(`div`,{className:`grid gap-2`,children:[(0,h.jsxs)(`div`,{className:`flex items-center justify-between gap-3`,children:[(0,h.jsxs)(`span`,{className:`text-xs font-medium text-muted-foreground`,children:[`Item `,n.index+1]}),(0,h.jsx)(i,{className:`h-7 min-h-7 rounded-md px-2 text-xs`,disabled:e.disabled,type:`button`,variant:`ghost`,onClick:()=>e.onRemoveArrayItem(e.path,n.index),children:`Remove`})]}),(0,h.jsx)(y,{disabled:e.disabled,field:{name:String(n.index+1),required:!0,schema:t},path:[...e.path,n.index],rootValue:e.rootValue,onChange:e.onChange,onRemoveArrayItem:e.onRemoveArrayItem})]},n.key))})]})}function x(e){return(0,h.jsxs)(`div`,{className:`flex min-w-0 items-center gap-2`,children:[(0,h.jsx)(`span`,{className:`min-w-0 truncate text-sm font-semibold text-foreground`,children:e.label}),e.required?(0,h.jsx)(S,{}):null]})}function S(){return(0,h.jsx)(`span`,{className:`rounded-md bg-muted px-2 py-0.5 text-[11px] font-medium text-muted-foreground`,children:`required`})}function te(e){let t=O(e.schema);if(t.length>0){let n=t.findIndex(t=>B(t,e.value)),r=t.map((e,t)=>({label:V(e),value:String(t),key:`${t}:${V(e)}`}));return(0,h.jsxs)(`div`,{className:`flex min-w-0 items-center gap-2`,children:[(0,h.jsxs)(u,{value:n===-1?``:String(n),disabled:e.disabled,onValueChange:n=>e.onChange(e.path,t[Number(n)]),children:[(0,h.jsx)(s,{className:`h-9 min-h-9 rounded-md border-border bg-background text-sm`,children:(0,h.jsx)(o,{placeholder:`Select value`})}),(0,h.jsx)(c,{children:r.map(e=>(0,h.jsx)(l,{value:e.value,children:e.label},e.key))})]}),n===-1||e.required?null:(0,h.jsx)(i,{className:`h-9 min-h-9 rounded-md px-3 text-xs`,disabled:e.disabled,type:`button`,variant:`ghost`,onClick:()=>e.onChange(e.path,void 0),children:`Clear`})]})}let n=E(e.schema);return n===`boolean`?(0,h.jsxs)(`label`,{className:`flex min-h-9 w-fit cursor-pointer items-center gap-2 rounded-md border border-hair bg-background px-3 text-sm text-foreground`,children:[(0,h.jsx)(`input`,{checked:e.value===!0,disabled:e.disabled,type:`checkbox`,className:`h-4 w-4 accent-foreground`,onChange:t=>e.onChange(e.path,t.target.checked)}),`Enabled`]}):n===`number`||n===`integer`?(0,h.jsx)(C,{disabled:e.disabled,path:e.path,schema:e.schema,type:n,value:e.value,onChange:e.onChange}):n===`string`?(0,h.jsx)(p,{className:`h-9 rounded-md border-border bg-background text-sm`,disabled:e.disabled,type:`text`,value:typeof e.value==`string`?e.value:``,placeholder:j(e.schema),onChange:t=>{let n=t.target.value;e.onChange(e.path,n.length===0&&!e.required?void 0:n)}}):(0,h.jsx)(w,{disabled:e.disabled,path:e.path,value:e.value,onChange:e.onChange})}function C(e){let t=typeof e.value==`number`?String(e.value):``,[n,r]=(0,m.useState)(t);return(0,m.useEffect)(()=>{r(t)},[t]),(0,h.jsx)(p,{className:`h-9 rounded-md border-border bg-background text-sm`,disabled:e.disabled,inputMode:e.type===`integer`?`numeric`:`decimal`,type:`text`,value:n,placeholder:j(e.schema),onBlur:()=>{if(n.trim().length===0){r(``);return}let i=I(n,e.type);r(i.ok?String(i.value):t)},onChange:t=>{let n=t.target.value;if(r(n),n.trim().length===0){e.onChange(e.path,void 0);return}let i=I(n,e.type);i.ok&&e.onChange(e.path,i.value)}})}function w(e){let t=(0,m.useMemo)(()=>R(e.value),[e.value]),[n,r]=(0,m.useState)(t),i=(0,m.useMemo)(()=>F(n),[n]);return(0,m.useEffect)(()=>{r(t)},[t]),(0,h.jsxs)(`div`,{className:`grid gap-2`,children:[(0,h.jsx)(d,{className:`min-h-24 resize-y rounded-md border-border bg-background p-3 text-xs leading-5`,disabled:e.disabled,value:n,spellCheck:!1,onChange:t=>{let n=t.target.value;if(r(n),n.trim().length===0){e.onChange(e.path,void 0);return}let i=F(n);i.ok&&e.onChange(e.path,i.value)}}),i.ok||n.trim().length===0?null:(0,h.jsx)(`div`,{className:`rounded-md border border-status-danger-ink bg-status-danger-fill px-3 py-2 text-xs leading-5 text-destructive`,children:i.error})]})}function T(e){if(!a(e))return[];let t=e.properties;if(!a(t))return[];let n=ne(e);return Object.entries(t).map(([e,t])=>({name:e,required:n.has(e),schema:a(t)?t:{}}))}function ne(e){let t=e.required;return Array.isArray(t)?new Set(t.filter(e=>typeof e==`string`)):new Set}function E(e){let t=e.type;if(typeof t==`string`)return t;if(Array.isArray(t)){let e=t.find(e=>typeof e==`string`&&e!==`null`);if(e!==void 0)return e}return O(e).length>0?`enum`:a(e.properties)?`object`:e.items===void 0?`unknown`:`array`}function D(e){return a(e.items)?e.items:void 0}function O(e){return Array.isArray(e.enum)?e.enum:[]}function k(e,t){return typeof e.title==`string`&&e.title.length>0?e.title:U(t)}function A(e){return typeof e.description==`string`&&e.description.length>0?e.description:void 0}function j(e){return Object.hasOwn(e,`default`)?V(e.default):void 0}function M(e){if(Object.hasOwn(e,`default`))return e.default;let t=O(e);if(t.length>0)return t[0];let n=E(e);return n===`boolean`?!1:n===`integer`||n===`number`?0:n===`array`?[]:n===`object`?{}:n===`string`?``:null}function N(e,t){let n=e;for(let e of t){if(typeof e==`number`){if(!Array.isArray(n))return;n=n[e];continue}if(!a(n))return;n=n[e]}return n}function P(e,t,n){if(t.length===0)return n;let[r,...i]=t,o=Array.isArray(e)?[...e]:a(e)?{...e}:{};if(i.length===0)return n===void 0?(Array.isArray(o)&&typeof r==`number`?o.splice(r,1):!Array.isArray(o)&&typeof r==`string`&&delete o[r],o):((Array.isArray(o)&&typeof r==`number`||!Array.isArray(o)&&typeof r==`string`)&&(o[r]=n),o);let s=P(Array.isArray(o)&&typeof r==`number`||!Array.isArray(o)&&typeof r==`string`?o[r]:void 0,i,n);return(Array.isArray(o)&&typeof r==`number`||!Array.isArray(o)&&typeof r==`string`)&&(o[r]=s),o}function F(e){if(e.trim().length===0)return{ok:!0,value:void 0};try{return{ok:!0,value:JSON.parse(e)}}catch(e){return{ok:!1,error:e instanceof Error?e.message:String(e)}}}function I(e,t){let n=e.trim();if(n.length===0||L(n))return{ok:!1};let r=Number(n);return!Number.isFinite(r)||t===`integer`&&!Number.isInteger(r)?{ok:!1}:{ok:!0,value:r}}function L(e){return e===`-`||e===`+`||e===`.`||e===`-.`||e===`+.`||/^[+-]?\d+\.$/.test(e)||/[eE][+-]?$/.test(e)}function R(e){return e===void 0?``:z(e)}function z(e){return JSON.stringify(e,null,2)}function B(e,t){return JSON.stringify(e)===JSON.stringify(t)}function V(e){return typeof e==`string`?e:typeof e==`number`||typeof e==`boolean`?String(e):e===null?`null`:JSON.stringify(e)}function H(e){return e.join(`.`)}function U(e){return e.replace(/[_-]+/g,` `).replace(/([a-z])([A-Z])/g,`$1 $2`).replace(/\b\w/g,e=>e.toUpperCase())}function W(e){let t=e.selectedTool===void 0?0:$(e.selectedTool.parameters);return(0,h.jsxs)(`section`,{className:`grid gap-4 border-t border-hair pt-4 xl:grid-cols-[minmax(260px,0.42fr)_minmax(0,1fr)]`,children:[(0,h.jsxs)(`div`,{className:`grid content-start gap-3`,children:[(0,h.jsxs)(`div`,{className:`grid gap-1.5`,children:[(0,h.jsx)(`h2`,{className:`m-0 text-base font-semibold text-foreground`,children:`Runner`}),e.selectedTool===void 0?(0,h.jsx)(`p`,{className:`m-0 text-sm leading-6 text-muted-foreground`,children:`No tool selected`}):(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(`p`,{className:`m-0 break-all text-sm font-semibold leading-6 text-foreground`,children:e.selectedTool.name}),(0,h.jsx)(`p`,{className:`m-0 max-w-[62ch] text-sm leading-6 text-muted-foreground`,children:e.selectedTool.description})]})]}),e.selectedTool===void 0?null:(0,h.jsxs)(`div`,{className:`flex min-w-0 flex-wrap gap-2`,children:[(0,h.jsx)(f,{className:X(e.selectedTool),children:Z(e.selectedTool)}),(0,h.jsxs)(f,{className:J(e.selectedTool.approval.required),children:[`approval `,e.selectedTool.approval.required?`required`:`none`]}),(0,h.jsxs)(q,{children:[t,` `,t===1?`field`:`fields`]})]}),e.selectedTool?.approval.reason===void 0?null:(0,h.jsx)(`p`,{className:`m-0 border-l border-hair pl-3 text-xs leading-5 text-muted-foreground`,children:e.selectedTool.approval.reason})]}),(0,h.jsxs)(`div`,{className:`grid min-w-0 gap-3`,children:[(0,h.jsx)(g,{disabled:e.selectedTool===void 0,schema:e.selectedTool?.parameters,value:e.argsText,onChange:e.onArgsTextChange}),(0,h.jsxs)(`div`,{className:`flex min-w-0 items-center justify-between gap-3`,children:[(0,h.jsx)(`span`,{className:`min-w-0 truncate text-xs text-muted-foreground`,children:`Arguments must be valid JSON.`}),(0,h.jsx)(i,{className:`h-8 min-h-8 rounded-md px-4 text-xs`,type:`button`,disabled:e.runState===`running`||e.selectedTool===void 0,onClick:e.onRun,children:e.runState===`running`?`Running`:`Run`})]}),e.runError.length>0?(0,h.jsx)(`div`,{className:`rounded-md border border-status-danger-ink bg-status-danger-fill px-3 py-2 text-xs leading-5 text-destructive`,children:e.runError}):null,e.selectedTool===void 0?null:(0,h.jsxs)(`details`,{className:`group border-t border-hair pt-3`,children:[(0,h.jsxs)(`summary`,{className:`flex cursor-pointer list-none items-center justify-between gap-3 text-xs font-semibold uppercase tracking-[0.16em] text-muted-foreground marker:hidden`,children:[`Parameter schema`,(0,h.jsx)(`span`,{className:`font-medium normal-case tracking-normal`,children:Q(e.selectedTool.parameters)})]}),(0,h.jsx)(`div`,{className:`mt-3`,children:(0,h.jsx)(K,{value:e.selectedTool.parameters,title:`JSON schema`})})]}),e.runResponse===void 0?null:(0,h.jsx)(G,{response:e.runResponse})]})]})}function G(e){let t=Object.hasOwn(e.response,`result`),n=t?e.response.result:e.response.error,r=t?`Tool result`:`Tool error`;return(0,h.jsxs)(`div`,{className:`grid gap-3`,children:[(0,h.jsx)(K,{value:ae(n),title:r}),(0,h.jsxs)(`details`,{className:`group border-t border-hair pt-3`,children:[(0,h.jsxs)(`summary`,{className:`flex cursor-pointer list-none items-center justify-between gap-3 text-xs font-semibold uppercase tracking-[0.16em] text-muted-foreground marker:hidden`,children:[`Raw run response`,(0,h.jsxs)(`span`,{className:`font-medium normal-case tracking-normal`,children:[e.response.status,` / `,e.response.durationMs,`ms`]})]}),(0,h.jsx)(`div`,{className:`mt-3`,children:(0,h.jsx)(K,{value:e.response,title:`Studio envelope`})})]})]})}function K(e){return(0,h.jsxs)(`section`,{className:`grid min-w-0 content-start overflow-hidden rounded-lg bg-background`,children:[(0,h.jsxs)(`div`,{className:`flex min-h-9 items-center justify-between gap-3 bg-muted px-4`,children:[(0,h.jsx)(`span`,{className:` text-xs font-semibold uppercase tracking-[0.2em] text-muted-foreground`,children:e.title}),(0,h.jsx)(`span`,{className:` text-xs text-muted-foreground`,children:Q(e.value)})]}),(0,h.jsx)(`div`,{className:`min-w-0 overflow-x-auto`,children:(0,h.jsx)(`pre`,{className:`m-0 max-h-96 min-w-max p-4 text-xs leading-5 text-foreground`,children:(0,h.jsx)(`code`,{children:(0,h.jsx)(ee,{text:oe(e.value)})})})})]})}function q(e){return(0,h.jsx)(`span`,{className:`inline-flex min-h-7 items-center rounded-md bg-muted px-2.5 text-xs font-medium text-muted-foreground`,children:e.children})}function J(e){return e?`border-hair bg-muted text-foreground`:`border-transparent bg-transparent text-dim`}function Y(e){return e===`dynamic`?`border-hair bg-muted text-foreground`:`border-hair bg-muted text-muted-foreground`}function X(e){return e.mcpServerName===void 0?Y(e.source):`border-hair bg-muted text-foreground`}function Z(e){return e.mcpServerName===void 0?e.source:`MCP / ${e.mcpServerName}`}function Q(e){if(typeof e!=`object`||!e||Array.isArray(e))return`value`;let t=e.type;return typeof t==`string`?t:`object`}function $(e){if(typeof e!=`object`||!e||Array.isArray(e))return 0;let t=e.properties;return typeof t==`object`&&t&&!Array.isArray(t)?Object.keys(t).length:0}function re(e){try{return JSON.stringify(e,null,2)}catch{return String(e)}}function ie(e){if(a(e)&&typeof e.agentId==`string`&&e.agentId.length!==0&&typeof e.toolName==`string`&&e.toolName.length!==0&&(e.status===`success`||e.status===`error`)&&!(typeof e.durationMs!=`number`||!Number.isFinite(e.durationMs))&&typeof e.startedAt==`string`&&typeof e.endedAt==`string`&&Array.isArray(e.events))return e}function ae(e){if(typeof e!=`string`)return e;let t=r(e);return t.kind===`json`?t.value:e}function oe(e){try{return JSON.stringify(e,null,2)}catch{return String(e)}}export{re as a,$ as c,Z as d,J as i,Q as l,q as n,X as o,W as r,ie as s,K as t,Y as u};
2
+ //# sourceMappingURL=tool-runner-xLspgGPa.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tool-runner-CExWna8k.js","names":[],"sources":["../../../src/ui/app/modules/tools/schema-argument-editor.tsx","../../../src/ui/app/modules/tools/tool-runner.tsx"],"sourcesContent":["import { useEffect, useMemo, useState } from \"react\";\nimport { Button } from \"../../components/ui/button\";\nimport { Input } from \"../../components/ui/input\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"../../components/ui/select\";\nimport { Textarea } from \"../../components/ui/textarea\";\nimport { isRecord } from \"../shared/object\";\n\ntype ArgumentMode = \"form\" | \"json\";\ntype JsonPath = Array<string | number>;\ntype ParseResult = { ok: true; value: unknown } | { ok: false; error: string };\n\nexport function SchemaArgumentEditor(props: {\n schema: unknown;\n value: string;\n disabled?: boolean;\n onChange: (value: string) => void;\n}) {\n const [mode, setMode] = useState<ArgumentMode>(\"form\");\n const rootFields = useMemo(() => schemaFields(props.schema), [props.schema]);\n const parsed = useMemo(() => parseJson(props.value), [props.value]);\n const disabled = props.disabled === true;\n const canRenderForm = rootFields.length > 0;\n const effectiveMode = canRenderForm ? mode : \"json\";\n const rootValue = parsed.ok && isRecord(parsed.value) ? parsed.value : undefined;\n\n function updatePath(path: JsonPath, value: unknown | undefined) {\n const base = rootValue ?? {};\n props.onChange(formatEditorJson(setValueAtPath(base, path, value)));\n }\n\n function removePathItem(path: JsonPath, index: number) {\n const base = rootValue ?? {};\n const arrayValue = getValueAtPath(base, path);\n if (!Array.isArray(arrayValue)) {\n return;\n }\n props.onChange(\n formatEditorJson(\n setValueAtPath(\n base,\n path,\n arrayValue.filter((_, itemIndex) => itemIndex !== index),\n ),\n ),\n );\n }\n\n return (\n <div className=\"grid min-w-0 gap-3\">\n <div className=\"flex min-w-0 items-center justify-between gap-3\">\n <span className=\"text-xs font-semibold uppercase tracking-[0.16em] text-muted-foreground\">\n Arguments\n </span>\n {canRenderForm ? (\n <div className=\"inline-grid h-8 grid-cols-2 overflow-hidden rounded-md border border-hair bg-background p-0.5\">\n <ModeButton active={effectiveMode === \"form\"} onClick={() => setMode(\"form\")}>\n Form\n </ModeButton>\n <ModeButton active={effectiveMode === \"json\"} onClick={() => setMode(\"json\")}>\n JSON\n </ModeButton>\n </div>\n ) : (\n <span className=\"text-xs font-medium text-muted-foreground\">JSON</span>\n )}\n </div>\n\n {effectiveMode === \"json\" || rootValue === undefined ? (\n <RawJsonEditor\n disabled={disabled}\n error={parsed.ok ? \"\" : parsed.error}\n value={props.value}\n onChange={props.onChange}\n />\n ) : (\n <div className=\"grid gap-3\">\n {rootFields.map((field) => (\n <SchemaField\n disabled={disabled}\n field={field}\n key={field.name}\n path={[field.name]}\n rootValue={rootValue}\n onChange={updatePath}\n onRemoveArrayItem={removePathItem}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\nfunction ModeButton(props: { active: boolean; children: string; onClick: () => void }) {\n return (\n <button\n className={\n props.active\n ? \"rounded-[5px] bg-muted px-3 text-xs font-semibold text-foreground\"\n : \"rounded-[5px] px-3 text-xs font-medium text-muted-foreground transition hover:text-foreground\"\n }\n type=\"button\"\n onClick={props.onClick}\n >\n {props.children}\n </button>\n );\n}\n\nfunction RawJsonEditor(props: {\n value: string;\n error: string;\n disabled: boolean;\n onChange: (value: string) => void;\n}) {\n return (\n <div className=\"grid gap-2\">\n <Textarea\n className=\"min-h-36 resize-y rounded-md border-border bg-background p-3 text-xs leading-5\"\n disabled={props.disabled}\n value={props.value}\n spellCheck={false}\n onChange={(event) => props.onChange(event.target.value)}\n />\n {props.error.length === 0 ? null : (\n <div className=\"rounded-md border border-status-danger-ink bg-status-danger-fill px-3 py-2 text-xs leading-5 text-destructive\">\n {props.error}\n </div>\n )}\n </div>\n );\n}\n\ntype SchemaFieldDefinition = {\n name: string;\n schema: Record<string, unknown>;\n required: boolean;\n};\n\nfunction SchemaField(props: {\n field: SchemaFieldDefinition;\n path: JsonPath;\n rootValue: Record<string, unknown>;\n disabled: boolean;\n onChange: (path: JsonPath, value: unknown | undefined) => void;\n onRemoveArrayItem: (path: JsonPath, index: number) => void;\n}) {\n const value = getValueAtPath(props.rootValue, props.path);\n const label = schemaLabel(props.field.schema, props.field.name);\n const description = schemaDescription(props.field.schema);\n const type = schemaPrimaryType(props.field.schema);\n\n if (type === \"object\") {\n const fields = schemaFields(props.field.schema);\n return (\n <fieldset className=\"grid min-w-0 gap-3 border-b border-hair pb-3 last:border-b-0\">\n <div className=\"flex min-w-0 items-center justify-between gap-3\">\n <legend className=\"min-w-0 truncate text-sm font-semibold text-foreground\">\n {label}\n </legend>\n {props.field.required ? <RequiredBadge /> : null}\n </div>\n {description === undefined ? null : (\n <p className=\"m-0 text-xs leading-5 text-muted-foreground\">{description}</p>\n )}\n {fields.length === 0 ? (\n <JsonValueField\n disabled={props.disabled}\n path={props.path}\n value={value}\n onChange={props.onChange}\n />\n ) : (\n <div className=\"grid gap-3 border-l border-hair pl-3\">\n {fields.map((field) => (\n <SchemaField\n disabled={props.disabled}\n field={field}\n key={field.name}\n path={[...props.path, field.name]}\n rootValue={props.rootValue}\n onChange={props.onChange}\n onRemoveArrayItem={props.onRemoveArrayItem}\n />\n ))}\n </div>\n )}\n </fieldset>\n );\n }\n\n if (type === \"array\") {\n return (\n <ArrayField\n description={description}\n disabled={props.disabled}\n field={props.field}\n label={label}\n path={props.path}\n rootValue={props.rootValue}\n value={value}\n onChange={props.onChange}\n onRemoveArrayItem={props.onRemoveArrayItem}\n />\n );\n }\n\n return (\n <div className=\"grid min-w-0 gap-2 border-b border-hair pb-3 last:border-b-0\">\n <FieldHeader label={label} required={props.field.required} />\n {description === undefined ? null : (\n <p className=\"m-0 text-xs leading-5 text-muted-foreground\">{description}</p>\n )}\n <ScalarFieldControl\n disabled={props.disabled}\n path={props.path}\n required={props.field.required}\n schema={props.field.schema}\n value={value}\n onChange={props.onChange}\n />\n </div>\n );\n}\n\nfunction ArrayField(props: {\n field: SchemaFieldDefinition;\n label: string;\n description: string | undefined;\n path: JsonPath;\n rootValue: Record<string, unknown>;\n value: unknown;\n disabled: boolean;\n onChange: (path: JsonPath, value: unknown | undefined) => void;\n onRemoveArrayItem: (path: JsonPath, index: number) => void;\n}) {\n const itemSchema = schemaItems(props.field.schema);\n const items = Array.isArray(props.value) ? props.value : [];\n const itemEntries = items.map((item, index) => ({\n index,\n key: `${formatPath(props.path)}:${index}:${formatEnumValue(item)}`,\n }));\n return (\n <div className=\"grid min-w-0 gap-3 border-b border-hair pb-3 last:border-b-0\">\n <div className=\"flex min-w-0 items-center justify-between gap-3\">\n <FieldHeader label={props.label} required={props.field.required} />\n {itemSchema === undefined ? null : (\n <Button\n className=\"h-8 min-h-8 rounded-md px-3 text-xs\"\n disabled={props.disabled}\n type=\"button\"\n variant=\"secondary\"\n onClick={() =>\n props.onChange(props.path, [...items, defaultValueForSchema(itemSchema)])\n }\n >\n Add\n </Button>\n )}\n </div>\n {props.description === undefined ? null : (\n <p className=\"m-0 text-xs leading-5 text-muted-foreground\">{props.description}</p>\n )}\n {itemSchema === undefined ? (\n <JsonValueField\n disabled={props.disabled}\n path={props.path}\n value={props.value}\n onChange={props.onChange}\n />\n ) : items.length === 0 ? (\n <div className=\"rounded-md border border-dashed border-hair px-3 py-2 text-xs text-muted-foreground\">\n Empty array\n </div>\n ) : (\n <div className=\"grid gap-3 border-l border-hair pl-3\">\n {itemEntries.map((item) => (\n <div className=\"grid gap-2\" key={item.key}>\n <div className=\"flex items-center justify-between gap-3\">\n <span className=\"text-xs font-medium text-muted-foreground\">\n Item {item.index + 1}\n </span>\n <Button\n className=\"h-7 min-h-7 rounded-md px-2 text-xs\"\n disabled={props.disabled}\n type=\"button\"\n variant=\"ghost\"\n onClick={() => props.onRemoveArrayItem(props.path, item.index)}\n >\n Remove\n </Button>\n </div>\n <SchemaField\n disabled={props.disabled}\n field={{\n name: String(item.index + 1),\n required: true,\n schema: itemSchema,\n }}\n path={[...props.path, item.index]}\n rootValue={props.rootValue}\n onChange={props.onChange}\n onRemoveArrayItem={props.onRemoveArrayItem}\n />\n </div>\n ))}\n </div>\n )}\n </div>\n );\n}\n\nfunction FieldHeader(props: { label: string; required: boolean }) {\n return (\n <div className=\"flex min-w-0 items-center gap-2\">\n <span className=\"min-w-0 truncate text-sm font-semibold text-foreground\">{props.label}</span>\n {props.required ? <RequiredBadge /> : null}\n </div>\n );\n}\n\nfunction RequiredBadge() {\n return (\n <span className=\"rounded-md bg-muted px-2 py-0.5 text-[11px] font-medium text-muted-foreground\">\n required\n </span>\n );\n}\n\nfunction ScalarFieldControl(props: {\n schema: Record<string, unknown>;\n path: JsonPath;\n value: unknown;\n required: boolean;\n disabled: boolean;\n onChange: (path: JsonPath, value: unknown | undefined) => void;\n}) {\n const enumOptions = schemaEnum(props.schema);\n if (enumOptions.length > 0) {\n const selectedIndex = enumOptions.findIndex((option) => jsonEqual(option, props.value));\n const optionEntries = enumOptions.map((option, index) => ({\n label: formatEnumValue(option),\n value: String(index),\n key: `${index}:${formatEnumValue(option)}`,\n }));\n return (\n <div className=\"flex min-w-0 items-center gap-2\">\n <Select\n value={selectedIndex === -1 ? \"\" : String(selectedIndex)}\n disabled={props.disabled}\n onValueChange={(value) => props.onChange(props.path, enumOptions[Number(value)])}\n >\n <SelectTrigger className=\"h-9 min-h-9 rounded-md border-border bg-background text-sm\">\n <SelectValue placeholder=\"Select value\" />\n </SelectTrigger>\n <SelectContent>\n {optionEntries.map((option) => (\n <SelectItem value={option.value} key={option.key}>\n {option.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {selectedIndex === -1 || props.required ? null : (\n <Button\n className=\"h-9 min-h-9 rounded-md px-3 text-xs\"\n disabled={props.disabled}\n type=\"button\"\n variant=\"ghost\"\n onClick={() => props.onChange(props.path, undefined)}\n >\n Clear\n </Button>\n )}\n </div>\n );\n }\n\n const type = schemaPrimaryType(props.schema);\n if (type === \"boolean\") {\n return (\n <label className=\"flex min-h-9 w-fit cursor-pointer items-center gap-2 rounded-md border border-hair bg-background px-3 text-sm text-foreground\">\n <input\n checked={props.value === true}\n disabled={props.disabled}\n type=\"checkbox\"\n className=\"h-4 w-4 accent-foreground\"\n onChange={(event) => props.onChange(props.path, event.target.checked)}\n />\n Enabled\n </label>\n );\n }\n\n if (type === \"number\" || type === \"integer\") {\n return (\n <NumberFieldControl\n disabled={props.disabled}\n path={props.path}\n schema={props.schema}\n type={type}\n value={props.value}\n onChange={props.onChange}\n />\n );\n }\n\n if (type === \"string\") {\n return (\n <Input\n className=\"h-9 rounded-md border-border bg-background text-sm\"\n disabled={props.disabled}\n type=\"text\"\n value={typeof props.value === \"string\" ? props.value : \"\"}\n placeholder={schemaDefaultPlaceholder(props.schema)}\n onChange={(event) => {\n const nextValue = event.target.value;\n props.onChange(\n props.path,\n nextValue.length === 0 && !props.required ? undefined : nextValue,\n );\n }}\n />\n );\n }\n\n return (\n <JsonValueField\n disabled={props.disabled}\n path={props.path}\n value={props.value}\n onChange={props.onChange}\n />\n );\n}\n\nfunction NumberFieldControl(props: {\n schema: Record<string, unknown>;\n type: \"number\" | \"integer\";\n path: JsonPath;\n value: unknown;\n disabled: boolean;\n onChange: (path: JsonPath, value: unknown | undefined) => void;\n}) {\n const externalValue = typeof props.value === \"number\" ? String(props.value) : \"\";\n const [draft, setDraft] = useState(externalValue);\n\n useEffect(() => {\n setDraft(externalValue);\n }, [externalValue]);\n\n return (\n <Input\n className=\"h-9 rounded-md border-border bg-background text-sm\"\n disabled={props.disabled}\n inputMode={props.type === \"integer\" ? \"numeric\" : \"decimal\"}\n type=\"text\"\n value={draft}\n placeholder={schemaDefaultPlaceholder(props.schema)}\n onBlur={() => {\n if (draft.trim().length === 0) {\n setDraft(\"\");\n return;\n }\n const nextValue = parseNumberDraft(draft, props.type);\n setDraft(nextValue.ok ? String(nextValue.value) : externalValue);\n }}\n onChange={(event) => {\n const nextDraft = event.target.value;\n setDraft(nextDraft);\n if (nextDraft.trim().length === 0) {\n props.onChange(props.path, undefined);\n return;\n }\n const nextValue = parseNumberDraft(nextDraft, props.type);\n if (nextValue.ok) {\n props.onChange(props.path, nextValue.value);\n }\n }}\n />\n );\n}\n\nfunction JsonValueField(props: {\n path: JsonPath;\n value: unknown;\n disabled: boolean;\n onChange: (path: JsonPath, value: unknown | undefined) => void;\n}) {\n const externalValue = useMemo(() => fieldJsonValue(props.value), [props.value]);\n const [draft, setDraft] = useState(externalValue);\n const parsed = useMemo(() => parseJson(draft), [draft]);\n\n useEffect(() => {\n setDraft(externalValue);\n }, [externalValue]);\n\n return (\n <div className=\"grid gap-2\">\n <Textarea\n className=\"min-h-24 resize-y rounded-md border-border bg-background p-3 text-xs leading-5\"\n disabled={props.disabled}\n value={draft}\n spellCheck={false}\n onChange={(event) => {\n const nextDraft = event.target.value;\n setDraft(nextDraft);\n if (nextDraft.trim().length === 0) {\n props.onChange(props.path, undefined);\n return;\n }\n const nextValue = parseJson(nextDraft);\n if (nextValue.ok) {\n props.onChange(props.path, nextValue.value);\n }\n }}\n />\n {parsed.ok || draft.trim().length === 0 ? null : (\n <div className=\"rounded-md border border-status-danger-ink bg-status-danger-fill px-3 py-2 text-xs leading-5 text-destructive\">\n {parsed.error}\n </div>\n )}\n </div>\n );\n}\n\nfunction schemaFields(schema: unknown): SchemaFieldDefinition[] {\n if (!isRecord(schema)) {\n return [];\n }\n const properties = schema.properties;\n if (!isRecord(properties)) {\n return [];\n }\n const required = schemaRequired(schema);\n return Object.entries(properties).map(([name, propertySchema]) => ({\n name,\n required: required.has(name),\n schema: isRecord(propertySchema) ? propertySchema : {},\n }));\n}\n\nfunction schemaRequired(schema: Record<string, unknown>): Set<string> {\n const required = schema.required;\n if (!Array.isArray(required)) {\n return new Set();\n }\n return new Set(required.filter((item): item is string => typeof item === \"string\"));\n}\n\nfunction schemaPrimaryType(schema: Record<string, unknown>): string {\n const type = schema.type;\n if (typeof type === \"string\") {\n return type;\n }\n if (Array.isArray(type)) {\n const firstType = type.find(\n (item): item is string => typeof item === \"string\" && item !== \"null\",\n );\n if (firstType !== undefined) {\n return firstType;\n }\n }\n if (schemaEnum(schema).length > 0) {\n return \"enum\";\n }\n if (isRecord(schema.properties)) {\n return \"object\";\n }\n if (schema.items !== undefined) {\n return \"array\";\n }\n return \"unknown\";\n}\n\nfunction schemaItems(schema: Record<string, unknown>): Record<string, unknown> | undefined {\n return isRecord(schema.items) ? schema.items : undefined;\n}\n\nfunction schemaEnum(schema: Record<string, unknown>): unknown[] {\n return Array.isArray(schema.enum) ? schema.enum : [];\n}\n\nfunction schemaLabel(schema: Record<string, unknown>, fallback: string): string {\n return typeof schema.title === \"string\" && schema.title.length > 0\n ? schema.title\n : formatFieldName(fallback);\n}\n\nfunction schemaDescription(schema: Record<string, unknown>): string | undefined {\n return typeof schema.description === \"string\" && schema.description.length > 0\n ? schema.description\n : undefined;\n}\n\nfunction schemaDefaultPlaceholder(schema: Record<string, unknown>): string | undefined {\n return Object.hasOwn(schema, \"default\") ? formatEnumValue(schema.default) : undefined;\n}\n\nfunction defaultValueForSchema(schema: Record<string, unknown>): unknown {\n if (Object.hasOwn(schema, \"default\")) {\n return schema.default;\n }\n const enumOptions = schemaEnum(schema);\n if (enumOptions.length > 0) {\n return enumOptions[0];\n }\n const type = schemaPrimaryType(schema);\n if (type === \"boolean\") {\n return false;\n }\n if (type === \"integer\" || type === \"number\") {\n return 0;\n }\n if (type === \"array\") {\n return [];\n }\n if (type === \"object\") {\n return {};\n }\n if (type === \"string\") {\n return \"\";\n }\n return null;\n}\n\nfunction getValueAtPath(root: unknown, path: JsonPath): unknown {\n let current = root;\n for (const segment of path) {\n if (typeof segment === \"number\") {\n if (!Array.isArray(current)) {\n return undefined;\n }\n current = current[segment];\n continue;\n }\n if (!isRecord(current)) {\n return undefined;\n }\n current = current[segment];\n }\n return current;\n}\n\nfunction setValueAtPath(root: unknown, path: JsonPath, value: unknown | undefined): unknown {\n if (path.length === 0) {\n return value;\n }\n const [segment, ...rest] = path;\n const nextRoot = Array.isArray(root) ? [...root] : isRecord(root) ? { ...root } : {};\n if (rest.length === 0) {\n if (value === undefined) {\n if (Array.isArray(nextRoot) && typeof segment === \"number\") {\n nextRoot.splice(segment, 1);\n } else if (!Array.isArray(nextRoot) && typeof segment === \"string\") {\n delete nextRoot[segment];\n }\n return nextRoot;\n }\n if (Array.isArray(nextRoot) && typeof segment === \"number\") {\n nextRoot[segment] = value;\n } else if (!Array.isArray(nextRoot) && typeof segment === \"string\") {\n nextRoot[segment] = value;\n }\n return nextRoot;\n }\n const currentValue =\n Array.isArray(nextRoot) && typeof segment === \"number\"\n ? nextRoot[segment]\n : !Array.isArray(nextRoot) && typeof segment === \"string\"\n ? nextRoot[segment]\n : undefined;\n const nextValue = setValueAtPath(currentValue, rest, value);\n if (Array.isArray(nextRoot) && typeof segment === \"number\") {\n nextRoot[segment] = nextValue;\n } else if (!Array.isArray(nextRoot) && typeof segment === \"string\") {\n nextRoot[segment] = nextValue;\n }\n return nextRoot;\n}\n\nfunction parseJson(value: string): ParseResult {\n if (value.trim().length === 0) {\n return { ok: true, value: undefined };\n }\n try {\n return { ok: true, value: JSON.parse(value) };\n } catch (error) {\n return { ok: false, error: error instanceof Error ? error.message : String(error) };\n }\n}\n\ntype NumberParseResult = { ok: true; value: number } | { ok: false };\n\nfunction parseNumberDraft(value: string, type: \"number\" | \"integer\"): NumberParseResult {\n const normalized = value.trim();\n if (normalized.length === 0 || isIncompleteNumberDraft(normalized)) {\n return { ok: false };\n }\n const parsed = Number(normalized);\n if (!Number.isFinite(parsed)) {\n return { ok: false };\n }\n if (type === \"integer\" && !Number.isInteger(parsed)) {\n return { ok: false };\n }\n return { ok: true, value: parsed };\n}\n\nfunction isIncompleteNumberDraft(value: string): boolean {\n return (\n value === \"-\" ||\n value === \"+\" ||\n value === \".\" ||\n value === \"-.\" ||\n value === \"+.\" ||\n /^[+-]?\\d+\\.$/.test(value) ||\n /[eE][+-]?$/.test(value)\n );\n}\n\nfunction fieldJsonValue(value: unknown): string {\n if (value === undefined) {\n return \"\";\n }\n return formatEditorJson(value);\n}\n\nfunction formatEditorJson(value: unknown): string {\n return JSON.stringify(value, null, 2);\n}\n\nfunction jsonEqual(left: unknown, right: unknown): boolean {\n return JSON.stringify(left) === JSON.stringify(right);\n}\n\nfunction formatEnumValue(value: unknown): string {\n if (typeof value === \"string\") {\n return value;\n }\n if (typeof value === \"number\" || typeof value === \"boolean\") {\n return String(value);\n }\n if (value === null) {\n return \"null\";\n }\n return JSON.stringify(value);\n}\n\nfunction formatPath(path: JsonPath): string {\n return path.join(\".\");\n}\n\nfunction formatFieldName(value: string): string {\n return value\n .replace(/[_-]+/g, \" \")\n .replace(/([a-z])([A-Z])/g, \"$1 $2\")\n .replace(/\\b\\w/g, (match) => match.toUpperCase());\n}\n","import type { ReactNode } from \"react\";\nimport type { StudioAgentToolMetadata, StudioToolRunResponse } from \"../../../../types\";\nimport { Badge } from \"../../components/ui/badge\";\nimport { Button } from \"../../components/ui/button\";\nimport { parseToolDisplayValue } from \"../shared/format\";\nimport { isRecord } from \"../shared/object\";\nimport { JsonSyntax } from \"../shared/renderers\";\nimport { SchemaArgumentEditor } from \"./schema-argument-editor\";\n\nexport type ToolRunState = \"idle\" | \"running\";\n\nexport function ToolRunner(props: {\n selectedTool: StudioAgentToolMetadata | undefined;\n argsText: string;\n runState: ToolRunState;\n runError: string;\n runResponse: StudioToolRunResponse | undefined;\n onArgsTextChange: (value: string) => void;\n onRun: () => void;\n}) {\n const propertyCount =\n props.selectedTool === undefined ? 0 : schemaPropertyCount(props.selectedTool.parameters);\n return (\n <section className=\"grid gap-4 border-t border-hair pt-4 xl:grid-cols-[minmax(260px,0.42fr)_minmax(0,1fr)]\">\n <div className=\"grid content-start gap-3\">\n <div className=\"grid gap-1.5\">\n <h2 className=\"m-0 text-base font-semibold text-foreground\">Runner</h2>\n {props.selectedTool === undefined ? (\n <p className=\"m-0 text-sm leading-6 text-muted-foreground\">No tool selected</p>\n ) : (\n <>\n <p className=\"m-0 break-all text-sm font-semibold leading-6 text-foreground\">\n {props.selectedTool.name}\n </p>\n <p className=\"m-0 max-w-[62ch] text-sm leading-6 text-muted-foreground\">\n {props.selectedTool.description}\n </p>\n </>\n )}\n </div>\n {props.selectedTool === undefined ? null : (\n <div className=\"flex min-w-0 flex-wrap gap-2\">\n <Badge className={originBadgeClass(props.selectedTool)}>\n {toolOriginLabel(props.selectedTool)}\n </Badge>\n <Badge className={approvalBadgeClass(props.selectedTool.approval.required)}>\n approval {props.selectedTool.approval.required ? \"required\" : \"none\"}\n </Badge>\n <ToolMetaPill>\n {propertyCount} {propertyCount === 1 ? \"field\" : \"fields\"}\n </ToolMetaPill>\n </div>\n )}\n {props.selectedTool?.approval.reason === undefined ? null : (\n <p className=\"m-0 border-l border-hair pl-3 text-xs leading-5 text-muted-foreground\">\n {props.selectedTool.approval.reason}\n </p>\n )}\n </div>\n <div className=\"grid min-w-0 gap-3\">\n <SchemaArgumentEditor\n disabled={props.selectedTool === undefined}\n schema={props.selectedTool?.parameters}\n value={props.argsText}\n onChange={props.onArgsTextChange}\n />\n <div className=\"flex min-w-0 items-center justify-between gap-3\">\n <span className=\"min-w-0 truncate text-xs text-muted-foreground\">\n Arguments must be valid JSON.\n </span>\n <Button\n className=\"h-8 min-h-8 rounded-md px-4 text-xs\"\n type=\"button\"\n disabled={props.runState === \"running\" || props.selectedTool === undefined}\n onClick={props.onRun}\n >\n {props.runState === \"running\" ? \"Running\" : \"Run\"}\n </Button>\n </div>\n {props.runError.length > 0 ? (\n <div className=\"rounded-md border border-status-danger-ink bg-status-danger-fill px-3 py-2 text-xs leading-5 text-destructive\">\n {props.runError}\n </div>\n ) : null}\n {props.selectedTool === undefined ? null : (\n <details className=\"group border-t border-hair pt-3\">\n <summary className=\"flex cursor-pointer list-none items-center justify-between gap-3 text-xs font-semibold uppercase tracking-[0.16em] text-muted-foreground marker:hidden\">\n Parameter schema\n <span className=\"font-medium normal-case tracking-normal\">\n {schemaType(props.selectedTool.parameters)}\n </span>\n </summary>\n <div className=\"mt-3\">\n <SchemaBlock value={props.selectedTool.parameters} title=\"JSON schema\" />\n </div>\n </details>\n )}\n {props.runResponse === undefined ? null : <ToolRunResult response={props.runResponse} />}\n </div>\n </section>\n );\n}\n\nfunction ToolRunResult(props: { response: StudioToolRunResponse }) {\n const hasResult = Object.hasOwn(props.response, \"result\");\n const primaryValue = hasResult ? props.response.result : props.response.error;\n const title = hasResult ? \"Tool result\" : \"Tool error\";\n\n return (\n <div className=\"grid gap-3\">\n <SchemaBlock value={displayToolRunValue(primaryValue)} title={title} />\n <details className=\"group border-t border-hair pt-3\">\n <summary className=\"flex cursor-pointer list-none items-center justify-between gap-3 text-xs font-semibold uppercase tracking-[0.16em] text-muted-foreground marker:hidden\">\n Raw run response\n <span className=\"font-medium normal-case tracking-normal\">\n {props.response.status} / {props.response.durationMs}ms\n </span>\n </summary>\n <div className=\"mt-3\">\n <SchemaBlock value={props.response} title=\"Studio envelope\" />\n </div>\n </details>\n </div>\n );\n}\n\nexport function SchemaBlock(props: { value: unknown; title: string }) {\n return (\n <section className=\"grid min-w-0 content-start overflow-hidden rounded-lg bg-background\">\n <div className=\"flex min-h-9 items-center justify-between gap-3 bg-muted px-4\">\n <span className=\" text-xs font-semibold uppercase tracking-[0.2em] text-muted-foreground\">\n {props.title}\n </span>\n <span className=\" text-xs text-muted-foreground\">{schemaType(props.value)}</span>\n </div>\n <div className=\"min-w-0 overflow-x-auto\">\n <pre className=\"m-0 max-h-96 min-w-max p-4 text-xs leading-5 text-foreground\">\n <code>\n <JsonSyntax text={formatSchema(props.value)} />\n </code>\n </pre>\n </div>\n </section>\n );\n}\n\nexport function ToolMetaPill(props: { children: ReactNode }) {\n return (\n <span className=\"inline-flex min-h-7 items-center rounded-md bg-muted px-2.5 text-xs font-medium text-muted-foreground\">\n {props.children}\n </span>\n );\n}\n\nexport function approvalBadgeClass(required: boolean): string {\n return required\n ? \"border-hair bg-muted text-foreground\"\n : \"border-transparent bg-transparent text-dim\";\n}\n\nexport function sourceBadgeClass(source: \"static\" | \"dynamic\"): string {\n return source === \"dynamic\"\n ? \"border-hair bg-muted text-foreground\"\n : \"border-hair bg-muted text-muted-foreground\";\n}\n\nexport function originBadgeClass(tool: StudioAgentToolMetadata): string {\n return tool.mcpServerName === undefined\n ? sourceBadgeClass(tool.source)\n : \"border-hair bg-muted text-foreground\";\n}\n\nexport function toolOriginLabel(tool: StudioAgentToolMetadata): string {\n return tool.mcpServerName === undefined ? tool.source : `MCP / ${tool.mcpServerName}`;\n}\n\nexport function schemaType(value: unknown): string {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return \"value\";\n }\n const type = (value as { type?: unknown }).type;\n return typeof type === \"string\" ? type : \"object\";\n}\n\nexport function schemaPropertyCount(value: unknown): number {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return 0;\n }\n const properties = (value as { properties?: unknown }).properties;\n return typeof properties === \"object\" && properties !== null && !Array.isArray(properties)\n ? Object.keys(properties).length\n : 0;\n}\n\nexport function formatJson(value: unknown): string {\n try {\n return JSON.stringify(value, null, 2);\n } catch {\n return String(value);\n }\n}\n\nexport function parseStudioToolRunResponse(value: unknown): StudioToolRunResponse | undefined {\n if (!isRecord(value)) {\n return undefined;\n }\n if (typeof value.agentId !== \"string\" || value.agentId.length === 0) {\n return undefined;\n }\n if (typeof value.toolName !== \"string\" || value.toolName.length === 0) {\n return undefined;\n }\n if (value.status !== \"success\" && value.status !== \"error\") {\n return undefined;\n }\n if (typeof value.durationMs !== \"number\" || !Number.isFinite(value.durationMs)) {\n return undefined;\n }\n if (typeof value.startedAt !== \"string\" || typeof value.endedAt !== \"string\") {\n return undefined;\n }\n if (!Array.isArray(value.events)) {\n return undefined;\n }\n return value as StudioToolRunResponse;\n}\n\nfunction displayToolRunValue(value: unknown): unknown {\n if (typeof value !== \"string\") {\n return value;\n }\n const parsed = parseToolDisplayValue(value);\n return parsed.kind === \"json\" ? parsed.value : value;\n}\n\nfunction formatSchema(value: unknown): string {\n try {\n return JSON.stringify(value, null, 2);\n } catch {\n return String(value);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"tool-runner-xLspgGPa.js","names":[],"sources":["../../../src/ui/app/modules/tools/schema-argument-editor.tsx","../../../src/ui/app/modules/tools/tool-runner.tsx"],"sourcesContent":["import { useEffect, useMemo, useState } from \"react\";\nimport { Button } from \"../../components/ui/button\";\nimport { Input } from \"../../components/ui/input\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"../../components/ui/select\";\nimport { Textarea } from \"../../components/ui/textarea\";\nimport { isRecord } from \"../shared/object\";\n\ntype ArgumentMode = \"form\" | \"json\";\ntype JsonPath = Array<string | number>;\ntype ParseResult = { ok: true; value: unknown } | { ok: false; error: string };\n\nexport function SchemaArgumentEditor(props: {\n schema: unknown;\n value: string;\n disabled?: boolean;\n onChange: (value: string) => void;\n}) {\n const [mode, setMode] = useState<ArgumentMode>(\"form\");\n const rootFields = useMemo(() => schemaFields(props.schema), [props.schema]);\n const parsed = useMemo(() => parseJson(props.value), [props.value]);\n const disabled = props.disabled === true;\n const canRenderForm = rootFields.length > 0;\n const effectiveMode = canRenderForm ? mode : \"json\";\n const rootValue = parsed.ok && isRecord(parsed.value) ? parsed.value : undefined;\n\n function updatePath(path: JsonPath, value: unknown | undefined) {\n const base = rootValue ?? {};\n props.onChange(formatEditorJson(setValueAtPath(base, path, value)));\n }\n\n function removePathItem(path: JsonPath, index: number) {\n const base = rootValue ?? {};\n const arrayValue = getValueAtPath(base, path);\n if (!Array.isArray(arrayValue)) {\n return;\n }\n props.onChange(\n formatEditorJson(\n setValueAtPath(\n base,\n path,\n arrayValue.filter((_, itemIndex) => itemIndex !== index),\n ),\n ),\n );\n }\n\n return (\n <div className=\"grid min-w-0 gap-3\">\n <div className=\"flex min-w-0 items-center justify-between gap-3\">\n <span className=\"text-xs font-semibold uppercase tracking-[0.16em] text-muted-foreground\">\n Arguments\n </span>\n {canRenderForm ? (\n <div className=\"inline-grid h-8 grid-cols-2 overflow-hidden rounded-md border border-hair bg-background p-0.5\">\n <ModeButton active={effectiveMode === \"form\"} onClick={() => setMode(\"form\")}>\n Form\n </ModeButton>\n <ModeButton active={effectiveMode === \"json\"} onClick={() => setMode(\"json\")}>\n JSON\n </ModeButton>\n </div>\n ) : (\n <span className=\"text-xs font-medium text-muted-foreground\">JSON</span>\n )}\n </div>\n\n {effectiveMode === \"json\" || rootValue === undefined ? (\n <RawJsonEditor\n disabled={disabled}\n error={parsed.ok ? \"\" : parsed.error}\n value={props.value}\n onChange={props.onChange}\n />\n ) : (\n <div className=\"grid gap-3\">\n {rootFields.map((field) => (\n <SchemaField\n disabled={disabled}\n field={field}\n key={field.name}\n path={[field.name]}\n rootValue={rootValue}\n onChange={updatePath}\n onRemoveArrayItem={removePathItem}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\nfunction ModeButton(props: { active: boolean; children: string; onClick: () => void }) {\n return (\n <button\n className={\n props.active\n ? \"rounded-[5px] bg-muted px-3 text-xs font-semibold text-foreground\"\n : \"rounded-[5px] px-3 text-xs font-medium text-muted-foreground transition hover:text-foreground\"\n }\n type=\"button\"\n onClick={props.onClick}\n >\n {props.children}\n </button>\n );\n}\n\nfunction RawJsonEditor(props: {\n value: string;\n error: string;\n disabled: boolean;\n onChange: (value: string) => void;\n}) {\n return (\n <div className=\"grid gap-2\">\n <Textarea\n className=\"min-h-36 resize-y rounded-md border-border bg-background p-3 text-xs leading-5\"\n disabled={props.disabled}\n value={props.value}\n spellCheck={false}\n onChange={(event) => props.onChange(event.target.value)}\n />\n {props.error.length === 0 ? null : (\n <div className=\"rounded-md border border-status-danger-ink bg-status-danger-fill px-3 py-2 text-xs leading-5 text-destructive\">\n {props.error}\n </div>\n )}\n </div>\n );\n}\n\ntype SchemaFieldDefinition = {\n name: string;\n schema: Record<string, unknown>;\n required: boolean;\n};\n\nfunction SchemaField(props: {\n field: SchemaFieldDefinition;\n path: JsonPath;\n rootValue: Record<string, unknown>;\n disabled: boolean;\n onChange: (path: JsonPath, value: unknown | undefined) => void;\n onRemoveArrayItem: (path: JsonPath, index: number) => void;\n}) {\n const value = getValueAtPath(props.rootValue, props.path);\n const label = schemaLabel(props.field.schema, props.field.name);\n const description = schemaDescription(props.field.schema);\n const type = schemaPrimaryType(props.field.schema);\n\n if (type === \"object\") {\n const fields = schemaFields(props.field.schema);\n return (\n <fieldset className=\"grid min-w-0 gap-3 border-b border-hair pb-3 last:border-b-0\">\n <div className=\"flex min-w-0 items-center justify-between gap-3\">\n <legend className=\"min-w-0 truncate text-sm font-semibold text-foreground\">\n {label}\n </legend>\n {props.field.required ? <RequiredBadge /> : null}\n </div>\n {description === undefined ? null : (\n <p className=\"m-0 text-xs leading-5 text-muted-foreground\">{description}</p>\n )}\n {fields.length === 0 ? (\n <JsonValueField\n disabled={props.disabled}\n path={props.path}\n value={value}\n onChange={props.onChange}\n />\n ) : (\n <div className=\"grid gap-3 border-l border-hair pl-3\">\n {fields.map((field) => (\n <SchemaField\n disabled={props.disabled}\n field={field}\n key={field.name}\n path={[...props.path, field.name]}\n rootValue={props.rootValue}\n onChange={props.onChange}\n onRemoveArrayItem={props.onRemoveArrayItem}\n />\n ))}\n </div>\n )}\n </fieldset>\n );\n }\n\n if (type === \"array\") {\n return (\n <ArrayField\n description={description}\n disabled={props.disabled}\n field={props.field}\n label={label}\n path={props.path}\n rootValue={props.rootValue}\n value={value}\n onChange={props.onChange}\n onRemoveArrayItem={props.onRemoveArrayItem}\n />\n );\n }\n\n return (\n <div className=\"grid min-w-0 gap-2 border-b border-hair pb-3 last:border-b-0\">\n <FieldHeader label={label} required={props.field.required} />\n {description === undefined ? null : (\n <p className=\"m-0 text-xs leading-5 text-muted-foreground\">{description}</p>\n )}\n <ScalarFieldControl\n disabled={props.disabled}\n path={props.path}\n required={props.field.required}\n schema={props.field.schema}\n value={value}\n onChange={props.onChange}\n />\n </div>\n );\n}\n\nfunction ArrayField(props: {\n field: SchemaFieldDefinition;\n label: string;\n description: string | undefined;\n path: JsonPath;\n rootValue: Record<string, unknown>;\n value: unknown;\n disabled: boolean;\n onChange: (path: JsonPath, value: unknown | undefined) => void;\n onRemoveArrayItem: (path: JsonPath, index: number) => void;\n}) {\n const itemSchema = schemaItems(props.field.schema);\n const items = Array.isArray(props.value) ? props.value : [];\n const itemEntries = items.map((item, index) => ({\n index,\n key: `${formatPath(props.path)}:${index}:${formatEnumValue(item)}`,\n }));\n return (\n <div className=\"grid min-w-0 gap-3 border-b border-hair pb-3 last:border-b-0\">\n <div className=\"flex min-w-0 items-center justify-between gap-3\">\n <FieldHeader label={props.label} required={props.field.required} />\n {itemSchema === undefined ? null : (\n <Button\n className=\"h-8 min-h-8 rounded-md px-3 text-xs\"\n disabled={props.disabled}\n type=\"button\"\n variant=\"secondary\"\n onClick={() =>\n props.onChange(props.path, [...items, defaultValueForSchema(itemSchema)])\n }\n >\n Add\n </Button>\n )}\n </div>\n {props.description === undefined ? null : (\n <p className=\"m-0 text-xs leading-5 text-muted-foreground\">{props.description}</p>\n )}\n {itemSchema === undefined ? (\n <JsonValueField\n disabled={props.disabled}\n path={props.path}\n value={props.value}\n onChange={props.onChange}\n />\n ) : items.length === 0 ? (\n <div className=\"rounded-md border border-dashed border-hair px-3 py-2 text-xs text-muted-foreground\">\n Empty array\n </div>\n ) : (\n <div className=\"grid gap-3 border-l border-hair pl-3\">\n {itemEntries.map((item) => (\n <div className=\"grid gap-2\" key={item.key}>\n <div className=\"flex items-center justify-between gap-3\">\n <span className=\"text-xs font-medium text-muted-foreground\">\n Item {item.index + 1}\n </span>\n <Button\n className=\"h-7 min-h-7 rounded-md px-2 text-xs\"\n disabled={props.disabled}\n type=\"button\"\n variant=\"ghost\"\n onClick={() => props.onRemoveArrayItem(props.path, item.index)}\n >\n Remove\n </Button>\n </div>\n <SchemaField\n disabled={props.disabled}\n field={{\n name: String(item.index + 1),\n required: true,\n schema: itemSchema,\n }}\n path={[...props.path, item.index]}\n rootValue={props.rootValue}\n onChange={props.onChange}\n onRemoveArrayItem={props.onRemoveArrayItem}\n />\n </div>\n ))}\n </div>\n )}\n </div>\n );\n}\n\nfunction FieldHeader(props: { label: string; required: boolean }) {\n return (\n <div className=\"flex min-w-0 items-center gap-2\">\n <span className=\"min-w-0 truncate text-sm font-semibold text-foreground\">{props.label}</span>\n {props.required ? <RequiredBadge /> : null}\n </div>\n );\n}\n\nfunction RequiredBadge() {\n return (\n <span className=\"rounded-md bg-muted px-2 py-0.5 text-[11px] font-medium text-muted-foreground\">\n required\n </span>\n );\n}\n\nfunction ScalarFieldControl(props: {\n schema: Record<string, unknown>;\n path: JsonPath;\n value: unknown;\n required: boolean;\n disabled: boolean;\n onChange: (path: JsonPath, value: unknown | undefined) => void;\n}) {\n const enumOptions = schemaEnum(props.schema);\n if (enumOptions.length > 0) {\n const selectedIndex = enumOptions.findIndex((option) => jsonEqual(option, props.value));\n const optionEntries = enumOptions.map((option, index) => ({\n label: formatEnumValue(option),\n value: String(index),\n key: `${index}:${formatEnumValue(option)}`,\n }));\n return (\n <div className=\"flex min-w-0 items-center gap-2\">\n <Select\n value={selectedIndex === -1 ? \"\" : String(selectedIndex)}\n disabled={props.disabled}\n onValueChange={(value) => props.onChange(props.path, enumOptions[Number(value)])}\n >\n <SelectTrigger className=\"h-9 min-h-9 rounded-md border-border bg-background text-sm\">\n <SelectValue placeholder=\"Select value\" />\n </SelectTrigger>\n <SelectContent>\n {optionEntries.map((option) => (\n <SelectItem value={option.value} key={option.key}>\n {option.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {selectedIndex === -1 || props.required ? null : (\n <Button\n className=\"h-9 min-h-9 rounded-md px-3 text-xs\"\n disabled={props.disabled}\n type=\"button\"\n variant=\"ghost\"\n onClick={() => props.onChange(props.path, undefined)}\n >\n Clear\n </Button>\n )}\n </div>\n );\n }\n\n const type = schemaPrimaryType(props.schema);\n if (type === \"boolean\") {\n return (\n <label className=\"flex min-h-9 w-fit cursor-pointer items-center gap-2 rounded-md border border-hair bg-background px-3 text-sm text-foreground\">\n <input\n checked={props.value === true}\n disabled={props.disabled}\n type=\"checkbox\"\n className=\"h-4 w-4 accent-foreground\"\n onChange={(event) => props.onChange(props.path, event.target.checked)}\n />\n Enabled\n </label>\n );\n }\n\n if (type === \"number\" || type === \"integer\") {\n return (\n <NumberFieldControl\n disabled={props.disabled}\n path={props.path}\n schema={props.schema}\n type={type}\n value={props.value}\n onChange={props.onChange}\n />\n );\n }\n\n if (type === \"string\") {\n return (\n <Input\n className=\"h-9 rounded-md border-border bg-background text-sm\"\n disabled={props.disabled}\n type=\"text\"\n value={typeof props.value === \"string\" ? props.value : \"\"}\n placeholder={schemaDefaultPlaceholder(props.schema)}\n onChange={(event) => {\n const nextValue = event.target.value;\n props.onChange(\n props.path,\n nextValue.length === 0 && !props.required ? undefined : nextValue,\n );\n }}\n />\n );\n }\n\n return (\n <JsonValueField\n disabled={props.disabled}\n path={props.path}\n value={props.value}\n onChange={props.onChange}\n />\n );\n}\n\nfunction NumberFieldControl(props: {\n schema: Record<string, unknown>;\n type: \"number\" | \"integer\";\n path: JsonPath;\n value: unknown;\n disabled: boolean;\n onChange: (path: JsonPath, value: unknown | undefined) => void;\n}) {\n const externalValue = typeof props.value === \"number\" ? String(props.value) : \"\";\n const [draft, setDraft] = useState(externalValue);\n\n useEffect(() => {\n setDraft(externalValue);\n }, [externalValue]);\n\n return (\n <Input\n className=\"h-9 rounded-md border-border bg-background text-sm\"\n disabled={props.disabled}\n inputMode={props.type === \"integer\" ? \"numeric\" : \"decimal\"}\n type=\"text\"\n value={draft}\n placeholder={schemaDefaultPlaceholder(props.schema)}\n onBlur={() => {\n if (draft.trim().length === 0) {\n setDraft(\"\");\n return;\n }\n const nextValue = parseNumberDraft(draft, props.type);\n setDraft(nextValue.ok ? String(nextValue.value) : externalValue);\n }}\n onChange={(event) => {\n const nextDraft = event.target.value;\n setDraft(nextDraft);\n if (nextDraft.trim().length === 0) {\n props.onChange(props.path, undefined);\n return;\n }\n const nextValue = parseNumberDraft(nextDraft, props.type);\n if (nextValue.ok) {\n props.onChange(props.path, nextValue.value);\n }\n }}\n />\n );\n}\n\nfunction JsonValueField(props: {\n path: JsonPath;\n value: unknown;\n disabled: boolean;\n onChange: (path: JsonPath, value: unknown | undefined) => void;\n}) {\n const externalValue = useMemo(() => fieldJsonValue(props.value), [props.value]);\n const [draft, setDraft] = useState(externalValue);\n const parsed = useMemo(() => parseJson(draft), [draft]);\n\n useEffect(() => {\n setDraft(externalValue);\n }, [externalValue]);\n\n return (\n <div className=\"grid gap-2\">\n <Textarea\n className=\"min-h-24 resize-y rounded-md border-border bg-background p-3 text-xs leading-5\"\n disabled={props.disabled}\n value={draft}\n spellCheck={false}\n onChange={(event) => {\n const nextDraft = event.target.value;\n setDraft(nextDraft);\n if (nextDraft.trim().length === 0) {\n props.onChange(props.path, undefined);\n return;\n }\n const nextValue = parseJson(nextDraft);\n if (nextValue.ok) {\n props.onChange(props.path, nextValue.value);\n }\n }}\n />\n {parsed.ok || draft.trim().length === 0 ? null : (\n <div className=\"rounded-md border border-status-danger-ink bg-status-danger-fill px-3 py-2 text-xs leading-5 text-destructive\">\n {parsed.error}\n </div>\n )}\n </div>\n );\n}\n\nfunction schemaFields(schema: unknown): SchemaFieldDefinition[] {\n if (!isRecord(schema)) {\n return [];\n }\n const properties = schema.properties;\n if (!isRecord(properties)) {\n return [];\n }\n const required = schemaRequired(schema);\n return Object.entries(properties).map(([name, propertySchema]) => ({\n name,\n required: required.has(name),\n schema: isRecord(propertySchema) ? propertySchema : {},\n }));\n}\n\nfunction schemaRequired(schema: Record<string, unknown>): Set<string> {\n const required = schema.required;\n if (!Array.isArray(required)) {\n return new Set();\n }\n return new Set(required.filter((item): item is string => typeof item === \"string\"));\n}\n\nfunction schemaPrimaryType(schema: Record<string, unknown>): string {\n const type = schema.type;\n if (typeof type === \"string\") {\n return type;\n }\n if (Array.isArray(type)) {\n const firstType = type.find(\n (item): item is string => typeof item === \"string\" && item !== \"null\",\n );\n if (firstType !== undefined) {\n return firstType;\n }\n }\n if (schemaEnum(schema).length > 0) {\n return \"enum\";\n }\n if (isRecord(schema.properties)) {\n return \"object\";\n }\n if (schema.items !== undefined) {\n return \"array\";\n }\n return \"unknown\";\n}\n\nfunction schemaItems(schema: Record<string, unknown>): Record<string, unknown> | undefined {\n return isRecord(schema.items) ? schema.items : undefined;\n}\n\nfunction schemaEnum(schema: Record<string, unknown>): unknown[] {\n return Array.isArray(schema.enum) ? schema.enum : [];\n}\n\nfunction schemaLabel(schema: Record<string, unknown>, fallback: string): string {\n return typeof schema.title === \"string\" && schema.title.length > 0\n ? schema.title\n : formatFieldName(fallback);\n}\n\nfunction schemaDescription(schema: Record<string, unknown>): string | undefined {\n return typeof schema.description === \"string\" && schema.description.length > 0\n ? schema.description\n : undefined;\n}\n\nfunction schemaDefaultPlaceholder(schema: Record<string, unknown>): string | undefined {\n return Object.hasOwn(schema, \"default\") ? formatEnumValue(schema.default) : undefined;\n}\n\nfunction defaultValueForSchema(schema: Record<string, unknown>): unknown {\n if (Object.hasOwn(schema, \"default\")) {\n return schema.default;\n }\n const enumOptions = schemaEnum(schema);\n if (enumOptions.length > 0) {\n return enumOptions[0];\n }\n const type = schemaPrimaryType(schema);\n if (type === \"boolean\") {\n return false;\n }\n if (type === \"integer\" || type === \"number\") {\n return 0;\n }\n if (type === \"array\") {\n return [];\n }\n if (type === \"object\") {\n return {};\n }\n if (type === \"string\") {\n return \"\";\n }\n return null;\n}\n\nfunction getValueAtPath(root: unknown, path: JsonPath): unknown {\n let current = root;\n for (const segment of path) {\n if (typeof segment === \"number\") {\n if (!Array.isArray(current)) {\n return undefined;\n }\n current = current[segment];\n continue;\n }\n if (!isRecord(current)) {\n return undefined;\n }\n current = current[segment];\n }\n return current;\n}\n\nfunction setValueAtPath(root: unknown, path: JsonPath, value: unknown | undefined): unknown {\n if (path.length === 0) {\n return value;\n }\n const [segment, ...rest] = path;\n const nextRoot = Array.isArray(root) ? [...root] : isRecord(root) ? { ...root } : {};\n if (rest.length === 0) {\n if (value === undefined) {\n if (Array.isArray(nextRoot) && typeof segment === \"number\") {\n nextRoot.splice(segment, 1);\n } else if (!Array.isArray(nextRoot) && typeof segment === \"string\") {\n delete nextRoot[segment];\n }\n return nextRoot;\n }\n if (Array.isArray(nextRoot) && typeof segment === \"number\") {\n nextRoot[segment] = value;\n } else if (!Array.isArray(nextRoot) && typeof segment === \"string\") {\n nextRoot[segment] = value;\n }\n return nextRoot;\n }\n const currentValue =\n Array.isArray(nextRoot) && typeof segment === \"number\"\n ? nextRoot[segment]\n : !Array.isArray(nextRoot) && typeof segment === \"string\"\n ? nextRoot[segment]\n : undefined;\n const nextValue = setValueAtPath(currentValue, rest, value);\n if (Array.isArray(nextRoot) && typeof segment === \"number\") {\n nextRoot[segment] = nextValue;\n } else if (!Array.isArray(nextRoot) && typeof segment === \"string\") {\n nextRoot[segment] = nextValue;\n }\n return nextRoot;\n}\n\nfunction parseJson(value: string): ParseResult {\n if (value.trim().length === 0) {\n return { ok: true, value: undefined };\n }\n try {\n return { ok: true, value: JSON.parse(value) };\n } catch (error) {\n return { ok: false, error: error instanceof Error ? error.message : String(error) };\n }\n}\n\ntype NumberParseResult = { ok: true; value: number } | { ok: false };\n\nfunction parseNumberDraft(value: string, type: \"number\" | \"integer\"): NumberParseResult {\n const normalized = value.trim();\n if (normalized.length === 0 || isIncompleteNumberDraft(normalized)) {\n return { ok: false };\n }\n const parsed = Number(normalized);\n if (!Number.isFinite(parsed)) {\n return { ok: false };\n }\n if (type === \"integer\" && !Number.isInteger(parsed)) {\n return { ok: false };\n }\n return { ok: true, value: parsed };\n}\n\nfunction isIncompleteNumberDraft(value: string): boolean {\n return (\n value === \"-\" ||\n value === \"+\" ||\n value === \".\" ||\n value === \"-.\" ||\n value === \"+.\" ||\n /^[+-]?\\d+\\.$/.test(value) ||\n /[eE][+-]?$/.test(value)\n );\n}\n\nfunction fieldJsonValue(value: unknown): string {\n if (value === undefined) {\n return \"\";\n }\n return formatEditorJson(value);\n}\n\nfunction formatEditorJson(value: unknown): string {\n return JSON.stringify(value, null, 2);\n}\n\nfunction jsonEqual(left: unknown, right: unknown): boolean {\n return JSON.stringify(left) === JSON.stringify(right);\n}\n\nfunction formatEnumValue(value: unknown): string {\n if (typeof value === \"string\") {\n return value;\n }\n if (typeof value === \"number\" || typeof value === \"boolean\") {\n return String(value);\n }\n if (value === null) {\n return \"null\";\n }\n return JSON.stringify(value);\n}\n\nfunction formatPath(path: JsonPath): string {\n return path.join(\".\");\n}\n\nfunction formatFieldName(value: string): string {\n return value\n .replace(/[_-]+/g, \" \")\n .replace(/([a-z])([A-Z])/g, \"$1 $2\")\n .replace(/\\b\\w/g, (match) => match.toUpperCase());\n}\n","import type { ReactNode } from \"react\";\nimport type { StudioAgentToolMetadata, StudioToolRunResponse } from \"../../../../types\";\nimport { Badge } from \"../../components/ui/badge\";\nimport { Button } from \"../../components/ui/button\";\nimport { parseToolDisplayValue } from \"../shared/format\";\nimport { isRecord } from \"../shared/object\";\nimport { JsonSyntax } from \"../shared/renderers\";\nimport { SchemaArgumentEditor } from \"./schema-argument-editor\";\n\nexport type ToolRunState = \"idle\" | \"running\";\n\nexport function ToolRunner(props: {\n selectedTool: StudioAgentToolMetadata | undefined;\n argsText: string;\n runState: ToolRunState;\n runError: string;\n runResponse: StudioToolRunResponse | undefined;\n onArgsTextChange: (value: string) => void;\n onRun: () => void;\n}) {\n const propertyCount =\n props.selectedTool === undefined ? 0 : schemaPropertyCount(props.selectedTool.parameters);\n return (\n <section className=\"grid gap-4 border-t border-hair pt-4 xl:grid-cols-[minmax(260px,0.42fr)_minmax(0,1fr)]\">\n <div className=\"grid content-start gap-3\">\n <div className=\"grid gap-1.5\">\n <h2 className=\"m-0 text-base font-semibold text-foreground\">Runner</h2>\n {props.selectedTool === undefined ? (\n <p className=\"m-0 text-sm leading-6 text-muted-foreground\">No tool selected</p>\n ) : (\n <>\n <p className=\"m-0 break-all text-sm font-semibold leading-6 text-foreground\">\n {props.selectedTool.name}\n </p>\n <p className=\"m-0 max-w-[62ch] text-sm leading-6 text-muted-foreground\">\n {props.selectedTool.description}\n </p>\n </>\n )}\n </div>\n {props.selectedTool === undefined ? null : (\n <div className=\"flex min-w-0 flex-wrap gap-2\">\n <Badge className={originBadgeClass(props.selectedTool)}>\n {toolOriginLabel(props.selectedTool)}\n </Badge>\n <Badge className={approvalBadgeClass(props.selectedTool.approval.required)}>\n approval {props.selectedTool.approval.required ? \"required\" : \"none\"}\n </Badge>\n <ToolMetaPill>\n {propertyCount} {propertyCount === 1 ? \"field\" : \"fields\"}\n </ToolMetaPill>\n </div>\n )}\n {props.selectedTool?.approval.reason === undefined ? null : (\n <p className=\"m-0 border-l border-hair pl-3 text-xs leading-5 text-muted-foreground\">\n {props.selectedTool.approval.reason}\n </p>\n )}\n </div>\n <div className=\"grid min-w-0 gap-3\">\n <SchemaArgumentEditor\n disabled={props.selectedTool === undefined}\n schema={props.selectedTool?.parameters}\n value={props.argsText}\n onChange={props.onArgsTextChange}\n />\n <div className=\"flex min-w-0 items-center justify-between gap-3\">\n <span className=\"min-w-0 truncate text-xs text-muted-foreground\">\n Arguments must be valid JSON.\n </span>\n <Button\n className=\"h-8 min-h-8 rounded-md px-4 text-xs\"\n type=\"button\"\n disabled={props.runState === \"running\" || props.selectedTool === undefined}\n onClick={props.onRun}\n >\n {props.runState === \"running\" ? \"Running\" : \"Run\"}\n </Button>\n </div>\n {props.runError.length > 0 ? (\n <div className=\"rounded-md border border-status-danger-ink bg-status-danger-fill px-3 py-2 text-xs leading-5 text-destructive\">\n {props.runError}\n </div>\n ) : null}\n {props.selectedTool === undefined ? null : (\n <details className=\"group border-t border-hair pt-3\">\n <summary className=\"flex cursor-pointer list-none items-center justify-between gap-3 text-xs font-semibold uppercase tracking-[0.16em] text-muted-foreground marker:hidden\">\n Parameter schema\n <span className=\"font-medium normal-case tracking-normal\">\n {schemaType(props.selectedTool.parameters)}\n </span>\n </summary>\n <div className=\"mt-3\">\n <SchemaBlock value={props.selectedTool.parameters} title=\"JSON schema\" />\n </div>\n </details>\n )}\n {props.runResponse === undefined ? null : <ToolRunResult response={props.runResponse} />}\n </div>\n </section>\n );\n}\n\nfunction ToolRunResult(props: { response: StudioToolRunResponse }) {\n const hasResult = Object.hasOwn(props.response, \"result\");\n const primaryValue = hasResult ? props.response.result : props.response.error;\n const title = hasResult ? \"Tool result\" : \"Tool error\";\n\n return (\n <div className=\"grid gap-3\">\n <SchemaBlock value={displayToolRunValue(primaryValue)} title={title} />\n <details className=\"group border-t border-hair pt-3\">\n <summary className=\"flex cursor-pointer list-none items-center justify-between gap-3 text-xs font-semibold uppercase tracking-[0.16em] text-muted-foreground marker:hidden\">\n Raw run response\n <span className=\"font-medium normal-case tracking-normal\">\n {props.response.status} / {props.response.durationMs}ms\n </span>\n </summary>\n <div className=\"mt-3\">\n <SchemaBlock value={props.response} title=\"Studio envelope\" />\n </div>\n </details>\n </div>\n );\n}\n\nexport function SchemaBlock(props: { value: unknown; title: string }) {\n return (\n <section className=\"grid min-w-0 content-start overflow-hidden rounded-lg bg-background\">\n <div className=\"flex min-h-9 items-center justify-between gap-3 bg-muted px-4\">\n <span className=\" text-xs font-semibold uppercase tracking-[0.2em] text-muted-foreground\">\n {props.title}\n </span>\n <span className=\" text-xs text-muted-foreground\">{schemaType(props.value)}</span>\n </div>\n <div className=\"min-w-0 overflow-x-auto\">\n <pre className=\"m-0 max-h-96 min-w-max p-4 text-xs leading-5 text-foreground\">\n <code>\n <JsonSyntax text={formatSchema(props.value)} />\n </code>\n </pre>\n </div>\n </section>\n );\n}\n\nexport function ToolMetaPill(props: { children: ReactNode }) {\n return (\n <span className=\"inline-flex min-h-7 items-center rounded-md bg-muted px-2.5 text-xs font-medium text-muted-foreground\">\n {props.children}\n </span>\n );\n}\n\nexport function approvalBadgeClass(required: boolean): string {\n return required\n ? \"border-hair bg-muted text-foreground\"\n : \"border-transparent bg-transparent text-dim\";\n}\n\nexport function sourceBadgeClass(source: \"static\" | \"dynamic\"): string {\n return source === \"dynamic\"\n ? \"border-hair bg-muted text-foreground\"\n : \"border-hair bg-muted text-muted-foreground\";\n}\n\nexport function originBadgeClass(tool: StudioAgentToolMetadata): string {\n return tool.mcpServerName === undefined\n ? sourceBadgeClass(tool.source)\n : \"border-hair bg-muted text-foreground\";\n}\n\nexport function toolOriginLabel(tool: StudioAgentToolMetadata): string {\n return tool.mcpServerName === undefined ? tool.source : `MCP / ${tool.mcpServerName}`;\n}\n\nexport function schemaType(value: unknown): string {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return \"value\";\n }\n const type = (value as { type?: unknown }).type;\n return typeof type === \"string\" ? type : \"object\";\n}\n\nexport function schemaPropertyCount(value: unknown): number {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return 0;\n }\n const properties = (value as { properties?: unknown }).properties;\n return typeof properties === \"object\" && properties !== null && !Array.isArray(properties)\n ? Object.keys(properties).length\n : 0;\n}\n\nexport function formatJson(value: unknown): string {\n try {\n return JSON.stringify(value, null, 2);\n } catch {\n return String(value);\n }\n}\n\nexport function parseStudioToolRunResponse(value: unknown): StudioToolRunResponse | undefined {\n if (!isRecord(value)) {\n return undefined;\n }\n if (typeof value.agentId !== \"string\" || value.agentId.length === 0) {\n return undefined;\n }\n if (typeof value.toolName !== \"string\" || value.toolName.length === 0) {\n return undefined;\n }\n if (value.status !== \"success\" && value.status !== \"error\") {\n return undefined;\n }\n if (typeof value.durationMs !== \"number\" || !Number.isFinite(value.durationMs)) {\n return undefined;\n }\n if (typeof value.startedAt !== \"string\" || typeof value.endedAt !== \"string\") {\n return undefined;\n }\n if (!Array.isArray(value.events)) {\n return undefined;\n }\n return value as StudioToolRunResponse;\n}\n\nfunction displayToolRunValue(value: unknown): unknown {\n if (typeof value !== \"string\") {\n return value;\n }\n const parsed = parseToolDisplayValue(value);\n return parsed.kind === \"json\" ? parsed.value : value;\n}\n\nfunction formatSchema(value: unknown): string {\n try {\n return JSON.stringify(value, null, 2);\n } catch {\n return String(value);\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{i as e,r as t,s as n}from"./dist-CHLp-Np4.js";import{t as r}from"./button-BWxpVW85.js";import{a as i,i as a,n as o,r as s,t as c}from"./select-C4MbvpHr.js";import{a as l,i as u,n as d,r as f,t as p}from"./studio-CtQdOoHK.js";import{t as m}from"./badge-DUs0RCHV.js";import{a as h,c as g,d as _,i as v,l as y,n as b,o as x,r as S,s as C}from"./tool-runner-xLspgGPa.js";var w=n(e(),1),T=t();function E(e){let t=e.agents.find(t=>t.id===e.selectedAgentId)??e.agents[0],n=(0,w.useMemo)(()=>e.summary?.tools??[],[e.summary]),[r,m]=(0,w.useState)(``),[g,_]=(0,w.useState)(`{}`),[v,y]=(0,w.useState)(`idle`),[b,x]=(0,w.useState)(),[E,O]=(0,w.useState)(``),k=(0,w.useMemo)(()=>n.find(e=>e.name===r)??n[0],[r,n]),A=t===void 0||k===void 0?``:`${t.id}:${k.name}`,M=(0,w.useRef)(A),N=(0,w.useRef)(0),P=j(n);(0,w.useEffect)(()=>{if(n.length===0){m(``);return}n.some(e=>e.name===r)||m(n[0]?.name??``)},[r,n]),(0,w.useEffect)(()=>{M.current!==A&&(M.current=A,N.current+=1,y(`idle`),O(``),x(void 0))},[A]);async function F(){if(t===void 0||k===void 0)return;let e;try{e=JSON.parse(g)}catch(e){O(e instanceof Error?e.message:String(e)),x(void 0);return}y(`running`),O(``),x(void 0);let n=A,r=N.current+1;N.current=r;let i=()=>N.current===r&&M.current===n;try{let n=await fetch(`/agents/${encodeURIComponent(t.id)}/tools/${encodeURIComponent(k.name)}/runs`,{method:`POST`,headers:{"content-type":`application/json`},body:JSON.stringify({args:e})}),r=await n.json();if(!i())return;let a=C(r);if(a===void 0){O(`Unexpected Studio tool run response: ${h(r)}`);return}x(a),(!n.ok||a.status===`error`)&&O(h(a.error??a))}catch(e){i()&&O(e instanceof Error?e.message:String(e))}finally{i()&&y(`idle`)}}return(0,T.jsxs)(l,{className:`grid-rows-[auto_minmax(0,1fr)]`,"aria-label":`Tools`,children:[(0,T.jsx)(u,{title:`Tools`,description:`Tool definitions registered on Studio agents, including approval policy and input schema.`,action:(0,T.jsxs)(`div`,{className:`flex min-w-0 flex-wrap justify-end gap-2 max-sm:justify-start`,children:[(0,T.jsx)(d,{label:`tools`,value:P.total}),(0,T.jsx)(d,{label:`mcp`,value:P.mcp}),(0,T.jsx)(d,{label:`static`,value:P.static}),(0,T.jsx)(d,{label:`dynamic`,value:P.dynamic}),(0,T.jsx)(d,{label:`approvals`,value:P.approvals}),e.agents.length>1?(0,T.jsxs)(c,{value:t?.id??``,onValueChange:e.onSelectAgent,children:[(0,T.jsx)(a,{className:`h-8 min-h-8 w-64 rounded-md border-border text-xs max-sm:w-full`,children:(0,T.jsx)(i,{placeholder:`Agent`})}),(0,T.jsx)(o,{align:`end`,children:e.agents.map(e=>(0,T.jsx)(s,{value:e.id,children:e.name??e.id},e.id))})]}):null]})}),(0,T.jsx)(f,{className:`overflow-auto`,children:e.enabled?e.loading?(0,T.jsx)(p,{title:`Loading tools`,text:`Reading registered tool metadata.`}):n.length===0?(0,T.jsx)(p,{title:`No tools`,text:`The selected agent has no registered tools.`}):(0,T.jsxs)(`div`,{className:`grid w-full gap-5`,children:[(0,T.jsx)(D,{selectedToolName:k?.name??``,tools:n,onSelectTool:m}),(0,T.jsx)(S,{argsText:g,runError:E,runResponse:b,runState:v,selectedTool:k,onArgsTextChange:_,onRun:()=>void F()})]}):(0,T.jsx)(p,{title:`Tools unavailable`,text:`No registered Studio agent exposes static or dynamic tools.`})})]})}function D(e){return(0,T.jsx)(`div`,{className:`min-w-[1040px]`,children:(0,T.jsxs)(`table`,{className:`w-full border-separate border-spacing-0 text-left`,children:[(0,T.jsx)(`thead`,{className:`sticky top-0 z-10 bg-header backdrop-blur`,children:(0,T.jsxs)(`tr`,{children:[(0,T.jsx)(k,{children:`Tool`}),(0,T.jsx)(k,{children:`Origin`}),(0,T.jsx)(k,{children:`Schema`}),(0,T.jsx)(k,{children:`Approval`}),(0,T.jsx)(k,{children:`Run`})]})}),(0,T.jsx)(`tbody`,{children:e.tools.map(t=>(0,T.jsx)(O,{active:e.selectedToolName===t.name,tool:t,onSelectTool:e.onSelectTool},`${t.source}:${t.name}`))})]})})}function O(e){let t=g(e.tool.parameters);return(0,T.jsxs)(`tr`,{children:[(0,T.jsx)(A,{children:(0,T.jsxs)(`div`,{className:`grid min-w-0 gap-1.5`,children:[(0,T.jsxs)(`div`,{className:`flex min-w-0 items-center gap-2`,children:[(0,T.jsx)(`span`,{className:`min-w-0 truncate text-sm font-semibold text-foreground`,children:e.tool.name}),e.active?(0,T.jsx)(m,{className:M,children:`selected`}):null]}),(0,T.jsx)(`span`,{className:`min-w-0 truncate text-xs font-medium text-muted-foreground`,children:e.tool.agentId}),(0,T.jsx)(`p`,{className:`m-0 max-w-[64ch] truncate text-sm leading-6 text-muted-foreground`,children:e.tool.description})]})}),(0,T.jsx)(A,{children:(0,T.jsx)(m,{className:x(e.tool),children:_(e.tool)})}),(0,T.jsx)(A,{children:(0,T.jsxs)(`div`,{className:`flex min-w-0 flex-wrap gap-2`,children:[(0,T.jsx)(b,{children:y(e.tool.parameters)}),(0,T.jsxs)(b,{children:[t,` `,t===1?`field`:`fields`]})]})}),(0,T.jsx)(A,{children:(0,T.jsxs)(`div`,{className:`grid min-w-0 gap-1.5`,children:[(0,T.jsx)(m,{className:v(e.tool.approval.required),children:e.tool.approval.required?`required`:`none`}),e.tool.approval.reason===void 0?null:(0,T.jsx)(`span`,{className:`max-w-[280px] truncate text-xs leading-5 text-muted-foreground`,title:e.tool.approval.reason,children:e.tool.approval.reason})]})}),(0,T.jsx)(A,{children:(0,T.jsx)(r,{className:`h-8 min-h-8 rounded-md px-3 text-xs`,type:`button`,variant:e.active?`secondary`:`ghost`,onClick:()=>e.onSelectTool(e.tool.name),children:e.active?`Selected`:`Use`})})]})}function k(e){return(0,T.jsx)(`th`,{className:`border-b border-hair py-2.5 pr-5 text-xs font-semibold uppercase tracking-[0.16em] text-muted-foreground first:pl-0`,children:e.children})}function A(e){return(0,T.jsx)(`td`,{className:`border-b border-hair py-3.5 pr-5 align-top first:pl-0`,children:e.children})}function j(e){return e.reduce((e,t)=>(e.total+=1,t.source===`dynamic`?e.dynamic+=1:e.static+=1,t.mcpServerName!==void 0&&(e.mcp+=1),t.approval.required&&(e.approvals+=1),e),{approvals:0,dynamic:0,mcp:0,static:0,total:0})}var M=`border-hair bg-row-selected text-foreground`;export{E as ToolsPage};
2
+ //# sourceMappingURL=tools-page-BMyx2xRT.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tools-page-CdkExqNd.js","names":[],"sources":["../../../src/ui/app/modules/tools/tools-page.tsx"],"sourcesContent":["import { type ReactNode, useEffect, useMemo, useRef, useState } from \"react\";\nimport type {\n StudioAgentToolMetadata,\n StudioAgentToolsSummary,\n StudioConfig,\n StudioToolRunResponse,\n} from \"../../../../types\";\nimport { Badge } from \"../../components/ui/badge\";\nimport { Button } from \"../../components/ui/button\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"../../components/ui/select\";\nimport {\n StudioEmptyState,\n StudioHeaderMetric,\n StudioPageContent,\n StudioPageHeader,\n StudioPageShell,\n} from \"../../components/ui/studio\";\nimport {\n approvalBadgeClass,\n formatJson,\n originBadgeClass,\n parseStudioToolRunResponse,\n schemaPropertyCount,\n schemaType,\n ToolMetaPill,\n ToolRunner,\n toolOriginLabel,\n} from \"./tool-runner\";\n\nexport function ToolsPage(props: {\n agents: StudioConfig[\"agents\"];\n selectedAgentId: string;\n summary: StudioAgentToolsSummary | undefined;\n enabled: boolean;\n loading: boolean;\n onSelectAgent: (agentId: string) => void;\n}) {\n const selectedAgent =\n props.agents.find((agent) => agent.id === props.selectedAgentId) ?? props.agents[0];\n const tools = useMemo(() => props.summary?.tools ?? [], [props.summary]);\n const [selectedToolName, setSelectedToolName] = useState(\"\");\n const [argsText, setArgsText] = useState(\"{}\");\n const [runState, setRunState] = useState<\"idle\" | \"running\">(\"idle\");\n const [runResponse, setRunResponse] = useState<StudioToolRunResponse | undefined>();\n const [runError, setRunError] = useState(\"\");\n const selectedTool = useMemo(\n () => tools.find((tool) => tool.name === selectedToolName) ?? tools[0],\n [selectedToolName, tools],\n );\n const selectedToolRunKey =\n selectedAgent === undefined || selectedTool === undefined\n ? \"\"\n : `${selectedAgent.id}:${selectedTool.name}`;\n const selectedToolRunKeyRef = useRef(selectedToolRunKey);\n const runRequestIdRef = useRef(0);\n const toolTotals = summarizeTools(tools);\n\n useEffect(() => {\n if (tools.length === 0) {\n setSelectedToolName(\"\");\n return;\n }\n if (!tools.some((tool) => tool.name === selectedToolName)) {\n setSelectedToolName(tools[0]?.name ?? \"\");\n }\n }, [selectedToolName, tools]);\n\n useEffect(() => {\n if (selectedToolRunKeyRef.current === selectedToolRunKey) {\n return;\n }\n selectedToolRunKeyRef.current = selectedToolRunKey;\n runRequestIdRef.current += 1;\n setRunState(\"idle\");\n setRunError(\"\");\n setRunResponse(undefined);\n }, [selectedToolRunKey]);\n\n async function runSelectedTool() {\n if (selectedAgent === undefined || selectedTool === undefined) {\n return;\n }\n let args: unknown;\n try {\n args = JSON.parse(argsText);\n } catch (parseError) {\n setRunError(parseError instanceof Error ? parseError.message : String(parseError));\n setRunResponse(undefined);\n return;\n }\n\n setRunState(\"running\");\n setRunError(\"\");\n setRunResponse(undefined);\n const runToolKey = selectedToolRunKey;\n const requestId = runRequestIdRef.current + 1;\n runRequestIdRef.current = requestId;\n const isCurrentRun = () =>\n runRequestIdRef.current === requestId && selectedToolRunKeyRef.current === runToolKey;\n try {\n const response = await fetch(\n `/agents/${encodeURIComponent(selectedAgent.id)}/tools/${encodeURIComponent(\n selectedTool.name,\n )}/runs`,\n {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify({ args }),\n },\n );\n const rawBody = await response.json();\n if (!isCurrentRun()) {\n return;\n }\n const body = parseStudioToolRunResponse(rawBody);\n if (body === undefined) {\n setRunError(`Unexpected Studio tool run response: ${formatJson(rawBody)}`);\n return;\n }\n setRunResponse(body);\n if (!response.ok || body.status === \"error\") {\n setRunError(formatJson(body.error ?? body));\n }\n } catch (error) {\n if (isCurrentRun()) {\n setRunError(error instanceof Error ? error.message : String(error));\n }\n } finally {\n if (isCurrentRun()) {\n setRunState(\"idle\");\n }\n }\n }\n\n return (\n <StudioPageShell className=\"grid-rows-[auto_minmax(0,1fr)]\" aria-label=\"Tools\">\n <StudioPageHeader\n title=\"Tools\"\n description=\"Tool definitions registered on Studio agents, including approval policy and input schema.\"\n action={\n <div className=\"flex min-w-0 flex-wrap justify-end gap-2 max-sm:justify-start\">\n <StudioHeaderMetric label=\"tools\" value={toolTotals.total} />\n <StudioHeaderMetric label=\"mcp\" value={toolTotals.mcp} />\n <StudioHeaderMetric label=\"static\" value={toolTotals.static} />\n <StudioHeaderMetric label=\"dynamic\" value={toolTotals.dynamic} />\n <StudioHeaderMetric label=\"approvals\" value={toolTotals.approvals} />\n {props.agents.length > 1 ? (\n <Select value={selectedAgent?.id ?? \"\"} onValueChange={props.onSelectAgent}>\n <SelectTrigger className=\"h-8 min-h-8 w-64 rounded-md border-border text-xs max-sm:w-full\">\n <SelectValue placeholder=\"Agent\" />\n </SelectTrigger>\n <SelectContent align=\"end\">\n {props.agents.map((agent) => (\n <SelectItem value={agent.id} key={agent.id}>\n {agent.name ?? agent.id}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n ) : null}\n </div>\n }\n />\n\n <StudioPageContent className=\"overflow-auto\">\n {!props.enabled ? (\n <StudioEmptyState\n title=\"Tools unavailable\"\n text=\"No registered Studio agent exposes static or dynamic tools.\"\n />\n ) : props.loading ? (\n <StudioEmptyState title=\"Loading tools\" text=\"Reading registered tool metadata.\" />\n ) : tools.length === 0 ? (\n <StudioEmptyState title=\"No tools\" text=\"The selected agent has no registered tools.\" />\n ) : (\n <div className=\"grid w-full gap-5\">\n <ToolRegistryTable\n selectedToolName={selectedTool?.name ?? \"\"}\n tools={tools}\n onSelectTool={setSelectedToolName}\n />\n <ToolRunner\n argsText={argsText}\n runError={runError}\n runResponse={runResponse}\n runState={runState}\n selectedTool={selectedTool}\n onArgsTextChange={setArgsText}\n onRun={() => void runSelectedTool()}\n />\n </div>\n )}\n </StudioPageContent>\n </StudioPageShell>\n );\n}\n\nfunction ToolRegistryTable(props: {\n tools: StudioAgentToolMetadata[];\n selectedToolName: string;\n onSelectTool: (toolName: string) => void;\n}) {\n return (\n <div className=\"min-w-[1040px]\">\n <table className=\"w-full border-separate border-spacing-0 text-left\">\n <thead className=\"sticky top-0 z-10 bg-header backdrop-blur\">\n <tr>\n <ToolTableHead>Tool</ToolTableHead>\n <ToolTableHead>Origin</ToolTableHead>\n <ToolTableHead>Schema</ToolTableHead>\n <ToolTableHead>Approval</ToolTableHead>\n <ToolTableHead>Run</ToolTableHead>\n </tr>\n </thead>\n <tbody>\n {props.tools.map((tool) => (\n <ToolRegistryRow\n active={props.selectedToolName === tool.name}\n key={`${tool.source}:${tool.name}`}\n tool={tool}\n onSelectTool={props.onSelectTool}\n />\n ))}\n </tbody>\n </table>\n </div>\n );\n}\n\nfunction ToolRegistryRow(props: {\n tool: StudioAgentToolMetadata;\n active: boolean;\n onSelectTool: (toolName: string) => void;\n}) {\n const propertyCount = schemaPropertyCount(props.tool.parameters);\n return (\n <tr>\n <ToolTableCell>\n <div className=\"grid min-w-0 gap-1.5\">\n <div className=\"flex min-w-0 items-center gap-2\">\n <span className=\"min-w-0 truncate text-sm font-semibold text-foreground\">\n {props.tool.name}\n </span>\n {props.active ? <Badge className={selectedBadge}>selected</Badge> : null}\n </div>\n <span className=\"min-w-0 truncate text-xs font-medium text-muted-foreground\">\n {props.tool.agentId}\n </span>\n <p className=\"m-0 max-w-[64ch] truncate text-sm leading-6 text-muted-foreground\">\n {props.tool.description}\n </p>\n </div>\n </ToolTableCell>\n <ToolTableCell>\n <Badge className={originBadgeClass(props.tool)}>{toolOriginLabel(props.tool)}</Badge>\n </ToolTableCell>\n <ToolTableCell>\n <div className=\"flex min-w-0 flex-wrap gap-2\">\n <ToolMetaPill>{schemaType(props.tool.parameters)}</ToolMetaPill>\n <ToolMetaPill>\n {propertyCount} {propertyCount === 1 ? \"field\" : \"fields\"}\n </ToolMetaPill>\n </div>\n </ToolTableCell>\n <ToolTableCell>\n <div className=\"grid min-w-0 gap-1.5\">\n <Badge className={approvalBadgeClass(props.tool.approval.required)}>\n {props.tool.approval.required ? \"required\" : \"none\"}\n </Badge>\n {props.tool.approval.reason === undefined ? null : (\n <span\n className=\"max-w-[280px] truncate text-xs leading-5 text-muted-foreground\"\n title={props.tool.approval.reason}\n >\n {props.tool.approval.reason}\n </span>\n )}\n </div>\n </ToolTableCell>\n <ToolTableCell>\n <Button\n className=\"h-8 min-h-8 rounded-md px-3 text-xs\"\n type=\"button\"\n variant={props.active ? \"secondary\" : \"ghost\"}\n onClick={() => props.onSelectTool(props.tool.name)}\n >\n {props.active ? \"Selected\" : \"Use\"}\n </Button>\n </ToolTableCell>\n </tr>\n );\n}\n\nfunction ToolTableHead(props: { children: string }) {\n return (\n <th className=\"border-b border-hair py-2.5 pr-5 text-xs font-semibold uppercase tracking-[0.16em] text-muted-foreground first:pl-0\">\n {props.children}\n </th>\n );\n}\n\nfunction ToolTableCell(props: { children: ReactNode }) {\n return (\n <td className=\"border-b border-hair py-3.5 pr-5 align-top first:pl-0\">{props.children}</td>\n );\n}\n\nfunction summarizeTools(tools: StudioAgentToolMetadata[]) {\n return tools.reduce(\n (totals, tool) => {\n totals.total += 1;\n if (tool.source === \"dynamic\") {\n totals.dynamic += 1;\n } else {\n totals.static += 1;\n }\n if (tool.mcpServerName !== undefined) {\n totals.mcp += 1;\n }\n if (tool.approval.required) {\n totals.approvals += 1;\n }\n return totals;\n },\n { approvals: 0, dynamic: 0, mcp: 0, static: 0, total: 0 },\n );\n}\n\nconst selectedBadge = \"border-hair bg-row-selected text-foreground\";\n"],"mappings":"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"}
1
+ {"version":3,"file":"tools-page-BMyx2xRT.js","names":[],"sources":["../../../src/ui/app/modules/tools/tools-page.tsx"],"sourcesContent":["import { type ReactNode, useEffect, useMemo, useRef, useState } from \"react\";\nimport type {\n StudioAgentToolMetadata,\n StudioAgentToolsSummary,\n StudioConfig,\n StudioToolRunResponse,\n} from \"../../../../types\";\nimport { Badge } from \"../../components/ui/badge\";\nimport { Button } from \"../../components/ui/button\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"../../components/ui/select\";\nimport {\n StudioEmptyState,\n StudioHeaderMetric,\n StudioPageContent,\n StudioPageHeader,\n StudioPageShell,\n} from \"../../components/ui/studio\";\nimport {\n approvalBadgeClass,\n formatJson,\n originBadgeClass,\n parseStudioToolRunResponse,\n schemaPropertyCount,\n schemaType,\n ToolMetaPill,\n ToolRunner,\n toolOriginLabel,\n} from \"./tool-runner\";\n\nexport function ToolsPage(props: {\n agents: StudioConfig[\"agents\"];\n selectedAgentId: string;\n summary: StudioAgentToolsSummary | undefined;\n enabled: boolean;\n loading: boolean;\n onSelectAgent: (agentId: string) => void;\n}) {\n const selectedAgent =\n props.agents.find((agent) => agent.id === props.selectedAgentId) ?? props.agents[0];\n const tools = useMemo(() => props.summary?.tools ?? [], [props.summary]);\n const [selectedToolName, setSelectedToolName] = useState(\"\");\n const [argsText, setArgsText] = useState(\"{}\");\n const [runState, setRunState] = useState<\"idle\" | \"running\">(\"idle\");\n const [runResponse, setRunResponse] = useState<StudioToolRunResponse | undefined>();\n const [runError, setRunError] = useState(\"\");\n const selectedTool = useMemo(\n () => tools.find((tool) => tool.name === selectedToolName) ?? tools[0],\n [selectedToolName, tools],\n );\n const selectedToolRunKey =\n selectedAgent === undefined || selectedTool === undefined\n ? \"\"\n : `${selectedAgent.id}:${selectedTool.name}`;\n const selectedToolRunKeyRef = useRef(selectedToolRunKey);\n const runRequestIdRef = useRef(0);\n const toolTotals = summarizeTools(tools);\n\n useEffect(() => {\n if (tools.length === 0) {\n setSelectedToolName(\"\");\n return;\n }\n if (!tools.some((tool) => tool.name === selectedToolName)) {\n setSelectedToolName(tools[0]?.name ?? \"\");\n }\n }, [selectedToolName, tools]);\n\n useEffect(() => {\n if (selectedToolRunKeyRef.current === selectedToolRunKey) {\n return;\n }\n selectedToolRunKeyRef.current = selectedToolRunKey;\n runRequestIdRef.current += 1;\n setRunState(\"idle\");\n setRunError(\"\");\n setRunResponse(undefined);\n }, [selectedToolRunKey]);\n\n async function runSelectedTool() {\n if (selectedAgent === undefined || selectedTool === undefined) {\n return;\n }\n let args: unknown;\n try {\n args = JSON.parse(argsText);\n } catch (parseError) {\n setRunError(parseError instanceof Error ? parseError.message : String(parseError));\n setRunResponse(undefined);\n return;\n }\n\n setRunState(\"running\");\n setRunError(\"\");\n setRunResponse(undefined);\n const runToolKey = selectedToolRunKey;\n const requestId = runRequestIdRef.current + 1;\n runRequestIdRef.current = requestId;\n const isCurrentRun = () =>\n runRequestIdRef.current === requestId && selectedToolRunKeyRef.current === runToolKey;\n try {\n const response = await fetch(\n `/agents/${encodeURIComponent(selectedAgent.id)}/tools/${encodeURIComponent(\n selectedTool.name,\n )}/runs`,\n {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify({ args }),\n },\n );\n const rawBody = await response.json();\n if (!isCurrentRun()) {\n return;\n }\n const body = parseStudioToolRunResponse(rawBody);\n if (body === undefined) {\n setRunError(`Unexpected Studio tool run response: ${formatJson(rawBody)}`);\n return;\n }\n setRunResponse(body);\n if (!response.ok || body.status === \"error\") {\n setRunError(formatJson(body.error ?? body));\n }\n } catch (error) {\n if (isCurrentRun()) {\n setRunError(error instanceof Error ? error.message : String(error));\n }\n } finally {\n if (isCurrentRun()) {\n setRunState(\"idle\");\n }\n }\n }\n\n return (\n <StudioPageShell className=\"grid-rows-[auto_minmax(0,1fr)]\" aria-label=\"Tools\">\n <StudioPageHeader\n title=\"Tools\"\n description=\"Tool definitions registered on Studio agents, including approval policy and input schema.\"\n action={\n <div className=\"flex min-w-0 flex-wrap justify-end gap-2 max-sm:justify-start\">\n <StudioHeaderMetric label=\"tools\" value={toolTotals.total} />\n <StudioHeaderMetric label=\"mcp\" value={toolTotals.mcp} />\n <StudioHeaderMetric label=\"static\" value={toolTotals.static} />\n <StudioHeaderMetric label=\"dynamic\" value={toolTotals.dynamic} />\n <StudioHeaderMetric label=\"approvals\" value={toolTotals.approvals} />\n {props.agents.length > 1 ? (\n <Select value={selectedAgent?.id ?? \"\"} onValueChange={props.onSelectAgent}>\n <SelectTrigger className=\"h-8 min-h-8 w-64 rounded-md border-border text-xs max-sm:w-full\">\n <SelectValue placeholder=\"Agent\" />\n </SelectTrigger>\n <SelectContent align=\"end\">\n {props.agents.map((agent) => (\n <SelectItem value={agent.id} key={agent.id}>\n {agent.name ?? agent.id}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n ) : null}\n </div>\n }\n />\n\n <StudioPageContent className=\"overflow-auto\">\n {!props.enabled ? (\n <StudioEmptyState\n title=\"Tools unavailable\"\n text=\"No registered Studio agent exposes static or dynamic tools.\"\n />\n ) : props.loading ? (\n <StudioEmptyState title=\"Loading tools\" text=\"Reading registered tool metadata.\" />\n ) : tools.length === 0 ? (\n <StudioEmptyState title=\"No tools\" text=\"The selected agent has no registered tools.\" />\n ) : (\n <div className=\"grid w-full gap-5\">\n <ToolRegistryTable\n selectedToolName={selectedTool?.name ?? \"\"}\n tools={tools}\n onSelectTool={setSelectedToolName}\n />\n <ToolRunner\n argsText={argsText}\n runError={runError}\n runResponse={runResponse}\n runState={runState}\n selectedTool={selectedTool}\n onArgsTextChange={setArgsText}\n onRun={() => void runSelectedTool()}\n />\n </div>\n )}\n </StudioPageContent>\n </StudioPageShell>\n );\n}\n\nfunction ToolRegistryTable(props: {\n tools: StudioAgentToolMetadata[];\n selectedToolName: string;\n onSelectTool: (toolName: string) => void;\n}) {\n return (\n <div className=\"min-w-[1040px]\">\n <table className=\"w-full border-separate border-spacing-0 text-left\">\n <thead className=\"sticky top-0 z-10 bg-header backdrop-blur\">\n <tr>\n <ToolTableHead>Tool</ToolTableHead>\n <ToolTableHead>Origin</ToolTableHead>\n <ToolTableHead>Schema</ToolTableHead>\n <ToolTableHead>Approval</ToolTableHead>\n <ToolTableHead>Run</ToolTableHead>\n </tr>\n </thead>\n <tbody>\n {props.tools.map((tool) => (\n <ToolRegistryRow\n active={props.selectedToolName === tool.name}\n key={`${tool.source}:${tool.name}`}\n tool={tool}\n onSelectTool={props.onSelectTool}\n />\n ))}\n </tbody>\n </table>\n </div>\n );\n}\n\nfunction ToolRegistryRow(props: {\n tool: StudioAgentToolMetadata;\n active: boolean;\n onSelectTool: (toolName: string) => void;\n}) {\n const propertyCount = schemaPropertyCount(props.tool.parameters);\n return (\n <tr>\n <ToolTableCell>\n <div className=\"grid min-w-0 gap-1.5\">\n <div className=\"flex min-w-0 items-center gap-2\">\n <span className=\"min-w-0 truncate text-sm font-semibold text-foreground\">\n {props.tool.name}\n </span>\n {props.active ? <Badge className={selectedBadge}>selected</Badge> : null}\n </div>\n <span className=\"min-w-0 truncate text-xs font-medium text-muted-foreground\">\n {props.tool.agentId}\n </span>\n <p className=\"m-0 max-w-[64ch] truncate text-sm leading-6 text-muted-foreground\">\n {props.tool.description}\n </p>\n </div>\n </ToolTableCell>\n <ToolTableCell>\n <Badge className={originBadgeClass(props.tool)}>{toolOriginLabel(props.tool)}</Badge>\n </ToolTableCell>\n <ToolTableCell>\n <div className=\"flex min-w-0 flex-wrap gap-2\">\n <ToolMetaPill>{schemaType(props.tool.parameters)}</ToolMetaPill>\n <ToolMetaPill>\n {propertyCount} {propertyCount === 1 ? \"field\" : \"fields\"}\n </ToolMetaPill>\n </div>\n </ToolTableCell>\n <ToolTableCell>\n <div className=\"grid min-w-0 gap-1.5\">\n <Badge className={approvalBadgeClass(props.tool.approval.required)}>\n {props.tool.approval.required ? \"required\" : \"none\"}\n </Badge>\n {props.tool.approval.reason === undefined ? null : (\n <span\n className=\"max-w-[280px] truncate text-xs leading-5 text-muted-foreground\"\n title={props.tool.approval.reason}\n >\n {props.tool.approval.reason}\n </span>\n )}\n </div>\n </ToolTableCell>\n <ToolTableCell>\n <Button\n className=\"h-8 min-h-8 rounded-md px-3 text-xs\"\n type=\"button\"\n variant={props.active ? \"secondary\" : \"ghost\"}\n onClick={() => props.onSelectTool(props.tool.name)}\n >\n {props.active ? \"Selected\" : \"Use\"}\n </Button>\n </ToolTableCell>\n </tr>\n );\n}\n\nfunction ToolTableHead(props: { children: string }) {\n return (\n <th className=\"border-b border-hair py-2.5 pr-5 text-xs font-semibold uppercase tracking-[0.16em] text-muted-foreground first:pl-0\">\n {props.children}\n </th>\n );\n}\n\nfunction ToolTableCell(props: { children: ReactNode }) {\n return (\n <td className=\"border-b border-hair py-3.5 pr-5 align-top first:pl-0\">{props.children}</td>\n );\n}\n\nfunction summarizeTools(tools: StudioAgentToolMetadata[]) {\n return tools.reduce(\n (totals, tool) => {\n totals.total += 1;\n if (tool.source === \"dynamic\") {\n totals.dynamic += 1;\n } else {\n totals.static += 1;\n }\n if (tool.mcpServerName !== undefined) {\n totals.mcp += 1;\n }\n if (tool.approval.required) {\n totals.approvals += 1;\n }\n return totals;\n },\n { approvals: 0, dynamic: 0, mcp: 0, static: 0, total: 0 },\n );\n}\n\nconst selectedBadge = \"border-hair bg-row-selected text-foreground\";\n"],"mappings":"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"}