@schlenkr/ragents 0.1.13 → 0.1.15

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 (145) hide show
  1. package/apps/server/package.json +1 -1
  2. package/apps/server/src/api/contracts.ts +19 -1
  3. package/apps/server/src/api/core-methods.ts +12 -0
  4. package/apps/server/src/chat-handler.ts +19 -0
  5. package/apps/server/src/host-api.json +2 -0
  6. package/apps/server/src/host-api.ts +2 -2
  7. package/apps/server/src/plugin-build/build.ts +1 -1
  8. package/apps/server/src/plugin-support/actor-programs/app-project.ts +61 -17
  9. package/apps/server/src/plugin-support/actor-programs/contract.ts +18 -1
  10. package/apps/server/src/plugin-support/actor-programs/service.ts +22 -1
  11. package/apps/server/src/plugin-support/plugin-folder.ts +14 -1
  12. package/apps/server/src/plugin-support/run-scripts.ts +27 -2
  13. package/apps/server/src/profile/compose.ts +2 -0
  14. package/apps/server/src/provider.ts +31 -6
  15. package/apps/server/src/ragents/chat-projection.ts +7 -0
  16. package/apps/server/src/ragents/global-chat.ts +5 -1
  17. package/apps/server/src/ragents/run-script-tools.ts +66 -0
  18. package/apps/server/src/ragents/session.ts +122 -60
  19. package/apps/server/src/title-compactor.ts +1 -1
  20. package/apps/web/dist/assets/{highlighted-body-KPVGNVTW-CpPi6QLr.js → highlighted-body-KPVGNVTW-BwD4uYEe.js} +1 -1
  21. package/apps/web/dist/assets/main-KBrc5Q77.js +11 -0
  22. package/apps/web/dist/assets/{mermaid-HWGCJPDP-q-mf1kLN.js → mermaid-HWGCJPDP-CSCkaArr.js} +88 -88
  23. package/apps/web/dist/assets/runPanel-BjG5NBKm.js +26 -0
  24. package/apps/web/dist/help/guide-clients.html +21 -4
  25. package/apps/web/dist/help/guide-clients.md +23 -4
  26. package/apps/web/dist/help/guide-plugins.html +12 -2
  27. package/apps/web/dist/help/guide-plugins.md +9 -2
  28. package/apps/web/dist/help/guide-programs.html +8 -2
  29. package/apps/web/dist/help/guide-programs.md +9 -2
  30. package/apps/web/dist/help/guide-runtime.html +3 -2
  31. package/apps/web/dist/help/guide-runtime.md +3 -2
  32. package/apps/web/dist/help/index.html +1 -1
  33. package/apps/web/dist/help/mini-app.css +16 -2
  34. package/apps/web/dist/host-web.json +13 -13
  35. package/apps/web/dist/index.html +2 -2
  36. package/apps/web/dist/run-panel.html +2 -2
  37. package/apps/web/package.json +1 -1
  38. package/apps/web/src/App.tsx +12 -1
  39. package/apps/web/src/PluginRegistry.tsx +2 -2
  40. package/apps/web/src/SessionList.tsx +7 -6
  41. package/apps/web/src/SettingsModal.tsx +3 -3
  42. package/apps/web/src/actor-programs/client-ui/FilePicker.tsx +1 -1
  43. package/apps/web/src/api.ts +2 -0
  44. package/apps/web/src/run-overview.ts +1 -1
  45. package/apps/web/src/run-panel/RunPanelApp.tsx +1 -1
  46. package/apps/web/src/run-panel/RunPanelMenu.tsx +47 -11
  47. package/apps/web/src/ui/relative-time.ts +1 -1
  48. package/bundles/ragents.activity/ragents-bundle.json +1 -1
  49. package/bundles/ragents.actor-programs/ragents-bundle.json +4 -2
  50. package/bundles/ragents.actor-programs/server/index.js +437 -24
  51. package/bundles/ragents.actor-programs/server/index.js.map +4 -4
  52. package/bundles/ragents.actor-programs/web/index.js.map +1 -1
  53. package/bundles/ragents.ask/ragents-bundle.json +2 -2
  54. package/bundles/ragents.ask/server/index.js +1 -0
  55. package/bundles/ragents.ask/server/index.js.map +2 -2
  56. package/bundles/ragents.browser/ragents-bundle.json +1 -1
  57. package/bundles/ragents.documents/ragents-bundle.json +2 -2
  58. package/bundles/ragents.documents/web/classes.json +1 -1
  59. package/bundles/ragents.documents/web/index.js +1 -1
  60. package/bundles/ragents.documents/web/index.js.map +2 -2
  61. package/bundles/ragents.lsp-fsharp/ragents-bundle.json +1 -1
  62. package/bundles/ragents.lsp-roslyn/ragents-bundle.json +1 -1
  63. package/bundles/ragents.lsp-typescript/ragents-bundle.json +1 -1
  64. package/bundles/ragents.model-relay/ragents-bundle.json +1 -1
  65. package/bundles/ragents.orchestration/ragents-bundle.json +7 -4
  66. package/bundles/ragents.orchestration/server/chunks/chunk-QS3WJ3D7.js +11 -0
  67. package/bundles/ragents.orchestration/server/chunks/chunk-QS3WJ3D7.js.map +7 -0
  68. package/bundles/ragents.orchestration/server/exports/server/contract.js +9 -0
  69. package/bundles/ragents.orchestration/server/exports/server/contract.js.map +7 -0
  70. package/bundles/ragents.orchestration/server/index.js +49 -3
  71. package/bundles/ragents.orchestration/server/index.js.map +2 -2
  72. package/bundles/ragents.orchestration/surface.hbs +5 -0
  73. package/bundles/ragents.orchestration/web/index.js +3 -3
  74. package/bundles/ragents.orchestration/web/index.js.map +2 -2
  75. package/bundles/ragents.overseer/ragents-bundle.json +4 -3
  76. package/bundles/ragents.overseer/web/classes.json +1 -1
  77. package/bundles/ragents.overseer/web/index.js +1 -1
  78. package/bundles/ragents.overseer/web/index.js.map +4 -4
  79. package/bundles/ragents.processes/ragents-bundle.json +2 -2
  80. package/bundles/ragents.processes/web/classes.json +1 -1
  81. package/bundles/ragents.processes/web/index.js +1 -1
  82. package/bundles/ragents.processes/web/index.js.map +2 -2
  83. package/bundles/ragents.product/ragents-bundle.json +1 -1
  84. package/bundles/ragents.profile-distribution/ragents-bundle.json +1 -1
  85. package/bundles/ragents.reference/actors/notebook/package.json +16 -0
  86. package/bundles/ragents.reference/actors/notebook/src/client.tsx +31 -0
  87. package/bundles/ragents.reference/actors/notebook/src/server.ts +27 -0
  88. package/bundles/ragents.reference/actors/notebook/tests/program.test.ts +27 -0
  89. package/bundles/ragents.reference/ragents-bundle.json +4 -3
  90. package/bundles/ragents.reference/run-scripts/quick-note/RUN.md +14 -0
  91. package/bundles/ragents.reference/run-scripts/quick-note/package.json +9 -0
  92. package/bundles/ragents.reference/run-scripts/quick-note/src/server.ts +29 -0
  93. package/bundles/ragents.reference/run-scripts/quick-note/tests/program.test.ts +43 -0
  94. package/bundles/ragents.reference/run-scripts/run-roster/RUN.md +19 -0
  95. package/bundles/ragents.reference/run-scripts/run-roster/package.json +9 -0
  96. package/bundles/ragents.reference/run-scripts/run-roster/src/server.ts +26 -0
  97. package/bundles/ragents.reference/run-scripts/run-roster/tests/program.test.ts +47 -0
  98. package/bundles/ragents.todo/ragents-bundle.json +1 -1
  99. package/bundles/ragents.transcript/ragents-bundle.json +1 -1
  100. package/bundles/ragents.watch/ragents-bundle.json +1 -1
  101. package/bundles/ragents.workspace/ragents-bundle.json +2 -2
  102. package/bundles/ragents.workspace/web/classes.json +1 -1
  103. package/bundles/ragents.workspace/web/index.js +1 -1
  104. package/bundles/ragents.workspace/web/index.js.map +2 -2
  105. package/package.json +3 -3
  106. package/packages/ragents/src/domain/vocabulary.ts +4 -0
  107. package/packages/ragents/src/index.ts +3 -1
  108. package/packages/ragents/src/plugin-host.ts +62 -10
  109. package/packages/ragents/src/plugin-types.ts +11 -0
  110. package/packages/ragents/src/runtime/guards.ts +2 -1
  111. package/packages/ragents/src/typescript/async-compiler.ts +11 -1
  112. package/plugins/ragents.actor-programs/server/index.ts +3 -0
  113. package/plugins/ragents.actor-programs/server/runtime.ts +424 -28
  114. package/plugins/ragents.actor-programs/server/script-state.ts +54 -0
  115. package/plugins/ragents.actor-programs/server/tool-contributor.ts +2 -0
  116. package/plugins/ragents.ask/server/ask-tool.ts +1 -0
  117. package/plugins/ragents.documents/web/DocumentViewer.tsx +2 -2
  118. package/plugins/ragents.orchestration/ragents-plugin.json +1 -0
  119. package/plugins/ragents.orchestration/server/contract.ts +14 -0
  120. package/plugins/ragents.orchestration/server/index.ts +4 -1
  121. package/plugins/ragents.orchestration/server/surface-tool.ts +58 -2
  122. package/plugins/ragents.orchestration/surface.hbs +5 -0
  123. package/plugins/ragents.orchestration/web/ExecutionsPanel.tsx +1 -1
  124. package/plugins/ragents.orchestration/web/FlowInspector.tsx +1 -1
  125. package/plugins/ragents.orchestration/web/JournalStatus.tsx +1 -1
  126. package/plugins/ragents.orchestration/web/format.ts +1 -1
  127. package/plugins/ragents.overseer/web/index.tsx +51 -3
  128. package/plugins/ragents.processes/web/processes.ts +1 -1
  129. package/plugins/ragents.reference/actors/notebook/package.json +16 -0
  130. package/plugins/ragents.reference/actors/notebook/src/client.tsx +31 -0
  131. package/plugins/ragents.reference/actors/notebook/src/server.ts +27 -0
  132. package/plugins/ragents.reference/actors/notebook/tests/program.test.ts +27 -0
  133. package/plugins/ragents.reference/run-scripts/quick-note/RUN.md +14 -0
  134. package/plugins/ragents.reference/run-scripts/quick-note/package.json +9 -0
  135. package/plugins/ragents.reference/run-scripts/quick-note/src/server.ts +29 -0
  136. package/plugins/ragents.reference/run-scripts/quick-note/tests/program.test.ts +43 -0
  137. package/plugins/ragents.reference/run-scripts/run-roster/RUN.md +19 -0
  138. package/plugins/ragents.reference/run-scripts/run-roster/package.json +9 -0
  139. package/plugins/ragents.reference/run-scripts/run-roster/src/server.ts +26 -0
  140. package/plugins/ragents.reference/run-scripts/run-roster/tests/program.test.ts +47 -0
  141. package/plugins/ragents.workspace/web/FileBrowser.tsx +1 -1
  142. package/scripts/agent/agent-cli.ts +46 -2
  143. package/scripts/package/ragents.mjs +3 -1
  144. package/apps/web/dist/assets/main-DJmCHGzM.js +0 -11
  145. package/apps/web/dist/assets/runPanel-nk_aMxSn.js +0 -21
