@marimo-team/islands 0.25.3-dev275 → 0.25.3-dev279

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 (60) hide show
  1. package/dist/{ErrorBoundary-BuIXiuc5.js → ErrorBoundary-DmTMuDPR.js} +1 -1
  2. package/dist/{chat-ui-SZ6lSH52.js → chat-ui-v1Fdh0NA.js} +270 -270
  3. package/dist/{code-visibility-BEAPMrC-.js → code-visibility-Dw4-TXN0.js} +2 -2
  4. package/dist/{common-CEmzaoJ8.js → common-BXMFi4lr.js} +4947 -4943
  5. package/dist/{data-grid-overlay-editor-CUo25_W8.js → data-grid-overlay-editor-hZzwX7Ia.js} +1 -1
  6. package/dist/{error-entries-B-1yUdcH.js → error-entries-C1S-Rmyt.js} +545 -535
  7. package/dist/{feedback-button-BqiR7zMO.js → feedback-button-6Ui2TDLR.js} +5 -5
  8. package/dist/{glide-data-editor-B7dguvqk.js → glide-data-editor-PZNlrSDI.js} +3 -3
  9. package/dist/{globals-CYykXfGI.js → globals-DX6FPZYq.js} +1 -1
  10. package/dist/{html-to-image-DC_pmZLs.js → html-to-image-CqGUd58T.js} +14452 -14452
  11. package/dist/main.js +6031 -6036
  12. package/dist/{number-overlay-editor-C4u7SJAJ.js → number-overlay-editor-D0CsL3_R.js} +1 -1
  13. package/dist/{process-output-DYu84VfZ.js → process-output-DskX9jLa.js} +2 -2
  14. package/dist/{reveal-component-DGi-irHV.js → reveal-component-D7xeI1QR.js} +906 -906
  15. package/package.json +1 -1
  16. package/src/__mocks__/executions.ts +4 -2
  17. package/src/__mocks__/notebook.ts +0 -2
  18. package/src/__tests__/CellStatus.test.tsx +6 -6
  19. package/src/components/editor/__tests__/data-attributes.test.tsx +0 -2
  20. package/src/components/editor/__tests__/output-persistence.test.tsx +20 -5
  21. package/src/components/editor/cell/CellStatus.tsx +6 -5
  22. package/src/components/editor/cell/__tests__/useRunCells.test.tsx +169 -0
  23. package/src/components/editor/cell/collapse.tsx +3 -4
  24. package/src/components/editor/cell/useRunCells.ts +32 -3
  25. package/src/components/editor/errors/__tests__/send-error-report-button.test.tsx +2 -3
  26. package/src/components/editor/notebook-cell.tsx +23 -37
  27. package/src/components/editor/renderers/grid-layout/grid-layout.tsx +4 -10
  28. package/src/components/editor/renderers/slides-layout/__tests__/plugin.test.ts +0 -2
  29. package/src/components/editor/renderers/vertical-layout/vertical-layout.tsx +8 -5
  30. package/src/components/slides/minimap.tsx +3 -2
  31. package/src/components/slides/reveal-component.tsx +3 -2
  32. package/src/components/slides/slide-cell-view.tsx +8 -8
  33. package/src/core/cells/__tests__/__snapshots__/cells.test.ts.snap +0 -101
  34. package/src/core/cells/__tests__/actions.test.ts +0 -1
  35. package/src/core/cells/__tests__/cell.test.ts +81 -17
  36. package/src/core/cells/__tests__/cells.test.ts +0 -100
  37. package/src/core/cells/__tests__/document.test.ts +2 -8
  38. package/src/core/cells/__tests__/utils.test.ts +93 -24
  39. package/src/core/cells/actions.ts +0 -1
  40. package/src/core/cells/cell.ts +37 -14
  41. package/src/core/cells/cells.ts +10 -99
  42. package/src/core/cells/document.ts +2 -13
  43. package/src/core/cells/types.ts +0 -23
  44. package/src/core/cells/utils.ts +44 -17
  45. package/src/core/codemirror/cells/extensions.ts +0 -14
  46. package/src/core/errors/__tests__/error-entries.test.ts +40 -1
  47. package/src/core/errors/error-entries.ts +2 -3
  48. package/src/core/executions/__tests__/freshness.test.ts +420 -0
  49. package/src/core/executions/__tests__/hooks.test.tsx +106 -0
  50. package/src/core/executions/atoms.ts +22 -0
  51. package/src/core/executions/freshness.ts +164 -0
  52. package/src/core/executions/hooks.ts +17 -1
  53. package/src/core/executions/index.ts +3 -1
  54. package/src/core/islands/bootstrap.ts +0 -1
  55. package/src/core/kernel/handlers.ts +0 -4
  56. package/src/core/session/useNotebookSession.tsx +2 -7
  57. package/src/stories/cell-status.stories.tsx +12 -14
  58. package/src/stories/cell.stories.tsx +44 -10
  59. package/src/stories/layout/vertical/one-column.stories.tsx +0 -10
  60. package/src/components/editor/cell/__tests__/useRunCells.test.ts +0 -45
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marimo-team/islands",
3
- "version": "0.25.3-dev275",
3
+ "version": "0.25.3-dev279",
4
4
  "main": "dist/main.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -8,6 +8,7 @@ import type { CellExecutionInputs } from "@/core/executions";
