@marimo-team/islands 0.23.14-dev6 → 0.23.14-dev61

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 (171) hide show
  1. package/dist/{ConnectedDataExplorerComponent-Du3_nUzI.js → ConnectedDataExplorerComponent-CU4fZJzG.js} +4 -4
  2. package/dist/assets/__vite-browser-external-BQCLNwri.js +1 -0
  3. package/dist/assets/{worker-DEDLIQQV.js → worker-DAWRHcPq.js} +2 -2
  4. package/dist/{chat-ui-BZxLHwyD.js → chat-ui-DinOvbWu.js} +3248 -3044
  5. package/dist/{click-outside-container-BDd67_1U.js → click-outside-container-BLPjMamz.js} +141 -113
  6. package/dist/{code-visibility-C90Am97q.js → code-visibility-EvXXzjfW.js} +1169 -960
  7. package/dist/data-grid-overlay-editor-C6lxUJp-.js +136 -0
  8. package/dist/{dist-D_bzzWBm.js → dist-Bf9f8MuT.js} +3 -3
  9. package/dist/{formats-d6MhLuQ9.js → formats-Dzx4J_z1.js} +1 -1
  10. package/dist/{glide-data-editor-DkzAInWG.js → glide-data-editor-CjTu7ukN.js} +2084 -1889
  11. package/dist/{html-to-image-CGp_08St.js → html-to-image-_wGfk8V-.js} +2389 -2322
  12. package/dist/{input-CbEz_aj_.js → input-DtsN7xm-.js} +1 -1
  13. package/dist/main.js +3630 -1801
  14. package/dist/{mermaid-CJW9vIyO.js → mermaid-BYqXy_NE.js} +2 -2
  15. package/dist/{number-overlay-editor-D-a0qCT8.js → number-overlay-editor-BLJXvX9c.js} +1 -1
  16. package/dist/{process-output-R6JsYrv3.js → process-output-Mh4UrjwM.js} +1 -1
  17. package/dist/{reveal-component-C_u9FY4_.js → reveal-component-CKfV5wlk.js} +600 -596
  18. package/dist/{spec-Bv-XlYiv.js → spec-Cz-Bj1JI.js} +1 -1
  19. package/dist/style.css +1 -1
  20. package/dist/{toDate-D-l5s8nn.js → toDate-CWNNlFEX.js} +15 -7
  21. package/dist/{useAsyncData-1Dhzjfwf.js → useAsyncData-KfHB8wQR.js} +1 -1
  22. package/dist/{useDeepCompareMemoize-CDWT3BDz.js → useDeepCompareMemoize-nJMtxhm4.js} +1 -1
  23. package/dist/{useLifecycle-AHlswLw-.js → useLifecycle-DegSo0lV.js} +1 -1
  24. package/dist/{useTheme-BrYvK-_A.js → useTheme-6eZ3GOTS.js} +31 -26
  25. package/dist/{vega-component-Pk6lyc_a.js → vega-component-DzyyM9fc.js} +5 -5
  26. package/package.json +4 -4
  27. package/src/__mocks__/requests.ts +1 -0
  28. package/src/__tests__/CellStatus.test.tsx +1 -2
  29. package/src/components/app-config/user-config-form.tsx +52 -0
  30. package/src/components/chat/acp/agent-panel.tsx +35 -1
  31. package/src/components/chat/chat-panel.tsx +68 -29
  32. package/src/components/data-table/__tests__/column-explorer.test.tsx +25 -0
  33. package/src/components/data-table/__tests__/column-visibility-dropdown.test.tsx +60 -3
  34. package/src/components/data-table/charts/__tests__/altair-generator.test.ts +24 -0
  35. package/src/components/data-table/charts/__tests__/merge-index-fields.test.ts +33 -0
  36. package/src/components/data-table/charts/chart-spec/altair-generator.ts +4 -1
  37. package/src/components/data-table/charts/charts.tsx +23 -1
  38. package/src/components/data-table/column-explorer-panel/column-explorer.tsx +33 -12
  39. package/src/components/data-table/column-visibility-dropdown.tsx +15 -0
  40. package/src/components/debugger/debugger-code.tsx +7 -2
  41. package/src/components/editor/actions/useNotebookActions.tsx +2 -2
  42. package/src/components/editor/cell/CellStatus.tsx +1 -20
  43. package/src/components/editor/cell/PendingDeleteConfirmation.tsx +1 -1
  44. package/src/components/editor/cell/cell-context-menu.tsx +2 -2
  45. package/src/components/editor/chrome/panels/snippets-panel.tsx +3 -3
  46. package/src/components/editor/chrome/wrapper/__tests__/useOpenAiAssistant.test.ts +36 -0
  47. package/src/components/editor/chrome/wrapper/footer-items/pyodide-status.tsx +6 -36
  48. package/src/components/editor/chrome/wrapper/useAiPanel.ts +3 -1
  49. package/src/components/editor/chrome/wrapper/useOpenAiAssistant.ts +88 -0
  50. package/src/components/editor/code/__tests__/readonly-python-code.test.tsx +79 -0
  51. package/src/components/editor/code/readonly-python-code.tsx +60 -33
  52. package/src/components/editor/errors/__tests__/auto-fix.test.ts +23 -0
  53. package/src/components/editor/errors/auto-fix.tsx +88 -34
  54. package/src/components/editor/errors/fix-mode.ts +1 -1
  55. package/src/components/editor/notebook-cell.tsx +7 -0
  56. package/src/components/editor/output/ImageOutput.tsx +20 -6
  57. package/src/components/editor/output/MarimoTracebackOutput.tsx +28 -2
  58. package/src/components/editor/output/__tests__/ImageOutput.test.tsx +53 -0
  59. package/src/components/editor/output/__tests__/traceback.test.tsx +14 -6
  60. package/src/components/editor/renderers/grid-layout/grid-layout.tsx +7 -2
  61. package/src/components/editor/renderers/vertical-layout/vertical-layout.tsx +7 -3
  62. package/src/components/lifecycle/ProgressiveBoundary.tsx +42 -0
  63. package/src/components/lifecycle/RuntimeStatusBadge.tsx +59 -0
  64. package/src/components/lifecycle/__tests__/ProgressiveBoundary.test.tsx +147 -0
  65. package/src/components/lifecycle/__tests__/RuntimeStatusBadge.test.tsx +72 -0
  66. package/src/components/slides/__tests__/slide.test.tsx +33 -0
  67. package/src/components/slides/minimap.tsx +7 -1
  68. package/src/components/slides/reveal-component.tsx +3 -0
  69. package/src/components/slides/slide-cell-view.tsx +10 -6
  70. package/src/components/slides/slide.tsx +16 -13
  71. package/src/components/tracing/tracing.tsx +2 -1
  72. package/src/core/ai/config.ts +2 -2
  73. package/src/core/ai/context/__tests__/registry.test.ts +133 -3
  74. package/src/core/ai/context/providers/__tests__/datasource.test.ts +3 -1
  75. package/src/core/ai/context/providers/__tests__/error.test.ts +200 -15
  76. package/src/core/ai/context/providers/datasource.ts +27 -2
  77. package/src/core/ai/context/providers/error.ts +226 -36
  78. package/src/core/ai/context/registry.ts +77 -43
  79. package/src/core/ai/state.ts +11 -0
  80. package/src/core/cells/__tests__/cell.test.ts +39 -0
  81. package/src/core/cells/__tests__/readonly-code-display.test.ts +46 -0
  82. package/src/core/cells/cell.ts +5 -3
  83. package/src/core/cells/readonly-code-display.ts +35 -0
  84. package/src/core/codemirror/__tests__/setup.test.ts +33 -1
  85. package/src/core/codemirror/ai/resources.ts +15 -10
  86. package/src/core/codemirror/cells/__tests__/debugger-decorations.test.ts +185 -0
  87. package/src/core/codemirror/cells/__tests__/debugger-state.test.ts +224 -0
  88. package/src/core/codemirror/cells/__tests__/line-timing-decorations.test.ts +126 -0
  89. package/src/core/codemirror/cells/debugger-decorations.ts +188 -0
  90. package/src/core/codemirror/cells/debugger-state.ts +133 -0
  91. package/src/core/codemirror/cells/extensions.ts +32 -4
  92. package/src/core/codemirror/cells/line-timing-decorations.ts +165 -0
  93. package/src/core/codemirror/go-to-definition/__tests__/utils.test.ts +75 -3
  94. package/src/core/codemirror/go-to-definition/extension.ts +3 -3
  95. package/src/core/codemirror/go-to-definition/underline.ts +5 -14
  96. package/src/core/codemirror/go-to-definition/utils.ts +49 -1
  97. package/src/core/codemirror/utils.ts +15 -0
  98. package/src/core/config/__tests__/config-schema.test.ts +17 -0
  99. package/src/core/config/config-schema.ts +1 -0
  100. package/src/core/config/config.ts +10 -0
  101. package/src/core/config/feature-flag.tsx +4 -0
  102. package/src/core/edit-app.tsx +8 -5
  103. package/src/core/errors/errors.ts +2 -1
  104. package/src/core/islands/bootstrap.ts +4 -3
  105. package/src/core/islands/bridge.ts +1 -0
  106. package/src/core/lifecycle/__tests__/render-policy.test.ts +247 -0
  107. package/src/core/lifecycle/render-policy.ts +125 -0
  108. package/src/core/mime.ts +11 -4
  109. package/src/core/network/__tests__/api.test.ts +17 -0
  110. package/src/core/network/__tests__/requests-toasting.test.tsx +46 -0
  111. package/src/core/network/api.ts +17 -6
  112. package/src/core/network/requests-lazy.ts +1 -0
  113. package/src/core/network/requests-network.ts +8 -0
  114. package/src/core/network/requests-static.ts +1 -0
  115. package/src/core/network/requests-toasting.tsx +10 -1
  116. package/src/core/network/types.ts +2 -0
  117. package/src/core/run-app.tsx +27 -23
  118. package/src/core/runtime/__tests__/adapter.test.ts +160 -0
  119. package/src/core/runtime/__tests__/runtime.test.ts +45 -0
  120. package/src/core/runtime/adapter.ts +182 -0
  121. package/src/core/runtime/runtime.ts +30 -16
  122. package/src/core/wasm/PyodideLoader.tsx +20 -62
  123. package/src/core/wasm/bridge.ts +13 -4
  124. package/src/core/wasm/state.ts +8 -19
  125. package/src/core/websocket/__tests__/useMarimoKernelConnection.test.ts +4 -0
  126. package/src/core/websocket/__tests__/useWebSocket.test.ts +49 -0
  127. package/src/core/websocket/transports/__tests__/sse.test.ts +338 -0
  128. package/src/core/websocket/transports/sse.ts +308 -0
  129. package/src/core/websocket/useMarimoKernelConnection.tsx +58 -7
  130. package/src/core/websocket/useWebSocket.tsx +12 -2
  131. package/src/css/app/codemirror.css +14 -0
  132. package/src/hooks/__tests__/useDelayElapsed.test.tsx +55 -0
  133. package/src/hooks/useDelayElapsed.ts +27 -0
  134. package/src/mount.tsx +3 -3
  135. package/src/plugins/core/RenderHTML.tsx +35 -1
  136. package/src/plugins/core/__test__/RenderHTML.test.ts +44 -0
  137. package/src/plugins/impl/DataTablePlugin.tsx +1 -0
  138. package/src/plugins/impl/anywidget/AnyWidgetPlugin.tsx +33 -254
  139. package/src/plugins/impl/anywidget/__tests__/AnyWidgetPlugin.test.tsx +116 -174
  140. package/src/plugins/impl/anywidget/__tests__/host.test.ts +313 -0
  141. package/src/plugins/impl/anywidget/__tests__/model-proxy.test.ts +158 -0
  142. package/src/plugins/impl/anywidget/__tests__/model.test.ts +8 -177
  143. package/src/plugins/impl/anywidget/__tests__/registry.test.ts +708 -0
  144. package/src/plugins/impl/anywidget/__tests__/resolve-widget.test.ts +132 -0
  145. package/src/plugins/impl/anywidget/__tests__/widget-binding.test.ts +305 -133
  146. package/src/plugins/impl/anywidget/__tests__/widget-ref.test.ts +28 -0
  147. package/src/plugins/impl/anywidget/host.ts +54 -0
  148. package/src/plugins/impl/anywidget/model-proxy.ts +70 -0
  149. package/src/plugins/impl/anywidget/model.ts +59 -239
  150. package/src/plugins/impl/anywidget/registry.ts +268 -0
  151. package/src/plugins/impl/anywidget/resolve-widget.ts +138 -0
  152. package/src/plugins/impl/anywidget/runtime.ts +422 -0
  153. package/src/plugins/impl/anywidget/types.ts +14 -0
  154. package/src/plugins/impl/anywidget/widget-binding.ts +280 -119
  155. package/src/plugins/impl/anywidget/widget-ref.ts +29 -0
  156. package/src/plugins/impl/data-editor/__tests__/glide-data-editor.test.tsx +187 -0
  157. package/src/plugins/impl/data-editor/glide-data-editor.tsx +6 -0
  158. package/src/plugins/impl/data-editor/glide-portal.tsx +73 -0
  159. package/src/plugins/impl/mpl-interactive/MplInteractivePlugin.tsx +3 -2
  160. package/src/plugins/impl/mpl-interactive/__tests__/MplInteractivePlugin.test.tsx +16 -13
  161. package/src/plugins/impl/mpl-interactive/mpl-websocket-shim.ts +1 -1
  162. package/src/utils/errors.ts +15 -0
  163. package/src/utils/time.ts +20 -0
  164. package/dist/assets/__vite-browser-external-DAm_YW43.js +0 -1
  165. package/dist/data-grid-overlay-editor-mfEJ5475.js +0 -128
  166. package/src/components/editor/chrome/panels/__tests__/snippet-display.test.ts +0 -22
  167. package/src/components/editor/chrome/panels/snippet-display.ts +0 -27
  168. package/src/core/ai/context/providers/__tests__/__snapshots__/error.test.ts.snap +0 -3
  169. package/src/core/wasm/__tests__/PyodideLoader.test.ts +0 -72
  170. package/src/core/wasm/__tests__/state.test.ts +0 -124
  171. package/src/plugins/impl/anywidget/schemas.ts +0 -32
