@marimo-team/frontend 0.21.2-dev39 → 0.21.2-dev40

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 (78) hide show
  1. package/dist/assets/{edit-page-OLDApdB5.js → edit-page-Cqvk7zWH.js} +7 -7
  2. package/dist/assets/{index-DZVnuqxZ.js → index-BSzIstPK.js} +2 -2
  3. package/dist/assets/{panels-LFK8M8Jo.js → panels-B2DAaT1E.js} +1 -1
  4. package/dist/assets/{run-page-B-zpKjX2.js → run-page-DMpRvHgf.js} +1 -1
  5. package/dist/assets/tracing-BxcUfhUv.js +1 -0
  6. package/dist/assets/{tracing-panel-CKmy1CaA.js → tracing-panel-DK4YfdoZ.js} +2 -2
  7. package/dist/index.html +1 -1
  8. package/package.json +1 -1
  9. package/src/__mocks__/notebook.ts +9 -9
  10. package/src/__tests__/branded.ts +20 -0
  11. package/src/components/data-table/charts/__tests__/storage.test.ts +7 -7
  12. package/src/components/editor/__tests__/data-attributes.test.tsx +8 -8
  13. package/src/components/editor/ai/__tests__/completion-utils.test.ts +15 -15
  14. package/src/components/editor/navigation/__tests__/clipboard.test.ts +2 -2
  15. package/src/components/editor/navigation/__tests__/selection.test.ts +7 -6
  16. package/src/components/editor/navigation/__tests__/state.test.ts +8 -7
  17. package/src/components/editor/output/MarimoErrorOutput.tsx +7 -7
  18. package/src/components/editor/output/__tests__/traceback.test.tsx +4 -4
  19. package/src/components/editor/output/console/__tests__/ConsoleOutput.test.tsx +4 -4
  20. package/src/components/editor/renderers/vertical-layout/useFocusFirstEditor.ts +8 -1
  21. package/src/components/storage/storage-inspector.tsx +1 -2
  22. package/src/components/tracing/tracing.tsx +3 -1
  23. package/src/core/ai/__tests__/staged-cells.test.ts +9 -8
  24. package/src/core/ai/context/providers/__tests__/cell-output.test.ts +31 -31
  25. package/src/core/ai/context/providers/__tests__/datasource.test.ts +3 -3
  26. package/src/core/ai/context/providers/__tests__/tables.test.ts +3 -2
  27. package/src/core/ai/context/providers/__tests__/variable.test.ts +84 -63
  28. package/src/core/ai/tools/__tests__/edit-notebook-tool.test.ts +10 -9
  29. package/src/core/ai/tools/__tests__/run-cells-tool.test.ts +6 -6
  30. package/src/core/ai/tools/edit-notebook-tool.ts +3 -3
  31. package/src/core/cells/__tests__/add-missing-import.test.ts +3 -3
  32. package/src/core/cells/__tests__/cells.test.ts +192 -135
  33. package/src/core/cells/__tests__/focus.test.ts +5 -4
  34. package/src/core/cells/__tests__/logs.test.ts +13 -12
  35. package/src/core/cells/__tests__/pending-delete-service.test.tsx +3 -3
  36. package/src/core/cells/__tests__/runs.test.ts +22 -21
  37. package/src/core/cells/__tests__/scrollCellIntoView.test.ts +8 -7
  38. package/src/core/cells/__tests__/session.test.ts +23 -22
  39. package/src/core/cells/cells.ts +1 -1
  40. package/src/core/cells/ids.ts +5 -5
  41. package/src/core/cells/logs.ts +2 -2
  42. package/src/core/cells/runs.ts +6 -8
  43. package/src/core/codemirror/__tests__/format.test.ts +34 -36
  44. package/src/core/codemirror/__tests__/setup.test.ts +2 -2
  45. package/src/core/codemirror/cells/__tests__/traceback-decorations.test.ts +33 -32
  46. package/src/core/codemirror/copilot/__tests__/getCodes.test.ts +12 -13
  47. package/src/core/codemirror/language/__tests__/utils.test.ts +3 -3
  48. package/src/core/codemirror/language/embedded/__tests__/embedded-python.test.ts +7 -8
  49. package/src/core/codemirror/lsp/__tests__/notebook-lsp.test.ts +4 -3
  50. package/src/core/codemirror/reactive-references/__tests__/analyzer.test.ts +7 -6
  51. package/src/core/codemirror/reactive-references/analyzer.ts +2 -2
  52. package/src/core/datasets/__tests__/data-source.test.ts +5 -6
  53. package/src/core/datasets/state.ts +1 -1
  54. package/src/core/errors/__tests__/errors.test.ts +2 -1
  55. package/src/core/export/__tests__/hooks.test.ts +37 -36
  56. package/src/core/islands/main.ts +2 -7
  57. package/src/core/kernel/__tests__/handlers.test.ts +5 -4
  58. package/src/core/kernel/handlers.ts +7 -4
  59. package/src/core/network/DeferredRequestRegistry.ts +2 -2
  60. package/src/core/network/__tests__/CachingRequestRegistry.test.ts +9 -10
  61. package/src/core/network/__tests__/DeferredRequestRegistry.test.ts +4 -6
  62. package/src/core/static/__tests__/virtual-file-tracker.test.ts +8 -8
  63. package/src/core/static/virtual-file-tracker.ts +1 -1
  64. package/src/core/storage/__tests__/state.test.ts +31 -21
  65. package/src/core/storage/state.ts +1 -1
  66. package/src/core/variables/__tests__/state.test.ts +6 -6
  67. package/src/core/variables/types.ts +2 -2
  68. package/src/core/wasm/__tests__/state.test.ts +8 -8
  69. package/src/core/websocket/useMarimoKernelConnection.tsx +12 -15
  70. package/src/plugins/impl/anywidget/model.ts +1 -2
  71. package/src/stories/cell.stories.tsx +8 -8
  72. package/src/stories/layout/vertical/one-column.stories.tsx +9 -8
  73. package/src/stories/log-viewer.stories.tsx +8 -8
  74. package/src/stories/variables.stories.tsx +2 -2
  75. package/src/utils/__tests__/download.test.tsx +19 -18
  76. package/src/utils/json/base64.ts +3 -3
  77. package/src/utils/traceback.ts +5 -3
  78. package/dist/assets/tracing-QGIu3SN5.js +0 -1