8
8
  import {
9
9
  ConnectionState,
10
10
  type ConnectionStatus,
11
+ type Document,
11
12
  type Execution,
12
13
  type Executions,
13
14
  type NotebookReplica,
@@ -162,16 +163,16 @@ export const MockExecutions = {
162
163
  };
163
164
  },
164
165
 
165
- /** Make the store's active replica report `records` and `runtime`. */
166
+ /** Make the store's active replica report `records`, `runtime`, and `document`. */
166
167
  seed(
167
168
  store: Store,
168
169
  records: Protocol.Execution[],
169
170
  runtime: Protocol.Runtime | null = null,
171
+ document: Document | null = null,
170
172
  ) {
171
173
  const current = store.get(activeNotebookReplicaAtom);
172
174
  const replica = {
173
175
  connectionAtom: atom<ConnectionStatus>({ state: ConnectionState.OPEN }),
174
- documentAtom: atom(null),
175
176
  backendAtom: atom(null),
176
177
  attachmentsAtom: atom([]),
177
178
  connect: () => () => undefined,
@@ -185,6 +186,7 @@ export const MockExecutions = {
185
186
  operations: [],
186
187
  updated_at: null,
187
188
  }),
189
+ documentAtom: atom<Document | null>(document),
188
190
  runtimeAtom: atom(runtime),
189
191
  executionsAtom: atom(mirror(records)),
190
192
  resultsAtom: atom(results(records)),
@@ -39,8 +39,6 @@ export const MockNotebook = {
39
39
  expand_output: false,
40
40
  ...data.config,
41
41
  },
42
- edited: false,
43
- lastCodeRun: null,
44
42
  serializedEditorState: null,
45
43
  ...data,
46
44
  })),
@@ -3,6 +3,7 @@
3
3
  import { render } from "@testing-library/react";
4
4
  import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
5
5
  import { TooltipProvider } from "@/components/ui/tooltip";
6
+ import type { CellFreshness } from "@/core/executions";
6
7
  import { formatElapsedTime, type Milliseconds } from "@/utils/time";
