@jxsuite/studio 6.1.0 → 6.1.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 (645) hide show
  1. package/dist/chunks/2020-f2gkpy8d.js +4 -0
  2. package/dist/chunks/{action-group-2mqby73c.js → action-group-4aan7g6g.js} +3 -3
  3. package/dist/chunks/adapter-4912g339.js +4 -0
  4. package/dist/chunks/cf-account-picker-wccaenh6.js +4 -0
  5. package/dist/chunks/cf-settings-br6105tr.js +4 -0
  6. package/dist/chunks/color-28ksk2qm.js +4 -0
  7. package/dist/chunks/color-area-0fj8a4ga.js +4 -0
  8. package/dist/chunks/color-field-xch8kx2g.js +4 -0
  9. package/dist/chunks/color-slider-jxd8v350.js +4 -0
  10. package/dist/chunks/combobox-p0efwjke.js +4 -0
  11. package/dist/chunks/components-db68vsn7.js +4 -0
  12. package/dist/chunks/content-source-1449qesq.js +4 -0
  13. package/dist/chunks/convert-to-repeater-5h457egj.js +4 -0
  14. package/dist/chunks/dialog-c4x05vyx.js +4 -0
  15. package/dist/chunks/editor-x9jn86a7.js +4 -0
  16. package/dist/chunks/entry-commands-may24cpt.js +4 -0
  17. package/dist/chunks/extension-sections-pvr14vxr.js +4 -0
  18. package/dist/chunks/file-ops-x9v54pcj.js +4 -0
  19. package/dist/chunks/files-j3knqf0s.js +4 -0
  20. package/dist/chunks/format-host-tyre2trb.js +4 -0
  21. package/dist/chunks/fs-events-64ma9htc.js +4 -0
  22. package/dist/chunks/git-panel-84ps5dex.js +4 -0
  23. package/dist/chunks/grid-view-d2wq9ezg.js +51 -0
  24. package/dist/chunks/icons-pnfz478q.js +4 -0
  25. package/dist/chunks/iframe-entry-fvbk89gm.js +5 -0
  26. package/dist/chunks/iframe-entry-jdcktez8.js +5 -0
  27. package/dist/chunks/iframe-entry-x0ygf2yr.js +5 -0
  28. package/dist/chunks/iframe-entry-zap785cw.js +5 -0
  29. package/dist/chunks/iframe-host-ck6vejt5.js +4 -0
  30. package/dist/chunks/index-b8xw3vy9.js +4 -0
  31. package/dist/chunks/{index-gybvv7a6.js → index-zpjmzqfk.js} +3 -3
  32. package/dist/chunks/{javascript-rnvdp3k4.js → javascript-m54mnwp6.js} +3 -3
  33. package/dist/chunks/jsonMode-w15cmrcm.js +13 -0
  34. package/dist/chunks/jx-validate-at3zn8wa.js +4 -0
  35. package/dist/chunks/layers-h4xp1pss.js +4 -0
  36. package/dist/chunks/layers-panel-m5hw1d7g.js +4 -0
  37. package/dist/chunks/listbox-e74qjyq6.js +4 -0
  38. package/dist/chunks/lit-html-8t8t3dnr.js +4 -0
  39. package/dist/chunks/media-picker-2cweexc5.js +4 -0
  40. package/dist/chunks/menu-n6yzswmy.js +4 -0
  41. package/dist/chunks/menu-ynw13y0s.js +4 -0
  42. package/dist/chunks/monaco-binding-7gx83x3r.js +4 -0
  43. package/dist/chunks/monaco-buffer-qzxn567r.js +4 -0
  44. package/dist/chunks/monaco-setup-gxf6656g.js +4 -0
  45. package/dist/chunks/notify-cj5zbrs2.js +4 -0
  46. package/dist/chunks/number-field-y62xq0ty.js +4 -0
  47. package/dist/chunks/parse-b7ddhr8m.js +4 -0
  48. package/dist/chunks/platform-3dfws9js.js +4 -0
  49. package/dist/chunks/popover-jt2gxmzs.js +4 -0
  50. package/dist/chunks/publish-panel-1gvxbj21.js +4 -0
  51. package/dist/chunks/quick-search-0dajrwqg.js +4 -0
  52. package/dist/chunks/references-49qgt404.js +4 -0
  53. package/dist/chunks/right-panel-jm1bwe53.js +4 -0
  54. package/dist/chunks/section-registry-6kwc4fky.js +4 -0
  55. package/dist/chunks/select-rzds841e.js +4 -0
  56. package/dist/chunks/split-n2gfpm5m.js +4 -0
  57. package/dist/chunks/{studio-5g0ag7c0.js → studio-0q988f9w.js} +3 -3
  58. package/dist/chunks/studio-0rt52vpq.js +5 -0
  59. package/dist/chunks/studio-18vgbhs5.js +5 -0
  60. package/dist/chunks/{studio-pxg4ap1e.js → studio-1fxkaaea.js} +4 -4
  61. package/dist/chunks/studio-24mccdrj.js +5 -0
  62. package/dist/chunks/studio-2eh507zk.js +9 -0
  63. package/dist/chunks/studio-2hcbccfv.js +5 -0
  64. package/dist/chunks/studio-2j1cb95x.js +5 -0
  65. package/dist/chunks/studio-2jbs3rxv.js +5 -0
  66. package/dist/chunks/{studio-qbj760tx.js → studio-485046te.js} +7 -7
  67. package/dist/chunks/studio-4h8k4dw9.js +5 -0
  68. package/dist/chunks/studio-5f6n18kx.js +5 -0
  69. package/dist/chunks/studio-5gthpky6.js +5 -0
  70. package/dist/chunks/studio-5ve6bbep.js +5 -0
  71. package/dist/chunks/studio-6ep3js6b.js +9 -0
  72. package/dist/chunks/studio-6wkmf3wz.js +9 -0
  73. package/dist/chunks/studio-841rf3cg.js +5 -0
  74. package/dist/chunks/studio-8gmwgheg.js +5 -0
  75. package/dist/chunks/studio-8qm0ep50.js +5 -0
  76. package/dist/chunks/{studio-anyrgzvb.js → studio-90pq9km1.js} +4 -4
  77. package/dist/chunks/studio-924p1tm1.js +6 -0
  78. package/dist/chunks/{studio-v2bvmbjj.js → studio-a3g98wjr.js} +4 -4
  79. package/dist/chunks/studio-a3shpz9y.js +5 -0
  80. package/dist/chunks/studio-amsbaaar.js +6 -0
  81. package/dist/chunks/studio-at5spjbc.js +7 -0
  82. package/dist/chunks/studio-b2xv945e.js +5 -0
  83. package/dist/chunks/studio-bn5nkafw.js +5 -0
  84. package/dist/chunks/studio-bw6q5xjf.js +9 -0
  85. package/dist/chunks/studio-c7q0t9x1.js +5 -0
  86. package/dist/chunks/studio-camnhc96.js +6 -0
  87. package/dist/chunks/studio-cffqvnzd.js +5 -0
  88. package/dist/chunks/studio-d81xfh1g.js +5 -0
  89. package/dist/chunks/studio-dgz8d0c1.js +5 -0
  90. package/dist/chunks/studio-efvfrsf8.js +5 -0
  91. package/dist/chunks/studio-er30bpcx.js +5 -0
  92. package/dist/chunks/studio-ezscgr64.js +5 -0
  93. package/dist/chunks/studio-ffrrncvz.js +5 -0
  94. package/dist/chunks/studio-fpphgn8y.js +10 -0
  95. package/dist/chunks/studio-j1kvhdjk.js +4 -0
  96. package/dist/chunks/{studio-txjjzrsm.js → studio-j430n16g.js} +5 -5
  97. package/dist/chunks/studio-jjkg84nj.js +5 -0
  98. package/dist/chunks/studio-m0q32ars.js +4 -0
  99. package/dist/chunks/studio-m6bdst11.js +5 -0
  100. package/dist/chunks/studio-nv2cptd4.js +64 -0
  101. package/dist/chunks/studio-nwfrc98n.js +5 -0
  102. package/dist/chunks/studio-p1wgvp7r.js +5 -0
  103. package/dist/chunks/studio-pag2wncm.js +5 -0
  104. package/dist/chunks/studio-qvanvzfd.js +5 -0
  105. package/dist/chunks/studio-qwa64kt7.js +5 -0
  106. package/dist/chunks/studio-rk1zc4x3.js +928 -0
  107. package/dist/chunks/studio-se2r3ptc.js +5 -0
  108. package/dist/chunks/studio-sg2a0dh0.js +5 -0
  109. package/dist/chunks/studio-tjzjhe68.js +5 -0
  110. package/dist/chunks/{studio-0x3jyb8r.js → studio-tq0rtfwj.js} +4 -4
  111. package/dist/chunks/{studio-cpxkgjrj.js → studio-v0jzqdjm.js} +4 -4
  112. package/dist/chunks/studio-v2w7q8r1.js +7 -0
  113. package/dist/chunks/studio-v5vjq1h0.js +4 -0
  114. package/dist/chunks/studio-v8aga3vp.js +14 -0
  115. package/dist/chunks/studio-vfcdrfmv.js +5 -0
  116. package/dist/chunks/studio-vmfkgdjf.js +5 -0
  117. package/dist/chunks/studio-wt1816jj.js +5 -0
  118. package/dist/chunks/studio-wz73q5kq.js +4 -0
  119. package/dist/chunks/studio-y04qtxvp.js +7 -0
  120. package/dist/chunks/studio-y21g8zzg.js +5 -0
  121. package/dist/chunks/studio-y64hrt8p.js +12 -0
  122. package/dist/chunks/studio-ynn90f58.js +16 -0
  123. package/dist/chunks/studio-yxz682sx.js +5 -0
  124. package/dist/chunks/studio-zp7snvkq.js +5 -0
  125. package/dist/chunks/studio-zq4z6tm6.js +5 -0
  126. package/dist/chunks/swatch-group-ewh24n1f.js +4 -0
  127. package/dist/chunks/tabs-f5cw3tgp.js +4 -0
  128. package/dist/chunks/textfield-wewc8rq2.js +4 -0
  129. package/dist/chunks/toast-c9fn075p.js +4 -0
  130. package/dist/chunks/toast-host-ke5z4ng7.js +4 -0
  131. package/dist/chunks/{toolbar-2nnzqhrj.js → toolbar-44cm5cta.js} +3 -3
  132. package/dist/chunks/tooltip-5v8ngwj2.js +4 -0
  133. package/dist/chunks/tree-mdq3v5cw.js +4 -0
  134. package/dist/chunks/tsMode-sf49ee9x.js +14 -0
  135. package/dist/chunks/workspace-jtfahpee.js +4 -0
  136. package/dist/chunks/ws-client-nze0k6mv.js +4 -0
  137. package/dist/iframe-entry.js +16 -16
  138. package/dist/manifest.json +63 -63
  139. package/dist/studio.js +98 -98
  140. package/dist/workers/ts.worker.js +3 -3
  141. package/package.json +11 -11
  142. package/src/about/about-modal.ts +4 -3
  143. package/src/account/action-flow.ts +45 -38
  144. package/src/account-status.ts +7 -2
  145. package/src/browse/library-layouts.ts +8 -5
  146. package/src/browse/library-model.ts +18 -6
  147. package/src/browse/library-pane.ts +37 -21
  148. package/src/browse/library-preview.ts +14 -9
  149. package/src/browse/library-source.ts +1 -1
  150. package/src/canvas/asset-refs.ts +24 -9
  151. package/src/canvas/asset-resolve.ts +19 -23
  152. package/src/canvas/canvas-helpers.ts +7 -6
  153. package/src/canvas/canvas-live-render.ts +44 -53
  154. package/src/canvas/canvas-patcher.ts +30 -30
  155. package/src/canvas/canvas-perf.ts +11 -5
  156. package/src/canvas/canvas-render.ts +66 -42
  157. package/src/canvas/canvas-surface.ts +5 -3
  158. package/src/canvas/canvas-utils.ts +163 -64
  159. package/src/canvas/dialog-path.ts +9 -4
  160. package/src/canvas/dialog-state.ts +1 -2
  161. package/src/canvas/diff-marks.ts +9 -16
  162. package/src/canvas/diff-toolbar.ts +8 -7
  163. package/src/canvas/edit-width-drag.ts +4 -1
  164. package/src/canvas/edit-width.ts +1 -3
  165. package/src/canvas/iframe-channel.ts +27 -13
  166. package/src/canvas/iframe-drop.ts +13 -12
  167. package/src/canvas/iframe-editable-root.ts +29 -16
  168. package/src/canvas/iframe-entry.ts +80 -63
  169. package/src/canvas/iframe-eval.ts +73 -49
  170. package/src/canvas/iframe-host.ts +203 -118
  171. package/src/canvas/iframe-inline-edit.ts +69 -32
  172. package/src/canvas/iframe-insert.ts +5 -4
  173. package/src/canvas/iframe-interaction.ts +37 -26
  174. package/src/canvas/iframe-overlay.ts +1 -1
  175. package/src/canvas/iframe-patch.ts +18 -15
  176. package/src/canvas/iframe-position.ts +12 -6
  177. package/src/canvas/iframe-protocol.ts +15 -16
  178. package/src/canvas/iframe-render.ts +41 -36
  179. package/src/canvas/iframe-slash.ts +24 -11
  180. package/src/canvas/iframe-subtree.ts +6 -2
  181. package/src/canvas/path-mapping.ts +19 -12
  182. package/src/canvas/popover-path.ts +7 -3
  183. package/src/canvas/popover-state.ts +1 -2
  184. package/src/canvas/serialize-scope.ts +13 -5
  185. package/src/canvas/stage-scrollbar.ts +2 -1
  186. package/src/canvas/surface-registry.ts +21 -3
  187. package/src/collab/collab-commands.ts +7 -2
  188. package/src/collab/collab-session.ts +84 -45
  189. package/src/collab/collab-state.ts +4 -3
  190. package/src/collab/monaco-binding.ts +16 -13
  191. package/src/collab/monaco-cursors.ts +5 -2
  192. package/src/commands/budget.ts +3 -3
  193. package/src/commands/command-args.ts +103 -71
  194. package/src/commands/context.ts +22 -20
  195. package/src/commands/defaults.ts +4 -1
  196. package/src/commands/keymap.ts +47 -43
  197. package/src/commands/levels.ts +3 -3
  198. package/src/commands/live-context.ts +10 -8
  199. package/src/commands/reference.ts +2 -1
  200. package/src/commands/registry.ts +12 -10
  201. package/src/commands/run-reported.ts +15 -10
  202. package/src/component-props.ts +46 -30
  203. package/src/content/collection-match.ts +5 -4
  204. package/src/content/draft-state.ts +4 -3
  205. package/src/content/entry-commands.ts +3 -2
  206. package/src/content/entry-editor.ts +29 -17
  207. package/src/content/entry-fields.ts +12 -7
  208. package/src/content/entry-model.ts +21 -12
  209. package/src/editor/canvas-context-menu.ts +1 -2
  210. package/src/editor/canvas-slash-bridge.ts +3 -6
  211. package/src/editor/content-slice.ts +16 -14
  212. package/src/editor/context-menu.ts +35 -22
  213. package/src/editor/convert-targets.ts +30 -35
  214. package/src/editor/convert-to-component.ts +11 -5
  215. package/src/editor/convert-to-repeater.ts +34 -22
  216. package/src/editor/editable-tags.ts +17 -2
  217. package/src/editor/file-drop-action.ts +21 -22
  218. package/src/editor/inline-edit-apply.ts +35 -17
  219. package/src/editor/inline-edit.ts +66 -50
  220. package/src/editor/inline-format.ts +59 -56
  221. package/src/editor/inline-link.ts +40 -15
  222. package/src/editor/insert-zone-action.ts +1 -1
  223. package/src/editor/merge-tags.ts +58 -19
  224. package/src/editor/repeater-scope.ts +39 -28
  225. package/src/editor/shortcuts.ts +87 -47
  226. package/src/editor/slash-menu.ts +1 -6
  227. package/src/files/asset-versions.ts +4 -4
  228. package/src/files/components.ts +15 -10
  229. package/src/files/elements.ts +5 -6
  230. package/src/files/file-ops.ts +77 -36
  231. package/src/files/files.ts +90 -95
  232. package/src/files/media-meta.ts +2 -1
  233. package/src/files/media-paths.ts +6 -1
  234. package/src/files/serialize-document.ts +2 -2
  235. package/src/format/constraints.ts +1 -1
  236. package/src/format/convert-file.ts +27 -13
  237. package/src/format/format-choices.ts +2 -1
  238. package/src/format/format-host.ts +76 -50
  239. package/src/github/github-auth-status.ts +27 -3
  240. package/src/github/github-auth.ts +19 -9
  241. package/src/github/github-publish.ts +24 -20
  242. package/src/grid/cell-editors.ts +46 -31
  243. package/src/grid/cell-popovers.ts +5 -3
  244. package/src/grid/edit-buffer.ts +10 -9
  245. package/src/grid/grid-controller.ts +20 -22
  246. package/src/grid/grid-layout.ts +21 -5
  247. package/src/grid/grid-open.ts +3 -6
  248. package/src/grid/grid-panel.ts +11 -4
  249. package/src/grid/grid-source.ts +8 -8
  250. package/src/grid/grid-view.ts +14 -17
  251. package/src/grid/redirects-grid.ts +14 -5
  252. package/src/grid/redirects.ts +16 -14
  253. package/src/grid/schema-columns.ts +25 -19
  254. package/src/grid/sources/connector-source.ts +47 -20
  255. package/src/grid/sources/content-source.ts +25 -24
  256. package/src/grid/sources/csv-file-source.ts +2 -2
  257. package/src/grid/tabulator-tables.d.ts +55 -34
  258. package/src/hosting/stage.ts +7 -7
  259. package/src/i18n/i18n-commands.ts +1 -2
  260. package/src/media/media-pane.ts +4 -1
  261. package/src/new-project/add-repo-modal.ts +20 -19
  262. package/src/new-project/import-tab.ts +10 -14
  263. package/src/new-project/location-fields.ts +2 -1
  264. package/src/new-project/new-project-modal.ts +12 -9
  265. package/src/packages/jxsuite-update.ts +4 -3
  266. package/src/packages/pull-package-sync.ts +26 -25
  267. package/src/page-params.ts +97 -68
  268. package/src/panels/activity-panel.ts +17 -9
  269. package/src/panels/ai-chat/attached-context.ts +13 -7
  270. package/src/panels/ai-chat/chat-view.ts +80 -73
  271. package/src/panels/ai-chat/composer.ts +30 -33
  272. package/src/panels/ai-chat/sessions-view.ts +1 -2
  273. package/src/panels/ai-panel.ts +23 -20
  274. package/src/panels/block-action-bar.ts +46 -35
  275. package/src/panels/bottom-dock.ts +5 -3
  276. package/src/panels/canvas-dnd-bridge.ts +31 -24
  277. package/src/panels/data-explorer.ts +62 -25
  278. package/src/panels/data-grid.ts +14 -11
  279. package/src/panels/dnd.ts +108 -118
  280. package/src/panels/editors.ts +55 -22
  281. package/src/panels/elements-panel.ts +10 -3
  282. package/src/panels/events-panel.ts +84 -69
  283. package/src/panels/formula-workspace.ts +76 -51
  284. package/src/panels/frontmatter-fields.ts +24 -19
  285. package/src/panels/frontmatter-panel.ts +44 -34
  286. package/src/panels/git-diff-open.ts +4 -4
  287. package/src/panels/git-panel.ts +49 -61
  288. package/src/panels/head-panel.ts +131 -111
  289. package/src/panels/i18n-panel.ts +10 -3
  290. package/src/panels/imports-panel.ts +23 -47
  291. package/src/panels/jump-bar.ts +48 -29
  292. package/src/panels/layers-panel.ts +97 -74
  293. package/src/panels/left-panel.ts +3 -3
  294. package/src/panels/pane-context.ts +31 -22
  295. package/src/panels/pane-grid.ts +49 -20
  296. package/src/panels/panel-registry.ts +22 -37
  297. package/src/panels/properties-panel.ts +175 -121
  298. package/src/panels/quick-search.ts +53 -31
  299. package/src/panels/right-panel.ts +3 -3
  300. package/src/panels/seo-modal.ts +13 -17
  301. package/src/panels/settings-menu.ts +15 -15
  302. package/src/panels/signals-panel.ts +153 -131
  303. package/src/panels/statement-editor.ts +230 -140
  304. package/src/panels/style-panel.ts +254 -216
  305. package/src/panels/style-utils.ts +114 -51
  306. package/src/panels/stylebook-doc.ts +57 -54
  307. package/src/panels/stylebook-layers-panel.ts +9 -9
  308. package/src/panels/stylebook-panel.ts +13 -17
  309. package/src/panels/tab-drop.ts +27 -11
  310. package/src/panels/tab-strip.ts +36 -26
  311. package/src/platform-errors.ts +57 -43
  312. package/src/platform.ts +58 -30
  313. package/src/platforms/cloud.ts +345 -175
  314. package/src/platforms/default-platform.ts +10 -4
  315. package/src/platforms/devserver.ts +174 -127
  316. package/src/platforms/read-batcher.ts +16 -8
  317. package/src/project-list.ts +2 -1
  318. package/src/publish/deploy-checklist.ts +8 -2
  319. package/src/publish/pages-service.ts +28 -13
  320. package/src/publish/publish-commands.ts +5 -4
  321. package/src/publish/publish-panel.ts +10 -6
  322. package/src/recent-projects.ts +15 -8
  323. package/src/resize-edges.ts +26 -36
  324. package/src/services/a11y-report.ts +26 -19
  325. package/src/services/agent-seed.ts +23 -11
  326. package/src/services/ai-ask.ts +9 -12
  327. package/src/services/ai-command-tools.ts +68 -62
  328. package/src/services/ai-import-tools.ts +80 -67
  329. package/src/services/ai-models.ts +17 -13
  330. package/src/services/ai-project-tools.ts +68 -32
  331. package/src/services/ai-session-store.ts +19 -10
  332. package/src/services/ai-system-prompt.ts +46 -20
  333. package/src/services/ai-tools.ts +71 -27
  334. package/src/services/ai-write-report.ts +20 -12
  335. package/src/services/ai-writes.ts +4 -4
  336. package/src/services/automation.ts +58 -31
  337. package/src/services/cem-export.ts +149 -58
  338. package/src/services/clock.ts +6 -1
  339. package/src/services/code-services.ts +37 -31
  340. package/src/services/context-manager.ts +14 -10
  341. package/src/services/context-resolver.ts +20 -8
  342. package/src/services/data-service.ts +19 -15
  343. package/src/services/directory-picker.ts +18 -12
  344. package/src/services/document-assistant.ts +39 -19
  345. package/src/services/gated-registry.ts +10 -6
  346. package/src/services/harness/chat-reducer.ts +23 -1
  347. package/src/services/import-client.ts +91 -38
  348. package/src/services/import-seed.ts +8 -2
  349. package/src/services/jx-validate.ts +28 -31
  350. package/src/services/live-preview.ts +0 -0
  351. package/src/services/live-surfaces.ts +6 -3
  352. package/src/services/model-uri.ts +10 -2
  353. package/src/services/module-preloads.ts +12 -8
  354. package/src/services/monaco-buffer.ts +43 -24
  355. package/src/services/monaco-lazy.ts +7 -8
  356. package/src/services/monaco-setup.ts +23 -16
  357. package/src/services/notify.ts +44 -17
  358. package/src/services/popover-report.ts +25 -10
  359. package/src/services/preview-eval.ts +20 -8
  360. package/src/services/profile.ts +13 -6
  361. package/src/services/project-path.ts +13 -10
  362. package/src/services/references.ts +0 -0
  363. package/src/services/render-critic.ts +8 -7
  364. package/src/services/settings/kernel.ts +13 -4
  365. package/src/services/settings/write-queue.ts +9 -9
  366. package/src/services/token-lint.ts +12 -10
  367. package/src/services/tool-executor.ts +17 -5
  368. package/src/services/tool-outcomes.ts +44 -24
  369. package/src/services/trusted-types.ts +24 -7
  370. package/src/settings/contexts-section.ts +11 -8
  371. package/src/settings/contributed-section.ts +79 -60
  372. package/src/settings/css-vars-editor.ts +37 -16
  373. package/src/settings/defs-editor.ts +38 -35
  374. package/src/settings/extension-rows.ts +16 -8
  375. package/src/settings/extension-sections.ts +23 -13
  376. package/src/settings/extensions-section.ts +4 -1
  377. package/src/settings/general-settings.ts +11 -8
  378. package/src/settings/locales-section.ts +20 -12
  379. package/src/settings/preferences-dialog.ts +9 -6
  380. package/src/settings/preferences-keymap.ts +7 -5
  381. package/src/settings/preferences-sections.ts +11 -5
  382. package/src/settings/project-sections.ts +1 -1
  383. package/src/settings/schema-field-ui.ts +9 -0
  384. package/src/settings/settings-document.ts +5 -5
  385. package/src/shell/tree.ts +6 -5
  386. package/src/shell.ts +104 -81
  387. package/src/site-context.ts +37 -22
  388. package/src/state.ts +41 -49
  389. package/src/store.ts +54 -34
  390. package/src/studio.ts +39 -77
  391. package/src/style/live-preview.ts +1 -1
  392. package/src/style/project-styles.ts +6 -7
  393. package/src/style/token-ref.ts +5 -4
  394. package/src/surfaces/about.ts +18 -19
  395. package/src/surfaces/add-repo.ts +17 -19
  396. package/src/surfaces/ai-chat.ts +31 -36
  397. package/src/surfaces/ai-credentials-form.ts +6 -16
  398. package/src/surfaces/ai-managed-connect.ts +3 -4
  399. package/src/surfaces/ai-model-picker.ts +3 -5
  400. package/src/surfaces/block-action-bar.ts +22 -11
  401. package/src/surfaces/boot-failure.ts +4 -5
  402. package/src/surfaces/bottom-dock.ts +9 -18
  403. package/src/surfaces/canvas-stage.ts +12 -11
  404. package/src/surfaces/cf-account-picker.ts +17 -18
  405. package/src/surfaces/commandbar.ts +14 -9
  406. package/src/surfaces/convert-repeater.ts +17 -19
  407. package/src/surfaces/data-actions.ts +9 -7
  408. package/src/surfaces/dialog.ts +26 -28
  409. package/src/surfaces/diff-toolbar.ts +9 -7
  410. package/src/surfaces/doc-header.ts +10 -19
  411. package/src/surfaces/empty-state.ts +7 -10
  412. package/src/surfaces/entry-editor.ts +14 -11
  413. package/src/surfaces/expression-editor.ts +11 -25
  414. package/src/surfaces/files-panel.ts +27 -14
  415. package/src/surfaces/formula-palette.ts +4 -5
  416. package/src/surfaces/git-panel.ts +7 -15
  417. package/src/surfaces/github-auth.ts +16 -20
  418. package/src/surfaces/github-publish.ts +17 -22
  419. package/src/surfaces/grid-cell.ts +30 -31
  420. package/src/surfaces/grid-open.ts +10 -14
  421. package/src/surfaces/grid-panel.ts +13 -9
  422. package/src/surfaces/grid-replace.ts +13 -13
  423. package/src/surfaces/grid-views.ts +15 -18
  424. package/src/surfaces/inspector-dock.ts +13 -12
  425. package/src/surfaces/jump-bar.ts +5 -6
  426. package/src/surfaces/jxsuite-update.ts +16 -22
  427. package/src/surfaces/library-pane.ts +25 -20
  428. package/src/surfaces/logic-panel.ts +17 -30
  429. package/src/surfaces/logic-workspace.ts +13 -15
  430. package/src/surfaces/media-browser.ts +11 -10
  431. package/src/surfaces/media-field.ts +4 -5
  432. package/src/surfaces/media-pane.ts +8 -7
  433. package/src/surfaces/menu.ts +29 -23
  434. package/src/surfaces/navigator-dock.ts +11 -12
  435. package/src/surfaces/new-project.ts +27 -26
  436. package/src/surfaces/pane-context.ts +20 -25
  437. package/src/surfaces/pane-grid.ts +15 -10
  438. package/src/surfaces/panel-activity.ts +5 -6
  439. package/src/surfaces/panel-data.ts +3 -4
  440. package/src/surfaces/panel-deploy-checklist.ts +5 -6
  441. package/src/surfaces/panel-elements.ts +5 -7
  442. package/src/surfaces/panel-i18n.ts +5 -7
  443. package/src/surfaces/panel-imports.ts +6 -13
  444. package/src/surfaces/panel-outline.ts +25 -19
  445. package/src/surfaces/panel-page.ts +11 -18
  446. package/src/surfaces/panel-problems.ts +5 -7
  447. package/src/surfaces/panel-signals.ts +20 -34
  448. package/src/surfaces/panel-stylebook-layers.ts +5 -8
  449. package/src/surfaces/preferences.ts +21 -11
  450. package/src/surfaces/progress-modal.ts +15 -9
  451. package/src/surfaces/properties-panel.json +1 -1
  452. package/src/surfaces/properties-panel.ts +20 -42
  453. package/src/surfaces/publish.ts +18 -18
  454. package/src/surfaces/push-plan.ts +7 -8
  455. package/src/surfaces/rail.json +126 -73
  456. package/src/surfaces/rail.ts +38 -12
  457. package/src/surfaces/reference-field.ts +11 -15
  458. package/src/surfaces/schema-builder.ts +16 -22
  459. package/src/surfaces/schema-form.ts +15 -25
  460. package/src/surfaces/secret-field.ts +9 -6
  461. package/src/surfaces/seo.ts +21 -15
  462. package/src/surfaces/settings-contexts.ts +9 -7
  463. package/src/surfaces/settings-contributed.ts +14 -10
  464. package/src/surfaces/settings-css-vars.ts +5 -12
  465. package/src/surfaces/settings-defs.json +2 -2
  466. package/src/surfaces/settings-defs.ts +17 -21
  467. package/src/surfaces/settings-deploy.ts +8 -15
  468. package/src/surfaces/settings-extensions.ts +5 -6
  469. package/src/surfaces/settings-head.ts +33 -39
  470. package/src/surfaces/settings-locales.ts +8 -20
  471. package/src/surfaces/settings-overview.ts +5 -6
  472. package/src/surfaces/settings-packages.ts +8 -7
  473. package/src/surfaces/settings-pane.ts +9 -18
  474. package/src/surfaces/settings-rawjson.ts +5 -6
  475. package/src/surfaces/shell.ts +1 -2
  476. package/src/surfaces/slash-menu.ts +19 -9
  477. package/src/surfaces/statements.ts +13 -18
  478. package/src/surfaces/statusbar.ts +17 -14
  479. package/src/surfaces/style-panel.ts +18 -31
  480. package/src/surfaces/stylebook-chrome.ts +3 -5
  481. package/src/surfaces/tab-strip.ts +14 -13
  482. package/src/surfaces/target-line.ts +6 -7
  483. package/src/surfaces/welcome.ts +5 -7
  484. package/src/tabs/patch-ops.ts +4 -3
  485. package/src/tabs/project-config.ts +32 -21
  486. package/src/tabs/selection.ts +36 -8
  487. package/src/tabs/tab.ts +52 -41
  488. package/src/tabs/transact.ts +98 -53
  489. package/src/tabs/typing.ts +31 -0
  490. package/src/types.ts +32 -17
  491. package/src/ui/ai-credentials-form.ts +10 -13
  492. package/src/ui/ai-model-picker.ts +3 -3
  493. package/src/ui/cf-account-picker.ts +7 -9
  494. package/src/ui/color-selector.ts +9 -5
  495. package/src/ui/dynamic-slot.ts +7 -8
  496. package/src/ui/expression-editor.ts +112 -105
  497. package/src/ui/form-controls.ts +57 -48
  498. package/src/ui/formula-catalog.ts +239 -230
  499. package/src/ui/formula-chips.ts +33 -18
  500. package/src/ui/layers.ts +44 -31
  501. package/src/ui/media-picker.ts +18 -9
  502. package/src/ui/popover-surface.ts +20 -12
  503. package/src/ui/progress-modal.ts +13 -8
  504. package/src/ui/regions.ts +7 -6
  505. package/src/ui/schema-form.ts +113 -70
  506. package/src/ui/surface.ts +71 -8
  507. package/src/ui/timing.ts +9 -0
  508. package/src/ui/value-source.ts +44 -31
  509. package/src/ui/virtual-window.ts +3 -2
  510. package/src/utils/base64.ts +3 -1
  511. package/src/utils/edit-display.ts +103 -74
  512. package/src/utils/element-selectors.ts +3 -2
  513. package/src/utils/google-fonts.ts +15 -14
  514. package/src/utils/inherited-style.ts +18 -20
  515. package/src/utils/link-target.ts +1 -1
  516. package/src/utils/preview-format.ts +25 -3
  517. package/src/utils/strip-events.ts +49 -22
  518. package/src/utils/studio-utils.ts +29 -14
  519. package/src/view.ts +2 -3
  520. package/src/workspace/pane-derive.ts +10 -12
  521. package/src/workspace/session.ts +53 -43
  522. package/src/workspace/workspace.ts +47 -36
  523. package/dist/chunks/2020-nkxms0ay.js +0 -4
  524. package/dist/chunks/adapter-m948ab5f.js +0 -4
  525. package/dist/chunks/cf-account-picker-n8hr38v7.js +0 -4
  526. package/dist/chunks/cf-settings-356xdtne.js +0 -4
  527. package/dist/chunks/color-area-jqhna8zy.js +0 -4
  528. package/dist/chunks/color-field-embq5ctg.js +0 -4
  529. package/dist/chunks/color-fpezvnkt.js +0 -4
  530. package/dist/chunks/color-slider-1qmw7wqy.js +0 -4
  531. package/dist/chunks/combobox-773hdzyj.js +0 -4
  532. package/dist/chunks/components-yk3t844e.js +0 -4
  533. package/dist/chunks/content-source-bawmyc09.js +0 -4
  534. package/dist/chunks/convert-to-repeater-7wns8kf1.js +0 -4
  535. package/dist/chunks/dialog-mtm9fq5t.js +0 -4
  536. package/dist/chunks/editor-6sc8nacq.js +0 -4
  537. package/dist/chunks/entry-commands-8ay9fh81.js +0 -4
  538. package/dist/chunks/extension-sections-na7rj3nr.js +0 -4
  539. package/dist/chunks/file-ops-gye0qw56.js +0 -4
  540. package/dist/chunks/files-dmc2xvcq.js +0 -4
  541. package/dist/chunks/format-host-t76b53f8.js +0 -4
  542. package/dist/chunks/fs-events-cg4tpz06.js +0 -4
  543. package/dist/chunks/git-panel-yef7bshy.js +0 -4
  544. package/dist/chunks/grid-view-7tt4bxw1.js +0 -51
  545. package/dist/chunks/icons-qbh8akb1.js +0 -4
  546. package/dist/chunks/iframe-entry-f7mqjwpm.js +0 -5
  547. package/dist/chunks/iframe-entry-haw7jkvz.js +0 -5
  548. package/dist/chunks/iframe-entry-z6qrytv3.js +0 -5
  549. package/dist/chunks/iframe-host-tmz30gfp.js +0 -4
  550. package/dist/chunks/index-nag78a9h.js +0 -4
  551. package/dist/chunks/jsonMode-zhwsprqk.js +0 -13
  552. package/dist/chunks/jx-validate-3gbp5nkn.js +0 -4
  553. package/dist/chunks/layers-fvz99859.js +0 -4
  554. package/dist/chunks/layers-panel-gchmbf9p.js +0 -4
  555. package/dist/chunks/listbox-s8fkmnq8.js +0 -4
  556. package/dist/chunks/lit-html-9agdspkt.js +0 -4
  557. package/dist/chunks/media-picker-rhjvyy00.js +0 -4
  558. package/dist/chunks/menu-2e4y9j7b.js +0 -4
  559. package/dist/chunks/menu-37d07z9m.js +0 -4
  560. package/dist/chunks/monaco-binding-2jnhjjvr.js +0 -4
  561. package/dist/chunks/monaco-buffer-rp21359g.js +0 -4
  562. package/dist/chunks/monaco-setup-vhh7gayr.js +0 -4
  563. package/dist/chunks/notify-h3www560.js +0 -4
  564. package/dist/chunks/number-field-gw7sq8rn.js +0 -4
  565. package/dist/chunks/parse-897fvqah.js +0 -4
  566. package/dist/chunks/platform-hz34wcd7.js +0 -4
  567. package/dist/chunks/popover-8htra4er.js +0 -4
  568. package/dist/chunks/publish-panel-exsmjzyj.js +0 -4
  569. package/dist/chunks/quick-search-pgaqeh0m.js +0 -4
  570. package/dist/chunks/references-2cgdxnb8.js +0 -4
  571. package/dist/chunks/right-panel-jf856w5w.js +0 -4
  572. package/dist/chunks/section-registry-jnf8r5gy.js +0 -4
  573. package/dist/chunks/select-n3v7gwas.js +0 -4
  574. package/dist/chunks/split-pff8f3ze.js +0 -4
  575. package/dist/chunks/studio-0f55h9ye.js +0 -5
  576. package/dist/chunks/studio-0sqdhnew.js +0 -12
  577. package/dist/chunks/studio-19x1c75w.js +0 -5
  578. package/dist/chunks/studio-2sqcndak.js +0 -5
  579. package/dist/chunks/studio-3aey7dd3.js +0 -5
  580. package/dist/chunks/studio-3bpdkq2s.js +0 -5
  581. package/dist/chunks/studio-47y6fbpf.js +0 -5
  582. package/dist/chunks/studio-4m3826v2.js +0 -5
  583. package/dist/chunks/studio-4nx2dj1g.js +0 -4
  584. package/dist/chunks/studio-4xv5s47r.js +0 -9
  585. package/dist/chunks/studio-5g4t8v6w.js +0 -5
  586. package/dist/chunks/studio-5py436sf.js +0 -5
  587. package/dist/chunks/studio-77kt594t.js +0 -5
  588. package/dist/chunks/studio-8f87n763.js +0 -10
  589. package/dist/chunks/studio-8mb00b84.js +0 -5
  590. package/dist/chunks/studio-8p51gq2h.js +0 -6
  591. package/dist/chunks/studio-954ds834.js +0 -5
  592. package/dist/chunks/studio-9ft45c83.js +0 -9
  593. package/dist/chunks/studio-a2138x5k.js +0 -7
  594. package/dist/chunks/studio-a9yzstqj.js +0 -5
  595. package/dist/chunks/studio-acdksxx6.js +0 -5
  596. package/dist/chunks/studio-ar8jcf2y.js +0 -5
  597. package/dist/chunks/studio-bmn4mn9j.js +0 -7
  598. package/dist/chunks/studio-e7xxa0sj.js +0 -5
  599. package/dist/chunks/studio-ecaz25vk.js +0 -5
  600. package/dist/chunks/studio-ery42sqr.js +0 -4
  601. package/dist/chunks/studio-fzdywr6p.js +0 -9
  602. package/dist/chunks/studio-g5fmf0c1.js +0 -5
  603. package/dist/chunks/studio-g7nse7zb.js +0 -5
  604. package/dist/chunks/studio-geq1ea6k.js +0 -14
  605. package/dist/chunks/studio-ghkb32r8.js +0 -5
  606. package/dist/chunks/studio-ghrhy2y7.js +0 -5
  607. package/dist/chunks/studio-grawhey1.js +0 -5
  608. package/dist/chunks/studio-h0xgswew.js +0 -5
  609. package/dist/chunks/studio-h9c4p2tx.js +0 -5
  610. package/dist/chunks/studio-jyzj5cxs.js +0 -5
  611. package/dist/chunks/studio-mgx8yhnz.js +0 -64
  612. package/dist/chunks/studio-mpb04y1d.js +0 -6
  613. package/dist/chunks/studio-n17mty64.js +0 -5
  614. package/dist/chunks/studio-nwh2eqsk.js +0 -6
  615. package/dist/chunks/studio-q1h883bt.js +0 -16
  616. package/dist/chunks/studio-q4tv82h7.js +0 -9
  617. package/dist/chunks/studio-qpqa7vk3.js +0 -5
  618. package/dist/chunks/studio-qqz8e5gk.js +0 -5
  619. package/dist/chunks/studio-qvasen3f.js +0 -5
  620. package/dist/chunks/studio-rggdb3hm.js +0 -5
  621. package/dist/chunks/studio-sghy936h.js +0 -4
  622. package/dist/chunks/studio-skprc6ef.js +0 -5
  623. package/dist/chunks/studio-tt2nactf.js +0 -5
  624. package/dist/chunks/studio-tyasmc39.js +0 -5
  625. package/dist/chunks/studio-vk9ezads.js +0 -5
  626. package/dist/chunks/studio-vzacdfsc.js +0 -4
  627. package/dist/chunks/studio-w4c0xmrw.js +0 -5
  628. package/dist/chunks/studio-wfjqhhbk.js +0 -5
  629. package/dist/chunks/studio-wgh5kxpj.js +0 -5
  630. package/dist/chunks/studio-xasj0796.js +0 -5
  631. package/dist/chunks/studio-y78s8r2n.js +0 -5
  632. package/dist/chunks/studio-z8w183sh.js +0 -5
  633. package/dist/chunks/studio-zscd9ty4.js +0 -928
  634. package/dist/chunks/studio-zxp13sss.js +0 -7
  635. package/dist/chunks/studio-zygnmm01.js +0 -5
  636. package/dist/chunks/swatch-group-8qh9a3bm.js +0 -4
  637. package/dist/chunks/tabs-jwthg40w.js +0 -4
  638. package/dist/chunks/textfield-spy3hc77.js +0 -4
  639. package/dist/chunks/toast-4d35zd64.js +0 -4
  640. package/dist/chunks/toast-host-8sjmfed3.js +0 -4
  641. package/dist/chunks/tooltip-fd6g9xy3.js +0 -4
  642. package/dist/chunks/tree-h19v1jfz.js +0 -4
  643. package/dist/chunks/tsMode-gr0m4dzr.js +0 -14
  644. package/dist/chunks/workspace-m15qtcqp.js +0 -4
  645. package/dist/chunks/ws-client-nf61frr1.js +0 -4
