@marimo-team/islands 0.25.3-dev29 → 0.25.3-dev290

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 (841) hide show
  1. package/dist/{ConnectedDataExplorerComponent-7EaP9VWb.js → ConnectedDataExplorerComponent-CErm132k.js} +116 -113
  2. package/dist/{ErrorBoundary-ysC54Xwn.js → ErrorBoundary-DwcFY0Nf.js} +76 -82
  3. package/dist/_baseSet-BfI5FjBM.js +328 -0
  4. package/dist/{abnfDiagram-VCTEODGH-z_OSynK8.js → abnfDiagram-VCTEODGH-d-Qn2fwb.js} +2 -2
  5. package/dist/any-language-editor-6k6F12Z3.js +75 -0
  6. package/dist/{architectureDiagram-5GKGNRK7-Cs8J8BZr.js → architectureDiagram-5GKGNRK7-DxragHYv.js} +1 -1
  7. package/dist/{arrays-CN1djC4k.js → arrays-DoQ-AILx.js} +15 -27
  8. package/dist/assertNever-B-YzWzbL.js +507 -0
  9. package/dist/assets/__vite-browser-external-BKBpimif.js +1 -0
  10. package/dist/assets/worker-CgoMtD-_.js +113 -0
  11. package/dist/{blockDiagram-I7D4REHJ-Cg25UrxT.js → blockDiagram-I7D4REHJ-Dkhe6_PP.js} +1 -1
  12. package/dist/{button-CvjkwdSk.js → button-DZuNnIZO.js} +56 -48
  13. package/dist/{capabilities-CQ5IjhzL.js → capabilities-D9FskwsK.js} +2 -2
  14. package/dist/{chat-ui-0udY4hpv.js → chat-ui-ByGe2rP1.js} +2100 -1810
  15. package/dist/{check-BMKBBrdc.js → check-XFzZeH-y.js} +1 -1
  16. package/dist/{chunk-IMKFNOWR-aoSFasqF.js → chunk-IMKFNOWR-C0x0feFg.js} +1 -1
  17. package/dist/{chunk-SHT3W25Y-CMaybO3O.js → chunk-SHT3W25Y-D0ZdASqB.js} +1 -1
  18. package/dist/{chunk-SVP7TREG-BNBrTAw1.js → chunk-SVP7TREG-BHjL96zx.js} +1 -1
  19. package/dist/{chunk-TICWLB2K-DXNxvUJn.js → chunk-TICWLB2K-CzcrwGfp.js} +1 -1
  20. package/dist/{classDiagram-ZZMXUADV-DXdCCDOg.js → classDiagram-ZZMXUADV-BTqFAZTP.js} +2 -2
  21. package/dist/{classDiagram-v2-VYDZK3BY-DyZqrtLP.js → classDiagram-v2-VYDZK3BY-EPXb0Elt.js} +2 -2
  22. package/dist/{code-visibility-CZmyRTO8.js → code-visibility-DSS4dPIe.js} +43 -50
  23. package/dist/{common-CCrzSQnL.js → common-CHNDbyF2.js} +10605 -10045
  24. package/dist/config-C8MFHQ2E.js +637 -0
  25. package/dist/{copy-icon-BgUO8jsi.js → copy-icon-CtllOdmg.js} +3 -3
  26. package/dist/createReducer-DRqwmaTc.js +67 -0
  27. package/dist/{cynefinDiagram-5FMLGOSQ-DWHuKJs8.js → cynefinDiagram-5FMLGOSQ-CBSD344q.js} +1 -1
  28. package/dist/{dagre-GXQ25YYZ-DYLu-OCU.js → dagre-GXQ25YYZ-JItjh3Ge.js} +3 -3
  29. package/dist/{dagre-BGSfXNEb.js → dagre-mqiMAsFY.js} +531 -680
  30. package/dist/{data-grid-overlay-editor-B141KnZO.js → data-grid-overlay-editor-8fOxyvQO.js} +1 -1
  31. package/dist/{debounce-C3jyATpc.js → debounce-DrhhziJv.js} +2 -2
  32. package/dist/{diagram-S7CK7UJ4-PwwcUOHP.js → diagram-S7CK7UJ4-CTD9xTVb.js} +1 -1
  33. package/dist/{diagram-UQ7AKVKN-CvJbL_IM.js → diagram-UQ7AKVKN-DTfnFai8.js} +1 -1
  34. package/dist/{diagram-VX7I27RA-B5RkqnzN.js → diagram-VX7I27RA-BcSnucV-.js} +1 -1
  35. package/dist/{diagram-Z3DM3KII-CyijwTR2.js → diagram-Z3DM3KII-C2ATIE8A.js} +1 -1
  36. package/dist/{dialog-Cc479ZEH.js → dialog-CaYm5imE.js} +32 -32
  37. package/dist/{dist-Bvs24R_E.js → dist-11T5wq3_.js} +31 -30
  38. package/dist/{dist-F8Ep36rk.js → dist-17ugwGZc.js} +59 -58
  39. package/dist/{dist-BMQf5zIS.js → dist-7cRjf--y.js} +123 -122
  40. package/dist/{dist-diIx5qJW.js → dist-B8pkfkzc.js} +31 -30
  41. package/dist/{dist-CN_BeG2I.js → dist-B9UoM_wq.js} +58 -57
  42. package/dist/{dist-CLdpGQVr.js → dist-BGuMTs1i.js} +118 -117
  43. package/dist/{dist-BK4Oj99o.js → dist-BHW11fni.js} +18 -17
  44. package/dist/dist-BLY4m1Wi.js +850 -0
  45. package/dist/{dist-PXYI_yuP.js → dist-BNlcVoxs.js} +24 -23
  46. package/dist/{dist-D6d86eNJ.js → dist-BQYe5Bju.js} +47 -46
  47. package/dist/{dist-CkTTIdBe.js → dist-BX1mn8na.js} +337 -337
  48. package/dist/{dist-DiDibOYr.js → dist-Bh0PTKUW.js} +151 -150
  49. package/dist/{dist-CSJ0MDRw.js → dist-CKaXK92p.js} +56 -55
  50. package/dist/{dist-C8fAKSH1.js → dist-CLhwfhpJ.js} +53 -52
  51. package/dist/{dist-DoE4XJBC.js → dist-CYeqK4Xw.js} +9801 -10649
  52. package/dist/{dist-BLfKmR-l.js → dist-Cxlp3WH6.js} +16 -15
  53. package/dist/{dist-D-wwqlzJ.js → dist-DSJPGj42.js} +158 -157
  54. package/dist/{dist-BorMD-uX.js → dist-DU9ICsWZ.js} +75 -74
  55. package/dist/{dist-DBtSl3sf.js → dist-DWv0ALBi.js} +47 -46
  56. package/dist/{dist-OR1OnN-y.js → dist-DiBpWEsB.js} +31 -30
  57. package/dist/{dist-CrSP_H1M.js → dist-DiLFTlnl.js} +242 -242
  58. package/dist/{dist-CN8zI-XC.js → dist-X9CsotJl.js} +239 -239
  59. package/dist/{dist-CSbh1PNP.js → dist-cVDV5IuI.js} +23 -22
  60. package/dist/{dist-BuaRHxOc.js → dist-fRfaOoq8.js} +44 -43
  61. package/dist/{dist-Cg7gzw-a.js → dist-gTTI-9Px.js} +78 -77
  62. package/dist/{dropdown-menu-BuE2b8Yb.js → dropdown-menu-Bb0bFOIk.js} +2904 -1493
  63. package/dist/{ebnfDiagram-PWID7BFC-DG90ELFp.js → ebnfDiagram-PWID7BFC-B7B9JPxc.js} +2 -2
  64. package/dist/{erDiagram-RLTQ6QDP-FMo_SpyX.js → erDiagram-RLTQ6QDP-v6hDno1O.js} +1 -1
  65. package/dist/{error-banner-CFPHFw4h.js → error-banner-CHCdHVFB.js} +87 -87
  66. package/dist/error-entries-9U4BFHjf.js +2586 -0
  67. package/dist/{esm-AMFssoNp.js → esm-BDqqT86j.js} +329 -329
  68. package/dist/{esm-D2gTsXEV.js → esm-BgKjMvWw.js} +530 -529
  69. package/dist/feedback-button-C7Wzdmjf.js +374 -0
  70. package/dist/{flowDiagram-HODETNUW-DQ4JuadE.js → flowDiagram-HODETNUW-aIFlAtOy.js} +2 -2
  71. package/dist/{formats-DRHUWwSK.js → formats-PzBQMUnr.js} +6 -6
  72. package/dist/{glide-data-editor-DLHbRbsj.js → glide-data-editor-BA2VyhpI.js} +6630 -2846
  73. package/dist/{glide-utils-pisbYVjH.js → glide-utils-BSQr4d90.js} +107 -76
  74. package/dist/{globals-D2g1BHQ0.js → globals-DLzuY2gk.js} +3 -3
  75. package/dist/{graphlib-BmY_CCV9.js → graphlib-nlwT3Wvy.js} +177 -220
  76. package/dist/hasIn-C20JsQ2m.js +28 -0
  77. package/dist/{error-entries-DgtRTNaG.js → html-to-image-BYh_MorV.js} +26294 -26451
  78. package/dist/{infoDiagram-27XIBGKW-CRSDtRrd.js → infoDiagram-27XIBGKW-D6YHLeCP.js} +1 -1
  79. package/dist/isArrayLikeObject-B-HXCsex.js +626 -0
  80. package/dist/isEmpty-CdX7MTE1.js +14 -0
  81. package/dist/{ishikawaDiagram-5VMMS53U-DxLEUldB.js → ishikawaDiagram-5VMMS53U-D1ZvprOX.js} +1 -1
  82. package/dist/{kanban-definition-UXKFOSKX-BLhvu8o4.js → kanban-definition-UXKFOSKX-Bna_3BMr.js} +1 -1
  83. package/dist/{loader-BPdQhmlq.js → loader-DZvtzQoD.js} +3 -3
  84. package/dist/main.js +10276 -8171
  85. package/dist/{mermaid-Bjm6C1qN.js → mermaid-A36unKXJ.js} +62 -62
  86. package/dist/{mindmap-definition-YA3MSWOX-g2LwxnYQ.js → mindmap-definition-YA3MSWOX-CyVCs__G.js} +1 -1
  87. package/dist/{now-jM8-M7IR.js → now-BKZCLE5P.js} +12 -13
  88. package/dist/{number-overlay-editor-DHqP6YVn.js → number-overlay-editor-BpuvB3ho.js} +1 -1
  89. package/dist/{objects-CzUgoMIF.js → objects-DCmMvZtn.js} +1 -3
  90. package/dist/{once-BtE-wKRL.js → once-NnpX_HnX.js} +1 -1
  91. package/dist/{pegDiagram-XKGWAZYB-CpMAt3Qs.js → pegDiagram-XKGWAZYB-9hNBD2wZ.js} +2 -2
  92. package/dist/pencil-DYUlSKxZ.js +10 -0
  93. package/dist/pick-tCszMUbm.js +35 -0
  94. package/dist/{pieDiagram-E7YTZNPT-CVTthoZo.js → pieDiagram-E7YTZNPT-8tr-NYo7.js} +1 -1
  95. package/dist/{process-output-CuIlhYwn.js → process-output-bS3MGJ3f.js} +4 -4
  96. package/dist/{railroadDiagram-O6MQD6OU-ao8cqqFB.js → railroadDiagram-O6MQD6OU-Dzg1dyyp.js} +2 -2
  97. package/dist/{react-vega-BDpbvBCb.js → react-vega-C4T9Rb_w.js} +1 -1
  98. package/dist/{requirementDiagram-BXWQKSXE--J8vyfm-.js → requirementDiagram-BXWQKSXE-B7sNqwGG.js} +1 -1
  99. package/dist/{reveal-component-DYHhtPqq.js → reveal-component-BKBSU4IA.js} +1151 -1128
  100. package/dist/select-DsoP1qe8.js +1200 -0
  101. package/dist/{sequenceDiagram-WJ2MYXX4-CiQbn62x.js → sequenceDiagram-WJ2MYXX4-oP9shbaG.js} +1 -1
  102. package/dist/{spec-D_u2ipzF.js → spec-BZMDxAu7.js} +41 -11
  103. package/dist/{stateDiagram-D77RDMKH-DVEeGs5b.js → stateDiagram-D77RDMKH-CjCv4ogv.js} +4 -4
  104. package/dist/{stateDiagram-v2-MP3YSRHH-1OQRe6iA.js → stateDiagram-v2-MP3YSRHH-BW9X162a.js} +2 -2
  105. package/dist/static-state-D-Q-Ajaa.js +72 -0
  106. package/dist/style.css +1 -1
  107. package/dist/{swimlanes-42K2YHIH-CqkGoGqn.js → swimlanes-42K2YHIH-Ckfs9Wrn.js} +1 -1
  108. package/dist/{swimlanesDiagram-VR7AAH4N-CszjkrKo.js → swimlanesDiagram-VR7AAH4N-DpTNG9YP.js} +2 -2
  109. package/dist/{swiper-component-DKntyn8p.js → swiper-component-DQbK_ZWm.js} +7 -7
  110. package/dist/{timeline-definition-24CTP7MA-DLRUNVAx.js → timeline-definition-24CTP7MA-BXaBlV6U.js} +1 -1
  111. package/dist/toast-BhjIy3Tq.js +491 -0
  112. package/dist/{tooltip-CtBZ5q8p.js → tooltip-DMMiOn2f.js} +321 -297
  113. package/dist/use-restore-focus-CosX7-gx.js +7568 -0
  114. package/dist/{useAsyncData-BneN349z.js → useAsyncData-Ci4AvJff.js} +18 -17
  115. package/dist/{useDateFormatter-DkajGwwd.js → useDateFormatter-CPlava52.js} +2 -2
  116. package/dist/{useDeepCompareMemoize-Z_7R8wTt.js → useDeepCompareMemoize-NaaWoFlX.js} +1 -1
  117. package/dist/useEvent-BRH-aCqi.js +19 -0
  118. package/dist/{useIframeCapabilities-DBETvvPl.js → useIframeCapabilities-BXhDDoCG.js} +1 -1
  119. package/dist/useLifecycle-SniivYmC.js +112 -0
  120. package/dist/{vega-component-1lFfDE_8.js → vega-component-DIxaDQNs.js} +161 -160
  121. package/dist/{vega-embed-container-BgKnsDbB.js → vega-embed-container--LYZqguO.js} +2 -2
  122. package/dist/{vega-loader.browser-CpbZAXub.js → vega-loader.browser-B9Pz0EGP.js} +1 -1
  123. package/dist/{vennDiagram-4TSXK5OY-CypgoBVZ.js → vennDiagram-4TSXK5OY-C-hQ4iNJ.js} +1 -1
  124. package/dist/{wardleyDiagram-VM6X3IG4-B6xjiQ_g.js → wardleyDiagram-VM6X3IG4-C2MQ_Umv.js} +1 -1
  125. package/dist/{xychartDiagram-S5SC5T6Z-e0PefDVs.js → xychartDiagram-S5SC5T6Z-BtTTBn7Q.js} +1 -1
  126. package/package.json +16 -20
  127. package/src/__mocks__/document.tsx +63 -0
  128. package/src/__mocks__/executions.ts +197 -0
  129. package/src/__mocks__/notebook.ts +3 -7
  130. package/src/__mocks__/partial.ts +26 -0
  131. package/src/__mocks__/requests.ts +1 -4
  132. package/src/__tests__/CellStatus.test.tsx +25 -26
  133. package/src/__tests__/fixtures/pair-config.ts +1 -1
  134. package/src/__tests__/main.test.tsx +24 -1
  135. package/src/__tests__/module-entry.test.ts +44 -0
  136. package/src/__tests__/mount.test.ts +1 -21
  137. package/src/__tests__/{host-imports.test.ts → replica-imports.test.ts} +12 -11
  138. package/src/components/ai/__tests__/ai-model-dropdown.test.tsx +63 -0
  139. package/src/components/ai/ai-model-dropdown.tsx +11 -6
  140. package/src/components/app-config/__tests__/state.test.tsx +50 -0
  141. package/src/components/app-config/ai-config.tsx +156 -150
  142. package/src/components/app-config/app-config-button.tsx +6 -5
  143. package/src/components/app-config/app-config-form.tsx +5 -9
  144. package/src/components/app-config/common.tsx +7 -9
  145. package/src/components/app-config/data-form.tsx +112 -113
  146. package/src/components/app-config/mcp-config.tsx +30 -53
  147. package/src/components/app-config/user-config-form.css +91 -0
  148. package/src/components/app-config/user-config-form.tsx +266 -349
  149. package/src/components/chat/__tests__/capabilities-popover.test.tsx +0 -1
  150. package/src/components/chat/__tests__/chat-display.test.tsx +196 -0
  151. package/src/components/chat/__tests__/chat-markdown.test.tsx +43 -0
  152. package/src/components/chat/__tests__/chat-utils.test.ts +93 -1
  153. package/src/components/chat/__tests__/message-queue.test.tsx +17 -0
  154. package/src/components/chat/__tests__/notebook-access-selector.test.tsx +64 -0
  155. package/src/components/chat/__tests__/turn-timing.test.ts +84 -0
  156. package/src/components/chat/__tests__/use-assistant-turn.test.ts +95 -0
  157. package/src/components/chat/__tests__/user-message.test.tsx +27 -0
  158. package/src/components/chat/acp/__tests__/agent-panel-initialization.test.tsx +1 -1
  159. package/src/components/chat/acp/__tests__/agent-panel.test.tsx +22 -17
  160. package/src/components/chat/acp/__tests__/session-tabs.test.tsx +43 -0
  161. package/src/components/chat/acp/__tests__/state.test.ts +2 -2
  162. package/src/components/chat/acp/agent-panel.tsx +6 -3
  163. package/src/components/chat/acp/blocks.tsx +13 -12
  164. package/src/components/chat/acp/common.tsx +4 -5
  165. package/src/components/chat/acp/model-selector.tsx +1 -1
  166. package/src/components/chat/acp/session-tabs.tsx +8 -3
  167. package/src/components/chat/agent-activity.tsx +132 -0
  168. package/src/components/chat/capabilities-popover.tsx +2 -11
  169. package/src/components/chat/chat-components.tsx +9 -4
  170. package/src/components/chat/chat-display.tsx +131 -57
  171. package/src/components/chat/chat-history-popover.tsx +6 -1
  172. package/src/components/chat/chat-markdown.tsx +15 -0
  173. package/src/components/chat/chat-panel.tsx +216 -294
  174. package/src/components/chat/chat-typography.css +108 -0
  175. package/src/components/chat/chat-utils.ts +24 -35
  176. package/src/components/chat/notebook-access-selector.stories.tsx +22 -0
  177. package/src/components/chat/notebook-access-selector.tsx +100 -0
  178. package/src/components/chat/tool-call/__tests__/tool-labels.test.ts +76 -0
  179. package/src/components/chat/tool-call/__tests__/tool-step.test.tsx +57 -0
  180. package/src/components/chat/tool-call/shared.ts +6 -0
  181. package/src/components/chat/tool-call/tool-call-view.tsx +22 -76
  182. package/src/components/chat/tool-call/tool-labels.ts +172 -0
  183. package/src/components/chat/tool-call/tool-result.tsx +1 -1
  184. package/src/components/chat/tool-call/tool-step.tsx +145 -0
  185. package/src/components/chat/turn-timing.ts +73 -0
  186. package/src/components/chat/use-assistant-turn.ts +65 -0
  187. package/src/components/chat/use-chat-generation.ts +20 -0
  188. package/src/components/chat/user-message.tsx +145 -0
  189. package/src/components/data-table/TableBottomBar.tsx +4 -1
  190. package/src/components/data-table/TableTopBar.tsx +2 -0
  191. package/src/components/data-table/__tests__/chart-spec-model.test.ts +195 -195
  192. package/src/components/data-table/__tests__/column-explorer.test.tsx +27 -1
  193. package/src/components/data-table/__tests__/columns.test.tsx +105 -0
  194. package/src/components/data-table/__tests__/context-menu-interaction.test.tsx +130 -0
  195. package/src/components/data-table/__tests__/data-table.test.tsx +1 -0
  196. package/src/components/data-table/__tests__/date-popover.test.tsx +72 -0
  197. package/src/components/data-table/__tests__/export-actions.test.tsx +105 -0
  198. package/src/components/data-table/__tests__/keyboard-selection.test.tsx +188 -0
  199. package/src/components/data-table/__tests__/pagination.test.tsx +28 -1
  200. package/src/components/data-table/__tests__/search-highlight.test.tsx +109 -0
  201. package/src/components/data-table/__tests__/url-detector.test.tsx +74 -0
  202. package/src/components/data-table/cell-selection/feature.ts +2 -2
  203. package/src/components/data-table/cell-selection/types.ts +2 -2
  204. package/src/components/data-table/charts/__tests__/chart-panel.test.tsx +74 -1
  205. package/src/components/data-table/charts/__tests__/spec-snapshot.test.ts +20 -20
  206. package/src/components/data-table/charts/__tests__/spec.test.ts +78 -52
  207. package/src/components/data-table/charts/__tests__/storage.test.ts +4 -1
  208. package/src/components/data-table/charts/chart-spec/spec.ts +68 -43
  209. package/src/components/data-table/charts/charts.tsx +40 -30
  210. package/src/components/data-table/charts/storage.ts +16 -5
  211. package/src/components/data-table/column-explorer-panel/column-explorer.tsx +1 -1
  212. package/src/components/data-table/column-formatting/types.ts +1 -2
  213. package/src/components/data-table/column-summary/chart-spec-model.tsx +23 -16
  214. package/src/components/data-table/column-summary/column-summary.tsx +2 -4
  215. package/src/components/data-table/column-visibility-dropdown.tsx +8 -13
  216. package/src/components/data-table/columns.tsx +45 -46
  217. package/src/components/data-table/context-menu.tsx +36 -20
  218. package/src/components/data-table/data-table.tsx +17 -1
  219. package/src/components/data-table/date-popover.tsx +6 -4
  220. package/src/components/data-table/export-actions.tsx +76 -48
  221. package/src/components/data-table/pagination.tsx +44 -33
  222. package/src/components/data-table/range-focus/atoms.ts +4 -6
  223. package/src/components/data-table/range-focus/use-cell-range-selection.ts +65 -38
  224. package/src/components/data-table/range-focus/use-scroll-into-view.ts +21 -2
  225. package/src/components/data-table/renderers.tsx +16 -7
  226. package/src/components/data-table/row-viewer-panel/__tests__/row-viewer.test.tsx +24 -1
  227. package/src/components/data-table/row-viewer-panel/row-viewer.tsx +4 -4
  228. package/src/components/data-table/search-highlight.tsx +79 -0
  229. package/src/components/data-table/types.ts +1 -0
  230. package/src/components/data-table/url-detector.tsx +49 -9
  231. package/src/components/datasources/__tests__/column-actions.test.tsx +97 -0
  232. package/src/components/datasources/__tests__/column-preview.test.tsx +96 -5
  233. package/src/components/datasources/__tests__/datasources-interactions.test.tsx +181 -0
  234. package/src/components/datasources/__tests__/table-list.test.tsx +118 -0
  235. package/src/components/datasources/__tests__/utils.test.ts +57 -6
  236. package/src/components/datasources/column-preview.tsx +17 -12
  237. package/src/components/datasources/datasources.tsx +56 -43
  238. package/src/components/datasources/utils.ts +32 -23
  239. package/src/components/debugger/debugger-code.tsx +5 -0
  240. package/src/components/dependency-graph/custom-node.tsx +1 -1
  241. package/src/components/dependency-graph/dependency-graph-tree.tsx +8 -8
  242. package/src/components/dependency-graph/elements.ts +24 -21
  243. package/src/components/dependency-graph/minimap-content.tsx +15 -20
  244. package/src/components/dependency-graph/panels.tsx +4 -2
  245. package/src/components/dependency-graph/utils/__tests__/layout.test.ts +18 -11
  246. package/src/components/editor/SortableCell.tsx +1 -3
  247. package/src/components/editor/__tests__/Output.test.tsx +50 -32
  248. package/src/{core/attachments/__tests__/toast.test.tsx → components/editor/__tests__/agent-toast.test.tsx} +1 -1
  249. package/src/components/editor/__tests__/data-attributes.test.tsx +28 -23
  250. package/src/components/editor/__tests__/dynamic-favicon.test.tsx +111 -18
  251. package/src/components/editor/__tests__/output-persistence.test.tsx +28 -9
  252. package/src/components/editor/__tests__/package-alert.test.tsx +22 -1
  253. package/src/components/editor/actions/__tests__/name-cell-input.test.tsx +69 -0
  254. package/src/components/editor/actions/__tests__/pair-with-agent-commands.test.ts +21 -40
  255. package/src/components/editor/actions/__tests__/pair-with-agent-modal.test.tsx +41 -14
  256. package/src/components/editor/actions/__tests__/pair-with-agent.test.tsx +6 -24
  257. package/src/components/editor/actions/__tests__/useCellActionButton.test.tsx +131 -0
  258. package/src/components/editor/actions/name-cell-input.tsx +4 -3
  259. package/src/components/editor/actions/pair-with-agent-commands.ts +10 -7
  260. package/src/components/editor/actions/pair-with-agent-modal.tsx +29 -30
  261. package/src/components/editor/actions/pair-with-agent.tsx +16 -39
  262. package/src/components/editor/actions/useCellActionButton.tsx +47 -35
  263. package/src/components/editor/actions/useConfigActions.tsx +3 -4
  264. package/src/components/editor/actions/useNotebookActions.tsx +25 -29
  265. package/src/components/editor/actions/useRestartKernel.tsx +1 -1
  266. package/src/components/editor/actions/useSetCodeVisibility.ts +11 -12
  267. package/src/components/editor/actions/useSetOutputsExpanded.ts +14 -19
  268. package/src/components/editor/ai/ai-completion-editor.tsx +2 -1
  269. package/src/components/editor/ai/completion-handlers.tsx +0 -37
  270. package/src/components/editor/ai/prompt-input.tsx +189 -0
  271. package/src/components/editor/alerts/__tests__/connection-notice.test.tsx +1 -1
  272. package/src/components/editor/alerts/connection-notice.tsx +1 -1
  273. package/src/components/editor/alerts/startup-logs-alert.tsx +1 -0
  274. package/src/components/editor/alerts/stdin-blocking-alert.tsx +4 -2
  275. package/src/components/editor/app-container.tsx +1 -1
  276. package/src/components/editor/boundary/__tests__/ErrorBoundary.test.tsx +1 -1
  277. package/src/components/editor/cell/CellStatus.tsx +28 -23
  278. package/src/components/editor/cell/CreateCellButton.tsx +15 -21
  279. package/src/components/editor/cell/DeleteButton.tsx +3 -2
  280. package/src/components/editor/cell/RunButton.tsx +18 -8
  281. package/src/components/editor/cell/StagedAICell.tsx +52 -137
  282. package/src/components/editor/cell/StopButton.tsx +2 -2
  283. package/src/components/editor/cell/__tests__/useRunCells.test.tsx +169 -0
  284. package/src/components/editor/cell/__tests__/useShouldShowInterrupt.test.ts +39 -0
  285. package/src/components/editor/cell/cell-actions.tsx +12 -1
  286. package/src/components/editor/cell/cell-context-menu.tsx +4 -1
  287. package/src/components/editor/cell/code/__tests__/language-toggle.test.tsx +54 -0
  288. package/src/components/editor/cell/code/cell-editor.tsx +65 -169
  289. package/src/components/editor/cell/code/language-toggle.tsx +8 -7
  290. package/src/components/editor/cell/collapse.tsx +16 -6
  291. package/src/components/editor/cell/useAddCell.ts +4 -8
  292. package/src/components/editor/cell/useDeleteCell.tsx +10 -36
  293. package/src/components/editor/cell/useRunCells.ts +49 -8
  294. package/src/components/editor/cell/useShouldShowInterrupt.ts +2 -12
  295. package/src/components/editor/cell/useSplitCell.tsx +10 -6
  296. package/src/components/editor/chrome/components/__tests__/feedback-button.test.tsx +1 -1
  297. package/src/components/editor/chrome/components/feedback-button.tsx +2 -8
  298. package/src/components/editor/chrome/panels/__tests__/packages-panel.test.tsx +31 -2
  299. package/src/components/editor/chrome/panels/__tests__/runtime-details.test.tsx +1 -1
  300. package/src/components/editor/chrome/panels/__tests__/sandbox-recovery.test.tsx +1 -1
  301. package/src/components/editor/chrome/panels/cache-panel.tsx +1 -0
  302. package/src/components/editor/chrome/panels/dependency-graph-panel.tsx +1 -1
  303. package/src/components/editor/chrome/panels/logs-panel.tsx +2 -1
  304. package/src/components/editor/chrome/panels/outline/__tests__/outline-keyboard.test.tsx +84 -0
  305. package/src/components/editor/chrome/panels/outline/floating-outline.tsx +39 -14
  306. package/src/components/editor/chrome/panels/outline/useActiveOutline.tsx +3 -2
  307. package/src/components/editor/chrome/panels/packages-panel.tsx +4 -7
  308. package/src/components/editor/chrome/panels/panel-header.tsx +13 -0
  309. package/src/components/editor/chrome/panels/secrets-panel.tsx +1 -0
  310. package/src/components/editor/chrome/panels/session-panel.tsx +1 -1
  311. package/src/components/editor/chrome/panels/snippets-panel.tsx +10 -12
  312. package/src/components/editor/chrome/panels/variable-panel.tsx +1 -5
  313. package/src/components/editor/chrome/types.ts +1 -1
  314. package/src/components/editor/chrome/wrapper/__tests__/attachment-status.test.tsx +7 -9
  315. package/src/components/editor/chrome/wrapper/__tests__/document-sync-status.test.tsx +92 -0
  316. package/src/components/editor/chrome/wrapper/__tests__/pending-ai-cells.test.tsx +265 -37
  317. package/src/components/editor/chrome/wrapper/__tests__/useAskAiAboutCell.test.tsx +58 -0
  318. package/src/components/editor/chrome/wrapper/app-chrome.tsx +91 -74
  319. package/src/components/editor/chrome/wrapper/footer-items/attachment-status.tsx +4 -4
  320. package/src/components/editor/chrome/wrapper/footer-items/backend-status.tsx +1 -1
  321. package/src/components/editor/chrome/wrapper/footer-items/document-sync-status.tsx +54 -0
  322. package/src/components/editor/chrome/wrapper/footer-items/lsp-status.tsx +1 -1
  323. package/src/components/editor/chrome/wrapper/footer-items/machine-stats.tsx +1 -1
  324. package/src/components/editor/chrome/wrapper/footer-items/runtime-settings.tsx +1 -7
  325. package/src/components/editor/chrome/wrapper/footer.tsx +2 -2
  326. package/src/components/editor/chrome/wrapper/minimap-state.ts +1 -1
  327. package/src/components/editor/chrome/wrapper/pending-ai-cells.tsx +143 -72
  328. package/src/components/editor/chrome/wrapper/pending-ai-changes-badge.tsx +25 -0
  329. package/src/components/editor/chrome/wrapper/sidebar.tsx +8 -4
  330. package/src/components/editor/chrome/wrapper/storage.ts +1 -1
  331. package/src/components/editor/chrome/wrapper/useAskAiAboutCell.ts +36 -0
  332. package/src/components/editor/columns/__tests__/cell-column.test.tsx +1 -1
  333. package/src/components/editor/columns/cell-column.tsx +1 -1
  334. package/src/components/editor/columns/sortable-column.tsx +2 -2
  335. package/src/components/editor/connections/components.tsx +5 -10
  336. package/src/components/editor/controls/Controls.tsx +4 -4
  337. package/src/components/editor/controls/__tests__/command-palette.test.tsx +53 -0
  338. package/src/components/editor/controls/__tests__/keyboard-shortcuts.test.tsx +61 -0
  339. package/src/components/editor/controls/__tests__/notebook-menu-dropdown.test.tsx +10 -4
  340. package/src/components/editor/controls/command-palette.tsx +22 -10
  341. package/src/components/editor/controls/keyboard-shortcuts.tsx +14 -5
  342. package/src/components/editor/documentation.css +34 -11
  343. package/src/components/editor/dynamic-favicon.tsx +21 -40
  344. package/src/components/editor/errors/__tests__/send-error-report-button.test.tsx +26 -22
  345. package/src/components/editor/errors/auto-fix.tsx +4 -8
  346. package/src/components/editor/errors/send-error-report-button.tsx +3 -6
  347. package/src/components/editor/file-tree/__tests__/file-explorer-interactions.test.tsx +6 -0
  348. package/src/components/editor/file-tree/__tests__/file-explorer-navigation.test.tsx +47 -0
  349. package/src/components/editor/file-tree/__tests__/use-file-search.test.tsx +91 -0
  350. package/src/components/editor/file-tree/file-explorer.tsx +48 -15
  351. package/src/components/editor/file-tree/file-name-input.tsx +1 -0
  352. package/src/components/editor/file-tree/file-viewer.tsx +4 -2
  353. package/src/components/editor/file-tree/use-file-search.ts +35 -21
  354. package/src/components/editor/header/__tests__/filename-form.test.tsx +1 -4
  355. package/src/components/editor/header/__tests__/status.test.tsx +5 -3
  356. package/src/components/editor/header/app-header.tsx +1 -1
  357. package/src/components/editor/header/filename-form.tsx +1 -1
  358. package/src/components/editor/header/status.tsx +44 -22
  359. package/src/components/editor/links/__tests__/cell-link.test.tsx +148 -0
  360. package/src/components/editor/links/cell-link-list.tsx +1 -1
  361. package/src/components/editor/links/cell-link.tsx +21 -11
  362. package/src/components/editor/navigation/__tests__/clipboard.test.ts +60 -38
  363. package/src/components/editor/navigation/__tests__/navigation.test.ts +108 -85
  364. package/src/components/editor/navigation/__tests__/selection.test.ts +43 -21
  365. package/src/components/editor/navigation/clipboard.ts +17 -14
  366. package/src/components/editor/navigation/focus-utils.ts +23 -4
  367. package/src/components/editor/navigation/multi-cell-action-toolbar.tsx +17 -33
  368. package/src/components/editor/navigation/navigation.ts +74 -72
  369. package/src/components/editor/navigation/selection.ts +30 -29
  370. package/src/components/editor/notebook-banner.tsx +1 -0
  371. package/src/components/editor/notebook-cell.tsx +126 -152
  372. package/src/components/editor/output/MarimoErrorOutput.tsx +2 -1
  373. package/src/components/editor/output/MarimoTracebackOutput.tsx +19 -17
  374. package/src/components/editor/output/Outputs.css +8 -0
  375. package/src/components/editor/output/VideoOutput.tsx +6 -0
  376. package/src/components/editor/output/__tests__/VideoOutput.test.tsx +131 -0
  377. package/src/components/editor/output/__tests__/traceback.test.tsx +27 -1
  378. package/src/components/editor/output/ansi-reduce.ts +33 -20
  379. package/src/components/editor/output/console/ConsoleOutput.tsx +19 -25
  380. package/src/components/editor/output/console/__tests__/ConsoleOutput.test.tsx +125 -69
  381. package/src/components/editor/package-alert.tsx +14 -7
  382. package/src/components/editor/renderers/__tests__/add-cell-buttons.test.tsx +18 -0
  383. package/src/components/editor/renderers/cell-array.tsx +32 -100
  384. package/src/components/editor/renderers/grid-layout/__tests__/grid-layout.test.tsx +75 -0
  385. package/src/components/editor/renderers/grid-layout/grid-layout.tsx +28 -22
  386. package/src/components/editor/renderers/slides-layout/__tests__/plugin.test.ts +0 -4
  387. package/src/components/editor/renderers/slides-layout/slides-layout.tsx +1 -1
  388. package/src/components/editor/renderers/vertical-layout/__tests__/useFocusFirstEditor.test.ts +4 -4
  389. package/src/components/editor/renderers/vertical-layout/sidebar/toggle.tsx +7 -1
  390. package/src/components/editor/renderers/vertical-layout/useFocusFirstEditor.ts +1 -1
  391. package/src/components/editor/renderers/vertical-layout/vertical-layout.tsx +19 -37
  392. package/src/components/editor/stdin-blocking-alert.tsx +4 -2
  393. package/src/components/home/components.tsx +17 -31
  394. package/src/components/icons/__tests__/large-spinner.test.tsx +39 -0
  395. package/src/components/icons/large-spinner.tsx +3 -14
  396. package/src/components/icons/spinner.tsx +1 -1
  397. package/src/components/markdown/markdown-renderer.tsx +39 -28
  398. package/src/components/mcp/mcp-status-indicator.tsx +18 -14
  399. package/src/components/pages/__tests__/home-page.test.tsx +116 -0
  400. package/src/components/pages/edit-page.tsx +19 -17
  401. package/src/components/pages/home-page.tsx +164 -91
  402. package/src/components/scratchpad/scratchpad.test.tsx +89 -0
  403. package/src/components/scratchpad/scratchpad.tsx +47 -33
  404. package/src/components/scratchpad/state.ts +7 -0
  405. package/src/components/slides/__tests__/minimap-actions.test.tsx +22 -29
  406. package/src/components/slides/__tests__/minimap.test.ts +38 -19
  407. package/src/components/slides/__tests__/slide-scroll-hint.test.tsx +37 -0
  408. package/src/components/slides/minimap.tsx +22 -14
  409. package/src/components/slides/reveal-component.tsx +73 -36
  410. package/src/components/slides/reveal-slides.css +5 -4
  411. package/src/components/slides/slide-cell-view.tsx +37 -34
  412. package/src/components/slides/slide-form.tsx +1 -0
  413. package/src/components/slides/slide-scroll-hint.tsx +3 -1
  414. package/src/components/slides/slide.tsx +3 -4
  415. package/src/components/sort/SortableCellsProvider.tsx +8 -25
  416. package/src/components/tracing/tracing-keyboard.test.tsx +85 -0
  417. package/src/components/tracing/tracing.tsx +46 -42
  418. package/src/components/ui/__tests__/draggable-popover.test.tsx +24 -0
  419. package/src/components/ui/__tests__/fullscreen.test.tsx +44 -2
  420. package/src/components/ui/__tests__/range-slider.test.tsx +165 -0
  421. package/src/components/ui/alert-dialog.tsx +1 -1
  422. package/src/components/ui/draggable-popover.tsx +24 -2
  423. package/src/components/ui/fullscreen.tsx +25 -1
  424. package/src/components/ui/range-slider.tsx +22 -9
  425. package/src/components/ui/toast.tsx +1 -1
  426. package/src/core/MarimoApp.tsx +3 -1
  427. package/src/core/ai/__tests__/staged-cells.test.ts +89 -608
  428. package/src/core/ai/context/context.ts +2 -0
  429. package/src/core/ai/context/providers/__tests__/cell-output.test.ts +8 -12
  430. package/src/core/ai/context/providers/__tests__/cell.test.ts +49 -0
  431. package/src/core/ai/context/providers/cell-output.ts +2 -2
  432. package/src/core/ai/context/providers/cell.ts +54 -0
  433. package/src/core/ai/context/providers/datasource.ts +6 -2
  434. package/src/core/ai/staged-cells.ts +56 -323
  435. package/src/core/ai/state.ts +3 -0
  436. package/src/core/ai/tools/__tests__/edit-notebook-tool.test.ts +40 -88
  437. package/src/core/ai/tools/__tests__/registry.test.ts +17 -0
  438. package/src/core/ai/tools/base.ts +18 -15
  439. package/src/core/ai/tools/edit-notebook-tool.ts +86 -80
  440. package/src/core/ai/tools/registry.ts +13 -10
  441. package/src/core/ai/tools/sample-tool.ts +6 -7
  442. package/src/core/cells/__tests__/__snapshots__/cells.test.ts.snap +4 -527
  443. package/src/core/cells/__tests__/actions.test.ts +623 -35
  444. package/src/core/cells/__tests__/add-missing-import.test.ts +7 -8
  445. package/src/core/cells/__tests__/arrange.test.ts +432 -0
  446. package/src/core/cells/__tests__/cell.test.ts +148 -150
  447. package/src/core/cells/__tests__/cells.test.ts +390 -2925
  448. package/src/core/cells/__tests__/collapseConsoleOutputs.test.ts +54 -0
  449. package/src/core/cells/__tests__/document.test.ts +158 -0
  450. package/src/core/cells/__tests__/editor.test.ts +57 -0
  451. package/src/core/cells/__tests__/flush-document.test.ts +40 -0
  452. package/src/core/cells/__tests__/harness.ts +106 -0
  453. package/src/core/cells/__tests__/layout.test.ts +176 -0
  454. package/src/core/cells/__tests__/logs.test.ts +0 -13
  455. package/src/core/cells/__tests__/notebook-outline.test.ts +122 -0
  456. package/src/core/cells/__tests__/outputs.test.tsx +71 -53
  457. package/src/core/cells/__tests__/pending-delete-service.test.tsx +11 -20
  458. package/src/core/cells/__tests__/session.test.ts +445 -211
  459. package/src/core/cells/__tests__/utils.test.ts +135 -337
  460. package/src/core/cells/actions.ts +677 -6
  461. package/src/core/cells/add-missing-import.ts +47 -43
  462. package/src/core/cells/arrange.ts +529 -0
  463. package/src/core/cells/cell.ts +78 -146
  464. package/src/core/cells/cells.ts +116 -1457
  465. package/src/core/cells/columns.ts +38 -0
  466. package/src/core/cells/document.ts +167 -0
  467. package/src/core/cells/edit.ts +30 -0
  468. package/src/core/cells/editor.ts +82 -0
  469. package/src/core/cells/focus.ts +27 -6
  470. package/src/core/cells/layout.ts +221 -0
  471. package/src/core/cells/outputs.ts +12 -28
  472. package/src/core/cells/pending-delete-service.ts +8 -14
  473. package/src/core/cells/scrollCellIntoView.ts +6 -0
  474. package/src/core/cells/session.ts +76 -53
  475. package/src/core/cells/types.ts +21 -51
  476. package/src/core/cells/utils.ts +85 -87
  477. package/src/core/codemirror/__tests__/format.test.ts +0 -34
  478. package/src/core/codemirror/__tests__/setup.test.ts +61 -29
  479. package/src/core/codemirror/ai/__tests__/resources.test.ts +117 -0
  480. package/src/core/codemirror/ai/resources.ts +1 -1
  481. package/src/core/codemirror/cells/__tests__/extensions.test.ts +2 -6
  482. package/src/core/codemirror/cells/extensions.ts +18 -30
  483. package/src/core/codemirror/cells/state.ts +2 -6
  484. package/src/core/codemirror/cm.ts +5 -1
  485. package/src/core/codemirror/config/types.ts +1 -1
  486. package/src/core/codemirror/copilot/__tests__/getCodes.test.ts +6 -7
  487. package/src/core/codemirror/copilot/getCodes.ts +2 -2
  488. package/src/core/codemirror/format.ts +6 -23
  489. package/src/core/codemirror/keymaps/vim.ts +4 -8
  490. package/src/core/codemirror/language/__tests__/sql.test.ts +22 -20
  491. package/src/core/codemirror/language/__tests__/utils.test.ts +187 -15
  492. package/src/core/codemirror/language/cell-code.ts +114 -0
  493. package/src/core/codemirror/language/extension.ts +52 -35
  494. package/src/core/codemirror/language/languages/markdown.ts +8 -6
  495. package/src/core/codemirror/language/languages/python.ts +19 -13
  496. package/src/core/codemirror/language/languages/sql/sql.ts +16 -24
  497. package/src/core/codemirror/language/panel/panel.tsx +1 -0
  498. package/src/core/codemirror/language/types.ts +7 -7
  499. package/src/core/codemirror/language/utils.ts +9 -39
  500. package/src/core/codemirror/lsp/__tests__/notebook-lsp.test.ts +1 -2
  501. package/src/core/codemirror/lsp/notebook-lsp.ts +6 -5
  502. package/src/core/codemirror/lsp/utils.ts +1 -1
  503. package/src/core/codemirror/misc/__tests__/paste.test.ts +3 -1
  504. package/src/core/codemirror/misc/paste.ts +1 -1
  505. package/src/core/codemirror/placeholder/__tests__/extensions.test.ts +75 -0
  506. package/src/core/codemirror/placeholder/extensions.ts +80 -19
  507. package/src/core/codemirror/readonly/__tests__/extension.test.ts +1 -1
  508. package/src/core/codemirror/readonly/extension.ts +2 -2
  509. package/src/core/codemirror/utils.ts +1 -0
  510. package/src/core/config/__tests__/app-config.test.ts +64 -0
  511. package/src/core/config/__tests__/config-schema.test.ts +56 -6
  512. package/src/core/config/config-schema.ts +17 -4
  513. package/src/core/config/config.ts +65 -20
  514. package/src/core/config/feature-flag.tsx +0 -2
  515. package/src/core/datasets/__tests__/data-source-discovery.test.ts +5 -5
  516. package/src/core/datasets/data-source-discovery.ts +4 -6
  517. package/src/core/documentation/doc-lookup.ts +1 -1
  518. package/src/core/edit-app.tsx +22 -28
  519. package/src/core/errors/__tests__/error-entries.test.ts +40 -1
  520. package/src/core/errors/error-entries.ts +6 -4
  521. package/src/core/executions/__tests__/atoms.test.ts +98 -0
  522. package/src/core/executions/__tests__/freshness.test.ts +482 -0
  523. package/src/core/executions/__tests__/hooks.test.tsx +106 -0
  524. package/src/core/executions/__tests__/select.test.ts +268 -0
  525. package/src/core/executions/atoms.ts +228 -0
  526. package/src/core/executions/freshness.ts +171 -0
  527. package/src/core/executions/hooks.ts +47 -0
  528. package/src/core/executions/index.ts +33 -0
  529. package/src/core/executions/select.ts +175 -0
  530. package/src/core/export/__tests__/hooks.test.ts +0 -5
  531. package/src/core/export/hooks.ts +1 -1
  532. package/src/core/export/layout.ts +2 -2
  533. package/src/core/hotkeys/actions.ts +2 -4
  534. package/src/core/hotkeys/hotkeys.ts +2 -1
  535. package/src/core/islands/__tests__/bootstrap.test.ts +69 -17
  536. package/src/core/islands/__tests__/bridge.test.ts +85 -27
  537. package/src/core/islands/bootstrap.ts +49 -54
  538. package/src/core/islands/bridge.ts +84 -25
  539. package/src/core/islands/components/__tests__/IslandControls.test.tsx +7 -5
  540. package/src/core/islands/components/__tests__/web-components.test.tsx +63 -0
  541. package/src/core/islands/components/output-wrapper.tsx +5 -5
  542. package/src/core/islands/components/web-components.tsx +12 -1
  543. package/src/core/islands/worker/__tests__/controller.test.ts +62 -4
  544. package/src/core/islands/worker/controller.ts +4 -10
  545. package/src/core/islands/worker/worker.tsx +33 -33
  546. package/src/core/kernel/__tests__/RuntimeState.test.ts +1 -1
  547. package/src/core/kernel/__tests__/handlers.test.ts +7 -157
  548. package/src/core/kernel/handlers.ts +13 -79
  549. package/src/core/kernel/state.ts +0 -15
  550. package/src/core/lifecycle/render-policy.ts +12 -26
  551. package/src/core/meta/__tests__/code-visibility.test.tsx +78 -70
  552. package/src/core/meta/code-visibility.ts +18 -9
  553. package/src/core/network/__tests__/connection.test.ts +1 -1
  554. package/src/core/network/__tests__/requests-lazy.test.ts +6 -8
  555. package/src/core/network/connection-notice.ts +1 -1
  556. package/src/core/network/connection.ts +1 -1
  557. package/src/core/network/requests-lazy.ts +5 -8
  558. package/src/core/network/requests-network.ts +5 -31
  559. package/src/core/network/requests-static.ts +1 -4
  560. package/src/core/network/requests-toasting.tsx +1 -4
  561. package/src/core/network/types.ts +6 -14
  562. package/src/core/network/useConnectionNotice.ts +8 -2
  563. package/src/core/notebook/__tests__/operations.test.ts +51 -0
  564. package/src/core/notebook/attachments.ts +38 -0
  565. package/src/core/notebook/document/__tests__/codemirror.test.ts +759 -0
  566. package/src/core/notebook/document/__tests__/draft.test.ts +363 -0
  567. package/src/core/notebook/document/__tests__/fixtures.ts +92 -0
  568. package/src/core/notebook/document/__tests__/hooks.test.tsx +391 -0
  569. package/src/core/notebook/document/__tests__/lifecycle-scenarios.test.ts +61 -0
  570. package/src/core/notebook/document/__tests__/model.test.ts +247 -0
  571. package/src/core/notebook/document/__tests__/protocol-fixtures.ts +38 -0
  572. package/src/core/notebook/document/__tests__/recovery-scenarios.test.ts +230 -0
  573. package/src/core/notebook/document/__tests__/scenario-fixture.ts +43 -0
  574. package/src/core/notebook/document/__tests__/scenarios.test.ts +205 -0
  575. package/src/core/notebook/document/__tests__/state.test.ts +459 -0
  576. package/src/core/notebook/document/__tests__/submission.test.ts +203 -0
  577. package/src/core/notebook/document/__tests__/test-host.test.ts +92 -0
  578. package/src/core/notebook/document/__tests__/test-host.ts +247 -0
  579. package/src/core/notebook/document/__tests__/test-notebook.ts +149 -0
  580. package/src/core/notebook/document/__tests__/user.ts +61 -0
  581. package/src/core/notebook/document/codemirror.ts +216 -0
  582. package/src/core/notebook/document/draft.ts +502 -0
  583. package/src/core/notebook/document/hooks.tsx +118 -0
  584. package/src/core/notebook/document/index.ts +24 -0
  585. package/src/core/notebook/document/model.ts +102 -0
  586. package/src/core/notebook/document/select.ts +41 -0
  587. package/src/core/notebook/document/state.ts +378 -0
  588. package/src/core/notebook/document/sync.ts +369 -0
  589. package/src/core/notebook/index.ts +19 -0
  590. package/src/core/notebook/operations.ts +30 -0
  591. package/src/core/notebook/replica/AGENTS.md +11 -0
  592. package/src/core/{host → notebook/replica}/__tests__/attachments.test.ts +9 -10
  593. package/src/core/{host → notebook/replica}/__tests__/document.test.ts +18 -16
  594. package/src/core/notebook/replica/__tests__/executions.test.ts +200 -0
  595. package/src/core/notebook/replica/__tests__/fixtures.ts +79 -0
  596. package/src/core/notebook/replica/__tests__/replica.test.ts +559 -0
  597. package/src/core/notebook/replica/__tests__/results.test.ts +193 -0
  598. package/src/core/notebook/replica/__tests__/runtime.test.ts +78 -0
  599. package/src/core/notebook/replica/backend.ts +19 -0
  600. package/src/core/notebook/replica/connection.ts +42 -0
  601. package/src/core/notebook/replica/index.ts +20 -0
  602. package/src/core/notebook/replica/replica.ts +336 -0
  603. package/src/core/{host → notebook/replica}/resources/attachments.ts +6 -3
  604. package/src/core/{host → notebook/replica}/resources/document.ts +3 -3
  605. package/src/core/notebook/replica/resources/executions.ts +157 -0
  606. package/src/core/notebook/replica/resources/results.ts +48 -0
  607. package/src/core/notebook/replica/resources/runtime.ts +14 -0
  608. package/src/core/packages/__tests__/useSandboxController.test.tsx +1 -1
  609. package/src/core/packages/useSandboxController.ts +1 -1
  610. package/src/core/run-app.tsx +49 -51
  611. package/src/core/runtime/__tests__/adapter.test.ts +4 -4
  612. package/src/core/runtime/__tests__/createWsUrl.test.ts +77 -7
  613. package/src/core/runtime/__tests__/runtime.test.ts +32 -74
  614. package/src/core/runtime/adapter.ts +5 -5
  615. package/src/core/runtime/config.ts +2 -2
  616. package/src/core/runtime/runtime.ts +33 -46
  617. package/src/core/runtime/types.ts +0 -2
  618. package/src/core/saving/__tests__/document.test.tsx +123 -0
  619. package/src/core/saving/__tests__/state.test.ts +111 -0
  620. package/src/core/saving/__tests__/useAutoSave.test.tsx +67 -0
  621. package/src/core/saving/document.ts +33 -0
  622. package/src/core/saving/filename.ts +1 -1
  623. package/src/core/saving/save-component.tsx +39 -60
  624. package/src/core/saving/state.ts +38 -39
  625. package/src/core/saving/useAutoSave.ts +17 -53
  626. package/src/core/session/__tests__/backend.test.ts +236 -0
  627. package/src/core/session/__tests__/useNotebookReplica.hook.test.tsx +186 -0
  628. package/src/core/{websocket → session}/__tests__/useNotebookSession.hook.test.tsx +245 -262
  629. package/src/core/session/active-notebook.ts +28 -0
  630. package/src/core/session/backend.ts +123 -0
  631. package/src/core/session/embedded.ts +7 -0
  632. package/src/core/{websocket → session}/types.ts +2 -2
  633. package/src/core/session/useNotebookReplica.ts +74 -0
  634. package/src/core/{websocket → session}/useNotebookSession.tsx +80 -67
  635. package/src/core/state/__tests__/jotai.test.tsx +108 -0
  636. package/src/core/state/jotai.ts +1 -1
  637. package/src/core/static/__tests__/files.test.ts +38 -10
  638. package/src/core/static/files.ts +2 -0
  639. package/src/core/{websocket → transports}/__tests__/connection-state.test.ts +1 -13
  640. package/src/core/transports/__tests__/server.test.ts +408 -0
  641. package/src/core/transports/__tests__/static.test.ts +306 -0
  642. package/src/core/transports/__tests__/wasm.test.ts +166 -0
  643. package/src/core/{websocket → transports}/connection-state.ts +9 -16
  644. package/src/core/transports/server.ts +152 -0
  645. package/src/core/transports/static.ts +166 -0
  646. package/src/core/transports/wasm.ts +97 -0
  647. package/src/core/vscode/__tests__/vscode-bindings.test.ts +125 -0
  648. package/src/core/vscode/vscode-bindings.ts +14 -2
  649. package/src/core/wasm/__tests__/bridge.test.ts +210 -64
  650. package/src/core/wasm/__tests__/worker.test.ts +188 -0
  651. package/src/core/wasm/bridge.ts +120 -73
  652. package/src/core/wasm/rpc.ts +15 -3
  653. package/src/core/wasm/store.ts +3 -3
  654. package/src/core/wasm/worker/bootstrap.ts +55 -51
  655. package/src/core/wasm/worker/getMarimoWheel.ts +1 -1
  656. package/src/core/wasm/worker/save-worker.ts +9 -10
  657. package/src/core/wasm/worker/types.ts +30 -18
  658. package/src/core/wasm/worker/worker.ts +118 -72
  659. package/src/css/app/Cell.css +7 -36
  660. package/src/css/app/codemirror.css +1 -1
  661. package/src/css/common.css +1 -1
  662. package/src/css/globals.css +72 -24
  663. package/src/hooks/__tests__/useAsyncData.test.tsx +148 -0
  664. package/src/hooks/__tests__/useDebounce.test.tsx +51 -0
  665. package/src/hooks/__tests__/useDeepCompareMemoize.test.tsx +39 -0
  666. package/src/hooks/__tests__/useDelayElapsed.test.tsx +28 -0
  667. package/src/hooks/__tests__/useInternalStateWithSync.test.tsx +20 -0
  668. package/src/hooks/__tests__/useScript.test.tsx +77 -0
  669. package/src/hooks/__tests__/useStateForKey.test.tsx +257 -0
  670. package/src/hooks/useAsyncData.ts +3 -3
  671. package/src/hooks/useDataSourceDiscovery.ts +6 -4
  672. package/src/hooks/useDebounce.ts +6 -10
  673. package/src/hooks/useDeepCompareMemoize.ts +1 -1
  674. package/src/hooks/useDelayElapsed.ts +14 -10
  675. package/src/hooks/useElapsedTime.ts +3 -3
  676. package/src/hooks/useEventListener.ts +1 -2
  677. package/src/hooks/useInputHistory.ts +4 -7
  678. package/src/hooks/useInternalStateWithSync.ts +6 -6
  679. package/src/hooks/useResizeObserver.ts +4 -7
  680. package/src/hooks/useScript.ts +67 -70
  681. package/src/hooks/useStateForKey.ts +93 -0
  682. package/src/mount.tsx +20 -15
  683. package/src/plugins/__tests__/plugin-object-schemas.test.ts +104 -0
  684. package/src/plugins/core/RenderHTML.tsx +3 -5
  685. package/src/plugins/core/__test__/RenderHTML-copy.test.tsx +60 -0
  686. package/src/plugins/core/registerReactComponent.tsx +5 -14
  687. package/src/plugins/impl/CodeEditorPlugin.tsx +1 -1
  688. package/src/plugins/impl/DataEditorPlugin.tsx +34 -13
  689. package/src/plugins/impl/DataTablePlugin.tsx +69 -37
  690. package/src/plugins/impl/DropdownPlugin.tsx +2 -6
  691. package/src/plugins/impl/FileBrowserPlugin.tsx +4 -16
  692. package/src/plugins/impl/FormPlugin.tsx +1 -1
  693. package/src/plugins/impl/RangeSliderPlugin.tsx +16 -2
  694. package/src/plugins/impl/RefreshPlugin.tsx +1 -0
  695. package/src/plugins/impl/SliderPlugin.tsx +6 -8
  696. package/src/plugins/impl/__tests__/DataEditorPlugin.test.ts +93 -4
  697. package/src/plugins/impl/__tests__/DataTablePlugin.test.tsx +387 -1
  698. package/src/plugins/impl/__tests__/FileBrowserPlugin.test.tsx +45 -0
  699. package/src/plugins/impl/__tests__/RangeSliderPlugin.test.tsx +109 -0
  700. package/src/plugins/impl/__tests__/SliderPlugin.test.tsx +24 -3
  701. package/src/plugins/impl/anywidget/__tests__/registry.test.ts +153 -0
  702. package/src/plugins/impl/anywidget/__tests__/widget-binding.test.ts +241 -2
  703. package/src/plugins/impl/anywidget/model.ts +3 -1
  704. package/src/plugins/impl/anywidget/registry.ts +18 -14
  705. package/src/plugins/impl/anywidget/runtime.ts +21 -9
  706. package/src/plugins/impl/anywidget/widget-binding.ts +160 -82
  707. package/src/plugins/impl/chat/__tests__/chat-prompts.test.tsx +93 -0
  708. package/src/plugins/impl/chat/chat-ui.tsx +17 -15
  709. package/src/plugins/impl/code/any-language-editor.tsx +2 -2
  710. package/src/plugins/impl/common/error-banner.tsx +5 -3
  711. package/src/plugins/impl/data-editor/__tests__/column-types.test.ts +42 -0
  712. package/src/plugins/impl/data-editor/__tests__/editor-state.test.ts +52 -1
  713. package/src/plugins/impl/data-editor/__tests__/glide-data-editor.test.tsx +120 -4
  714. package/src/plugins/impl/data-editor/__tests__/glide-utils.test.ts +116 -0
  715. package/src/plugins/impl/data-editor/column-types.ts +55 -0
  716. package/src/plugins/impl/data-editor/editor-state.ts +18 -2
  717. package/src/plugins/impl/data-editor/glide-data-editor.tsx +74 -12
  718. package/src/plugins/impl/data-editor/glide-utils.ts +39 -38
  719. package/src/plugins/impl/data-editor/types.ts +5 -0
  720. package/src/plugins/impl/data-explorer/ConnectedDataExplorerComponent.tsx +1 -1
  721. package/src/plugins/impl/data-explorer/components/column-summary.tsx +4 -2
  722. package/src/plugins/impl/data-explorer/state/reducer.ts +1 -1
  723. package/src/plugins/impl/data-frames/DataFramePlugin.tsx +1 -2
  724. package/src/plugins/impl/data-frames/__tests__/sidebar.test.tsx +160 -0
  725. package/src/plugins/impl/data-frames/forms/__tests__/__snapshots__/form.test.tsx.snap +66 -66
  726. package/src/plugins/impl/data-frames/panel.tsx +44 -16
  727. package/src/plugins/impl/mpl-interactive/MplInteractivePlugin.tsx +5 -3
  728. package/src/plugins/impl/panel/PanelPlugin.tsx +16 -17
  729. package/src/plugins/impl/panel/__tests__/utils.test.ts +39 -1
  730. package/src/plugins/impl/panel/utils.ts +17 -0
  731. package/src/plugins/impl/plotly/PlotlyPlugin.tsx +2 -5
  732. package/src/plugins/impl/plotly/selection.ts +25 -19
  733. package/src/plugins/impl/vega/VegaPlugin.tsx +2 -3
  734. package/src/plugins/impl/vega/make-selectable.ts +4 -7
  735. package/src/plugins/layout/DownloadPlugin.tsx +7 -11
  736. package/src/plugins/layout/RoutesPlugin.tsx +1 -1
  737. package/src/plugins/layout/__test__/DownloadPlugin.test.tsx +205 -0
  738. package/src/stories/__tests__/editor-story.test.tsx +33 -0
  739. package/src/stories/button.stories.tsx +1 -0
  740. package/src/stories/cell-status.stories.tsx +29 -24
  741. package/src/stories/cell.stories.tsx +46 -46
  742. package/src/stories/data-table.stories.tsx +31 -0
  743. package/src/stories/editor.stories.tsx +24 -17
  744. package/src/stories/form-wrapper.stories.tsx +2 -2
  745. package/src/stories/layout/vertical/one-column.stories.tsx +28 -42
  746. package/src/stories/runtime-story.tsx +23 -17
  747. package/src/stories/select.stories.tsx +2 -2
  748. package/src/stories/switchable-multi-select.stories.tsx +1 -1
  749. package/src/theme/__tests__/islands-theme.test.tsx +276 -0
  750. package/src/theme/namespace.tsx +4 -3
  751. package/src/theme/useTheme.ts +71 -41
  752. package/src/utils/__tests__/arrays.test.ts +35 -0
  753. package/src/utils/__tests__/batch-requests.test.ts +3 -3
  754. package/src/utils/__tests__/{createReducer.test.ts → createReducer.test.tsx} +127 -1
  755. package/src/utils/__tests__/download.test.tsx +183 -23
  756. package/src/utils/__tests__/numbers.test.ts +105 -1
  757. package/src/utils/__tests__/objects.test.ts +21 -0
  758. package/src/utils/arrays.ts +11 -2
  759. package/src/utils/blob.ts +1 -1
  760. package/src/utils/createReducer.ts +115 -79
  761. package/src/utils/download.ts +67 -6
  762. package/src/utils/maps.ts +0 -3
  763. package/src/utils/numbers.ts +79 -18
  764. package/src/utils/objects.ts +4 -9
  765. package/src/utils/time.ts +10 -0
  766. package/src/utils/tracer.ts +9 -5
  767. package/src/utils/zod-utils.ts +1 -3
  768. package/dist/_baseMerge-BiGRwuqv.js +0 -165
  769. package/dist/any-language-editor-D4q-IFcM.js +0 -76
  770. package/dist/assets/__vite-browser-external-BXYkiFsk.js +0 -1
  771. package/dist/assets/worker-HPY9fbhz.js +0 -114
  772. package/dist/feedback-button-CykZqHY-.js +0 -379
  773. package/dist/hasIn-o2Us0uVx.js +0 -132
  774. package/dist/html-to-image--r0l9wUy.js +0 -3251
  775. package/dist/isArrayLikeObject-BZl-15ir.js +0 -450
  776. package/dist/isEmpty-BSZ1LaUo.js +0 -35
  777. package/dist/isSymbol-kQcfYbNX.js +0 -8
  778. package/dist/label-DoysmLMW.js +0 -281
  779. package/dist/pick-CJeoxYOS.js +0 -51
  780. package/dist/select-DemoKT4G.js +0 -1344
  781. package/dist/toDate-gyi35XS2.js +0 -1185
  782. package/dist/toast-PkdZraM8.js +0 -1830
  783. package/dist/use-restore-focus-CKjfFjLM.js +0 -6369
  784. package/dist/useLifecycle-Dfq8UD-b.js +0 -169
  785. package/dist/useTheme-Bu5bBgrh.js +0 -904
  786. package/src/components/chat/reasoning-accordion.tsx +0 -61
  787. package/src/components/chat/tool-call/tool-error-card.tsx +0 -81
  788. package/src/components/chat/tool-call/tool-history-row.tsx +0 -174
  789. package/src/components/editor/ai/__tests__/staged-cell-submission.test.ts +0 -106
  790. package/src/components/editor/ai/add-cell-with-ai.tsx +0 -506
  791. package/src/components/editor/ai/staged-cell-submission.ts +0 -46
  792. package/src/components/editor/cell/__tests__/StagedAICell.test.tsx +0 -64
  793. package/src/components/editor/cell/code/__tests__/rtc-editor-config.test.ts +0 -50
  794. package/src/components/editor/chrome/wrapper/footer-items/rtc-status.tsx +0 -65
  795. package/src/components/editor/navigation/__tests__/state.test.ts +0 -81
  796. package/src/components/editor/navigation/state.ts +0 -65
  797. package/src/components/icons/loading-ellipsis.tsx +0 -46
  798. package/src/core/ai/tools/__tests__/run-cells-tool.test.ts +0 -656
  799. package/src/core/ai/tools/run-cells-tool.ts +0 -303
  800. package/src/core/attachments/state.ts +0 -18
  801. package/src/core/cells/__tests__/apply-transaction.test.ts +0 -991
  802. package/src/core/cells/__tests__/document-changes.test.ts +0 -1140
  803. package/src/core/cells/__tests__/document-roundtrip.test.ts +0 -392
  804. package/src/core/cells/document-changes.ts +0 -944
  805. package/src/core/codemirror/rtc/extension.ts +0 -453
  806. package/src/core/codemirror/rtc/loro/__tests__/sync.test.ts +0 -52
  807. package/src/core/codemirror/rtc/loro/awareness.ts +0 -531
  808. package/src/core/codemirror/rtc/loro/colors.ts +0 -38
  809. package/src/core/codemirror/rtc/loro/sync.ts +0 -168
  810. package/src/core/host/AGENTS.md +0 -11
  811. package/src/core/host/__tests__/events.test.ts +0 -46
  812. package/src/core/host/__tests__/fixtures.ts +0 -39
  813. package/src/core/host/__tests__/notebook-client.test.ts +0 -433
  814. package/src/core/host/__tests__/protocol.test.ts +0 -229
  815. package/src/core/host/__tests__/stream.test.ts +0 -209
  816. package/src/core/host/connection.ts +0 -81
  817. package/src/core/host/events.ts +0 -61
  818. package/src/core/host/notebook-client.ts +0 -290
  819. package/src/core/host/protocol.ts +0 -1948
  820. package/src/core/host/resources/resource.ts +0 -47
  821. package/src/core/host/stream.ts +0 -211
  822. package/src/core/rtc/state.ts +0 -34
  823. package/src/core/state/__tests__/jotai.test.ts +0 -25
  824. package/src/core/wasm/worker/message-buffer.ts +0 -33
  825. package/src/core/websocket/__tests__/createConnectionTransport.test.ts +0 -49
  826. package/src/core/websocket/__tests__/useNotebookClient.hook.test.tsx +0 -170
  827. package/src/core/websocket/state.ts +0 -7
  828. package/src/core/websocket/transports/__tests__/basic.test.ts +0 -275
  829. package/src/core/websocket/transports/__tests__/sse.test.ts +0 -335
  830. package/src/core/websocket/transports/__tests__/transport.test.ts +0 -308
  831. package/src/core/websocket/transports/__tests__/ws.test.ts +0 -125
  832. package/src/core/websocket/transports/basic.ts +0 -102
  833. package/src/core/websocket/transports/create.ts +0 -31
  834. package/src/core/websocket/transports/sse.ts +0 -308
  835. package/src/core/websocket/transports/transport.ts +0 -50
  836. package/src/core/websocket/transports/ws.ts +0 -98
  837. package/src/core/websocket/useNotebookClient.ts +0 -88
  838. package/src/utils/__tests__/id-tree.test.ts +0 -2145
  839. package/src/utils/id-tree.tsx +0 -1134
  840. /package/src/{core/attachments/toast.ts → components/editor/agent-toast.ts} +0 -0
  841. /package/src/core/{websocket → session}/connection-utils.ts +0 -0
