@marimo-team/islands 0.25.3-dev266 → 0.25.3-dev268

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 (184) hide show
  1. package/dist/{ConnectedDataExplorerComponent-C_hj7Poi.js → ConnectedDataExplorerComponent-eLHPh6uu.js} +9 -9
  2. package/dist/{ErrorBoundary-CvxlC3F1.js → ErrorBoundary-CQYAoD7X.js} +64 -69
  3. package/dist/{abnfDiagram-VCTEODGH-DzrZZXRD.js → abnfDiagram-VCTEODGH-hqd0IBtX.js} +2 -2
  4. package/dist/{any-language-editor-CFeWfC3o.js → any-language-editor-DnG26QXh.js} +1 -1
  5. package/dist/{architectureDiagram-5GKGNRK7-iF_snyFL.js → architectureDiagram-5GKGNRK7-BzLAFcc0.js} +1 -1
  6. package/dist/{strings-BCKpLFNU.js → assertNever-DIU3JJbt.js} +14 -14
  7. package/dist/{chat-ui-DFxNgzXF.js → chat-ui-BAnLgpTe.js} +1964 -1740
  8. package/dist/{chunk-IMKFNOWR-B7xytD4B.js → chunk-IMKFNOWR-DOeVvuyE.js} +1 -1
  9. package/dist/{chunk-SHT3W25Y-I8ZFP5L1.js → chunk-SHT3W25Y-DZoFI8wR.js} +1 -1
  10. package/dist/{chunk-SVP7TREG-Di-uAPdT.js → chunk-SVP7TREG-CWu86PSW.js} +1 -1
  11. package/dist/{chunk-TICWLB2K-BFpUy0ud.js → chunk-TICWLB2K-BrM0GoP3.js} +1 -1
  12. package/dist/{classDiagram-ZZMXUADV-Cqm4JGpx.js → classDiagram-ZZMXUADV-DYi4V2bB.js} +2 -2
  13. package/dist/{classDiagram-v2-VYDZK3BY-DFHRJpN3.js → classDiagram-v2-VYDZK3BY-tN7FIk-m.js} +2 -2
  14. package/dist/{code-visibility-SRM1JiD_.js → code-visibility-DcZ_RwaH.js} +44 -47
  15. package/dist/{common-yiRhZ6ZZ.js → common-BGeQilvh.js} +5846 -5519
  16. package/dist/{config-CmeG_Pb6.js → config-BsPruWMR.js} +2 -2
  17. package/dist/{createReducer-C_syF8Td.js → createReducer-DdtT_7ji.js} +1 -1
  18. package/dist/{cynefinDiagram-5FMLGOSQ-cuGOeTBC.js → cynefinDiagram-5FMLGOSQ-D5nCnDc-.js} +1 -1
  19. package/dist/{dagre-GXQ25YYZ-DJ76aC4k.js → dagre-GXQ25YYZ-BHkd7f_i.js} +1 -1
  20. package/dist/{data-grid-overlay-editor-DLTzcQ4O.js → data-grid-overlay-editor-Dc4lW4A3.js} +1 -1
  21. package/dist/{diagram-S7CK7UJ4-DLLc0sw7.js → diagram-S7CK7UJ4-D1ALppT2.js} +1 -1
  22. package/dist/{diagram-UQ7AKVKN-Tz_d6qmk.js → diagram-UQ7AKVKN-DLv0b83L.js} +1 -1
  23. package/dist/{diagram-VX7I27RA-D7SzPrDN.js → diagram-VX7I27RA-7XJ7J6qg.js} +1 -1
  24. package/dist/{diagram-Z3DM3KII-qr37XV58.js → diagram-Z3DM3KII-7M7zbHp_.js} +1 -1
  25. package/dist/{dialog-BtprQCUw.js → dialog-DzCj1qQv.js} +1 -1
  26. package/dist/{dropdown-menu-CkJ7ErY6.js → dropdown-menu-CdXE15an.js} +1214 -1208
  27. package/dist/{ebnfDiagram-PWID7BFC-BKOQb4J0.js → ebnfDiagram-PWID7BFC-DHH1qlmV.js} +2 -2
  28. package/dist/{erDiagram-RLTQ6QDP-CM15Vq68.js → erDiagram-RLTQ6QDP-fI_0dGef.js} +1 -1
  29. package/dist/{error-banner-DbRFOd2O.js → error-banner-DPc9eIw5.js} +3 -3
  30. package/dist/{error-entries-CMoaUX9V.js → error-entries-CxN-Nq3V.js} +524 -456
  31. package/dist/{feedback-button-DBUrE4OL.js → feedback-button-BqaeQcvX.js} +77 -77
  32. package/dist/{flowDiagram-HODETNUW-Dt3N5yFT.js → flowDiagram-HODETNUW-Brg9MA6i.js} +2 -2
  33. package/dist/{formats-gGospKWJ.js → formats-DbSvAPY-.js} +1 -1
  34. package/dist/{glide-data-editor-Cfv4HeOh.js → glide-data-editor-CiijPXA7.js} +2042 -2041
  35. package/dist/{glide-utils-Ba9WD2IN.js → glide-utils-BSw3SSHF.js} +29 -35
  36. package/dist/{globals-dIbBIR5-.js → globals-CpmSWKI_.js} +2 -2
  37. package/dist/{html-to-image-D_5CMreP.js → html-to-image-8sywF4my.js} +5452 -5751
  38. package/dist/{infoDiagram-27XIBGKW-C7axJMCl.js → infoDiagram-27XIBGKW-E9e403YT.js} +1 -1
  39. package/dist/{ishikawaDiagram-5VMMS53U-CdC9Eur7.js → ishikawaDiagram-5VMMS53U-C-RlYDRo.js} +1 -1
  40. package/dist/{kanban-definition-UXKFOSKX-BHnMIgD7.js → kanban-definition-UXKFOSKX-CLFl_uqK.js} +1 -1
  41. package/dist/main.js +6294 -6324
  42. package/dist/{mermaid-DFYN_PXd.js → mermaid-rd09e1JL.js} +35 -35
  43. package/dist/{mindmap-definition-YA3MSWOX-BagHoCGU.js → mindmap-definition-YA3MSWOX-BQ8TWtyB.js} +1 -1
  44. package/dist/{number-overlay-editor-CTiJp5Mj.js → number-overlay-editor-Ft4NiAEN.js} +1 -1
  45. package/dist/{pegDiagram-XKGWAZYB-8IIZczip.js → pegDiagram-XKGWAZYB-CN8UHFPi.js} +2 -2
  46. package/dist/pencil-DcT8AE0h.js +10 -0
  47. package/dist/{pieDiagram-E7YTZNPT-CE6dKBIr.js → pieDiagram-E7YTZNPT-DGuJ0EBd.js} +1 -1
  48. package/dist/{process-output-CGFNVC60.js → process-output-Dku5POvm.js} +3 -3
  49. package/dist/{railroadDiagram-O6MQD6OU-CkexPq3b.js → railroadDiagram-O6MQD6OU-BPDA8wy8.js} +2 -2
  50. package/dist/{requirementDiagram-BXWQKSXE-B0-OkuAe.js → requirementDiagram-BXWQKSXE-ChzLGbGW.js} +1 -1
  51. package/dist/{reveal-component-DH09ygHo.js → reveal-component-D0cfwbbl.js} +1094 -1094
  52. package/dist/{select-C33FVPPN.js → select-OxgozOC8.js} +1 -1
  53. package/dist/{sequenceDiagram-WJ2MYXX4-Dxysg8DX.js → sequenceDiagram-WJ2MYXX4-DFX-bE6O.js} +1 -1
  54. package/dist/{spec-DH1lmF7Q.js → spec-oJn0RhpQ.js} +2 -2
  55. package/dist/{stateDiagram-D77RDMKH-DTEN3-OJ.js → stateDiagram-D77RDMKH-BR7cI3wK.js} +2 -2
  56. package/dist/{stateDiagram-v2-MP3YSRHH-vktk3Xc5.js → stateDiagram-v2-MP3YSRHH-oGqB5UDI.js} +2 -2
  57. package/dist/{static-state-BldGd99T.js → static-state-CuV6Pc3a.js} +1 -1
  58. package/dist/style.css +1 -1
  59. package/dist/{swimlanes-42K2YHIH-Cjveh9OM.js → swimlanes-42K2YHIH-DwSZl1yC.js} +1 -1
  60. package/dist/{swimlanesDiagram-VR7AAH4N-Bdr7Ev_2.js → swimlanesDiagram-VR7AAH4N-BHlcd-Ri.js} +2 -2
  61. package/dist/{timeline-definition-24CTP7MA-KIuDcefn.js → timeline-definition-24CTP7MA-DMmP-G2O.js} +1 -1
  62. package/dist/{toast-CY1_Qv41.js → toast-DbBHmxmB.js} +2 -2
  63. package/dist/{useAsyncData-DsZMvNXn.js → useAsyncData-BYIAoMqn.js} +1 -1
  64. package/dist/{useDateFormatter-Dk_xFci4.js → useDateFormatter-ButWkdcK.js} +1 -1
  65. package/dist/{useDeepCompareMemoize-KMBBux8C.js → useDeepCompareMemoize-Bz0c5GN6.js} +1 -1
  66. package/dist/{useTheme-BZ2GGLgm.js → useTheme-DPLobSFs.js} +7 -7
  67. package/dist/{utils-DXkj82sK.js → utils-EBklsC5R.js} +31 -31
  68. package/dist/{vega-component-C-lqjV0q.js → vega-component-rxIxAAh9.js} +7 -7
  69. package/dist/{vennDiagram-4TSXK5OY-DrIOUHfb.js → vennDiagram-4TSXK5OY-Db8GtH1G.js} +1 -1
  70. package/dist/{wardleyDiagram-VM6X3IG4-CJNjf4OH.js → wardleyDiagram-VM6X3IG4-DmIiC3FU.js} +1 -1
  71. package/dist/{xychartDiagram-S5SC5T6Z-DEshFho-.js → xychartDiagram-S5SC5T6Z-DS9OPrNq.js} +1 -1
  72. package/package.json +1 -1
  73. package/src/__mocks__/executions.ts +195 -0
  74. package/src/__mocks__/notebook.ts +0 -1
  75. package/src/__tests__/CellStatus.test.tsx +19 -20
  76. package/src/components/chat/__tests__/chat-display.test.tsx +157 -86
  77. package/src/components/chat/__tests__/chat-utils.test.ts +42 -0
  78. package/src/components/chat/__tests__/turn-timing.test.ts +84 -0
  79. package/src/components/chat/__tests__/use-assistant-turn.test.ts +95 -0
  80. package/src/components/chat/__tests__/user-message.test.tsx +27 -0
  81. package/src/components/chat/acp/agent-panel.tsx +2 -0
  82. package/src/components/chat/agent-activity.tsx +132 -0
  83. package/src/components/chat/chat-display.tsx +125 -96
  84. package/src/components/chat/chat-panel.tsx +123 -106
  85. package/src/components/chat/chat-utils.ts +12 -24
  86. package/src/components/chat/tool-call/__tests__/tool-labels.test.ts +76 -0
  87. package/src/components/chat/tool-call/__tests__/tool-step.test.tsx +57 -0
  88. package/src/components/chat/tool-call/shared.ts +6 -0
  89. package/src/components/chat/tool-call/tool-call-view.tsx +22 -76
  90. package/src/components/chat/tool-call/tool-labels.ts +172 -0
  91. package/src/components/chat/tool-call/tool-step.tsx +145 -0
  92. package/src/components/chat/turn-timing.ts +73 -0
  93. package/src/components/chat/use-assistant-turn.ts +65 -0
  94. package/src/components/chat/use-chat-generation.ts +5 -4
  95. package/src/components/chat/user-message.tsx +145 -0
  96. package/src/components/dependency-graph/minimap-content.tsx +3 -2
  97. package/src/components/editor/__tests__/data-attributes.test.tsx +0 -7
  98. package/src/components/editor/__tests__/output-persistence.test.tsx +2 -2
  99. package/src/components/editor/actions/__tests__/useCellActionButton.test.tsx +19 -1
  100. package/src/components/editor/actions/useCellActionButton.tsx +10 -3
  101. package/src/components/editor/ai/completion-handlers.tsx +0 -37
  102. package/src/components/editor/alerts/stdin-blocking-alert.tsx +3 -1
  103. package/src/components/editor/cell/CellStatus.tsx +23 -19
  104. package/src/components/editor/cell/RunButton.tsx +16 -6
  105. package/src/components/editor/cell/StagedAICell.tsx +51 -144
  106. package/src/components/editor/cell/__tests__/useRunCells.test.ts +45 -0
  107. package/src/components/editor/cell/cell-context-menu.tsx +4 -1
  108. package/src/components/editor/cell/code/cell-editor.tsx +7 -5
  109. package/src/components/editor/cell/collapse.tsx +4 -0
  110. package/src/components/editor/cell/useRunCells.ts +18 -3
  111. package/src/components/editor/chrome/wrapper/__tests__/pending-ai-cells.test.tsx +193 -32
  112. package/src/components/editor/chrome/wrapper/app-chrome.tsx +2 -2
  113. package/src/components/editor/chrome/wrapper/pending-ai-cells.tsx +145 -81
  114. package/src/components/editor/chrome/wrapper/pending-ai-changes-badge.tsx +25 -0
  115. package/src/components/editor/chrome/wrapper/sidebar.tsx +8 -4
  116. package/src/components/editor/header/status.tsx +4 -2
  117. package/src/components/editor/links/cell-link.tsx +4 -4
  118. package/src/components/editor/navigation/navigation.ts +3 -2
  119. package/src/components/editor/notebook-cell.tsx +85 -94
  120. package/src/components/editor/renderers/grid-layout/__tests__/grid-layout.test.tsx +75 -0
  121. package/src/components/editor/renderers/grid-layout/grid-layout.tsx +22 -16
  122. package/src/components/editor/renderers/slides-layout/__tests__/plugin.test.ts +0 -1
  123. package/src/components/editor/renderers/vertical-layout/vertical-layout.tsx +12 -33
  124. package/src/components/editor/stdin-blocking-alert.tsx +3 -1
  125. package/src/components/scratchpad/scratchpad.tsx +4 -1
  126. package/src/components/slides/minimap.tsx +4 -2
  127. package/src/components/slides/reveal-component.tsx +14 -10
  128. package/src/components/slides/slide-cell-view.tsx +28 -24
  129. package/src/components/slides/slide.tsx +3 -4
  130. package/src/components/ui/toast.tsx +1 -1
  131. package/src/core/ai/__tests__/staged-cells.test.ts +74 -126
  132. package/src/core/ai/staged-cells.ts +48 -38
  133. package/src/core/cells/__tests__/__snapshots__/cells.test.ts.snap +0 -389
  134. package/src/core/cells/__tests__/cell.test.ts +49 -154
  135. package/src/core/cells/__tests__/cells.test.ts +18 -127
  136. package/src/core/cells/__tests__/pending-delete-service.test.tsx +11 -20
  137. package/src/core/cells/__tests__/utils.test.ts +75 -247
  138. package/src/core/cells/actions.ts +5 -2
  139. package/src/core/cells/cell.ts +31 -133
  140. package/src/core/cells/cells.ts +14 -29
  141. package/src/core/cells/document.ts +3 -3
  142. package/src/core/cells/focus.ts +27 -6
  143. package/src/core/cells/layout.ts +1 -1
  144. package/src/core/cells/pending-delete-service.ts +5 -7
  145. package/src/core/cells/scrollCellIntoView.ts +6 -0
  146. package/src/core/cells/types.ts +13 -36
  147. package/src/core/cells/utils.ts +37 -68
  148. package/src/core/codemirror/placeholder/__tests__/extensions.test.ts +59 -0
  149. package/src/core/codemirror/placeholder/extensions.ts +23 -0
  150. package/src/core/edit-app.tsx +2 -1
  151. package/src/core/executions/__tests__/atoms.test.ts +99 -0
  152. package/src/core/executions/__tests__/select.test.ts +268 -0
  153. package/src/core/executions/atoms.ts +206 -0
  154. package/src/core/executions/hooks.ts +31 -0
  155. package/src/core/executions/index.ts +31 -0
  156. package/src/core/executions/select.ts +175 -0
  157. package/src/core/export/__tests__/hooks.test.ts +0 -5
  158. package/src/core/islands/bootstrap.ts +4 -1
  159. package/src/core/islands/components/output-wrapper.tsx +5 -5
  160. package/src/core/kernel/handlers.ts +2 -11
  161. package/src/core/kernel/state.ts +0 -15
  162. package/src/core/lifecycle/render-policy.ts +12 -26
  163. package/src/core/network/__tests__/requests-lazy.test.ts +5 -5
  164. package/src/core/network/requests-lazy.ts +3 -3
  165. package/src/core/notebook/operations.ts +1 -1
  166. package/src/core/run-app.tsx +2 -1
  167. package/src/core/runtime/__tests__/adapter.test.ts +3 -3
  168. package/src/core/runtime/adapter.ts +4 -4
  169. package/src/core/session/__tests__/useNotebookSession.hook.test.tsx +34 -0
  170. package/src/core/session/useNotebookSession.tsx +10 -5
  171. package/src/core/wasm/bridge.ts +1 -1
  172. package/src/css/app/Cell.css +7 -36
  173. package/src/plugins/core/registerReactComponent.tsx +4 -13
  174. package/src/plugins/impl/chat/chat-ui.tsx +2 -3
  175. package/src/plugins/impl/common/error-banner.tsx +5 -3
  176. package/src/stories/cell-status.stories.tsx +17 -10
  177. package/src/stories/cell.stories.tsx +0 -31
  178. package/src/stories/layout/vertical/one-column.stories.tsx +0 -9
  179. package/src/utils/time.ts +10 -0
  180. package/src/components/chat/reasoning-accordion.tsx +0 -61
  181. package/src/components/chat/tool-call/tool-activity-group.tsx +0 -49
  182. package/src/components/chat/tool-call/tool-error-card.tsx +0 -81
  183. package/src/components/chat/tool-call/tool-history-row.tsx +0 -147
  184. package/src/components/icons/loading-ellipsis.tsx +0 -46