7
8
  import {
8
9
  CellStatusComponent,
@@ -70,9 +71,8 @@ describe("CellStatusComponent", () => {
70
71
  // Base props that will be modified for different test cases
71
72
  const baseProps = {
72
73
  editing: true,
73
- edited: false,
74
74
  disabled: false,
75
- staleInputs: false,
75
+ freshness: { sourceChanged: false, inputsChanged: false } as CellFreshness,
76
76
  status: "idle" as const,
77
77
  interrupted: false,
78
78
  elapsedTime: null,
@@ -94,7 +94,7 @@ describe("CellStatusComponent", () => {
94
94
  const props = {
95
95
  ...baseProps,
96
96
  disabled: true,
97
- staleInputs: true,
97
+ freshness: { sourceChanged: false, inputsChanged: true } as CellFreshness,
98
98
  startedAt: 1_704_096_000_000 as Milliseconds, // Jan 1, 2024 12:00:00
99
99
  };
100
100
 
@@ -140,7 +140,7 @@ describe("CellStatusComponent", () => {
140
140
  const props = {
141
141
  ...baseProps,
142
142
  blocked: true,
143
- staleInputs: true,
143
+ freshness: { sourceChanged: false, inputsChanged: true } as CellFreshness,
144
144
  startedAt: 1_704_096_000_000 as Milliseconds,
145
145
  };
146
146
 
@@ -215,7 +215,7 @@ describe("CellStatusComponent", () => {
215
215
  test("renders edited state", () => {
216
216
  const props = {
217
217
  ...baseProps,
218
- edited: true,
218
+ freshness: { sourceChanged: true, inputsChanged: false } as CellFreshness,
219
219
  elapsedTime: 1500 as Milliseconds,
220
220
  startedAt: 1_704_096_000_000 as Milliseconds,
221
221
  };
@@ -231,7 +231,7 @@ describe("CellStatusComponent", () => {
231
231
  test("renders stale inputs state", () => {
232
232
  const props = {
233
233
  ...baseProps,
234
- staleInputs: true,
234
+ freshness: { sourceChanged: false, inputsChanged: true } as CellFreshness,
235
235
  elapsedTime: 1500 as Milliseconds,
236
236
  startedAt: 1_704_096_000_000 as Milliseconds,
237
237
  };
@@ -93,7 +93,6 @@ describe("Cell data attributes", () => {
93
93
  [cid]: {
94
94
  code: "",
95
95
  name: cellName,
96
- edited: false,
97
96
  config: {
98
97
  disabled: false,
99
98
  hide_code: false,
@@ -106,7 +105,6 @@ describe("Cell data attributes", () => {
106
105
  notebook.cellRuntime[cid] = createCellRuntimeState({
107
106
  output: null,
108
107
  consoleOutputs: [],
109
- staleInputs: false,
110
108
  debuggerActive: false,
111
109
  outline: null,
112
110
  });
@@ -11,6 +11,11 @@ import { cellId } from "@/__tests__/branded";
11
11
  import { TooltipProvider } from "@/components/ui/tooltip";
12
12
  import { notebookAtom } from "@/core/cells/cells";
13
13
  import { DocumentProvider } from "@/core/notebook/document";
14
+ import {
15
+ cell,
16
+ document as documentOf,
17
+ withCells,
18
+ } from "@/core/notebook/document/__tests__/fixtures";
14
19
  import type { CellRuntimeState } from "@/core/cells/types";
15
20
  import { createCellRuntimeState } from "@/core/cells/types";
16
21
  import { defaultUserConfig } from "@/core/config/config-schema";
@@ -41,7 +46,6 @@ function seedNotebook(
41
46
  [cid]: {
42
47
  code: "1 + 1",
43
48
  name: "test_cell",
44
- edited: false,
45
49
  config: {
46
50
  disabled: false,
47
51
  hide_code: false,
@@ -188,11 +192,22 @@ describe("output persistence across mode changes", () => {
188
192
 
189
193
  it("does not dim edited-but-not-run outputs as stale while presenting", () => {
190
194
  const { store, wrapper } = createTestWrapper();
195
+ // The host holds newer source than the cell last ran with
196
+ MockExecutions.seed(
197
+ store,
198
+ [MockExecutions.completed(cid, { code_fingerprint: "ran" })],
199
+ null,
200
+ withCells(
201
+ documentOf(),
202
+ {
203
+ c1: null,
204
+ c2: null,
205
+ [cid]: cell(cid, "1 + 1", { code_fingerprint: "edited" }),
206
+ },
207
+ [cid],
208
+ ),
209
+ );
191
210
  seedNotebook(store);
192
- // Mark the cell as edited without re-running it
193
- const notebook = store.get(notebookAtom);
194
- notebook.cellData[cid] = { ...notebook.cellData[cid], edited: true };
195
- store.set(notebookAtom, { ...notebook });
196
211
 
197
212
  const { container, rerender } = render(renderCell("edit"), { wrapper });
198
213
  expect(container.querySelector(".marimo-output-stale")).toBeTruthy();
@@ -7,7 +7,7 @@ import {
7
7
  } from "lucide-react";
8
8
  import { useDateFormatter } from "react-aria";
9
9
  import { MultiIcon } from "@/components/icons/multi-icon";
10
- import type { CellRunStatus } from "@/core/executions";
10
+ import type { CellFreshness, CellRunStatus } from "@/core/executions";
11
11
  import { Logger } from "@/utils/Logger";
12
12
  import { useElapsedTime } from "../../../hooks/useElapsedTime";
13
13
  import { Tooltip } from "../../ui/tooltip";
@@ -18,11 +18,11 @@ import { formatElapsedTime, type Milliseconds, Time } from "@/utils/time";
18
18
 
19
19
  export interface CellStatusComponentProps {
20
20
  editing: boolean;
21
- edited: boolean;
22
21
  disabled: boolean;
23
22
  /** Whether a cell it depends on is disabled. */
24
23
  blocked: boolean;
25
- staleInputs: boolean;
24
+ /** Whether the cell's result is current. */
25
+ freshness: CellFreshness;
26
26
  status: CellRunStatus;
27
27
  /** Whether the cell's last run was interrupted. */
28
28
  interrupted: boolean;
@@ -38,8 +38,7 @@ export const CellStatusComponent: React.FC<CellStatusComponentProps> = ({
38
38
  status,
39
39
  disabled,
40
40
  blocked,
41
- staleInputs,
42
- edited,
41
+ freshness,
43
42
  interrupted,
44
43
  elapsedTime,
45
44
  startedAt,
@@ -48,6 +47,8 @@ export const CellStatusComponent: React.FC<CellStatusComponentProps> = ({
48
47
  if (!editing) {
49
48
  return null;
50
49
  }
50
+ const edited = freshness.sourceChanged;
51
+ const staleInputs = freshness.inputsChanged;
51
52
 
52
53
  const lastRanTime = startedAt ? (
53
54
  <LastRanTime lastRanTime={startedAt} />
@@ -0,0 +1,169 @@
1
+ /* Copyright 2026 Marimo. All rights reserved. */
2
+
3
+ import { act, renderHook } from "@testing-library/react";
4
+ import { Provider } from "jotai";
5
+ import type { ReactNode } from "react";
6
+ import { afterEach, describe, expect, it, vi } from "vitest";
7
+ import { MockExecutions } from "@/__mocks__/executions";
8
+ import { MockNotebook } from "@/__mocks__/notebook";
9
+ import { MockRequestClient } from "@/__mocks__/requests";
10
+ import { cellId } from "@/__tests__/branded";
11
+ import { notebookAtom } from "@/core/cells/cells";
12
+ import {
13
+ cellExecutionInputsAtom,
14
+ cellExecutionView,
15
+ notebookQueuedOrRunningCountAtom,
16
+ } from "@/core/executions";
17
+ import { requestClientAtom } from "@/core/network/requests";
18
+ import type { DocumentModel } from "@/core/notebook/document";
19
+ import {
20
+ cell,
21
+ document as documentOf,
22
+ withCells,
23
+ } from "@/core/notebook/document/__tests__/fixtures";
24
+ import { activeDocumentModelAtom } from "@/core/session/active-notebook";
25
+ import { store } from "@/core/state/jotai";
26
+ import { runCells, useRunStaleCells } from "../useRunCells";
27
+
28
+ const ENABLED = cellId("enabled");
29
+ const DISABLED = cellId("disabled");
30
+
31
+ describe("runCells", () => {
32
+ it("sends a disabled cell to the kernel without reading it as queued", async () => {
33
+ MockExecutions.seed(store, []);
34
+ const notebook = MockNotebook.notebookState({
35
+ cellData: {
36
+ [ENABLED]: { code: "x = 1" },
37
+ [DISABLED]: { code: "y = 2", config: { disabled: true } },
38
+ },
39
+ });
40
+ const sendRun = vi.fn(async () => null);
41
+
42
+ await runCells({
43
+ cellIds: [ENABLED, DISABLED],
44
+ sendRun,
45
+ prepareForRun: vi.fn(),
46
+ notebook,
47
+ });
48
+
49
+ expect(sendRun).toHaveBeenCalledWith({
50
+ cellIds: [ENABLED, DISABLED],
51
+ codes: ["x = 1", "y = 2"],
52
+ });
53
+ const inputs = store.get(cellExecutionInputsAtom);
54
+ expect(cellExecutionView(inputs, ENABLED).status).toBe("queued");
55
+ expect(cellExecutionView(inputs, DISABLED).status).toBe("idle");
56
+ expect(store.get(notebookQueuedOrRunningCountAtom)).toBe(1);
57
+ });
58
+ });
59
+
60
+ describe("useRunStaleCells", () => {
61
+ const C1 = cellId("c1");
62
+ const C2 = cellId("c2");
63
+
64
+ afterEach(() => {
65
+ store.set(activeDocumentModelAtom, null);
66
+ });
67
+
68
+ it("flushes pending edits before choosing the stale cells", async () => {
69
+ const document = documentOf();
70
+ const replica = MockExecutions.seed(
71
+ store,
72
+ [
73
+ MockExecutions.completed(C1, { code_fingerprint: "c1-hash" }),
74
+ MockExecutions.completed(C2, { code_fingerprint: "c2-hash" }),
75
+ ],
76
+ null,
77
+ document,
78
+ );
79
+ store.set(
80
+ notebookAtom,
81
+ MockNotebook.notebookState({
82
+ cellData: { [C1]: { code: "x = 2" }, [C2]: { code: "y = 2" } },
83
+ }),
84
+ );
85
+ const client = MockRequestClient.create();
86
+ store.set(requestClientAtom, client);
87
+ // The edit to c1 is still in flight: the host confirms it on flush.
88
+ const flush = vi.fn(async () => {
89
+ await new Promise((resolve) => setTimeout(resolve, 0));
90
+ store.set(
91
+ replica.documentAtom,
92
+ withCells(document, {
93
+ [C1]: cell(C1, "x = 2", { code_fingerprint: "c1-hash-2" }),
94
+ }),
95
+ );
96
+ });
97
+ store.set(activeDocumentModelAtom, { flush } as unknown as DocumentModel);
98
+ const wrapper = ({ children }: { children: ReactNode }) => (
99
+ <Provider store={store}>{children}</Provider>
100
+ );
101
+ const { result } = renderHook(useRunStaleCells, { wrapper });
102
+
103
+ await act(() => result.current());
104
+
105
+ expect(flush).toHaveBeenCalledOnce();
106
+ expect(client.sendRun).toHaveBeenCalledWith({
107
+ cellIds: [C1],
108
+ codes: ["x = 2"],
109
+ });
110
+ });
111
+
112
+ it("does nothing when the notebook changed while the flush was pending", async () => {
113
+ MockExecutions.seed(
114
+ store,
115
+ [MockExecutions.completed(C1, { code_fingerprint: "stale" })],
116
+ null,
117
+ documentOf(),
118
+ );
119
+ store.set(
120
+ notebookAtom,
121
+ MockNotebook.notebookState({ cellData: { [C1]: { code: "x = 1" } } }),
122
+ );
123
+ const client = MockRequestClient.create();
124
+ store.set(requestClientAtom, client);
125
+ const flush = vi.fn(async () => {
126
+ store.set(activeDocumentModelAtom, null);
127
+ throw new Error("aborted");
128
+ });
129
+ store.set(activeDocumentModelAtom, { flush } as unknown as DocumentModel);
130
+ const wrapper = ({ children }: { children: ReactNode }) => (
131
+ <Provider store={store}>{children}</Provider>
132
+ );
133
+ const { result } = renderHook(useRunStaleCells, { wrapper });
134
+
135
+ await act(() => result.current());
136
+
137
+ expect(client.sendRun).not.toHaveBeenCalled();
138
+ });
139
+
140
+ it("still runs what is stale when the flush fails", async () => {
141
+ MockExecutions.seed(
142
+ store,
143
+ [MockExecutions.completed(C1, { code_fingerprint: "stale" })],
144
+ null,
145
+ documentOf(),
146
+ );
147
+ store.set(
148
+ notebookAtom,
149
+ MockNotebook.notebookState({ cellData: { [C1]: { code: "x = 1" } } }),
150
+ );
151
+ const client = MockRequestClient.create();
152
+ store.set(requestClientAtom, client);
153
+ const flush = vi.fn(async () => {
154
+ throw new Error("offline");
155
+ });
156
+ store.set(activeDocumentModelAtom, { flush } as unknown as DocumentModel);
157
+ const wrapper = ({ children }: { children: ReactNode }) => (
158
+ <Provider store={store}>{children}</Provider>
159
+ );
160
+ const { result } = renderHook(useRunStaleCells, { wrapper });
161
+
162
+ await act(() => result.current());
163
+
164
+ expect(client.sendRun).toHaveBeenCalledWith({
165
+ cellIds: [C1],
166
+ codes: ["x = 1"],
167
+ });
168
+ });
169
+ });
@@ -14,11 +14,10 @@ import { memo } from "react";
14
14
  import { Toolbar } from "@/components/layout/toolbar";
15
15
  import { Button } from "@/components/ui/button";
16
16
  import { Tooltip } from "@/components/ui/tooltip";
17
- import { useNotebook } from "@/core/cells/cells";
18
17
  import { columnOf, useLayout } from "@/core/cells/layout";
19
18
  import type { CellId } from "@/core/cells/ids";
20
19
  import { getDescendantsStatus } from "@/core/cells/utils";
21
- import { cellExecutionInputsAtom } from "@/core/executions";
20
+ import { cellExecutionInputsAtom, cellFreshnessAtom } from "@/core/executions";
22
21
  import { cn } from "@/utils/cn";
23
22
 
24
23
  interface Props {
@@ -66,12 +65,12 @@ export const CollapsedCellBanner: React.FC<{
66
65
  cellId: CellId;
67
66
  count: number;
68
67
  }> = memo(({ onClick, count, cellId }) => {
69
- const notebook = useNotebook();
70
68
  const executions = useAtomValue(cellExecutionInputsAtom);
69
+ const freshness = useAtomValue(cellFreshnessAtom);
71
70
  const layout = useLayout();
72
71
  const states = getDescendantsStatus(
73
- notebook,
74
72
  executions,
73
+ freshness,
75
74
  columnOf(layout, cellId).folds.get(cellId) ?? [],
76
75
  );
77
76
 
@@ -3,12 +3,14 @@
3
3
  import { closeCompletion } from "@codemirror/autocomplete";
4
4
  import { atom, useSetAtom } from "jotai";
5
5
  import useEvent from "react-use-event-hook";
6
+ import { toast } from "@/components/ui/use-toast";
6
7
  import { getNotebook, type NotebookState } from "@/core/cells/cells";
7
8
  import { useCellActions } from "@/core/cells/actions";
8
9
  import type { CellId } from "@/core/cells/ids";
9
10
  import { enabledCellIds, staleCellIds } from "@/core/cells/utils";
10
11
  import {
11
12
  cellExecutionInputsAtom,
13
+ cellFreshnessAtom,
12
14
  submitCells,
13
15
  withdrawCells,
14
16
  } from "@/core/executions";
@@ -16,6 +18,7 @@ import { getCurrentLanguageAdapter } from "@/core/codemirror/language/commands";
16
18
  import { getEditorCodeAsPython } from "@/core/codemirror/language/utils";
17
19
  import { useRequestClient } from "@/core/network/requests";
18
20
  import type { ExecuteCellsRequest } from "@/core/network/types";
21
+ import { activeDocumentModelAtom } from "@/core/session/active-notebook";
19
22
  import { store } from "@/core/state/jotai";
20
23
  import { Logger } from "@/utils/Logger";
21
24
 
@@ -26,9 +29,35 @@ export const hasRunAnyCellAtom = atom<boolean>(false);
26
29
  */
27
30
  export function useRunStaleCells() {
28
31
  const runCells = useRunCells();
29
- const runStaleCells = useEvent(() =>
30
- runCells(staleCellIds(getNotebook(), store.get(cellExecutionInputsAtom))),
31
- );
32
+ const runStaleCells = useEvent(async () => {
33
+ // Freshness reads the confirmed document, so an edit still in flight
34
+ // reaches the host before the stale cells are chosen.
35
+ const model = store.get(activeDocumentModelAtom);
36
+ try {
37
+ await model?.flush();
38
+ } catch (error) {
39
+ if (store.get(activeDocumentModelAtom) !== model) {
40
+ return;
41
+ }
42
+ Logger.warn("Running stale cells with unsynced edits", error);
43
+ toast({
44
+ title: "Edits not yet synced",
45
+ description: "Stale cells were chosen from the last synced source.",
46
+ variant: "danger",
47
+ });
48
+ }
49
+ // The request was for the notebook that was open when it was made.
50
+ if (store.get(activeDocumentModelAtom) !== model) {
51
+ return;
52
+ }
53
+ return runCells(
54
+ staleCellIds(
55
+ getNotebook(),
56
+ store.get(cellExecutionInputsAtom),
57
+ store.get(cellFreshnessAtom),
58
+ ),
59
+ );
60
+ });
32
61
  return runStaleCells;
33
62
  }
34
63
 
@@ -418,7 +418,7 @@ describe("SendErrorReportButton", () => {
418
418
  store.set(
419
419
  notebookAtom,
420
420
  MockNotebook.notebookState({
421
- cellData: { [CELL_ID]: { code: CODE, lastCodeRun: CODE } },
421
+ cellData: { [CELL_ID]: { code: CODE } },
422
422
  cellRuntime: { [CELL_ID]: { output } },
423
423
  }),
424
424
  );
@@ -429,7 +429,6 @@ describe("SendErrorReportButton", () => {
429
429
  [CELL_ID]: {
430
430
  ...state.cellData[CELL_ID],
431
431
  code: "print('edited')",
432
- edited: true,
433
432
  },
434
433
  },
435
434
  }));
@@ -466,7 +465,7 @@ describe("SendErrorReportButton", () => {
466
465
  notebookAtom,
467
466
  MockNotebook.notebookState({
468
467
  cellData: {
469
- [CELL_ID]: { code: "unrelated edit", lastCodeRun: "older run" },
468
+ [CELL_ID]: { code: "unrelated edit" },
470
469
  },
471
470
  cellRuntime: {
472
471
  [CELL_ID]: {