pmx-canvas 0.7.3 → 0.8.2

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 (244) hide show
  1. package/.github/extensions/pmx-canvas/THIRD_PARTY_LICENSES.txt +331 -0
  2. package/.github/extensions/pmx-canvas/extension.mjs +25 -172
  3. package/.github/extensions/pmx-canvas/mcp-bootstrap.ts +198 -0
  4. package/.github/extensions/pmx-canvas/runtime.d.mts +41 -0
  5. package/.github/extensions/pmx-canvas/runtime.json +3 -0
  6. package/.github/extensions/pmx-canvas/runtime.mjs +194 -0
  7. package/.github/extensions/pmx-canvas/start-mcp.mjs +51 -0
  8. package/.github/extensions/pmx-canvas/tools.json +2560 -0
  9. package/CHANGELOG.md +64 -0
  10. package/Readme.md +21 -7
  11. package/dist/canvas/fonts/OFL.txt +93 -0
  12. package/dist/canvas/fonts/ibm-plex-mono-latin-400-normal.woff2 +0 -0
  13. package/dist/canvas/fonts/ibm-plex-mono-latin-500-normal.woff2 +0 -0
  14. package/dist/canvas/fonts/ibm-plex-mono-latin-ext-400-normal.woff2 +0 -0
  15. package/dist/canvas/fonts/ibm-plex-mono-latin-ext-500-normal.woff2 +0 -0
  16. package/dist/canvas/fonts/ibm-plex-sans-latin-400-normal.woff2 +0 -0
  17. package/dist/canvas/fonts/ibm-plex-sans-latin-500-normal.woff2 +0 -0
  18. package/dist/canvas/fonts/ibm-plex-sans-latin-600-normal.woff2 +0 -0
  19. package/dist/canvas/fonts/ibm-plex-sans-latin-ext-400-normal.woff2 +0 -0
  20. package/dist/canvas/fonts/ibm-plex-sans-latin-ext-500-normal.woff2 +0 -0
  21. package/dist/canvas/fonts/ibm-plex-sans-latin-ext-600-normal.woff2 +0 -0
  22. package/dist/canvas/global.css +726 -674
  23. package/dist/canvas/index.js +90 -88
  24. package/dist/canvas/mcp-app.html +7879 -0
  25. package/dist/canvas/mermaid-entry.js +1 -1
  26. package/dist/canvas/surface-theme.css +151 -46
  27. package/dist/json-render/index.css +81 -1
  28. package/dist/json-render/index.js +1 -1
  29. package/dist/types/cli/commands/record.d.ts +1 -1
  30. package/dist/types/client/canvas/NodeContextMark.d.ts +24 -0
  31. package/dist/types/client/canvas/SessionReceipt.d.ts +3 -1
  32. package/dist/types/client/icons.d.ts +1 -2
  33. package/dist/types/client/mcp-app/index.d.ts +1 -0
  34. package/dist/types/client/nodes/HtmlNode.d.ts +1 -0
  35. package/dist/types/client/nodes/ax-node-actions.d.ts +2 -2
  36. package/dist/types/client/nodes/markdown-sanitize.d.ts +2 -0
  37. package/dist/types/client/nodes/use-workbench-asset.d.ts +2 -0
  38. package/dist/types/client/state/attention-store.d.ts +0 -5
  39. package/dist/types/client/state/context-status-store.d.ts +53 -0
  40. package/dist/types/client/state/intent-bridge.d.ts +3 -0
  41. package/dist/types/client/state/near-pin-store.d.ts +16 -0
  42. package/dist/types/client/state/presence-store.d.ts +5 -0
  43. package/dist/types/client/state/session-store.d.ts +33 -3
  44. package/dist/types/client/state/workbench-transport.d.ts +16 -0
  45. package/dist/types/client/theme/tokens.d.ts +1 -3
  46. package/dist/types/client/types.d.ts +9 -0
  47. package/dist/types/json-render/server.d.ts +1 -1
  48. package/dist/types/mcp/app-server.d.ts +3 -0
  49. package/dist/types/mcp/canvas-access.d.ts +1 -1
  50. package/dist/types/mcp/canvas-app.d.ts +4 -0
  51. package/dist/types/mcp/workbench-app.d.ts +4 -0
  52. package/dist/types/server/agent-presence.d.ts +1 -1
  53. package/dist/types/server/ax-state.d.ts +1 -1
  54. package/dist/types/server/canvas-db.d.ts +8 -0
  55. package/dist/types/server/canvas-geometry.d.ts +25 -0
  56. package/dist/types/server/canvas-operations.d.ts +1 -11
  57. package/dist/types/server/canvas-state.d.ts +25 -3
  58. package/dist/types/server/context-brief.d.ts +8 -1
  59. package/dist/types/server/context-reads.d.ts +30 -7
  60. package/dist/types/server/index.d.ts +6 -1
  61. package/dist/types/server/mcp-app-runtime.d.ts +1 -0
  62. package/dist/types/server/operations/http.d.ts +2 -0
  63. package/dist/types/server/operations/invoker.d.ts +4 -2
  64. package/dist/types/server/operations/ops/nodes.d.ts +0 -6
  65. package/dist/types/server/server.d.ts +1 -0
  66. package/dist/types/server/spatial-analysis.d.ts +2 -0
  67. package/dist/types/shared/agent-context.d.ts +22 -0
  68. package/dist/types/shared/agent-presence.d.ts +3 -10
  69. package/dist/types/shared/canvas-app.d.ts +54 -0
  70. package/dist/types/shared/themes.d.ts +1 -1
  71. package/docs/RELEASE.md +7 -3
  72. package/docs/agent-plugin.md +123 -0
  73. package/docs/ax-state-contract.md +40 -0
  74. package/docs/cli.md +7 -2
  75. package/docs/design/AgentContext.dc.html +186 -0
  76. package/docs/design/Before.dc.html +208 -0
  77. package/docs/design/BoardPins.dc.html +151 -0
  78. package/docs/design/Chrome.dc.html +211 -0
  79. package/docs/design/Context.dc.html +239 -0
  80. package/docs/design/Flows.dc.html +181 -0
  81. package/docs/design/Home.dc.html +209 -0
  82. package/docs/design/HomeGraph.dc.html +211 -0
  83. package/docs/design/HomeMap.dc.html +117 -0
  84. package/docs/design/HomeTeam.dc.html +176 -0
  85. package/docs/design/Light.dc.html +28 -0
  86. package/docs/design/Main.dc.html +280 -0
  87. package/docs/design/NearPin.dc.html +260 -0
  88. package/docs/design/Pane600.dc.html +120 -0
  89. package/docs/design/Relations.dc.html +297 -0
  90. package/docs/design/Themes.dc.html +121 -0
  91. package/docs/design/TokenSystem.dc.html +136 -0
  92. package/docs/design/Tokens.dc.html +163 -0
  93. package/docs/design/Types1.dc.html +177 -0
  94. package/docs/design/Types2.dc.html +226 -0
  95. package/docs/design/Types3.dc.html +195 -0
  96. package/docs/design/Uses.dc.html +152 -0
  97. package/docs/design/Vision.dc.html +116 -0
  98. package/docs/design/Zoom.dc.html +82 -0
  99. package/docs/design/canvas.json +274 -0
  100. package/docs/design.md +217 -0
  101. package/docs/environment.md +1 -1
  102. package/docs/http-api.md +86 -16
  103. package/docs/mcp.md +202 -4
  104. package/docs/node-types.md +34 -10
  105. package/docs/plans/plan-009-tech-debt-backlog.md +1 -1
  106. package/docs/plans/plan-015-design-foundation-wave-0.md +177 -0
  107. package/docs/plans/plan-016-context-made-visible-wave-1.md +148 -0
  108. package/docs/product-vision-2026-09.md +47 -7
  109. package/docs/screenshot.png +0 -0
  110. package/docs/sdk.md +1 -0
  111. package/package.json +10 -4
  112. package/plugins/pmx-canvas/LICENSE +21 -0
  113. package/plugins/pmx-canvas/THIRD_PARTY_LICENSES.txt +331 -0
  114. package/plugins/pmx-canvas/assets/preview.png +0 -0
  115. package/plugins/pmx-canvas/com.github.copilot/extensions/pmx-canvas/extension.mjs +930 -0
  116. package/plugins/pmx-canvas/com.github.copilot/extensions/pmx-canvas/runtime.json +3 -0
  117. package/plugins/pmx-canvas/com.github.copilot/extensions/pmx-canvas/runtime.mjs +194 -0
  118. package/plugins/pmx-canvas/com.github.copilot/extensions/pmx-canvas/steering-delivery.mjs +79 -0
  119. package/plugins/pmx-canvas/mcp.json +12 -0
  120. package/plugins/pmx-canvas/plugin.json +24 -0
  121. package/plugins/pmx-canvas/runtime.json +3 -0
  122. package/plugins/pmx-canvas/runtime.mjs +194 -0
  123. package/plugins/pmx-canvas/start-mcp.mjs +51 -0
  124. package/plugins/pmx-canvas/tools.json +2560 -0
  125. package/skills/pmx-canvas/SKILL.md +29 -9
  126. package/skills/pmx-canvas/evals/evals.json +62 -0
  127. package/skills/pmx-canvas/references/ax-html-control-surface.md +6 -0
  128. package/skills/pmx-canvas/references/full-reference.md +11 -7
  129. package/skills/pmx-canvas/references/github-copilot-app-adapter.md +20 -8
  130. package/skills/pmx-canvas/references/installing-pmx-canvas.md +6 -6
  131. package/skills/pmx-canvas-testing/SKILL.md +5 -4
  132. package/src/cli/commands/copilot.ts +5 -0
  133. package/src/cli/commands/nodes.ts +3 -2
  134. package/src/cli/commands/view.ts +1 -1
  135. package/src/cli/index.ts +10 -4
  136. package/src/client/App.tsx +6 -1
  137. package/src/client/canvas/AgentPresenceLayer.tsx +3 -3
  138. package/src/client/canvas/AnnotationLayer.tsx +1 -1
  139. package/src/client/canvas/CanvasNode.tsx +32 -49
  140. package/src/client/canvas/CanvasViewport.tsx +0 -2
  141. package/src/client/canvas/CommandPalette.tsx +3 -2
  142. package/src/client/canvas/ContextMenu.tsx +11 -0
  143. package/src/client/canvas/EdgeLayer.tsx +1 -1
  144. package/src/client/canvas/ExportDialog.tsx +33 -6
  145. package/src/client/canvas/IntentLayer.tsx +2 -2
  146. package/src/client/canvas/Minimap.tsx +12 -7
  147. package/src/client/canvas/NodeContextMark.tsx +156 -0
  148. package/src/client/canvas/SessionPanel.tsx +4 -7
  149. package/src/client/canvas/SessionReceipt.tsx +114 -17
  150. package/src/client/canvas/ShortcutOverlay.tsx +6 -1
  151. package/src/client/canvas/SnapshotPanel.tsx +11 -2
  152. package/src/client/canvas/ToolRail.tsx +12 -9
  153. package/src/client/canvas/TopBar.tsx +16 -11
  154. package/src/client/icons.tsx +2 -12
  155. package/src/client/mcp-app/index.tsx +137 -0
  156. package/src/client/mcp-app/style.css +10 -0
  157. package/src/client/nodes/AttachmentNode.tsx +8 -1
  158. package/src/client/nodes/AxStepControls.tsx +1 -1
  159. package/src/client/nodes/ContextNode.tsx +9 -9
  160. package/src/client/nodes/ExtAppFrame.tsx +13 -8
  161. package/src/client/nodes/FileNode.tsx +8 -5
  162. package/src/client/nodes/HtmlNode.tsx +12 -2
  163. package/src/client/nodes/ImageNode.tsx +4 -2
  164. package/src/client/nodes/InlineMarkdownEditor.tsx +2 -1
  165. package/src/client/nodes/LedgerNode.tsx +2 -2
  166. package/src/client/nodes/MarkdownNode.tsx +44 -9
  167. package/src/client/nodes/McpAppNode.tsx +6 -4
  168. package/src/client/nodes/PromptNode.tsx +5 -17
  169. package/src/client/nodes/ResponseNode.tsx +3 -15
  170. package/src/client/nodes/StatusNode.tsx +2 -2
  171. package/src/client/nodes/StatusSummary.tsx +3 -1
  172. package/src/client/nodes/TraceNode.tsx +6 -4
  173. package/src/client/nodes/WebpageNode.tsx +1 -1
  174. package/src/client/nodes/ax-node-actions.ts +2 -2
  175. package/src/client/nodes/iframe-document-url.ts +3 -2
  176. package/src/client/nodes/markdown-sanitize.ts +10 -0
  177. package/src/client/nodes/surface-url.ts +10 -0
  178. package/src/client/nodes/use-surface-frame.ts +3 -1
  179. package/src/client/nodes/use-workbench-asset.ts +26 -0
  180. package/src/client/state/attention-bridge.ts +0 -8
  181. package/src/client/state/attention-store.ts +0 -17
  182. package/src/client/state/canvas-store.ts +4 -2
  183. package/src/client/state/context-status-store.ts +66 -0
  184. package/src/client/state/human-store.ts +2 -0
  185. package/src/client/state/iframe-mode.ts +5 -0
  186. package/src/client/state/intent-bridge.ts +10 -4
  187. package/src/client/state/near-pin-store.ts +53 -0
  188. package/src/client/state/presence-store.ts +5 -10
  189. package/src/client/state/session-store.ts +106 -9
  190. package/src/client/state/sse-bridge.ts +26 -7
  191. package/src/client/state/theme-override.ts +1 -1
  192. package/src/client/state/workbench-transport.ts +36 -0
  193. package/src/client/theme/global.css +726 -674
  194. package/src/client/theme/surface-theme.css +151 -46
  195. package/src/client/theme/tokens.ts +7 -11
  196. package/src/client/types.ts +10 -0
  197. package/src/json-render/renderer/index.css +6 -1
  198. package/src/json-render/renderer/index.tsx +0 -1
  199. package/src/json-render/server.ts +71 -14
  200. package/src/mcp/app-server.ts +64 -0
  201. package/src/mcp/canvas-access.ts +14 -11
  202. package/src/mcp/canvas-app.ts +318 -0
  203. package/src/mcp/server.ts +1 -1
  204. package/src/mcp/workbench-app.ts +211 -0
  205. package/src/server/agent-presence.ts +45 -6
  206. package/src/server/ax-context.ts +1 -1
  207. package/src/server/ax-state.ts +1 -1
  208. package/src/server/board-export.ts +5 -2
  209. package/src/server/canvas-db.ts +46 -12
  210. package/src/server/canvas-geometry.ts +64 -0
  211. package/src/server/canvas-operations.ts +7 -25
  212. package/src/server/canvas-state.ts +105 -15
  213. package/src/server/canvas-validation.ts +19 -4
  214. package/src/server/context-brief.ts +39 -2
  215. package/src/server/context-reads.ts +87 -15
  216. package/src/server/demo-state.json +31 -31
  217. package/src/server/html-surface.ts +4 -5
  218. package/src/server/index.ts +41 -5
  219. package/src/server/mcp-app-runtime.ts +11 -0
  220. package/src/server/operations/composites.ts +4 -3
  221. package/src/server/operations/http.ts +4 -4
  222. package/src/server/operations/invoker.ts +13 -4
  223. package/src/server/operations/mcp.ts +6 -0
  224. package/src/server/operations/ops/ax-read.ts +1 -1
  225. package/src/server/operations/ops/ax-timeline.ts +37 -0
  226. package/src/server/operations/ops/boards.ts +1 -1
  227. package/src/server/operations/ops/canvas-wire.ts +3 -6
  228. package/src/server/operations/ops/intent.ts +31 -2
  229. package/src/server/operations/ops/json-render.ts +6 -2
  230. package/src/server/operations/ops/nodes.ts +8 -76
  231. package/src/server/operations/ops/query.ts +8 -2
  232. package/src/server/operations/ops/snapshots.ts +4 -1
  233. package/src/server/operations/ops/viewport.ts +29 -5
  234. package/src/server/operations/registry.ts +41 -5
  235. package/src/server/scope-fence.ts +55 -10
  236. package/src/server/server.ts +83 -5
  237. package/src/server/spatial-analysis.ts +2 -2
  238. package/src/server/workboard.ts +6 -1
  239. package/src/{server → shared}/agent-context.ts +2 -2
  240. package/src/shared/agent-presence.ts +3 -15
  241. package/src/shared/canvas-app.ts +62 -0
  242. package/src/shared/themes.ts +5 -5
  243. package/src/client/canvas/FocusFieldLayer.tsx +0 -116
  244. package/src/client/canvas/kind-colors.ts +0 -23