@@ -37,6 +37,7 @@ import { NumberField } from "@/components/ui/number-field";
37
37
  import { Switch } from "@/components/ui/switch";
38
38
  import { outputIsLoading, outputIsStale } from "@/core/cells/cell";
39
39
  import type { CellId } from "@/core/cells/ids";
40
+ import { useCellExecution } from "@/core/executions";
40
41
  import type { AppMode } from "@/core/mode";
41
42
  import { useIsDragging } from "@/hooks/useIsDragging";
42
43
  import { cn } from "@/utils/cn";
@@ -227,11 +228,10 @@ export const GridLayoutRenderer: React.FC<Props> = ({
227
228
  mode={mode}
228
229
  cellId={cell.id}
229
230
  output={cell.output}
230
- status={cell.status}
231
- stale={outputIsStale(cell, false)}
231
+ staleInputs={cell.staleInputs}
232
+ hideWithoutValue={true}
232
233
  isScrollable={isScrollable}
233
234
  side={side}
234
- hidden={cell.errored || cell.interrupted || cell.stopped}
235
235
  />
236
236
  );
237
237
 
@@ -294,10 +294,9 @@ export const GridLayoutRenderer: React.FC<Props> = ({
294
294
  mode={mode}
295
295
  cellId={cell.id}
296
296
  output={cell.output}
297
- status={cell.status}
298
- stale={outputIsStale(cell, false)}
297
+ staleInputs={cell.staleInputs}
298
+ hideWithoutValue={false}
299
299
  isScrollable={false}
300
- hidden={false}
301
300
  />
302
301
  );
303
302
  })}