@@ -4,15 +4,15 @@
4
4
  *
5
5
  * Message-row anatomy: user messages render as right-aligned bubbles (attached-context blocks
6
6
  * become chips), assistant messages render sanitized markdown plus tool-call chips, tool messages
7
- * surface failures only, the streaming tail renders as plain text with a cursor
8
- * (markdown parses once on finalize), and chat errors get a danger row with recovery advice and a
9
- * Retry. **None of that is markup here any more** — `surfaces/ai-chat.json` draws it and this
10
- * module decides what it says, which is the same split the file always had with a document on the
11
- * other side of it instead of a lit template.
7
+ * surface failures only, the streaming tail renders as plain text with a cursor (markdown parses
8
+ * once on finalize), and chat errors get a danger row with recovery advice and a Retry. **None of
9
+ * that is markup here any more** — `surfaces/ai-chat.json` draws it and this module decides what it
10
+ * says, which is the same split the file always had with a document on the other side of it instead
11
+ * of a lit template.
12
12
  *
13
- * ai.md §3.2 (the accountable turn) is why three things here are not what they were:
13
+ * The accountable turn (ai.md §3.2) is why three things here are not what they were:
14
14
  *
15
- * - **A chip renders its OUTCOME.** It reads `ToolCallRecord.result`, so a chip that said
15
+ * - **A chip renders its OUTCOME.** It reads `LiveToolCall.result`, so a chip that said
16
16
  * `update_style: ["children",0]` no longer says exactly as much when the edit was refused as when
