@jxsuite/studio 8.0.1 → 9.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (282) hide show
  1. package/dist/chunks/{2020-5wtzce5g.js → 2020-89fz3pfy.js} +3 -3
  2. package/dist/chunks/adapter-ay13gema.js +4 -0
  3. package/dist/chunks/add-new-flow-nmkqpjym.js +4 -0
  4. package/dist/chunks/cf-account-picker-2e06qxey.js +4 -0
  5. package/dist/chunks/cf-settings-5y04810c.js +4 -0
  6. package/dist/chunks/color-04361ttk.js +4 -0
  7. package/dist/chunks/{color-area-6rbra5dy.js → color-area-h8dbasp1.js} +2 -2
  8. package/dist/chunks/{color-field-gy56c94g.js → color-field-qv5r2b16.js} +3 -3
  9. package/dist/chunks/{color-slider-sqqdyf6c.js → color-slider-nz2mrzky.js} +2 -2
  10. package/dist/chunks/{combobox-72h32ejk.js → combobox-6hs00996.js} +2 -2
  11. package/dist/chunks/components-3vf75n83.js +4 -0
  12. package/dist/chunks/content-source-4f2raf4a.js +4 -0
  13. package/dist/chunks/{convert-to-repeater-he70fc2b.js → convert-to-repeater-j9hfcj4f.js} +3 -3
  14. package/dist/chunks/editor-645krvtz.js +4 -0
  15. package/dist/chunks/entry-commands-3qmv8wkr.js +4 -0
  16. package/dist/chunks/{extension-sections-0egb88dm.js → extension-sections-thfke054.js} +3 -3
  17. package/dist/chunks/file-ops-kkhp9ma7.js +4 -0
  18. package/dist/chunks/files-yswdhxrf.js +4 -0
  19. package/dist/chunks/format-host-4g8ex6bz.js +4 -0
  20. package/dist/chunks/fs-events-z9gpvc6t.js +4 -0
  21. package/dist/chunks/grid-open-fm4j183c.js +4 -0
  22. package/dist/chunks/{grid-view-qg1b5eqx.js → grid-view-7d2nx83y.js} +16 -15
  23. package/dist/chunks/{icons-63bjtbs7.js → icons-853n6qt3.js} +2 -2
  24. package/dist/chunks/{iframe-entry-pkgmcgp0.js → iframe-entry-2x9bn5ng.js} +4 -4
  25. package/dist/chunks/{iframe-entry-99nr5zfb.js → iframe-entry-42hpmwz5.js} +4 -4
  26. package/dist/chunks/{iframe-entry-76j8vwwx.js → iframe-entry-b5qgggyp.js} +2 -2
  27. package/dist/chunks/{iframe-entry-2zggzajv.js → iframe-entry-btck0e9s.js} +4 -4
  28. package/dist/chunks/iframe-host-q7fedsmr.js +4 -0
  29. package/dist/chunks/{index-32eqzv1k.js → index-jxmt7vh8.js} +3 -3
  30. package/dist/chunks/index-pt4wh98x.js +4 -0
  31. package/dist/chunks/{javascript-pjp734q4.js → javascript-vmqp56ke.js} +2 -2
  32. package/dist/chunks/{jsonMode-njkvsa02.js → jsonMode-n3wmpant.js} +5 -5
  33. package/dist/chunks/jx-validate-19y62knt.js +4 -0
  34. package/dist/chunks/layers-panel-1qvc83y9.js +4 -0
  35. package/dist/chunks/layers-qf0bc7ze.js +4 -0
  36. package/dist/chunks/{listbox-c421cf8c.js → listbox-7gka1h86.js} +2 -2
  37. package/dist/chunks/lit-html-wyqw04y2.js +4 -0
  38. package/dist/chunks/media-library-f9d5qcjb.js +4 -0
  39. package/dist/chunks/media-picker-rsb1fmk2.js +4 -0
  40. package/dist/chunks/{menu-bdpzbfvs.js → menu-d2jxpgma.js} +2 -2
  41. package/dist/chunks/{monaco-binding-vq1hgnn0.js → monaco-binding-wfhmz89d.js} +3 -3
  42. package/dist/chunks/monaco-buffer-ak0raadw.js +4 -0
  43. package/dist/chunks/{monaco-setup-xrd2cbkp.js → monaco-setup-fty7a8vg.js} +3 -3
  44. package/dist/chunks/notify-4qj70q0x.js +4 -0
  45. package/dist/chunks/parse-n8dfxnqf.js +4 -0
  46. package/dist/chunks/platform-ehg6t9vd.js +4 -0
  47. package/dist/chunks/{popover-b89sfej7.js → popover-9tf4cjrk.js} +2 -2
  48. package/dist/chunks/publish-panel-yhmda3cd.js +4 -0
  49. package/dist/chunks/{publish-quick-qx2455cj.js → publish-quick-12hh8926.js} +3 -3
  50. package/dist/chunks/publish-workspace-hx8qdv9p.js +4 -0
  51. package/dist/chunks/quick-search-r955m3q1.js +4 -0
  52. package/dist/chunks/references-8gxv0x7t.js +4 -0
  53. package/dist/chunks/right-panel-jarwqjpy.js +4 -0
  54. package/dist/chunks/source-control-84qt25m9.js +4 -0
  55. package/dist/chunks/{split-c9zfdgxf.js → split-m5rwn31z.js} +2 -2
  56. package/dist/chunks/studio-0nefxhar.js +7 -0
  57. package/dist/chunks/studio-0rg30pvs.js +5 -0
  58. package/dist/chunks/{studio-s32578pn.js → studio-14hh60j8.js} +4 -4
  59. package/dist/chunks/studio-1cfyd1ys.js +5 -0
  60. package/dist/chunks/studio-2bq7hheq.js +5 -0
  61. package/dist/chunks/{studio-zz9qe3rw.js → studio-32d8wyxq.js} +37 -37
  62. package/dist/chunks/studio-3hpcawh8.js +4 -0
  63. package/dist/chunks/{studio-svb7yyve.js → studio-4j35hgsw.js} +4 -4
  64. package/dist/chunks/{studio-x1x167jh.js → studio-4qg61g9j.js} +4 -4
  65. package/dist/chunks/studio-4rgem12q.js +5 -0
  66. package/dist/chunks/studio-6k9djnxw.js +5 -0
  67. package/dist/chunks/studio-6rbaedw2.js +9 -0
  68. package/dist/chunks/studio-732mw0g8.js +5 -0
  69. package/dist/chunks/studio-79r8msnr.js +7 -0
  70. package/dist/chunks/studio-7q6jdd4h.js +5 -0
  71. package/dist/chunks/{studio-r5qy30vx.js → studio-8hf8qcm1.js} +4 -4
  72. package/dist/chunks/{studio-8tr6cfrc.js → studio-8pne0rx4.js} +4 -4
  73. package/dist/chunks/{studio-y0n7yxea.js → studio-9179bsm7.js} +7 -7
  74. package/dist/chunks/{studio-pbxa5fpc.js → studio-9ff0vqff.js} +3 -3
  75. package/dist/chunks/studio-9gzvypw4.js +5 -0
  76. package/dist/chunks/studio-9ndgd55w.js +5 -0
  77. package/dist/chunks/studio-9ra9e7m4.js +5 -0
  78. package/dist/chunks/studio-a6e5fzve.js +5 -0
  79. package/dist/chunks/studio-a9k86nq6.js +5 -0
  80. package/dist/chunks/studio-ae7a69jc.js +6 -0
  81. package/dist/chunks/studio-aghsg0ds.js +7 -0
  82. package/dist/chunks/{studio-k3xxbagr.js → studio-ajw4k8hp.js} +3 -3
  83. package/dist/chunks/{studio-qmn1xc24.js → studio-apapy17g.js} +4 -4
  84. package/dist/chunks/{studio-8m0y2qe7.js → studio-by8x0jvc.js} +4 -4
  85. package/dist/chunks/{studio-wbcjbhy1.js → studio-c88gq88j.js} +5 -5
  86. package/dist/chunks/{studio-n0c5h6mf.js → studio-cg54vtet.js} +4 -4
  87. package/dist/chunks/studio-dvhxxxbd.js +5 -0
  88. package/dist/chunks/{studio-3q40e3rj.js → studio-e4rq6x0q.js} +4 -4
  89. package/dist/chunks/{studio-fbhxxc5f.js → studio-ekzbgnjp.js} +4 -4
  90. package/dist/chunks/studio-fg4fj9ec.js +10 -0
  91. package/dist/chunks/studio-fj6jzgxw.js +5 -0
  92. package/dist/chunks/{studio-nh6d342n.js → studio-g45r5vm8.js} +7 -7
  93. package/dist/chunks/{studio-a2bvaptz.js → studio-gczve8zf.js} +4 -4
  94. package/dist/chunks/studio-ge08zwpv.js +5 -0
  95. package/dist/chunks/studio-gk9yk8dj.js +12 -0
  96. package/dist/chunks/{studio-bbe4c90a.js → studio-gskkgfe3.js} +4 -4
  97. package/dist/chunks/{studio-83mk4bgg.js → studio-h4jbgne2.js} +8 -8
  98. package/dist/chunks/{studio-b7y5mr30.js → studio-hcy9zeac.js} +4 -4
  99. package/dist/chunks/studio-ht81xjkr.js +5 -0
  100. package/dist/chunks/{studio-jaaz8ce9.js → studio-jr30g4ae.js} +4 -4
  101. package/dist/chunks/{studio-qgh13jtz.js → studio-k5n4es74.js} +4 -4
  102. package/dist/chunks/{studio-ccv2svc6.js → studio-k6hbx2fc.js} +4 -4
  103. package/dist/chunks/{studio-9tmebf0s.js → studio-kqh7fxn6.js} +4 -4
  104. package/dist/chunks/{studio-q0mvbaq6.js → studio-kyw47pet.js} +4 -4
  105. package/dist/chunks/studio-mkw17ngg.js +5 -0
  106. package/dist/chunks/{studio-x9hsze61.js → studio-myb4mf0h.js} +4 -4
  107. package/dist/chunks/studio-n4qq1n57.js +5 -0
  108. package/dist/chunks/studio-nfmpmkqb.js +5 -0
  109. package/dist/chunks/studio-nfwacw31.js +5 -0
  110. package/dist/chunks/{studio-rthyg42z.js → studio-nm86874b.js} +172 -172
  111. package/dist/chunks/studio-nqexty8x.js +16 -0
  112. package/dist/chunks/studio-nr0kcqc6.js +5 -0
  113. package/dist/chunks/{studio-jsgf2q5k.js → studio-nvfa137z.js} +5 -5
  114. package/dist/chunks/studio-psh8mwnw.js +4 -0
  115. package/dist/chunks/studio-qd0cycm4.js +9 -0
  116. package/dist/chunks/{studio-tfkznv39.js → studio-qevf5z9d.js} +4 -4
  117. package/dist/chunks/studio-qs5fmhtj.js +14 -0
  118. package/dist/chunks/studio-ry4789ng.js +7 -0
  119. package/dist/chunks/studio-s4fq9jht.js +5 -0
  120. package/dist/chunks/studio-sc35ttdk.js +5 -0
  121. package/dist/chunks/studio-sm2f0sc6.js +6 -0
  122. package/dist/chunks/{studio-3qeh9t0h.js → studio-spza69tb.js} +5 -5
  123. package/dist/chunks/studio-t6dqnnft.js +5 -0
  124. package/dist/chunks/{studio-43sd2mam.js → studio-tfmhnwyr.js} +3 -3
  125. package/dist/chunks/studio-tn7v8gey.js +6 -0
  126. package/dist/chunks/{studio-tft6r105.js → studio-trcfer2b.js} +4 -4
  127. package/dist/chunks/studio-tyw7tk0x.js +5 -0
  128. package/dist/chunks/{studio-jcnsdaep.js → studio-tyzgte21.js} +4 -4
  129. package/dist/chunks/studio-vtey9w98.js +5 -0
  130. package/dist/chunks/studio-ws2r1d7e.js +5 -0
  131. package/dist/chunks/studio-x2trkhk5.js +5 -0
  132. package/dist/chunks/{studio-mn0476ag.js → studio-xzgp0cp7.js} +4 -4
  133. package/dist/chunks/studio-y47090vq.js +5 -0
  134. package/dist/chunks/{studio-5g0rprdt.js → studio-yjh9gddd.js} +5 -5
  135. package/dist/chunks/studio-ywf9y1e2.js +5 -0
  136. package/dist/chunks/{studio-k7evxqh4.js → studio-z1p91z5a.js} +4 -4
  137. package/dist/chunks/studio-ztppbam0.js +5 -0
  138. package/dist/chunks/{toast-host-1yg5ar8d.js → toast-host-g3r2s0kn.js} +2 -2
  139. package/dist/chunks/toast-w11qpkyz.js +4 -0
  140. package/dist/chunks/{tooltip-yypz28gq.js → tooltip-dj1pvgz7.js} +2 -2
  141. package/dist/chunks/{tree-9xa4hm7n.js → tree-j0ebwr5s.js} +2 -2
  142. package/dist/chunks/{tsMode-epyfz1hv.js → tsMode-byje4a01.js} +5 -5
  143. package/dist/chunks/workspace-7q4arnt3.js +4 -0
  144. package/dist/chunks/workspace-home-ge027kr6.js +4 -0
  145. package/dist/chunks/{ws-client-bv552sfx.js → ws-client-h09h6sqg.js} +3 -3
  146. package/dist/iframe-entry.js +14 -14
  147. package/dist/manifest.json +76 -76
  148. package/dist/studio.js +88 -88
  149. package/package.json +15 -16
  150. package/src/browse/component-examples.ts +15 -224
  151. package/src/browse/library-preview.ts +6 -13
  152. package/src/browse/preview-root.ts +7 -4
  153. package/src/canvas/canvas-utils.ts +18 -4
  154. package/src/canvas/iframe-editable-root.ts +13 -4
  155. package/src/canvas/iframe-entry.ts +3 -1
  156. package/src/canvas/iframe-interaction.ts +11 -2
  157. package/src/canvas/iframe-render.ts +25 -3
  158. package/src/canvas/preview-placeholder.ts +120 -0
  159. package/src/collab/collab-session.ts +6 -2
  160. package/src/commands/context.ts +4 -0
  161. package/src/commands/defaults.ts +2 -0
  162. package/src/commands/live-context.ts +2 -0
  163. package/src/editor/shortcuts.ts +3 -0
  164. package/src/files/files.ts +6 -3
  165. package/src/new-project/new-project-modal.ts +1 -4
  166. package/src/panels/ai-panel.ts +27 -34
  167. package/src/panels/component-preview.ts +5 -0
  168. package/src/panels/pane-context.ts +43 -18
  169. package/src/panels/site-model.ts +7 -19
  170. package/src/panels/site-panel.ts +2 -25
  171. package/src/panels/stylebook-doc.ts +2 -53
  172. package/src/platform.ts +20 -0
  173. package/src/platforms/devserver.ts +2 -120
  174. package/src/services/ai-ask.ts +29 -171
  175. package/src/services/ai-command-tools.ts +40 -50
  176. package/src/services/ai-import-tools.ts +4 -5
  177. package/src/services/ai-project-tools.ts +13 -3
  178. package/src/services/ai-tools.ts +26 -564
  179. package/src/services/ai-writes.ts +84 -2
  180. package/src/services/document-assistant.ts +29 -58
  181. package/src/services/harness/assistant-tools.ts +68 -0
  182. package/src/services/harness/interaction-store.ts +118 -0
  183. package/src/services/harness/studio-documents.ts +105 -0
  184. package/src/services/harness/turn-hooks.ts +1 -6
  185. package/src/services/project-adoption.ts +8 -16
  186. package/src/services/references.ts +0 -0
  187. package/src/services/tool-executor.ts +25 -22
  188. package/src/state.ts +3 -13
  189. package/src/style/stylebook-specimens.ts +11 -15
  190. package/src/surfaces/files-panel.json +12 -0
  191. package/src/surfaces/files-panel.ts +5 -2
  192. package/src/surfaces/pane-context.json +286 -265
  193. package/src/surfaces/pane-context.ts +17 -8
  194. package/src/surfaces/welcome.ts +4 -1
  195. package/src/tabs/selection.ts +14 -109
  196. package/src/tabs/tab.ts +15 -7
  197. package/src/tabs/transact.ts +316 -124
  198. package/src/types.ts +13 -8
  199. package/src/utils/geometry.ts +49 -2
  200. package/dist/chunks/adapter-5tphg7xe.js +0 -4
  201. package/dist/chunks/add-new-flow-psym14sn.js +0 -4
  202. package/dist/chunks/cf-account-picker-haqazq5r.js +0 -4
  203. package/dist/chunks/cf-settings-h2wrh6hq.js +0 -4
  204. package/dist/chunks/color-m7r1vk54.js +0 -4
  205. package/dist/chunks/components-r22xca09.js +0 -4
  206. package/dist/chunks/content-source-mmppmcyg.js +0 -4
  207. package/dist/chunks/editor-ccd9jwsa.js +0 -4
  208. package/dist/chunks/entry-commands-6qxz9e8p.js +0 -4
  209. package/dist/chunks/file-ops-qnab36ek.js +0 -4
  210. package/dist/chunks/files-rcn56qvm.js +0 -4
  211. package/dist/chunks/format-host-yxz0kjjs.js +0 -4
  212. package/dist/chunks/fs-events-d1qxq4z4.js +0 -4
  213. package/dist/chunks/grid-open-4z1g062t.js +0 -4
  214. package/dist/chunks/iframe-host-ssv7kyj0.js +0 -4
  215. package/dist/chunks/index-f0jn7nnp.js +0 -4
  216. package/dist/chunks/jx-validate-ttasrbh7.js +0 -4
  217. package/dist/chunks/layers-bgyr11tr.js +0 -4
  218. package/dist/chunks/layers-panel-7ez66zeq.js +0 -4
  219. package/dist/chunks/lit-html-v9gh687x.js +0 -4
  220. package/dist/chunks/media-library-sq468wts.js +0 -4
  221. package/dist/chunks/media-picker-shfe59pt.js +0 -4
  222. package/dist/chunks/monaco-buffer-3afgwvbp.js +0 -4
  223. package/dist/chunks/notify-kzrjr3fv.js +0 -4
  224. package/dist/chunks/parse-v77xtwv7.js +0 -4
  225. package/dist/chunks/platform-7v4rtd7m.js +0 -4
  226. package/dist/chunks/publish-panel-2z9gw8ee.js +0 -4
  227. package/dist/chunks/publish-workspace-wrc1dgwx.js +0 -4
  228. package/dist/chunks/quick-search-n0t0eqxb.js +0 -4
  229. package/dist/chunks/references-9547rg5s.js +0 -4
  230. package/dist/chunks/right-panel-wsgnr9pn.js +0 -4
  231. package/dist/chunks/source-control-kwktr9y6.js +0 -4
  232. package/dist/chunks/studio-03ct6yfv.js +0 -9
  233. package/dist/chunks/studio-07rcfje3.js +0 -5
  234. package/dist/chunks/studio-3e54qh39.js +0 -7
  235. package/dist/chunks/studio-3exxhz5g.js +0 -5
  236. package/dist/chunks/studio-3qqjeep5.js +0 -6
  237. package/dist/chunks/studio-4hp8pkyt.js +0 -5
  238. package/dist/chunks/studio-58xg6j2q.js +0 -9
  239. package/dist/chunks/studio-6m380wp7.js +0 -5
  240. package/dist/chunks/studio-80jyh1xh.js +0 -4
  241. package/dist/chunks/studio-8vcvfs7r.js +0 -6
  242. package/dist/chunks/studio-bavb31r0.js +0 -5
  243. package/dist/chunks/studio-c05wdnt3.js +0 -5
  244. package/dist/chunks/studio-d5grtb9e.js +0 -16
  245. package/dist/chunks/studio-df0baea9.js +0 -5
  246. package/dist/chunks/studio-dgk4dqtx.js +0 -7
  247. package/dist/chunks/studio-e1g64q43.js +0 -5
  248. package/dist/chunks/studio-ed1hp6zf.js +0 -6
  249. package/dist/chunks/studio-ed3xx40h.js +0 -7
  250. package/dist/chunks/studio-f14e1zdj.js +0 -5
  251. package/dist/chunks/studio-fyh0jc96.js +0 -5
  252. package/dist/chunks/studio-gcxk20n7.js +0 -5
  253. package/dist/chunks/studio-kt3pjkwd.js +0 -5
  254. package/dist/chunks/studio-m8g16bgz.js +0 -5
  255. package/dist/chunks/studio-mx1smyq0.js +0 -5
  256. package/dist/chunks/studio-nqxqf8p2.js +0 -4
  257. package/dist/chunks/studio-p4nrkvqr.js +0 -5
  258. package/dist/chunks/studio-pgmvdv7z.js +0 -7
  259. package/dist/chunks/studio-ph84avkf.js +0 -5
  260. package/dist/chunks/studio-q0tccd43.js +0 -5
  261. package/dist/chunks/studio-q7rtx6zq.js +0 -14
  262. package/dist/chunks/studio-qwdqwkj0.js +0 -5
  263. package/dist/chunks/studio-rj9eamf8.js +0 -5
  264. package/dist/chunks/studio-rptgsk96.js +0 -5
  265. package/dist/chunks/studio-s19tp1xr.js +0 -5
  266. package/dist/chunks/studio-syreb644.js +0 -5
  267. package/dist/chunks/studio-tf9jryb1.js +0 -10
  268. package/dist/chunks/studio-txf2kysx.js +0 -5
  269. package/dist/chunks/studio-v8867ddv.js +0 -12
  270. package/dist/chunks/studio-vxq7fcvv.js +0 -5
  271. package/dist/chunks/studio-w4rz9hdk.js +0 -5
  272. package/dist/chunks/studio-wc649wss.js +0 -5
  273. package/dist/chunks/studio-wys23mxz.js +0 -5
  274. package/dist/chunks/studio-y3ahhdpx.js +0 -5
  275. package/dist/chunks/studio-z97c48fk.js +0 -5
  276. package/dist/chunks/studio-zat62m0c.js +0 -5
  277. package/dist/chunks/studio-zcd2e7yz.js +0 -5
  278. package/dist/chunks/toast-1gv0h53h.js +0 -4
  279. package/dist/chunks/workspace-dz7nxfhv.js +0 -4
  280. package/dist/chunks/workspace-home-xsd7hkjw.js +0 -4
  281. package/src/services/directory-picker.ts +0 -187
  282. package/src/services/gated-registry.ts +0 -77