@@ -6,7 +6,7 @@ import { _ as Logger } from "./button-BacYv-bE.js";
6
6
  import { t as require_compiler_runtime } from "./compiler-runtime-CEbnTgxf.js";
7
7
  import { u as createLucideIcon } from "./dist--2Bqjvs0.js";
8
8
  import { r as KnownQueryParams } from "./constants-T20xxyNf.js";
9
- import { b as atom, d as store, m as isIslands, p as waitFor } from "./useTheme-BrYvK-_A.js";
9
+ import { S as atom, g as isIslands, h as waitFor, p as store } from "./useTheme-6eZ3GOTS.js";
10
10
  import { t as invariant } from "./invariant-wRzNXIsJ.js";
11
11
  var CircleQuestionMark = createLucideIcon("circle-question-mark", [
12
12
  ["circle", {
@@ -529,17 +529,25 @@ var RuntimeManager = class {
529
529
  });
530
530
  return !this.isSameOrigin && this.config.authToken && x.searchParams.set(KnownQueryParams.accessToken, this.config.authToken), asWsUrl(x.toString());
531
531
  }
532
- getWsURL(e) {
532
+ getSessionSearchParams(e) {
533
533
  let b = new URL(this.config.url), x = new URLSearchParams(b.search);
534
534
  return new URLSearchParams(window.location.search).forEach((e2, b2) => {
535
535
  x.has(b2) || x.set(b2, e2);
536
- }), x.set(KnownQueryParams.sessionId, e), this.formatWsURL("/ws", x);
536
+ }), x.set(KnownQueryParams.sessionId, e), x;
537
+ }
538
+ getWsURL(e) {
539
+ return this.formatWsURL("/ws", this.getSessionSearchParams(e));
540
+ }
541
+ getSseURL(e) {
542
+ let b = this.formatHttpURL({
543
+ path: "/sse",
544
+ searchParams: this.getSessionSearchParams(e),
545
+ restrictToKnownQueryParams: false
546
+ });
547
+ return b.searchParams.delete(KnownQueryParams.accessToken), b;
537
548
  }
538
549
  getWsSyncURL(e) {
539
- let b = new URL(this.config.url), x = new URLSearchParams(b.search);
540
- return new URLSearchParams(window.location.search).forEach((e2, b2) => {
541
- x.has(b2) || x.set(b2, e2);
542
- }), x.set(KnownQueryParams.sessionId, e), this.formatWsURL("/ws_sync", x);
550
+ return this.formatWsURL("/ws_sync", this.getSessionSearchParams(e));
543
551
  }
544
552
  getTerminalWsURL() {
545
553
  return this.formatWsURL("/terminal/ws");
@@ -1,7 +1,7 @@
1
1
  import { s as __toESM } from "./chunk-BNovOVIE.js";
2
2
  import { t as require_react } from "./react-DA-nE2FX.js";
3
3
  import { t as require_compiler_runtime } from "./compiler-runtime-CEbnTgxf.js";
4
- import { T as useEvent_default } from "./useTheme-BrYvK-_A.js";
4
+ import { D as useEvent_default } from "./useTheme-6eZ3GOTS.js";
5
5
  import { t as invariant } from "./invariant-wRzNXIsJ.js";
6
6
  var import_compiler_runtime = require_compiler_runtime(), import_react = /* @__PURE__ */ __toESM(require_react(), 1), Result = {
7
7
  error(e, s) {
@@ -1,6 +1,6 @@
1
1
  import { s as __toESM } from "./chunk-BNovOVIE.js";
2
2
  import { t as require_react } from "./react-DA-nE2FX.js";
3
- import { w as dequal } from "./useTheme-BrYvK-_A.js";
3
+ import { E as dequal } from "./useTheme-6eZ3GOTS.js";
4
4
  var import_react = /* @__PURE__ */ __toESM(require_react(), 1);
5
5
  function useDeepCompareMemoize(e) {
6
6
  let i = import_react.useRef(e);
@@ -4,7 +4,7 @@ import { t as require_react } from "./react-DA-nE2FX.js";
4
4
  import { t as require_compiler_runtime } from "./compiler-runtime-CEbnTgxf.js";
5
5
  import { u as createLucideIcon } from "./dist--2Bqjvs0.js";
6
6
  import { t as require_jsx_runtime } from "./jsx-runtime-DebpN0FN.js";
7
- import { b as atom, v as useSetAtom } from "./useTheme-BrYvK-_A.js";
7
+ import { S as atom, b as useSetAtom } from "./useTheme-6eZ3GOTS.js";
8
8
  var Calendar = createLucideIcon("calendar", [
9
9
  ["path", {
10
10
  d: "M8 2v4",
@@ -637,7 +637,10 @@ const UserConfigSchema = looseObject({
637
637
  markdown: boolean().optional(),
638
638
  rtc: boolean().optional()
639
639
  }).prefault(() => ({})),
640
- server: looseObject({ disable_file_downloads: boolean().optional() }).prefault(() => ({})),
640
+ server: looseObject({
641
+ disable_file_downloads: boolean().optional(),
642
+ transport: _enum(["websocket", "sse"]).optional()
643
+ }).prefault(() => ({})),
641
644
  diagnostics: looseObject({
642
645
  enabled: boolean().optional(),
643
646
  sql_linter: boolean().optional()
@@ -701,7 +704,7 @@ const userConfigAtom = atom(defaultUserConfig()), configOverridesAtom = atom({})
701
704
  let A = e(configOverridesAtom);
702
705
  return merge_default({}, e(userConfigAtom), A);
703
706
  }), autoInstantiateAtom = atom((e) => e(resolvedMarimoConfigAtom).runtime.auto_instantiate), hotkeyOverridesAtom = atom((e) => e(resolvedMarimoConfigAtom).keymap.overrides ?? {}), platformAtom = atom(resolvePlatform());
704
- atom((e) => new OverridingHotkeyProvider(e(hotkeyOverridesAtom), { platform: e(platformAtom) })), atom((e) => e(resolvedMarimoConfigAtom).save), atom((e) => e(resolvedMarimoConfigAtom).ai), atom((e) => e(resolvedMarimoConfigAtom).completion), atom((e) => e(resolvedMarimoConfigAtom).keymap.preset);
707
+ atom((e) => new OverridingHotkeyProvider(e(hotkeyOverridesAtom), { platform: e(platformAtom) })), atom((e) => e(resolvedMarimoConfigAtom).save), atom((e) => e(resolvedMarimoConfigAtom).server.transport === "sse" ? "sse" : "websocket"), atom((e) => e(resolvedMarimoConfigAtom).ai), atom((e) => e(resolvedMarimoConfigAtom).completion), atom((e) => e(resolvedMarimoConfigAtom).keymap.preset);
705
708
  function useResolvedMarimoConfig() {
706
709
  let e = (0, import_compiler_runtime$1.c)(3), A = useAtomValue(resolvedMarimoConfigAtom), j = useSetAtom(userConfigAtom), M;
707
710
  return e[0] !== A || e[1] !== j ? (M = [A, j], e[0] = A, e[1] = j, e[2] = M) : M = e[2], M;
@@ -709,8 +712,8 @@ function useResolvedMarimoConfig() {
709
712
  function getResolvedMarimoConfig() {
710
713
  return store.get(resolvedMarimoConfigAtom);
711
714
  }
712
- atom((e) => isAiEnabled(e(resolvedMarimoConfigAtom))), atom((e) => isAiModelConfigured(e(resolvedMarimoConfigAtom)));
713
- const aiFeaturesEnabledAtom = atom((e) => isAiFeatureEnabled(e(resolvedMarimoConfigAtom)));
715
+ atom((e) => isAiEnabled(e(resolvedMarimoConfigAtom)));
716
+ const aiModelConfiguredAtom = atom((e) => isAiModelConfigured(e(resolvedMarimoConfigAtom))), aiFeaturesEnabledAtom = atom((e) => isAiFeatureEnabled(e(resolvedMarimoConfigAtom)));
714
717
  atom((e) => e(resolvedMarimoConfigAtom).display.code_editor_font_size);
715
718
  const localeAtom = atom((e) => e(resolvedMarimoConfigAtom).display.locale);
716
719
  function isAiEnabled(e) {
@@ -790,29 +793,31 @@ function useTheme() {
790
793
  return e[1] === j ? M = e[2] : (M = { theme: j }, e[1] = j, e[2] = M), M;
791
794
  }
792
795
  export {
793
- getBuildingBlocks as C,
794
- buildStore as S,
795
- useEvent_default as T,
796
- useAtomValue as _,
797
- getResolvedMarimoConfig as a,
798
- atom as b,
799
- useResolvedMarimoConfig as c,
800
- store as d,
801
- useJotaiEffect as f,
802
- useAtom as g,
803
- Provider as h,
804
- autoInstantiateAtom as i,
805
- AppConfigSchema as l,
806
- isIslands as m,
796
+ createStore as C,
797
+ useEvent_default as D,
798
+ dequal as E,
799
+ atom as S,
800
+ getBuildingBlocks as T,
801
+ Provider as _,
802
+ autoInstantiateAtom as a,
803
+ useSetAtom as b,
804
+ resolvedMarimoConfigAtom as c,
805
+ AppConfigSchema as d,
806
+ createDeepEqualAtom as f,
807
+ isIslands as g,
808
+ waitFor as h,
809
+ aiModelConfiguredAtom as i,
810
+ useResolvedMarimoConfig as l,
811
+ useJotaiEffect as m,
807
812
  useTheme as n,
808
- localeAtom as o,
809
- waitFor as p,
813
+ getResolvedMarimoConfig as o,
814
+ store as p,
810
815
  aiFeaturesEnabledAtom as r,
811
- resolvedMarimoConfigAtom as s,
816
+ localeAtom as s,
812
817
  resolvedThemeAtom as t,
813
- createDeepEqualAtom as u,
814
- useSetAtom as v,
815
- dequal as w,
816
- createStore as x,
817
- useStore as y
818
+ userConfigAtom as u,
819
+ useAtom as v,
820
+ buildStore as w,
821
+ useStore as x,
822
+ useAtomValue as y
818
823
  };
@@ -2,23 +2,23 @@ import { s as __toESM } from "./chunk-BNovOVIE.js";
2
2
  import { _ as Logger, c as Objects, g as cn, h as Events } from "./button-BacYv-bE.js";
3
3
  import { t as require_react } from "./react-DA-nE2FX.js";
4
4
  import { t as require_compiler_runtime } from "./compiler-runtime-CEbnTgxf.js";
5
- import { c as asRemoteURL, v as CircleQuestionMark } from "./toDate-D-l5s8nn.js";
5
+ import { c as asRemoteURL, v as CircleQuestionMark } from "./toDate-CWNNlFEX.js";
6
6
  import "./react-dom-BTJzcVJ9.js";
7
7
  import { t as require_jsx_runtime } from "./jsx-runtime-DebpN0FN.js";
8
8
  import "./zod-CijjQh4u.js";
9
9
  import { n as ErrorBanner } from "./error-banner-DFPfz_Qf.js";
10
10
  import { t as Tooltip } from "./tooltip-Czds6Qr8.js";
11
11
  import { i as debounce_default } from "./constants-T20xxyNf.js";
12
- import { T as useEvent_default, n as useTheme } from "./useTheme-BrYvK-_A.js";
12
+ import { D as useEvent_default, n as useTheme } from "./useTheme-6eZ3GOTS.js";
13
13
  import { s as uniq } from "./arrays-sEtDRoG4.js";
14
- import { a as isValid, i as AlertTitle, n as Alert, t as arrow } from "./formats-d6MhLuQ9.js";
14
+ import { a as isValid, i as AlertTitle, n as Alert, t as arrow } from "./formats-Dzx4J_z1.js";
15
15
  import { n as formats } from "./vega-loader.browser-CZ-J8Py3.js";
16
16
  import { a as getContainerWidth, n as vegaLoadData, s as tooltipHandler } from "./loader-Boph2xIS.js";
17
17
  import { t as j } from "./react-vega-B0sAlDTL.js";
18
18
  import "./defaultLocale-u-3osm0P.js";
19
19
  import "./defaultLocale-BoHTsDG6.js";
20
- import { t as useAsyncData } from "./useAsyncData-1Dhzjfwf.js";
21
- import { t as useDeepCompareMemoize } from "./useDeepCompareMemoize-CDWT3BDz.js";
20
+ import { t as useAsyncData } from "./useAsyncData-KfHB8wQR.js";
21
+ import { t as useDeepCompareMemoize } from "./useDeepCompareMemoize-nJMtxhm4.js";
22
22
  import { t as Semaphore } from "./semaphore-CNDGTzkX.js";
23
23
  var import_compiler_runtime = require_compiler_runtime(), import_react = /* @__PURE__ */ __toESM(require_react(), 1);
24
24
  function fixRelativeUrl(e) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marimo-team/islands",
3
- "version": "0.23.14-dev6",
3
+ "version": "0.23.14-dev61",
4
4
  "main": "dist/main.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -22,7 +22,7 @@
22
22
  },
23
23
  "dependencies": {
24
24
  "@ai-sdk/react": "^3.0.134",
25
- "@anywidget/types": "^0.2.0",
25
+ "@anywidget/types": "^0.4.0",
26
26
  "@codemirror/autocomplete": "^6.20.1",
27
27
  "@codemirror/commands": "^6.10.2",
28
28
  "@codemirror/lang-markdown": "^6.5.0",
@@ -45,7 +45,7 @@
45
45
  "@dnd-kit/utilities": "^3.2.2",
46
46
  "@emotion/cache": "^11.14.0",
47
47
  "@emotion/react": "^11.14.0",
48
- "@glideapps/glide-data-grid": "6.0.4-alpha9",
48
+ "@glideapps/glide-data-grid": "6.0.4-alpha24",
49
49
  "@hookform/resolvers": "^5.2.2",
50
50
  "@img-comparison-slider/react": "^8.0.2",
51
51
  "@internationalized/date": "^3.10.1",
@@ -56,7 +56,7 @@
56
56
  "@lezer/python": "^1.1.18",
57
57
  "@marimo-team/codemirror-ai": "^0.3.7",
58
58
  "@marimo-team/codemirror-languageserver": "^1.16.12",
59
- "@marimo-team/codemirror-mcp": "^0.1.5",
59
+ "@marimo-team/codemirror-mcp": "^0.1.7",
60
60
  "@marimo-team/codemirror-sql": "^0.2.8",
61
61
  "@marimo-team/llm-info": "workspace:*",
62
62
  "@marimo-team/marimo-api": "workspace:*",
@@ -45,6 +45,7 @@ export const MockRequestClient = {
45
45
  openFile: vi.fn().mockResolvedValue({}),
46
46
  getUsageStats: vi.fn().mockResolvedValue({}),
47
47
  sendPdb: vi.fn().mockResolvedValue({}),
48
+ sendSetBreakpoints: vi.fn().mockResolvedValue({}),
48
49
  sendListFiles: vi.fn().mockResolvedValue({ files: [] }),
49
50
  sendSearchFiles: vi
50
51
  .fn()
@@ -3,11 +3,10 @@
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 { Seconds } from "@/utils/time";
6
+ import { formatElapsedTime, type Seconds } from "@/utils/time";
7
7
  import {
8
8
  CellStatusComponent,
9
9
  ElapsedTime,
10
- formatElapsedTime,
11
10
  } from "../components/editor/cell/CellStatus";
12
11
 
13
12
  // Mock date-fns to have consistent date formatting in tests
@@ -1288,6 +1288,58 @@ export const UserConfigForm: React.FC = () => {
1288
1288
  </div>
1289
1289
  )}
1290
1290
  />
1291
+ <OverriddenFormField
1292
+ control={form.control}
1293
+ name="experimental.debugger"
1294
+ render={({ field, override }) => (
1295
+ <div className="flex flex-col gap-y-1">
1296
+ <FormItem className={formItemClasses}>
1297
+ <FormLabel className="font-normal">Debugger</FormLabel>
1298
+ <FormControl>
1299
+ <Checkbox
1300
+ data-testid="debugger-checkbox"
1301
+ checked={override.value === true}
1302
+ disabled={override.isOverridden}
1303
+ onCheckedChange={field.onChange}
1304
+ />
1305
+ </FormControl>
1306
+ </FormItem>
1307
+ <IsOverridden override={override} />
1308
+ <FormDescription>
1309
+ Enable the live debugger: a clickable breakpoint gutter,
1310
+ current-line highlighting while a cell runs, and dropping
1311
+ into <Kbd className="inline">pdb</Kbd> at breakpoints. This
1312
+ change requires a page refresh to take effect.
1313
+ </FormDescription>
1314
+ </div>
1315
+ )}
1316
+ />
1317
+ <OverriddenFormField
1318
+ control={form.control}
1319
+ name="experimental.line_timing"
1320
+ render={({ field, override }) => (
1321
+ <div className="flex flex-col gap-y-1">
1322
+ <FormItem className={formItemClasses}>
1323
+ <FormLabel className="font-normal">Line Timing</FormLabel>
1324
+ <FormControl>
1325
+ <Checkbox
1326
+ data-testid="line-timing-checkbox"
1327
+ checked={override.value === true}
1328
+ disabled={override.isOverridden}
1329
+ onCheckedChange={field.onChange}
1330
+ />
1331
+ </FormControl>
1332
+ </FormItem>
1333
+ <IsOverridden override={override} />
1334
+ <FormDescription>
1335
+ Highlight the line a cell is currently executing in green,
1336
+ with an elapsed timer next to long-running lines. Adds
1337
+ tracing overhead to every run while enabled. This change
1338
+ requires a page refresh to take effect.
1339
+ </FormDescription>
1340
+ </div>
1341
+ )}
1342
+ />
1291
1343
  </SettingGroup>
1292
1344
  );
1293
1345
  }
@@ -49,6 +49,7 @@ import {
49
49
  addContextCompletion,
50
50
  CONTEXT_TRIGGER,
51
51
  } from "@/components/editor/ai/completion-utils";
52
+ import { pendingAiPromptAtom } from "@/core/ai/state";
52
53
  import {
53
54
  Select,
54
55
  SelectContent,
@@ -72,6 +73,7 @@ import {
72
73
  SendButton,
73
74
  } from "../chat-components";
74
75
  import { useFileState } from "../chat-utils";
76
+ import { focusInputAndMoveToEnd } from "@/core/codemirror/utils";
75
77
  import { ReadyToChatBlock } from "./blocks";
76
78
  import {
77
79
  convertFilesToResourceLinks,
@@ -305,6 +307,7 @@ interface PromptAreaProps {
305
307
  onModeChange?: (mode: string) => void;
306
308
  sessionModels?: SessionModelState | null;
307
309
  onModelChange?: (modelId: string) => void;
310
+ inputRef: React.RefObject<ReactCodeMirrorRef | null>;
308
311
  }
309
312
 
310
313
  const PromptArea = memo<PromptAreaProps>(
@@ -322,8 +325,8 @@ const PromptArea = memo<PromptAreaProps>(
322
325
  onModeChange,
323
326
  sessionModels,
324
327
  onModelChange,
328
+ inputRef,
325
329
  }) => {
326
- const inputRef = useRef<ReactCodeMirrorRef | null>(null);
327
330
  const promptCompletions: AdditionalCompletions | undefined = useMemo(() => {
328
331
  if (!commands) {
329
332
  return undefined;
@@ -660,6 +663,8 @@ const AgentPanel: React.FC = () => {
660
663
  const [isLoading, setIsLoading] = useState(false);
661
664
  const [error, setError] = useState<Error | string | null>(null);
662
665
  const [promptValue, setPromptValue] = useState("");
666
+ const promptInputRef = useRef<ReactCodeMirrorRef | null>(null);
667
+ const [pendingPrompt, setPendingPrompt] = useAtom(pendingAiPromptAtom);
663
668
  const { files, addFiles, clearFiles, removeFile } = useFileState();
664
669
  const [sessionModels, setSessionModels] = useState<SessionModelState | null>(
665
670
  null,
@@ -973,6 +978,34 @@ const AgentPanel: React.FC = () => {
973
978
  },
974
979
  );
975
980
 
981
+ // Consume a prompt queued by another part of the app (e.g. error auto-fix).
982
+ useEffect(() => {
983
+ if (
984
+ !activeSessionId ||
985
+ !agent ||
986
+ isLoading ||
987
+ connectionState.status !== "connected" ||
988
+ !pendingPrompt
989
+ ) {
990
+ return;
991
+ }
992
+ setPendingPrompt(null);
993
+ if (pendingPrompt.submit) {
994
+ void handlePromptSubmit(undefined, pendingPrompt.prompt);
995
+ } else {
996
+ setPromptValue(pendingPrompt.prompt);
997
+ focusInputAndMoveToEnd(promptInputRef);
998
+ }
999
+ }, [
1000
+ activeSessionId,
1001
+ agent,
1002
+ isLoading,
1003
+ connectionState.status,
1004
+ pendingPrompt,
1005
+ setPendingPrompt,
1006
+ handlePromptSubmit,
1007
+ ]);
1008
+
976
1009
  // Handler for stopping the current operation
977
1010
  const handleStop = useEvent(async () => {
978
1011
  if (!activeSessionId || !agent) {
@@ -1187,6 +1220,7 @@ const AgentPanel: React.FC = () => {
1187
1220
  onModeChange={handleModeChange}
1188
1221
  sessionModels={sessionModels}
1189
1222
  onModelChange={handleModelChange}
1223
+ inputRef={promptInputRef}
1190
1224
  />
1191
1225
  </>
1192
1226
  );
@@ -45,6 +45,7 @@ import {
45
45
  type Chat,
46
46
  type ChatId,
47
47
  chatStateAtom,
48
+ pendingAiPromptAtom,
48
49
  } from "@/core/ai/state";
49
50
  import type { ToolNotebookContext } from "@/core/ai/tools/base";
50
51
  import {
@@ -94,6 +95,7 @@ import {
94
95
  useFileState,
95
96
  } from "./chat-utils";
96
97
  import { getCodes } from "@/core/codemirror/copilot/getCodes";
98
+ import { focusInputAndMoveToEnd } from "@/core/codemirror/utils";
97
99
 
98
100
  // Default mode for the AI
99
101
  const DEFAULT_MODE = "manual";
@@ -407,6 +409,7 @@ const ChatInput: React.FC<ChatInputProps> = memo(
407
409
  <div className="relative shrink-0 min-h-[80px] flex flex-col border-t">
408
410
  <div className={cn("px-2 py-3 flex-1", inputClassName)}>
409
411
  <PromptInput
412
+ className="max-h-[400px]"
410
413
  inputRef={inputRef}
411
414
  value={input}
412
415
  onChange={setInput}
@@ -481,6 +484,7 @@ const ChatPanel = () => {
481
484
  const ChatPanelBody = () => {
482
485
  const setChatState = useSetAtom(chatStateAtom);
483
486
  const [activeChat, setActiveChat] = useAtom(activeChatAtom);
487
+ const [pendingPrompt, setPendingPrompt] = useAtom(pendingAiPromptAtom);
484
488
  const [input, setInput] = useState("");
485
489
  const [newThreadInput, setNewThreadInput] = useState("");
486
490
  const { files, addFiles, clearFiles, removeFile } = useFileState();
@@ -600,10 +604,7 @@ const ChatPanelBody = () => {
600
604
  requestAnimationFrame(scrollToBottom);
601
605
  }, [activeChatId]);
602
606
 
603
- const createNewThread = async (
604
- initialMessage: string,
605
- initialAttachments?: File[],
606
- ) => {
607
+ const startNewChatState = useEvent((initialMessage: string) => {
607
608
  const now = Date.now();
608
609
  const newChat: Chat = {
609
610
  id: chatId as ChatId,
@@ -613,41 +614,41 @@ const ChatPanelBody = () => {
613
614
  updatedAt: now,
614
615
  };
615
616
 
616
- // Create new chat and set as active
617
617
  setChatState((prev) => {
618
618
  const newChats = new Map(prev.chats);
619
619
  newChats.set(newChat.id, newChat);
620
- const newState = {
620
+ return {
621
621
  ...prev,
622
622
  chats: newChats,
623
623
  activeChatId: newChat.id,
624
624
  };
625
- return newState;
626
625
  });
626
+ });
627
627
 
628
- const fileParts =
629
- initialAttachments && initialAttachments.length > 0
630
- ? await convertToFileUIPart(initialAttachments)
631
- : undefined;
632
- const { contextPart, attachments } =
633
- await resolveChatContext(initialMessage);
628
+ const createNewThread = useEvent(
629
+ async (initialMessage: string, initialAttachments?: File[]) => {
630
+ startNewChatState(initialMessage);
634
631
 
635
- // Trigger AI conversation with append
636
- sendMessage({
637
- role: "user",
638
- parts: [
639
- {
640
- type: "text" as const,
641
- text: initialMessage,
642
- },
643
- ...(contextPart ? [contextPart] : []),
644
- ...(fileParts ?? []),
645
- ...attachments,
646
- ],
647
- });
648
- clearFiles();
649
- setInput("");
650
- };
632
+ const fileParts =
633
+ initialAttachments && initialAttachments.length > 0
634
+ ? await convertToFileUIPart(initialAttachments)
635
+ : undefined;
636
+ const { contextPart, attachments } =
637
+ await resolveChatContext(initialMessage);
638
+
639
+ sendMessage({
640
+ role: "user",
641
+ parts: [
642
+ { type: "text" as const, text: initialMessage },
643
+ ...(contextPart ? [contextPart] : []),
644
+ ...(fileParts ?? []),
645
+ ...attachments,
646
+ ],
647
+ });
648
+ clearFiles();
649
+ setInput("");
650
+ },
651
+ );
651
652
 
652
653
  const handleNewChat = useEvent(() => {
653
654
  setActiveChat(null);
@@ -728,7 +729,45 @@ const ChatPanelBody = () => {
728
729
 
729
730
  const handleOnCloseThread = () => newThreadInputRef.current?.editor?.blur();
730
731
 
732
+ const submitPendingPrompt = useEvent(async (prompt: string) => {
733
+ if (activeChatId == null) {
734
+ startNewChatState(prompt);
735
+ // Starting a chat swaps the new-thread input for the regular input;
736
+ // carry over any draft the user had typed so it isn't lost.
737
+ setInput(newThreadInput);
738
+ }
739
+ const { contextPart, attachments } = await resolveChatContext(prompt);
740
+ sendMessage({
741
+ role: "user",
742
+ parts: [
743
+ { type: "text", text: prompt },
744
+ ...(contextPart ? [contextPart] : []),
745
+ ...attachments,
746
+ ],
747
+ });
748
+ });
749
+
731
750
  const isNewThread = messages.length === 0;
751
+
752
+ // Deliver a prompt queued elsewhere (e.g. error auto-fix) to the chat,
753
+ // appending to the active thread or starting one if none exists.
754
+ useEffect(() => {
755
+ if (!pendingPrompt) {
756
+ return;
757
+ }
758
+ setPendingPrompt(null);
759
+ const { prompt, submit } = pendingPrompt;
760
+ if (submit) {
761
+ void submitPendingPrompt(prompt);
762
+ } else if (isNewThread) {
763
+ setNewThreadInput(prompt);
764
+ focusInputAndMoveToEnd(newThreadInputRef);
765
+ } else {
766
+ setInput(prompt);
767
+ focusInputAndMoveToEnd(newMessageInputRef);
768
+ }
769
+ }, [pendingPrompt, setPendingPrompt, isNewThread, submitPendingPrompt]);
770
+
732
771
  const chatInput = isNewThread ? (
733
772
  <ChatInput
734
773
  key="new-thread-input"
@@ -126,3 +126,28 @@ describe("ColumnExplorerPanel header counts", () => {
126
126
  expect(screen.queryByText(/hidden/)).not.toBeInTheDocument();
127
127
  });
128
128
  });
129
+
130
+ describe("ColumnExplorerPanel visibility actions", () => {
131
+ const showAll = () => screen.getByRole("button", { name: /Show all/ });
132
+ const hideAll = () => screen.getByRole("button", { name: /Hide all/ });
133
+
134
+ it("disables 'Show all' when every column is visible", () => {
135
+ renderPanel();
136
+ expect(showAll()).toBeDisabled();
137
+ expect(hideAll()).toBeEnabled();
138
+ });
139
+
140
+ it("disables 'Hide all' when every column is hidden", () => {
141
+ renderPanel({
142
+ initiallyHidden: ["customer_name", "cust_age", "order_total"],
143
+ });
144
+ expect(showAll()).toBeEnabled();
145
+ expect(hideAll()).toBeDisabled();
146
+ });
147
+
148
+ it("enables both actions when some columns are hidden", () => {
149
+ renderPanel({ initiallyHidden: ["cust_age"] });
150
+ expect(showAll()).toBeEnabled();
151
+ expect(hideAll()).toBeEnabled();
152
+ });
153
+ });