@marimo-team/islands 0.23.15-dev33 → 0.23.15-dev4

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 (85) hide show
  1. package/dist/{ConnectedDataExplorerComponent-7p7rt9iw.js → ConnectedDataExplorerComponent-CU4fZJzG.js} +4 -4
  2. package/dist/{ErrorBoundary-B_CAG7_e.js → ErrorBoundary-DE6tzZf-.js} +1 -1
  3. package/dist/{ImageComparisonComponent-1i5IBhon.js → ImageComparisonComponent-CHrI72em.js} +129 -173
  4. package/dist/assets/__vite-browser-external-BQCLNwri.js +1 -0
  5. package/dist/assets/worker-DAWRHcPq.js +73 -0
  6. package/dist/{chat-ui-C0wkSwxB.js → chat-ui-DinOvbWu.js} +3111 -3111
  7. package/dist/{code-visibility-BI94mK4u.js → code-visibility-Dk8cVOny.js} +864 -946
  8. package/dist/{debounce-BOD3DbfP.js → constants-T20xxyNf.js} +24 -1
  9. package/dist/{formats-BX3uDQbB.js → formats-Dzx4J_z1.js} +1 -1
  10. package/dist/{glide-data-editor-CwZz71BD.js → glide-data-editor-CjTu7ukN.js} +3 -3
  11. package/dist/{html-to-image-D8Q5SLSJ.js → html-to-image-_wGfk8V-.js} +2241 -2277
  12. package/dist/{input-BGPrFH3g.js → input-DtsN7xm-.js} +2 -2
  13. package/dist/main.js +1201 -1297
  14. package/dist/{mermaid-UdmxG2PZ.js → mermaid-BYqXy_NE.js} +2 -2
  15. package/dist/{process-output-C_A12w9J.js → process-output-Mh4UrjwM.js} +1 -1
  16. package/dist/{reveal-component-ELidGmPF.js → reveal-component-B5DXLyO7.js} +605 -618
  17. package/dist/{spec-DSs9v0xx.js → spec-Cz-Bj1JI.js} +1 -1
  18. package/dist/style.css +1 -1
  19. package/dist/{toDate-CKpRx4TS.js → toDate-CWNNlFEX.js} +4 -3
  20. package/dist/{useAsyncData-BSOyAbac.js → useAsyncData-KfHB8wQR.js} +1 -1
  21. package/dist/{useDeepCompareMemoize-BTLeWzuR.js → useDeepCompareMemoize-nJMtxhm4.js} +1 -1
  22. package/dist/{useLifecycle-C6wHjkhW.js → useLifecycle-DegSo0lV.js} +1 -1
  23. package/dist/{useTheme-Df_vGflw.js → useTheme-6eZ3GOTS.js} +27 -62
  24. package/dist/{vega-component-DNHEV0u0.js → vega-component-DzyyM9fc.js} +6 -6
  25. package/package.json +1 -1
  26. package/src/components/chat/__tests__/chat-utils.test.ts +1 -244
  27. package/src/components/chat/chat-panel.tsx +67 -196
  28. package/src/components/chat/chat-utils.ts +2 -111
  29. package/src/components/editor/SortableCell.tsx +2 -6
  30. package/src/components/editor/actions/pair-with-agent-modal.tsx +64 -20
  31. package/src/components/editor/ai/add-cell-with-ai.tsx +5 -14
  32. package/src/components/editor/ai/ai-completion-editor.tsx +1 -4
  33. package/src/components/editor/cell/cell-context-menu.tsx +0 -7
  34. package/src/components/editor/chrome/panels/packages-panel.tsx +1 -11
  35. package/src/components/editor/columns/cell-column.tsx +4 -34
  36. package/src/components/editor/columns/sortable-column.tsx +4 -24
  37. package/src/components/editor/navigation/__tests__/navigation.test.ts +0 -33
  38. package/src/components/editor/navigation/navigation.ts +1 -8
  39. package/src/components/editor/notebook-cell.tsx +106 -203
  40. package/src/components/editor/renderers/cell-array.tsx +13 -26
  41. package/src/components/editor/renderers/cells-renderer.tsx +2 -8
  42. package/src/components/editor/renderers/slides-layout/__tests__/plugin.test.ts +0 -29
  43. package/src/components/editor/renderers/slides-layout/types.ts +0 -4
  44. package/src/components/editor/renderers/vertical-layout/vertical-layout.tsx +19 -19
  45. package/src/components/slides/reveal-component.tsx +4 -37
  46. package/src/components/slides/slide-form.tsx +0 -72
  47. package/src/core/cells/__tests__/utils.test.ts +0 -59
  48. package/src/core/cells/utils.ts +0 -51
  49. package/src/core/codemirror/completion/__tests__/signature-hint.test.ts +3 -97
  50. package/src/core/codemirror/completion/signature-hint.ts +11 -78
  51. package/src/core/constants.ts +0 -6
  52. package/src/core/islands/__tests__/bridge.test.ts +46 -341
  53. package/src/core/islands/__tests__/parse.test.ts +0 -105
  54. package/src/core/islands/bootstrap.ts +3 -8
  55. package/src/core/islands/bridge.ts +23 -116
  56. package/src/core/islands/components/web-components.tsx +15 -76
  57. package/src/core/islands/constants.ts +0 -1
  58. package/src/core/islands/main.ts +3 -69
  59. package/src/core/islands/parse.ts +23 -70
  60. package/src/core/islands/worker/worker.tsx +57 -145
  61. package/src/core/wasm/worker/bootstrap.ts +20 -113
  62. package/src/css/app/Cell.css +0 -10
  63. package/src/hooks/useHotkey.ts +4 -29
  64. package/src/plugins/impl/anywidget/__tests__/host.test.ts +9 -6
  65. package/src/plugins/impl/anywidget/__tests__/widget-binding.test.ts +61 -22
  66. package/src/plugins/impl/anywidget/model-proxy.ts +13 -0
  67. package/src/plugins/impl/anywidget/widget-binding.ts +34 -4
  68. package/src/plugins/impl/image-comparison/ImageComparisonComponent.tsx +2 -53
  69. package/src/plugins/impl/matplotlib/__tests__/matplotlib-renderer.test.ts +3 -71
  70. package/src/plugins/impl/matplotlib/matplotlib-renderer.ts +0 -1
  71. package/src/theme/useTheme.ts +1 -16
  72. package/dist/assets/__vite-browser-external-CjNAy01L.js +0 -1
  73. package/dist/assets/worker-B3XPCb6y.js +0 -98
  74. package/src/components/chat/__tests__/message-queue.test.tsx +0 -121
  75. package/src/components/editor/__tests__/output-persistence.test.tsx +0 -241
  76. package/src/components/editor/actions/__tests__/pair-with-agent-commands.test.ts +0 -153
  77. package/src/components/editor/actions/pair-with-agent-commands.ts +0 -109
  78. package/src/components/editor/columns/__tests__/cell-column.test.tsx +0 -105
  79. package/src/components/editor/renderers/__tests__/cells-renderer.test.tsx +0 -66
  80. package/src/core/islands/__tests__/main.test.ts +0 -176
  81. package/src/core/islands/components/__tests__/web-components.test.tsx +0 -214
  82. package/src/core/islands/worker/__tests__/controller.test.ts +0 -173
  83. package/src/hooks/__tests__/useHotkey.test.tsx +0 -88
  84. package/src/plugins/impl/image-comparison/__tests__/ImageComparisonComponent.test.tsx +0 -71
  85. package/src/theme/__tests__/useTheme.test.ts +0 -68
