@marimo-team/islands 0.25.3-dev301 → 0.25.3-dev303

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 (100) hide show
  1. package/dist/{ConnectedDataExplorerComponent-X-_Gsw0B.js → ConnectedDataExplorerComponent-DJnSxHJB.js} +9 -9
  2. package/dist/{ErrorBoundary-D2XuUNty.js → ErrorBoundary-CkXYBt02.js} +6 -6
  3. package/dist/{abnfDiagram-VCTEODGH-B8nNWmL7.js → abnfDiagram-VCTEODGH-CR0U5hup.js} +2 -2
  4. package/dist/{any-language-editor-DhAtCzlx.js → any-language-editor-C5dsTpeB.js} +2 -2
  5. package/dist/{architectureDiagram-5GKGNRK7-DcfTzRDz.js → architectureDiagram-5GKGNRK7-Bc_fbI1Q.js} +1 -1
  6. package/dist/{assertNever-De6m1Aro.js → assertNever-efcK_v3t.js} +2 -2
  7. package/dist/assets/__vite-browser-external-DzTYIHH_.js +1 -0
  8. package/dist/assets/worker-BH08I2Il.js +171 -0
  9. package/dist/{chat-ui-CtbON6Zl.js → chat-ui-C4iLRzY0.js} +12 -12
  10. package/dist/{check-C7fmwkwt.js → check-DCQEEsUn.js} +1 -1
  11. package/dist/{chunk-IMKFNOWR-BHJ3ZxAy.js → chunk-IMKFNOWR-y9z5oeAY.js} +1 -1
  12. package/dist/{chunk-SHT3W25Y-CkOPJgVC.js → chunk-SHT3W25Y-Tu-V-e_v.js} +1 -1
  13. package/dist/{chunk-SVP7TREG-rDd35EZ7.js → chunk-SVP7TREG-CJFxs5R_.js} +1 -1
  14. package/dist/{chunk-TICWLB2K-uKdr5PNy.js → chunk-TICWLB2K-zkTP7ya7.js} +1 -1
  15. package/dist/{classDiagram-ZZMXUADV-DctWoMRF.js → classDiagram-ZZMXUADV-DxJAZI0N.js} +2 -2
  16. package/dist/{classDiagram-v2-VYDZK3BY-DyanDjSq.js → classDiagram-v2-VYDZK3BY-TmHo2BpS.js} +2 -2
  17. package/dist/{code-visibility-Y0zfGGT1.js → code-visibility-BWqxH-SS.js} +5 -5
  18. package/dist/{common-B_rBSwAA.js → common-BzSr-5bH.js} +19 -19
  19. package/dist/{config-C4oddKcw.js → config-BG2qKzDg.js} +3 -3
  20. package/dist/{copy-icon-CVrC6aa6.js → copy-icon-oHFcxX_y.js} +2 -2
  21. package/dist/{createReducer-DzlYBqjn.js → createReducer-DHfURLCk.js} +1 -1
  22. package/dist/{cynefinDiagram-5FMLGOSQ-uEhVcLHR.js → cynefinDiagram-5FMLGOSQ-Eb40hmhD.js} +1 -1
  23. package/dist/{dagre-GXQ25YYZ-B_NBKhOr.js → dagre-GXQ25YYZ-_paaVwit.js} +1 -1
  24. package/dist/{data-grid-overlay-editor-04SWN9ol.js → data-grid-overlay-editor-D-JJeDak.js} +1 -1
  25. package/dist/{diagram-S7CK7UJ4-BQr1iw91.js → diagram-S7CK7UJ4-BtKJm1_4.js} +1 -1
  26. package/dist/{diagram-UQ7AKVKN-DsAjdQ2j.js → diagram-UQ7AKVKN-DQbxhEMd.js} +1 -1
  27. package/dist/{diagram-VX7I27RA-0VAUrHmz.js → diagram-VX7I27RA-DITDIfGC.js} +1 -1
  28. package/dist/{diagram-Z3DM3KII-C1aEuADo.js → diagram-Z3DM3KII-Ct9_zo6F.js} +1 -1
  29. package/dist/{dialog-U3stKkkL.js → dialog-BIUdMLIS.js} +2 -2
  30. package/dist/{dropdown-menu-BMtxnyHc.js → dropdown-menu-CAejOChE.js} +5 -5
  31. package/dist/{ebnfDiagram-PWID7BFC-oBie_-vi.js → ebnfDiagram-PWID7BFC-6cOntwfv.js} +2 -2
  32. package/dist/{erDiagram-RLTQ6QDP-DtWDCiaw.js → erDiagram-RLTQ6QDP-CJiOER41.js} +1 -1
  33. package/dist/{error-banner-CfIck83X.js → error-banner-DGOrmBk5.js} +1 -1
  34. package/dist/{error-entries-CjsQY6ym.js → error-entries-BWmleiL0.js} +8 -8
  35. package/dist/{feedback-button-DoriP8b7.js → feedback-button-3g6wZGH4.js} +7 -7
  36. package/dist/{flowDiagram-HODETNUW-EXK7bg_t.js → flowDiagram-HODETNUW-1lPBEUuW.js} +2 -2
  37. package/dist/{formats-G0-mQsFy.js → formats-qhBmYb0l.js} +1 -1
  38. package/dist/{glide-data-editor-BU_jOTDv.js → glide-data-editor-WryZQ9w2.js} +11 -11
  39. package/dist/{glide-utils-BkcGyXLQ.js → glide-utils-C4TKZeBA.js} +2 -2
  40. package/dist/{globals-DziKJCFY.js → globals-CMJjdKbd.js} +3 -3
  41. package/dist/{html-to-image-CIm3PqDi.js → html-to-image-B8hE6HIH.js} +12 -12
  42. package/dist/{infoDiagram-27XIBGKW-N4ajFTXv.js → infoDiagram-27XIBGKW-C6K4tri5.js} +1 -1
  43. package/dist/{ishikawaDiagram-5VMMS53U-Bb2itmv5.js → ishikawaDiagram-5VMMS53U-DwcwgRNH.js} +1 -1
  44. package/dist/{kanban-definition-UXKFOSKX-DWfkIEDX.js → kanban-definition-UXKFOSKX-E489OMdc.js} +1 -1
  45. package/dist/main.js +31 -31
  46. package/dist/{mermaid-BEBd0PHi.js → mermaid-DMPMkVqY.js} +34 -34
  47. package/dist/{mindmap-definition-YA3MSWOX-CmGSiRxU.js → mindmap-definition-YA3MSWOX-DWHjasOp.js} +1 -1
  48. package/dist/{number-overlay-editor-BaZBWVbO.js → number-overlay-editor-D96g34vO.js} +1 -1
  49. package/dist/{pegDiagram-XKGWAZYB-dXflGNi0.js → pegDiagram-XKGWAZYB-COjcPOZT.js} +2 -2
  50. package/dist/{pencil-BGy5pfXo.js → pencil-BUfnNZAE.js} +1 -1
  51. package/dist/{pieDiagram-E7YTZNPT-Bl9G_NNa.js → pieDiagram-E7YTZNPT-BHAVZ38h.js} +1 -1
  52. package/dist/{process-output-DAVapIAQ.js → process-output-DZDL_j1a.js} +4 -4
  53. package/dist/{railroadDiagram-O6MQD6OU-Dg7GUHj4.js → railroadDiagram-O6MQD6OU-94ThFyKX.js} +2 -2
  54. package/dist/{requirementDiagram-BXWQKSXE-JNZB3XKK.js → requirementDiagram-BXWQKSXE-CpF-Fxbb.js} +1 -1
  55. package/dist/{reveal-component-vRQ0ZbEq.js → reveal-component-CIP7WMa0.js} +8 -8
  56. package/dist/{select-Ba_tMQWZ.js → select-XmXyen3r.js} +4 -4
  57. package/dist/{sequenceDiagram-WJ2MYXX4-DekbwWOI.js → sequenceDiagram-WJ2MYXX4-CvANK2x7.js} +1 -1
  58. package/dist/{spec-CN3OxHz7.js → spec-CSS9g9Su.js} +4 -4
  59. package/dist/{stateDiagram-D77RDMKH-COzvSaN-.js → stateDiagram-D77RDMKH-WHuJ4mJL.js} +2 -2
  60. package/dist/{stateDiagram-v2-MP3YSRHH-rCvxZ0L8.js → stateDiagram-v2-MP3YSRHH-DbO7lwYq.js} +2 -2
  61. package/dist/{static-state-BJdfR8Bn.js → static-state-Dtocd9UO.js} +1 -1
  62. package/dist/{swimlanes-42K2YHIH-DX2mMlXc.js → swimlanes-42K2YHIH-CS2s29Vo.js} +1 -1
  63. package/dist/{swimlanesDiagram-VR7AAH4N-DswSPZ5e.js → swimlanesDiagram-VR7AAH4N-CXaA1vQg.js} +2 -2
  64. package/dist/{timeline-definition-24CTP7MA-DAT9AlwV.js → timeline-definition-24CTP7MA-B-SQMg5h.js} +1 -1
  65. package/dist/{toast-BRd_eTIj.js → toast-xEFvuGpt.js} +3 -3
  66. package/dist/{tooltip-CHvXUQVs.js → tooltip-BekOCQ3v.js} +1 -1
  67. package/dist/{use-restore-focus-Ckq0jQzc.js → use-restore-focus-DyrKLdSB.js} +1379 -1311
  68. package/dist/{useDateFormatter-CIPe17AG.js → useDateFormatter-Brx-S2sN.js} +2 -2
  69. package/dist/{useDeepCompareMemoize-Kg-7A4b-.js → useDeepCompareMemoize-CxywEb3a.js} +1 -1
  70. package/dist/{useLifecycle-BKVRcyGu.js → useLifecycle-BMlFy2yY.js} +1 -1
  71. package/dist/{vega-component-C23pVuni.js → vega-component-DwqGfN3_.js} +6 -6
  72. package/dist/{vennDiagram-4TSXK5OY-E7CMtY2M.js → vennDiagram-4TSXK5OY-etEFgvaG.js} +1 -1
  73. package/dist/{wardleyDiagram-VM6X3IG4-BjtOazpV.js → wardleyDiagram-VM6X3IG4-BEQN7g62.js} +1 -1
  74. package/dist/{xychartDiagram-S5SC5T6Z-DC09jtph.js → xychartDiagram-S5SC5T6Z-D8-e5Z0R.js} +1 -1
  75. package/package.json +1 -1
  76. package/src/components/ai/__tests__/ai-utils.test.ts +8 -0
  77. package/src/components/app-config/ai-config.tsx +4 -6
  78. package/src/components/app-config/data-form.tsx +1 -3
  79. package/src/components/app-config/get-dirty-values.ts +4 -4
  80. package/src/components/editor/__tests__/data-attributes.test.tsx +10 -3
  81. package/src/components/editor/actions/__tests__/useSetOutputsExpanded.test.ts +2 -1
  82. package/src/components/editor/actions/useSetOutputsExpanded.ts +1 -4
  83. package/src/components/editor/navigation/__tests__/navigation.test.ts +1 -0
  84. package/src/components/static-html/__tests__/static-banner.test.tsx +1 -1
  85. package/src/core/ai/tools/__tests__/edit-notebook-tool.test.ts +7 -3
  86. package/src/core/cells/__tests__/cells.test.ts +4 -1
  87. package/src/core/cells/__tests__/harness.ts +4 -1
  88. package/src/core/codemirror/__tests__/format.test.ts +4 -1
  89. package/src/core/codemirror/__tests__/setup.test.ts +6 -4
  90. package/src/core/codemirror/copilot/__tests__/completion-integration.test.ts +4 -0
  91. package/src/core/codemirror/copilot/__tests__/getCodes.test.ts +7 -3
  92. package/src/core/codemirror/language/__tests__/extension.test.ts +7 -3
  93. package/src/core/codemirror/language/__tests__/utils.test.ts +7 -2
  94. package/src/core/config/__tests__/config-schema.test.ts +121 -11
  95. package/src/core/config/config-schema.ts +100 -15
  96. package/src/core/notebook/document/__tests__/codemirror.test.ts +8 -2
  97. package/src/stories/editor.stories.tsx +4 -0
  98. package/src/stories/theme.stories.tsx +4 -1
  99. package/dist/assets/__vite-browser-external-BzfoKXxV.js +0 -1
  100. package/dist/assets/worker-DVG30pr3.js +0 -171