17
17
  * it landed. The live loop attaches each result as its call finishes (`appendToolResult`), and a
18
18
  * restored chat backfills it from the tool message that answered the call
@@ -24,48 +24,57 @@
24
24
  * - **An error offers Retry.** `chatState.retryLast()` has been implemented, exported and called by
25
25
  * nobody; the error row is where it belongs.
26
26
  *
27
- * ai.md §3.0 is why the three buttons here are not callbacks any more. History, New Chat and Retry
28
- * were closures this module received and invoked, so the capabilities existed ONLY as buttons: the
29
- * `Assistant` category held zero records, and nothing could reach them from the palette, a chord,
30
- * the automation runner or the generated commands sheet. They are {@link projectCommand} now, in
31
- * the idiom `surfaces/statusbar.ts` established — the record is the definition site, and this file
32
- * only decides where it is drawn and with which glyph.
27
+ * The assistant being addressable by name (ai.md §3.0) is why the three buttons here are not
28
+ * callbacks any more. History, New Chat and Retry were closures this module received and invoked,
29
+ * so the capabilities existed ONLY as buttons: the `Assistant` category held zero records, and
30
+ * nothing could reach them from the palette, a chord, the automation runner or the generated
31
+ * commands sheet. They are {@link projectCommand} now, in the idiom `surfaces/statusbar.ts`
32
+ * established — the record is the definition site, and this file only decides where it is drawn and
33
+ * with which glyph.
33
34
  *
