@marimo-team/frontend 0.24.1-dev115 → 0.24.1-dev119
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.
- package/dist/assets/{CellStatus-DJBTB8Tm.js → CellStatus-LoTwk7fR.js} +1 -1
- package/dist/assets/{ConnectedDataExplorerComponent-C22y7sbC.js → ConnectedDataExplorerComponent-DW6cJ-Lr.js} +1 -1
- package/dist/assets/{JsonOutput-COWoYBdx.js → JsonOutput-Bgxc9G7d.js} +10 -10
- package/dist/assets/{LazyAnyLanguageCodeMirror-nhd5JrSb.js → LazyAnyLanguageCodeMirror-LboTfNDv.js} +2 -2
- package/dist/assets/{MarimoErrorOutput-Cpp7YwEl.js → MarimoErrorOutput-DqpoYOvw.js} +1 -1
- package/dist/assets/{RenderHTML-DlIzJTPL.js → RenderHTML-DwhMAd9l.js} +1 -1
- package/dist/assets/{RunButton-CT16Dkr4.js → RunButton-BlpbweyH.js} +1 -1
- package/dist/assets/{VisuallyHidden-wlQyxf8y.js → VisuallyHidden-CBMDmozt.js} +1 -1
- package/dist/assets/{add-cell-with-ai-DSjyPknP.js → add-cell-with-ai-R-3DS79K.js} +1 -1
- package/dist/assets/{add-connection-dialog-DO478_EL.js → add-connection-dialog-BGfpw5lC.js} +1 -1
- package/dist/assets/{agent-panel-DIvPSTyY.js → agent-panel-B03P2qSx.js} +1 -1
- package/dist/assets/ai-model-dropdown-DCmiuk7x.js +3 -0
- package/dist/assets/alert-dialog-CA-2mBs3.js +11 -0
- package/dist/assets/{any-language-editor-kw0XJFxM.js → any-language-editor-DflLjPSQ.js} +1 -1
- package/dist/assets/{app-config-button-CAZWYP6R.js → app-config-button-DUJC6b6x.js} +1 -1
- package/dist/assets/{blob-B82D3b64.js → blob-B2d_dHwI.js} +1 -1
- package/dist/assets/{cache-panel-iphovHma.js → cache-panel-DqgtC98s.js} +1 -1
- package/dist/assets/{cell-editor-CL59E8W0.js → cell-editor-QmA8u1Ay.js} +1 -1
- package/dist/assets/{cell-link-DOeJzvRH.js → cell-link-6burT2XF.js} +1 -1
- package/dist/assets/{cells-BgH2MZS9.js → cells-Cp-G34Rz.js} +3 -3
- package/dist/assets/{chat-display-kzxea9r-.js → chat-display-Bu405iyc.js} +1 -1
- package/dist/assets/{chat-panel-BVsbI9bp.js → chat-panel-BlUwNY5j.js} +1 -1
- package/dist/assets/{chat-ui-BIaqeCtJ.js → chat-ui-DGiVDzNh.js} +1 -1
- package/dist/assets/{circle-BiW8b6Xq.js → circle-ByJdIf5p.js} +1 -1
- package/dist/assets/{column-preview-BWoK0ZFU.js → column-preview-DHe0-7z4.js} +1 -1
- package/dist/assets/{command-palette-CcLmXXVs.js → command-palette-D-kPO0tm.js} +1 -1
- package/dist/assets/{common-DeDcgYdz.js → common-CHR7w7aQ.js} +1 -1
- package/dist/assets/{components-CtHLnRet.js → components-C7mWrmXr.js} +1 -1
- package/dist/assets/{components-DAhqHptJ.js → components-DUYCXngU.js} +1 -1
- package/dist/assets/config-B-r81uZ6.js +1 -0
- package/dist/assets/{config-BRRSKtP3.js → config-BlNM0caL.js} +1 -1
- package/dist/assets/{copy-icon-D522mvZL.js → copy-icon-z8fuTE3w.js} +1 -1
- package/dist/assets/{datasource-HG_yVRxq.js → datasource-DrODSIs0.js} +1 -1
- package/dist/assets/{dependency-graph-panel-CVsva03Q.js → dependency-graph-panel-AY5BEVH2.js} +1 -1
- package/dist/assets/{dist-ConG15vZ.js → dist-DzCQtGkt.js} +1 -1
- package/dist/assets/{documentation-panel-BSiOFIpg.js → documentation-panel-CaJF7e-j.js} +1 -1
- package/dist/assets/{download-C4umhthc.js → download-DMxOzI7b.js} +1 -1
- package/dist/assets/dropdown-menu-C40jM9o4.js +1 -0
- package/dist/assets/{edit-page-DCOdX3sJ.js → edit-page-CdCPUPqZ.js} +4 -4
- package/dist/assets/{error-banner-C5aiAh3q.js → error-banner-Dw5YY9wq.js} +1 -1
- package/dist/assets/{error-entries-Yh2iX13J.js → error-entries-Cv2m1yhc.js} +1 -1
- package/dist/assets/{error-panel-CGUFTbfd.js → error-panel-Bhlvt6_H.js} +1 -1
- package/dist/assets/{es-DP79Qs0u.js → es-CrFhA96G.js} +1 -1
- package/dist/assets/file-explorer-panel-DMKcHVIX.js +1 -0
- package/dist/assets/{file-icons-C0Mf_Axb.js → file-icons-DdGYuADJ.js} +1 -1
- package/dist/assets/file-name-input-K4MKESI_.js +3 -0
- package/dist/assets/{floating-outline-8Uo6Qp8W.js → floating-outline-DaUHnl_e.js} +1 -1
- package/dist/assets/{fullscreen-BFfuaW3H.js → fullscreen-BH2jz-F4.js} +5 -5
- package/dist/assets/{gallery-page-BpxbCG1a.js → gallery-page-C3pBpHlY.js} +1 -1
- package/dist/assets/{glide-data-editor-k7azNhFM.js → glide-data-editor-sICUMEhk.js} +1 -1
- package/dist/assets/{home-page-CEzr9Hhn.js → home-page-Cir7n_EF.js} +1 -1
- package/dist/assets/index-BGT7have.css +2 -0
- package/dist/assets/{index-kkDJK6-j.js → index-ClZGC-u9.js} +6 -6
- package/dist/assets/{input-D4qvzBWu.js → input-DEbY281O.js} +1 -1
- package/dist/assets/{kiosk-mode-BqYH0GIF.js → kiosk-mode-mxgb5lWf.js} +1 -1
- package/dist/assets/{layout-D5ovQPUb.js → layout-CC2AHMrW.js} +3 -3
- package/dist/assets/{logs-panel-Cqxpxz5Z.js → logs-panel-BGS2v3ba.js} +1 -1
- package/dist/assets/{markdown-renderer-zZh3O1Hm.js → markdown-renderer-BZKlbm2Q.js} +1 -1
- package/dist/assets/{menu-items-CsV3aDPH.js → menu-items-BSRA2YI9.js} +1 -1
- package/dist/assets/{mermaid-BovZosCC.js → mermaid-l6lQkCib.js} +1 -1
- package/dist/assets/{name-cell-input-DXP1MqrH.js → name-cell-input-BMCdK-el.js} +1 -1
- package/dist/assets/{outline-panel-CMMPf-P7.js → outline-panel-Dr5u73V6.js} +1 -1
- package/dist/assets/{packages-panel-BHZOSh3s.js → packages-panel-BdpRg9tX.js} +1 -1
- package/dist/assets/{pair-with-agent-modal-DgckrViE.js → pair-with-agent-modal-CbUFKJHP.js} +1 -1
- package/dist/assets/{panel-accordion-state-9kdNootf.js → panel-accordion-state-DjUTN7i5.js} +1 -1
- package/dist/assets/{panels-Ca-tbb7P.js → panels-BsXw4GTa.js} +1 -1
- package/dist/assets/{process-output-Bi9pDe1a.js → process-output-Ck7-P_xp.js} +1 -1
- package/dist/assets/{readonly-code-display-ilZfA3ua.js → readonly-code-display--S2daDa6.js} +1 -1
- package/dist/assets/{readonly-python-code-Bqk6NhSW.js → readonly-python-code-DpIyjHqY.js} +1 -1
- package/dist/assets/{renderShortcut-BnBOGXqJ.js → renderShortcut-X-CJUSM8.js} +1 -1
- package/dist/assets/{reveal-component-DpoL_y06.js → reveal-component-BuI7t0JO.js} +1 -1
- package/dist/assets/{run-page-rnCMzZmN.js → run-page-DZNsqz9H.js} +1 -1
- package/dist/assets/{scratchpad-panel-BBd8n8wh.js → scratchpad-panel-CARmXIqQ.js} +1 -1
- package/dist/assets/{secrets-panel-C5D_CNW2.js → secrets-panel-D3BpDIgg.js} +1 -1
- package/dist/assets/select-nLt2y0Sw.js +1 -0
- package/dist/assets/{session-panel-C3kmYD9D.js → session-panel-CB5EvmZs.js} +1 -1
- package/dist/assets/{skeleton-xsRIwsVr.js → skeleton-idYPIMw_.js} +1 -1
- package/dist/assets/{snippets-panel-C1fCmhNQ.js → snippets-panel-D5yy7kj0.js} +1 -1
- package/dist/assets/{state-DJSqAVnx.js → state-B6AklCzD.js} +1 -1
- package/dist/assets/{state-CsL-gymg.js → state-Di9TbuV9.js} +1 -1
- package/dist/assets/{switch-CYJ2u4G9.js → switch-DjXr9Y9D.js} +1 -1
- package/dist/assets/{tabs-DxfkQ6UI.js → tabs-Cy1qXLzH.js} +1 -1
- package/dist/assets/{terminal-CfkxQQwT.js → terminal-CQAFGBfN.js} +1 -1
- package/dist/assets/{tooltip-BO5vfMvm.js → tooltip-BUtPzKB4.js} +1 -1
- package/dist/assets/{tracing-BHb672Fd.js → tracing-DNk3gmWv.js} +1 -1
- package/dist/assets/{tracing-panel-3JaAnsDw.js → tracing-panel-Yqazr6w_.js} +2 -2
- package/dist/assets/{tree-actions-CzmLf39g.js → tree-actions-CG5g7aUQ.js} +1 -1
- package/dist/assets/{useAddCell-DuzEVBJj.js → useAddCell-DdB_uBif.js} +1 -1
- package/dist/assets/{useBoolean-Dh6ALPsT.js → useBoolean-BXC4CItZ.js} +1 -1
- package/dist/assets/{useCellActionButton-B3Ve1KW5.js → useCellActionButton-B31neI3m.js} +1 -1
- package/dist/assets/{useDebounce-Dulm61-t.js → useDebounce-DgpSQhrP.js} +1 -1
- package/dist/assets/{useDeleteCell-CEtU0g91.js → useDeleteCell-Bz49_cFj.js} +1 -1
- package/dist/assets/{useDependencyPanelTab-BpSWTQLC.js → useDependencyPanelTab-C_ps0r--.js} +1 -1
- package/dist/assets/{useNotebookActions-C3LAhEgG.js → useNotebookActions-Br4AVVRg.js} +1 -1
- package/dist/assets/{useRunCells-omrTl5XU.js → useRunCells-CX7oW5zy.js} +1 -1
- package/dist/assets/{useSplitCell-CgXD2Gcw.js → useSplitCell-Dy2_DmJR.js} +1 -1
- package/dist/assets/{useTheme-OSyXt1jZ.js → useTheme-C-ri8BtY.js} +1 -1
- package/dist/assets/utils-D5Ywm7-q.js +1 -0
- package/dist/assets/{vega-component-CwdVpUdb.js → vega-component-C7TCzyaU.js} +1 -1
- package/dist/assets/write-secret-modal-D6zoZgLY.js +2 -0
- package/dist/index.html +44 -44
- package/package.json +1 -1
- package/src/components/ai/ai-provider-icon.tsx +2 -2
- package/src/components/ai/ai-utils.ts +1 -1
- package/src/components/app-config/ai-config.tsx +33 -37
- package/src/components/app-config/user-config-form.tsx +1 -1
- package/src/components/data-table/renderers.tsx +2 -6
- package/src/components/editor/Output.tsx +40 -0
- package/src/components/editor/__tests__/Output.test.tsx +85 -2
- package/src/components/editor/file-tree/__tests__/file-explorer-navigation.test.tsx +832 -0
- package/src/components/editor/file-tree/__tests__/file-viewer.test.tsx +27 -0
- package/src/components/editor/file-tree/__tests__/requesting-tree.test.ts +130 -0
- package/src/components/editor/file-tree/file-browser-row.tsx +82 -0
- package/src/components/editor/file-tree/file-explorer.tsx +377 -159
- package/src/components/editor/file-tree/file-operations.tsx +1 -1
- package/src/components/editor/file-tree/file-search-results.tsx +142 -0
- package/src/components/editor/file-tree/file-tree-row.tsx +40 -0
- package/src/components/editor/file-tree/file-viewer.tsx +2 -1
- package/src/components/editor/file-tree/requesting-tree.tsx +162 -32
- package/src/components/editor/file-tree/use-file-search.ts +142 -0
- package/src/components/editor/file-tree/use-hover-expand.ts +34 -0
- package/src/components/ui/__tests__/fullscreen.test.tsx +88 -0
- package/src/components/ui/fullscreen.tsx +43 -1
- package/src/components/ui/links.tsx +2 -1
- package/src/core/ai/ids/__tests__/ids.test.ts +0 -8
- package/src/core/ai/ids/ids.ts +1 -1
- package/src/core/config/config-schema.ts +1 -0
- package/src/core/network/__tests__/requests-toasting.test.tsx +14 -0
- package/src/core/network/requests-toasting.tsx +1 -1
- package/src/hooks/useEventListener.ts +1 -1
- package/dist/assets/ai-model-dropdown-BxqpRM7R.js +0 -3
- package/dist/assets/alert-dialog-BnNhUpVP.js +0 -11
- package/dist/assets/config-DnyziF11.js +0 -1
- package/dist/assets/dropdown-menu-B-ZAV5lw.js +0 -1
- package/dist/assets/file-explorer-panel-Db-8C8fm.js +0 -1
- package/dist/assets/file-name-input-DmwIfRLx.js +0 -3
- package/dist/assets/index-DuY6Lm00.css +0 -2
- package/dist/assets/select-BJKJFWHk.js +0 -1
- package/dist/assets/utils-B-_Wem_I.js +0 -1
- package/dist/assets/write-secret-modal-GHpJRc36.js +0 -2
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
import { act, render } from "@testing-library/react";
|
|
3
|
+
import { useRef } from "react";
|
|
4
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
5
|
+
import { useIsFullScreen } from "../fullscreen";
|
|
6
|
+
|
|
7
|
+
const FullScreenFlag = ({ label }: { label: string }) => {
|
|
8
|
+
const ref = useRef<HTMLDivElement>(null);
|
|
9
|
+
const isFullScreen = useIsFullScreen(ref);
|
|
10
|
+
|
|
11
|
+
return (
|
|
12
|
+
<div ref={ref} data-testid={label}>
|
|
13
|
+
{String(isFullScreen)}
|
|
14
|
+
</div>
|
|
15
|
+
);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
describe("useIsFullScreen", () => {
|
|
19
|
+
let fullscreenElement: Element | null = null;
|
|
20
|
+
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
fullscreenElement = null;
|
|
23
|
+
Object.defineProperty(document, "fullscreenElement", {
|
|
24
|
+
configurable: true,
|
|
25
|
+
get: () => fullscreenElement,
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
afterEach(() => {
|
|
30
|
+
Reflect.deleteProperty(document, "fullscreenElement");
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const countFullScreenListeners = (calls: unknown[][]) =>
|
|
34
|
+
calls.filter((call) => call[0] === "fullscreenchange").length;
|
|
35
|
+
|
|
36
|
+
it("adds one document listener for many subscribers", () => {
|
|
37
|
+
const addEventListener = vi.spyOn(document, "addEventListener");
|
|
38
|
+
|
|
39
|
+
render(
|
|
40
|
+
<>
|
|
41
|
+
<FullScreenFlag label="first" />
|
|
42
|
+
<FullScreenFlag label="second" />
|
|
43
|
+
<FullScreenFlag label="third" />
|
|
44
|
+
</>,
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
expect(countFullScreenListeners(addEventListener.mock.calls)).toBe(1);
|
|
48
|
+
addEventListener.mockRestore();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("removes the listener when the last subscriber unmounts", () => {
|
|
52
|
+
const removeEventListener = vi.spyOn(document, "removeEventListener");
|
|
53
|
+
|
|
54
|
+
const { unmount } = render(
|
|
55
|
+
<>
|
|
56
|
+
<FullScreenFlag label="first" />
|
|
57
|
+
<FullScreenFlag label="second" />
|
|
58
|
+
</>,
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
expect(countFullScreenListeners(removeEventListener.mock.calls)).toBe(0);
|
|
62
|
+
|
|
63
|
+
unmount();
|
|
64
|
+
|
|
65
|
+
expect(countFullScreenListeners(removeEventListener.mock.calls)).toBe(1);
|
|
66
|
+
removeEventListener.mockRestore();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it("reports true for the full screen element only", () => {
|
|
70
|
+
const { getByTestId } = render(
|
|
71
|
+
<>
|
|
72
|
+
<FullScreenFlag label="first" />
|
|
73
|
+
<FullScreenFlag label="second" />
|
|
74
|
+
</>,
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
expect(getByTestId("first")).toHaveTextContent("false");
|
|
78
|
+
expect(getByTestId("second")).toHaveTextContent("false");
|
|
79
|
+
|
|
80
|
+
fullscreenElement = getByTestId("second");
|
|
81
|
+
act(() => {
|
|
82
|
+
document.dispatchEvent(new Event("fullscreenchange"));
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
expect(getByTestId("first")).toHaveTextContent("false");
|
|
86
|
+
expect(getByTestId("second")).toHaveTextContent("true");
|
|
87
|
+
});
|
|
88
|
+
});
|
|
@@ -4,7 +4,7 @@ import type { Popover } from "radix-ui";
|
|
|
4
4
|
|
|
5
5
|
type PopoverContentProps = Popover.PopoverContentProps;
|
|
6
6
|
|
|
7
|
-
import React, { useState } from "react";
|
|
7
|
+
import React, { type RefObject, useState, useSyncExternalStore } from "react";
|
|
8
8
|
import { isInVscodeExtension } from "@/core/vscode/is-in-vscode";
|
|
9
9
|
import { useEventListener } from "@/hooks/useEventListener";
|
|
10
10
|
|
|
@@ -27,6 +27,48 @@ export function useFullScreenElement() {
|
|
|
27
27
|
return fullScreenElement;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
const fullScreenSubscribers = new Set<() => void>();
|
|
31
|
+
|
|
32
|
+
function notifyFullScreenSubscribers() {
|
|
33
|
+
for (const subscriber of fullScreenSubscribers) {
|
|
34
|
+
subscriber();
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* One document listener serves every subscriber, so the cost of a full screen
|
|
40
|
+
* transition does not grow with the number of mounted components.
|
|
41
|
+
*/
|
|
42
|
+
function subscribeToFullScreen(onStoreChange: () => void) {
|
|
43
|
+
if (fullScreenSubscribers.size === 0) {
|
|
44
|
+
document.addEventListener("fullscreenchange", notifyFullScreenSubscribers);
|
|
45
|
+
}
|
|
46
|
+
fullScreenSubscribers.add(onStoreChange);
|
|
47
|
+
|
|
48
|
+
return () => {
|
|
49
|
+
fullScreenSubscribers.delete(onStoreChange);
|
|
50
|
+
if (fullScreenSubscribers.size === 0) {
|
|
51
|
+
document.removeEventListener(
|
|
52
|
+
"fullscreenchange",
|
|
53
|
+
notifyFullScreenSubscribers,
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Whether the given element is the full screen element.
|
|
61
|
+
*
|
|
62
|
+
* The hook returns a boolean, so a component re-renders only when its own
|
|
63
|
+
* element enters or leaves full screen.
|
|
64
|
+
*/
|
|
65
|
+
export function useIsFullScreen(ref: RefObject<Element | null>): boolean {
|
|
66
|
+
return useSyncExternalStore(subscribeToFullScreen, () => {
|
|
67
|
+
const fullScreenElement = document.fullscreenElement;
|
|
68
|
+
return fullScreenElement !== null && fullScreenElement === ref.current;
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
30
72
|
/**
|
|
31
73
|
* HOC wrapping a Portal component to use the
|
|
32
74
|
* full screen element as the container if we are in full screen mode
|
|
@@ -16,7 +16,8 @@ export const ExternalLink = ({
|
|
|
16
16
|
| `https://links.marimo.app/${string}`
|
|
17
17
|
| `https://wandb.ai/${string}`
|
|
18
18
|
| `https://portal.azure.com/${string}`
|
|
19
|
-
| `https://opencode.ai/${string}
|
|
19
|
+
| `https://opencode.ai/${string}`
|
|
20
|
+
| `https://pydantic.dev/${string}`;
|
|
20
21
|
children: React.ReactNode;
|
|
21
22
|
}) => {
|
|
22
23
|
return (
|
|
@@ -26,7 +26,6 @@ describe("AiModelId", () => {
|
|
|
26
26
|
"google",
|
|
27
27
|
"ollama",
|
|
28
28
|
"bedrock",
|
|
29
|
-
"github",
|
|
30
29
|
];
|
|
31
30
|
|
|
32
31
|
providers.forEach((provider) => {
|
|
@@ -68,12 +67,6 @@ describe("AiModelId", () => {
|
|
|
68
67
|
expect(modelId.shortModelId).toBe("titan-text");
|
|
69
68
|
});
|
|
70
69
|
|
|
71
|
-
it("should parse github qualified id", () => {
|
|
72
|
-
const modelId = AiModelId.parse("github/gpt-4o");
|
|
73
|
-
expect(modelId.providerId).toBe("github");
|
|
74
|
-
expect(modelId.shortModelId).toBe("gpt-4o");
|
|
75
|
-
});
|
|
76
|
-
|
|
77
70
|
it("should handle multiple slashes", () => {
|
|
78
71
|
const modelId = AiModelId.parse("openai/gpt-4/turbo");
|
|
79
72
|
expect(modelId.providerId).toBe("openai");
|
|
@@ -178,7 +171,6 @@ describe("AiModelId", () => {
|
|
|
178
171
|
"google",
|
|
179
172
|
"ollama",
|
|
180
173
|
"bedrock",
|
|
181
|
-
"github",
|
|
182
174
|
];
|
|
183
175
|
|
|
184
176
|
providers.forEach((provider) => {
|
package/src/core/ai/ids/ids.ts
CHANGED
|
@@ -4,13 +4,13 @@ import type { TypedString } from "@/utils/typed";
|
|
|
4
4
|
|
|
5
5
|
export const KNOWN_PROVIDERS = [
|
|
6
6
|
"openai",
|
|
7
|
+
"github",
|
|
7
8
|
"anthropic",
|
|
8
9
|
"google",
|
|
9
10
|
"ollama",
|
|
10
11
|
"bedrock",
|
|
11
12
|
"deepseek",
|
|
12
13
|
"azure",
|
|
13
|
-
"github",
|
|
14
14
|
"openrouter",
|
|
15
15
|
"wandb",
|
|
16
16
|
"opencode-go",
|
|
@@ -171,6 +171,7 @@ export const UserConfigSchema = z
|
|
|
171
171
|
inline_tooltip: z.boolean().prefault(false),
|
|
172
172
|
allow_provider_config: z.boolean().prefault(true),
|
|
173
173
|
open_ai: AiConfigSchema.optional(),
|
|
174
|
+
github: AiConfigSchema.optional(),
|
|
174
175
|
anthropic: AiConfigSchema.optional(),
|
|
175
176
|
google: AiConfigSchema.optional(),
|
|
176
177
|
ollama: AiConfigSchema.optional(),
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
3
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
4
|
+
import { MockRequestClient } from "@/__mocks__/requests";
|
|
4
5
|
import { HTTPError } from "@/utils/errors";
|
|
5
6
|
|
|
6
7
|
const toastMock = vi.fn();
|
|
@@ -44,6 +45,19 @@ describe("createErrorToastingRequests", () => {
|
|
|
44
45
|
);
|
|
45
46
|
});
|
|
46
47
|
|
|
48
|
+
it("leaves search errors to callers without a toast per failed root", async () => {
|
|
49
|
+
const client = MockRequestClient.create();
|
|
50
|
+
const error = new Error("Storage unavailable");
|
|
51
|
+
vi.mocked(client.sendSearchFiles).mockRejectedValue(error);
|
|
52
|
+
const requests = createErrorToastingRequests(client);
|
|
53
|
+
for (const path of ["/workspace", "/shared"]) {
|
|
54
|
+
await expect(
|
|
55
|
+
requests.sendSearchFiles({ query: "report", path }),
|
|
56
|
+
).rejects.toBe(error);
|
|
57
|
+
}
|
|
58
|
+
expect(toastMock).not.toHaveBeenCalled();
|
|
59
|
+
});
|
|
60
|
+
|
|
47
61
|
it("leaves file-root errors for the requesting tree to surface", async () => {
|
|
48
62
|
const error = new Error("Failed to load roots");
|
|
49
63
|
const requests = createErrorToastingRequests({
|
|
@@ -50,7 +50,7 @@ export function createErrorToastingRequests(
|
|
|
50
50
|
getEnvironmentInfo: "", // No toast
|
|
51
51
|
getFileRoots: "", // RequestingTree surfaces this error
|
|
52
52
|
sendListFiles: "Failed to list files",
|
|
53
|
-
sendSearchFiles: "
|
|
53
|
+
sendSearchFiles: "", // Search callers handle errors
|
|
54
54
|
sendPdb: "Failed to start debug session",
|
|
55
55
|
sendSetBreakpoints: "", // No toast
|
|
56
56
|
sendCreateFileOrFolder: "Failed to create file or folder",
|
|
@@ -17,7 +17,7 @@ export function isRefObject<T>(target: unknown): target is RefObject<T | null> {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
export function useEventListener<K extends keyof DocumentEventMap>(
|
|
20
|
-
targetValue: Document,
|
|
20
|
+
targetValue: Document | null,
|
|
21
21
|
type: K,
|
|
22
22
|
listener: (ev: DocumentEventMap[K]) => unknown,
|
|
23
23
|
options?: boolean | AddEventListenerOptions,
|