@@ -1,7 +1,7 @@
1
1
  import { a as e } from "./rolldown-runtime-BPCzCO3I.js";
2
2
  import { t } from "./react-CHbZqgBF.js";
3
- import { h as n } from "./tooltip-CHvXUQVs.js";
4
- import { C as r } from "./select-Ba_tMQWZ.js";
3
+ import { h as n } from "./tooltip-BekOCQ3v.js";
4
+ import { C as r } from "./select-XmXyen3r.js";
5
5
  var i = n("chart-pie", [["path", {
6
6
  d: "M21 12c.552 0 1.005-.449.95-.998a10 10 0 0 0-8.953-8.951c-.55-.055-.998.398-.998.95v8a1 1 0 0 0 1 1z",
7
7
  key: "pzmjnu"
@@ -1,6 +1,6 @@
1
1
  import { a as e } from "./rolldown-runtime-BPCzCO3I.js";
2
2
  import { t } from "./react-CHbZqgBF.js";
3
- import { Mt as n } from "./use-restore-focus-Ckq0jQzc.js";
3
+ import { Mt as n } from "./use-restore-focus-DyrKLdSB.js";
4
4
  //#region src/hooks/useDeepCompareMemoize.ts
5
5
  var r = /* @__PURE__ */ e(t(), 1);
6
6
  function i(e) {
@@ -2,7 +2,7 @@ import { a as e } from "./rolldown-runtime-BPCzCO3I.js";
2
2
  import { h as t, r as n } from "./button-BuSV-mLI.js";
3
3
  import { t as r } from "./react-CHbZqgBF.js";
4
4
  import { t as i } from "./compiler-runtime-DNezxW8I.js";
5
- import { h as a } from "./tooltip-CHvXUQVs.js";
5
+ import { h as a } from "./tooltip-BekOCQ3v.js";
6
6
  import { t as o } from "./jsx-runtime-6ZiU38At.js";
7
7
  var s = a("calendar", [
8
8
  ["path", {
@@ -2,22 +2,22 @@ import { a as e } from "./rolldown-runtime-BPCzCO3I.js";
2
2
  import { g as t, h as n, m as r, s as i } from "./button-BuSV-mLI.js";
3
3
  import { t as a } from "./react-CHbZqgBF.js";
4
4
  import { t as o } from "./compiler-runtime-DNezxW8I.js";
5
- import { t as s } from "./tooltip-CHvXUQVs.js";
6
- import { l as c, t as l } from "./config-C4oddKcw.js";
5
+ import { t as s } from "./tooltip-BekOCQ3v.js";
6
+ import { l as c, t as l } from "./config-BG2qKzDg.js";
7
7
  import { t as u } from "./jsx-runtime-6ZiU38At.js";
8
- import { u as d } from "./use-restore-focus-Ckq0jQzc.js";
9
- import { n as f } from "./error-banner-CfIck83X.js";
8
+ import { u as d } from "./use-restore-focus-DyrKLdSB.js";
9
+ import { n as f } from "./error-banner-DGOrmBk5.js";
10
10
  import { t as p } from "./debounce-DrhhziJv.js";
11
11
  import { t as ee } from "./objects-DCmMvZtn.js";
12
12
  import { t as te } from "./useEvent-xDnF2X04.js";
13
- import { a as ne, i as re, n as ie, t as m } from "./formats-G0-mQsFy.js";
13
+ import { a as ne, i as re, n as ie, t as m } from "./formats-qhBmYb0l.js";
14
14
  import { a as h, t as g } from "./arrays-DoQ-AILx.js";
15
15
  import { t as ae } from "./useAsyncData-DMBliR6D.js";
16
16
  import { t as _ } from "./semaphore-8KhQouXt.js";
17
17
  import { D as oe, n as se } from "./vega-loader.browser-Cnf7IHA8.js";
18
18
  import { t as ce } from "./react-vega-DVr24mNk.js";
19
19
  import { a as le, n as v } from "./loader-BIlwkY0d.js";
20
- import { t as ue } from "./useDeepCompareMemoize-Kg-7A4b-.js";
20
+ import { t as ue } from "./useDeepCompareMemoize-CxywEb3a.js";
21
21
  import { t as de } from "./use-vega-container-remeasure-DFBTESqc.js";
22
22
  //#region src/plugins/impl/vega/fix-relative-url.ts
23
23
  var fe = /* @__PURE__ */ e(a(), 1), pe = o();
@@ -3,7 +3,7 @@ import { t } from "./src-D5uZaZib.js";
3
3
  import { n } from "./chunk-Y2CYZVJY-DKKS1VyV.js";
4
4
  import { $ as r, H as i, K as a, U as o, a as s, b as c, c as l, et as u, f as d, nt as f, tt as p, v as m, w as h, y as g } from "./chunk-DU6HZSFF-B20LZ-hE.js";
5
5
  import { t as _ } from "./rough.esm-CtV9AnV1.js";
6
- import { p as v } from "./mermaid-BEBd0PHi.js";
6
+ import { p as v } from "./mermaid-DMPMkVqY.js";
7
7
  //#region ../node_modules/.pnpm/khroma@2.1.0/node_modules/khroma/dist/methods/transparentize.js
8
8
  var y = (e, t) => p(e, "a", -t), b = 1e-10;
9
9
  function x(e, t) {
@@ -2,7 +2,7 @@ import { i as e } from "./chunk-75Z2AOVW-9jQIEAxd.js";
2
2
  import { n as t } from "./src-D5uZaZib.js";
3
3
  import { n } from "./chunk-Y2CYZVJY-DKKS1VyV.js";
4
4
  import { D as r, H as i, K as a, U as o, a as s, b as c, c as l, v as u, w as d, x as f, y as p } from "./chunk-DU6HZSFF-B20LZ-hE.js";
5
- import { p as m } from "./mermaid-BEBd0PHi.js";
5
+ import { p as m } from "./mermaid-DMPMkVqY.js";
6
6
  import { n as h } from "./mermaid-parser.core-DtOnl7m4.js";
7
7
  import { t as g } from "./chunk-JWPE2WC7-DJvv1t8U.js";
8
8
  //#region ../node_modules/.pnpm/mermaid@11.17.2/node_modules/mermaid/dist/chunks/mermaid.core/wardleyDiagram-VM6X3IG4.mjs
@@ -9,7 +9,7 @@ import { n as s } from "./chunk-Y2CYZVJY-DKKS1VyV.js";
9
9
  import { D as c, H as l, K as u, U as d, a as f, b as p, c as m, f as h, v as g, w as _, y as v, z as y } from "./chunk-DU6HZSFF-B20LZ-hE.js";
10
10
  import "./chunk-PWAF6VOD-oT_Qd2OU.js";
11
11
  import { t as b } from "./chunk-GMAD6QVW-DokpSFdf.js";
12
- import { p as x } from "./mermaid-BEBd0PHi.js";
12
+ import { p as x } from "./mermaid-DMPMkVqY.js";
13
13
  //#region ../node_modules/.pnpm/d3-scale@4.0.2/node_modules/d3-scale/src/band.js
14
14
  function S() {
15
15
  var e = t().unknown(void 0), r = e.domain, i = e.range, o = 0, s = 1, c, l, u = !1, d = 0, f = 0, p = .5;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marimo-team/islands",
3
- "version": "0.25.3-dev301",
3
+ "version": "0.25.3-dev303",
4
4
  "main": "dist/main.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -1,5 +1,7 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
 
3
+ import { defaultUserConfig } from "@/core/config/config-schema";
4
+
3
5
  import type { AiModel } from "@marimo-team/llm-info";
4
6
  import { beforeEach, describe, expect, it, vi } from "vitest";
5
7
  import type { UserConfig } from "@/core/config/config-schema";
@@ -75,6 +77,7 @@ describe("ai-utils", () => {
75
77
  it("returns known providers with credentials, then custom providers with a base URL", () => {
76
78
  expect(
77
79
  listConfiguredProviders({
80
+ ...defaultUserConfig().ai,
78
81
  wandb: { api_key: "unused" },
79
82
  open_ai: { api_key: "sk-test" },
80
83
  open_ai_compatible: { api_key: "unused", base_url: "https://x" },
@@ -89,6 +92,7 @@ describe("ai-utils", () => {
89
92
  it("treats marimo as configured when open_ai_compatible has a base URL", () => {
90
93
  expect(
91
94
  listConfiguredProviders({
95
+ ...defaultUserConfig().ai,
92
96
  open_ai_compatible: { api_key: "unused", base_url: "https://x" },
93
97
  }),
94
98
  ).toEqual(["marimo"]);
@@ -97,6 +101,7 @@ describe("ai-utils", () => {
97
101
  it("omits openai-compatible as its own provider id", () => {
98
102
  expect(
99
103
  listConfiguredProviders({
104
+ ...defaultUserConfig().ai,
100
105
  open_ai: {},
101
106
  open_ai_compatible: { api_key: "unused" },
102
107
  }),
@@ -115,6 +120,7 @@ describe("ai-utils", () => {
115
120
  it("returns all groups when provider config is allowed", () => {
116
121
  expect(
117
122
  listModelsForAiSettings(entries, {
123
+ ...defaultUserConfig().ai,
118
124
  allow_provider_config: true,
119
125
  wandb: { api_key: "unused" },
120
126
  }),
@@ -124,6 +130,7 @@ describe("ai-utils", () => {
124
130
  it("filters to configured providers when provider config is locked", () => {
125
131
  expect(
126
132
  listModelsForAiSettings(entries, {
133
+ ...defaultUserConfig().ai,
127
134
  allow_provider_config: false,
128
135
  wandb: { api_key: "unused" },
129
136
  }),
@@ -133,6 +140,7 @@ describe("ai-utils", () => {
133
140
  it("keeps marimo models when locked with an openai-compatible gateway", () => {
134
141
  expect(
135
142
  listModelsForAiSettings(entries, {
143
+ ...defaultUserConfig().ai,
136
144
  allow_provider_config: false,
137
145
  open_ai_compatible: { base_url: "https://ai.marimo.app/molab/v1" },
138
146
  }),
@@ -1394,12 +1394,10 @@ export const AiAssistConfig: React.FC<AiConfigProps> = ({
1394
1394
  onCheckedChange={(checked) => {
1395
1395
  const isChecked = checked === true;
1396
1396
  setMaxTokensEnabled(isChecked);
1397
- // null signals delete to the server; cast because
1398
- // UserConfig (OpenAPI-derived) types max_tokens as
1399
- // `number | undefined`, but zod accepts `null`.
1400
- const next = (
1401
- isChecked ? (field.value ?? 32768) : null
1402
- ) as number | undefined;
1397
+ // null signals delete to the server.
1398
+ const next = isChecked
1399
+ ? (field.value ?? 32768)
1400
+ : null;
1403
1401
  // shouldDirty: true forces RHF to keep this in
1404
1402
  // dirtyFields even when `next` happens to equal the
1405
1403
  // form's defaultValue (e.g. untick → tick when disk
@@ -51,9 +51,7 @@ export const DataForm = ({
51
51
  data-testid="auto-discover-schemas-select"
52
52
  onChange={onChange}
53
53
  value={
54
- override.value === undefined
55
- ? "auto"
56
- : override.value.toString()
54
+ override.value == null ? "auto" : override.value.toString()
57
55
  }
58
56
  disabled={field.disabled || override.isOverridden}
59
57
  className="w-[100px]"
@@ -1,6 +1,6 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
 
3
- import type { FieldPath, FieldValues } from "react-hook-form";
3
+ import type { DeepPartial, FieldPath, FieldValues } from "react-hook-form";
4
4
  import type { UserConfig } from "@/core/config/config-schema";
5
5
 
6
6
  /**
@@ -39,12 +39,12 @@ export function getDirtyValues<T extends FieldValues>(
39
39
 
40
40
  type ManualInjector = (
41
41
  values: UserConfig,
42
- dirtyValues: Partial<UserConfig>,
42
+ dirtyValues: DeepPartial<UserConfig>,
43
43
  ) => void;
44
44
 
45
45
  const modelsAiInjection = (
46
46
  values: UserConfig,
47
- dirtyValues: Partial<UserConfig>,
47
+ dirtyValues: DeepPartial<UserConfig>,
48
48
  ) => {
49
49
  dirtyValues.ai = {
50
50
  ...dirtyValues.ai,
@@ -88,7 +88,7 @@ const isTouchedPath = (
88
88
 
89
89
  export const applyManualInjections = (opts: {
90
90
  values: UserConfig;
91
- dirtyValues: Partial<UserConfig>;
91
+ dirtyValues: DeepPartial<UserConfig>;
92
92
  touchedFields: unknown;
93
93
  }) => {
94
94
  const { values, dirtyValues, touchedFields } = opts;
@@ -1,4 +1,6 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
+
3
+ import { defaultUserConfig } from "@/core/config/config-schema";
2
4
  import { render } from "@testing-library/react";
3
5
  import { createStore, Provider } from "jotai";
4
6
  import { beforeAll, describe, expect, it } from "vitest";
@@ -46,7 +48,9 @@ describe("Cell data attributes", () => {
46
48
  const cellName = "test_cell";
47
49
 
48
50
  const userConfig: UserConfig = {
51
+ ...defaultUserConfig(),
49
52
  display: {
53
+ ...defaultUserConfig().display,
50
54
  cell_output: "below",
51
55
  code_editor_font_size: 14,
52
56
  dataframes: "rich",
@@ -56,8 +60,9 @@ describe("Cell data attributes", () => {
56
60
  theme: "light",
57
61
  reference_highlighting: false,
58
62
  },
59
- keymap: { preset: "default" },
63
+ keymap: { ...defaultUserConfig().keymap, preset: "default" },
60
64
  completion: {
65
+ ...defaultUserConfig().completion,
61
66
  activate_on_typing: true,
62
67
  signature_hint_on_typing: false,
63
68
  copilot: false,
@@ -65,6 +70,7 @@ describe("Cell data attributes", () => {
65
70
  formatting: { line_length: 88, infer_types: "off" },
66
71
  package_management: { manager: "pip" },
67
72
  runtime: {
73
+ ...defaultUserConfig().runtime,
68
74
  auto_instantiate: false,
69
75
  default_sql_output: "native",
70
76
  auto_reload: "off",
@@ -77,6 +83,7 @@ describe("Cell data attributes", () => {
77
83
  dotenv: [".env"],
78
84
  },
79
85
  server: {
86
+ ...defaultUserConfig().server,
80
87
  browser: "default",
81
88
  follow_symlink: false,
82
89
  },
@@ -85,8 +92,8 @@ describe("Cell data attributes", () => {
85
92
  autosave_delay: 1000,
86
93
  format_on_save: false,
87
94
  },
88
- ai: {},
89
- } as UserConfig;
95
+ ai: defaultUserConfig().ai,
96
+ };
90
97
 
91
98
  const notebook = MockNotebook.notebookState({
92
99
  cellData: {
@@ -34,9 +34,10 @@ describe("outputExpansionConfigs", () => {
34
34
  });
35
35
  });
36
36
 
37
- it("clamps expanded cells with output and skips cells without output", () => {
37
+ it("clamps all expanded cells, including those without current output", () => {
38
38
  expect(outputExpansionConfigs(notebook, false)).toEqual({
39
39
  [expanded]: { expand_output: false },
40
+ [expandedWithoutOutput]: { expand_output: false },
40
41
  });
41
42
  });
42
43
  });
@@ -10,9 +10,6 @@ import { Objects } from "@/utils/objects";
10
10
 
11
11
  /**
12
12
  * The `expand_output` config changes needed to expand or clamp every output.
13
- *
14
- * Both actions skip cells without output, so their source isn't annotated
15
- * with a config that has no effect.
16
13
  */
17
14
  export function outputExpansionConfigs(
18
15
  notebook: NotebookState,
@@ -27,7 +24,7 @@ export function outputExpansionConfigs(
27
24
  ) {
28
25
  continue;
29
26
  }
30
- if (isOutputEmpty(notebook.cellRuntime[cellId]?.output)) {
27
+ if (expanded && isOutputEmpty(notebook.cellRuntime[cellId]?.output)) {
31
28
  continue;
32
29
  }
33
30
  configs[cellId] = { expand_output: expanded };
@@ -1253,6 +1253,7 @@ describe("useCellNavigationProps", () => {
1253
1253
  ai: {
1254
1254
  ...config.ai,
1255
1255
  models: {
1256
+ ...config.ai.models,
1256
1257
  displayed_models: [],
1257
1258
  custom_models: [],
1258
1259
  edit_model: "openai/gpt-4o",
@@ -18,7 +18,7 @@ function renderBanner(sharing?: {
18
18
  store.set(filenameAtom, "/notebooks/my notebook.py");
19
19
  store.set(userConfigAtom, {
20
20
  ...defaultUserConfig(),
21
- sharing,
21
+ sharing: sharing ?? null,
22
22
  });
23
23
  window.__MARIMO_STATIC__ = { files: {} };
24
24
 
@@ -1,5 +1,7 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
 
3
+ import { defaultUserConfig } from "@/core/config/config-schema";
4
+
3
5
  import { EditorState } from "@codemirror/state";
4
6
  import { EditorView } from "@codemirror/view";
5
7
  import { getDefaultStore } from "jotai";
@@ -35,6 +37,7 @@ function createMockEditorView(code: string): EditorView {
35
37
  adaptiveLanguageConfiguration({
36
38
  cellId: cellId("cell1"),
37
39
  completionConfig: {
40
+ ...defaultUserConfig().completion,
38
41
  copilot: false,
39
42
  activate_on_typing: true,
40
43
  signature_hint_on_typing: false,
@@ -42,11 +45,12 @@ function createMockEditorView(code: string): EditorView {
42
45
  },
43
46
  hotkeys: new OverridingHotkeyProvider({}),
44
47
  placeholderType: "marimo-import",
45
- lspConfig: {},
48
+ lspConfig: { ...defaultUserConfig().language_servers },
46
49
  }),
47
50
  cellConfigExtension({
48
51
  cellId: cellId("cell1"),
49
52
  completionConfig: {
53
+ ...defaultUserConfig().completion,
50
54
  copilot: false,
51
55
  activate_on_typing: true,
52
56
  signature_hint_on_typing: false,
@@ -54,8 +58,8 @@ function createMockEditorView(code: string): EditorView {
54
58
  },
55
59
  hotkeys: new OverridingHotkeyProvider({}),
56
60
  placeholderType: "marimo-import",
57
- lspConfig: {},
58
- diagnosticsConfig: {},
61
+ lspConfig: { ...defaultUserConfig().language_servers },
62
+ diagnosticsConfig: { ...defaultUserConfig().diagnostics },
59
63
  }),
60
64
  ],
61
65
  }),
@@ -1,5 +1,7 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
 
3
+ import { defaultUserConfig } from "@/core/config/config-schema";
4
+
3
5
  import { python } from "@codemirror/lang-python";
4
6
  import { EditorState } from "@codemirror/state";
5
7
  import { EditorView } from "@codemirror/view";
@@ -88,6 +90,7 @@ function createEditor(content: string) {
88
90
  adaptiveLanguageConfiguration({
89
91
  cellId: cellId("cell1"),
90
92
  completionConfig: {
93
+ ...defaultUserConfig().completion,
91
94
  activate_on_typing: true,
92
95
  signature_hint_on_typing: false,
93
96
  copilot: false,
@@ -95,7 +98,7 @@ function createEditor(content: string) {
95
98
  },
96
99
  hotkeys: new OverridingHotkeyProvider({}),
97
100
  placeholderType: "marimo-import",
98
- lspConfig: {},
101
+ lspConfig: { ...defaultUserConfig().language_servers },
99
102
  }),
100
103
  ],
101
104
  });
@@ -1,5 +1,7 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
 
3
+ import { defaultUserConfig } from "@/core/config/config-schema";
4
+
3
5
  /** A store whose notebook follows a document model, as the session wires it. */
4
6
 
5
7
  import { history } from "@codemirror/commands";
@@ -68,6 +70,7 @@ export function setupNotebook(
68
70
  adaptiveLanguageConfiguration({
69
71
  cellId: id as CellId,
70
72
  completionConfig: {
73
+ ...defaultUserConfig().completion,
71
74
  activate_on_typing: true,
72
75
  signature_hint_on_typing: false,
73
76
  copilot: false,
@@ -75,7 +78,7 @@ export function setupNotebook(
75
78
  },
76
79
  hotkeys: new OverridingHotkeyProvider({}),
77
80
  placeholderType: "marimo-import",
78
- lspConfig: {},
81
+ lspConfig: { ...defaultUserConfig().language_servers },
79
82
  }),
80
83
  ],
81
84
  }),
@@ -1,5 +1,7 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
 
3
+ import { defaultUserConfig } from "@/core/config/config-schema";
4
+
3
5
  import { python } from "@codemirror/lang-python";
4
6
  import { EditorState } from "@codemirror/state";
5
7
  import { EditorView } from "@codemirror/view";
@@ -53,6 +55,7 @@ function createEditor(content: string, cellId: CellId) {
53
55
  adaptiveLanguageConfiguration({
54
56
  cellId,
55
57
  completionConfig: {
58
+ ...defaultUserConfig().completion,
56
59
  activate_on_typing: true,
57
60
  signature_hint_on_typing: false,
58
61
  copilot: false,
@@ -60,7 +63,7 @@ function createEditor(content: string, cellId: CellId) {
60
63
  },
61
64
  hotkeys: new OverridingHotkeyProvider({}),
62
65
  placeholderType: "marimo-import",
63
- lspConfig: {},
66
+ lspConfig: { ...defaultUserConfig().language_servers },
64
67
  }),
65
68
  cellIdState.of(cellId),
66
69
  ],
@@ -1,5 +1,7 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
 
3
+ import { defaultUserConfig } from "@/core/config/config-schema";
4
+
3
5
  import { EditorState, type Extension } from "@codemirror/state";
4
6
  import { EditorView, keymap } from "@codemirror/view";
5
7
  import { describe, expect, test, vi } from "vitest";
@@ -49,6 +51,7 @@ function getOpts() {
49
51
  afterToggleSQL: namedFunction("afterToggleSQL"),
50
52
  } as unknown as CodemirrorCellActions,
51
53
  completionConfig: {
54
+ ...defaultUserConfig().completion,
52
55
  activate_on_typing: false,
53
56
  signature_hint_on_typing: false,
54
57
  copilot: false,
@@ -60,13 +63,12 @@ function getOpts() {
60
63
  },
61
64
  lspConfig: {
62
65
  pylsp: {
66
+ ...defaultUserConfig().language_servers.pylsp,
63
67
  enabled: false,
64
68
  },
65
- diagnostics: {
66
- enabled: false,
67
- },
69
+ diagnostics: { ...defaultUserConfig().diagnostics, enabled: false },
68
70
  },
69
- diagnosticsConfig: {},
71
+ diagnosticsConfig: { ...defaultUserConfig().diagnostics },
70
72
  hotkeys: new OverridingHotkeyProvider({}),
71
73
  theme: "light",
72
74
  displayConfig: { reference_highlighting: false, code_lens: true },
@@ -1,5 +1,7 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
 
3
+ import { defaultUserConfig } from "@/core/config/config-schema";
4
+
3
5
  import { EditorView } from "@codemirror/view";
4
6
  import {
5
7
  languageServerWithClient,
@@ -79,6 +81,7 @@ describe("Copilot editor integration", () => {
79
81
  extensions: [
80
82
  languageAdapterState,
81
83
  copilotBundle({
84
+ ...defaultUserConfig().completion,
82
85
  copilot: "custom",
83
86
  activate_on_typing: true,
84
87
  signature_hint_on_typing: false,
@@ -130,6 +133,7 @@ describe("Copilot editor integration", () => {
130
133
  doc: "pri",
131
134
  selection: { anchor: 3 },
132
135
  extensions: copilotBundle({
136
+ ...defaultUserConfig().completion,
133
137
  copilot: "github",
134
138
  activate_on_typing: true,
135
139
  signature_hint_on_typing: false,
@@ -1,5 +1,7 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
 
3
+ import { defaultUserConfig } from "@/core/config/config-schema";
4
+
3
5
  import { EditorState } from "@codemirror/state";
4
6
  import { EditorView } from "@codemirror/view";
5
7
  import { describe, expect, it } from "vitest";
@@ -38,6 +40,7 @@ function createMockEditorView(code: string) {
38
40
  adaptiveLanguageConfiguration({
39
41
  cellId: cellId("cell1"),
40
42
  completionConfig: {
43
+ ...defaultUserConfig().completion,
41
44
  copilot: false,
42
45
  activate_on_typing: true,
43
46
  signature_hint_on_typing: false,
@@ -45,11 +48,12 @@ function createMockEditorView(code: string) {
45
48
  },
46
49
  hotkeys: new OverridingHotkeyProvider({}),
47
50
  placeholderType: "marimo-import",
48
- lspConfig: {},
51
+ lspConfig: { ...defaultUserConfig().language_servers },
49
52
  }),
50
53
  cellConfigExtension({
51
54
  cellId: cellId("cell1"),
52
55
  completionConfig: {
56
+ ...defaultUserConfig().completion,
53
57
  copilot: false,
54
58
  activate_on_typing: true,
55
59
  signature_hint_on_typing: false,
@@ -57,8 +61,8 @@ function createMockEditorView(code: string) {
57
61
  },
58
62
  hotkeys: new OverridingHotkeyProvider({}),
59
63
  placeholderType: "marimo-import",
60
- lspConfig: {},
61
- diagnosticsConfig: {},
64
+ lspConfig: { ...defaultUserConfig().language_servers },
65
+ diagnosticsConfig: { ...defaultUserConfig().diagnostics },
62
66
  }),
63
67
  ],
64
68
  }),
@@ -1,4 +1,6 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
+
3
+ import { defaultUserConfig } from "@/core/config/config-schema";
2
4
  // @vitest-environment jsdom
3
5
 
4
6
  import { EditorState } from "@codemirror/state";
@@ -39,18 +41,20 @@ function createState(content: string, selection?: { anchor: number }) {
39
41
  adaptiveLanguageConfiguration({
40
42
  cellId: "cell1" as CellId,
41
43
  completionConfig: {
44
+ ...defaultUserConfig().completion,
42
45
  copilot: false,
43
46
  activate_on_typing: true,
44
47
  signature_hint_on_typing: false,
45
48
  codeium_api_key: null,
46
49
  },
47
- lspConfig: {},
50
+ lspConfig: { ...defaultUserConfig().language_servers },
48
51
  hotkeys: new OverridingHotkeyProvider({}),
49
52
  placeholderType: "marimo-import",
50
53
  }),
51
54
  cellConfigExtension({
52
55
  cellId: "cell1" as CellId,
53
56
  completionConfig: {
57
+ ...defaultUserConfig().completion,
54
58
  copilot: false,
55
59
  activate_on_typing: true,
56
60
  signature_hint_on_typing: false,
@@ -58,8 +62,8 @@ function createState(content: string, selection?: { anchor: number }) {
58
62
  },
59
63
  hotkeys: new OverridingHotkeyProvider({}),
60
64
  placeholderType: "marimo-import",
61
- lspConfig: {},
62
- diagnosticsConfig: {},
65
+ lspConfig: { ...defaultUserConfig().language_servers },
66
+ diagnosticsConfig: { ...defaultUserConfig().diagnostics },
63
67
  }),
64
68
  ],
65
69
  selection,
@@ -1,5 +1,7 @@
1
1
  /* Copyright 2026 Marimo. All rights reserved. */
2
2
 
3
+ import { defaultUserConfig } from "@/core/config/config-schema";
4
+
3
5
  import { history, redo, undo } from "@codemirror/commands";
4
6
  import { EditorSelection, EditorState, StateEffect } from "@codemirror/state";
5
7
  import { EditorView } from "@codemirror/view";
@@ -32,6 +34,7 @@ function createEditor(doc: string) {
32
34
  history(),
33
35
  adaptiveLanguageConfiguration({
34
36
  completionConfig: {
37
+ ...defaultUserConfig().completion,
35
38
  activate_on_typing: true,
36
39
  signature_hint_on_typing: false,
37
40
  copilot: false,
@@ -40,11 +43,12 @@ function createEditor(doc: string) {
40
43
  hotkeys: new OverridingHotkeyProvider({}),
41
44
  cellId: cellId("cell1"),
42
45
  placeholderType: "marimo-import",
43
- lspConfig: {},
46
+ lspConfig: { ...defaultUserConfig().language_servers },
44
47
  }),
45
48
  cellConfigExtension({
46
49
  cellId: cellId("cell1"),
47
50
  completionConfig: {
51
+ ...defaultUserConfig().completion,
48
52
  activate_on_typing: true,
49
53
  signature_hint_on_typing: false,
50
54
  copilot: false,
@@ -54,10 +58,11 @@ function createEditor(doc: string) {
54
58
  placeholderType: "marimo-import",
55
59
  lspConfig: {
56
60
  pylsp: {
61
+ ...defaultUserConfig().language_servers.pylsp,
57
62
  enabled: true,
58
63
  },
59
64
  },
60
- diagnosticsConfig: {},
65
+ diagnosticsConfig: { ...defaultUserConfig().diagnostics },
61
66
  }),
62
67
  ],
63
68
  }),