34
35
  * @license MIT
35
36
  */
36
37
 
37
- import type { Message, ToolCallRecord } from "@jxsuite/ai/chat-state";
38
+ import type { LiveMessage, LiveToolCall } from "@jxsuite/ai/messages";
39
+ import { isBoolean, isJsonObject, isString } from "@jxsuite/schema/guards";
40
+ import type { JsonObject, JsonValue } from "@jxsuite/schema/types";
38
41
  import { splitAttachedContext } from "./attached-context";
39
42
  import { renderMarkdown } from "./chat-markdown";
40
43
  import { summarizeWrites, writesForTurn } from "../../services/ai-writes";
44
+ import { ASK_TOOL } from "../../services/tool-outcomes";
41
45
  import { activeRegistry } from "../../commands/active-registry";
42
46
 
47
+ import type { AskAnswer } from "../../services/ai-ask";
43
48
  import type { CommandRegistry } from "../../commands/registry";
44
49
  import type { ImportRunRecord } from "../../services/import-run";
45
- import type {
46
- ChatChangeView,
47
- ChatChipView,
48
- ChatCommandView,
49
- ChatContextChip,
50
- ChatRowView,
51
- } from "../../surfaces/ai-chat";
50
+ import type { ChatChipView, ChatCommandView, ChatRowView } from "../../surfaces/ai-chat";
51
+ import type { KeyedLabel } from "../../ui/surface";
52
52
 