@@ -920,4 +920,4 @@ html[data-jr-devtools-picking="true"] * {
920
920
  <path d="M16 21h1a2 2 0 0 0 2-2v-5a2 2 0 0 1 2-2 2 2 0 0 1-2-2V5a2 2 0 0 0-2-2h-1"/>
921
921
  </svg>`;function wte(){return{id:$2e,label:"Spec",badge(e){let t=e.getSpec();if(!t)return;return Object.keys(t.elements).length||void 0},mount(e,t){return q2e(e,t)}}}function q2e(e,t){let r=new Set,n=te("div",{className:"jr-split-left",role:"tree",tabindex:"0"}),a=te("div",{className:"jr-generations","aria-label":"Spec generation"}),o=null,i=null,s=te("nav",{className:"jr-breadcrumbs","aria-label":"Selected element ancestors"}),l=te("div",{className:"jr-breadcrumbs-trail"}),u=te("div",{className:"jr-breadcrumbs-tools",role:"group","aria-label":"Spec view"}),c=te("button",{className:"jr-view-btn",type:"button",title:"Tree view","aria-label":"Tree view","data-active":"true",onClick:()=>m("tree")});c.innerHTML=U2e;let f=te("button",{className:"jr-view-btn",type:"button",title:"Raw JSON view","aria-label":"Raw JSON view","data-active":"false",onClick:()=>m("raw")});f.innerHTML=V2e,u.append(c,f),s.append(l,u);let d=te("div",{className:"jr-tree-rows"});n.append(a,s,d);let p=te("div",{className:"jr-split-right"});e.appendChild(te("div",{className:"jr-split"},n,p));let g="tree";function m(z){if(g===z)return;g=z,c.dataset.active=String(g==="tree"),f.dataset.active=String(g==="raw"),j()}let y=t.selection.subscribe(()=>{let z=t.selection.get();if(z){let{spec:_,generations:O}=T();if(_&&!_.elements[z]&&O.length>1){let k=O.find((E)=>E.spec.elements[z]);if(k)o=k.id}}j()}),h=()=>oo(null);n.addEventListener("mouseleave",h);let v=[];function x(z){if(r.has(z))r.delete(z);else r.add(z);j()}function S(){n.querySelector('.jr-tree-row[data-selected="true"]')?.scrollIntoView({block:"nearest"})}function C(z){if(!z)return;t.selection.set(z),oo(z),S()}function P(z){if(g==="raw")return;if(z.metaKey||z.ctrlKey||z.altKey)return;let _=z.key;if(_!=="ArrowUp"&&_!=="ArrowDown"&&_!=="ArrowLeft"&&_!=="ArrowRight"&&_!=="Enter"&&_!==" "&&_!=="Home"&&_!=="End")return;let{spec:O}=T();if(!O||v.length===0)return;let k=t.selection.get(),E=k?v.indexOf(k):-1;if(z.preventDefault(),_==="ArrowDown"){if(E<0)C(v[0]);else C(v[Math.min(E+1,v.length-1)]);return}if(_==="ArrowUp"){if(E<0)C(v[0]);else C(v[Math.max(E-1,0)]);return}if(_==="Home"){C(v[0]);return}if(_==="End"){C(v[v.length-1]);return}if(_==="ArrowRight"){if(!k){C(v[0]);return}let D=O.elements[k],W=Ql(D);if(!(W.length>0))return;if(!r.has(k))r.add(k),j(),S();else C(W[0]);return}if(_==="ArrowLeft"){if(!k)return;let D=O.elements[k];if(Ql(D).length>0&&r.has(k))r.delete(k),j(),S();else{let K=K2e(O,k);if(K)C(K)}return}if(!k){C(v[0]);return}let L=O.elements[k];if(Ql(L).length>0)x(k),S()}let A=()=>{let z=t.selection.get();if(z)oo(z)},I=(z)=>{let _=z.relatedTarget;if(!_||!n.contains(_))oo(null)},R=()=>{try{n.focus({preventScroll:!0})}catch{}};n.addEventListener("mousedown",R),n.addEventListener("keydown",P),n.addEventListener("focusin",A),n.addEventListener("focusout",I);function T(){let z=t.getSpecs?.()??[];if(z.length===0)return{spec:t.getSpec(),generations:z};let _=z[z.length-1];if(o==null||!z.some((k)=>k.id===o))o=_.id;else if(i!=null&&o===i&&i!==_.id)o=_.id;return i=_.id,{spec:z.find((k)=>k.id===o).spec,generations:z}}function N(z){if(z.length<2){zt(a,null);return}let _=z[z.length-1].id,O=te("select",{className:"jr-generation-select","aria-label":"Inspect generation",onChange:(E)=>{o=E.target.value,j()}},...z.map((E,L)=>te("option",{value:E.id,selected:E.id===o?"true":void 0},E.id===_?`Gen ${L+1} (latest)`:`Gen ${L+1}`))),k=te("span",{className:"jr-generations-count"},`${z.length} generation${z.length===1?"":"s"}`);zt(a,O,k)}function j(){let{spec:z,generations:_}=T();if(N(_),!z||!z.root||Object.keys(z.elements).length===0){v=[],Z(null,null),zt(d,te("div",{className:"jr-empty"},"No spec attached.")),zt(p,null);return}let O=G2e(z),k=t.selection.get(),E=k?Z2e(z,k):[];for(let L of E)r.add(L);if(v=H2e(z,r),Z(z,E),g==="raw")q(z);else zt(d,Cte(z,z.root,0,r,k,O,t,x,null));if(k&&z.elements[k])Y2e(p,z,k,O);else zt(p,te("div",{className:"jr-empty"},"Select an element to inspect."))}function q(z){let _;try{_=JSON.stringify(z,null,2)}catch{_=String(z)}zt(d,te("pre",{className:"jr-raw"},_))}function Z(z,_){if(!z||!_||_.length===0){zt(l,te("span",{className:"jr-breadcrumbs-empty"},"No element selected"));return}let O=[..._].reverse(),k=[];O.forEach((E,L)=>{let W=z.elements[E]?.type??"<missing>",K=L===O.length-1,Y=te("button",{className:"jr-breadcrumb",type:"button","data-current":String(K),title:`#${E}`,onClick:(ae)=>{ae.stopPropagation(),t.selection.set(E),oo(E)},onMouseEnter:()=>oo(E),onMouseLeave:()=>oo(null)},W);if(k.push(Y),!K)k.push(te("span",{className:"jr-breadcrumb-sep"},"▸"))}),zt(l,k)}return j(),{update:j,destroy(){y(),n.removeEventListener("mouseleave",h),n.removeEventListener("mousedown",R),n.removeEventListener("keydown",P),n.removeEventListener("focusin",A),n.removeEventListener("focusout",I),oo(null)}}}function H2e(e,t){let r=[];function n(a){r.push(a);let o=e.elements[a],i=Ql(o);if(i.length===0)return;if(!t.has(a))return;for(let s of i)n(s)}return n(e.root),r}function K2e(e,t){for(let[r,n]of Object.entries(e.elements))if(Ql(n).includes(t))return r;return null}function Ql(e){if(!e)return[];return[...e.children??[],...Object.values(e.slots??{}).flat()]}function G2e(e){let t=$j(e,{checkOrphans:!0}),r=new Map;for(let n of t.issues){let a=n.elementKey??"__spec__",o=r.get(a)??[];o.push(n),r.set(a,o)}return{all:t.issues,byKey:r}}function Z2e(e,t){let r=[];function n(a){if(a===t)return r.push(a),!0;let o=e.elements[a];for(let i of Ql(o))if(n(i))return r.push(a),!0;return!1}return n(e.root),r}function Cte(e,t,r,n,a,o,i,s,l){let u=e.elements[t];if(!u)return te("div",{className:"jr-tree-row",style:{paddingLeft:`${12+r*14}px`}},te("span",{className:"jr-tree-toggle"}," "),te("span",{className:"jr-tree-type"},"<missing>"),te("span",{className:"jr-tree-key"},t));let c=Ql(u),f=c.length>0,d=f&&n.has(t),p=a===t,g=o.byKey.get(t)??[],m=g.some((S)=>S.severity==="error"),y=W2e(u),h=u.visible!==void 0?null:l,v=te("div",{className:`jr-tree-row${h===!0?" jr-tree-hidden":""}`,"data-selected":String(p),style:{paddingLeft:`${8+r*14}px`},onClick:(S)=>{S.stopPropagation(),i.selection.set(t)},onMouseEnter:()=>{oo(t)},onMouseLeave:()=>{oo(null)}},te("span",{className:"jr-tree-toggle",onClick:(S)=>{if(S.stopPropagation(),f)s(t)}},f?d?"▾":"▸":" "),te("span",{className:"jr-tree-type"},u.type),te("span",{className:"jr-tree-key"},`#${t}`),y?te("span",{className:"jr-tree-summary"},y):null,u.visible!==void 0?te("span",{className:"jr-badge","data-tone":"amber"},"visible"):null,u.repeat?te("span",{className:"jr-badge","data-tone":"accent"},"repeat"):null,m?te("span",{className:"jr-badge","data-tone":"red",title:g.map((S)=>S.message).join(`
922
922
  `)},`${g.length}`):null),x=te("div",null,v);if(d&&f)for(let S of c){let C=Cte(e,S,r+1,n,a,o,i,s,h);if(C)x.appendChild(C)}return x}function W2e(e){let t=e.props;if(!t)return null;let r=["title","label","text","name","value","status"];for(let n of r){let a=t[n];if(typeof a==="string"&&a.length>0)return ste(a,60);if(typeof a==="number"||typeof a==="boolean")return String(a)}for(let[,n]of Object.entries(t)){if(typeof n==="string"&&n.length>0)return ste(n,60);if(typeof n==="number"||typeof n==="boolean")return String(n)}return null}function ste(e,t){if(e.length<=t)return e;return e.slice(0,t-1)+"…"}function Y2e(e,t,r,n){let a=t.elements[r];if(!a){zt(e,te("div",{className:"jr-empty"},`Element '${r}' not found.`));return}let o=n.byKey.get(r)??[],i=Ql(a).length;zt(e,te("div",{className:"jr-detail"},te("h4",null,"Element"),te("div",{style:{marginBottom:"10px"}},te("span",{className:"jr-tree-type"},a.type)," ",te("span",{className:"jr-tree-key"},`#${r}`)," ",te("span",{className:"jr-tree-summary"},`${i} child${i===1?"":"ren"}`)),o.length>0?[te("h4",null,"Issues"),...o.map((s)=>te("div",{className:"jr-badge","data-tone":s.severity==="error"?"red":"amber",style:{marginBottom:"6px",display:"block",padding:"4px 8px"}},`${s.severity.toUpperCase()}: ${s.message}`))]:null,a.visible!==void 0?[te("h4",null,"Visibility"),te("pre",null,tf(a.visible,2000))]:null,a.on&&Object.keys(a.on).length>0?[te("h4",null,"Events"),te("pre",null,tf(a.on,2000))]:null,a.watch&&Object.keys(a.watch).length>0?[te("h4",null,"Watchers"),te("pre",null,tf(a.watch,2000))]:null,a.repeat?[te("h4",null,"Repeat"),te("pre",null,tf(a.repeat,2000))]:null,te("h4",null,"Props"),te("pre",null,JSON.stringify(a.props,null,2))))}var X2e="state";function Ate(){return{id:X2e,label:"State",badge(e){let t=e.getStateStore();if(!t)return;try{let r=Ns(t.getSnapshot());return Object.keys(r).length||void 0}catch{return}},mount(e,t){return J2e(e,t)}}}function J2e(e,t){let r=te("div",{style:{height:"100%",display:"flex",flexDirection:"column"}}),n=te("div",{className:"jr-toolbar"}),a=te("div",{style:{overflow:"auto",flex:"1",minHeight:"0"}});r.appendChild(n),r.appendChild(a),e.appendChild(r);let o="",i=new Set,s=te("input",{className:"jr-search",type:"text",placeholder:"Filter paths…",onInput:(c)=>{o=(c.target.value||"").toLowerCase(),u()}});function l(){zt(n,s,te("button",{className:"jr-icon-btn",title:"Refresh state listing",onClick:()=>u()},"refresh"))}function u(){let c=t.getStateStore();if(!c){zt(a,te("div",{className:"jr-empty"},"No StateStore attached. Devtools sees state once a provider mounts."));return}let f={};try{f=Ns(c.getSnapshot())}catch(p){zt(a,te("div",{className:"jr-empty"},`State read failed: ${String(p)}`));return}let d=Object.entries(f).filter(([p])=>!o||p.toLowerCase().includes(o)).sort(([p],[g])=>p.localeCompare(g));if(d.length===0){zt(a,te("div",{className:"jr-empty"},o?"No paths match the filter.":"State is empty."));return}zt(a,d.map(([p,g])=>Q2e(p,g,c.set,i)))}return l(),u(),{update(){if(i.size===0)u()}}}function Q2e(e,t,r,n){let a=te("input",{className:"jr-state-value",type:"text",value:lte(t),spellcheck:"false",onFocus:()=>{n.add(e)},onBlur:(o)=>{n.delete(e);let i=o.target.value;try{let s=i===""?"":JSON.parse(i);r(e,s),a.dataset.dirty="false"}catch{r(e,i),a.dataset.dirty="false"}},onInput:()=>{a.dataset.dirty="true"},onKeyDown:(o)=>{if(o.key==="Enter")o.preventDefault(),o.target.blur();if(o.key==="Escape")a.value=lte(t),a.dataset.dirty="false",o.target.blur()}});return te("div",{className:"jr-state-row",title:`${e}
923
- ${tf(t,1000)}`},te("span",{className:"jr-state-path"},e),a)}function lte(e){if(typeof e==="string")return JSON.stringify(e);if(e===null)return"null";if(e===void 0)return"";if(typeof e==="number"||typeof e==="boolean")return String(e);try{return JSON.stringify(e)}catch{return String(e)}}var eze="actions";function Pte(){return{id:eze,label:"Actions",badge(e){return Ite(e.events.snapshot()).length||void 0},mount(e,t){return tze(e,t)}}}function tze(e,t){let r=te("div",{style:{height:"100%",display:"flex",flexDirection:"column"}}),n=te("div",{className:"jr-toolbar"}),a=te("div",{style:{overflow:"auto",flex:"1",minHeight:"0"}});r.appendChild(n),r.appendChild(a),e.appendChild(r);let o="",i=new Set,s=te("input",{className:"jr-search",type:"text",placeholder:"Filter by action name…",onInput:(f)=>{o=(f.target.value||"").toLowerCase(),c()}}),l=te("span",{className:"jr-badge"},"0 actions"),u=te("button",{className:"jr-icon-btn",title:"Clear action log",onClick:()=>{let f=t.events.snapshot().filter((d)=>d.kind!=="action-dispatched"&&d.kind!=="action-settled");t.events.clear();for(let d of f)t.events.push(d)}},"clear");n.append(s,l,u);function c(){let f=Ite(t.events.snapshot()).filter((d)=>!o||d.name.toLowerCase().includes(o)).reverse();if(l.textContent=`${f.length} action${f.length===1?"":"s"}`,f.length===0){zt(a,te("div",{className:"jr-empty"},o?"No actions match the filter.":"No actions dispatched yet."));return}zt(a,f.map((d)=>rze(d,i,c)))}return c(),{update:c}}function Ite(e){let t=new Map,r=[];for(let n of e)if(n.kind==="action-dispatched"){if(t.has(n.id))continue;t.set(n.id,{id:n.id,name:n.name,params:n.params,dispatchedAt:n.at}),r.push(n.id)}else if(n.kind==="action-settled"){let a=t.get(n.id);if(!a)continue;a.settledAt=n.at,a.durationMs=n.durationMs,a.ok=n.ok,a.result=n.result,a.error=n.error}return r.map((n)=>t.get(n)).filter(Boolean)}function rze(e,t,r){let n=t.has(e.id),a=e.settledAt===void 0,o=a?"amber":e.ok?"green":"red",i=a?"pending":e.ok?"ok":"error",s=e.durationMs!==void 0?`${e.durationMs.toFixed(0)}ms`:"",l=te("div",{className:"jr-row",onClick:()=>{if(n)t.delete(e.id);else t.add(e.id);r()}},te("span",{className:"jr-row-time"},mv(e.dispatchedAt)),te("span",{className:"jr-row-main"},te("strong",null,e.name),e.params!==void 0?te("span",{className:"jr-tree-summary",style:{marginLeft:"8px"}},tf(e.params,80)):null),te("span",{className:"jr-row-meta"},te("span",{className:"jr-badge","data-tone":o},i),s?te("span",{style:{marginLeft:"6px"}},s):null));if(!n)return l;let u=te("div",null,l);return u.appendChild(te("div",{className:"jr-row-expanded"},te("h4",null,"Params"),te("pre",null,JSON.stringify(e.params??null,null,2)),e.ok===!1?[te("h4",null,"Error"),te("pre",null,e.error??"(unknown error)")]:null,e.result!==void 0&&e.ok!==!1?[te("h4",null,"Result"),te("pre",null,JSON.stringify(e.result,null,2))]:null)),u}var nze="stream";function _te(){return{id:nze,label:"Stream",badge(e){return Ete(e.events.snapshot()).length||void 0},mount(e,t){return aze(e,t)}}}function aze(e,t){let r=te("div",{style:{height:"100%",display:"flex",flexDirection:"column"}}),n=te("div",{className:"jr-toolbar"}),a=te("div",{style:{overflow:"auto",flex:"1",minHeight:"0"}});r.appendChild(n),r.appendChild(a),e.appendChild(r);function o(){let i=t.events.snapshot(),s=Ete(i),l=oze(i);if(zt(n,te("span",{className:"jr-badge"},`${s.length} generation${s.length===1?"":"s"}`)),s.length===0&&l.length===0){zt(a,te("div",{className:"jr-empty"},"No stream events yet. Tap a stream or pass messages to capture patches."));return}let u=[];if(l.length>0)u.push(ute({startedAt:l[0]?.at??Date.now(),events:l},"live",!0));for(let c=s.length-1;c>=0;c--){let f=s[c];u.push(ute(f,`gen-${c}`,c===s.length-1))}zt(a,u)}return o(),{update:o}}function Ete(e){let t=[],r=null;for(let n of e){if(n.kind==="stream-lifecycle"){if(n.phase==="start"){if(r)t.push(r);r={startedAt:n.at,events:[]}}else{if(!r)r={startedAt:n.at,events:[]};r.endedAt=n.at,r.ok=n.ok,t.push(r),r=null}continue}if(n.kind==="stream-patch"||n.kind==="stream-text"||n.kind==="stream-usage"){if(!r)r={startedAt:n.at,events:[]};if(r.events.push(n),n.kind==="stream-usage")r.usage=n.usage}}if(r)t.push(r);return t}function oze(e){if(e.some((r)=>r.kind==="stream-lifecycle"))return[];return e.filter((r)=>r.kind==="stream-patch"||r.kind==="stream-text"||r.kind==="stream-usage")}function ute(e,t,r){let n=e.events.filter((c)=>c.kind==="stream-patch").length,a=e.events.filter((c)=>c.kind==="stream-text").length,o=e.endedAt!==void 0?e.endedAt-e.startedAt:void 0,i=e.endedAt===void 0?"amber":e.ok===!1?"red":"green",s=e.endedAt===void 0?"live":e.ok===!1?"error":"done",l=te("div",{style:{borderTop:"1px solid var(--jr-border)",background:"var(--jr-bg-soft)",display:r?"block":"none"}},...e.events.map(ize)),u=te("div",{className:"jr-row",style:{cursor:"pointer"},onClick:()=>{l.style.display=l.style.display==="none"?"block":"none"}},te("span",{className:"jr-row-time"},mv(e.startedAt)),te("span",{className:"jr-row-main"},te("strong",null,`generation #${t}`),te("span",{className:"jr-tree-summary",style:{marginLeft:"8px"}},`${n} patch${n===1?"":"es"}`,a>0?`, ${a} text chunk${a===1?"":"s"}`:"")),te("span",{className:"jr-row-meta"},te("span",{className:"jr-badge","data-tone":i},s),o!==void 0?te("span",{style:{marginLeft:"6px"}},`${o}ms`):null,e.usage?te("span",{style:{marginLeft:"6px"}},`${TC(e.usage.totalTokens)} tok`):null));return te("div",null,u,l)}function ize(e){if(e.kind==="stream-patch")return te("div",{className:"jr-row"},te("span",{className:"jr-row-time"},mv(e.at)),te("span",{className:"jr-row-main"},te("span",{className:"jr-badge","data-tone":"accent"},e.patch.op),te("span",{className:"jr-tree-summary",style:{marginLeft:"8px"}},e.patch.path,e.patch.value!==void 0?` = ${tf(e.patch.value,80)}`:"")),te("span",{className:"jr-row-meta"},e.source));if(e.kind==="stream-text")return te("div",{className:"jr-row"},te("span",{className:"jr-row-time"},mv(e.at)),te("span",{className:"jr-row-main",style:{whiteSpace:"pre-wrap"}},e.text),te("span",{className:"jr-row-meta"},te("span",{className:"jr-badge"},"text")));if(e.kind==="stream-usage")return te("div",{className:"jr-row"},te("span",{className:"jr-row-time"},mv(e.at)),te("span",{className:"jr-row-main"},`prompt ${TC(e.usage.promptTokens)} / completion ${TC(e.usage.completionTokens)} / total ${TC(e.usage.totalTokens)}`),te("span",{className:"jr-row-meta"},te("span",{className:"jr-badge","data-tone":"accent"},"usage")));return te("div")}function TC(e){if(e>=1000)return`${(e/1000).toFixed(1).replace(/\.0$/,"")}k`;return String(e)}var sze="catalog";function Ote(){return{id:sze,label:"Catalog",badge(e){let t=e.getCatalog();if(!t)return;return t.componentNames.length+t.actionNames.length||void 0},mount(e,t){return lze(e,t)}}}function lze(e,t){let r=te("div",{style:{height:"100%",display:"flex",flexDirection:"column"}}),n=te("div",{className:"jr-toolbar"}),a=te("div",{style:{overflow:"auto",flex:"1",minHeight:"0"}});r.appendChild(n),r.appendChild(a),e.appendChild(r);let o="components",i="",s=te("button",{className:"jr-icon-btn","data-active":"true",onClick:()=>{if(o==="components")return;o="components",c(),f()}},"components"),l=te("button",{className:"jr-icon-btn","data-active":"false",onClick:()=>{if(o==="actions")return;o="actions",c(),f()}},"actions"),u=te("input",{className:"jr-search",type:"text",placeholder:"Filter by name…",onInput:(p)=>{i=(p.target.value||"").toLowerCase(),f()}});n.append(s,l,u);function c(){let p=t.getCatalog(),g=p?cte(p.data):null,m=g?.components.length??0,y=g?.actions.length??0;s.textContent=`components (${m})`,l.textContent=`actions (${y})`,s.dataset.active=String(o==="components"),l.dataset.active=String(o==="actions")}function f(){let p=t.getCatalog();if(!p){zt(a,te("div",{className:"jr-empty"},"No catalog attached. Pass `catalog` to `<JsonRenderDevtools>` to browse it here."));return}let g=cte(p.data);if(o==="components"){let m=g.components.filter((y)=>!i||y.name.toLowerCase().includes(i));if(m.length===0){zt(a,te("div",{className:"jr-empty"},"No components match."));return}zt(a,m.map(uze))}else{let m=g.actions.filter((y)=>!i||y.name.toLowerCase().includes(i));if(m.length===0){zt(a,te("div",{className:"jr-empty"},"No actions match."));return}zt(a,m.map(cze))}}function d(){c(),f()}return d(),{update:d}}function uze(e){return te("div",{className:"jr-catalog-item"},te("div",{className:"jr-catalog-name"},e.name),e.description?te("div",{className:"jr-catalog-desc"},e.description):null,e.props.length>0||e.events.length>0?te("div",{className:"jr-chips"},...e.props.map((t)=>te("span",{className:"jr-chip","data-tone":"prop"},`${t.name}: ${t.type}`)),...e.events.map((t)=>te("span",{className:"jr-chip","data-tone":"event"},`on.${t}`))):null)}function cze(e){return te("div",{className:"jr-catalog-item"},te("div",{className:"jr-catalog-name"},e.name),e.description?te("div",{className:"jr-catalog-desc"},e.description):null,e.params.length>0?te("div",{className:"jr-chips"},...e.params.map((t)=>te("span",{className:"jr-chip","data-tone":"param"},`${t.name}: ${t.type}`))):null)}function cte(e){let t=e??{},r=t.components??{},n=t.actions??{},a=Object.entries(r).map(([i,s])=>{let l=s??{};return{name:i,description:l.description??"",props:fte(l.props),slots:Array.isArray(l.slots)?l.slots:[],events:Array.isArray(l.events)?l.events:[]}}).sort((i,s)=>i.name.localeCompare(s.name)),o=Object.entries(n).map(([i,s])=>{let l=s??{};return{name:i,description:l.description??"",params:fte(l.params)}}).sort((i,s)=>i.name.localeCompare(s.name));return{components:a,actions:o}}function fte(e){if(!e)return[];try{let t=e,r=typeof t.shape==="object"&&t.shape!==null?t.shape:typeof t._def?.shape==="function"?t._def.shape():typeof t._def?.shape==="object"?t._def.shape:null;if(!r)return[];return Object.entries(r).map(([n,a])=>{let o="unknown";try{let i=a,s=i?._zod?.def?.type??i?._def?.typeName??"";if(s.includes("string"))o="string";else if(s.includes("number"))o="number";else if(s.includes("boolean"))o="boolean";else if(s.includes("array"))o="array";else if(s.includes("enum")){let l=i?._zod?.def?.values??i?._def?.values;o=Array.isArray(l)?l.join(" | "):"enum"}else if(s.includes("union"))o="union";else if(s.includes("nullable")){let l=i?._zod?.def?.innerType??i?._def?.innerType,u=l?._zod?.def?.type??l?._def?.typeName??"";if(u.includes("string"))o="string?";else if(u.includes("number"))o="number?";else if(u.includes("boolean"))o="boolean?";else if(u.includes("array"))o="array?";else if(u.includes("enum")){let c=l?._zod?.def?.values??l?._def?.values;o=Array.isArray(c)?`(${c.join(" | ")})?`:"enum?"}else o="optional"}}catch{}return{name:n,type:o}})}catch{return[]}}function Rte(e,t,r){if(!e)return;for(let n of e){if(!n||typeof n!=="object")continue;if(r.has(n))continue;if(r.add(n),n.type===Hp){let a=n.data;if(!a)continue;if(a.type==="patch")t.push({kind:"stream-patch",at:Date.now(),patch:a.patch,source:"json"})}}}function Lte(e){if(!e)return null;let t={root:"",elements:{}},r=!1;for(let n of e){if(!n||typeof n!=="object")continue;if(n.type!==Hp)continue;let a=n.data;if(!a)continue;if(a.type==="patch")r=!0,Kv(t,a.patch);else if(a.type==="flat")r=!0,Object.assign(t,a.spec);else if(a.type==="nested")r=!0,Object.assign(t,Gv(a.spec))}return r?t:null}function fze(e,t){let r=[];if(e){let n=0;for(let a of e){let o=Lte(a?.parts);if(!o||Object.keys(o.elements).length===0)continue;n+=1,r.push({id:a?.id??`gen-${n}`,label:`Generation ${n}`,spec:o})}}if(r.length===0&&t)r.push({id:"spec",label:"Current spec",spec:t});return r}var kte=null;function Tte(e){if(pte())return null;let t=M(e.spec??null);t.current=e.spec??null;let r=M(e.catalog??null);r.current=e.catalog??null;let n=M(e.messages);n.current=e.messages;let a=Gi(),o=M(null);o.current={get:a.get,set:a.set,update:a.update,getSnapshot:a.getSnapshot,subscribe:()=>()=>{}};let i=he(()=>dte({bufferSize:e.bufferSize}),[e.bufferSize]);G(()=>{if(!e.onEvent)return;return i.subscribe(()=>{let u=i.snapshot(),c=u[u.length-1];if(c)e.onEvent?.(c)})},[i,e.onEvent]),G(()=>Tj({onDispatch(u){i.push({kind:"action-dispatched",at:u.at,id:u.id,name:u.name,params:u.params})},onSettle(u){i.push({kind:"action-settled",at:u.at,id:u.id,ok:u.ok,durationMs:u.durationMs,result:u.result,error:u.error!==void 0?String(u.error):void 0})}}),[i]),G(()=>{l.current?.refresh()});let s=M(new WeakSet);G(()=>{if(!e.messages)return;for(let u of e.messages)if(u?.parts)Rte(u.parts,i,s.current)},[e.messages,i]);let l=M(null);return G(()=>{if(l.current)return;let u=Ste(),f=bte({context:{events:i,getSpec:()=>t.current,getSpecs:()=>fze(n.current,t.current),getCatalog:()=>r.current,getStateStore:()=>o.current,startPicker:(g)=>gte(g),selection:u,activateTab:()=>{}},tabs:[wte(),Ate(),Pte(),_te(),Ote()],initialOpen:e.initialOpen,position:e.position,hotkey:e.hotkey,reserveSpace:e.reserveSpace,allowDockToggle:e.allowDockToggle});l.current=f;let d=u.subscribe((g)=>{if(g)vte(g)});kte={open:()=>f.open(),close:()=>f.close(),toggle:()=>f.toggle(),recordEvent:(g)=>i.push(g),clear:()=>i.clear()};let p=jj();return()=>{d(),p(),f.destroy(),l.current=null,kte=null}},[i,e.initialOpen,e.position,e.hotkey,e.reserveSpace,e.allowDockToggle]),null}function dze({props:e}){let r=e.variant??"default";return b("span",{"data-slot":"badge","data-variant":r,className:`pmx-badge pmx-badge--${r}`,children:e.text})}function pze({props:e,emit:t}){let r=e.variant??"primary";return b("button",{type:"button","data-slot":"button","data-variant":r,className:`pmx-button pmx-button--${r}`,disabled:e.disabled??!1,onClick:()=>t("press"),children:e.label})}function mze({props:e,children:t,slots:r,...n}){let a=r?.header,o=r?.footer;return le(PO.Card,{...n,props:a?{...e,title:null,description:null}:e,children:[a&&b("header",{"data-pmx-card-slot":"header",children:a}),t,o&&b("footer",{"data-pmx-card-slot":"footer",className:"flex flex-wrap items-center gap-3",children:o})]})}var{registry:Dte}=nU(d5,{components:{...PO,Card:mze,Badge:dze,Button:pze,...Qee,...ete,...tte}}),hze=["ax.event.record","ax.steer","ax.work.create","ax.work.update","ax.evidence.add","ax.approval.request","ax.review.add","ax.focus.set","ax.elicitation.request","ax.mode.request","ax.command.invoke"];function gze(){let{__PMX_CANVAS_JSON_RENDER_NODE_ID__:e,__PMX_CANVAS_AX_TOKEN__:t}=window,r={};if(!e||!t)return r;for(let n of hze)r[n]=(a)=>{window.parent.postMessage({source:qj,token:t,nodeId:e,interaction:{type:n,payload:a&&typeof a==="object"?a:{}}},"*")};return r}function vze(){let e=window.__PMX_CANVAS_JSON_RENDER_THEME__;if(e){Mte(e);return}let t=window.matchMedia?.("(prefers-color-scheme: dark)").matches??!1;Mte(t?"dark":"light")}function Mte(e){if(e!=="dark"&&e!=="light"&&e!=="high-contrast")return;document.documentElement.setAttribute("data-theme",e),document.documentElement.classList.toggle("dark",e==="dark"||e==="high-contrast"),document.documentElement.style.colorScheme=e==="light"?"light":"dark"}function yze({store:e}){let t=window.__PMX_CANVAS_JSON_RENDER_SPEC__;if(!t)return b("div",{style:{height:"100vh",display:"flex",alignItems:"center",justifyContent:"center",color:"var(--muted-foreground, #666)",fontFamily:"system-ui"},children:"Waiting for UI spec..."});let r=window.__PMX_CANVAS_JSON_RENDER_DISPLAY__==="site";return b("div",{style:r?{display:"flex",flexDirection:"column",height:"100dvh",minHeight:"100dvh",padding:0,boxSizing:"border-box"}:{minHeight:"100vh",padding:16,boxSizing:"border-box"},children:le(rU,{registry:Dte,store:e,directives:IO,handlers:gze(),children:[b("div",{style:r?{flex:1,minHeight:0}:void 0,children:b(tU,{spec:t,registry:Dte,loading:!1})}),window.__PMX_CANVAS_JSON_RENDER_DEVTOOLS__?b(Tte,{position:"right"}):null]})})}var Nte=document.getElementById("root");if(Nte){vze();let e=window.__PMX_CANVAS_UI_STATE_TOKEN__,t,r=(n)=>{if(t)return;let a=n??window.__PMX_CANVAS_JSON_RENDER_SPEC__?.state??{},o=window.__PMX_CANVAS_AX_STATE__;if(t=af(o!=null?{...a,ax:o}:a),e)t.subscribe(()=>{let{ax:i,...s}=t.getSnapshot();window.parent.postMessage({source:kA,type:"snapshot",token:e,nodeId:window.__PMX_CANVAS_JSON_RENDER_NODE_ID__,state:s},"*")});S_(Nte).render(b(yze,{store:t}))};if(window.addEventListener("message",(n)=>{if(n.source!==window.parent)return;let a=n.data;if(!a)return;if(a.source===kA&&a.type==="restore"&&e&&a.token===e){if(a.state===null||typeof a.state==="object"&&!Array.isArray(a.state))r(a.state)}if(a.source===Hj&&a.type==="ax-update"&&window.__PMX_CANVAS_AX_TOKEN__&&a.token===window.__PMX_CANVAS_AX_TOKEN__)window.__PMX_CANVAS_AX_STATE__=a.state,t?.set("/ax",a.state)}),!e)r(null)}
923
+ ${tf(t,1000)}`},te("span",{className:"jr-state-path"},e),a)}function lte(e){if(typeof e==="string")return JSON.stringify(e);if(e===null)return"null";if(e===void 0)return"";if(typeof e==="number"||typeof e==="boolean")return String(e);try{return JSON.stringify(e)}catch{return String(e)}}var eze="actions";function Pte(){return{id:eze,label:"Actions",badge(e){return Ite(e.events.snapshot()).length||void 0},mount(e,t){return tze(e,t)}}}function tze(e,t){let r=te("div",{style:{height:"100%",display:"flex",flexDirection:"column"}}),n=te("div",{className:"jr-toolbar"}),a=te("div",{style:{overflow:"auto",flex:"1",minHeight:"0"}});r.appendChild(n),r.appendChild(a),e.appendChild(r);let o="",i=new Set,s=te("input",{className:"jr-search",type:"text",placeholder:"Filter by action name…",onInput:(f)=>{o=(f.target.value||"").toLowerCase(),c()}}),l=te("span",{className:"jr-badge"},"0 actions"),u=te("button",{className:"jr-icon-btn",title:"Clear action log",onClick:()=>{let f=t.events.snapshot().filter((d)=>d.kind!=="action-dispatched"&&d.kind!=="action-settled");t.events.clear();for(let d of f)t.events.push(d)}},"clear");n.append(s,l,u);function c(){let f=Ite(t.events.snapshot()).filter((d)=>!o||d.name.toLowerCase().includes(o)).reverse();if(l.textContent=`${f.length} action${f.length===1?"":"s"}`,f.length===0){zt(a,te("div",{className:"jr-empty"},o?"No actions match the filter.":"No actions dispatched yet."));return}zt(a,f.map((d)=>rze(d,i,c)))}return c(),{update:c}}function Ite(e){let t=new Map,r=[];for(let n of e)if(n.kind==="action-dispatched"){if(t.has(n.id))continue;t.set(n.id,{id:n.id,name:n.name,params:n.params,dispatchedAt:n.at}),r.push(n.id)}else if(n.kind==="action-settled"){let a=t.get(n.id);if(!a)continue;a.settledAt=n.at,a.durationMs=n.durationMs,a.ok=n.ok,a.result=n.result,a.error=n.error}return r.map((n)=>t.get(n)).filter(Boolean)}function rze(e,t,r){let n=t.has(e.id),a=e.settledAt===void 0,o=a?"amber":e.ok?"green":"red",i=a?"pending":e.ok?"ok":"error",s=e.durationMs!==void 0?`${e.durationMs.toFixed(0)}ms`:"",l=te("div",{className:"jr-row",onClick:()=>{if(n)t.delete(e.id);else t.add(e.id);r()}},te("span",{className:"jr-row-time"},mv(e.dispatchedAt)),te("span",{className:"jr-row-main"},te("strong",null,e.name),e.params!==void 0?te("span",{className:"jr-tree-summary",style:{marginLeft:"8px"}},tf(e.params,80)):null),te("span",{className:"jr-row-meta"},te("span",{className:"jr-badge","data-tone":o},i),s?te("span",{style:{marginLeft:"6px"}},s):null));if(!n)return l;let u=te("div",null,l);return u.appendChild(te("div",{className:"jr-row-expanded"},te("h4",null,"Params"),te("pre",null,JSON.stringify(e.params??null,null,2)),e.ok===!1?[te("h4",null,"Error"),te("pre",null,e.error??"(unknown error)")]:null,e.result!==void 0&&e.ok!==!1?[te("h4",null,"Result"),te("pre",null,JSON.stringify(e.result,null,2))]:null)),u}var nze="stream";function _te(){return{id:nze,label:"Stream",badge(e){return Ete(e.events.snapshot()).length||void 0},mount(e,t){return aze(e,t)}}}function aze(e,t){let r=te("div",{style:{height:"100%",display:"flex",flexDirection:"column"}}),n=te("div",{className:"jr-toolbar"}),a=te("div",{style:{overflow:"auto",flex:"1",minHeight:"0"}});r.appendChild(n),r.appendChild(a),e.appendChild(r);function o(){let i=t.events.snapshot(),s=Ete(i),l=oze(i);if(zt(n,te("span",{className:"jr-badge"},`${s.length} generation${s.length===1?"":"s"}`)),s.length===0&&l.length===0){zt(a,te("div",{className:"jr-empty"},"No stream events yet. Tap a stream or pass messages to capture patches."));return}let u=[];if(l.length>0)u.push(ute({startedAt:l[0]?.at??Date.now(),events:l},"live",!0));for(let c=s.length-1;c>=0;c--){let f=s[c];u.push(ute(f,`gen-${c}`,c===s.length-1))}zt(a,u)}return o(),{update:o}}function Ete(e){let t=[],r=null;for(let n of e){if(n.kind==="stream-lifecycle"){if(n.phase==="start"){if(r)t.push(r);r={startedAt:n.at,events:[]}}else{if(!r)r={startedAt:n.at,events:[]};r.endedAt=n.at,r.ok=n.ok,t.push(r),r=null}continue}if(n.kind==="stream-patch"||n.kind==="stream-text"||n.kind==="stream-usage"){if(!r)r={startedAt:n.at,events:[]};if(r.events.push(n),n.kind==="stream-usage")r.usage=n.usage}}if(r)t.push(r);return t}function oze(e){if(e.some((r)=>r.kind==="stream-lifecycle"))return[];return e.filter((r)=>r.kind==="stream-patch"||r.kind==="stream-text"||r.kind==="stream-usage")}function ute(e,t,r){let n=e.events.filter((c)=>c.kind==="stream-patch").length,a=e.events.filter((c)=>c.kind==="stream-text").length,o=e.endedAt!==void 0?e.endedAt-e.startedAt:void 0,i=e.endedAt===void 0?"amber":e.ok===!1?"red":"green",s=e.endedAt===void 0?"live":e.ok===!1?"error":"done",l=te("div",{style:{borderTop:"1px solid var(--jr-border)",background:"var(--jr-bg-soft)",display:r?"block":"none"}},...e.events.map(ize)),u=te("div",{className:"jr-row",style:{cursor:"pointer"},onClick:()=>{l.style.display=l.style.display==="none"?"block":"none"}},te("span",{className:"jr-row-time"},mv(e.startedAt)),te("span",{className:"jr-row-main"},te("strong",null,`generation #${t}`),te("span",{className:"jr-tree-summary",style:{marginLeft:"8px"}},`${n} patch${n===1?"":"es"}`,a>0?`, ${a} text chunk${a===1?"":"s"}`:"")),te("span",{className:"jr-row-meta"},te("span",{className:"jr-badge","data-tone":i},s),o!==void 0?te("span",{style:{marginLeft:"6px"}},`${o}ms`):null,e.usage?te("span",{style:{marginLeft:"6px"}},`${TC(e.usage.totalTokens)} tok`):null));return te("div",null,u,l)}function ize(e){if(e.kind==="stream-patch")return te("div",{className:"jr-row"},te("span",{className:"jr-row-time"},mv(e.at)),te("span",{className:"jr-row-main"},te("span",{className:"jr-badge","data-tone":"accent"},e.patch.op),te("span",{className:"jr-tree-summary",style:{marginLeft:"8px"}},e.patch.path,e.patch.value!==void 0?` = ${tf(e.patch.value,80)}`:"")),te("span",{className:"jr-row-meta"},e.source));if(e.kind==="stream-text")return te("div",{className:"jr-row"},te("span",{className:"jr-row-time"},mv(e.at)),te("span",{className:"jr-row-main",style:{whiteSpace:"pre-wrap"}},e.text),te("span",{className:"jr-row-meta"},te("span",{className:"jr-badge"},"text")));if(e.kind==="stream-usage")return te("div",{className:"jr-row"},te("span",{className:"jr-row-time"},mv(e.at)),te("span",{className:"jr-row-main"},`prompt ${TC(e.usage.promptTokens)} / completion ${TC(e.usage.completionTokens)} / total ${TC(e.usage.totalTokens)}`),te("span",{className:"jr-row-meta"},te("span",{className:"jr-badge","data-tone":"accent"},"usage")));return te("div")}function TC(e){if(e>=1000)return`${(e/1000).toFixed(1).replace(/\.0$/,"")}k`;return String(e)}var sze="catalog";function Ote(){return{id:sze,label:"Catalog",badge(e){let t=e.getCatalog();if(!t)return;return t.componentNames.length+t.actionNames.length||void 0},mount(e,t){return lze(e,t)}}}function lze(e,t){let r=te("div",{style:{height:"100%",display:"flex",flexDirection:"column"}}),n=te("div",{className:"jr-toolbar"}),a=te("div",{style:{overflow:"auto",flex:"1",minHeight:"0"}});r.appendChild(n),r.appendChild(a),e.appendChild(r);let o="components",i="",s=te("button",{className:"jr-icon-btn","data-active":"true",onClick:()=>{if(o==="components")return;o="components",c(),f()}},"components"),l=te("button",{className:"jr-icon-btn","data-active":"false",onClick:()=>{if(o==="actions")return;o="actions",c(),f()}},"actions"),u=te("input",{className:"jr-search",type:"text",placeholder:"Filter by name…",onInput:(p)=>{i=(p.target.value||"").toLowerCase(),f()}});n.append(s,l,u);function c(){let p=t.getCatalog(),g=p?cte(p.data):null,m=g?.components.length??0,y=g?.actions.length??0;s.textContent=`components (${m})`,l.textContent=`actions (${y})`,s.dataset.active=String(o==="components"),l.dataset.active=String(o==="actions")}function f(){let p=t.getCatalog();if(!p){zt(a,te("div",{className:"jr-empty"},"No catalog attached. Pass `catalog` to `<JsonRenderDevtools>` to browse it here."));return}let g=cte(p.data);if(o==="components"){let m=g.components.filter((y)=>!i||y.name.toLowerCase().includes(i));if(m.length===0){zt(a,te("div",{className:"jr-empty"},"No components match."));return}zt(a,m.map(uze))}else{let m=g.actions.filter((y)=>!i||y.name.toLowerCase().includes(i));if(m.length===0){zt(a,te("div",{className:"jr-empty"},"No actions match."));return}zt(a,m.map(cze))}}function d(){c(),f()}return d(),{update:d}}function uze(e){return te("div",{className:"jr-catalog-item"},te("div",{className:"jr-catalog-name"},e.name),e.description?te("div",{className:"jr-catalog-desc"},e.description):null,e.props.length>0||e.events.length>0?te("div",{className:"jr-chips"},...e.props.map((t)=>te("span",{className:"jr-chip","data-tone":"prop"},`${t.name}: ${t.type}`)),...e.events.map((t)=>te("span",{className:"jr-chip","data-tone":"event"},`on.${t}`))):null)}function cze(e){return te("div",{className:"jr-catalog-item"},te("div",{className:"jr-catalog-name"},e.name),e.description?te("div",{className:"jr-catalog-desc"},e.description):null,e.params.length>0?te("div",{className:"jr-chips"},...e.params.map((t)=>te("span",{className:"jr-chip","data-tone":"param"},`${t.name}: ${t.type}`))):null)}function cte(e){let t=e??{},r=t.components??{},n=t.actions??{},a=Object.entries(r).map(([i,s])=>{let l=s??{};return{name:i,description:l.description??"",props:fte(l.props),slots:Array.isArray(l.slots)?l.slots:[],events:Array.isArray(l.events)?l.events:[]}}).sort((i,s)=>i.name.localeCompare(s.name)),o=Object.entries(n).map(([i,s])=>{let l=s??{};return{name:i,description:l.description??"",params:fte(l.params)}}).sort((i,s)=>i.name.localeCompare(s.name));return{components:a,actions:o}}function fte(e){if(!e)return[];try{let t=e,r=typeof t.shape==="object"&&t.shape!==null?t.shape:typeof t._def?.shape==="function"?t._def.shape():typeof t._def?.shape==="object"?t._def.shape:null;if(!r)return[];return Object.entries(r).map(([n,a])=>{let o="unknown";try{let i=a,s=i?._zod?.def?.type??i?._def?.typeName??"";if(s.includes("string"))o="string";else if(s.includes("number"))o="number";else if(s.includes("boolean"))o="boolean";else if(s.includes("array"))o="array";else if(s.includes("enum")){let l=i?._zod?.def?.values??i?._def?.values;o=Array.isArray(l)?l.join(" | "):"enum"}else if(s.includes("union"))o="union";else if(s.includes("nullable")){let l=i?._zod?.def?.innerType??i?._def?.innerType,u=l?._zod?.def?.type??l?._def?.typeName??"";if(u.includes("string"))o="string?";else if(u.includes("number"))o="number?";else if(u.includes("boolean"))o="boolean?";else if(u.includes("array"))o="array?";else if(u.includes("enum")){let c=l?._zod?.def?.values??l?._def?.values;o=Array.isArray(c)?`(${c.join(" | ")})?`:"enum?"}else o="optional"}}catch{}return{name:n,type:o}})}catch{return[]}}function Rte(e,t,r){if(!e)return;for(let n of e){if(!n||typeof n!=="object")continue;if(r.has(n))continue;if(r.add(n),n.type===Hp){let a=n.data;if(!a)continue;if(a.type==="patch")t.push({kind:"stream-patch",at:Date.now(),patch:a.patch,source:"json"})}}}function Lte(e){if(!e)return null;let t={root:"",elements:{}},r=!1;for(let n of e){if(!n||typeof n!=="object")continue;if(n.type!==Hp)continue;let a=n.data;if(!a)continue;if(a.type==="patch")r=!0,Kv(t,a.patch);else if(a.type==="flat")r=!0,Object.assign(t,a.spec);else if(a.type==="nested")r=!0,Object.assign(t,Gv(a.spec))}return r?t:null}function fze(e,t){let r=[];if(e){let n=0;for(let a of e){let o=Lte(a?.parts);if(!o||Object.keys(o.elements).length===0)continue;n+=1,r.push({id:a?.id??`gen-${n}`,label:`Generation ${n}`,spec:o})}}if(r.length===0&&t)r.push({id:"spec",label:"Current spec",spec:t});return r}var kte=null;function Tte(e){if(pte())return null;let t=M(e.spec??null);t.current=e.spec??null;let r=M(e.catalog??null);r.current=e.catalog??null;let n=M(e.messages);n.current=e.messages;let a=Gi(),o=M(null);o.current={get:a.get,set:a.set,update:a.update,getSnapshot:a.getSnapshot,subscribe:()=>()=>{}};let i=he(()=>dte({bufferSize:e.bufferSize}),[e.bufferSize]);G(()=>{if(!e.onEvent)return;return i.subscribe(()=>{let u=i.snapshot(),c=u[u.length-1];if(c)e.onEvent?.(c)})},[i,e.onEvent]),G(()=>Tj({onDispatch(u){i.push({kind:"action-dispatched",at:u.at,id:u.id,name:u.name,params:u.params})},onSettle(u){i.push({kind:"action-settled",at:u.at,id:u.id,ok:u.ok,durationMs:u.durationMs,result:u.result,error:u.error!==void 0?String(u.error):void 0})}}),[i]),G(()=>{l.current?.refresh()});let s=M(new WeakSet);G(()=>{if(!e.messages)return;for(let u of e.messages)if(u?.parts)Rte(u.parts,i,s.current)},[e.messages,i]);let l=M(null);return G(()=>{if(l.current)return;let u=Ste(),f=bte({context:{events:i,getSpec:()=>t.current,getSpecs:()=>fze(n.current,t.current),getCatalog:()=>r.current,getStateStore:()=>o.current,startPicker:(g)=>gte(g),selection:u,activateTab:()=>{}},tabs:[wte(),Ate(),Pte(),_te(),Ote()],initialOpen:e.initialOpen,position:e.position,hotkey:e.hotkey,reserveSpace:e.reserveSpace,allowDockToggle:e.allowDockToggle});l.current=f;let d=u.subscribe((g)=>{if(g)vte(g)});kte={open:()=>f.open(),close:()=>f.close(),toggle:()=>f.toggle(),recordEvent:(g)=>i.push(g),clear:()=>i.clear()};let p=jj();return()=>{d(),p(),f.destroy(),l.current=null,kte=null}},[i,e.initialOpen,e.position,e.hotkey,e.reserveSpace,e.allowDockToggle]),null}function dze({props:e}){let r=e.variant??"default";return b("span",{"data-slot":"badge","data-variant":r,className:`pmx-badge pmx-badge--${r}`,children:e.text})}function pze({props:e,emit:t}){let r=e.variant??"primary";return b("button",{type:"button","data-slot":"button","data-variant":r,className:`pmx-button pmx-button--${r}`,disabled:e.disabled??!1,onClick:()=>t("press"),children:e.label})}function mze({props:e,children:t,slots:r,...n}){let a=r?.header,o=r?.footer;return le(PO.Card,{...n,props:a?{...e,title:null,description:null}:e,children:[a&&b("header",{"data-pmx-card-slot":"header",children:a}),t,o&&b("footer",{"data-pmx-card-slot":"footer",className:"flex flex-wrap items-center gap-3",children:o})]})}var{registry:Dte}=nU(d5,{components:{...PO,Card:mze,Badge:dze,Button:pze,...Qee,...ete,...tte}}),hze=["ax.event.record","ax.steer","ax.work.create","ax.work.update","ax.evidence.add","ax.approval.request","ax.review.add","ax.focus.set","ax.elicitation.request","ax.mode.request","ax.command.invoke"];function gze(){let{__PMX_CANVAS_JSON_RENDER_NODE_ID__:e,__PMX_CANVAS_AX_TOKEN__:t}=window,r={};if(!e||!t)return r;for(let n of hze)r[n]=(a)=>{window.parent.postMessage({source:qj,token:t,nodeId:e,interaction:{type:n,payload:a&&typeof a==="object"?a:{}}},"*")};return r}function vze(){let e=window.__PMX_CANVAS_JSON_RENDER_THEME__;if(e){Mte(e);return}let t=window.matchMedia?.("(prefers-color-scheme: dark)").matches??!1;Mte(t?"dark":"light")}function Mte(e){if(e!=="dark"&&e!=="light"&&e!=="high-contrast")return;document.documentElement.setAttribute("data-theme",e),document.documentElement.classList.toggle("dark",e==="dark"||e==="high-contrast"),document.documentElement.style.colorScheme=e==="light"?"light":"dark"}function yze({store:e}){let t=window.__PMX_CANVAS_JSON_RENDER_SPEC__;if(!t)return b("div",{style:{height:"100vh",display:"flex",alignItems:"center",justifyContent:"center",color:"var(--muted-foreground, #666)"},children:"Waiting for UI spec..."});let r=window.__PMX_CANVAS_JSON_RENDER_DISPLAY__==="site";return b("div",{style:r?{display:"flex",flexDirection:"column",height:"100dvh",minHeight:"100dvh",padding:0,boxSizing:"border-box"}:{minHeight:"100vh",padding:16,boxSizing:"border-box"},children:le(rU,{registry:Dte,store:e,directives:IO,handlers:gze(),children:[b("div",{style:r?{flex:1,minHeight:0}:void 0,children:b(tU,{spec:t,registry:Dte,loading:!1})}),window.__PMX_CANVAS_JSON_RENDER_DEVTOOLS__?b(Tte,{position:"right"}):null]})})}var Nte=document.getElementById("root");if(Nte){vze();let e=window.__PMX_CANVAS_UI_STATE_TOKEN__,t,r=(n)=>{if(t)return;let a=n??window.__PMX_CANVAS_JSON_RENDER_SPEC__?.state??{},o=window.__PMX_CANVAS_AX_STATE__;if(t=af(o!=null?{...a,ax:o}:a),e)t.subscribe(()=>{let{ax:i,...s}=t.getSnapshot();window.parent.postMessage({source:kA,type:"snapshot",token:e,nodeId:window.__PMX_CANVAS_JSON_RENDER_NODE_ID__,state:s},"*")});S_(Nte).render(b(yze,{store:t}))};if(window.addEventListener("message",(n)=>{if(n.source!==window.parent)return;let a=n.data;if(!a)return;if(a.source===kA&&a.type==="restore"&&e&&a.token===e){if(a.state===null||typeof a.state==="object"&&!Array.isArray(a.state))r(a.state)}if(a.source===Hj&&a.type==="ax-update"&&window.__PMX_CANVAS_AX_TOKEN__&&a.token===window.__PMX_CANVAS_AX_TOKEN__)window.__PMX_CANVAS_AX_STATE__=a.state,t?.set("/ax",a.state)}),!e)r(null)}
@@ -1,5 +1,5 @@
1
1
  export declare function parseRecordOptions(flags: Record<string, string | boolean>): {
2
- theme: "dark" | "light" | "high-contrast" | "midnight" | "sepia" | "arctic" | "ember" | "forest" | "volt" | undefined;
2
+ theme: "harbor" | "daylight" | "high-contrast" | "midnight" | "sepia" | "arctic" | "ember" | "forest" | "volt" | undefined;
3
3
  present: boolean;
4
4
  tourFile: string | undefined;
5
5
  chromePath: string | undefined;
@@ -0,0 +1,24 @@
1
+ import type { CanvasNodeState } from '../types';
2
+ export declare const GLYPHS: {
3
+ readonly eye: "M2 12s3.5-6 10-6 10 6 10 6-3.5 6-10 6S2 12 2 12zM12 9.5a2.5 2.5 0 1 0 0 5a2.5 2.5 0 1 0 0-5";
4
+ readonly eyeOff: "M3 3l18 18M10.6 6.1A10 10 0 0 1 12 6c6.5 0 10 6 10 6a17 17 0 0 1-3 3.6M6.6 6.6C3.8 8.3 2 12 2 12s3.5 6 10 6a9.6 9.6 0 0 0 4.4-1";
5
+ readonly spark: "M12 3l1.8 5.2L19 10l-5.2 1.8L12 17l-1.8-5.2L5 10l5.2-1.8z";
6
+ readonly pen: "M4 20l4.2-1L19 8.2 15.8 5 5 15.8z";
7
+ readonly warn: "M12 4l9 16H3zM12 10v4M12 17v.5";
8
+ };
9
+ /** The header chip saying what agents did with this node (one per node; glyph + word). */
10
+ export declare function NodeContextMark({ node, pinned }: {
11
+ node: CanvasNodeState;
12
+ pinned: boolean;
13
+ }): import("preact/src").JSX.Element | null;
14
+ /** Pinned by an agent: the violet dot on the pin badge. */
15
+ export declare function isAgentPin(nodeId: string): boolean;
16
+ /**
17
+ * Near a pin (docs/design/NearPin.dc.html): a dotted pin-blue chip on an
18
+ * unpinned node the brief carries as title + short summary. Weaker than "in
19
+ * context" on purpose: the agent never gets this node's full content.
20
+ */
21
+ export declare function NearPinMark({ node, pinned }: {
22
+ node: CanvasNodeState;
23
+ pinned: boolean;
24
+ }): import("preact/src").JSX.Element | null;
@@ -3,7 +3,9 @@
3
3
  * at the canvas region's top-right after a session ends — what the session did
4
4
  * (items / done / vetoed), the pre-session snapshot (taken at attach, so View
5
5
  * diff shows the session's changes and a restore undoes them), and History
6
- * (the snapshots panel). Client-side state, cleared on dismiss.
6
+ * (the snapshots panel). Client-side state, cleared on dismiss (see
7
+ * applySessionReceipt for which endings show at all and how a burst merges
8
+ * into one card).
7
9
  */
8
10
  export interface DiffSummary {
9
11
  added: number;
@@ -13,7 +13,6 @@ export declare function IconExpand(p: IconProps): JSX.Element;
13
13
  export declare function IconArrowLeft(p: IconProps): JSX.Element;
14
14
  export declare function IconRefresh(p: IconProps): JSX.Element;
15
15
  export declare function IconUndo(p: IconProps): JSX.Element;
16
- export declare function IconSparkle(p: IconProps): JSX.Element;
17
16
  /** Upload into a tray — attach a document. */
18
17
  export declare function IconUpload(p: IconProps): JSX.Element;
19
18
  /** Dropdown disclosure, sized like the other toolbar icons. */
@@ -50,7 +49,7 @@ export declare function IconSearch(p: IconProps): JSX.Element;
50
49
  export declare function IconShortcuts(p: IconProps): JSX.Element;
51
50
  /** Speech bubble — steer the agent (command bar composer). */
52
51
  export declare function IconSteer(p: IconProps): JSX.Element;
53
- /** Framed pin — context pinning. */
52
+ /** Push pin — context pinning (docs/design/Chrome.dc.html). */
54
53
  export declare function IconPin(p: IconProps): JSX.Element;
55
54
  /** Focus Field — PMX Canvas brand mark (concentric rounded squares → lit core). */
56
55
  export declare function IconLogo({ size, class: className }: IconProps): JSX.Element;
@@ -0,0 +1 @@
1
+ import '../uuid-polyfill';
@@ -1,5 +1,6 @@
1
1
  import type { CanvasNodeState } from '../types';
2
2
  export declare function shouldShowPresentationControls(node: CanvasNodeState): boolean;
3
+ export declare function htmlAxCapabilitySignature(value: unknown): string;
3
4
  export declare function HtmlNode({ node, expanded, presentation, presentationExitToken, autoFocus, }: {
4
5
  node: CanvasNodeState;
5
6
  expanded?: boolean;
@@ -9,8 +9,8 @@ export declare function runNodeAxInteraction(node: CanvasNodeState, type: string
9
9
  export declare const axNodeActionButtonStyle: {
10
10
  readonly padding: "3px 8px";
11
11
  readonly fontSize: "10px";
12
- readonly background: "var(--c-accent-12)";
13
- readonly border: "1px solid var(--c-accent-25)";
12
+ readonly background: "color-mix(in srgb, var(--c-accent) 12%, transparent)";
13
+ readonly border: "1px solid color-mix(in srgb, var(--c-accent) 25%, transparent)";
14
14
  readonly borderRadius: "4px";
15
15
  readonly color: "var(--c-text-soft)";
16
16
  readonly cursor: "pointer";
@@ -0,0 +1,2 @@
1
+ /** Sanitize rendered Markdown before it enters the privileged workbench DOM. */
2
+ export declare function sanitizeMarkdownHtml(html: string): string;
@@ -0,0 +1,2 @@
1
+ /** Asset bytes travel through the host, not a localhost URL in the user's browser. */
2
+ export declare function useWorkbenchAsset(path: string): string | undefined;
@@ -1,4 +1,3 @@
1
- import type { SemanticAttentionRegion } from '../../shared/semantic-attention.js';
2
1
  export type AttentionTone = 'context' | 'relationship' | 'group' | 'cluster' | 'neighborhood' | 'remove';
3
2
  export interface AttentionEntry {
4
3
  id: string;
@@ -10,16 +9,12 @@ export interface AttentionEntry {
10
9
  }
11
10
  export declare const attentionToast: import("@preact/signals-core").Signal<AttentionEntry | null>;
12
11
  export declare const attentionHistory: import("@preact/signals-core").Signal<AttentionEntry[]>;
13
- export declare const attentionPrimaryNodeIds: import("@preact/signals-core").Signal<Set<string>>;
14
- export declare const attentionSecondaryNodeIds: import("@preact/signals-core").Signal<Set<string>>;
15
- export declare const attentionRegions: import("@preact/signals-core").Signal<SemanticAttentionRegion[]>;
16
12
  export declare const attentionPulseNodeIds: import("@preact/signals-core").Signal<Set<string>>;
17
13
  export declare const attentionHistoryOpen: import("@preact/signals-core").Signal<boolean>;
18
14
  export declare const attentionHistoryUnread: import("@preact/signals-core").Signal<number>;
19
15
  export declare function resetAttentionState(): void;
20
16
  export declare function openAttentionHistory(): void;
21
17
  export declare function closeAttentionHistory(): void;
22
- export declare function setAttentionFocus(primaryNodeIds: string[], secondaryNodeIds: string[], regions: SemanticAttentionRegion[]): void;
23
18
  export declare function setAttentionToast(entry: AttentionEntry | null): void;
24
19
  export declare function pushAttentionHistory(entry: AttentionEntry, limit?: number): void;
25
20
  export declare function setAttentionPulse(nodeIds: string[]): void;
@@ -0,0 +1,53 @@
1
+ /**
2
+ * What agents did with the board's context (docs/design/AgentContext.dc.html):
3
+ * per node, the latest agent read of its content and the revision it read;
4
+ * per pin, who pinned it, when and why. Server truth from
5
+ * `GET /api/canvas/ax/context-status`, refetched when a read lands
6
+ * (`context-status-changed`), when pins change, and on (re)connect.
7
+ */
8
+ export interface NodeReadStatus {
9
+ nodeId: string;
10
+ lastReadAt: string;
11
+ lastReadBy: string;
12
+ readRevision: number;
13
+ readCount: number;
14
+ }
15
+ export interface ContextPinMeta {
16
+ pinnedBy: {
17
+ actor: 'human' | 'agent' | 'system' | 'unknown';
18
+ source: string;
19
+ agentId?: string;
20
+ };
21
+ pinnedAt: string;
22
+ reason?: string;
23
+ }
24
+ interface ContextStatusResponse {
25
+ ok?: boolean;
26
+ boardId?: string | null;
27
+ nodes?: NodeReadStatus[];
28
+ pins?: Record<string, ContextPinMeta>;
29
+ }
30
+ export declare const nodeReadStatus: import("@preact/signals-core").Signal<Map<string, NodeReadStatus>>;
31
+ export declare const contextPinMeta: import("@preact/signals-core").Signal<Record<string, ContextPinMeta>>;
32
+ export declare function applyContextStatus(response: ContextStatusResponse): void;
33
+ export declare function refreshContextStatus(): Promise<void>;
34
+ /** How an agent's context relates to one pinned node — the mark its header shows. */
35
+ export type PinnedReadState = {
36
+ kind: 'not-read';
37
+ } | {
38
+ kind: 'read';
39
+ by: string;
40
+ at: string;
41
+ count: number;
42
+ } | {
43
+ kind: 'changed';
44
+ by: string;
45
+ at: string;
46
+ };
47
+ export declare function pinnedReadState(nodeId: string, currentRevision: number): PinnedReadState;
48
+ /** Display name for an attributed writer: its agent id, else its transport label. */
49
+ export declare function writerName(actor: {
50
+ source: string;
51
+ agentId?: string;
52
+ }): string;
53
+ export {};
@@ -120,9 +120,12 @@ export declare function updateNodeFromClient(id: string, patch: {
120
120
  data?: Record<string, unknown>;
121
121
  /** Groups: replace the membership list (positions preserved). */
122
122
  children?: string[];
123
+ expectedContentRevision?: number;
124
+ expectedBoardId?: string | null;
123
125
  }): Promise<{
124
126
  ok: boolean;
125
127
  id?: string;
128
+ contentRevision?: number;
126
129
  }>;
127
130
  /** Refresh a webpage node from its persisted URL on the server. */
128
131
  export declare function refreshWebpageNodeFromClient(id: string, url?: string): Promise<{
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Near a pin (docs/design/NearPin.dc.html): each pinned node pulls up to five
3
+ * unpinned nodes within 600 px into the agent's brief as title + short
4
+ * summary. Same rule as the server's brief (`findNeighborhoods`), so the mark
5
+ * claims exactly what the agent receives.
6
+ */
7
+ export interface NearPin {
8
+ pinNodeId: string;
9
+ pinTitle: string;
10
+ }
11
+ /**
12
+ * Unpinned node id → the pins it is near, nearest first. Every drag frame
13
+ * moves a node, so the result keeps its identity while no node's set of pins
14
+ * changes: the chips subscribed to it re-render only when a neighbourhood does.
15
+ */
16
+ export declare const nearPins: import("@preact/signals-core").ReadonlySignal<Map<string, NearPin[]>>;
@@ -17,6 +17,11 @@ export declare const activityFeedOpen: import("@preact/signals-core").Signal<boo
17
17
  export declare const writersSheetOpen: import("@preact/signals-core").Signal<boolean>;
18
18
  /** Feed filter: a writer's sessionId, or null for all. */
19
19
  export declare const activityFilter: import("@preact/signals-core").Signal<string | null>;
20
+ /**
21
+ * A writer's colour says what it is, not who: agents take the agent violet,
22
+ * subagents (fleet workers) the subagent fuchsia. Writers are told apart by
23
+ * name and initial (docs/design.md, "Kinds carry no colour").
24
+ */
20
25
  export declare function writerColor(sessionId: string): string;
21
26
  /** Avatar initial: first letter of the label, upper-cased. */
22
27
  export declare function writerInitial(label: string): string;
@@ -155,12 +155,13 @@ export declare function endSession(session: {
155
155
  agentId: string | null;
156
156
  }): Promise<boolean>;
157
157
  export interface SessionReceipt {
158
- label: string;
158
+ /** Distinct labels of the sessions on this card (one unless merged). */
159
+ labels: string[];
160
+ /** Endings folded into this card (see applySessionReceipt). */
161
+ sessions: number;
159
162
  endedAt: string;
160
163
  /** Why it ended — the receipt should answer this, not leave the human asking. */
161
164
  endedBy?: 'human' | 'agent' | 'idle-timeout';
162
- /** The session changed nothing on the board (its pre-session snapshot was dropped). */
163
- unchanged?: boolean;
164
165
  /** Cancelled (withdrawn items), rejected (human's explicit no on a gate), and
165
166
  * held (TTL expired unanswered) are three different outcomes — never one
166
167
  * "vetoed" pile. */
@@ -171,13 +172,42 @@ export interface SessionReceipt {
171
172
  rejected: number;
172
173
  held: number;
173
174
  };
175
+ /** The pre-session snapshot; null when the board was empty at attach, or on a
176
+ * merged receipt (each session's snapshot is in History). */
174
177
  snapshot: {
175
178
  id: string;
176
179
  name: string;
177
180
  } | null;
181
+ /** What the session did with context (docs/design/AgentContext.dc.html receipt). */
182
+ context: SessionContextActivity;
183
+ }
184
+ export interface ReceiptNode {
185
+ id: string;
186
+ title: string;
187
+ reason?: string;
188
+ }
189
+ export interface SessionContextActivity {
190
+ read: ReceiptNode[];
191
+ pinned: ReceiptNode[];
192
+ created: ReceiptNode[];
193
+ edited: ReceiptNode[];
194
+ changedSinceRead: ReceiptNode[];
178
195
  }
196
+ /**
197
+ * The agent-activity lens: while on, nodes the last session did not touch
198
+ * (read, pin, create, edit) are dimmed. Null when off.
199
+ */
200
+ export declare const activityLensNodeIds: import("@preact/signals-core").Signal<Set<string> | null>;
201
+ export declare function setActivityLens(on: boolean): void;
179
202
  /** The last ended session's receipt (design item 2); client-side, cleared on dismiss. */
180
203
  export declare const sessionReceipt: import("@preact/signals-core").Signal<SessionReceipt | null>;
204
+ /**
205
+ * The receipt rule: a pop-up only for a top-level session that changed the
206
+ * board or read/pinned context. `unchanged` endings and worker endings
207
+ * (`parentAgentId` set — their orchestrator's receipt covers the board since
208
+ * it attached) stay in the timeline and History only, and never replace or
209
+ * extend an open receipt. Qualifying endings while one is up merge into it.
210
+ */
181
211
  export declare function applySessionReceipt(data: Record<string, unknown>): void;
182
212
  export declare function dismissSessionReceipt(): void;
183
213
  export declare function resetSessionStore(): void;
@@ -0,0 +1,16 @@
1
+ /** The normal workbench uses HTTP; an MCP App installs its host transport before mounting. */
2
+ type WorkbenchFetch = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
3
+ export declare function installWorkbenchTransport(transport: WorkbenchFetch | undefined): void;
4
+ export declare function isHostedWorkbench(): boolean;
5
+ export declare const workbenchFetch: WorkbenchFetch;
6
+ type WorkbenchDownload = (file: {
7
+ name: string;
8
+ mimeType: string;
9
+ text: string;
10
+ }) => Promise<{
11
+ isError?: boolean;
12
+ }>;
13
+ export declare function installWorkbenchDownload(download: WorkbenchDownload | undefined): void;
14
+ /** Export files live on PMX, not on the embedded frame's sandbox origin. */
15
+ export declare function downloadWorkbenchExport(path: string): Promise<void>;
16
+ export {};
@@ -11,10 +11,8 @@ export interface CanvasTokens {
11
11
  accent: string;
12
12
  ok: string;
13
13
  warn: string;
14
- warnAlt: string;
15
14
  danger: string;
16
- purple: string;
17
- thinking: string;
15
+ agent: string;
18
16
  subagent: string;
19
17
  font: string;
20
18
  mono: string;
@@ -18,8 +18,17 @@ export interface CanvasNodeState {
18
18
  zIndex: number;
19
19
  collapsed: boolean;
20
20
  pinned: boolean;
21
+ contentRevision?: number;
22
+ /** Who created / last edited the node's content (server attribution). */
23
+ createdBy?: NodeActor;
24
+ lastEditedBy?: NodeActor;
21
25
  data: Record<string, unknown>;
22
26
  }
27
+ export interface NodeActor {
28
+ actor: 'human' | 'agent' | 'system' | 'unknown';
29
+ source: string;
30
+ agentId?: string;
31
+ }
23
32
  export interface CanvasEdge {
24
33
  id: string;
25
34
  from: string;
@@ -66,7 +66,7 @@ export type GraphChartType = 'LineChart' | 'BarChart' | 'PieChart' | 'AreaChart'
66
66
  export declare function escapeInlineScriptSource(source: string): string;
67
67
  export declare function inferJsonRenderNodeTitle(spec: JsonRenderSpec, fallback?: string): string;
68
68
  export declare function normalizeAndValidateJsonRenderSpec(spec: unknown): JsonRenderSpec;
69
- /** shadcn 0.21 ignores these props unless the renderer supplies a two-way binding. */
69
+ /** Binding-only form props that normalization could not bind (see bindLiteralFormValues). */
70
70
  export declare function jsonRenderFormWarnings(spec: JsonRenderSpec): string[];
71
71
  export declare function normalizeGraphType(value: string): GraphChartType;
72
72
  export declare function buildGraphSpec(input: GraphNodeInput): JsonRenderSpec;
@@ -0,0 +1,3 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ /** Private, single-workspace profile. No public HTTP listener or tenant routing. */
3
+ export declare function createCanvasAppServer(): McpServer;
@@ -88,5 +88,5 @@ export declare function shouldAttachToExistingDaemon(occupant: {
88
88
  * FS-safe (defaults to false on any error).
89
89
  */
90
90
  export declare function looksLikeIncidentalCwd(cwd: string): boolean;
91
- export declare function createCanvasAccess(): Promise<CanvasAccess>;
91
+ export declare function createCanvasAccess(allowExternalMcp?: boolean): Promise<CanvasAccess>;
92
92
  export {};
@@ -0,0 +1,4 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { CanvasAccess } from './canvas-access.js';
3
+ /** Focused app profile; deliberately does not register the general-purpose composites. */
4
+ export declare function registerCanvasApp(server: McpServer, ensureCanvas: () => Promise<CanvasAccess>): void;
@@ -0,0 +1,4 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { CanvasAccess } from './canvas-access.js';
3
+ /** HTTP-shaped replies let the real workbench retain its existing API contracts. */
4
+ export declare function registerWorkbenchApp(server: McpServer, ensureCanvas: () => Promise<CanvasAccess>): void;
@@ -99,7 +99,7 @@ export declare function estimateContextBudget(): ContextBudget;
99
99
  /** Returns the id of the pre-session snapshot the server took, if any. */
100
100
  type SessionStartListener = (presence: AgentPresence) => string | null;
101
101
  export type SessionEndReason = 'human' | 'agent' | 'idle-timeout';
102
- type SessionEndListener = (presence: AgentPresence, startSnapshotId: string | null, endedBy: SessionEndReason) => void;
102
+ type SessionEndListener = (presence: AgentPresence, startSnapshotId: string | null, endedBy: SessionEndReason, startedAt: string | null) => void;
103
103
  export declare class AgentPresenceRegistry {
104
104
  private readonly presences;
105
105
  /** Newest first; bounded. Survives a writer fading — the feed is history, the writer list is presence. */
@@ -1,6 +1,6 @@
1
1
  import type { CanvasLayout, CanvasNodeState } from './canvas-state.js';
2
2
  import type { AxApprovalStatus, AxEventKind, AxWorkItemStatus } from '../shared/ax-kinds.js';
3
- import type { AgentContextNode } from './agent-context.js';
3
+ import type { AgentContextNode } from '../shared/agent-context.js';
4
4
  import type { ActorAttribution } from './attribution.js';
5
5
  export type PmxAxSource = 'agent' | 'amp' | 'api' | 'browser' | 'cli' | 'codex' | 'copilot' | 'mcp' | 'sdk' | 'system';
6
6
  export interface PmxAxFocusState {
@@ -5,6 +5,7 @@
5
5
  * WAL-mode persistence. Replaces the previous JSON file-based approach.
6
6
  */
7
7
  import { Database } from 'bun:sqlite';
8
+ import type { ActorAttribution } from './attribution.js';
8
9
  import { type Tour } from '../shared/tour.js';
9
10
  import { type CanvasThemeName } from '../shared/themes.js';
10
11
  import type { CanvasAnnotation, CanvasEdge, CanvasNodeState, CanvasSnapshot, CanvasSnapshotListOptions, ViewportState } from './canvas-state.js';
@@ -20,9 +21,16 @@ export interface PersistedCanvasState {
20
21
  edges: CanvasEdge[];
21
22
  annotations?: CanvasAnnotation[];
22
23
  contextPins: string[];
24
+ /** Who pinned each context pin, when and why; pins without an entry have an unknown pinner. */
25
+ contextPinMeta?: Record<string, ContextPinMeta>;
23
26
  ax?: PmxAxState;
24
27
  revisionState?: PersistedRevisionState;
25
28
  }
29
+ export interface ContextPinMeta {
30
+ pinnedBy: ActorAttribution;
31
+ pinnedAt: string;
32
+ reason?: string;
33
+ }
26
34
  export interface PersistedRevisionState {
27
35
  revision: number;
28
36
  floor: number;
@@ -0,0 +1,25 @@
1
+ import type { CanvasNodeState, CanvasNodeUpdate } from './canvas-state.js';
2
+ /** Flat fields take precedence over nested aliases; absent axes remain absent. */
3
+ export declare function resolveCreateGeometry(body: Record<string, unknown>): {
4
+ x: number | undefined;
5
+ y: number | undefined;
6
+ width: number | undefined;
7
+ height: number | undefined;
8
+ };
9
+ /** Guards and PATCH execution must resolve aliases and single-axis moves identically. */
10
+ export declare function resolvePatchGeometry(body: Record<string, unknown>, existing: CanvasNodeState): {
11
+ size?: {
12
+ width: number;
13
+ height: number;
14
+ } | undefined;
15
+ position?: {
16
+ x: number;
17
+ y: number;
18
+ } | undefined;
19
+ };
20
+ export declare function validateCanvasNodePatch(patch: {
21
+ position?: unknown;
22
+ size?: unknown;
23
+ }): string | null;
24
+ /** Invalid patches cannot count as explicit child-position overrides. */
25
+ export declare function validCanvasNodeUpdates(input: unknown): CanvasNodeUpdate[];
@@ -130,16 +130,6 @@ export declare function syncCanvasRuntimeBackends(options?: {
130
130
  rehydrated: number;
131
131
  failed: number;
132
132
  }>;
133
- export declare function validateCanvasNodePatch(patch: {
134
- position?: {
135
- x: number;
136
- y: number;
137
- };
138
- size?: {
139
- width: number;
140
- height: number;
141
- };
142
- }): string | null;
143
133
  export declare function mergeTraceNodeDataFields(base: Record<string, unknown>, input: Record<string, unknown>): Record<string, unknown>;
144
134
  export declare function hasTraceNodeDataFields(input: Record<string, unknown>): boolean;
145
135
  export declare function scheduleCodeGraphRecompute(onComplete?: () => void): void;
@@ -189,7 +179,7 @@ export declare function applyCanvasNodeUpdates(updates: CanvasNodeUpdate[]): {
189
179
  applied: number;
190
180
  skipped: number;
191
181
  };
192
- export declare function setCanvasContextPins(nodeIds: string[], mode?: CanvasPinMode): {
182
+ export declare function setCanvasContextPins(nodeIds: string[], mode?: CanvasPinMode, reason?: string): {
193
183
  count: number;
194
184
  nodeIds: string[];
195
185
  };