@@ -0,0 +1,26 @@
1
+ import{a as _,H as B,u as X,r as o,j as e,B as E,I as Fe,J as Me,K as De,v as Ue,l as W,m as Y,t as He,k as $e,P as Be,G as fe,L as Ve,p as Z,q as pe,i as qe,N as xe,O as le,T as Je,V as Ge,A as ce,Y as Ke,Z as Qe,_ as We,$ as Ye,s as Ze,a0 as Xe,e as et,a1 as tt,a2 as nt,x as st,y as rt,a3 as ot,a4 as at,a5 as it,z as lt,Q as ct,a6 as dt,a7 as ut,F as ht}from"./mermaid-HWGCJPDP-CSCkaArr.js";/**
2
+ * @license lucide-react v1.46.0 - ISC
3
+ *
4
+ * This source code is licensed under the ISC license.
5
+ * See the LICENSE file in the root directory of this source tree.
6
+ */const me={name:"ellipsis-vertical",size:24,node:[["circle",{cx:"12",cy:"12",r:"1",key:"41hilf"}],["circle",{cx:"12",cy:"5",r:"1",key:"gxeob9"}],["circle",{cx:"12",cy:"19",r:"1",key:"lyex9k"}]],aliases:["more-vertical"]};me.node;const ft=_(me);/**
7
+ * @license lucide-react v1.46.0 - ISC
8
+ *
9
+ * This source code is licensed under the ISC license.
10
+ * See the LICENSE file in the root directory of this source tree.
11
+ */const ve={name:"external-link",size:24,node:[["path",{d:"M15 3h6v6",key:"1q9fwt"}],["path",{d:"M10 14 21 3",key:"gplh6r"}],["path",{d:"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6",key:"a6xqqp"}]]};ve.node;const pt=_(ve);/**
12
+ * @license lucide-react v1.46.0 - ISC
13
+ *
14
+ * This source code is licensed under the ISC license.
15
+ * See the LICENSE file in the root directory of this source tree.
16
+ */const ge={name:"layout-grid",size:24,node:[["rect",{width:"7",height:"7",x:"3",y:"3",rx:"1",key:"1g98yp"}],["rect",{width:"7",height:"7",x:"14",y:"3",rx:"1",key:"6d4xhi"}],["rect",{width:"7",height:"7",x:"14",y:"14",rx:"1",key:"nxv5o0"}],["rect",{width:"7",height:"7",x:"3",y:"14",rx:"1",key:"1bb6yr"}]]};ge.node;const xt=_(ge);/**
17
+ * @license lucide-react v1.46.0 - ISC
18
+ *
19
+ * This source code is licensed under the ISC license.
20
+ * See the LICENSE file in the root directory of this source tree.
21
+ */const we={name:"log-out",size:24,node:[["path",{d:"m16 17 5-5-5-5",key:"1bji2h"}],["path",{d:"M21 12H9",key:"dn1m92"}],["path",{d:"M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4",key:"1uf3rs"}]]};we.node;const mt=_(we);/**
22
+ * @license lucide-react v1.46.0 - ISC
23
+ *
24
+ * This source code is licensed under the ISC license.
25
+ * See the LICENSE file in the root directory of this source tree.
26
+ */const be={name:"play",size:24,node:[["path",{d:"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z",key:"10ikf1"}]]};be.node;const vt=_(be),O="flex w-full cursor-pointer items-center gap-2.5 rounded-md px-2 py-1.5 text-left hover:bg-accent focus-visible:outline-2 focus-visible:outline-ring/60 focus-visible:-outline-offset-2 disabled:cursor-default disabled:opacity-50 disabled:hover:bg-transparent [&>svg]:size-4 [&>svg]:flex-none [&>svg]:text-muted-foreground",K=t=>t instanceof Error?t.message:String(t);function Q({onOpenSettings:t,runId:a}){const r=B(),n=X(),[l,c]=o.useState(!1),[u,f]=o.useState(!1),[m,x]=o.useState(),[d,b]=o.useState(),k=o.useRef(null),R=o.useId(),P=i=>{var p;return i.reason==="outside-press"&&i.event.target instanceof Node&&((p=k.current)==null?void 0:p.contains(i.event.target))===!0},v=()=>{c(!1),b(void 0),x(void 0)},g=()=>{if(r.kind==="vscode"){r.requestLogout(),c(!1);return}f(!0),x(void 0),n.logout().then(()=>c(!1)).catch(i=>x(K(i))).finally(()=>f(!1))},V=i=>{b({kind:"loading"}),x(void 0),W.call(Y.runs.scripts,{runId:i}).then(p=>b({kind:"ready",scripts:p})).catch(p=>{b({kind:"ready",scripts:[]}),x(K(p))})},z=(i,p)=>{f(!0),x(void 0),W.call(Y.runs.startScript,{runId:i,entry:p,input:null}).then(v).catch(F=>x(K(F))).finally(()=>f(!1))},h=a!==void 0&&n.can("runs.write")?a:void 0;return e.jsxs(e.Fragment,{children:[e.jsx(E,{"aria-controls":l?R:void 0,"aria-expanded":l,"aria-haspopup":"dialog","aria-label":"Panel menu",className:"self-center",onClick:()=>l?v():c(!0),ref:k,size:"icon-lg",title:"Menu",variant:"ghost",children:e.jsx(ft,{})}),e.jsx(Fe,{onOpenChange:(i,p)=>{!i&&P(p)||(i?c(!0):v())},open:l,children:e.jsxs(Me,{align:"end",anchor:k,"aria-label":"Panel menu",className:"w-[260px] gap-0 p-1 text-[0.8rem]",collisionPadding:8,dim:!0,id:R,role:"dialog",side:"bottom",children:[d&&h!==void 0?e.jsxs(e.Fragment,{children:[e.jsxs("button",{className:O,onClick:()=>{b(void 0),x(void 0)},type:"button",children:[e.jsx(De,{}),"Run script"]}),e.jsxs("div",{"aria-label":"Run scripts",className:"grid max-h-[50vh] overflow-auto border-t border-border-soft pt-1",role:"list",children:[d.kind==="loading"&&e.jsx("p",{className:"px-2 py-1.5 text-muted-foreground",children:"Loading run scripts ..."}),d.kind==="ready"&&d.scripts.length===0&&!m&&e.jsx("p",{className:"px-2 py-1.5 text-muted-foreground",children:"This profile has no run scripts for you."}),d.kind==="ready"&&d.scripts.map(i=>e.jsx("button",{className:O,disabled:u||!i.available,onClick:()=>z(h,i.id),role:"listitem",title:i.reason??i.description,type:"button",children:e.jsxs("span",{className:"grid min-w-0",children:[e.jsx("span",{className:"truncate",children:i.title}),e.jsx("span",{className:"line-clamp-2 text-[0.68rem] text-muted-foreground",children:i.available?i.description:i.reason})]})},i.id))]})]}):e.jsxs(e.Fragment,{children:[e.jsxs("button",{className:O,onClick:()=>{v(),t()},type:"button",children:[e.jsx(Ue,{}),"Settings"]}),h!==void 0&&e.jsxs("button",{className:O,onClick:()=>V(h),type:"button",children:[e.jsx(vt,{}),"Run script"]}),r.kind==="vscode"&&e.jsxs("button",{className:O,onClick:()=>{v(),r.openExternal(new URL("/",window.location.href).toString())},type:"button",children:[e.jsx(pt,{}),"Open in browser"]}),n.enabled&&n.user&&e.jsxs("button",{className:O,disabled:u,onClick:g,title:n.user.id,type:"button",children:[e.jsx(mt,{}),e.jsxs("span",{className:"grid min-w-0",children:[e.jsx("span",{children:"Sign out"}),e.jsx("span",{className:"truncate text-[0.68rem] text-muted-foreground",children:n.user.label})]})]})]}),m&&e.jsx("p",{className:"px-2 py-1.5 text-[0.72rem] text-destructive",role:"alert",children:m})]})})]})}const gt=5e3;function je(t){const[a,r]=o.useState([]),[n,l]=o.useState(!1),c=o.useRef(void 0),u=o.useRef(!1),f=o.useCallback(()=>{if(!t)return Promise.resolve();if(c.current)return u.current=!0,c.current;const m=async()=>{do{u.current=!1;try{r(await He()),l(!1)}catch{l(!0)}}while(u.current)};return c.current=m().finally(()=>{c.current=void 0}),c.current},[t]);return o.useEffect(()=>{if(!t)return;f();const m=W.subscribe(Y.channels.runs,{},()=>void f()),x=setInterval(()=>void f(),gt);return()=>{m(),clearInterval(x)}},[t,f]),{sessions:a,unreachable:n,refresh:f}}const Se="relative z-[80] flex h-header flex-none items-stretch border-b border-border bg-shell shadow-bar",de="max-w-[120px] self-center truncate rounded-full bg-secondary px-2 py-0.5 text-[0.66rem] font-semibold text-muted-foreground",wt="min-w-0 flex-1 self-center truncate px-1.5 text-[0.82rem] font-semibold",bt="Stopped in the run panel",jt=5e3,S="New run",St="relative z-[80] flex h-header flex-none items-center gap-2 border-b border-border bg-shell px-3 shadow-bar",ye="m-auto max-w-[420px] p-6 text-center text-muted-foreground",yt=new Set,kt=()=>({id:crypto.randomUUID(),title:S,updatedAt:Date.now()}),ke=(t,a="Run")=>({id:t,title:a,updatedAt:Date.now()}),Nt={kind:"working",title:"Loading profile",detail:"Loading the server's interface."},Rt={kind:"working",title:"Starting run",detail:"Creating the new run."},ue={kind:"working",title:"Starting run",detail:"Starting the template."},Ct={kind:"waiting",title:"No run selected",detail:"On the Start page you start a new run or open an existing one."},Et={kind:"error",title:"No runs enabled",detail:"No runs are enabled for this user account."};function It({location:t}){const a=$e(),r=t.layout==="app";if(a.status==="loading")return e.jsx(y,{headless:r,state:Nt});if(a.status==="failed")return e.jsx(y,{headless:r,state:{kind:"error",title:"The profile could not be loaded",detail:a.error},children:e.jsx(E,{onClick:()=>window.location.reload(),size:"sm",variant:"outline",children:"Reload"})});const n=t.layout==="app"?e.jsx(Tt,{elementId:t.elementId,registry:a.registry,runId:t.runId}):e.jsx(Ot,{connection:t.connection,initialRunId:t.runId,registry:a.registry});return a.failures.length===0?n:e.jsxs("div",{className:"flex h-full flex-col",children:[e.jsx(Be,{failures:a.failures}),e.jsx("div",{className:"flex min-h-0 flex-1 flex-col",children:n})]})}function Ot({connection:t,initialRunId:a,registry:r}){var ie;const n=B(),l=X(),c=l.can("runs.read"),u=c&&l.can("runs.write"),f=u&&l.can("runs.create"),m=f||u&&r.scriptEntries.some(s=>pe(l,s.id)),x=qe((ie=l.user)==null?void 0:ie.id),[d,b]=o.useState(a),[k,R]=o.useState(),[P,v]=o.useState(),g=o.useCallback(()=>v(s=>s===d?void 0:s),[d]),[V,z]=o.useState(),[h,i]=o.useState(),[p,F]=o.useState(),q=o.useRef(void 0),j=o.useCallback(s=>{q.current=s==null?void 0:s.runId,F(s)},[]),[ee,J]=o.useState(),[L,te]=o.useState(!1),[ne,se]=o.useState(),G=o.useCallback(()=>te(!0),[]),{sessions:re,unreachable:Re,refresh:Ce}=je(c&&!h&&!p),[Ee,Ie]=o.useState(null),[Oe,Pe]=o.useState(null),T=o.useCallback((s,w)=>{var $;const N=($=r.startEntries.find(ze=>ze.id===w))==null?void 0:$.fixedStartOptions;i({session:kt(),startOptions:s&&xe(s,N),entryId:w})},[r]),Le=o.useCallback(()=>T(),[T]),A=o.useCallback((s,w)=>{i(void 0),j(void 0),z(w),b(s),v(n.kind==="vscode"?s:void 0)},[n.kind,j]),oe=o.useCallback(s=>{i(void 0),j(s),Pt(s,r,l).then(()=>{q.current===s.runId&&A(s.runId)},w=>{q.current===s.runId&&F({...s,error:w instanceof Error?w.message:String(w)})})},[l,A,r,j]),Te=o.useCallback(s=>{v(void 0),R(void 0),b(s)},[]),M=o.useCallback(()=>{v(void 0),i(void 0),j(void 0),J(void 0),n.kind==="vscode"?n.notify({type:"showStart"}):b(void 0)},[n,j]);o.useLayoutEffect(()=>{if(P){if(L||h){g();return}return window.addEventListener("pointerdown",g,!0),window.addEventListener("keydown",g,!0),window.addEventListener("blur",g),()=>{window.removeEventListener("pointerdown",g,!0),window.removeEventListener("keydown",g,!0),window.removeEventListener("blur",g)}}},[h,P,L,g]),o.useEffect(()=>n.onCommand(s=>{if(s.type==="selectRun"&&(v(void 0),i(void 0),j(void 0),J(void 0),z(void 0),R(void 0),b(s.runId??void 0)),s.type!=="newRun")return;if(n.kind!=="vscode"){m&&T(s.startOptions,s.entryId);return}const w=m?s.entryId===void 0&&!f?"Free runs are not enabled for this user account.":void 0:"New runs are not enabled for this user account.";if(J(w),w!==void 0)return;const N=r.startEntries.find($=>$.id===s.entryId);if(R((N==null?void 0:N.title)??S),s.entryId===void 0){A(crypto.randomUUID(),s.startOptions);return}if(N!==void 0&&r.guideFor(N)!==void 0){j(void 0),T(s.startOptions,N.id);return}oe({runId:crypto.randomUUID(),entryId:s.entryId,startOptions:s.startOptions})}),[m,f,n,A,r,j,T,oe]),o.useEffect(()=>{n.notify({type:"ready"})},[n]),o.useEffect(()=>{n.notify({type:"runChanged",runId:d??null})},[n,d]);const D=L&&e.jsx(Ze,{onClose:()=>te(!1),registry:r}),I=s=>e.jsxs(e.Fragment,{children:[e.jsx(E,{"aria-label":"Back to Start",className:"self-center",onClick:M,size:"icon-lg",title:"Back to Start",variant:"ghost",children:e.jsx(le,{})}),e.jsx("strong",{className:wt,children:s}),t&&e.jsx("span",{className:de,title:`Server ${t}`,children:t}),e.jsx(Q,{onOpenSettings:G})]}),U=e.jsx(E,{onClick:M,size:"sm",variant:"outline",children:"Back to Start"}),ae=h&&e.jsx(Z,{initialStartOptions:h.startOptions,onStarted:()=>{A(h.session.id),R(s=>s??S),Ce()},registry:r,session:h.session,startDialog:{onClose:n.kind==="vscode"?M:()=>i(void 0),initialEntryId:h.entryId}},h.session.id);if(p)return e.jsxs(e.Fragment,{children:[p.error===void 0?e.jsx(y,{header:I(k??S),state:ue}):e.jsx(y,{header:I(k??S),state:{kind:"error",title:"The run could not be started",detail:p.error},children:U}),D]});if(n.kind==="vscode"&&h)return e.jsxs(e.Fragment,{children:[e.jsx(y,{header:I(k??S),state:ue}),ae,D]});if(n.kind==="vscode"&&!(c&&d))return e.jsxs(e.Fragment,{children:[c?ee!==void 0?e.jsx(y,{header:I(S),state:{kind:"error",title:"No new run possible",detail:ee},children:U}):e.jsx(Lt,{header:I(S),children:U}):e.jsx(y,{header:I(S),state:Et,children:U}),D]});const H=re.find(s=>s.id===d),Ae=()=>{d!==void 0&&(se(void 0),Xe(d,bt).catch(s=>se(`Stop failed: ${s instanceof Error?s.message:String(s)}`)))},_e=c?e.jsx(et,{activeId:d,onCreate:m?Le:void 0,onSelect:Te,onToggleSelected:()=>{},registry:r,seenRevisions:x.revisions,selectMode:!1,selectedIds:yt,sessions:re}):e.jsx("p",{className:ye,children:"No runs are enabled for this user account."});return e.jsxs("div",{className:"flex h-full flex-col bg-[image:var(--surface-backdrop)]",children:[c&&d?e.jsxs(e.Fragment,{children:[e.jsxs("header",{className:Se,children:[e.jsx(E,{"aria-label":"Back to Start",className:"self-center",onClick:M,size:"icon-lg",title:"Back to Start",variant:"ghost",children:e.jsx(le,{})}),e.jsx("div",{"aria-label":"Run title bar",className:"flex min-w-0 flex-1 items-stretch overflow-x-auto no-scrollbar",ref:Ie,role:"region"}),t&&e.jsx("span",{className:de,title:`Server ${t}`,children:t}),e.jsx(Je,{className:"self-center px-1.5",state:H!=null&&H.running?"running":"idle"}),e.jsx(Ge,{className:"self-center",disabled:!u,label:"Stop run",onClick:Ae,size:"icon-lg",title:"Stop the run with all agents and flows"}),e.jsx("div",{"aria-label":"Panel tools",className:"flex flex-none items-center empty:hidden",ref:Pe,role:"toolbar"}),e.jsx(Q,{onOpenSettings:G,runId:d})]}),ne&&e.jsx(ce,{variant:"destructive",children:ne}),e.jsx("main",{className:"relative z-1 flex min-h-0 min-w-0 flex-1 @container/chat-content",children:e.jsx(Z,{autoFocusChat:P===d&&!L&&!h,onAutoFocusChatSettled:g,toolbarContainer:Oe,headerContainer:Ee,initialStartOptions:V,layout:"panel",onViewed:x.markViewed,registry:r,session:H??ke(d,k),viewing:!h&&!L},d)})]}):e.jsxs(e.Fragment,{children:[e.jsxs("header",{className:St,children:[e.jsx(xt,{"aria-hidden":!0,className:"size-4 flex-none text-muted-foreground"}),e.jsx("strong",{className:"min-w-0 flex-1 truncate text-[0.82rem] font-semibold",children:r.brand.title}),e.jsx(Q,{onOpenSettings:G})]}),e.jsxs("div",{className:"min-h-0 flex-1 overflow-auto p-3",children:[Re&&e.jsx(ce,{className:"mb-3",variant:"destructive",children:"The server is unreachable."}),_e]})]}),D,ae]})}async function Pt(t,a,r){const n=a.startEntries.find(l=>l.id===t.entryId);if(!n)throw new Error("This template does not exist in this profile.");if(!pe(r,n.id))throw new Error(`${n.title} is not enabled for this user account.`);if(t.startOptions){const l=await Ke(t.runId),c=xe(t.startOptions,n.fixedStartOptions);for(const[u,f]of Qe(l,c))await We(t.runId,u,f)}await Ye(t.runId,n,null)}function Lt({children:t,header:a}){const[r,n]=o.useState(!1);return o.useEffect(()=>{const l=window.setTimeout(()=>n(!0),jt);return()=>window.clearTimeout(l)},[]),r?e.jsx(y,{header:a,state:Ct,children:t}):e.jsx(y,{header:a,state:Rt})}function y({children:t,header:a,headless:r=!1,state:n}){return e.jsxs("div",{className:"flex h-full flex-col bg-[image:var(--surface-backdrop)]",children:[!r&&e.jsx("header",{className:Se,children:a}),e.jsx("main",{className:"grid min-h-0 flex-1 place-items-center overflow-hidden p-6",children:e.jsx(Ve,{state:n,children:t})})]})}function Tt({elementId:t,registry:a,runId:r}){const n=B(),l=X().can("runs.read"),{sessions:c}=je(l);return o.useEffect(()=>{n.notify({type:"ready"})},[n]),l?e.jsx("main",{className:"relative flex h-full min-h-0 min-w-0 flex-1 bg-background @container/chat-content",children:e.jsx(Z,{layout:{element:t},registry:a,session:c.find(u=>u.id===r)??ke(r)},r)}):e.jsx("p",{className:ye,children:"No runs are enabled for this user account."})}function At(){const t=B();return e.jsxs(fe,{children:[e.jsx("h1",{className:"my-3 text-[1.5rem]",children:"Sign-in required"}),e.jsx("p",{className:"mb-6 leading-normal text-muted-foreground",children:"Sign-in goes through VS Code. The panel then reloads."}),e.jsx(E,{className:"w-full",onClick:()=>t.requestLogin(),children:"Sign in with VS Code"})]})}const C=t=>t!=null&&t.trim()?t.trim():void 0,_t=t=>{if(t==="browser"||t==="vscode")return t;throw new Error(`Unknown host ${JSON.stringify(t)}. Allowed are browser and vscode.`)};function zt(t){const a=new URLSearchParams(t),r=C(a.get("layout"))??"panel";if(r!=="panel"&&r!=="app")throw new Error(`Unknown layout ${JSON.stringify(r)}. Allowed are panel and app.`);const n=C(a.get("theme"));if(n!==void 0&&!tt(n))throw new Error(`Unknown theme ${JSON.stringify(n)}. Allowed are light and dark.`);const l={host:_t(C(a.get("host"))??"browser"),connection:C(a.get("connection")),theme:n,access:C(a.get(nt))},c=C(a.get("run"));if(r==="panel")return{layout:r,runId:c,...l};const u=C(a.get("element"));if(!c||!u)throw new Error("The app layout needs run and element.");return{layout:r,runId:c,elementId:u,...l}}st();const Ne=document.getElementById("root");if(!Ne)throw new Error("Root element is missing");const he=rt.createRoot(Ne);try{const t=zt(window.location.search);t.access!==void 0&&ot(t.access);const a=at(t.host,window);if(t.host==="vscode"){const n=it(window)}const r=lt(window);t.theme!==void 0&&r.setPreference(t.theme),a.onCommand(n=>{n.type==="theme"&&r.setPreference(n.theme)}),he.render(e.jsx(o.StrictMode,{children:e.jsx(ct,{children:e.jsx(dt,{value:a,children:e.jsx(ut,{value:t.host==="vscode"?{open:a.openPage}:void 0,children:e.jsx(ht,{Login:t.host==="vscode"?At:void 0,children:e.jsx(It,{location:t})})})})})}))}catch(t){he.render(e.jsxs(fe,{children:[e.jsx("h1",{className:"my-3 text-[1.5rem]",children:"The RAgents panel could not be loaded"}),e.jsx("p",{className:"mb-6 leading-normal",role:"alert",children:t instanceof Error?t.message:String(t)}),e.jsx(E,{onClick:()=>window.location.reload(),variant:"outline",children:"Reload"})]}))}
@@ -137,6 +137,13 @@ tab bar on the right. Without <code>run</code>, it shows the run list with &quot
137
137
  card. <code>run-panel.html?layout=app&amp;run=&lt;id&gt;&amp;element=&lt;app-id&gt;</code> shows one mini-app without the tab bar.