@@ -11,9 +11,8 @@
11
11
 
12
12
  import { initProjectRepo } from "../files/files";
13
13
  import { getPlatform, hasPlatform } from "../platform";
14
- import { beginBatch, endBatch, isBatching } from "../tabs/transact";
14
+ import { flushOpenBatches } from "../tabs/transact";
15
15
  import { workspace } from "../workspace/workspace";
16
- import type { Tab } from "../tabs/tab";
17
16
 
18
17
  let _adopter: ((root: string) => Promise<void>) | null = null;
19
18
 
@@ -52,8 +51,6 @@ export interface AdoptOutcome {
52
51
 
53
52
  /** The seams {@link adoptCreatedProject} runs through, so each caller keeps the one it already had. */
54
53
  export interface AdoptCreatedOptions {
55
- /** The active tab, read AFTER adoption to re-anchor the agent loop's undo batch. */
56
- getTab: () => Tab | null;
57
54
  /** The project-open flow. Defaults to this module's late-bound {@link adoptProject}. */
58
55
  adopt?: (root: string) => Promise<void>;
59
56
  /** Version-control init. Defaults to `files/files.ts`'s `initProjectRepo`. */
@@ -76,9 +73,8 @@ export interface AdoptCreatedOptions {
76
73
  * - **Verifying.** `openRecentProject` swallows its failures into a status message, so a resolved
77
74
  * promise is not proof of adoption. The caller must be told which of the two happened.
78
75
  *
79
- * The batch dance is the third: the agent loop may hold an undo batch on the pre-adoption tab, and
80
- * adoption replaces every tab in the workspace. Flush it, adopt, re-open one on whatever tab
81
- * adoption left active.
76
+ * The third is the undo batch: the agent loop's lane may hold segments on pre-adoption tabs, and
77
+ * adoption replaces every tab in the workspace, so they are closed first (specs/ai.md §3.3).
82
78
  *
83
79
  * @param {string} root - Absolute root of the project that was just created.
84
80
  * @param {AdoptCreatedOptions} opts
@@ -86,7 +82,7 @@ export interface AdoptCreatedOptions {
86
82
  */
87
83
  export async function adoptCreatedProject(
88
84
  root: string,
89
- { getTab, adopt = adoptProject, initRepo = initProjectRepo }: AdoptCreatedOptions,
85
+ { adopt = adoptProject, initRepo = initProjectRepo }: AdoptCreatedOptions = {},
90
86
  ): Promise<AdoptOutcome> {
91
87
  // Never fails the create: a project that was written stays written (initProjectRepo notifies).
92
88
  await initRepo(root);
@@ -117,19 +113,15 @@ export async function adoptCreatedProject(
117
113
  }
118
114
  }
119
115
 
120
- const wasBatching = isBatching();
121
- if (wasBatching) {
122
- endBatch();
123
- }
116
+ /* The tabs an open lane has segments on are about to be replaced: close each now, against the
117
+ document it was written into. The lane stays open, so the turn's next write opens a segment on
118
+ whatever document it writes in the adopted project. */
119
+ flushOpenBatches();
124
120
  let adoptionError: string | null = null;
125
121
  try {
126
122
  await adopt(root);
127
123
  } catch (error) {
128
124
  adoptionError = error instanceof Error ? error.message : String(error);
129
125
  }
130
- if (wasBatching) {
131
- beginBatch(getTab());
132
- }
133
-
134
126
  return { adopted: workspace.projectRoot === root, error: adoptionError, openedElsewhere };
135
127
  }
Binary file
@@ -9,17 +9,19 @@
9
9
  * happen (`services/harness/chat-reducer.ts`), and each round's request is projected from it, as
10
10
  * it always was, so the provider sees the conversation the panel shows, with whatever the send
11
11
  * path trimmed or sealed before the turn began.
12
- * - **A batch belongs to the tab it edits** (§3.3). The undo batch opens on the active tab and is
13
- * re-anchored after every call whose tools moved to another document, so a turn that edits two
14
- * documents gives each its own history step and collab publish.
12
+ * - **The batch belongs to the assistant** (§3.3). The turn opens a batch lane owned by its actor,
13
+ * and every write the turn's tools make joins it, one segment per document written: each document
14
+ * gets one history step and one collab publish, whichever tab is active, and a person's edit
15
+ * during the turn closes the segment on that document rather than being folded into it.
15
16
  * - **The ledger is filed under the last message the turn drew** (§3.2), in this module's `finally`,
16
17
  * so the transcript draws the turn's changed-files summary under it.
17
18
  *
18
19
  * @license MIT
19
20
  */
20
21
 
22
+ import type { InteractionStore } from "./harness/interaction-store";
21
23
  import type { createChatState } from "@jxsuite/ai/chat-state";
22
- import { DEFAULT_TURN_POLICY, runTurn } from "@jxsuite/ai/harness";
24
+ import { DEFAULT_TURN_POLICY, assistantActorId, runTurn } from "@jxsuite/ai/harness";
23
25
  import type { TurnInput, TurnRun } from "@jxsuite/ai/harness";
24
26
  import { toChatMessages, toOpenAITools } from "@jxsuite/ai/messages";
25
27
  import type { StreamingClient } from "@jxsuite/ai/streaming-client";
@@ -27,7 +29,7 @@ import { createSessionFacts } from "@jxsuite/ai/tools";
27
29
  import type { SessionFacts, ToolRegistry } from "@jxsuite/ai/tools";
28
30
 
29
31
  import type { Tab } from "../tabs/tab";
30
- import { batchTab, beginBatch, endBatch } from "../tabs/transact";
32
+ import { openBatchLane } from "../tabs/transact";
31
33
  import { estimatePromptTokens } from "./context-manager";
32
34
  import { fileTurn, openTurnLedger, turnAnchor } from "./ai-writes";
33
35
  import { applyHarnessEvent } from "./harness/chat-reducer";
@@ -48,6 +50,8 @@ interface RunAgentLoopOptions {
48
50
  getTab?: () => Tab | null;
49
51
  /** The conversation's facts, which every call's context carries; a fresh set when omitted. */
50
52
  session?: SessionFacts;
53
+ /** Where a call that needs the author waits on them. Without one, such a call is refused. */
54
+ interactions?: InteractionStore;
51
55
  }
52
56
 
53
57
  /**
@@ -62,26 +66,23 @@ export async function runAgentLoop({
62
66
  signal,
63
67
  getTab,
64
68
  session = createSessionFacts(),
69
+ interactions,
65
70
  }: RunAgentLoopOptions): Promise<void> {
66
71
  /* The ledger is filed under the turn's last DRAWN assistant message (see services/ai-writes), so
67
72
  the scan starts at the message this turn answers. */
68
73
  const turnUserId = chatState.messages.findLast((m) => m.role === "user")?.id;
69
74
  const ledger = openTurnLedger(`turn:${chatState.messages.length}`);
70
75
 
71
- // Batch all tool-call mutations into a single undo step, anchored on the tab being edited.
72
- if (getTab) {
73
- beginBatch(getTab());
74
- }
75
- const reanchorBatch = () => {
76
- if (!getTab) {
77
- return;
78
- }
79
- const current = getTab();
80
- if (current !== batchTab()) {
81
- endBatch();
82
- beginBatch(current);
83
- }
84
- };
76
+ /* One undo step per document the turn writes. A loop with no `getTab` has no document of its own
77
+ (the evals), so it gets no lane and each tool is its own entry. The owner's id is the one each
78
+ call's context will carry, so a tool's write joins the lane by naming `ctx.actor`. */
79
+ const lane = getTab
80
+ ? openBatchLane({
81
+ id: assistantActorId(session.sessionId, ledger.turnId),
82
+ kind: "assistant",
83
+ turnId: ledger.turnId,
84
+ })
85
+ : null;
85
86
 
86
87
  /* The placeholder `sendMessage` pushed is round one's message, so the turn answers into it; the
87
88
  conversation the turn continues is everything before it. */
@@ -124,7 +125,6 @@ export async function runAgentLoop({
124
125
  superseded = true;
125
126
  run?.cancel("superseded");
126
127
  },
127
- reanchor: reanchorBatch,
128
128
  }),
129
129
  session,
130
130
  ledger,
@@ -137,13 +137,16 @@ export async function runAgentLoop({
137
137
  if (signal) {
138
138
  input.signal = signal;
139
139
  }
140
+ if (interactions) {
141
+ input.interactions = interactions.strategy;
142
+ }
140
143
  if (placeholder) {
141
144
  input.firstMessageId = placeholder.id;
142
145
  }
143
146
  run = runTurn(input);
144
147
  await run.outcome;
145
148
  } finally {
146
- endBatch();
147
- fileTurn(turnAnchor(chatState.messages, turnUserId) ?? "", ledger.writes);
149
+ const batches = lane?.close() ?? [];
150
+ fileTurn(turnAnchor(chatState.messages, turnUserId) ?? "", ledger.writes, batches);
148
151
  }
149
152
  }
package/src/state.ts CHANGED
@@ -154,19 +154,9 @@ export function pathsEqual(a: JxPath | null, b: JxPath | null) {
154
154
  return a.every((v, i) => v === b[i]);
155
155
  }
156
156
 
157
- /**
158
- * Returns true if `path` is an ancestor of (or equal to) `descendant`.
159
- *
160
- * @param {JxPath} path
161
- * @param {JxPath} descendant
162
- * @returns {boolean}
163
- */
164
- export function isAncestor(path: JxPath, descendant: JxPath) {
165
- if (path.length > descendant.length) {
166
- return false;
167
- }
168
- return path.every((v, i) => v === descendant[i]);
169
- }
157
+ /* Lives beside the doc-op vocabulary (`@jxsuite/schema/doc-ops`), with the other structural-path
158
+ helpers; re-exported for the many callers that import it from here. */
159
+ export { isAncestor } from "@jxsuite/schema/doc-ops";
170
160
 
171
161
  // ─── Tree flattening (for layer panel) ────────────────────────────────────────
172
162
 
@@ -5,14 +5,17 @@
5
5
  * component is rarely drawable that way: the museum starter's `<mu-exhibition-card>` formats a
6
6
  * `date` that defaults to `""`, so its card stayed empty and the canvas logged "was not rendered:
7
7
  * RangeError: Invalid time value" for it on every paint (`spec.md` §16.4). The Site panel's
8
- * previews already know where a component's sample props live (`browse/component-examples.ts`), so
9
- * a card asks the same three sources, in the same order, and draws:
8
+ * previews already know where a component's sample props live (`browse/component-examples.ts`: the
9
+ * definition's own `examples`), so a card asks the same source and draws:
10
10
  *
11
11
  * - `props`: an instance given its sample props, when the definition renders with them;
12
- * - `row`: the first row of a list that draws it, when it is only ever used as a list row;
13
- * - `bare`: the bare instance, when it renders with its defaults and nothing better was found;
14
- * - `none`: no live instance at all (the catalogue's placeholder box), when it renders with none of
15
- * the above, because an instance that throws draws nothing and reports an error nobody can fix.
12
+ * - `bare`: the bare instance, when it renders with its defaults and has no sample props it renders
13
+ * with;
14
+ * - `none`: no live instance at all (the catalogue's placeholder box), when it renders with neither,
15
+ * because an instance that throws draws nothing and reports an error nobody can fix.
16
+ *
17
+ * Nothing here reads the rest of the project, so a catalogue of N components costs N definition
18
+ * reads and no usage queries.
16
19
  *
17
20
  * Answers are cached per component registry: the registry is replaced whenever the project's
18
21
  * components are re-read, so a changed definition is asked again.
@@ -20,17 +23,14 @@
20
23
  * @docs studio/design/stylebook
21
24
  */
22
25
 
23
- import { componentExampleProps, componentSampleRow } from "../browse/component-examples";
24
- import type { SampleRow } from "../browse/component-examples";
26
+ import { componentExampleProps } from "../browse/component-examples";
25
27
  import { readDefinition, rendersWith } from "../browse/library-preview";
26
- import { defineComponent } from "../panels/component-preview";
27
28
  import type { ComponentEntry } from "../files/components";
28
29
  import type { JsonValue } from "@jxsuite/schema/types";
29
30
 
30
31
  /** How one component card is drawn; see the module comment. */
31
32
  export type StylebookSpecimen =
32
33
  | { kind: "props"; props: Record<string, JsonValue> }
33
- | { kind: "row"; sample: SampleRow }
34
34
  | { kind: "bare" }
35
35
  | { kind: "none" };
36
36
 
@@ -49,14 +49,10 @@ export async function componentSpecimen(component: ComponentEntry): Promise<Styl
49
49
  if (!definition) {
50
50
  return { kind: "bare" };
51
51
  }
52
- const props = await componentExampleProps(definition, path);
52
+ const props = componentExampleProps(definition);
53
53
  if (props.size > 0 && (await rendersWith(definition, path, props))) {
54
54
  return { kind: "props", props: Object.fromEntries(props) };
55
55
  }
56
- const sample = await componentSampleRow(definition, path);
57
- if (sample && (await defineComponent(component))) {
58
- return { kind: "row", sample };
59
- }
60
56
  return (await rendersWith(definition, path, new Map())) ? { kind: "bare" } : { kind: "none" };
61
57
  }
62
58
 
@@ -136,6 +136,18 @@
136
136
  }
137
137
  ]
138
138
  },
139
+ "address": {
140
+ "tagName": "div",
141
+ "attributes": {
142
+ "part": "empty"
143
+ },
144
+ "children": [
145
+ {
146
+ "tagName": "p",
147
+ "textContent": "Add ?project= and a project folder's absolute path to this page's address to open it."
148
+ }
149
+ ]
150
+ },
139
151
  "welcome": {
140
152
  "tagName": "div",
141
153
  "attributes": {
@@ -81,8 +81,11 @@ export interface FileRowView {
81
81
 
82
82
  /** Everything the document draws, as one value. */
83
83
  export interface FilesPanelValues {
84
- /** Which of three things the panel is: no project, a monorepo root, or a tree. */
85
- view: "none" | "welcome" | "tree";
84
+ /**
85
+ * Which of four things the panel is: no project, a monorepo root on a host that can open a
86
+ * project, the same root on one that opens from the address (`?project=`), or a tree.
87
+ */
88
+ view: "none" | "welcome" | "address" | "tree";
86
89
  headerState: "hidden" | "shown";
87
90
  projectName: string;
88
91
  query: string;