@marimo-team/frontend 0.25.3-dev2 → 0.25.3-dev20
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-BP2mavAq.js → CellStatus-DVOHpdeJ.js} +1 -1
- package/dist/assets/{ConnectedDataExplorerComponent-t8fH_TNc.js → ConnectedDataExplorerComponent-TprnxZeJ.js} +1 -1
- package/dist/assets/{ErrorBoundary-Gl5nCA8C.js → ErrorBoundary-CM13wrd8.js} +2 -2
- package/dist/assets/JsonOutput-Cx1iyibB.js +11 -0
- package/dist/assets/{LazyAnyLanguageCodeMirror-CKcCbG2G.js → LazyAnyLanguageCodeMirror-B4fCknq1.js} +2 -2
- package/dist/assets/MarimoErrorOutput-s_5GOX8k.js +10 -0
- package/dist/assets/{RenderHTML-BbOqmHy3.js → RenderHTML-DX6i99Op.js} +1 -1
- package/dist/assets/{RunButton-CK3LhnP5.js → RunButton-BKoh0zYG.js} +1 -1
- package/dist/assets/{add-cell-with-ai-8UBC0xwR.js → add-cell-with-ai-BpD_790A.js} +11 -11
- package/dist/assets/{add-connection-dialog-DXQnd6eB.js → add-connection-dialog-B1BXCjex.js} +2 -2
- package/dist/assets/{agent-panel-D7kMZLG-.js → agent-panel-CDFUc1uu.js} +5 -5
- package/dist/assets/ai-model-dropdown-i1vfGeVi.js +13 -0
- package/dist/assets/{any-language-editor-BLCAD3yx.js → any-language-editor-BdTWdMCI.js} +1 -1
- package/dist/assets/{app-config-button-BKEG4x9u.js → app-config-button-AdV-QDD7.js} +1 -1
- package/dist/assets/{blob-D5nfNHOo.js → blob-BG8yoQmx.js} +1 -1
- package/dist/assets/{cell-editor-ADVfycpN.js → cell-editor-BKJ06H5F.js} +9 -9
- package/dist/assets/cell-link-8Auigi8P.js +1 -0
- package/dist/assets/{cells-BRkCaSsh.js → cells-C6YGYGdi.js} +56 -56
- package/dist/assets/{chat-display-Dnagy4Nv.js → chat-display-DhgI2MS9.js} +1 -1
- package/dist/assets/{chat-panel-DQ6HkWEF.js → chat-panel-Cau71Ygr.js} +2 -2
- package/dist/assets/{chat-ui-Df8Vcj6n.js → chat-ui-C5ql1Up-.js} +1 -1
- package/dist/assets/code-visibility-BJImdpDi.js +1 -0
- package/dist/assets/coerce-DWjFeXOY.js +1 -0
- package/dist/assets/{column-preview-Cm2D6vyX.js → column-preview-BZ_iNhtJ.js} +1 -1
- package/dist/assets/{command-palette-DTSQ7gOC.js → command-palette-DDC3kBet.js} +1 -1
- package/dist/assets/{common-Cu6CDbuw.js → common-Sl3uthjg.js} +1 -1
- package/dist/assets/{components-CGw16R_N.js → components-3cou6Mka.js} +1 -1
- package/dist/assets/{components-CP_UoFtT.js → components-CskjK6xZ.js} +1 -1
- package/dist/assets/{components-CXfO-F47.js → components-YBmtV0p6.js} +1 -1
- package/dist/assets/{config-VPSq73n8.js → config-CA1V-wjh.js} +1 -1
- package/dist/assets/config-DRIpOKqh.js +1 -0
- package/dist/assets/config-Dy28fDwn.js +1 -0
- package/dist/assets/{datasource-Cq6x_5ML.js → datasource-DfbNb83e.js} +1 -1
- package/dist/assets/{dates-BbFQ2oE4.js → dates-CfmdTL6B.js} +1 -1
- package/dist/assets/{dependency-graph-panel--Kgtktcw.js → dependency-graph-panel-L5cBE5sl.js} +1 -1
- package/dist/assets/{documentation-panel-BHmbeznw.js → documentation-panel-D7S8JIc2.js} +1 -1
- package/dist/assets/{download-DCJXy66H.js → download-C03FOElq.js} +1 -1
- package/dist/assets/edit-page-CLF_VUTW.js +9 -0
- package/dist/assets/{error-banner-Cd69vvyX.js → error-banner-COZ7SfYV.js} +1 -1
- package/dist/assets/{error-entries-Dk3VZ-OK.js → error-entries-CLnPDv7b.js} +1 -1
- package/dist/assets/{error-panel-BPRYmC5J.js → error-panel-D2xrYLue.js} +1 -1
- package/dist/assets/{errors-DCrsa1nH.js → errors-CNsgAw6m.js} +1 -1
- package/dist/assets/{feedback-button-Bik2-e33.js → feedback-button-DzPunIqU.js} +2 -2
- package/dist/assets/feedback-button-Kla7i5RT.js +1 -0
- package/dist/assets/{file-explorer-panel-BEEK5lcl.js → file-explorer-panel-Uk4_QIJQ.js} +1 -1
- package/dist/assets/{file-name-input-Cdc-TVqO.js → file-name-input-B4fRaQkI.js} +1 -1
- package/dist/assets/{floating-outline-XD9FAV-f.js → floating-outline-B5MaM1JS.js} +1 -1
- package/dist/assets/{gallery-page-Dm6mGwBi.js → gallery-page-BefvdsM7.js} +1 -1
- package/dist/assets/{glide-data-editor-J9CAb70d.js → glide-data-editor-C3eaYlXg.js} +1 -1
- package/dist/assets/{home-page-DMHnsRxm.js → home-page-hmvKlc1w.js} +1 -1
- package/dist/assets/{hooks-93IwHd2u.js → hooks-DzML9nez.js} +1 -1
- package/dist/assets/index-6b4mf8Ai.css +2 -0
- package/dist/assets/index-CMx5iSyu.js +30 -0
- package/dist/assets/{layout-DmcNEu3P.js → layout-Ck1RoL1B.js} +5 -5
- package/dist/assets/{logs-panel-ABM16htT.js → logs-panel-BRytaWaO.js} +1 -1
- package/dist/assets/{markdown-renderer-BG3sp2rs.js → markdown-renderer-DX0Xrrfy.js} +1 -1
- package/dist/assets/{mermaid-a3xYymTy.js → mermaid-C4EiVqcd.js} +1 -1
- package/dist/assets/{name-cell-input-BgEBmqyL.js → name-cell-input-DlpTvPLa.js} +1 -1
- package/dist/assets/{outline-panel-DCXQ3_F6.js → outline-panel-B2WIpz-1.js} +1 -1
- package/dist/assets/{packages-panel-BMGOmZkR.js → packages-panel-CI5ff9b-.js} +1 -1
- package/dist/assets/{panel-accordion-state-C1sdPp0m.js → panel-accordion-state-BqSH5ttk.js} +1 -1
- package/dist/assets/panels-B_jlikjE.js +107 -0
- package/dist/assets/{process-output-D0KGq04R.js → process-output-f3C3PD0Z.js} +1 -1
- package/dist/assets/{readonly-code-display-Do50PHI8.js → readonly-code-display-MnMEoYW5.js} +1 -1
- package/dist/assets/{readonly-python-code-DCSMIsTX.js → readonly-python-code-ggs4hAzC.js} +1 -1
- package/dist/assets/{renderShortcut-BkVJQ_Zh.js → renderShortcut-C1JwYcqW.js} +1 -1
- package/dist/assets/{reveal-component-ltaepAqw.js → reveal-component-PiV1eQk9.js} +1 -1
- package/dist/assets/run-page-CkP22x9D.js +1 -0
- package/dist/assets/{runtime-details-state-CSPobEdR.js → runtime-details-state-CoL-p0MC.js} +1 -1
- package/dist/assets/{schemas-Dv42wLFq.js → schemas-ChRqMOTL.js} +1 -1
- package/dist/assets/{scratchpad-panel-Dwd6W5PE.js → scratchpad-panel-D2rWg4k8.js} +1 -1
- package/dist/assets/{secrets-panel-Bctbtkrp.js → secrets-panel-D7KN4tVs.js} +1 -1
- package/dist/assets/session-panel-CnANhcTo.js +1 -0
- package/dist/assets/{snippets-panel-Bh1oTw4m.js → snippets-panel-ClGHtEKQ.js} +1 -1
- package/dist/assets/state-CbjBtkdd.js +3 -0
- package/dist/assets/{state-XsPO8hNi.js → state-DtGB7xeJ.js} +1 -1
- package/dist/assets/{terminal-Ck_vK-34.js → terminal-wnSHYT8N.js} +1 -1
- package/dist/assets/{tracing-Di6pUmX8.js → tracing-Dz2rYOFL.js} +1 -1
- package/dist/assets/{tracing-panel-PeRXHD8_.js → tracing-panel-DqQY9V91.js} +2 -2
- package/dist/assets/{tree-actions-GM5E_bUs.js → tree-actions-DnUokmva.js} +1 -1
- package/dist/assets/{useAddCell-GR7eEQrT.js → useAddCell-IN24thff.js} +1 -1
- package/dist/assets/{useBoolean-BDD6_xQQ.js → useBoolean-d0Tty94N.js} +1 -1
- package/dist/assets/{useCellActionButton-B-9eG5z_.js → useCellActionButton-DmaFZ4oF.js} +1 -1
- package/dist/assets/{useDeleteCell-2_bMClHd.js → useDeleteCell-fQlM46Y2.js} +1 -1
- package/dist/assets/{useDependencyPanelTab-k3C3M18S.js → useDependencyPanelTab-ImXYINm_.js} +1 -1
- package/dist/assets/{useInstallPackage-iX1eufdl.js → useInstallPackage-BW06eter.js} +1 -1
- package/dist/assets/{useNotebookActions-NHN6A-cN.js → useNotebookActions-DHt3s-ia.js} +1 -1
- package/dist/assets/{useRunCells-B2vUhREg.js → useRunCells-DSJPXE-j.js} +1 -1
- package/dist/assets/{useSplitCell-DEb03htp.js → useSplitCell-DQyMF5gd.js} +1 -1
- package/dist/assets/{useTheme-COhSHkCj.js → useTheme-n8Dj1zH7.js} +1 -1
- package/dist/assets/{vega-component-CnadTgoE.js → vega-component-IouMe13t.js} +1 -1
- package/dist/index.html +34 -35
- package/package.json +1 -1
- package/src/__tests__/fixtures/{pair-preview.ts → pair-config.ts} +3 -2
- package/src/__tests__/mount.test.ts +28 -8
- package/src/components/data-table/__tests__/context-menu.test.ts +176 -0
- package/src/components/data-table/__tests__/date-filter-inputs.test.tsx +24 -1
- package/src/components/data-table/__tests__/export-actions.test.tsx +329 -6
- package/src/components/data-table/context-menu.tsx +125 -26
- package/src/components/data-table/date-filter-inputs.tsx +15 -42
- package/src/components/data-table/export-actions.tsx +192 -116
- package/src/components/data-table/schemas.ts +14 -36
- package/src/components/data-table/utils.ts +18 -0
- package/src/components/editor/Output.tsx +9 -2
- package/src/components/editor/actions/__tests__/pair-with-agent-commands.test.ts +80 -252
- package/src/components/editor/actions/__tests__/pair-with-agent-modal.test.tsx +186 -34
- package/src/components/editor/actions/pair-with-agent-commands.ts +42 -51
- package/src/components/editor/actions/pair-with-agent-modal.tsx +96 -36
- package/src/components/editor/chrome/panels/error-panel.tsx +1 -0
- package/src/components/editor/chrome/wrapper/__tests__/attachment-status.test.tsx +372 -0
- package/src/components/editor/chrome/wrapper/footer-item.tsx +32 -24
- package/src/components/editor/chrome/wrapper/footer-items/attachment-status.tsx +237 -0
- package/src/components/editor/chrome/wrapper/footer.tsx +2 -0
- package/src/components/editor/errors/__tests__/send-error-report-button.test.tsx +548 -0
- package/src/components/editor/errors/send-error-report-button.tsx +69 -0
- package/src/components/editor/output/MarimoErrorOutput.tsx +21 -5
- package/src/components/editor/output/MarimoTracebackOutput.tsx +35 -20
- package/src/components/editor/output/__tests__/ansi-reduce.test.ts +18 -0
- package/src/components/editor/output/ansi-reduce.ts +6 -0
- package/src/core/attachments/__tests__/toast.test.tsx +58 -0
- package/src/core/attachments/state.ts +21 -0
- package/src/core/attachments/toast.ts +15 -0
- package/src/core/cells/__tests__/cells.test.ts +52 -0
- package/src/core/cells/__tests__/error-report.test.ts +139 -0
- package/src/core/cells/__tests__/session.test.ts +50 -1
- package/src/core/cells/error-report.ts +63 -0
- package/src/core/cells/session.ts +28 -1
- package/src/core/config/pair.ts +5 -3
- package/src/core/edit-app.tsx +2 -2
- package/src/core/host/AGENTS.md +5 -0
- package/src/core/host/__tests__/document.test.ts +124 -0
- package/src/core/host/__tests__/events.test.ts +46 -0
- package/src/core/host/__tests__/fixtures.ts +39 -0
- package/src/core/host/__tests__/notebook-client.test.ts +303 -0
- package/src/core/host/__tests__/stream.test.ts +211 -0
- package/src/core/host/connection.ts +81 -0
- package/src/core/host/events.ts +60 -0
- package/src/core/host/notebook-client.ts +272 -0
- package/src/core/host/resources/document.ts +101 -0
- package/src/core/host/resources/resource.ts +59 -0
- package/src/core/host/stream.ts +213 -0
- package/src/core/islands/__tests__/bootstrap.test.ts +26 -0
- package/src/core/islands/bootstrap.ts +1 -0
- package/src/core/network/connection.ts +4 -2
- package/src/core/run-app.tsx +2 -2
- package/src/core/runtime/__tests__/runtime.test.ts +55 -11
- package/src/core/runtime/runtime.ts +14 -1
- package/src/core/runtime/types.ts +2 -0
- package/src/core/websocket/__tests__/{useMarimoKernelConnection.test.ts → connection-state.test.ts} +15 -17
- package/src/core/websocket/__tests__/{useWebSocket.test.ts → createConnectionTransport.test.ts} +1 -1
- package/src/core/websocket/__tests__/useNotebookClient.hook.test.tsx +140 -0
- package/src/core/websocket/__tests__/{useMarimoKernelConnection.hook.test.tsx → useNotebookSession.hook.test.tsx} +352 -65
- package/src/core/websocket/connection-state.ts +70 -0
- package/src/core/websocket/transports/__tests__/sse.test.ts +1 -4
- package/src/core/websocket/transports/create.ts +31 -0
- package/src/core/websocket/transports/transport.ts +12 -23
- package/src/core/websocket/types.ts +9 -39
- package/src/core/websocket/useNotebookClient.ts +80 -0
- package/src/core/websocket/{useMarimoKernelConnection.tsx → useNotebookSession.tsx} +67 -225
- package/src/mount.tsx +7 -3
- package/src/plugins/impl/__tests__/DataTablePlugin.test.tsx +84 -0
- package/src/utils/__tests__/dates.test.ts +116 -0
- package/src/utils/dates.ts +94 -0
- package/dist/assets/JsonOutput-D6HIIsCb.js +0 -11
- package/dist/assets/MarimoErrorOutput-D60XkCny.js +0 -6
- package/dist/assets/ai-model-dropdown-B0z6-zhp.js +0 -5
- package/dist/assets/api-BeC_VSGv.js +0 -1
- package/dist/assets/cell-link-LSth_8hT.js +0 -1
- package/dist/assets/code-visibility-B-_GvwR5.js +0 -1
- package/dist/assets/coerce-CpE6kUdX.js +0 -1
- package/dist/assets/config-BOKzA3tF.js +0 -1
- package/dist/assets/config-DX8Y2WbJ.js +0 -1
- package/dist/assets/edit-page-ChcSgpke.js +0 -9
- package/dist/assets/feedback-button-B2gKC5cn.js +0 -1
- package/dist/assets/index-Bcdzex-3.css +0 -2
- package/dist/assets/index-s-M1OXjs.js +0 -29
- package/dist/assets/pair-CaQyK6En.js +0 -1
- package/dist/assets/panels-CxVG8-v2.js +0 -4
- package/dist/assets/run-page-DF3c5cDk.js +0 -1
- package/dist/assets/session-panel-VdDhEBa-.js +0 -1
- package/dist/assets/state-_Qai_QyX.js +0 -3
- package/src/core/websocket/useWebSocket.tsx +0 -88
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import type { CloseDecision } from "../host/connection";
|
|
4
|
+
import { Logger } from "@/utils/Logger";
|
|
5
|
+
import { TRANSPORT_EXHAUSTED_REASON } from "./transports/ws";
|
|
6
|
+
import { ConnectionState, WebSocketClosedReason } from "./types";
|
|
7
|
+
|
|
8
|
+
// Keep server reasons in sync with ws_endpoint.py and ws/*.py.
|
|
9
|
+
// SSE carries the same reasons in close events. Unclassified reasons retry.
|
|
10
|
+
export function classifyCloseEvent(event: { reason?: string }): CloseDecision {
|
|
11
|
+
switch (event.reason) {
|
|
12
|
+
case TRANSPORT_EXHAUSTED_REASON:
|
|
13
|
+
return {
|
|
14
|
+
kind: "gave-up",
|
|
15
|
+
status: {
|
|
16
|
+
state: ConnectionState.CLOSED,
|
|
17
|
+
code: WebSocketClosedReason.KERNEL_DISCONNECTED,
|
|
18
|
+
reason: "kernel not found",
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
case "MARIMO_NO_FILE_KEY":
|
|
22
|
+
case "MARIMO_NO_SESSION_ID":
|
|
23
|
+
case "MARIMO_NO_SESSION":
|
|
24
|
+
case "MARIMO_SHUTDOWN":
|
|
25
|
+
return {
|
|
26
|
+
kind: "terminal",
|
|
27
|
+
status: {
|
|
28
|
+
state: ConnectionState.CLOSED,
|
|
29
|
+
code: WebSocketClosedReason.KERNEL_DISCONNECTED,
|
|
30
|
+
reason: "kernel not found",
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
case "MARIMO_UNAUTHORIZED":
|
|
34
|
+
return {
|
|
35
|
+
kind: "terminal",
|
|
36
|
+
status: {
|
|
37
|
+
state: ConnectionState.CLOSED,
|
|
38
|
+
code: WebSocketClosedReason.KERNEL_DISCONNECTED,
|
|
39
|
+
reason: "not authorized",
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
case "MARIMO_KIOSK_NOT_ALLOWED":
|
|
43
|
+
return {
|
|
44
|
+
kind: "terminal",
|
|
45
|
+
status: {
|
|
46
|
+
state: ConnectionState.CLOSED,
|
|
47
|
+
code: WebSocketClosedReason.KERNEL_DISCONNECTED,
|
|
48
|
+
reason: "kiosk mode is not available for this session",
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
case "MARIMO_KERNEL_STARTUP_ERROR":
|
|
52
|
+
return {
|
|
53
|
+
kind: "terminal",
|
|
54
|
+
status: {
|
|
55
|
+
state: ConnectionState.CLOSED,
|
|
56
|
+
code: WebSocketClosedReason.KERNEL_STARTUP_ERROR,
|
|
57
|
+
reason: "Failed to start kernel sandbox",
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
default:
|
|
61
|
+
if (event.reason) {
|
|
62
|
+
Logger.warn("Unrecognized connection close reason", event.reason);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return {
|
|
67
|
+
kind: "retry",
|
|
68
|
+
status: { state: ConnectionState.CONNECTING },
|
|
69
|
+
};
|
|
70
|
+
}
|
|
@@ -108,8 +108,6 @@ describe("SseTransport", () => {
|
|
|
108
108
|
transport.reconnect();
|
|
109
109
|
await vi.waitFor(() => expect(opens).toHaveLength(1));
|
|
110
110
|
|
|
111
|
-
// Stop retrying when the consumer treats the close as terminal,
|
|
112
|
-
// mirroring useMarimoKernelConnection's terminal path.
|
|
113
111
|
transport.addEventListener("close", () => transport.close());
|
|
114
112
|
push('event: close\ndata: {"code": 1000, "reason": "MARIMO_SHUTDOWN"}\n\n');
|
|
115
113
|
await vi.waitFor(() => expect(closes).toHaveLength(1));
|
|
@@ -146,8 +144,7 @@ describe("SseTransport", () => {
|
|
|
146
144
|
fetchMock
|
|
147
145
|
.mockResolvedValueOnce(sseResponse(first.stream))
|
|
148
146
|
.mockResolvedValueOnce(sseResponse(second.stream));
|
|
149
|
-
//
|
|
150
|
-
// synchronously from inside the close handler.
|
|
147
|
+
// Reconnect synchronously from the close handler.
|
|
151
148
|
transport.addEventListener("close", () => transport.reconnect());
|
|
152
149
|
|
|
153
150
|
transport.reconnect();
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import { createPyodideConnection } from "../../wasm/bridge";
|
|
4
|
+
import { isWasm } from "../../wasm/utils";
|
|
5
|
+
import { BasicTransport } from "./basic";
|
|
6
|
+
import { SseTransport } from "./sse";
|
|
7
|
+
import { WsTransport } from "./ws";
|
|
8
|
+
import type { IConnectionTransport } from "./transport";
|
|
9
|
+
|
|
10
|
+
export interface ConnectionTransportOptions {
|
|
11
|
+
url: () => string;
|
|
12
|
+
static: boolean;
|
|
13
|
+
transportType: "websocket" | "sse";
|
|
14
|
+
headers: () => Record<string, string>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function createConnectionTransport(
|
|
18
|
+
options: ConnectionTransportOptions,
|
|
19
|
+
): IConnectionTransport {
|
|
20
|
+
if (options.static) {
|
|
21
|
+
return BasicTransport.empty();
|
|
22
|
+
}
|
|
23
|
+
if (isWasm()) {
|
|
24
|
+
return createPyodideConnection();
|
|
25
|
+
}
|
|
26
|
+
// Read the URL lazily to follow runtime redirects.
|
|
27
|
+
if (options.transportType === "sse") {
|
|
28
|
+
return new SseTransport(options.url, options.headers);
|
|
29
|
+
}
|
|
30
|
+
return new WsTransport(options.url);
|
|
31
|
+
}
|
|
@@ -1,30 +1,19 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
-
export type ConnectionEvent = "open" | "close" | "message" | "error";
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
3
|
+
import type {
|
|
4
|
+
NotebookTransport,
|
|
5
|
+
ConnectionEvent,
|
|
6
|
+
ConnectionTransportCallback,
|
|
7
|
+
IConnectionTransportMap,
|
|
8
|
+
} from "../../host/connection";
|
|
9
|
+
export type {
|
|
10
|
+
ConnectionEvent,
|
|
11
|
+
ConnectionTransportCallback,
|
|
12
|
+
IConnectionTransportMap,
|
|
13
|
+
} from "../../host/connection";
|
|
14
14
|
|
|
15
|
-
export interface IConnectionTransport {
|
|
16
|
-
reconnect(code?: number | undefined, reason?: string | undefined): void;
|
|
17
|
-
close(): void;
|
|
15
|
+
export interface IConnectionTransport extends NotebookTransport {
|
|
18
16
|
send(data: string | ArrayBuffer | Blob | ArrayBufferView<ArrayBuffer>): void;
|
|
19
|
-
addEventListener<T extends ConnectionEvent>(
|
|
20
|
-
event: T,
|
|
21
|
-
callback: ConnectionTransportCallback<T>,
|
|
22
|
-
): void;
|
|
23
|
-
removeEventListener<T extends ConnectionEvent>(
|
|
24
|
-
event: T,
|
|
25
|
-
callback: ConnectionTransportCallback<T>,
|
|
26
|
-
): void;
|
|
27
|
-
readyState: WebSocket["readyState"];
|
|
28
17
|
}
|
|
29
18
|
|
|
30
19
|
export class ConnectionSubscriptions {
|
|
@@ -1,47 +1,17 @@
|
|
|
1
1
|
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
2
|
|
|
3
|
+
import type { ConnectionStatus as HostConnectionStatus } from "../host/connection";
|
|
3
4
|
import type { NotificationMessageData } from "../kernel/messages";
|
|
4
5
|
|
|
6
|
+
export {
|
|
7
|
+
ConnectionState,
|
|
8
|
+
ConnectionClosedReason as WebSocketClosedReason,
|
|
9
|
+
} from "../host/connection";
|
|
10
|
+
|
|
5
11
|
export type ConnectionPhase =
|
|
6
12
|
| NotificationMessageData<"startup-progress">["phase"]
|
|
7
13
|
| "reconnecting";
|
|
8
14
|
|
|
9
|
-
export
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
OPEN: "OPEN",
|
|
13
|
-
CLOSING: "CLOSING",
|
|
14
|
-
CLOSED: "CLOSED",
|
|
15
|
-
} as const;
|
|
16
|
-
|
|
17
|
-
export type ConnectionState =
|
|
18
|
-
(typeof ConnectionState)[keyof typeof ConnectionState];
|
|
19
|
-
|
|
20
|
-
export const WebSocketClosedReason = {
|
|
21
|
-
KERNEL_DISCONNECTED: "KERNEL_DISCONNECTED",
|
|
22
|
-
KERNEL_STARTUP_ERROR: "KERNEL_STARTUP_ERROR",
|
|
23
|
-
} as const;
|
|
24
|
-
|
|
25
|
-
export type WebSocketClosedReason =
|
|
26
|
-
(typeof WebSocketClosedReason)[keyof typeof WebSocketClosedReason];
|
|
27
|
-
|
|
28
|
-
export type ConnectionStatus =
|
|
29
|
-
| {
|
|
30
|
-
state: typeof ConnectionState.CLOSED;
|
|
31
|
-
code: WebSocketClosedReason;
|
|
32
|
-
/**
|
|
33
|
-
* Human-readable reason for closing the connection.
|
|
34
|
-
*/
|
|
35
|
-
reason: string;
|
|
36
|
-
phase?: ConnectionPhase;
|
|
37
|
-
}
|
|
38
|
-
| {
|
|
39
|
-
state: typeof ConnectionState.CONNECTING;
|
|
40
|
-
phase?: ConnectionPhase;
|
|
41
|
-
}
|
|
42
|
-
| {
|
|
43
|
-
state:
|
|
44
|
-
| typeof ConnectionState.OPEN
|
|
45
|
-
| typeof ConnectionState.CLOSING
|
|
46
|
-
| typeof ConnectionState.NOT_STARTED;
|
|
47
|
-
};
|
|
15
|
+
export type ConnectionStatus = HostConnectionStatus & {
|
|
16
|
+
phase?: ConnectionPhase;
|
|
17
|
+
};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
+
|
|
3
|
+
import { useStore } from "jotai";
|
|
4
|
+
import { useEffect, useMemo } from "react";
|
|
5
|
+
import useEvent from "react-use-event-hook";
|
|
6
|
+
import { jsonParseWithSpecialChar } from "@/utils/json/json-parser";
|
|
7
|
+
import type {
|
|
8
|
+
NotificationMessage,
|
|
9
|
+
NotificationPayload,
|
|
10
|
+
} from "../kernel/messages";
|
|
11
|
+
import {
|
|
12
|
+
createNotebookClient,
|
|
13
|
+
type NotebookClient,
|
|
14
|
+
type NotebookConnection,
|
|
15
|
+
} from "../host/notebook-client";
|
|
16
|
+
import { classifyCloseEvent } from "./connection-state";
|
|
17
|
+
import {
|
|
18
|
+
createConnectionTransport,
|
|
19
|
+
type ConnectionTransportOptions,
|
|
20
|
+
} from "./transports/create";
|
|
21
|
+
|
|
22
|
+
type Options = ConnectionTransportOptions & {
|
|
23
|
+
sessionId: string;
|
|
24
|
+
messageFormat: NotebookConnection["messageFormat"];
|
|
25
|
+
waitUntilReady: () => Promise<void>;
|
|
26
|
+
checkHealth: () => Promise<boolean>;
|
|
27
|
+
onNotification: (notification: NotificationPayload) => void;
|
|
28
|
+
onMessageError: NotebookConnection["onMessageError"];
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export function useNotebookClient(options: Options): NotebookClient {
|
|
32
|
+
const store = useStore();
|
|
33
|
+
const { sessionId, static: isStatic, transportType, messageFormat } = options;
|
|
34
|
+
const controller = useMemo(() => createNotebookClient(store), [store]);
|
|
35
|
+
const url = useEvent(options.url);
|
|
36
|
+
const headers = useEvent(options.headers);
|
|
37
|
+
const waitUntilReady = useEvent(options.waitUntilReady);
|
|
38
|
+
const checkHealth = useEvent(options.checkHealth);
|
|
39
|
+
const onNotification = useEvent(options.onNotification);
|
|
40
|
+
const onMessageError = useEvent(options.onMessageError);
|
|
41
|
+
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
const lifetime = new AbortController();
|
|
44
|
+
controller.connect({
|
|
45
|
+
createTransport: (url) =>
|
|
46
|
+
createConnectionTransport({
|
|
47
|
+
url,
|
|
48
|
+
headers,
|
|
49
|
+
static: isStatic,
|
|
50
|
+
transportType,
|
|
51
|
+
}),
|
|
52
|
+
url,
|
|
53
|
+
messageFormat,
|
|
54
|
+
signal: lifetime.signal,
|
|
55
|
+
waitUntilReady,
|
|
56
|
+
checkHealth,
|
|
57
|
+
onMessageError,
|
|
58
|
+
// The host validates the envelope, not the native notification contents.
|
|
59
|
+
onNotification: (notification) =>
|
|
60
|
+
onNotification({ data: notification as NotificationMessage }),
|
|
61
|
+
decodeJson: jsonParseWithSpecialChar,
|
|
62
|
+
classifyClose: classifyCloseEvent,
|
|
63
|
+
});
|
|
64
|
+
return () => lifetime.abort();
|
|
65
|
+
}, [
|
|
66
|
+
controller,
|
|
67
|
+
sessionId,
|
|
68
|
+
isStatic,
|
|
69
|
+
transportType,
|
|
70
|
+
messageFormat,
|
|
71
|
+
url,
|
|
72
|
+
headers,
|
|
73
|
+
waitUntilReady,
|
|
74
|
+
checkHealth,
|
|
75
|
+
onNotification,
|
|
76
|
+
onMessageError,
|
|
77
|
+
]);
|
|
78
|
+
|
|
79
|
+
return controller.client;
|
|
80
|
+
}
|