138
138
  Run-panel state, including the selected app and actor, view mode, chat width, collapsed chat
139
139
  height, open tab, and tab-area height, is stored per run in the browser.</p>
140
+ <p>With write rights, the menu at the top right of an open run offers &quot;Run script&quot;: it lists the run
141
+ scripts you may start, each with its description, and greyed out with the reason when it cannot
142
+ join this run, because its <code>RUN.md</code> does not set <code>embeddable: true</code> or because it fixes a start
143
+ option to a value the run does not have. A click starts it inside the run without a start value;
144
+ the primary actor stays, a repeated start reuses the script, its main view is placed next to the
145
+ tiles, and its output and summary appear in the chat as <code>@handle: ...</code>. If the start is refused,
146
+ the menu shows why. The same menu works in the VS Code run panel.</p>
140
147
  <p>The narrow tab bar on the right contains the same tabs as the full web view: files, documents,
141
148
  functions, executions, and language-server diagnostics, depending on the run and the user&#39;s
142
149
  permissions. The tab name appears in a tooltip. A small counter sits at the top right of its
@@ -328,9 +335,9 @@ in their URL (the server accepts a bearer token or the <code>access</code> query
328
335
  After expiry or a server restart, that server asks for sign-in again without affecting others.
329
336
  <code>RAgents: Sign out</code> revokes the session.</p>
330
337
  <h2 id="control-ragents-as-an-agent">Control RAgents as an agent</h2>
331
- <p>An AI agent working on the same machine controls RAgents through four <code>ragents</code> subcommands. In
332
- a checkout, use <code>pnpm ragents &lt;command&gt;</code>. These commands are the agent-facing contract: each one
333
- waits for the turn to end and returns an exit code.</p>
338
+ <p>An AI agent working on the same machine controls RAgents through five <code>ragents</code> subcommands. In
339
+ a checkout, use <code>pnpm ragents &lt;command&gt;</code>. These commands are the agent-facing contract: <code>run</code> and
340
+ <code>send</code> wait for the turn to end, and every command returns an exit code.</p>
334
341
  <pre><code class="language-sh">ragents provision developer # once per machine
335
342
  ragents run selftest/workspace-project &quot;Fix the type error in src/broken.ts&quot;
336
343
  ragents send &lt;runId&gt; &quot;Read README.md and report the passphrase&quot;
@@ -338,6 +345,8 @@ ragents journal &lt;runId&gt; --tools
338
345
  ragents stop &lt;runId&gt; # interrupt the primary actor&#39;s active turn
339
346
  ragents stop &lt;runId&gt; --run # emergency stop: halt the whole run
340
347
  ragents stop --host # stop the remembered host
348
+ ragents script &lt;runId&gt; # list the run scripts and whether each can join the run
349
+ ragents script &lt;runId&gt; &lt;entry&gt; --input &#39;{&quot;topic&quot;:&quot;Launch&quot;}&#39; # start one inside the running run
341
350
  ragents --help # same as ragents help
342
351
  </code></pre>
343
352
  <p><code>run</code> checks <code>GET &lt;address&gt;/health</code> to see whether the profile host is already running. If not,
@@ -370,7 +379,11 @@ exactly like the stop button in the chat input: the run and all actors stay acti
370
379
  next task, and without an active turn nothing happens. <code>stop &lt;runId&gt; --run</code> is the emergency stop (<code>ragents.chat.stop</code>): it aborts every turn
371
380
  and stops all actors of the run. <code>stop --host</code> terminates exactly the PID in <code>host.json</code>, never a
372
381
  process pattern, and only if the host at the recorded address reports that same PID from
373
- <code>/health</code>; otherwise it fails, leaves the process alone and removes the stale record. <code>ragents --help</code> and <code>ragents help</code> show usage and exit with 0; invoking the
382
+ <code>/health</code>; otherwise it fails, leaves the process alone and removes the stale record.
383
+ <code>script &lt;runId&gt;</code> lists the run scripts through <code>ragents.runs.scripts</code>, one per line with id, title,
384
+ and the reason if one cannot join; <code>script &lt;runId&gt; &lt;entry&gt; [--input &lt;json&gt;]</code> starts it inside the
385
+ run through <code>ragents.runs.startScript</code> as the run&#39;s user and prints <code>script: @&lt;handle&gt;, start &lt;n&gt;</code>;
386
+ a refusal is an error with exit code 1. <code>--json</code> prints the RPC results instead. <code>ragents --help</code> and <code>ragents help</code> show usage and exit with 0; invoking the
374
387
  command without arguments is an error with exit code 1.</p>
375
388
  <p><code>--profile &lt;profile|path&gt;</code> selects something other than <code>developer</code>: a profile name beside the
376
389
  host or the path to a custom <code>ragents.config.&lt;profile&gt;.ts</code> anywhere on disk. Resolution matches
@@ -436,6 +449,10 @@ requests as Server-Sent Events:</p>
436
449
  -d &#39;{&quot;jsonrpc&quot;:&quot;2.0&quot;,&quot;id&quot;:1,&quot;method&quot;:&quot;ragents.runs.list&quot;,&quot;params&quot;:{}}&#39;
437
450
  </code></pre>
438
451
  <p>The response contains either <code>result</code> or <code>error</code>; <code>error.data</code> provides <code>code</code> and <code>status</code>.</p>
452
+ <p>A run script whose <code>RUN.md</code> sets <code>embeddable: true</code> also starts inside a running run:
453
+ <code>ragents.runs.startScript</code> with <code>runId</code>, <code>entry</code>, and <code>input</code> waits and returns the script actor and
454
+ which start of its package in the run this was, or the reason in <code>error</code>. The primary actor stays;
455
+ a repeated start reuses the script&#39;s actor.</p>
439
456
  <p>Without HTTP, use stdio: <code>pnpm start -- --stdio</code> exchanges one JSON message per line through
440
457
  stdin and stdout and opens no port. The startup modes are:</p>
441
458
  <ul>
@@ -11,6 +11,14 @@ card. `run-panel.html?layout=app&run=<id>&element=<app-id>` shows one mini-app w
11
11
  Run-panel state, including the selected app and actor, view mode, chat width, collapsed chat
12
12
  height, open tab, and tab-area height, is stored per run in the browser.
13
13
 
14
+ With write rights, the menu at the top right of an open run offers "Run script": it lists the run
15
+ scripts you may start, each with its description, and greyed out with the reason when it cannot
16
+ join this run, because its `RUN.md` does not set `embeddable: true` or because it fixes a start
17
+ option to a value the run does not have. A click starts it inside the run without a start value;
18
+ the primary actor stays, a repeated start reuses the script, its main view is placed next to the
19
+ tiles, and its output and summary appear in the chat as `@handle: ...`. If the start is refused,
20
+ the menu shows why. The same menu works in the VS Code run panel.
21
+
14
22
  The narrow tab bar on the right contains the same tabs as the full web view: files, documents,
15
23
  functions, executions, and language-server diagnostics, depending on the run and the user's
16
24
  permissions. The tab name appears in a tooltip. A small counter sits at the top right of its
@@ -224,9 +232,9 @@ After expiry or a server restart, that server asks for sign-in again without aff
224
232
 
225
233
  ## Control RAgents as an agent
226
234
 
227
- An AI agent working on the same machine controls RAgents through four `ragents` subcommands. In
228
- a checkout, use `pnpm ragents <command>`. These commands are the agent-facing contract: each one
229
- waits for the turn to end and returns an exit code.
235
+ An AI agent working on the same machine controls RAgents through five `ragents` subcommands. In
236
+ a checkout, use `pnpm ragents <command>`. These commands are the agent-facing contract: `run` and
237
+ `send` wait for the turn to end, and every command returns an exit code.
230
238
 
231
239
  ```sh
232
240
  ragents provision developer # once per machine
@@ -236,6 +244,8 @@ ragents journal <runId> --tools
236
244
  ragents stop <runId> # interrupt the primary actor's active turn
237
245
  ragents stop <runId> --run # emergency stop: halt the whole run
238
246
  ragents stop --host # stop the remembered host
247
+ ragents script <runId> # list the run scripts and whether each can join the run
248
+ ragents script <runId> <entry> --input '{"topic":"Launch"}' # start one inside the running run
239
249
  ragents --help # same as ragents help
240
250
  ```
241
251
 
@@ -272,7 +282,11 @@ exactly like the stop button in the chat input: the run and all actors stay acti
272
282
  next task, and without an active turn nothing happens. `stop <runId> --run` is the emergency stop (`ragents.chat.stop`): it aborts every turn
273
283
  and stops all actors of the run. `stop --host` terminates exactly the PID in `host.json`, never a
274
284
  process pattern, and only if the host at the recorded address reports that same PID from
275
- `/health`; otherwise it fails, leaves the process alone and removes the stale record. `ragents --help` and `ragents help` show usage and exit with 0; invoking the
285
+ `/health`; otherwise it fails, leaves the process alone and removes the stale record.
286
+ `script <runId>` lists the run scripts through `ragents.runs.scripts`, one per line with id, title,
287
+ and the reason if one cannot join; `script <runId> <entry> [--input <json>]` starts it inside the
288
+ run through `ragents.runs.startScript` as the run's user and prints `script: @<handle>, start <n>`;
289
+ a refusal is an error with exit code 1. `--json` prints the RPC results instead. `ragents --help` and `ragents help` show usage and exit with 0; invoking the
276
290
  command without arguments is an error with exit code 1.
277
291
 
278
292
  `--profile <profile|path>` selects something other than `developer`: a profile name beside the
@@ -355,6 +369,11 @@ curl -s http://localhost:4710/rpc -H 'content-type: application/json' \
355
369
 
356
370
  The response contains either `result` or `error`; `error.data` provides `code` and `status`.
357
371
 
372
+ A run script whose `RUN.md` sets `embeddable: true` also starts inside a running run:
373
+ `ragents.runs.startScript` with `runId`, `entry`, and `input` waits and returns the script actor and
374
+ which start of its package in the run this was, or the reason in `error`. The primary actor stays;
375
+ a repeated start reuses the script's actor.
376
+
358
377
  Without HTTP, use stdio: `pnpm start -- --stdio` exchanges one JSON message per line through
359
378
  stdin and stdout and opens no port. The startup modes are:
360
379
 
@@ -194,6 +194,11 @@ functions, actor programs, language servers, and interfaces; they add no new mec
194
194
  <td>Setup in code, domain decisions in the responsible model</td>
195
195
  </tr>
196
196
  <tr>
197
+ <td>Program several run scripts use</td>
198
+ <td>Shared actor package in the owning plugin (<code>actors/&lt;name&gt;/</code>)</td>
199
+ <td>One actor per run; scripts name it and ensure it, none copies it</td>
200
+ </tr>
201
+ <tr>
197
202
  <td>Reusable work instructions</td>
198
203
  <td>Skill in the owning plugin</td>
199
204
  <td>Describes the approach but does not perform required initialization</td>
@@ -253,6 +258,11 @@ a successful check. A compact status contract can expose state and work step wit
253
258
  reasoning or tool arguments. Grant diagnostic and change permissions independently from full
254
259
  technical inspection and enforce them on the server. Roles belong in configuration; neutral
255
260
  components check permissions, not user names.</p>
261
+ <p>A service that trusts a TypeScript actor more than others asks the actor programs service who it
262
+ is: <code>programOf(runId, actorId)</code> names the package, its revision, and its origin, a shared package
263
+ of a plugin, a run script&#39;s template, or a package created in the run, and a package changed in the
264
+ run counts as created there. Authorize by that identity, never by handle or package name: any
265
+ agent with the program functions creates a package under any free name.</p>
256
266
  <h3 id="7-develop-mini-apps-in-the-actual-host">7. Develop mini-apps in the actual host</h3>
257
267
  <p>The iframe constrains interaction, layout, and communication. Use shared controls and the
258
268
  declared function bridge. For a dialog spanning host areas, the app signals intent through a
@@ -341,8 +351,8 @@ bound identity apply equally, while a program&#39;s <code>capabilities</code> li
341
351
  <p>Every domain function is available through <code>context.functions</code> in <code>typescript_eval</code>.
342
352
  <code>nativeTool: true</code> additionally exposes it as a native model tool when the model normally must
343
353
  read its result before taking the next step: browser interactions, domain reports and status,
344
- language diagnostics, <code>read</code>, <code>edit</code>, <code>write</code>, <code>bash</code>, <code>document_write</code>, <code>show_document</code>, and
345
- <code>browser_view_screenshot</code>, which can return image pixels only natively. Snippets remain the right
354
+ language diagnostics, <code>read</code>, <code>edit</code>, <code>write</code>, <code>bash</code>, <code>document_write</code>, <code>show_document</code>,
355
+ <code>ask_user</code>, and <code>browser_view_screenshot</code>, which can return image pixels only natively. Snippets remain the right
346
356
  form for calls that combine, filter, or pass results onward, including data queries, management
347
357
  functions, list results, and values passed from earlier responses without transcription. Native
348
358
  tools remain callable from snippets. The building-block reference marks them in the catalog and
@@ -37,6 +37,7 @@ functions, actor programs, language servers, and interfaces; they add no new mec
37
37
  | Investigation, conversation, or multi-step implementation | LLM actor with suitable functions | Context and tools must match the task |
38
38
  | Controls or status for an existing actor | View on that actor | An interface alone does not justify another actor |
39
39
  | Repeatable prepared run | Run script in the owning plugin | Setup in code, domain decisions in the responsible model |
40
+ | Program several run scripts use | Shared actor package in the owning plugin (`actors/<name>/`) | One actor per run; scripts name it and ensure it, none copies it |
40
41
  | Reusable work instructions | Skill in the owning plugin | Describes the approach but does not perform required initialization |
41
42
 
42
43
  ### 1. Keep capabilities and workflows separate
@@ -105,6 +106,12 @@ reasoning or tool arguments. Grant diagnostic and change permissions independent
105
106
  technical inspection and enforce them on the server. Roles belong in configuration; neutral
106
107
  components check permissions, not user names.
107
108
 
109
+ A service that trusts a TypeScript actor more than others asks the actor programs service who it
110
+ is: `programOf(runId, actorId)` names the package, its revision, and its origin, a shared package
111
+ of a plugin, a run script's template, or a package created in the run, and a package changed in the
112
+ run counts as created there. Authorize by that identity, never by handle or package name: any
113
+ agent with the program functions creates a package under any free name.
114
+
108
115
  ### 7. Develop mini-apps in the actual host
109
116
 
110
117
  The iframe constrains interaction, layout, and communication. Use shared controls and the
@@ -212,8 +219,8 @@ bound identity apply equally, while a program's `capabilities` limit its install
212
219
  Every domain function is available through `context.functions` in `typescript_eval`.
213
220
  `nativeTool: true` additionally exposes it as a native model tool when the model normally must
214
221
  read its result before taking the next step: browser interactions, domain reports and status,
215
- language diagnostics, `read`, `edit`, `write`, `bash`, `document_write`, `show_document`, and
216
- `browser_view_screenshot`, which can return image pixels only natively. Snippets remain the right
222
+ language diagnostics, `read`, `edit`, `write`, `bash`, `document_write`, `show_document`,
223
+ `ask_user`, and `browser_view_screenshot`, which can return image pixels only natively. Snippets remain the right
217
224
  form for calls that combine, filter, or pass results onward, including data queries, management
218
225
  functions, list results, and values passed from earlier responses without transcription. Native
219
226
  tools remain callable from snippets. The building-block reference marks them in the catalog and
@@ -181,8 +181,11 @@ views.</p>
181
181
  as its default export. The TypeBox contract describes <code>state</code>, <code>functions</code>, and optional <code>input</code>.</p>
182
182
  <p>State must accept the initial value <code>{}</code>. Each function declares its input and output, with
183
183
  optional granted capabilities, confirmation, and publication as a tool. The implementation
184
- contains the same functions and, when input is declared, an <code>onInput</code> handler. TypeScript derives
185
- input, result, and state types from the contract.</p>
184
+ contains the same functions and, when input is declared, an <code>onInput</code> handler; a run script can
185
+ add <code>onStart</code>, which receives its starts instead of <code>onInput</code>, <code>onResult</code> for the results of scripts
186
+ it starts itself, and ends a start with <code>context.finish</code> (details in
187
+ <a href="https://github.com/SchlenkR/RAgents/blob/main/docs/spec/typescript-platform.md">TypeScript platform</a>, Run scripts). TypeScript derives input, result, and
188
+ state types from the contract.</p>
186
189
  <p>Each function receives <code>(input, context)</code> and returns only its domain result.
187
190
  <code>context.state.replace</code> stages state changes; a return value is never also interpreted as new
188
191
  state. <code>context.actor</code> identifies the actor that owns the function and state.
@@ -227,6 +230,9 @@ only then activates the verified version. Errors identify the location to fix.</
227
230
  <code>typescript_api</code> returns their exact contracts, and snippets call them through
228
231
  <code>context.functions</code>. Reactivation updates the schemas; removed functions disappear from the same
229
232
  catalog. No additional call contract is needed.</p>
233
+ <p><code>actor_program_ensure</code> makes a package active only when it is not: it returns an active package
234
+ unchanged, restarts its stopped actor, activates an installed package, or installs a shared
235
+ package of the profile (<a href="https://github.com/SchlenkR/RAgents/blob/main/docs/spec/typescript-platform.md">TypeScript platform</a>, Run scripts).</p>
230
236
  <p><code>actor_program_list</code> shows installed programs. <code>actor_program_remove</code> removes the binding and its
231
237
  views. It also stops a TypeScript actor, while an existing LLM actor remains. Activating a package
232
238
  of the same name again restarts that stopped actor with its state instead of creating another. Sources stay
@@ -65,8 +65,11 @@ as its default export. The TypeBox contract describes `state`, `functions`, and
65
65
 
66
66
  State must accept the initial value `{}`. Each function declares its input and output, with
67
67
  optional granted capabilities, confirmation, and publication as a tool. The implementation
68
- contains the same functions and, when input is declared, an `onInput` handler. TypeScript derives
69
- input, result, and state types from the contract.
68
+ contains the same functions and, when input is declared, an `onInput` handler; a run script can
69
+ add `onStart`, which receives its starts instead of `onInput`, `onResult` for the results of scripts
70
+ it starts itself, and ends a start with `context.finish` (details in
71
+ [TypeScript platform](https://github.com/SchlenkR/RAgents/blob/main/docs/spec/typescript-platform.md), Run scripts). TypeScript derives input, result, and
72
+ state types from the contract.
70
73
 
71
74
  Each function receives `(input, context)` and returns only its domain result.
72
75
  `context.state.replace` stages state changes; a return value is never also interpreted as new
@@ -119,6 +122,10 @@ Published functions appear in the current TypeScript API even during an active L
119
122
  `context.functions`. Reactivation updates the schemas; removed functions disappear from the same
120
123
  catalog. No additional call contract is needed.
121
124
 
125
+ `actor_program_ensure` makes a package active only when it is not: it returns an active package
126
+ unchanged, restarts its stopped actor, activates an installed package, or installs a shared
127
+ package of the profile ([TypeScript platform](https://github.com/SchlenkR/RAgents/blob/main/docs/spec/typescript-platform.md), Run scripts).
128
+
122
129
  `actor_program_list` shows installed programs. `actor_program_remove` removes the binding and its
123
130
  views. It also stops a TypeScript actor, while an existing LLM actor remains. Activating a package
124
131
  of the same name again restarts that stopped actor with its state instead of creating another. Sources stay
@@ -317,8 +317,9 @@ way, by the host, a run script, or an actor program, are checked by the schedule
317
317
  it runs (any driver except <code>manual</code>) is created or restarted, it resolves the requested names the way a turn would, counting functions
318
318
  that are currently unavailable as known. A name that no host function provides stops the actor
319
319
  before its first turn, and the stop reason names the unknown tools. The selection is not
320
- inherited, although delegable engine capabilities still are. <code>withoutCapabilities</code> removes
321
- named technical permissions. Availability and grants also apply when the value is <code>null</code>.
320
+ inherited, although delegable engine capabilities still are, except that an inherited copy of a
321
+ first-hand capability (<code>firstHandCapabilities</code> in <code>domain/vocabulary.ts</code>, today <code>script.start</code>) is
322
+ not delegable further. <code>withoutCapabilities</code> removes named technical permissions. Availability and grants also apply when the value is <code>null</code>.
322
323
  <code>forkOf</code> (a handle or ID) makes the new agent a fork of an LLM agent in the same run:
323
324
  <code>agent.spawned</code> records the source, and the new agent&#39;s context begins with an unchanged copy of
324
325
  the source&#39;s context up to the end of the source&#39;s last finished turn, reasoning blocks included.
@@ -203,8 +203,9 @@ way, by the host, a run script, or an actor program, are checked by the schedule
203
203
  it runs (any driver except `manual`) is created or restarted, it resolves the requested names the way a turn would, counting functions
204
204
  that are currently unavailable as known. A name that no host function provides stops the actor
205
205
  before its first turn, and the stop reason names the unknown tools. The selection is not
206
- inherited, although delegable engine capabilities still are. `withoutCapabilities` removes
207
- named technical permissions. Availability and grants also apply when the value is `null`.
206
+ inherited, although delegable engine capabilities still are, except that an inherited copy of a
207
+ first-hand capability (`firstHandCapabilities` in `domain/vocabulary.ts`, today `script.start`) is
208
+ not delegable further. `withoutCapabilities` removes named technical permissions. Availability and grants also apply when the value is `null`.
208
209
  `forkOf` (a handle or ID) makes the new agent a fork of an LLM agent in the same run:
209
210
  `agent.spawned` records the source, and the new agent's context begins with an unchanged copy of
210
211
  the source's context up to the end of the source's last finished turn, reasoning blocks included.
@@ -290,7 +290,7 @@ a { color: inherit; text-underline-offset: 4px; }
290
290
  <div class="end" data-end><button type="button" class="end-button" data-replay><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"/><path d="M3 3v5h5"/></svg>Replay</button><button type="button" class="end-button" data-onward><svg class="end-arrow" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 5v14"/><path d="m19 12-7 7-7-7"/></svg>Scroll down</button></div>
291
291
  </div>
292
292
  <div class="sr-only story" data-story>
293
- <article data-chapter="workspace" id="setups" data-anchor="setups"><h2><span>Tailor a workspace</span> <span>for a task</span></h2><p>The script builds the workspace, so the agents start with everything in place.</p><ul class="bullets"><li>A setup script creates agents, scripts and mini-apps</li><li>Start it again with one click</li><li>Ask for inputs before the run starts</li></ul><p class="how"><span class="how-label">How it works</span> A setup is a tested TypeScript package that appears as a start card. Its script starts agents, TypeScript programs and mini-apps through the same functions the AI uses. A setup dialog can ask for values, such as a repository or a topic, before the run starts.</p></article>
293
+ <article data-chapter="workspace" id="setups" data-anchor="setups"><h2><span>Tailor a workspace</span> <span>for a task</span></h2><p>The script builds the workspace, so the agents start with everything in place.</p><ul class="bullets"><li>A setup script creates agents, scripts and mini-apps</li><li>Start it again with one click</li><li>Add a setup to a run that is already running</li><li>Ask for inputs before the run starts</li></ul><p class="how"><span class="how-label">How it works</span> A setup is a tested TypeScript package that appears as a start card. Its script starts agents, TypeScript programs and mini-apps through the same functions the AI uses. A setup dialog can ask for values, such as a repository or a topic, before the run starts. A setup marked as embeddable also joins a running run, from the run menu, the command line or the coordinator, and reports its result back.</p></article>
294
294
  <article data-chapter="agents" id="agents" data-anchor="agents"><h2><span>Everyone talks</span> <span>to everyone</span></h2><p>Agents write plain text to each other, addressed by handle, such as @agent1.</p><ul class="bullets"><li>Agents hand work to each other</li><li>Agents talk to scripts, scripts answer</li><li>People talk to agents and mini-apps</li><li>Mini-apps talk to people and agents</li><li class="wink">... you get the idea :)</li></ul><p class="how"><span class="how-label">How it works</span> Each agent has its own model, prompt, history and handle. A coordinator takes the task and hands out work. A helper starts with no tools, a picked list, or all tools. When an agent asks you something, the choices appear in the chat and your answer goes back to that agent.</p></article>
295
295
  <article data-chapter="ui" id="ui" data-anchor="ui"><h2><span>Agents with</span> <span>their own UI</span></h2><p>People are used to working with interfaces. A UI shows what the agent is doing, and you step in with a click.</p><ul class="bullets"><li>The AI builds a UI while it works</li><li>Extensions ship UIs ready to use</li><li>You and the agent use the same UI and state</li><li>Your click goes straight to the agent</li><li>A new UI goes live after its tests pass</li></ul><p class="how"><span class="how-label">How it works</span> A mini-app is a React view on the state of an agent or a TypeScript program. Its buttons call the program's typed functions directly. The AI type-checks and tests a new view before it goes live; if a rebuild fails, the old version stays active. In VS Code, a mini-app opens in its own editor tab.</p></article>
296
296
  <article data-chapter="typescript" id="typescript" data-anchor="typescript"><h2><span>Tools are</span> <span>TypeScript functions</span></h2><ul class="bullets"><li>Register a typed function once, from your own plugin</li><li>Agents get it as a tool</li><li>AI-written code calls it, type-checked first</li><li>A button calls it without a model</li><li>Programs call it when events arrive</li></ul><p class="how"><span class="how-label">How it works</span> A snippet runs once and returns its result to the model. A program keeps its state and reacts to later messages. A setup starts agents, programs and UIs. All of them call the same typed functions, with the same permission checks.</p></article>
@@ -564,6 +564,12 @@
564
564
  -webkit-box-orient: vertical;
565
565
  -webkit-line-clamp: 2;
566
566
  }
567
+ .line-clamp-3 {
568
+ overflow: hidden;
569
+ display: -webkit-box;
570
+ -webkit-box-orient: vertical;
571
+ -webkit-line-clamp: 3;
572
+ }
567
573
  .block {
568
574
  display: block;
569
575
  }
@@ -747,6 +753,9 @@
747
753
  .max-h-\[180px\] {
748
754
  max-height: 180px;
749
755
  }
756
+ .max-h-\[240px\] {
757
+ max-height: 240px;
758
+ }
750
759
  .max-h-\[520px\] {
751
760
  max-height: 520px;
752
761
  }
@@ -846,8 +855,8 @@
846
855
  .w-\[42px\] {
847
856
  width: 42px;
848
857
  }
849
- .w-\[220px\] {
850
- width: 220px;
858
+ .w-\[260px\] {
859
+ width: 260px;
851
860
  }
852
861
  .w-\[calc\(100\%-3rem\)\] {
853
862
  width: calc(100% - 3rem);
@@ -3229,6 +3238,11 @@
3229
3238
  .disabled\:opacity-60:disabled {
3230
3239
  opacity: 60%;
3231
3240
  }
3241
+ @media (hover: hover) {
3242
+ .disabled\:hover\:bg-transparent:disabled:hover {
3243
+ background-color: transparent;
3244
+ }
3245
+ }
3232
3246
  :where([data-detail-level="summary"]) .in-data-\[detail-level\=summary\]\:py-\[10px\] {
3233
3247
  padding-block: 10px;
3234
3248
  }
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "inputs": {
3
- "apps/server/src/api/contracts.ts": "88d12d6b852a8d3b76a9fdba310f6e0e2e173558dd5663ab6e311c8ab9944346",
4
- "apps/server/src/host-api.ts": "0495247e24ec1d62b148f4293d526f62994855d4072c5d06b1c6ec551b1201d1",
5
- "apps/server/src/plugin-support/actor-programs/contract.ts": "70923e56f2780f71378a3420613256e27c724e6a82844c5486112d6fefc16624",
3
+ "apps/server/src/api/contracts.ts": "5dcbff61b0e317a674fa58475027e1d30da6ac9f1812aced1fdbf325c4271a91",
4
+ "apps/server/src/host-api.ts": "e5cd123304fbf0567eef1985e0e1b9ce3b1cf845f111238fa755b36d928a3e1f",
5
+ "apps/server/src/plugin-support/actor-programs/contract.ts": "e8a1ba7dde7b73ad8904bafba2f61b4ef1ea0f0aa957fae2a76920edfc668974",
6
6
  "apps/server/src/plugin-support/chat-display-contract.ts": "2fb8aab13b5a60b4fe28f87f93cc82afb34b7d8ef1463e376bc3cbc0bcdc797b",
7
7
  "apps/server/src/plugin-support/language-server/contract.ts": "01794d6b63c19bb3c201412b45480d8dde5bd0f3d50459fb936a5e9b314d5a83",
8
8
  "apps/server/src/plugin-support/product-model-settings-contract.ts": "40d139db6a5c9047ad832c4f29465321e939cdf610789c367f9d064878c3e5f7",
@@ -15,8 +15,8 @@
15
15
  "apps/web/src/access-token.ts": "d3040d9148dd31395da920e2c933d5066c20a249aa967200716070a2b1ecfcce",
16
16
  "apps/web/src/AccessContext.tsx": "38cffefabf8dd2bfb7171d1f1c6474c2cf6834c4134469fce460d1942d0ddfb4",
17
17
  "apps/web/src/actor-conversation.ts": "73063988356134a2dbf0f83c5cadbe7301870a29aebaf0163301bde792b96b24",
18
- "apps/web/src/api.ts": "cc80688566ba4beaf6a22bd083afd2f107c286fc0c5a2bd5755eedf6c1cec93f",
19
- "apps/web/src/App.tsx": "c47d5b1c56f2ec5ac479403366d6a27160008f1247c9d85379e97d5066419091",
18
+ "apps/web/src/api.ts": "13d17fb25c05aaf53220fe96be0bce9c7155270b7e3e22a0c605c3bd967bddd6",
19
+ "apps/web/src/App.tsx": "95f5eee9b1cb1a359fecc11c6322484842f6cf7f545a29d11764a98d3bcab8d2",
20
20
  "apps/web/src/chat-view-settings.tsx": "8a8bd0a77093c0c657c401efd52143c88825b085c06b34bf37440a115e9b3ad5",
21
21
  "apps/web/src/chat/chat-target.ts": "44303252e87f172b93194fe0c0eba84217992cb17a438cb2cd2ba00fefccf012",
22
22
  "apps/web/src/chat/QuasselHost.tsx": "66b3e2f3549537b8daaf955251ae3ef8254229b92953b9583557d46c3515a486",
@@ -48,7 +48,7 @@
48
48
  "apps/web/src/PluginActivation.ts": "4e2fa7ca943f3b4dae1f0eee5b1543971cb2cf81a5a5e29df374f9b1c066c3ec",
49
49
  "apps/web/src/PluginChat.tsx": "769d216a285ace4951df7f7488517e4e39808ea1f049ccf5909d2e8296d15f1b",
50
50
  "apps/web/src/PluginFailureNotice.tsx": "5443e628f50389ff6cc4f09be8b73f3d481efce5976f8955f853058c569bd932",
51
- "apps/web/src/PluginRegistry.tsx": "4decbdd6b591c0baf20d52e5ca0fa9fa045c38dc5ac38cbcff4bd77eaf803f0e",
51
+ "apps/web/src/PluginRegistry.tsx": "6eed3989ea350d4cc21b91c820824385c14c99489f97f87e92e8f27c323fdba6",
52
52
  "apps/web/src/product/model-settings.ts": "445b05f8dd34e8145b474d04825408c4b7a2527559ec3ee549f9dba61ef91e13",
53
53
  "apps/web/src/product/ModelControl.tsx": "c3467c74fd0c595054b8be92f8df2cbf4be53cdceaac8f3337c96f3da547077a",
54
54
  "apps/web/src/product/ProductModelSettings.tsx": "e8513da26228da46ed04a5913967b5453d1276b712e26fa0d663369c904fb608",
@@ -56,7 +56,7 @@
56
56
  "apps/web/src/product/SystemPromptControl.tsx": "fcbabb5ae84ef29c89826e968bc3583075dba96423fdd003125bf23605920383",
57
57
  "apps/web/src/rpc.ts": "586f9307afa85f11f11faef801bb731230f2099685649aa7d9f666a851c490b5",
58
58
  "apps/web/src/rpc/client.ts": "5c50be675f7534b8a20a4e7db25cbe82444886b0f30a0aeed562e380c656f43a",
59
- "apps/web/src/run-overview.ts": "12b1c2fd4a7df1efff42e32abc813b24a25d551cfca96ccb900a36f772ac3d95",
59
+ "apps/web/src/run-overview.ts": "d87b462aecfbb4eff5292c3cdafb8bf6b46a6d823ddc305eacc243acddaefc61",
60
60
  "apps/web/src/run-panel.tsx": "aa28c092fc3c58bb2efd0f1ad9cb913c985fe71e6d4476c0f81b198e23347d34",
61
61
  "apps/web/src/run-panel/clipboard.ts": "844b2bd9d7982df158183ee131992d1d19d332f2eab3064981d9d5082dc89aba",
62
62
  "apps/web/src/run-panel/host-contract.ts": "d2d23b2f20345adc9cd2739ad73f2812a28fec65fc6a4d1c06bcdb4477727292",
@@ -64,9 +64,9 @@
64
64
  "apps/web/src/run-panel/input-bridge.ts": "4c3deb8fe115286d20f29f92a6ae6cb38dbae8c883deb97e6f6c32c64fba843d",
65
65
  "apps/web/src/run-panel/keyboard.ts": "e89266a2e99c2d96dbec79f5c1aef937101cebdfa74fdc0b4bb1688986097526",
66
66
  "apps/web/src/run-panel/run-panel-location.ts": "d191d3d9da695f277cd8f899b9682ba149c4bf1ae8e3cecc1bc2bc60bf3e7adb",
67
- "apps/web/src/run-panel/RunPanelApp.tsx": "534c14df4d66d2c677812a0952a8622f41b826acf167bec2ec90ac732fb8f0f1",
67
+ "apps/web/src/run-panel/RunPanelApp.tsx": "a9541eafa3f67fc01e02ae3219bb6304bb0f91f43a97ade6a8313ab4c9b4c695",
68
68
  "apps/web/src/run-panel/RunPanelHeader.tsx": "a1ffbdbf4a705f14b859f11041f7954bfaccc7abe9b7640e7235774a953e0bad",
69
- "apps/web/src/run-panel/RunPanelMenu.tsx": "db7809ac8ed1730e9504a237b977ec11b9629031a3ac9f7794f3aa600f220f46",
69
+ "apps/web/src/run-panel/RunPanelMenu.tsx": "ea12a2e0a0867dbaee5e01473822ef238a9edb1739819140e3a669c01b219b28",
70
70
  "apps/web/src/run-panel/RunPanelRail.tsx": "d3c0cddb28805690f92d1aeb5fe32a9d7459022cae2a4cdeb4c15b1c6196bd10",
71
71
  "apps/web/src/run-panel/RunPanelWorkspace.tsx": "f240418198b9b2dc39c041aa4f7dccd2412d9d46b06c8fa748e1f055aa04aeca",
72
72
  "apps/web/src/run-panel/use-session-list.ts": "740a1040b50b597055b3950fcd99c42b3c6eef2cbbbac00eaee1c02370540838",
@@ -76,9 +76,9 @@
76
76
  "apps/web/src/run-view.ts": "2f87b3d8a4e8b8dd613bc24def2e9a77b6058c6b527f37a7b90bc1b6d96ca49b",
77
77
  "apps/web/src/RunPreparationChat.tsx": "cd0eb63781cc60c68adb7ed2410fb52b1646fb1d0907a22dbbd6bb508e10616e",
78
78
  "apps/web/src/RunStore.ts": "3ca3b947521e8e5df5a11ced352d37f90fccbede5889fb873e9ab0157a1d4299",
79
- "apps/web/src/SessionList.tsx": "ca95ca51f88dff8595b09df42aabe1d69f323c03bef49c62c419688c942532a8",
79
+ "apps/web/src/SessionList.tsx": "456fb59bd476ac480debc2eb21aafd5c6ac1a9e4bbcb9e471d18c02dc599148a",
80
80
  "apps/web/src/settings-contributions.ts": "5b5427293dde48cd85cbb99d1169823e0c89609d320363582bd131eb874ce893",
81
- "apps/web/src/SettingsModal.tsx": "b6d0633c03a31f241c43dfb567f2487521f227ac7d04169328271f193a2dbb0c",
81
+ "apps/web/src/SettingsModal.tsx": "014c227bdbdbe9029db720368b4a1aa826560474dc3f3992938345cbb0efef76",
82
82
  "apps/web/src/SourceCode.tsx": "bc80927cba80ac589dd89c8e0f9d1108dcf48d88a78e650051b084b9364c5001",
83
83
  "apps/web/src/StartOptions.tsx": "6c5d1407d2d3b72d5562ca094057d2f28b10b970c00baa17c66e67a1892fe3cc",
84
84
  "apps/web/src/StartSelection.tsx": "2b510e3a22ab099c795f47763043ee70294f663c442628d333aaa432ab7e0f08",
@@ -109,7 +109,7 @@
109
109
  "apps/web/src/ui/popover.tsx": "4cbf781de247770d3f24406d6322d1b3e159e38135ea45db2ab477f661417f2d",
110
110
  "apps/web/src/ui/progress.tsx": "bae4a2c7eded93a8da9e3237042011743572ac42b526b1be3054d95dc6626cc1",
111
111
  "apps/web/src/ui/radio-group.tsx": "62a1fa46c54ebbb71c84f09ebc5941dec41b0c75be3699b969eb5aae5820616d",
112
- "apps/web/src/ui/relative-time.ts": "0e60796bfa9171f5ce65c801143698937a8796c13721528a39c77c361b3f64fc",
112
+ "apps/web/src/ui/relative-time.ts": "5cf50e2d60afa8f397c8f86c0779b9c2ca9143e039d39e8bae4f346a4aab0100",
113
113
  "apps/web/src/ui/SectionLabel.tsx": "12396e7568f5507d47a6e303c0ea451e918f555cc7c1ee6fe97929dfd2ae4da4",
114
114
  "apps/web/src/ui/select.tsx": "932699e2bee1fe16ea4783eaa2acf2be0c133e0926a7d298650a0ae10c1c6912",
115
115
  "apps/web/src/ui/separator.tsx": "8a1d9397433ccf70631104f377b0e778754582a74c93a57cf13a2f2dcba778bf",
@@ -138,6 +138,6 @@
138
138
  "packages/ragents/src/rpc/peer.ts": "9050dff218bdc6603478a77bdca241629f55c03b65f6efe7df598b53446b4c09",
139
139
  "packages/ragents/src/rpc/protocol.ts": "82bbcb8181a2f90708dc607922fef4a9d472cd82d6dede09324df778773699a6",
140
140
  "packages/ragents/src/runtime/domain-error.ts": "d6bf8fa09769c4137e616c83a84cb9c05a58bfa6c2e32c9404a1c202815837a4",
141
- "pnpm-lock.yaml": "c7edb4e9414089daad46f922bae423d42b1257eb53ef490a3f0e3a8afb055fb3"
141
+ "pnpm-lock.yaml": "7a0ed220c7b68d8da22c5b6df864934dafa53aecad8e61d438ee86ddf79ee108"
142
142
  }
143
143
  }
@@ -5,8 +5,8 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <link rel="stylesheet" href="/ragents.css" />
7
7
  <title>RAgents</title>
8
- <script type="module" crossorigin src="/assets/main-DJmCHGzM.js"></script>
9
- <link rel="modulepreload" crossorigin href="/assets/mermaid-HWGCJPDP-q-mf1kLN.js">
8
+ <script type="module" crossorigin src="/assets/main-KBrc5Q77.js"></script>
9
+ <link rel="modulepreload" crossorigin href="/assets/mermaid-HWGCJPDP-CSCkaArr.js">
10
10
  <link rel="stylesheet" crossorigin href="/assets/mermaid-HWGCJPDP-BPn4aV2r.css">
11
11
  </head>
12
12
  <body>
@@ -5,8 +5,8 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <link rel="stylesheet" href="/ragents.css" />
7
7
  <title>RAgents Panel</title>
8
- <script type="module" crossorigin src="/assets/runPanel-nk_aMxSn.js"></script>
9
- <link rel="modulepreload" crossorigin href="/assets/mermaid-HWGCJPDP-q-mf1kLN.js">
8
+ <script type="module" crossorigin src="/assets/runPanel-BjG5NBKm.js"></script>
9
+ <link rel="modulepreload" crossorigin href="/assets/mermaid-HWGCJPDP-CSCkaArr.js">
10
10
  <link rel="stylesheet" crossorigin href="/assets/mermaid-HWGCJPDP-BPn4aV2r.css">
11
11
  </head>
12
12
  <body>
@@ -21,7 +21,7 @@
21
21
  "dompurify": "^3.4.13",
22
22
  "highlight.js": "^11.12.0",
23
23
  "lucide-react": "^1.46.0",
24
- "quassel": "^0.4.0",
24
+ "quassel": "^0.4.2",
25
25
  "react": "^19.2.0",
26
26
  "react-diff-view": "^3.3.3",
27
27
  "react-dom": "^19.2.0",
@@ -170,8 +170,9 @@ export function App() {
170
170
 
171
171
  const registry = pluginActivation.registry;
172
172
  const availablePanels = registry.overviewPanels.filter((panel) => panel.readRight === undefined || access.can(panel.readRight));
173
- const panels = availablePanels.filter((panel) => panel.placement !== "toolbar");
173
+ const panels = availablePanels.filter((panel) => (panel.placement ?? "overview") === "overview");
174
174
  const toolbarPanels = availablePanels.filter((panel) => panel.placement === "toolbar");
175
+ const idlePanel = readRuns ? availablePanels.find((panel) => panel.placement === "idle") : undefined;
175
176
  const overviewAvailable = readRuns || panels.length > 0;
176
177
  const busy = panels.some((panel) => busyPanels.has(panel.id));
177
178
  const userLocation = chatUserLocation(readRuns ? activeId : undefined, overviewOpen, runLocation);
@@ -234,6 +235,16 @@ export function App() {
234
235
  session={activeSession ?? { id: activeId, title: "New run", updatedAt: Date.now() }}
235
236
  />
236
237
  )
238
+ : idlePanel
239
+ ? (
240
+ <div className={chatWorkspaceClass}>
241
+ <ToolbarPanelHost
242
+ id={idlePanel.id} key={idlePanel.id} onBusy={setPanelBusy} onClose={() => {}} onOpen={() => {}}
243
+ open={!overviewOpen && !settingsOpen && !helpOpen && !draft && !toolbarPanel} Panel={idlePanel.Panel} registry={registry}
244
+ userLocation={userLocation}
245
+ />
246
+ </div>
247
+ )
237
248
  : (
238
249
  <div className={chatWorkspaceClass}>
239
250
  <div className="m-auto text-center text-muted-foreground">{readRuns ? writeRuns ? "Open the overview at the top left to choose a run or start a new one." : "Open the overview at the top left to choose a run. You have read access." : "No runs are shared with this user account."}</div>
@@ -230,7 +230,7 @@ export interface SessionStatusContribution {
230
230
  Status: ComponentType<SessionHeaderContext>;
231
231
  }
232
232
 
233
- /** A persistent application contribution in the overview or toolbar. */
233
+ /** A persistent application contribution in the overview, in the toolbar, or in the main area while no run is open (idle). */
234
234
  export interface OverviewPanelContext {
235
235
  registry: PluginRegistry;
236
236
  userLocation?: ChatUserLocation;
@@ -243,7 +243,7 @@ export interface OverviewPanelContext {
243
243
  }
244
244
 
245
245
  export interface OverviewPanelContribution {
246
- placement?: "overview" | "toolbar";
246
+ placement?: "overview" | "toolbar" | "idle";
247
247
  id: string;
248
248
  order: number;
249
249
  /** Right a user needs to see the panel; without it the panel is shown to everyone. */