@@ -13,28 +13,13 @@ import {
13
13
  import { useAtom, useAtomValue, useSetAtom, useStore } from "jotai";
14
14
  import {
15
15
  BotMessageSquareIcon,
16
- HatGlasses,
17
- ArrowRightIcon,
18
16
  Loader2,
19
- type LucideIcon,
20
- MessageCircleIcon,
21
- NotebookText,
22
17
  PlusIcon,
23
- SparklesIcon,
24
18
  SettingsIcon,
25
- CodeIcon,
26
19
  } from "lucide-react";
27
- import { memo, useEffect, useRef, useState } from "react";
20
+ import { memo, useEffect, useMemo, useRef, useState } from "react";
28
21
  import useEvent from "react-use-event-hook";
29
22
  import { Button } from "@/components/ui/button";
30
- import {
31
- Select,
32
- SelectContent,
33
- SelectGroup,
34
- SelectItem,
35
- SelectLabel,
36
- SelectTrigger,
37
- } from "@/components/ui/select";
38
23
  import { replaceMessagesInChat } from "@/core/ai/chat-utils";
39
24
  import { useAIConfigActions } from "@/core/ai/config";
40
25
  import { AI_SDK_UI_THROTTLE_MS } from "@/core/ai/constants";
@@ -49,37 +34,33 @@ import {
49
34
  pendingAiPromptAtom,
50
35
  } from "@/core/ai/state";
51
36
  import type { ToolNotebookContext } from "@/core/ai/tools/base";
52
- import {
53
- type CopilotMode,
54
- FRONTEND_TOOL_REGISTRY,
55
- } from "@/core/ai/tools/registry";
56
- import { useCellActions } from "@/core/cells/cells";
37
+ import { FRONTEND_TOOL_REGISTRY } from "@/core/ai/tools/registry";
38
+ import { useCellActions } from "@/core/cells/actions";
57
39
  import { aiAtom, aiModelConfiguredAtom } from "@/core/config/config";
58
40
  import { DEFAULT_AI_MODEL } from "@/core/config/config-schema";
59
41
  import { useRequestClient } from "@/core/network/requests";
60
42
  import { useRuntimeManager } from "@/core/runtime/config";
61
43
  import { isWasm } from "@/core/wasm/utils";
62
44
  import { ErrorBanner } from "@/plugins/impl/common/error-banner";
63
- import { cn } from "@/utils/cn";
64
45
  import { Logger } from "@/utils/Logger";
65
46
  import { AIModelDropdown } from "../ai/ai-model-dropdown";
66
47
  import { useOpenSettingsToTab } from "../app-config/state";
67
48
  import {
68
49
  PairWithAgentBanner,
69
- PairWithAgentButton,
50
+ usePairWithAgentModal,
70
51
  } from "../editor/actions/pair-with-agent";
71
- import { PairWithAgentModal } from "../editor/actions/pair-with-agent-modal";
72
- import { PromptInput } from "../editor/ai/add-cell-with-ai";
52
+ import { PromptInput } from "../editor/ai/prompt-input";
53
+ import { PendingAICells } from "../editor/chrome/wrapper/pending-ai-cells";
73
54
  import {
74
55
  addContextCompletion,
75
- CONTEXT_TRIGGER,
76
56
  isContextAttachment,
77
57
  resolveChatContext,
78
58
  } from "../editor/ai/completion-utils";
79
59
  import { StreamingChunkTransport } from "../editor/ai/transport/chat-transport";
60
+ import { PanelHeaderActions } from "../editor/chrome/panels/panel-header";
80
61
  import { PanelEmptyState } from "../editor/chrome/panels/empty-state";
81
62
  import { CopyClipboardIcon } from "../icons/copy-icon";
82
- import { useImperativeModal } from "../modal/ImperativeModal";
63
+ import "./chat-typography.css";
83
64
  import { MCPStatusIndicator } from "../mcp/mcp-status-indicator";
84
65
  import { Tooltip, TooltipProvider } from "../ui/tooltip";
85
66
  import {
@@ -94,9 +75,11 @@ import {
94
75
  getAbortReasonFromChunk,
95
76
  resolveChatAbortReason,
96
77
  } from "./chat-abort";
97
- import { renderUIMessage } from "./chat-display";
78
+ import { AgentActivity } from "./agent-activity";
79
+ import { getAnswerText, renderUIMessage } from "./chat-display";
98
80
  import { ChatHistoryPopover } from "./chat-history-popover";
99
81
  import { CapabilitiesPopover } from "./capabilities-popover";
82
+ import { NotebookAccessSelector } from "./notebook-access-selector";
100
83
  import {
101
84
  type ChatMessagePart,
102
85
  convertToFileUIPart,
@@ -104,7 +87,6 @@ import {
104
87
  handleToolCall,
105
88
  hasPendingToolCalls,
106
89
  hasUnresolvedToolCalls,
107
- isLastMessageReasoning,
108
90
  PROVIDERS_THAT_SUPPORT_ATTACHMENTS,
109
91
  type QueuedUserMessage,
110
92
  shouldFlushQueue,
@@ -115,9 +97,12 @@ import { getCodes } from "@/core/codemirror/copilot/getCodes";
115
97
  import { focusInputAndMoveToEnd } from "@/core/codemirror/utils";
116
98
  import ScrollToBottomButton from "./acp/scroll-to-bottom-button";
117
99
  import { useChatControllerId } from "./use-chat-controller-id";
100
+ import { isChatBusy, useChatGeneration } from "./use-chat-generation";
101
+ import { useAssistantTurn } from "./use-assistant-turn";
102
+ import { UserMessage } from "./user-message";
118
103
 
119
104
  // Default mode for the AI
120
- const DEFAULT_MODE = "manual";
105
+ const DEFAULT_MODE = "ask";
121
106
 
122
107
  const QueuedMessageDisplay = memo(
123
108
  ({ message }: { message: QueuedUserMessage }) => {
@@ -131,7 +116,7 @@ const QueuedMessageDisplay = memo(
131
116
 
132
117
  return (
133
118
  <div className="flex justify-end">
134
- <div className="w-[95%] bg-background border border-dashed p-2 rounded-sm opacity-70">
119
+ <div className="w-[95%] bg-background border border-dashed p-2 rounded-[10px] opacity-70">
135
120
  {fileParts.map((filePart, idx) => (
136
121
  <AttachmentRenderer attachment={filePart} key={idx} />
137
122
  ))}
@@ -164,35 +149,41 @@ const ChatHeader: React.FC<ChatHeaderProps> = ({
164
149
  const { handleClick } = useOpenSettingsToTab();
165
150
 
166
151
  return (
167
- <div className="flex border-b px-2 py-1 justify-between shrink-0 items-center">
168
- <Tooltip content="New chat">
169
- <Button variant="text" size="icon" onClick={onNewChat}>
170
- <PlusIcon className="h-4 w-4" />
171
- </Button>
172
- </Tooltip>
173
- <div className="flex items-center gap-2">
174
- <Tooltip content="Connect your agent">
175
- <PairWithAgentButton className="mr-1" label="Connect" />
176
- </Tooltip>
177
- <MCPStatusIndicator />
178
- <Tooltip content="AI Settings">
152
+ <PanelHeaderActions>
153
+ <div className="mo-ai-panel flex w-full shrink-0 items-center font-sans text-sm">
154
+ <div className="flex w-full items-center gap-1">
179
155
  <Button
180
- variant="text"
181
- size="xs"
182
- className="hover:bg-foreground/10 py-2"
183
- onClick={() => handleClick("ai")}
156
+ variant="ghost"
157
+ size="sm"
158
+ className="chat-control gap-1.5 font-normal"
159
+ onClick={onNewChat}
184
160
  >
185
- <SettingsIcon className="h-4 w-4" />
161
+ <PlusIcon className="size-4" aria-hidden={true} />
162
+ New chat
186
163
  </Button>
187
- </Tooltip>
188
- <ChatHistoryPopover
189
- activeChatId={activeChatId}
190
- setActiveChat={setActiveChat}
191
- onDeleteChats={onDeleteChats}
192
- isLoading={isLoading}
193
- />
164
+ <ChatHistoryPopover
165
+ activeChatId={activeChatId}
166
+ setActiveChat={setActiveChat}
167
+ onDeleteChats={onDeleteChats}
168
+ isLoading={isLoading}
169
+ />
170
+ <div className="ml-auto flex items-center gap-2">
171
+ <MCPStatusIndicator />
172
+ <Tooltip content="AI Settings">
173
+ <Button
174
+ className="chat-control"
175
+ aria-label="AI Settings"
176
+ variant="ghost"
177
+ size="icon"
178
+ onClick={() => handleClick("ai")}
179
+ >
180
+ <SettingsIcon className="size-4" aria-hidden={true} />
181
+ </Button>
182
+ </Tooltip>
183
+ </div>
184
+ </div>
194
185
  </div>
195
- </div>
186
+ </PanelHeaderActions>
196
187
  );
197
188
  };
198
189
 
@@ -200,9 +191,9 @@ interface ChatMessageProps {
200
191
  message: UIMessage;
201
192
  index: number;
202
193
  onEdit: (index: number, newValue: string) => void;
203
- isStreamingReasoning: boolean;
204
194
  isLast: boolean;
205
195
  isActive: boolean;
196
+ turnStartedAt: number | null;
206
197
  addToolApprovalResponse?: ChatAddToolApproveResponseFunction;
207
198
  }
208
199
 
@@ -211,78 +202,40 @@ const ChatMessageDisplay: React.FC<ChatMessageProps> = memo(
211
202
  message,
212
203
  index,
213
204
  onEdit,
214
- isStreamingReasoning,
215
205
  isLast,
216
206
  isActive,
207
+ turnStartedAt,
217
208
  addToolApprovalResponse,
218
209
  }) => {
219
- const renderUserMessage = (message: UIMessage) => {
220
- const textParts = message.parts?.filter(
221
- (p): p is TextUIPart => p.type === "text",
222
- );
223
- const content = textParts?.map((p) => p.text).join("\n");
224
- const fileParts = message.parts?.filter(
225
- (p): p is FileUIPart => p.type === "file",
226
- );
227
-
210
+ if (message.role === "user") {
228
211
  return (
229
- <div className="w-[95%] bg-background border p-1 rounded-sm">
230
- {fileParts?.map((filePart, idx) => (
231
- <AttachmentRenderer attachment={filePart} key={idx} />
232
- ))}
233
- <PromptInput
234
- key={message.id}
235
- value={content}
236
- placeholder="Type your message..."
237
- onChange={() => {
238
- // noop
239
- }}
240
- onSubmit={(_e, newValue) => {
241
- if (!newValue.trim()) {
242
- return;
243
- }
244
- onEdit(index, newValue);
245
- }}
246
- onClose={() => {
247
- // noop
248
- }}
212
+ <div className="group flex justify-end">
213
+ <UserMessage
214
+ message={message}
215
+ canEdit={!isActive}
216
+ onEdit={(newValue) => onEdit(index, newValue)}
249
217
  />
250
218
  </div>
251
219
  );
252
- };
253
-
254
- const renderOtherMessage = (message: UIMessage) => {
255
- const textParts = message.parts.filter(
256
- (p): p is TextUIPart => p.type === "text",
257
- );
258
- const content = textParts.map((p) => p.text).join("\n");
220
+ }
259
221
 
260
- return (
222
+ return (
223
+ <div className="group relative flex justify-start">
261
224
  <div className="w-[95%] wrap-break-word">
262
- <div className="absolute right-1 top-1 opacity-0 group-hover:opacity-100 transition-opacity">
263
- <CopyClipboardIcon className="h-3 w-3" value={content || ""} />
225
+ <div className="absolute right-1 top-1 opacity-0 group-hover:opacity-100 group-focus-within:opacity-100 transition-opacity">
226
+ <CopyClipboardIcon
227
+ className="h-3 w-3"
228
+ value={() => getAnswerText(message)}
229
+ />
264
230
  </div>
265
231
  {renderUIMessage({
266
232
  message,
267
- isStreamingReasoning,
268
233
  isLast,
269
234
  isActive,
235
+ turnStartedAt,
270
236
  addToolApprovalResponse,
271
237
  })}
272
238
  </div>
273
- );
274
- };
275
-
276
- return (
277
- <div
278
- className={cn(
279
- "flex group relative",
280
- message.role === "user" ? "justify-end" : "justify-start",
281
- )}
282
- >
283
- {message.role === "user"
284
- ? renderUserMessage(message)
285
- : renderOtherMessage(message)}
286
239
  </div>
287
240
  );
288
241
  },
@@ -316,92 +269,27 @@ const ChatInputFooter: React.FC<ChatInputFooterProps> = memo(
316
269
 
317
270
  const { saveModeChange } = useAIConfigActions();
318
271
 
319
- const modeOptions: {
320
- value: CopilotMode;
321
- label: string;
322
- subtitle: string;
323
- Icon: LucideIcon;
324
- }[] = [
325
- {
326
- value: "manual",
327
- label: "Manual",
328
- subtitle: "Pure chat, no tool usage",
329
- Icon: MessageCircleIcon,
330
- },
331
- {
332
- value: "ask",
333
- label: "Ask",
334
- subtitle: "AI with access to read-only tools like documentation search",
335
- Icon: NotebookText,
336
- },
337
- {
338
- value: "agent",
339
- label: "Agent",
340
- subtitle: "AI with access to read and write tools",
341
- Icon: HatGlasses,
342
- },
343
- {
344
- value: "code_mode",
345
- label: "Code Mode (beta)",
346
- subtitle:
347
- "AI with access to the notebook's kernel. Potentially destructive.",
348
- Icon: CodeIcon,
349
- },
350
- ];
351
-
352
272
  const isAttachmentSupported =
353
273
  PROVIDERS_THAT_SUPPORT_ATTACHMENTS.has(currentProvider);
354
274
 
355
- const currentModeOption = modeOptions.find((o) => o.value === currentMode);
356
- const CurrentModeIcon = currentModeOption?.Icon;
357
- const CurrentModeLabel = currentModeOption?.label;
358
-
359
275
  return (
360
276
  <TooltipProvider>
361
- <div className="px-3 py-2 border-t border-border/20 flex flex-wrap items-center gap-1">
362
- <div className="flex flex-wrap items-center gap-1">
363
- <Select value={currentMode} onValueChange={saveModeChange}>
364
- <SelectTrigger className="h-6 text-xs border-border shadow-none! ring-0! bg-muted hover:bg-muted/30 py-0 px-2 gap-1.5 shrink-0">
365
- {CurrentModeIcon && <CurrentModeIcon className="h-3 w-3" />}
366
- <span className="text-nowrap">{CurrentModeLabel}</span>
367
- </SelectTrigger>
368
- <SelectContent>
369
- <SelectGroup>
370
- <SelectLabel className="text-xs uppercase tracking-wider text-muted-foreground/70 font-medium">
371
- AI Mode
372
- </SelectLabel>
373
- {modeOptions.map((option) => (
374
- <SelectItem
375
- key={option.value}
376
- value={option.value}
377
- className="text-xs py-1"
378
- >
379
- <div className="flex items-start gap-2.5">
380
- <span className="mt-1 text-muted-foreground">
381
- <option.Icon className="h-3 w-3" />
382
- </span>
383
- <div className="flex flex-col gap-0.5">
384
- <span className="font-semibold">{option.label}</span>
385
- <span className="text-muted-foreground">
386
- {option.subtitle}
387
- </span>
388
- </div>
389
- </div>
390
- </SelectItem>
391
- ))}
392
- </SelectGroup>
393
- </SelectContent>
394
- </Select>
277
+ <div className="chat-input-footer px-3 py-2 border-t border-border/20 flex items-center gap-2">
278
+ <div className="chat-input-selectors flex min-w-0 flex-1 items-center gap-1">
279
+ <NotebookAccessSelector
280
+ value={currentMode}
281
+ onValueChange={saveModeChange}
282
+ />
395
283
  <AIModelDropdown
396
284
  placeholder="Model"
397
- triggerClassName="h-6 text-xs shadow-none! ring-0! bg-muted hover:bg-muted/30 rounded-sm max-w-[200px]"
285
+ triggerClassName="chat-control chat-selector h-6 text-xs rounded-sm min-w-0 max-w-[200px] flex-1"
398
286
  iconSize="small"
399
287
  showAddCustomModelDocs={true}
400
288
  forRole="chat"
401
289
  />
402
- <CapabilitiesPopover />
403
290
  </div>
404
- <div className="flex flex-row ml-auto">
291
+ <div className="chat-input-actions flex shrink-0 items-center gap-0.5 ml-auto">
292
+ <CapabilitiesPopover />
405
293
  <AddContextButton
406
294
  handleAddContext={onAddContext}
407
295
  isLoading={isLoading}
@@ -429,9 +317,7 @@ const ChatInputFooter: React.FC<ChatInputFooterProps> = memo(
429
317
  ChatInputFooter.displayName = "ChatInputFooter";
430
318
 
431
319
  interface ChatInputProps {
432
- placeholder?: string;
433
320
  input: string;
434
- inputClassName?: string;
435
321
  setInput: (value: string) => void;
436
322
  onSubmit: (e: KeyboardEvent | undefined, value: string) => void;
437
323
  inputRef: React.RefObject<ReactCodeMirrorRef | null>;
@@ -444,9 +330,7 @@ interface ChatInputProps {
444
330
 
445
331
  const ChatInput: React.FC<ChatInputProps> = memo(
446
332
  ({
447
- placeholder,
448
333
  input,
449
- inputClassName,
450
334
  setInput,
451
335
  onSubmit,
452
336
  inputRef,
@@ -456,6 +340,20 @@ const ChatInput: React.FC<ChatInputProps> = memo(
456
340
  onAddFiles,
457
341
  onClose,
458
342
  }) => {
343
+ const openPairWithAgentModal = usePairWithAgentModal();
344
+ const placeholderAction = useMemo(
345
+ () =>
346
+ isWasm()
347
+ ? undefined
348
+ : {
349
+ beforeText: "Type your message or ",
350
+ linkText: "pair your own coding agent",
351
+ afterText: ". Use @ to reference variables and cells.",
352
+ onClick: openPairWithAgentModal,
353
+ },
354
+ [openPairWithAgentModal],
355
+ );
356
+
459
357
  const handleSendClick = useEvent(() => {
460
358
  if (input.trim()) {
461
359
  onSubmit(undefined, input);
@@ -463,8 +361,8 @@ const ChatInput: React.FC<ChatInputProps> = memo(
463
361
  });
464
362
 
465
363
  return (
466
- <div className="relative shrink-0 flex flex-col border-t">
467
- <div className={cn("px-2 py-1.5", inputClassName)}>
364
+ <div className="relative shrink-0 flex flex-col">
365
+ <div className="px-2 py-1.5">
468
366
  <PromptInput
469
367
  className="max-h-[400px]"
470
368
  inputRef={inputRef}
@@ -473,7 +371,8 @@ const ChatInput: React.FC<ChatInputProps> = memo(
473
371
  onSubmit={onSubmit}
474
372
  onClose={onClose}
475
373
  onAddFiles={onAddFiles}
476
- placeholder={placeholder || "Type your message..."}
374
+ placeholder="Type your message. Use @ to reference variables and cells."
375
+ placeholderAction={placeholderAction}
477
376
  />
478
377
  </div>
479
378
  <ChatInputFooter
@@ -492,26 +391,6 @@ const ChatInput: React.FC<ChatInputProps> = memo(
492
391
 
493
392
  ChatInput.displayName = "ChatInput";
494
393
 
495
- const PairWithAgentCallout: React.FC<{
496
- onPairWithAgent: () => void;
497
- }> = ({ onPairWithAgent }) => {
498
- if (isWasm()) {
499
- return null;
500
- }
501
-
502
- return (
503
- <Button
504
- variant="text"
505
- className="gap-1.5 text-sm text-link hover:underline"
506
- onClick={onPairWithAgent}
507
- >
508
- <SparklesIcon className="h-3.5 w-3.5 shrink-0" />
509
- <span>Connect your own agent to this notebook</span>
510
- <ArrowRightIcon className="h-3 w-3 shrink-0" />
511
- </Button>
512
- );
513
- };
514
-
515
394
  const ChatPanel = () => {
516
395
  const aiConfigured = useAtomValue(aiModelConfiguredAtom);
517
396
  const { handleClick } = useOpenSettingsToTab();
@@ -567,9 +446,10 @@ const ChatPanelBody = () => {
567
446
  lastAbortReasonRef.current = null;
568
447
  setAbortNotice(null);
569
448
  });
449
+ const turn = useAssistantTurn();
450
+ const resetTurn = turn.reset;
570
451
  const runtimeManager = useRuntimeManager();
571
- const { invokeAiTool, sendRun } = useRequestClient();
572
- const { openModal, closeModal } = useImperativeModal();
452
+ const { invokeAiTool } = useRequestClient();
573
453
 
574
454
  const activeChatId = activeChat?.id;
575
455
  const { chatControllerId, renewDraftChatId } =
@@ -577,12 +457,10 @@ const ChatPanelBody = () => {
577
457
  const store = useStore();
578
458
 
579
459
  const { addStagedCell } = useStagedAICellsActions();
580
- const { createNewCell, prepareForRun } = useCellActions();
460
+ const { createCell } = useCellActions();
581
461
  const toolContext: ToolNotebookContext = {
582
462
  addStagedCell,
583
- createNewCell,
584
- prepareForRun,
585
- sendRun,
463
+ createCell,
586
464
  store,
587
465
  };
588
466
 
@@ -592,6 +470,7 @@ const ChatPanelBody = () => {
592
470
  error,
593
471
  status,
594
472
  regenerate,
473
+ setMessages,
595
474
  stop,
596
475
  addToolOutput,
597
476
  addToolApprovalResponse,
@@ -599,7 +478,8 @@ const ChatPanelBody = () => {
599
478
  } = useChat({
600
479
  id: chatControllerId,
601
480
  throttle: AI_SDK_UI_THROTTLE_MS,
602
- sendAutomaticallyWhen: ({ messages }) => hasPendingToolCalls(messages),
481
+ sendAutomaticallyWhen: ({ messages }) =>
482
+ !turn.hasEnded && hasPendingToolCalls(messages),
603
483
  messages: activeChat?.messages || [], // initial messages
604
484
  transport: new StreamingChunkTransport(
605
485
  {
@@ -646,7 +526,26 @@ const ChatPanelBody = () => {
646
526
  }
647
527
  },
648
528
  ),
649
- onFinish: ({ messages, isError, isAbort, finishReason }) => {
529
+ onFinish: ({
530
+ messages: finishedMessages,
531
+ isError,
532
+ isAbort,
533
+ finishReason,
534
+ }) => {
535
+ // useChat routes every chat's callbacks to the latest one. Its
536
+ // setMessages isn't a React setter: the updater runs synchronously.
537
+ const finished: { messages?: typeof finishedMessages } = {};
538
+ setMessages((current) => {
539
+ if (current.at(-1)?.id !== finishedMessages.at(-1)?.id) {
540
+ return current;
541
+ }
542
+ finished.messages = turn.finish(finishedMessages, { isAbort, isError });
543
+ return finished.messages;
544
+ });
545
+ const { messages } = finished;
546
+ if (!messages) {
547
+ return;
548
+ }
650
549
  setChatState((prev) => {
651
550
  return replaceMessagesInChat({
652
551
  chatState: prev,
@@ -691,6 +590,7 @@ const ChatPanelBody = () => {
691
590
 
692
591
  const sendUserMessage = useEvent((parts: ChatMessagePart[]) => {
693
592
  clearAbortState();
593
+ turn.start();
694
594
  sendMessage({ role: "user", parts });
695
595
  });
696
596
 
@@ -715,15 +615,43 @@ const ChatPanelBody = () => {
715
615
  },
716
616
  );
717
617
 
718
- const isLoading = status === "submitted" || status === "streaming";
719
- // Read via a ref so the queue-vs-send decision stays correct even when it is
720
- // made after an `await` (e.g. resolving @-context), by which point the render
721
- // closure's `isLoading` may be stale.
722
- const isLoadingRef = useRef(isLoading);
723
- isLoadingRef.current = isLoading;
618
+ const isLoading = isChatBusy(status);
619
+ const isTurnActive = turn.isActive({
620
+ isLoading,
621
+ hasError: error != null,
622
+ messages,
623
+ });
624
+ useChatGeneration(isTurnActive);
625
+
626
+ const stopTurn = useEvent(() => {
627
+ if (isLoading) {
628
+ turn.stop();
629
+ void stop();
630
+ return;
631
+ }
632
+ // Between requests there is no stream to abort, so `onFinish` won't run.
633
+ const stopped = turn.finish(messages, { isAbort: true, isError: false });
634
+ setMessages(stopped);
635
+ setChatState((prev) =>
636
+ replaceMessagesInChat({
637
+ chatState: prev,
638
+ chatId: prev.activeChatId,
639
+ messages: stopped,
640
+ }),
641
+ );
642
+ tryFlushQueuedMessages(stopped, { isError: false, isAbort: true });
643
+ });
724
644
 
645
+ const respondToApproval = useEvent(
646
+ (response: Parameters<ChatAddToolApproveResponseFunction>[0]) => {
647
+ turn.resume(messages.at(-1));
648
+ return addToolApprovalResponse(response);
649
+ },
650
+ );
651
+ // useEvent reads the latest loading state, even when called after an await
652
+ // (e.g. resolving @-context) that outlives the original render's closure.
725
653
  const submitOrQueue = useEvent((parts: ChatMessagePart[]) => {
726
- if (isLoadingRef.current || hasQueuedRef.current) {
654
+ if (isTurnActive || hasQueuedRef.current) {
727
655
  enqueueUserMessage(parts);
728
656
  } else {
729
657
  sendUserMessage(parts);
@@ -756,10 +684,6 @@ const ChatPanelBody = () => {
756
684
  });
757
685
  });
758
686
 
759
- // Check if we're currently streaming reasoning in the latest message
760
- const isStreamingReasoning =
761
- isLoading && messages.length > 0 && isLastMessageReasoning(messages);
762
-
763
687
  // Pin to the bottom while the user is already there.
764
688
  useEffect(() => {
765
689
  setIsScrolledToBottom(true);
@@ -767,6 +691,11 @@ const ChatPanelBody = () => {
767
691
  clearAbortState();
768
692
  }, [activeChatId, clearQueuedMessages, clearAbortState]);
769
693
 
694
+ // Creating a chat keeps the draft's controller, so its turn survives.
695
+ useEffect(() => {
696
+ resetTurn();
697
+ }, [chatControllerId, resetTurn]);
698
+
770
699
  useEffect(() => {
771
700
  if (!isScrolledToBottom) {
772
701
  return;
@@ -821,6 +750,7 @@ const ChatPanelBody = () => {
821
750
  const { contextPart, attachments } =
822
751
  await resolveChatContext(initialMessage);
823
752
 
753
+ turn.start();
824
754
  sendMessage({
825
755
  role: "user",
826
756
  parts: [
@@ -865,10 +795,6 @@ const ChatPanelBody = () => {
865
795
  });
866
796
  });
867
797
 
868
- const handlePairWithAgent = useEvent(() => {
869
- openModal(<PairWithAgentModal onClose={closeModal} />);
870
- });
871
-
872
798
  const handleMessageEdit = useEvent(
873
799
  async (index: number, newValue: string) => {
874
800
  const editedMessage = messages[index];
@@ -882,6 +808,7 @@ const ChatPanelBody = () => {
882
808
  const { contextPart, attachments } = await resolveChatContext(newValue);
883
809
 
884
810
  const messageId = editedMessage.id;
811
+ turn.start();
885
812
  sendMessage({
886
813
  messageId: messageId, // replace the message
887
814
  role: "user",
@@ -920,6 +847,7 @@ const ChatPanelBody = () => {
920
847
 
921
848
  const handleReload = () => {
922
849
  clearAbortState();
850
+ turn.start();
923
851
  regenerate();
924
852
  };
925
853
 
@@ -959,14 +887,20 @@ const ChatPanelBody = () => {
959
887
  return;
960
888
  }
961
889
  setPendingPrompt(null);
962
- const { prompt, submit } = pendingPrompt;
890
+ const { prompt, submit, append } = pendingPrompt;
891
+ const applyPrompt = (draft: string) =>
892
+ append
893
+ ? draft.includes(prompt.trim())
894
+ ? draft
895
+ : `${draft}${draft ? " " : ""}${prompt}`
896
+ : prompt;
963
897
  if (submit) {
964
898
  void submitPendingPrompt(prompt);
965
899
  } else if (isNewThread) {
966
- setNewThreadInput(prompt);
900
+ setNewThreadInput(applyPrompt);
967
901
  focusInputAndMoveToEnd(newThreadInputRef);
968
902
  } else {
969
- setInput(prompt);
903
+ setInput(applyPrompt);
970
904
  focusInputAndMoveToEnd(newMessageInputRef);
971
905
  }
972
906
  }, [pendingPrompt, setPendingPrompt, isNewThread, submitPendingPrompt]);
@@ -974,14 +908,12 @@ const ChatPanelBody = () => {
974
908
  const chatInput = isNewThread ? (
975
909
  <ChatInput
976
910
  key="new-thread-input"
977
- placeholder={`Ask anything, ${CONTEXT_TRIGGER} to include context about tables or dataframes`}
978
911
  input={newThreadInput}
979
912
  inputRef={newThreadInputRef}
980
- inputClassName="px-1 py-0"
981
913
  setInput={setNewThreadInput}
982
914
  onSubmit={handleNewThreadSubmit}
983
- isLoading={isLoading}
984
- onStop={stop}
915
+ isLoading={isTurnActive}
916
+ onStop={stopTurn}
985
917
  fileInputRef={fileInputRef}
986
918
  onAddFiles={addFiles}
987
919
  onClose={handleOnCloseThread}
@@ -992,8 +924,8 @@ const ChatPanelBody = () => {
992
924
  setInput={setInput}
993
925
  onSubmit={handleChatInputSubmit}
994
926
  inputRef={newMessageInputRef}
995
- isLoading={isLoading}
996
- onStop={stop}
927
+ isLoading={isTurnActive}
928
+ onStop={stopTurn}
997
929
  onClose={() => newMessageInputRef.current?.editor?.blur()}
998
930
  fileInputRef={fileInputRef}
999
931
  onAddFiles={addFiles}
@@ -1001,12 +933,7 @@ const ChatPanelBody = () => {
1001
933
  );
1002
934
 
1003
935
  const filesPills = files && files.length > 0 && (
1004
- <div
1005
- className={cn(
1006
- "flex flex-row gap-1 flex-wrap p-1",
1007
- isNewThread && "py-2 px-1",
1008
- )}
1009
- >
936
+ <div className="flex flex-row gap-1 flex-wrap px-3 pt-2">
1010
937
  {files?.map((file) => (
1011
938
  <FileAttachmentPill
1012
939
  file={file}
@@ -1017,8 +944,15 @@ const ChatPanelBody = () => {
1017
944
  </div>
1018
945
  );
1019
946
 
947
+ const composer = (
948
+ <div className="@container rounded-[10px] border border-border bg-background">
949
+ {filesPills}
950
+ {chatInput}
951
+ </div>
952
+ );
953
+
1020
954
  return (
1021
- <div className="flex flex-col h-[calc(100%-53px)]">
955
+ <div className="mo-ai-panel flex flex-col flex-1 min-h-0 font-prose text-sm leading-6">
1022
956
  <TooltipProvider>
1023
957
  <ChatHeader
1024
958
  onNewChat={handleNewChat}
@@ -1031,43 +965,44 @@ const ChatPanelBody = () => {
1031
965
 
1032
966
  <div className="flex-1 flex flex-col overflow-hidden relative min-h-0">
1033
967
  <div
1034
- className="flex-1 px-3 bg-(--slate-1) gap-4 py-3 flex flex-col overflow-y-auto"
968
+ className="flex-1 px-3 bg-background gap-4 py-3 flex flex-col overflow-y-auto"
1035
969
  ref={scrollContainerRef}
1036
970
  onScroll={handleScroll}
1037
971
  >
1038
- {isNewThread && (
1039
- <div className="flex flex-col gap-2">
1040
- <div className="rounded-md border bg-background">
1041
- {filesPills}
1042
- {chatInput}
1043
- </div>
1044
- <PairWithAgentCallout onPairWithAgent={handlePairWithAgent} />
1045
- </div>
1046
- )}
1047
-
1048
- {messages.map((message, idx) => (
1049
- <ChatMessageDisplay
1050
- key={message.id}
1051
- message={message}
1052
- index={idx}
1053
- onEdit={handleMessageEdit}
1054
- isStreamingReasoning={isStreamingReasoning}
1055
- isLast={idx === messages.length - 1}
1056
- isActive={isLoading}
1057
- addToolApprovalResponse={addToolApprovalResponse}
972
+ <TooltipProvider>
973
+ {messages.map((message, idx) => {
974
+ const isLast = idx === messages.length - 1;
975
+ return (
976
+ <ChatMessageDisplay
977
+ key={message.id}
978
+ message={message}
979
+ index={idx}
980
+ onEdit={handleMessageEdit}
981
+ isLast={isLast}
982
+ isActive={isTurnActive}
983
+ turnStartedAt={isLast ? turn.startedAt : null}
984
+ addToolApprovalResponse={respondToApproval}
985
+ />
986
+ );
987
+ })}
988
+ </TooltipProvider>
989
+
990
+ {isTurnActive && messages.at(-1)?.role === "user" && (
991
+ <AgentActivity
992
+ running={true}
993
+ thinking={true}
994
+ timing={
995
+ turn.startedAt == null
996
+ ? undefined
997
+ : { startedAt: turn.startedAt }
998
+ }
1058
999
  />
1059
- ))}
1000
+ )}
1060
1001
 
1061
1002
  {queuedMessages.map((message) => (
1062
1003
  <QueuedMessageDisplay key={message.id} message={message} />
1063
1004
  ))}
1064
1005
 
1065
- {isLoading && (
1066
- <div className="flex justify-center py-4">
1067
- <Loader2 className="h-4 w-4 animate-spin" />
1068
- </div>
1069
- )}
1070
-
1071
1006
  {error && (
1072
1007
  <div className="flex items-center justify-center space-x-2 mb-4">
1073
1008
  <ErrorBanner error={error || new Error("Unknown error")} />
@@ -1095,21 +1030,8 @@ const ChatPanelBody = () => {
1095
1030
  />
1096
1031
  </div>
1097
1032
 
1098
- {isLoading && (
1099
- <div className="w-full flex justify-center items-center z-20 border-t">
1100
- <Button variant="linkDestructive" size="sm" onClick={stop}>
1101
- Stop
1102
- </Button>
1103
- </div>
1104
- )}
1105
-
1106
- {/* For existing threads, we place the chat input at the bottom */}
1107
- {!isNewThread && (
1108
- <>
1109
- {filesPills}
1110
- {chatInput}
1111
- </>
1112
- )}
1033
+ {!isTurnActive && <PendingAICells />}
1034
+ <div className="shrink-0 p-3">{composer}</div>
1113
1035
  </div>
1114
1036
  );
1115
1037
  };