53
53
  // ─── Helpers (moved from ai-panel.ts) ────────────────────────────────────────
54
54
 
55
+ /** The parts of a tool result message the transcript reads. */
56
+ export interface ParsedToolResult {
57
+ success: boolean;
58
+ error?: string;
59
+ summary?: string;
60
+ }
61
+
55
62
  /**
56
63
  * Parse a tool result message content (JSON string) into its success/error shape. Returns null if
57
64
  * the content isn't a valid tool result.
58
65
  *
59
66
  * @param {string} content
60
- * @returns {{ success: boolean; error?: string; summary?: string } | null}
67
+ * @returns {ParsedToolResult | null}
61
68
  */
62
- export function tryParseToolResult(
63
- content: string,
64
- ): { success: boolean; error?: string; summary?: string } | null {
69
+ export function tryParseToolResult(content: string): ParsedToolResult | null {
65
70
  try {
66
- const parsed = JSON.parse(content) as { success?: unknown; error?: string; summary?: string };
67
- if (parsed && typeof parsed.success === "boolean") {
68
- return parsed as { success: boolean; error?: string; summary?: string };
71
+ // SAFETY: JSON.parse only ever produces JSON values.
72
+ const parsed = JSON.parse(content) as JsonValue;
73
+ if (isJsonObject(parsed) && isBoolean(parsed.success)) {
74
+ /* SAFETY: a tool message's content is the agent loop's JSON.stringify of a ToolResult, whose
75
+ `error` and `summary` are strings when present; a boolean `success` is what tells that
76
+ envelope apart from any other JSON a message might carry. */
77
+ return parsed as JsonObject & ParsedToolResult;
69
78
  }
70
79
  } catch {
71
80
  /* Not JSON — not a tool result */
@@ -82,13 +91,11 @@ export function tryParseToolResult(
82
91
  export function formatToolLabel(tc: { name: string; arguments: string }): string {
83
92
  let detail = "";
84
93
  try {
85
- const args = (tc.arguments ? JSON.parse(tc.arguments) : {}) as {
86
- path?: unknown;
87
- parentPath?: unknown;
88
- };
89
- if (Array.isArray(args.path)) {
94
+ // SAFETY: JSON.parse only ever produces JSON values.
95
+ const args = (tc.arguments ? JSON.parse(tc.arguments) : {}) as JsonValue;
96
+ if (isJsonObject(args) && Array.isArray(args.path)) {
90
97
  detail = `: ${JSON.stringify(args.path)}`;
91
- } else if (Array.isArray(args.parentPath)) {
98
+ } else if (isJsonObject(args) && Array.isArray(args.parentPath)) {
92
99
  detail = `: ${JSON.stringify(args.parentPath)}`;
93
100
  }
94
101
  } catch {
@@ -213,9 +220,6 @@ export function tokenHint(tokens: number, overBudget: boolean): string {
213
220
 
214
221
  // ─── Tool calls ─────────────────────────────────────────────────────────────
215
222
 
216
- /** The tool whose chip is a question card rather than a chip. */
217
- const ASK_TOOL = "ask_user";
218
-
219
223
  /** The tool whose chip grows a live progress line while it runs. */
220
224
  const IMPORT_TOOL = "import_site";
221
225
 
@@ -233,25 +237,30 @@ interface AskArgs {
233
237
  * to render a call whose JSON is still half-written. A card with an empty question renders as an
234
238
  * ordinary chip rather than as an empty box.
235
239
  *
236
- * @param {ToolCallRecord} tc
240
+ * @param {LiveToolCall} tc
237
241
  * @returns {AskArgs | null}
238
242
  */
239
- export function parseAsk(tc: ToolCallRecord): AskArgs | null {
240
- let parsed: { question?: unknown; options?: unknown; context?: unknown };
243
+ export function parseAsk(tc: LiveToolCall): AskArgs | null {
244
+ let parsed: JsonValue;
241
245
  try {
242
- parsed = tc.arguments ? (JSON.parse(tc.arguments) as typeof parsed) : {};
246
+ // SAFETY: JSON.parse only ever produces JSON values.
247
+ parsed = tc.arguments ? (JSON.parse(tc.arguments) as JsonValue) : {};
243
248
  } catch {
244
249
  return null; // Still streaming, or malformed — the generic chip is the honest fallback.
245
250
  }
246
- if (typeof parsed.question !== "string" || !parsed.question.trim()) {
251
+ if (!isJsonObject(parsed)) {
252
+ return null;
253
+ }
254
+ const { context, options, question } = parsed;
255
+ if (!isString(question) || !question.trim()) {
247
256
  return null;
248
257
  }
249
258
  return {
250
- context: typeof parsed.context === "string" ? parsed.context : "",
251
- options: Array.isArray(parsed.options)
252
- ? parsed.options.filter((o): o is string => typeof o === "string" && o.trim().length > 0)
259
+ context: isString(context) ? context : "",
260
+ options: Array.isArray(options)
261
+ ? options.filter((o): o is string => isString(o) && o.trim().length > 0)
253
262
  : [],
254
- question: parsed.question,
263
+ question,
255
264
  };
256
265
  }
257
266
 
@@ -263,13 +272,13 @@ export function parseAsk(tc: ToolCallRecord): AskArgs | null {
263
272
  * indistinguishable from a live one and spins forever waiting for a loop that is gone. It is a
264
273
  * property of the RUN, not of the record, so the caller supplies whether this call is still live.
265
274
  *
266
- * @param {ToolCallRecord} tc
275
+ * @param {LiveToolCall} tc
267
276
  * @param {boolean} [live] - Whether the loop is still waiting on this call. Only consulted for a
268
277
  * result-less interactive call; every other pending call belongs to a turn still in flight.
269
278
  * @returns {"pending" | "unanswered" | "ok" | "failed"}
270
279
  */
271
280
  export function toolOutcome(
272
- tc: ToolCallRecord,
281
+ tc: LiveToolCall,
273
282
  live = true,
274
283
  ): "pending" | "unanswered" | "ok" | "failed" {
275
284
  if (!tc.result) {
@@ -285,10 +294,10 @@ export function toolOutcome(
285
294
  * is no reason the human could not have been reading it all along. A tool that failed writes
286
295
  * `error`, which was surfaced only through the separate tool-message row and only after the fact.
287
296
  *
288
- * @param {ToolCallRecord} tc
297
+ * @param {LiveToolCall} tc
289
298
  * @returns {string}
290
299
  */
291
- export function toolOutcomeText(tc: ToolCallRecord): string {
300
+ export function toolOutcomeText(tc: LiveToolCall): string {
292
301
  const { result } = tc;
293
302
  if (!result) {
294
303
  return "";
@@ -313,8 +322,8 @@ export interface AskHandlers {
313
322
  importRun?: (id: string) => ImportRunRecord | null;
314
323
  }
315
324
 
316
- /** The empty import fields every chip carries, so a `$switch` never reads an absent path. */
317
- function noImport(): Pick<
325
+ /** The import fields of a chip: empty, or projected from a running import's record. */
326
+ type ChipImportView = Pick<
318
327
  ChatChipView,
319
328
  | "hasPhase"
320
329
  | "importCount"
@@ -325,7 +334,10 @@ function noImport(): Pick<
325
334
  | "importProgress"
326
335
  | "importSpinner"
327
336
  | "importState"
328
- > {
337
+ >;
338
+
339
+ /** The empty import fields every chip carries, so a `$switch` never reads an absent path. */
340
+ function noImport(): ChipImportView {
329
341
  return {
330
342
  hasPhase: false,
331
343
  importCount: "",
@@ -354,7 +366,7 @@ function noImport(): Pick<
354
366
  * @param {ImportRunRecord} record
355
367
  * @returns {Partial<ChatChipView>}
356
368
  */
357
- function projectImport(record: ImportRunRecord): Partial<ChatChipView> {
369
+ function projectImport(record: ImportRunRecord): ChipImportView {
358
370
  const running = record.status === "running";
359
371
  const determinate = record.total !== null && record.current !== null;
360
372
  const outcome =
@@ -391,17 +403,21 @@ function projectImport(record: ImportRunRecord): Partial<ChatChipView> {
391
403
  * answer are all facts about one tool call, and putting them anywhere else would give the
392
404
  * transcript two accounts of the same event that can disagree after a reload.
393
405
  *
394
- * @param {ToolCallRecord} tc
406
+ * @param {LiveToolCall} tc
395
407
  * @param {AskHandlers} handlers
396
408
  * @returns {ChatChipView}
397
409
  */
398
- export function projectChip(tc: ToolCallRecord, handlers: AskHandlers = {}): ChatChipView {
410
+ export function projectChip(tc: LiveToolCall, handlers: AskHandlers = {}): ChatChipView {
399
411
  const outcome = toolOutcome(tc, tc.id === handlers.pendingId || Boolean(tc.result));
400
412
  const text = toolOutcomeText(tc);
401
413
  const run = tc.name === IMPORT_TOOL ? (handlers.importRun?.(tc.id) ?? null) : null;
402
414
  const ask = tc.name === ASK_TOOL ? parseAsk(tc) : null;
415
+ /* SAFETY: a successful ask_user result carries an AskAnswer (services/ai-ask.ts). Any other
416
+ tool's data only feeds `answer`, which the surface draws inside the ask card alone, and
417
+ `askState`, which is set only when `ask` is non-null, so a mistyped read never reaches the
418
+ screen. */
403
419
  const answered = tc.result?.success
404
- ? ((tc.result.data as { answer?: string | null; skipped?: boolean } | undefined) ?? null)
420
+ ? ((tc.result.data as Partial<AskAnswer> | undefined) ?? null)
405
421
  : null;
406
422
  const base: ChatChipView = {
407
423
  answer: answered ? (answered.skipped ? "You decide" : (answered.answer ?? "")) : "",
@@ -419,8 +435,7 @@ export function projectChip(tc: ToolCallRecord, handlers: AskHandlers = {}): Cha
419
435
  outcomeText: text,
420
436
  question: ask?.question ?? "",
421
437
  tool: tc.name,
422
- ...noImport(),
423
- ...(run ? projectImport(run) : {}),
438
+ ...(run ? projectImport(run) : noImport()),
424
439
  };
425
440
  if (ask) {
426
441
  /* The options are a shortcut, never the whole answer — the composer is always live beneath, and
@@ -451,19 +466,11 @@ export function projectChip(tc: ToolCallRecord, handlers: AskHandlers = {}): Cha
451
466
  * one would be the same lie the model-facing caveat used to be.
452
467
  *
453
468
  * @param {string} messageId
454
- * @returns {{
455
- * changesState: string;
456
- * changesSummary: string;
457
- * canRestore: boolean;
458
- * changes: ChatChangeView[];
459
- * }}
469
+ * @returns {Pick<ChatRowView, "canRestore" | "changes" | "changesState" | "changesSummary">}
460
470
  */
461
- export function projectChanges(messageId: string): {
462
- changesState: string;
463
- changesSummary: string;
464
- canRestore: boolean;
465
- changes: ChatChangeView[];
466
- } {
471
+ export function projectChanges(
472
+ messageId: string,
473
+ ): Pick<ChatRowView, "canRestore" | "changes" | "changesState" | "changesSummary"> {
467
474
  const writes = writesForTurn(messageId);
468
475
  const summary = writes.length > 0 ? summarizeWrites(writes) : "";
469
476
  if (!summary) {
@@ -504,12 +511,12 @@ function emptyRow(key: string, kind: string): ChatRowView {
504
511
  }
505
512
 
506
513
  /** The attached-context block on a user turn, back apart into chips. */
507
- function contextChips(lines: readonly string[]): ChatContextChip[] {
514
+ function contextChips(lines: readonly string[]): KeyedLabel[] {
508
515
  return lines.map((line, index) => ({ key: `${index}:${line}`, label: line }));
509
516
  }
510
517
 
511
518
  export interface MessageListOptions {
512
- messages: readonly Message[];
519
+ messages: readonly LiveMessage[];
513
520
  /** ChatState status — "streaming" projects the tail live. */
514
521
  status: string;
515
522
  /** The outstanding question and the import records, passed down rather than read here. */
@@ -7,9 +7,9 @@
7
7
  * (precedent: createAiCredentialsForm) so draft state never leaks between hosts.
8
8
  *
9
9
  * **There is no markup here.** `surfaces/ai-chat.json` draws the composer and this module says what
10
- * it holds — which is what let the auto-grow go entirely: the textarea grows with
11
- * `field-sizing: content`, where this file used to write `scrollHeight` back into `style.height` on
12
- * every keystroke.
10
+ * it holds — which is what let the auto-grow go entirely: the textarea grows with `field-sizing:
11
+ * content`, where this file used to write `scrollHeight` back into `style.height` on every
12
+ * keystroke.
13
13
  *
14
14
  * **The draft is a controlled value now, and that is safe for the reason it was not before.** The
15
15
  * lit textarea had to be uncontrolled, because a streaming repaint re-rendered the whole panel and
@@ -24,7 +24,7 @@
24
24
  * @license MIT
25
25
  */
26
26
 
27
- import { displayTagName } from "@jxsuite/schema/guards";
27
+ import { displayTagName, isNodeObject, isString } from "@jxsuite/schema/guards";
28
28
  import { getNodeAtPath } from "../../state";
29
29
  import { createModelPicker } from "../../ui/ai-model-picker";
30
30
  import { openMenu } from "../../surfaces/menu";
@@ -34,8 +34,7 @@ import { primarySelection } from "../../tabs/selection";
34
34
  import { buildMessageWithContext } from "./attached-context";
35
35
  import type { ContextChip } from "./attached-context";
36
36
  import type { ChatComposerChip } from "../../surfaces/ai-chat";
37
- import type { MenuHandle } from "../../surfaces/menu";
38
- import type { JxMutableNode } from "@jxsuite/schema/types";
37
+ import type { MenuHandle, OpenMenuOptions } from "../../surfaces/menu";
39
38
 
40
39
  export interface ComposerOptions {
41
40
  /** Receives the full message content (typed text + serialized context). */
@@ -80,7 +79,7 @@ export interface Composer {
80
79
  send: () => void;
81
80
  clear: () => void;
82
81
  /** Open the attach menu under the button that was pressed. */
83
- openAttachMenu: (anchor: unknown) => void;
82
+ openAttachMenu: (anchor: EventTarget | null) => void;
84
83
  /** Take a chip off, by its kind. */
85
84
  dropChip: (kind: string) => void;
86
85
  /** The model picker's host is in the page; put the picker's own element in it. */
@@ -124,27 +123,24 @@ export function createComposer(opts: ComposerOptions): Composer {
124
123
  const selection = primarySelection(tab?.session.selection);
125
124
  let selectionChip: ContextChip | null = null;
126
125
  if (tab && selection) {
127
- /* No `tagName?: string` in this cast any more. It overrode the widened type — a tag may be
128
- a name or a choice between names — so the compiler could not see that this chip would
129
- render `[object Object]` for a chosen one. A cast that narrows a field back to what it
130
- used to be is a hole the type system cannot report. */
131
- const node = getNodeAtPath(tab.doc.document as JxMutableNode, selection) as
132
- | (JxMutableNode & { textContent?: string })
133
- | undefined;
126
+ /* No cast narrows `tagName` back to a string: a tag may be a name or a choice between names,
127
+ and `displayTagName` is what renders either. A stale selection path resolves to nothing,
128
+ and a string child is not a node, so both read as a bare "element". */
129
+ const found = getNodeAtPath(tab.doc.document, selection);
130
+ const node = isNodeObject(found) ? found : undefined;
134
131
  const tag = displayTagName(node?.tagName) || "element";
135
- const text = typeof node?.textContent === "string" ? node.textContent.slice(0, 40) : "";
132
+ const textContent = node?.textContent;
133
+ const text = isString(textContent) ? textContent.slice(0, 40) : "";
136
134
  selectionChip = {
137
135
  detail: `Selected element at ${JSON.stringify(selection)}: <${tag}>${text ? ` "${text}"` : ""}`,
138
136
  kind: "selection",
139
137
  label: `<${tag}>`,
140
138
  };
141
139
  }
142
- return {
143
- pageChip: documentPath
144
- ? ({ detail: `Page: ${documentPath}`, kind: "page", label: documentPath } as ContextChip)
145
- : null,
146
- selectionChip,
147
- };
140
+ const pageChip: ContextChip | null = documentPath
141
+ ? { detail: `Page: ${documentPath}`, kind: "page", label: documentPath }
142
+ : null;
143
+ return { pageChip, selectionChip };
148
144
  }
149
145
 
150
146
  /** Add (or refresh) a chip of the given kind — one chip per kind. */
@@ -174,7 +170,7 @@ export function createComposer(opts: ComposerOptions): Composer {
174
170
  * `openMenu` rather than a popover of this module's own — the kit menu is the settled answer, and
175
171
  * it brings roving focus, typeahead, Escape and light dismissal with it.
176
172
  */
177
- function openAttachMenu(anchor: unknown): void {
173
+ function openAttachMenu(anchor: EventTarget | null): void {
178
174
  if (menu) {
179
175
  menu.close();
180
176
  menu = null;
@@ -182,22 +178,13 @@ export function createComposer(opts: ComposerOptions): Composer {
182
178
  }
183
179
  const opener = anchor instanceof HTMLElement ? anchor : null;
184
180
  const { pageChip, selectionChip } = contextCandidates();
185
- menu = openMenu({
181
+ const options: OpenMenuOptions = {
186
182
  label: "Attach context",
187
183
  onClosed: (handle) => {
188
184
  if (menu === handle) {
189
185
  menu = null;
190
186
  }
191
187
  },
192
- ...(opener ? { opener } : {}),
193
- ...(opener
194
- ? {
195
- place: () => {
196
- const box = rectOf(opener);
197
- return { x: box.left, y: box.top - 4 };
198
- },
199
- }
200
- : { origin: { x: 0, y: 0 } }),
201
188
  region: "assistant-attach",
202
189
  rows: [
203
190
  {
@@ -227,7 +214,17 @@ export function createComposer(opts: ComposerOptions): Composer {
227
214
  title: selectionChip ? `Selected element — ${selectionChip.label}` : "Selected element",
228
215
  },
229
216
  ],
230
- });
217
+ };
218
+ if (opener) {
219
+ options.opener = opener;
220
+ options.place = () => {
221
+ const box = rectOf(opener);
222
+ return { x: box.left, y: box.top - 4 };
223
+ };
224
+ } else {
225
+ options.origin = { x: 0, y: 0 };
226
+ }
227
+ menu = openMenu(options);
231
228
  }
232
229
 
233
230
  // ── Input ─────────────────────────────────────────────────────────────
@@ -14,11 +14,10 @@
14
14
  * @license MIT
15
15
  */
16
16
 
17
- import { now } from "../../services/clock";
17
+ import { MINUTE, now } from "../../services/clock";
18
18
  import type { ChatSessionView } from "../../surfaces/ai-chat";
19
19
  import type { SessionMeta } from "../../services/ai-session-store";
20
20
 
21
- const MINUTE = 60_000;
22
21
  const HOUR = 60 * MINUTE;
23
22
  const DAY = 24 * HOUR;
24
23
 
@@ -4,9 +4,8 @@
4
4
  *
5
5
  * The assistant over the reactive document-assistant session: a view-state machine (sessions list ↔
6
6
  * chat), the transcript, the sticky composer, and the six `Assistant:` records that are the only
7
- * definition of what it can do. It is a Jx document over the kit now
8
- * (`surfaces/ai-chat.json` + `surfaces/ai-chat.ts`); this module is the flow, and everything below
9
- * decides rather than draws.
7
+ * definition of what it can do. It is a Jx document over the kit now (`surfaces/ai-chat.json` +
8
+ * `surfaces/ai-chat.ts`); this module is the flow, and everything below decides rather than draws.
10
9
  *
11
10
  * Credentials are NOT a state of this panel. A provider key is a roaming APPLICATION setting
12
11
  * configured once, so it lives in Preferences › Assistant (⌘,) — not in a dialog reachable only
@@ -23,8 +22,8 @@
23
22
  * nothing else — the composer is never re-rendered, so there is nothing to guard against and
24
23
  * nothing to coalesce. One `effect()` recomputes the projection; the surface follows.
25
24
  *
26
- * @docs studio/ai/chat
27
25
  * @license MIT
26
+ * @docs studio/ai/chat
28
27
  */
29
28
 
30
29
  import { effect, effectScope } from "../reactivity";
@@ -64,7 +63,7 @@ import type { AiChatSurface, AiChatView } from "../surfaces/ai-chat";
64
63
  import type { AnyCommand } from "../commands/registry";
65
64
  import type { CommandContext } from "../commands/context";
66
65
  import type { EffectScope } from "@vue/reactivity";
67
- import type { Message } from "@jxsuite/ai/chat-state";
66
+ import type { LiveMessage } from "@jxsuite/ai/messages";
68
67
 
69
68
  // ─── State (module-level, persists across tab switches) ─────────────────────
70
69
 
@@ -73,9 +72,14 @@ let mounted = false;
73
72
  /** Which pane the panel shows. */
74
73
  let view: "chat" | "sessions" = "chat";
75
74
 
75
+ declare global {
76
+ /** The live assistant session, for inspection from a devtools console. */
77
+ var assistant: ReturnType<typeof createDocumentAssistant> | undefined;
78
+ }
79
+
76
80
  /** Document AST assistant session — created lazily, persists across tab switches. */
77
81
  const assistant = createDocumentAssistant();
78
- (globalThis as Record<string, unknown>).assistant = assistant;
82
+ globalThis.assistant = assistant;
79
83
  let assistantScope: EffectScope | null = null;
80
84
 
81
85
  // ─── The surface ────────────────────────────────────────────────────────────
@@ -224,10 +228,10 @@ function watchAssistant() {
224
228
  * The assistant message the tool replies at the end of the transcript answer: the one whose chips a
225
229
  * running tool's result is about to change.
226
230
  *
227
- * @param {readonly Message[]} messages
228
- * @returns {Message | undefined}
231
+ * @param {readonly LiveMessage[]} messages
232
+ * @returns {LiveMessage | undefined}
229
233
  */
230
- function latestRequest(messages: readonly Message[]): Message | undefined {
234
+ function latestRequest(messages: readonly LiveMessage[]): LiveMessage | undefined {
231
235
  for (let index = messages.length - 1; index >= 0; index--) {
232
236
  if (messages[index]!.role !== "tool") {
233
237
  return messages[index];
@@ -463,21 +467,20 @@ export function seedAssistantMessages(messages: SeededAssistantMessage[]): void
463
467
  for (const msg of messages) {
464
468
  seededCount += 1;
465
469
  const seq = seededCount;
466
- assistant.chatState.messages.push({
470
+ const message: LiveMessage = {
467
471
  content: msg.content,
468
472
  id: `seeded_${seq}`,
469
473
  role: msg.role,
470
474
  timestamp: seq,
471
- ...(msg.toolCalls
472
- ? {
473
- toolCalls: msg.toolCalls.map((tc, i) => ({
474
- arguments: tc.arguments,
475
- id: `seeded_${seq}_tc${i}`,
476
- name: tc.name,
477
- })),
478
- }
479
- : {}),
480
- });
475
+ };
476
+ if (msg.toolCalls) {
477
+ message.toolCalls = msg.toolCalls.map((tc, i) => ({
478
+ arguments: tc.arguments,
479
+ id: `seeded_${seq}_tc${i}`,
480
+ name: tc.name,
481
+ }));
482
+ }
483
+ assistant.chatState.messages.push(message);
481
484
  }
482
485
  renderAiPanel();
483
486
  }