@@ -364,10 +363,9 @@ export const GridLayoutRenderer: React.FC<Props> = ({
364
363
  mode={mode}
365
364
  cellId={cell.id}
366
365
  output={cell.output}
366
+ staleInputs={cell.staleInputs}
367
+ hideWithoutValue={false}
367
368
  isScrollable={false}
368
- status={cell.status}
369
- stale={outputIsStale(cell, false)}
370
- hidden={false}
371
369
  />
372
370
  </div>
373
371
  ))}
@@ -377,31 +375,39 @@ export const GridLayoutRenderer: React.FC<Props> = ({
377
375
  );
378
376
  };
379
377
 
380
- interface GridCellProps extends Pick<CellRuntimeState, "output" | "status"> {
378
+ interface GridCellProps extends Pick<
379
+ CellRuntimeState,
380
+ "output" | "staleInputs"
381
+ > {
381
382
  className?: string;
382
383
  code: string;
383
384
  cellId: CellId;
384
385
  mode: AppMode;
385
- hidden: boolean;
386
+ /** Whether a cell whose last run ended without a value keeps its place but shows nothing. */
387
+ hideWithoutValue: boolean;
386
388
  isScrollable: boolean;
387
389
  side?: GridLayoutCellSide;
388
- stale: boolean;
389
390
  }
390
391
 
391
392
  const GridCell = memo(
392
393
  ({
393
394
  output,
395
+ staleInputs,
394
396
  cellId,
395
- status,
396
397
  mode,
397
398
  code,
398
- hidden,
399
+ hideWithoutValue,
399
400
  isScrollable,
400
401
  side,
401
402
  className,
402
- stale,
403
403
  }: GridCellProps) => {
404
- const loading = outputIsLoading(status);
404
+ const execution = useCellExecution(cellId);
405
+ const loading = outputIsLoading(execution.status);
406
+ const stale = outputIsStale(execution, staleInputs, false);
407
+ const hidden =
408
+ hideWithoutValue &&
409
+ execution.outcome !== null &&
410
+ execution.outcome !== "value";
405
411
 
406
412
  const isOutputEmpty = output == null || output.data === "";
407
413
  // If not reading, show code when there is no output
@@ -15,7 +15,6 @@ function makeCell(id: string, code = "print('hi')"): CellData {
15
15
  code,
16
16
  edited: false,
17
17
  lastCodeRun: null,
18
- lastExecutionTime: null,
19
18
  config: { hide_code: false, disabled: false, column: null },
20
19
  };
21
20
  }
@@ -32,7 +32,7 @@ import { getReadonlyCodeDisplay } from "@/core/cells/readonly-code-display";
32
32
  import { MarkdownLanguageAdapter } from "@/core/codemirror/language/languages/markdown";
33
33
  import { useResolvedMarimoConfig } from "@/core/config/config";
34
34
  import { CSSClasses } from "@/core/constants";
35
- import { kernelStateAtom } from "@/core/kernel/state";
35
+ import { runtimeStatusAtom, useCellExecution } from "@/core/executions";
36
36
  import { useNotebookCodeAvailable } from "@/core/meta/code-visibility";
37
37
  import { showCodeInRunModeAtom } from "@/core/meta/state";
38
38
  import {
@@ -73,7 +73,7 @@ const VerticalLayoutRenderer: React.FC<VerticalLayoutProps> = ({
73
73
  }) => {
74
74
  const { invisible } = useDelayVisibility(cells.length, mode);
75
75
  const kioskMode = useAtomValue(kioskModeAtom);
76
- const kernelState = useAtomValue(kernelStateAtom);
76
+ const runtimeStatus = useAtomValue(runtimeStatusAtom);
77
77
  const [userConfig] = useResolvedMarimoConfig();
78
78
  const showCodeInRunModePreference = useAtomValue(showCodeInRunModeAtom);
79
79
 
@@ -98,16 +98,11 @@ const VerticalLayoutRenderer: React.FC<VerticalLayoutProps> = ({
98
98
  cellId={cell.id}
99
99
  output={cell.output}
100
100
  consoleOutputs={cell.consoleOutputs}
101
- status={cell.status}
102
101
  code={cell.code}
103
102
  config={cell.config}
104
103
  cellOutputArea={userConfig.display.cell_output}
105
- stopped={cell.stopped}
106
104
  showCode={showCode && canShowCode}
107
- errored={cell.errored}
108
105
  mode={mode}
109
- runStartTimestamp={cell.runStartTimestamp}
110
- interrupted={cell.interrupted}
111
106
  staleInputs={cell.staleInputs}
112
107
  name={cell.name}
113
108
  kiosk={kioskMode}
@@ -134,8 +129,9 @@ const VerticalLayoutRenderer: React.FC<VerticalLayoutProps> = ({
134
129
  }
135
130
 
136
131
  if (cells.length === 0 && !invisible) {
137
- // If kernel is not yet instantiated, show loading state
138
- if (!kernelState.isInstantiated) {
132
+ // Until the host reports the runtime running, show loading state.
133
+ // A static notebook has no runtime to wait for.
134
+ if (runtimeStatus !== "running" && !isStaticNotebook()) {
139
135
  return (
140
136
  <div className="flex-1 flex flex-col items-center justify-center py-8">
141
137
  <Loader2Icon className="w-8 h-8 animate-spin text-muted-foreground" />
@@ -304,14 +300,7 @@ const ActionButtons: React.FC<{
304
300
 
305
301
  interface VerticalCellProps extends Pick<
306
302
  CellRuntimeState,
307
- | "output"
308
- | "consoleOutputs"
309
- | "status"
310
- | "stopped"
311
- | "errored"
312
- | "interrupted"
313
- | "staleInputs"
314
- | "runStartTimestamp"
303
+ "output" | "consoleOutputs" | "staleInputs"
315
304
  > {
316
305
  cellOutputArea: "above" | "below";
317
306
  cellId: CellId;
@@ -330,13 +319,8 @@ const VerticalCell = memo(
330
319
  consoleOutputs,
331
320
  cellOutputArea,
332
321
  cellId,
333
- status,
334
- stopped,
335
- errored,
336
322
  config,
337
- interrupted,
338
323
  staleInputs,
339
- runStartTimestamp,
340
324
  code,
341
325
  showCode,
342
326
  mode,
@@ -345,18 +329,13 @@ const VerticalCell = memo(
345
329
  showErrorTracebacks,
346
330
  }: VerticalCellProps) => {
347
331
  const cellRef = useRef<HTMLDivElement>(null);
332
+ const execution = useCellExecution(cellId);
333
+ const errored = execution.outcome === "error";
334
+ const interrupted = execution.outcome === "interrupted";
335
+ const stopped = execution.outcome === "skipped";
348
336
 
349
- const outputStale = outputIsStale(
350
- {
351
- status,
352
- output,
353
- interrupted,
354
- runStartTimestamp,
355
- staleInputs,
356
- },
357
- false,
358
- );
359
- const loading = outputIsLoading(status);
337
+ const outputStale = outputIsStale(execution, staleInputs, false);
338
+ const loading = outputIsLoading(execution.status);
360
339
 
361
340
  // Kiosk and not presenting
362
341
  const kioskFull = kiosk && mode !== "present";
@@ -2,6 +2,7 @@
2
2
 
3
3
  import { atom, useAtomValue } from "jotai";
4
4
  import { notebookAtom } from "@/core/cells/cells";
5
+ import { cellExecutionInputsAtom, cellExecutionView } from "@/core/executions";
5
6
  import { Banner } from "@/plugins/impl/common/error-banner";
6
7
  import { Logger } from "@/utils/Logger";
7
8
  import { Button } from "../ui/button";
@@ -11,12 +12,13 @@ import { DelayMount } from "../utils/delay-mount";
11
12
  // Atom to check if there is a cell with unresolved stdin
12
13
  const hasBlockingStdinAtom = atom((get) => {
13
14
  const notebook = get(notebookAtom);
15
+ const executions = get(cellExecutionInputsAtom);
14
16
 
15
17
  // Check each cell in order
16
18
  for (const cellId of notebook.cellIds) {
17
19
  // Check if the cell is idle and has unresolved stdin
18
20
  const runtime = notebook.cellRuntime[cellId];
19
- if (runtime.status === "idle") {
21
+ if (cellExecutionView(executions, cellId).status === "idle") {
20
22
  const hasUnresolvedStdin = runtime.consoleOutputs.some(
21
23
  (output) => output.channel === "stdin" && output.response === undefined,
22
24
  );
@@ -23,6 +23,7 @@ import { prepareCellCodeUpdate } from "@/core/codemirror/language/cell-code";
23
23
  import { getEditorCodeAsPython } from "@/core/codemirror/language/utils";
24
24
  import { useResolvedMarimoConfig } from "@/core/config/config";
25
25
  import { CSSClasses } from "@/core/constants";
26
+ import { cellExecutionInputsAtom, scratchStatus } from "@/core/executions";
26
27
  import { useRequestClient } from "@/core/network/requests";
27
28
  import type { CellConfig } from "@/core/network/types";
28
29
  import { LazyAnyLanguageCodeMirror } from "@/plugins/impl/code/LazyAnyLanguageCodeMirror";
@@ -67,7 +68,9 @@ export const ScratchPad: React.FC = () => {
67
68
  const cellId = SCRATCH_CELL_ID;
68
69
  const cellRuntime = notebookState.cellRuntime[cellId];
69
70
  const output = cellRuntime?.output;
70
- const status = cellRuntime?.status;
71
+ const status = scratchStatus(
72
+ useAtomValue(cellExecutionInputsAtom).executions,
73
+ );
71
74
  const consoleOutputs = cellRuntime?.consoleOutputs;
72
75
  const [code, setCode] = useAtom(scratchpadCodeAtom);
73
76
  const codeListener = useMemo(
@@ -2,6 +2,7 @@
2
2
 
3
3
  import { useDeleteCellCallback } from "@/components/editor/cell/useDeleteCell";
4
4
  import { outputIsStale } from "@/core/cells/cell";
5
+ import { useCellExecution } from "@/core/executions";
5
6
  import { useCellActions } from "@/core/cells/actions";
6
7
  import type { CellId } from "@/core/cells/ids";
7
8
  import { type CellColumnId, type Layout, useLayout } from "@/core/cells/layout";
@@ -627,6 +628,7 @@ const SlideThumbnailCard = ({
627
628
  ...props
628
629
  }: SlideThumbnailCardProps) => {
629
630
  const { width, height, scale } = dimensions;
631
+ const execution = useCellExecution(cell.id);
630
632
  const visual = isNoOutput ? NO_OUTPUT_VISUAL : getSlideTypeVisual(slideType);
631
633
  const isSkipped = isNoOutput || slideType === "skip";
632
634
 
@@ -675,9 +677,9 @@ const SlideThumbnailCard = ({
675
677
  ) : (
676
678
  <Slide
677
679
  cellId={cell.id}
678
- status={cell.status}
680
+ status={execution.status}
679
681
  output={cell.output}
680
- stale={outputIsStale(cell, false)}
682
+ stale={outputIsStale(execution, cell.staleInputs, false)}
681
683
  />
682
684
  )}
683
685
  </div>
@@ -20,6 +20,7 @@ import { Button } from "@/components/ui/button";
20
20
  import { useFullScreenElement } from "@/components/ui/fullscreen";
21
21
  import { Tooltip } from "@/components/ui/tooltip";
22
22
  import { outputIsStale } from "@/core/cells/cell";
23
+ import { useCellExecution } from "@/core/executions";
23
24
  import type { CellId } from "@/core/cells/ids";
24
25
  import type { RuntimeCell } from "@/core/cells/types";
25
26
  import type { RevealApi, RevealConfig } from "reveal.js";
@@ -351,16 +352,19 @@ function resolveSlideContentStyle(
351
352
  * different scheme than `HTMLCellId`) and its inner `OutputArea` uses
352
353
  * `display: contents`, which can't be targeted for background/border styling.
353
354
  */
354
- export const CellOutputBlock = ({ cell }: { cell: RuntimeCell }) => (
355
- <div className="flex flex-col" {...cellDomProps(cell.id, cell.name)}>
356
- <CellOutputSlide
357
- cellId={cell.id}
358
- status={cell.status}
359
- output={cell.output}
360
- stale={outputIsStale(cell, false)}
361
- />
362
- </div>
363
- );
355
+ export const CellOutputBlock = ({ cell }: { cell: RuntimeCell }) => {
356
+ const execution = useCellExecution(cell.id);
357
+ return (
358
+ <div className="flex flex-col" {...cellDomProps(cell.id, cell.name)}>
359
+ <CellOutputSlide
360
+ cellId={cell.id}
361
+ status={execution.status}
362
+ output={cell.output}
363
+ stale={outputIsStale(execution, cell.staleInputs, false)}
364
+ />
365
+ </div>
366
+ );
367
+ };
364
368
 
365
369
  const SubslideView = ({
366
370
  subslide,
@@ -23,6 +23,7 @@ import {
23
23
  } from "@/core/cells/utils";
24
24
  import type { CellData, CellRuntimeState } from "@/core/cells/types";
25
25
  import type { LanguageAdapterType } from "@/core/codemirror/language/types";
26
+ import { useCellExecution } from "@/core/executions";
26
27
  import { connectionAtom } from "@/core/network/connection";
27
28
  import { useTheme } from "@/theme/useTheme";
28
29
  import { cn } from "@/utils/cn";
@@ -62,21 +63,19 @@ export const SlideCellView = ({ cell }: { cell: RuntimeCell }) => {
62
63
 
63
64
  const cellOutputPosition = userConfig.display.cell_output;
64
65
  const hasOutput = cell.output != null;
66
+ const execution = useCellExecution(cell.id);
67
+ const errored = execution.outcome === "error";
68
+ const interrupted = execution.outcome === "interrupted";
69
+ const stopped = execution.outcome === "skipped";
65
70
 
66
- const uninstantiated = isUninstantiated({
67
- executionTime: cell.runElapsedTimeMs ?? cell.lastExecutionTime,
68
- status: cell.status,
69
- errored: cell.errored,
70
- interrupted: cell.interrupted,
71
- stopped: cell.stopped,
72
- });
71
+ const uninstantiated = isUninstantiated(execution);
73
72
 
74
73
  const needsRun = cellNeedsRun({
75
74
  edited: cell.edited,
76
- interrupted: cell.interrupted,
75
+ interrupted,
77
76
  staleInputs: cell.staleInputs,
78
77
  disabled: cell.config.disabled,
79
- status: cell.status,
78
+ blocked: execution.blocked,
80
79
  });
81
80
 
82
81
  const editorWrapperClassName = cn(
@@ -85,19 +84,19 @@ export const SlideCellView = ({ cell }: { cell: RuntimeCell }) => {
85
84
  "interactive",
86
85
  cellStatusClasses({
87
86
  needsRun,
88
- errored: cell.errored,
89
- stopped: cell.stopped,
87
+ errored,
88
+ stopped,
90
89
  disabled: cell.config.disabled,
91
- status: cell.status,
90
+ blocked: execution.blocked,
92
91
  }),
93
92
  );
94
93
 
95
94
  const output = (
96
95
  <CellOutputSlide
97
96
  cellId={cell.id}
98
- status={cell.status}
97
+ status={execution.status}
99
98
  output={cell.output}
100
- stale={outputIsStale(cell, false)}
99
+ stale={outputIsStale(execution, cell.staleInputs, false)}
101
100
  />
102
101
  );
103
102
 
@@ -105,14 +104,14 @@ export const SlideCellView = ({ cell }: { cell: RuntimeCell }) => {
105
104
  <div className="absolute top-1 right-2 z-10 flex items-center gap-1.5">
106
105
  <CellStatusComponent
107
106
  editing={true}
108
- status={cell.status}
107
+ status={execution.status}
109
108
  disabled={cell.config.disabled ?? false}
110
109
  staleInputs={cell.staleInputs}
111
110
  edited={cell.edited}
112
- interrupted={cell.interrupted}
113
- elapsedTime={cell.runElapsedTimeMs ?? cell.lastExecutionTime}
114
- runStartTimestamp={cell.runStartTimestamp}
115
- lastRunStartTimestamp={cell.lastRunStartTimestamp}
111
+ interrupted={interrupted}
112
+ elapsedTime={execution.duration}
113
+ startedAt={execution.startedAt}
114
+ blocked={execution.blocked}
116
115
  uninstantiated={uninstantiated}
117
116
  />
118
117
  <LanguageToggles
@@ -125,13 +124,17 @@ export const SlideCellView = ({ cell }: { cell: RuntimeCell }) => {
125
124
  <div className="flex items-center shadow-none gap-1">
126
125
  <RunButton
127
126
  edited={cell.edited}
128
- status={cell.status}
127
+ status={execution.status}
128
+ blocked={execution.blocked}
129
129
  needsRun={needsRun}
130
130
  connectionState={connection.state}
131
131
  config={cell.config}
132
132
  onClick={runCell}
133
133
  />
134
- <StopButton status={cell.status} connectionState={connection.state} />
134
+ <StopButton
135
+ status={execution.status}
136
+ connectionState={connection.state}
137
+ />
135
138
  </div>
136
139
  </div>
137
140
  );
@@ -148,7 +151,7 @@ export const SlideCellView = ({ cell }: { cell: RuntimeCell }) => {
148
151
  id={cell.id}
149
152
  code={cell.code}
150
153
  config={cell.config}
151
- status={cell.status}
154
+ status={execution.status}
152
155
  runCell={runCell}
153
156
  setEditorView={(ev) => {
154
157
  editorViewRef.current = ev;
@@ -188,15 +191,16 @@ export const SlideCellView = ({ cell }: { cell: RuntimeCell }) => {
188
191
  export const SlideCellReadOnlyView = ({ cell }: { cell: RuntimeCell }) => {
189
192
  const [userConfig] = useUserConfig();
190
193
  const cellOutputPosition = userConfig.display.cell_output;
194
+ const execution = useCellExecution(cell.id);
191
195
 
192
196
  const display = useMemo(() => getReadonlyCodeDisplay(cell.code), [cell.code]);
193
197
 
194
198
  const output = (
195
199
  <CellOutputSlide
196
200
  cellId={cell.id}
197
- status={cell.status}
201
+ status={execution.status}
198
202
  output={cell.output}
199
- stale={outputIsStale(cell, false)}
203
+ stale={outputIsStale(execution, cell.staleInputs, false)}
200
204
  />
201
205
  );
202
206
 
@@ -5,12 +5,11 @@ import { OutputArea } from "../editor/Output";
5
5
  import { memo } from "react";
6
6
  import type { CellId } from "@/core/cells/ids";
7
7
  import type { CellRuntimeState } from "@/core/cells/types";
8
+ import type { CellRunStatus } from "@/core/executions";
8
9
 
9
- interface SlideContentProps extends Pick<
10
- CellRuntimeState,
11
- "output" | "status"
12
- > {
10
+ interface SlideContentProps extends Pick<CellRuntimeState, "output"> {
13
11
  cellId: CellId;
12
+ status: CellRunStatus;
14
13
  stale: boolean;
15
14
  }
16
15
 
@@ -29,7 +29,7 @@ const VARIANT_CLASSES = {
29
29
  default:
30
30
  "bg-background border forced-colors:border-[CanvasText] forced-colors:bg-[Canvas] forced-colors:text-[CanvasText]",
31
31
  danger:
32
- "group destructive text-error border-destructive bg-(--red-1) shadow-md-solid shadow-error forced-colors:border-[CanvasText] forced-colors:bg-[Canvas] forced-colors:text-[CanvasText]",
32
+ "group destructive text-(--red-11) border-destructive bg-(--red-1) shadow-md-solid shadow-error forced-colors:border-[CanvasText] forced-colors:bg-[Canvas] forced-colors:text-[CanvasText]",
33
33
  } as const satisfies Record<string, string>;
34
34
 
35
35
  type ToastVariant = keyof typeof VARIANT_CLASSES;