@@ -5,7 +5,8 @@ import { t as __commonJSMin } from "./chunk-BNovOVIE.js";
5
5
  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
- import { T as atom, a as KnownQueryParams, g as store, v as waitFor, y as isIslands } from "./useTheme-Df_vGflw.js";
8
+ import { r as KnownQueryParams } from "./constants-T20xxyNf.js";
9
+ import { S as atom, g as isIslands, h as waitFor, p as store } from "./useTheme-6eZ3GOTS.js";
9
10
  import { t as invariant } from "./invariant-wRzNXIsJ.js";
10
11
  var CircleQuestionMark = createLucideIcon("circle-question-mark", [
11
12
  ["circle", {
@@ -515,9 +516,9 @@ var RuntimeManager = class {
515
516
  return isWasm() || isIslands() || isStaticNotebook();
516
517
  }
517
518
  formatHttpURL({ path: e = "", searchParams: b, restrictToKnownQueryParams: x = true }) {
518
- let S = this.httpURL, C = new URLSearchParams(window.location.search);
519
+ let S = this.httpURL, w = new URLSearchParams(window.location.search);
519
520
  if (b) for (let [e2, x2] of b.entries()) S.searchParams.set(e2, x2);
520
- for (let [e2, b2] of C.entries()) x && !Object.values(KnownQueryParams).includes(e2) || S.searchParams.set(e2, b2);
521
+ for (let [e2, b2] of w.entries()) x && !Object.values(KnownQueryParams).includes(e2) || S.searchParams.set(e2, b2);
521
522
  return S.pathname = `${S.pathname.replace(/\/$/, "")}/${e.replace(/^\//, "")}`, S.hash = "", S;
522
523
  }
523
524
  formatWsURL(e, b) {
@@ -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 { A as useEvent_default } from "./useTheme-Df_vGflw.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 { k as dequal } from "./useTheme-Df_vGflw.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 { C as useSetAtom, T as atom } from "./useTheme-Df_vGflw.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",
@@ -736,39 +736,7 @@ atom((e) => e(appConfigAtom).width), atom((e) => {
736
736
  var _a;
737
737
  return ((_a = e(resolvedMarimoConfigAtom).server) == null ? void 0 : _a.disable_file_downloads) ?? false;
738
738
  });
739
- const Constants = {
740
- githubPage: "https://github.com/marimo-team/marimo",
741
- releasesPage: "https://github.com/marimo-team/marimo/releases",
742
- issuesPage: "https://github.com/marimo-team/marimo/issues",
743
- feedbackForm: "https://marimo.io/feedback",
744
- discordLink: "https://marimo.io/discord?ref=notebook",
745
- docsPage: "https://docs.marimo.io",
746
- youtube: "https://www.youtube.com/@marimo-team",
747
- molab: "https://molab.marimo.io"
748
- }, KnownQueryParams = {
749
- showCode: "show-code",
750
- includeCode: "include-code",
751
- sessionId: "session_id",
752
- kiosk: "kiosk",
753
- vscode: "vscode",
754
- filePath: "file",
755
- accessToken: "access_token",
756
- viewAs: "view-as",
757
- showChrome: "show-chrome",
758
- theme: "theme"
759
- }, CSSClasses = { outputArea: "output-area" };
760
- var import_compiler_runtime = require_compiler_runtime();
761
- const THEMES = [
762
- "light",
763
- "dark",
764
- "system"
765
- ];
766
- function themeFromQueryParam() {
767
- if (typeof window > "u") return;
768
- let e = new URLSearchParams(window.location.search).get(KnownQueryParams.theme);
769
- return THEMES.includes(e) ? e : void 0;
770
- }
771
- var themeAtom = atom((e) => {
739
+ var import_compiler_runtime = require_compiler_runtime(), themeAtom = atom((e) => {
772
740
  if (isIslands()) {
773
741
  if (document.body.classList.contains("dark-mode") || document.body.classList.contains("dark") || document.body.dataset.theme === "dark" || document.body.dataset.mode === "dark" || getVsCodeTheme() === "dark") return "dark";
774
742
  let e2 = window.getComputedStyle(document.body), A = e2.getPropertyValue("color-scheme").trim();
@@ -780,7 +748,7 @@ var themeAtom = atom((e) => {
780
748
  }
781
749
  return "light";
782
750
  }
783
- return themeFromQueryParam() ?? e(resolvedMarimoConfigAtom).display.theme;
751
+ return e(resolvedMarimoConfigAtom).display.theme;
784
752
  }), prefersDarkModeAtom = atom(false);
785
753
  function setupThemeListener() {
786
754
  if (typeof window > "u" || !window.matchMedia) return;
@@ -825,34 +793,31 @@ function useTheme() {
825
793
  return e[1] === j ? M = e[2] : (M = { theme: j }, e[1] = j, e[2] = M), M;
826
794
  }
827
795
  export {
828
- useEvent_default as A,
829
- useSetAtom as C,
830
- buildStore as D,
831
- createStore as E,
832
- getBuildingBlocks as O,
833
- useAtomValue as S,
834
- atom as T,
835
- useJotaiEffect as _,
836
- KnownQueryParams as a,
837
- Provider as b,
838
- autoInstantiateAtom as c,
839
- resolvedMarimoConfigAtom as d,
840
- useResolvedMarimoConfig as f,
841
- store as g,
842
- createDeepEqualAtom as h,
843
- Constants as i,
844
- dequal as k,
845
- getResolvedMarimoConfig as l,
846
- AppConfigSchema 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,
847
812
  useTheme as n,
848
- aiFeaturesEnabledAtom as o,
849
- userConfigAtom as p,
850
- CSSClasses as r,
851
- aiModelConfiguredAtom as s,
813
+ getResolvedMarimoConfig as o,
814
+ store as p,
815
+ aiFeaturesEnabledAtom as r,
816
+ localeAtom as s,
852
817
  resolvedThemeAtom as t,
853
- localeAtom as u,
854
- waitFor as v,
855
- useStore as w,
856
- useAtom as x,
857
- isIslands as y
818
+ userConfigAtom as u,
819
+ useAtom as v,
820
+ buildStore as w,
821
+ useStore as x,
822
+ useAtomValue as y
858
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-CKpRx4TS.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
- import { t as debounce_default } from "./debounce-BOD3DbfP.js";
12
- import { A as useEvent_default, n as useTheme } from "./useTheme-Df_vGflw.js";
11
+ import { i as debounce_default } from "./constants-T20xxyNf.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-BX3uDQbB.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-BSOyAbac.js";
21
- import { t as useDeepCompareMemoize } from "./useDeepCompareMemoize-BTLeWzuR.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.15-dev33",
3
+ "version": "0.23.15-dev4",
4
4
  "main": "dist/main.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "type": "module",
@@ -2,11 +2,7 @@
2
2
 
3
3
  import type { UIMessage } from "ai";
4
4
  import { describe, expect, it } from "vitest";
5
- import {
6
- hasPendingToolCalls,
7
- hasUnresolvedToolCalls,
8
- shouldFlushQueue,
9
- } from "../chat-utils";
5
+ import { hasPendingToolCalls } from "../chat-utils";
10
6
 
11
7
  /**
12
8
  * `hasPendingToolCalls` powers `sendAutomaticallyWhen` in `mo.ui.chat`:
@@ -85,23 +81,6 @@ describe("hasPendingToolCalls", () => {
85
81
  ).toBe(true);
86
82
  });
87
83
 
88
- it("returns true when the user denied a tool approval", () => {
89
- expect(
90
- hasPendingToolCalls([
91
- userMessage("delete it"),
92
- assistantToolMessage([
93
- {
94
- type: "tool-delete_file",
95
- toolCallId: "call-1",
96
- state: "output-denied",
97
- input: { path: "secrets.env" },
98
- approval: { id: "approval-1", approved: false },
99
- } as unknown as UIMessage["parts"][number],
100
- ]),
101
- ]),
102
- ).toBe(true);
103
- });
104
-
105
84
  it("returns true when a tool reached a terminal output state", () => {
106
85
  expect(
107
86
  hasPendingToolCalls([
@@ -288,225 +267,3 @@ describe("hasPendingToolCalls", () => {
288
267
  ).toBe(true);
289
268
  });
290
269
  });
291
-
292
- describe("hasUnresolvedToolCalls", () => {
293
- it("returns false when there are no messages", () => {
294
- expect(hasUnresolvedToolCalls([])).toBe(false);
295
- });
296
-
297
- it("returns true while approval is still requested", () => {
298
- expect(
299
- hasUnresolvedToolCalls([
300
- userMessage("delete it"),
301
- assistantToolMessage([
302
- {
303
- type: "tool-delete_file",
304
- toolCallId: "call-1",
305
- state: "approval-requested",
306
- input: { path: "secrets.env" },
307
- approval: { id: "approval-1" },
308
- } as unknown as UIMessage["parts"][number],
309
- ]),
310
- ]),
311
- ).toBe(true);
312
- });
313
-
314
- it("returns true while a tool is still running", () => {
315
- expect(
316
- hasUnresolvedToolCalls([
317
- userMessage("run it"),
318
- assistantToolMessage([
319
- {
320
- type: "tool-run_query",
321
- toolCallId: "call-1",
322
- state: "input-available",
323
- input: { sql: "select 1" },
324
- } as unknown as UIMessage["parts"][number],
325
- ]),
326
- ]),
327
- ).toBe(true);
328
- });
329
-
330
- it("returns false once tools are ready to round-trip", () => {
331
- expect(
332
- hasUnresolvedToolCalls([
333
- userMessage("run it"),
334
- assistantToolMessage([
335
- {
336
- type: "tool-run_query",
337
- toolCallId: "call-1",
338
- state: "output-available",
339
- input: { sql: "select 1" },
340
- output: 1,
341
- } as unknown as UIMessage["parts"][number],
342
- ]),
343
- ]),
344
- ).toBe(false);
345
- });
346
-
347
- it("returns false once the user denied a tool approval", () => {
348
- expect(
349
- hasUnresolvedToolCalls([
350
- userMessage("delete it"),
351
- assistantToolMessage([
352
- {
353
- type: "tool-delete_file",
354
- toolCallId: "call-1",
355
- state: "output-denied",
356
- input: { path: "secrets.env" },
357
- approval: { id: "approval-1", approved: false },
358
- } as unknown as UIMessage["parts"][number],
359
- ]),
360
- ]),
361
- ).toBe(false);
362
- });
363
- });
364
-
365
- describe("shouldFlushQueue", () => {
366
- it("flushes when the turn completed without error or pending tools", () => {
367
- expect(
368
- shouldFlushQueue({
369
- isError: false,
370
- isAbort: false,
371
- hasPendingToolCalls: false,
372
- hasUnresolvedToolCalls: false,
373
- }),
374
- ).toBe(true);
375
- });
376
-
377
- it("does not flush on error", () => {
378
- expect(
379
- shouldFlushQueue({
380
- isError: true,
381
- isAbort: false,
382
- hasPendingToolCalls: false,
383
- hasUnresolvedToolCalls: false,
384
- }),
385
- ).toBe(false);
386
- });
387
-
388
- it("does not flush while a tool round-trip is still pending", () => {
389
- expect(
390
- shouldFlushQueue({
391
- isError: false,
392
- isAbort: false,
393
- hasPendingToolCalls: true,
394
- hasUnresolvedToolCalls: false,
395
- }),
396
- ).toBe(false);
397
- });
398
-
399
- it("does not flush while approval is still requested", () => {
400
- expect(
401
- shouldFlushQueue({
402
- isError: false,
403
- isAbort: false,
404
- hasPendingToolCalls: false,
405
- hasUnresolvedToolCalls: true,
406
- }),
407
- ).toBe(false);
408
- });
409
-
410
- it("flushes on abort even when a tool is still streaming", () => {
411
- expect(
412
- shouldFlushQueue({
413
- isError: false,
414
- isAbort: true,
415
- hasPendingToolCalls: false,
416
- hasUnresolvedToolCalls: true,
417
- }),
418
- ).toBe(true);
419
- });
420
-
421
- it("does not flush on abort when the run ended in error", () => {
422
- expect(
423
- shouldFlushQueue({
424
- isError: true,
425
- isAbort: true,
426
- hasPendingToolCalls: false,
427
- hasUnresolvedToolCalls: true,
428
- }),
429
- ).toBe(false);
430
- });
431
-
432
- it("flushes once trailing text is present and tools are resolved", () => {
433
- const messages = [
434
- userMessage("run it"),
435
- assistantToolMessage([
436
- {
437
- type: "tool-run_query",
438
- toolCallId: "call-1",
439
- state: "output-available",
440
- input: {},
441
- output: 1,
442
- } as unknown as UIMessage["parts"][number],
443
- { type: "text", text: "Done." },
444
- ]),
445
- ];
446
-
447
- expect(
448
- shouldFlushQueue({
449
- isError: false,
450
- isAbort: false,
451
- hasPendingToolCalls: hasPendingToolCalls(messages),
452
- hasUnresolvedToolCalls: hasUnresolvedToolCalls(messages),
453
- }),
454
- ).toBe(true);
455
- });
456
-
457
- it("blocks flush while text trails a still-running tool, then allows it after resolution", () => {
458
- const running = [
459
- userMessage("run it"),
460
- assistantToolMessage([
461
- {
462
- type: "tool-run_query",
463
- toolCallId: "call-1",
464
- state: "input-available",
465
- input: {},
466
- } as unknown as UIMessage["parts"][number],
467
- { type: "text", text: "Running your query..." },
468
- ]),
469
- ];
470
- const resolved = [
471
- userMessage("run it"),
472
- assistantToolMessage([
473
- {
474
- type: "tool-run_query",
475
- toolCallId: "call-1",
476
- state: "output-available",
477
- input: {},
478
- output: 1,
479
- } as unknown as UIMessage["parts"][number],
480
- { type: "text", text: "Running your query..." },
481
- ]),
482
- ];
483
-
484
- expect(
485
- shouldFlushQueue({
486
- isError: false,
487
- isAbort: false,
488
- hasPendingToolCalls: hasPendingToolCalls(running),
489
- hasUnresolvedToolCalls: hasUnresolvedToolCalls(running),
490
- }),
491
- ).toBe(false);
492
- expect(
493
- shouldFlushQueue({
494
- isError: false,
495
- isAbort: false,
496
- hasPendingToolCalls: hasPendingToolCalls(resolved),
497
- hasUnresolvedToolCalls: hasUnresolvedToolCalls(resolved),
498
- }),
499
- ).toBe(true);
500
- });
501
-
502
- it("does not flush on error even when tools are also pending", () => {
503
- expect(
504
- shouldFlushQueue({
505
- isError: true,
506
- isAbort: false,
507
- hasPendingToolCalls: true,
508
- hasUnresolvedToolCalls: true,
509
- }),
510
- ).toBe(false);
511
- });
512
- });