@@ -1,5 +1,6 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
  import { beforeEach, describe, expect, it, type Mock, vi } from "vitest";
3
+ import { variableName } from "@/__tests__/branded";
3
4
  import { getCodes } from "@/core/codemirror/copilot/getCodes";
4
5
  import { dataSourceConnectionsAtom } from "@/core/datasets/data-source-connections";
5
6
  import { DUCKDB_ENGINE } from "@/core/datasets/engines";
@@ -7,7 +8,6 @@ import { datasetsAtom } from "@/core/datasets/state";
7
8
  import type { DatasetsState } from "@/core/datasets/types";
8
9
  import { store } from "@/core/state/jotai";
9
10
  import { variablesAtom } from "@/core/variables/state";
10
- import type { Variable, VariableName } from "@/core/variables/types";
11
11
  import { codeToCells, getAICompletionBody } from "../completion-utils";
12
12
 
13
13
  // Mock getCodes function
@@ -205,16 +205,16 @@ describe("getAICompletionBody", () => {
205
205
 
206
206
  it("should return the correct completion body with mentioned variables", () => {
207
207
  // Set up test data in the Jotai store
208
- const testVariables: Record<VariableName, Variable> = {
209
- ["var1" as VariableName]: {
210
- name: "var1" as VariableName,
208
+ const testVariables = {
209
+ [variableName("var1")]: {
210
+ name: variableName("var1"),
211
211
  value: "string value",
212
212
  dataType: "string",
213
213
  declaredBy: [],
214
214
  usedBy: [],
215
215
  },
216
- ["var2" as VariableName]: {
217
- name: "var2" as VariableName,
216
+ [variableName("var2")]: {
217
+ name: variableName("var2"),
218
218
  value: "42",
219
219
  dataType: "number",
220
220
  declaredBy: [],
@@ -253,9 +253,9 @@ describe("getAICompletionBody", () => {
253
253
  ];
254
254
  store.set(datasetsAtom, { tables: testDatasets } as DatasetsState);
255
255
 
256
- const testVariables: Record<VariableName, Variable> = {
257
- ["var1" as VariableName]: {
258
- name: "var1" as VariableName,
256
+ const testVariables = {
257
+ [variableName("var1")]: {
258
+ name: variableName("var1"),
259
259
  value: "string value",
260
260
  dataType: "string",
261
261
  declaredBy: [],
@@ -285,9 +285,9 @@ describe("getAICompletionBody", () => {
285
285
 
286
286
  it("should handle non-existent variables", () => {
287
287
  // Set up test data in the Jotai store
288
- const testVariables: Record<VariableName, Variable> = {
289
- ["existingVar" as VariableName]: {
290
- name: "existingVar" as VariableName,
288
+ const testVariables = {
289
+ [variableName("existingVar")]: {
290
+ name: variableName("existingVar"),
291
291
  value: "string value",
292
292
  dataType: "string",
293
293
  declaredBy: [],
@@ -322,9 +322,9 @@ describe("getAICompletionBody", () => {
322
322
  ];
323
323
  store.set(datasetsAtom, { tables: testDatasets } as DatasetsState);
324
324
 
325
- const testVariables: Record<VariableName, Variable> = {
326
- ["conflict" as VariableName]: {
327
- name: "conflict" as VariableName,
325
+ const testVariables = {
326
+ [variableName("conflict")]: {
327
+ name: variableName("conflict"),
328
328
  value: "string value",
329
329
  dataType: "string",
330
330
  declaredBy: [],
@@ -4,8 +4,8 @@
4
4
  import { act, renderHook } from "@testing-library/react";
5
5
  import { beforeEach, describe, expect, it, vi } from "vitest";
6
6
  import { asMock, MockModules, Mocks, SetupMocks } from "@/__mocks__/common";
7
+ import { cellId } from "@/__tests__/branded";
7
8
  import type { CellActions, NotebookState } from "@/core/cells/cells";
8
- import type { CellId } from "@/core/cells/ids";
9
9
  import { useCellClipboard } from "../clipboard";
10
10
 
11
11
  // Mock dependencies
@@ -179,7 +179,7 @@ describe("useCellClipboard", () => {
179
179
  });
180
180
 
181
181
  it("should filter out non-existent cells", async () => {
182
- const nonExistentCellId = "non-existent" as CellId;
182
+ const nonExistentCellId = cellId("non-existent");
183
183
 
184
184
  const { result } = renderHook(() => useCellClipboard());
185
185
 
@@ -1,6 +1,7 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
+
2
3
  import { beforeEach, describe, expect, it } from "vitest";
3
- import type { CellId } from "@/core/cells/ids";
4
+ import { cellId } from "@/__tests__/branded";
4
5
  import { MultiColumn } from "@/utils/id-tree";
5
6
  import type { CellSelectionState } from "../selection";
6
7
  import { exportedForTesting } from "../selection";
@@ -8,11 +9,11 @@ import { exportedForTesting } from "../selection";
8
9
  const { initialState, reducer, createActions } = exportedForTesting;
9
10
 
10
11
  const CellIds = {
11
- a: "a" as CellId,
12
- b: "b" as CellId,
13
- c: "c" as CellId,
14
- d: "d" as CellId,
15
- e: "e" as CellId,
12
+ a: cellId("a"),
13
+ b: cellId("b"),
14
+ c: cellId("c"),
15
+ d: cellId("d"),
16
+ e: cellId("e"),
16
17
  };
17
18
 
18
19
  describe("cell selection reducer", () => {
@@ -1,6 +1,7 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
 
3
3
  import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
4
+ import { cellId } from "@/__tests__/branded";
4
5
  import { type CellId, HTMLCellId } from "@/core/cells/ids";
5
6
 
6
7
  const mockScrollCellIntoView = vi.fn();
@@ -14,12 +15,12 @@ vi.mock("../focus-utils", () => ({
14
15
  type TemporarilyShownCodeState = Set<CellId>;
15
16
 
16
17
  describe("temporarilyShownCodeActions", () => {
17
- const cellId = "cell-1" as CellId;
18
+ const cid = cellId("cell-1");
18
19
  let cellElement: HTMLElement;
19
20
 
20
21
  beforeEach(() => {
21
22
  cellElement = document.createElement("div");
22
- cellElement.id = HTMLCellId.create(cellId);
23
+ cellElement.id = HTMLCellId.create(cid);
23
24
  document.body.append(cellElement);
24
25
  cellElement.focus();
25
26
 
@@ -37,17 +38,17 @@ describe("temporarilyShownCodeActions", () => {
37
38
  });
38
39
 
39
40
  it("should scroll cell into view when removing cell causes layout shift", () => {
40
- const state = new Set<CellId>([cellId]);
41
- removeCell(state, cellId);
41
+ const state = new Set<CellId>([cid]);
42
+ removeCell(state, cid);
42
43
 
43
- expect(mockScrollCellIntoView).toHaveBeenCalledWith(cellId);
44
+ expect(mockScrollCellIntoView).toHaveBeenCalledWith(cid);
44
45
  });
45
46
 
46
47
  it("should not scroll when focused cell is not found", () => {
47
48
  vi.spyOn(HTMLCellId, "findElementThroughShadowDOMs").mockReturnValue(null);
48
49
 
49
- const state = new Set<CellId>([cellId]);
50
- removeCell(state, cellId);
50
+ const state = new Set<CellId>([cid]);
51
+ removeCell(state, cid);
51
52
 
52
53
  expect(mockScrollCellIntoView).not.toHaveBeenCalled();
53
54
  });
@@ -316,7 +316,7 @@ export const MarimoErrorOutput = ({
316
316
  <ul className="list-disc">
317
317
  {error.cells.map((cid, cidIdx) => (
318
318
  <li className={liStyle} key={`cell-${cidIdx}`}>
319
- <CellLinkError cellId={cid as CellId} />
319
+ <CellLinkError cellId={cid} />
320
320
  </li>
321
321
  ))}
322
322
  </ul>
@@ -491,7 +491,7 @@ export const MarimoErrorOutput = ({
491
491
  ) : (
492
492
  <div>
493
493
  {processTextForUrls(error.msg, `exception-${idx}`)}
494
- <CellLinkError cellId={error.raising_cell as CellId} />
494
+ <CellLinkError cellId={error.raising_cell} />
495
495
  </div>
496
496
  )}
497
497
  </li>
@@ -518,7 +518,7 @@ export const MarimoErrorOutput = ({
518
518
  ) : (
519
519
  <div>
520
520
  {error.msg}
521
- <CellLinkError cellId={error.blamed_cell as CellId} />
521
+ <CellLinkError cellId={error.blamed_cell} />
522
522
  </div>
523
523
  )}
524
524
  </li>
@@ -554,13 +554,13 @@ export const MarimoErrorOutput = ({
554
554
  {error.msg}
555
555
  {error.blamed_cell == null ? (
556
556
  <span>
557
- (<CellLinkError cellId={error.raising_cell as CellId} />)
557
+ (<CellLinkError cellId={error.raising_cell} />)
558
558
  </span>
559
559
  ) : (
560
560
  <span>
561
- (<CellLinkError cellId={error.raising_cell as CellId} />
561
+ (<CellLinkError cellId={error.raising_cell} />
562
562
  &nbsp;blames&nbsp;
563
- <CellLinkError cellId={error.blamed_cell as CellId} />)
563
+ <CellLinkError cellId={error.blamed_cell} />)
564
564
  </span>
565
565
  )}
566
566
  </div>
@@ -578,7 +578,7 @@ export const MarimoErrorOutput = ({
578
578
  {ancestorStoppedErrors.map((error, idx) => (
579
579
  <div key={`ancestor-stopped-${idx}`}>
580
580
  {error.msg}
581
- <CellLinkError cellId={error.raising_cell as CellId} />
581
+ <CellLinkError cellId={error.raising_cell} />
582
582
  </div>
583
583
  ))}
584
584
  {cellId && (
@@ -3,8 +3,8 @@
3
3
  import { render } from "@testing-library/react";
4
4
  import { beforeAll, beforeEach, describe, expect, test, vi } from "vitest";
5
5
  import { Tracebacks } from "@/__mocks__/tracebacks";
6
+ import { cellId } from "@/__tests__/branded";
6
7
  import { TooltipProvider } from "@/components/ui/tooltip";
7
- import type { CellId } from "@/core/cells/ids";
8
8
  import { initialModeAtom } from "@/core/mode";
9
9
  import { store } from "@/core/state/jotai";
10
10
  import { renderHTML } from "@/plugins/core/RenderHTML";
@@ -14,7 +14,7 @@ import {
14
14
  replaceTracebackPrefix,
15
15
  } from "../MarimoTracebackOutput";
16
16
 
17
- const cellId = "1" as CellId;
17
+ const cid = cellId("1");
18
18
 
19
19
  describe("traceback component", () => {
20
20
  beforeEach(() => {
@@ -25,7 +25,7 @@ describe("traceback component", () => {
25
25
  test("extracts cell-link", () => {
26
26
  const traceback = (
27
27
  <TooltipProvider>
28
- <MarimoTracebackOutput traceback={Tracebacks.raw} cellId={cellId} />
28
+ <MarimoTracebackOutput traceback={Tracebacks.raw} cellId={cid} />
29
29
  </TooltipProvider>
30
30
  );
31
31
  const { unmount, getAllByRole } = render(traceback);
@@ -45,7 +45,7 @@ describe("traceback component", () => {
45
45
  test("renames File to Cell for relevant lines", () => {
46
46
  const traceback = (
47
47
  <TooltipProvider>
48
- <MarimoTracebackOutput traceback={Tracebacks.raw} cellId={cellId} />
48
+ <MarimoTracebackOutput traceback={Tracebacks.raw} cellId={cid} />
49
49
  </TooltipProvider>
50
50
  );
51
51
  const { unmount, container } = render(traceback);
@@ -3,8 +3,8 @@
3
3
  import { act, fireEvent, render, screen } from "@testing-library/react";
4
4
  import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
5
5
  import { SetupMocks } from "@/__mocks__/common";
6
+ import { cellId } from "@/__tests__/branded";
6
7
  import { TooltipProvider } from "@/components/ui/tooltip";
7
- import type { CellId } from "@/core/cells/ids";
8
8
  import type { WithResponse } from "@/core/cells/types";
9
9
  import type { OutputMessage } from "@/core/kernel/messages";
10
10
  import { CONSOLE_CLEAR_DEBOUNCE_MS, ConsoleOutput } from "../ConsoleOutput";
@@ -24,7 +24,7 @@ describe("ConsoleOutput integration", () => {
24
24
  });
25
25
 
26
26
  const defaultProps = {
27
- cellId: "cell-1" as CellId,
27
+ cellId: cellId("cell-1"),
28
28
  cellName: "test_cell",
29
29
  consoleOutputs: [] as WithResponse<OutputMessage>[],
30
30
  stale: false,
@@ -55,7 +55,7 @@ describe("ConsoleOutput integration", () => {
55
55
 
56
56
  describe("ConsoleOutput pdb history", () => {
57
57
  const defaultProps = {
58
- cellId: "cell-1" as CellId,
58
+ cellId: cellId("cell-1"),
59
59
  cellName: "test_cell",
60
60
  consoleOutputs: [] as WithResponse<OutputMessage>[],
61
61
  stale: false,
@@ -215,7 +215,7 @@ describe("ConsoleOutput debounced clearing", () => {
215
215
  });
216
216
 
217
217
  const defaultProps = {
218
- cellId: "cell-1" as CellId,
218
+ cellId: cellId("cell-1"),
219
219
  cellName: "test_cell",
220
220
  consoleOutputs: [] as WithResponse<OutputMessage>[],
221
221
  stale: false,
@@ -91,7 +91,7 @@ function focusCellByName(cellName: string) {
91
91
 
92
92
  // Look for an editor to focus
93
93
  const { cellHandles } = getNotebook();
94
- const cellId = cellElement.dataset.cellId as CellId | undefined;
94
+ const cellId = extractCellIdFromDomElement(cellElement);
95
95
 
96
96
  if (!cellId) {
97
97
  Logger.error(`Missing cellId for cell with name ${cellName}`);
@@ -111,3 +111,10 @@ function focusCellByName(cellName: string) {
111
111
  focusFirstEditor();
112
112
  }
113
113
  }
114
+
115
+ function extractCellIdFromDomElement(
116
+ cellElement: HTMLElement,
117
+ ): CellId | undefined {
118
+ const cellIdStr = cellElement.dataset.cellId ?? undefined;
119
+ return cellIdStr as CellId | undefined;
120
+ }
@@ -50,7 +50,6 @@ import type {
50
50
  StoragePathKey,
51
51
  } from "@/core/storage/types";
52
52
  import { storagePathKey } from "@/core/storage/types";
53
- import type { VariableName } from "@/core/variables/types";
54
53
  import { cn } from "@/utils/cn";
55
54
  import { copyToClipboard } from "@/utils/copy";
56
55
  import { downloadByURL } from "@/utils/download";
@@ -474,7 +473,7 @@ const StorageNamespaceSection: React.FC<{
474
473
  <span>{namespace.displayName}</span>
475
474
  {namespace.name && (
476
475
  <span className="text-xs text-muted-foreground font-normal">
477
- (<EngineVariable variableName={namespace.name as VariableName} />)
476
+ (<EngineVariable variableName={namespace.name} />)
478
477
  </span>
479
478
  )}
480
479
  <RefreshIconButton
@@ -243,7 +243,9 @@ const TraceBlockBody: React.FC<{
243
243
  signalName: VEGA_HOVER_SIGNAL,
244
244
  handler: (_name: string, value: unknown) => {
245
245
  const signalValue = value as VegaHoverCellSignal;
246
- const hoveredCell = signalValue.cell?.[0] as CellId | undefined;
246
+ const hoveredCell = (signalValue.cell?.[0] ?? undefined) as
247
+ | CellId
248
+ | undefined;
247
249
  setHoveredCellId(hoveredCell ?? null);
248
250
  },
249
251
  },
@@ -3,6 +3,7 @@
3
3
  import { renderHook } from "@testing-library/react";
4
4
  import { getDefaultStore } from "jotai";
5
5
  import { beforeEach, describe, expect, it, vi } from "vitest";
6
+ import { cellId } from "@/__tests__/branded";
6
7
  import { CellId } from "@/core/cells/ids";
7
8
  import { updateEditorCodeFromPython } from "../../codemirror/language/utils";
8
9
  import {
@@ -61,8 +62,8 @@ describe("staged-cells", () => {
61
62
 
62
63
  beforeEach(() => {
63
64
  store = getDefaultStore();
64
- cellId1 = "cell-1" as CellId;
65
- cellId2 = "cell-2" as CellId;
65
+ cellId1 = cellId("cell-1");
66
+ cellId2 = cellId("cell-2");
66
67
 
67
68
  // Reset mocks
68
69
  vi.clearAllMocks();
@@ -213,7 +214,7 @@ describe("staged-cells", () => {
213
214
  const testCode = "print('hello world')";
214
215
 
215
216
  // Mock CellId.create to return a predictable ID
216
- const mockCellId = "mock-cell-id" as CellId;
217
+ const mockCellId = cellId("mock-cell-id");
217
218
  vi.mocked(CellId.create).mockReturnValue(mockCellId);
218
219
 
219
220
  const returnedCellId = result.current.createStagedCell(testCode);
@@ -229,7 +230,7 @@ describe("staged-cells", () => {
229
230
 
230
231
  it("should delete a staged cell", () => {
231
232
  const { result } = renderHook(() => useStagedCells(store));
232
- const testCellId = "test-cell-id" as CellId;
233
+ const testCellId = cellId("test-cell-id");
233
234
 
234
235
  result.current.deleteStagedCell(testCellId);
235
236
 
@@ -330,7 +331,7 @@ describe("staged-cells", () => {
330
331
  const { result } = renderHook(() => useStagedCells(store));
331
332
 
332
333
  // Create a staged cell
333
- const mockCellId = "mock-cell-id" as CellId;
334
+ const mockCellId = cellId("mock-cell-id");
334
335
  vi.mocked(CellId.create).mockReturnValue(mockCellId);
335
336
 
336
337
  const createdCellId = result.current.createStagedCell("test code");
@@ -341,7 +342,7 @@ describe("staged-cells", () => {
341
342
 
342
343
  let state = store.get(stagedAICellsAtom);
343
344
  expect(state.has(mockCellId)).toBe(true);
344
- expect(state.get(mockCellId)).toEqual({ type: "add_cell" });
345
+ expect(state.get(mockCellId)).toEqual({ type: cellId("add_cell") });
345
346
 
346
347
  // Delete the staged cell
347
348
  result.current.deleteStagedCell(mockCellId);
@@ -423,7 +424,7 @@ describe("onStream", () => {
423
424
  result.current.onStream({ type: "text-start", id: "test-id" });
424
425
 
425
426
  // Mock CellId.create to return a predictable ID
426
- const mockCellId = "mock-cell-id" as CellId;
427
+ const mockCellId = cellId("mock-cell-id");
427
428
  vi.mocked(CellId.create).mockReturnValue(mockCellId);
428
429
 
429
430
  result.current.onStream({
@@ -444,7 +445,7 @@ describe("onStream", () => {
444
445
  const { result } = renderHook(() => useStagedCells(store));
445
446
  result.current.onStream({ type: "text-start", id: "test-id" });
446
447
 
447
- const mockCellId = "mock-cell-id" as CellId;
448
+ const mockCellId = cellId("mock-cell-id");
448
449
  vi.mocked(CellId.create).mockReturnValue(mockCellId);
449
450
 
450
451
  result.current.onStream({
@@ -2,6 +2,7 @@
2
2
 
3
3
  import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
4
4
  import { Mocks } from "@/__mocks__/common";
5
+ import { cellId } from "@/__tests__/branded";
5
6
 
6
7
  // Mock the external dependencies
7
8
  vi.mock("html-to-image", () => ({
@@ -13,7 +14,6 @@ vi.mock("@/utils/Logger", () => ({
13
14
  }));
14
15
 
15
16
  import type { NotebookState } from "@/core/cells/cells";
16
- import type { CellId } from "@/core/cells/ids";
17
17
  import type { OutputMessage } from "@/core/kernel/messages";
18
18
  import type { JotaiStore } from "@/core/state/jotai";
19
19
  import { CellOutputContextProvider, getCellContextData } from "../cell-output";
@@ -35,21 +35,21 @@ describe("CellOutputContextProvider", () => {
35
35
  // Create a basic mock notebook state
36
36
  mockNotebook = {
37
37
  cellIds: {
38
- inOrderIds: ["cell1" as CellId, "cell2" as CellId, "cell3" as CellId],
38
+ inOrderIds: ["cell1", "cell2", "cell3"],
39
39
  },
40
40
  cellData: {
41
41
  cell1: {
42
- id: "cell1" as CellId,
42
+ id: "cell1",
43
43
  name: "My Cell",
44
44
  code: "print('hello world')",
45
45
  },
46
46
  cell2: {
47
- id: "cell2" as CellId,
47
+ id: "cell2",
48
48
  name: "",
49
49
  code: "import matplotlib.pyplot as plt\nplt.plot([1,2,3])",
50
50
  },
51
51
  cell3: {
52
- id: "cell3" as CellId,
52
+ id: "cell3",
53
53
  name: "Empty Cell",
54
54
  code: "# no output",
55
55
  },
@@ -226,9 +226,9 @@ describe("Cell output utility functions", () => {
226
226
 
227
227
  for (const testCase of testCases) {
228
228
  mockStore = createMockStore({
229
- cellIds: { inOrderIds: ["test" as CellId] },
229
+ cellIds: { inOrderIds: ["test"] },
230
230
  cellData: {
231
- test: { id: "test" as CellId, name: "", code: "" },
231
+ test: { id: "test", name: "", code: "" },
232
232
  },
233
233
  cellRuntime: {
234
234
  test: {
@@ -261,9 +261,9 @@ describe("Cell output utility functions", () => {
261
261
 
262
262
  for (const testCase of testCases) {
263
263
  mockStore = createMockStore({
264
- cellIds: { inOrderIds: ["test" as CellId] },
264
+ cellIds: { inOrderIds: ["test"] },
265
265
  cellData: {
266
- test: { id: "test" as CellId, name: "", code: "" },
266
+ test: { id: "test", name: "", code: "" },
267
267
  },
268
268
  cellRuntime: {
269
269
  test: {
@@ -295,9 +295,9 @@ describe("Cell output utility functions", () => {
295
295
 
296
296
  for (const testCase of testCases) {
297
297
  mockStore = createMockStore({
298
- cellIds: { inOrderIds: ["test" as CellId] },
298
+ cellIds: { inOrderIds: ["test"] },
299
299
  cellData: {
300
- test: { id: "test" as CellId, name: "", code: "" },
300
+ test: { id: "test", name: "", code: "" },
301
301
  },
302
302
  cellRuntime: {
303
303
  test: {
@@ -369,9 +369,9 @@ describe("Cell output utility functions", () => {
369
369
  ).mockReturnValue(mockDiv);
370
370
 
371
371
  mockStore = createMockStore({
372
- cellIds: { inOrderIds: ["test" as CellId] },
372
+ cellIds: { inOrderIds: ["test"] },
373
373
  cellData: {
374
- test: { id: "test" as CellId, name: "", code: "" },
374
+ test: { id: "test", name: "", code: "" },
375
375
  },
376
376
  cellRuntime: {
377
377
  test: {
@@ -396,16 +396,16 @@ describe("Cell output utility functions", () => {
396
396
  beforeEach(() => {
397
397
  mockNotebook = {
398
398
  cellIds: {
399
- inOrderIds: ["cell1" as CellId, "cell2" as CellId],
399
+ inOrderIds: ["cell1", "cell2"],
400
400
  },
401
401
  cellData: {
402
402
  cell1: {
403
- id: "cell1" as CellId,
403
+ id: "cell1",
404
404
  name: "My Named Cell",
405
405
  code: "x = 42",
406
406
  },
407
407
  cell2: {
408
- id: "cell2" as CellId,
408
+ id: "cell2",
409
409
  name: "",
410
410
  code: "y = x * 2",
411
411
  },
@@ -432,7 +432,7 @@ describe("Cell output utility functions", () => {
432
432
  });
433
433
 
434
434
  it("should extract basic cell data", () => {
435
- const result = getCellContextData("cell1" as CellId, mockNotebook);
435
+ const result = getCellContextData(cellId("cell1"), mockNotebook);
436
436
 
437
437
  expect(result.cellId).toBe("cell1");
438
438
  expect(result.cellName).toBe("My Named Cell");
@@ -440,13 +440,13 @@ describe("Cell output utility functions", () => {
440
440
  });
441
441
 
442
442
  it("should generate cell name for unnamed cells", () => {
443
- const result = getCellContextData("cell2" as CellId, mockNotebook);
443
+ const result = getCellContextData(cellId("cell2"), mockNotebook);
444
444
 
445
445
  expect(result.cellName).toBe("cell-1"); // 0-indexed, so cell2 is at index 1
446
446
  });
447
447
 
448
448
  it("should include cell output when present", () => {
449
- const result = getCellContextData("cell1" as CellId, mockNotebook);
449
+ const result = getCellContextData(cellId("cell1"), mockNotebook);
450
450
 
451
451
  expect(result.cellOutput).toBeDefined();
452
452
  expect(result.cellOutput?.outputType).toBe("text");
@@ -454,19 +454,19 @@ describe("Cell output utility functions", () => {
454
454
  });
455
455
 
456
456
  it("should not include cell output when not present", () => {
457
- const result = getCellContextData("cell2" as CellId, mockNotebook);
457
+ const result = getCellContextData(cellId("cell2"), mockNotebook);
458
458
 
459
459
  expect(result.cellOutput).toBeUndefined();
460
460
  });
461
461
 
462
462
  it("should not include console outputs by default", () => {
463
- const result = getCellContextData("cell2" as CellId, mockNotebook);
463
+ const result = getCellContextData(cellId("cell2"), mockNotebook);
464
464
 
465
465
  expect(result.consoleOutputs).toBeUndefined();
466
466
  });
467
467
 
468
468
  it("should include console outputs when opted in", () => {
469
- const result = getCellContextData("cell2" as CellId, mockNotebook, {
469
+ const result = getCellContextData(cellId("cell2"), mockNotebook, {
470
470
  includeConsoleOutput: true,
471
471
  });
472
472
 
@@ -478,7 +478,7 @@ describe("Cell output utility functions", () => {
478
478
  });
479
479
 
480
480
  it("should filter out empty console outputs", () => {
481
- const cell2Runtime = mockNotebook.cellRuntime["cell2" as CellId];
481
+ const cell2Runtime = mockNotebook.cellRuntime[cellId("cell2")];
482
482
  if (cell2Runtime) {
483
483
  (cell2Runtime as { consoleOutputs: OutputMessage[] }).consoleOutputs = [
484
484
  {
@@ -492,7 +492,7 @@ describe("Cell output utility functions", () => {
492
492
  ];
493
493
  }
494
494
 
495
- const result = getCellContextData("cell2" as CellId, mockNotebook, {
495
+ const result = getCellContextData(cellId("cell2"), mockNotebook, {
496
496
  includeConsoleOutput: true,
497
497
  });
498
498
 
@@ -501,7 +501,7 @@ describe("Cell output utility functions", () => {
501
501
  });
502
502
 
503
503
  it("should handle cells with both cell output and console outputs", () => {
504
- const cell1Runtime = mockNotebook.cellRuntime["cell1" as CellId];
504
+ const cell1Runtime = mockNotebook.cellRuntime[cellId("cell1")];
505
505
  if (cell1Runtime) {
506
506
  (cell1Runtime as { consoleOutputs: OutputMessage[] }).consoleOutputs = [
507
507
  {
@@ -511,7 +511,7 @@ describe("Cell output utility functions", () => {
511
511
  ];
512
512
  }
513
513
 
514
- const result = getCellContextData("cell1" as CellId, mockNotebook, {
514
+ const result = getCellContextData(cellId("cell1"), mockNotebook, {
515
515
  includeConsoleOutput: true,
516
516
  });
517
517
 
@@ -524,7 +524,7 @@ describe("Cell output utility functions", () => {
524
524
  });
525
525
 
526
526
  it("should handle empty console outputs array", () => {
527
- const result = getCellContextData("cell1" as CellId, mockNotebook, {
527
+ const result = getCellContextData(cellId("cell1"), mockNotebook, {
528
528
  includeConsoleOutput: true,
529
529
  });
530
530
 
@@ -532,7 +532,7 @@ describe("Cell output utility functions", () => {
532
532
  });
533
533
 
534
534
  it("should handle media outputs in cell output", () => {
535
- const cell1Runtime = mockNotebook.cellRuntime["cell1" as CellId];
535
+ const cell1Runtime = mockNotebook.cellRuntime[cellId("cell1")];
536
536
  if (cell1Runtime) {
537
537
  (cell1Runtime as { output: OutputMessage | null }).output = {
538
538
  mimetype: "image/png",
@@ -540,7 +540,7 @@ describe("Cell output utility functions", () => {
540
540
  } as OutputMessage;
541
541
  }
542
542
 
543
- const result = getCellContextData("cell1" as CellId, mockNotebook);
543
+ const result = getCellContextData(cellId("cell1"), mockNotebook);
544
544
 
545
545
  expect(result.cellOutput).toBeDefined();
546
546
  expect(result.cellOutput?.outputType).toBe("media");
@@ -548,7 +548,7 @@ describe("Cell output utility functions", () => {
548
548
  });
549
549
 
550
550
  it("should handle media outputs in console outputs", () => {
551
- const cell2Runtime = mockNotebook.cellRuntime["cell2" as CellId];
551
+ const cell2Runtime = mockNotebook.cellRuntime[cellId("cell2")];
552
552
  if (cell2Runtime) {
553
553
  (cell2Runtime as { consoleOutputs: OutputMessage[] }).consoleOutputs = [
554
554
  {
@@ -558,7 +558,7 @@ describe("Cell output utility functions", () => {
558
558
  ];
559
559
  }
560
560
 
561
- const result = getCellContextData("cell2" as CellId, mockNotebook, {
561
+ const result = getCellContextData(cellId("cell2"), mockNotebook, {
562
562
  includeConsoleOutput: true,
563
563
  });
564
564