@marimo-team/islands 0.25.3-dev312 → 0.25.3-dev317
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/{ErrorBoundary-CCrWQ8Zi.js → ErrorBoundary-BzPZHD9j.js} +1 -1
- package/dist/{chat-ui-DkuxGEDp.js → chat-ui-DASKYW38.js} +13 -13
- package/dist/{code-visibility-DLBADpvq.js → code-visibility-nvHsJTCm.js} +31 -32
- package/dist/{common-Cc-bvilP.js → common-DmnownXk.js} +5074 -5074
- package/dist/{config-BVYA1P0C.js → config-CL7mwGLX.js} +87 -129
- package/dist/{data-grid-overlay-editor-CAEih52I.js → data-grid-overlay-editor-eXoZLGys.js} +1 -1
- package/dist/{error-entries-istW7Xbs.js → error-entries-kb4H6PAT.js} +533 -508
- package/dist/feedback-button-DDdckIvG.js +370 -0
- package/dist/{formats-CMa7L3E8.js → formats-qhBmYb0l.js} +1 -1
- package/dist/{glide-data-editor-hsf5AOwE.js → glide-data-editor-keVyefZP.js} +3 -3
- package/dist/{globals-Blgj9EWO.js → globals-UY7m7ERN.js} +1 -1
- package/dist/{html-to-image-pPbR2cDx.js → html-to-image-DR8VPB7E.js} +4018 -4021
- package/dist/main.js +606 -607
- package/dist/{number-overlay-editor-BgNsDtQP.js → number-overlay-editor-Dryq4VDA.js} +1 -1
- package/dist/{process-output-BySO1nIs.js → process-output-BDMtqL6K.js} +2 -2
- package/dist/{reveal-component-MUD9gGln.js → reveal-component-BIBrITpY.js} +4 -4
- package/dist/static-state-Dtocd9UO.js +68 -0
- package/dist/{vega-component-Bly2lDhz.js → vega-component-CeN8zClP.js} +9 -9
- package/package.json +1 -1
- package/src/__tests__/mount.test.ts +17 -58
- package/src/components/editor/actions/useRestartKernel.tsx +0 -5
- package/src/components/editor/cell/__tests__/useRunCells.test.tsx +0 -3
- package/src/components/editor/cell/useRunCells.ts +2 -2
- package/src/components/editor/chrome/wrapper/footer-items/backend-status.tsx +2 -16
- package/src/components/editor/renderers/cell-array.tsx +0 -3
- package/src/core/edit-app.tsx +2 -7
- package/src/core/executions/__tests__/run.test.ts +0 -3
- package/src/core/executions/index.ts +1 -1
- package/src/core/executions/run.ts +1 -14
- package/src/core/islands/bootstrap.ts +0 -1
- package/src/core/network/__tests__/requests-network.test.ts +0 -16
- package/src/core/network/connection.ts +0 -5
- package/src/core/network/requests-toasting.tsx +1 -49
- package/src/core/network/resolve.ts +1 -5
- package/src/core/notebook/replica/__tests__/replica.test.ts +3 -3
- package/src/core/notebook/replica/connection.ts +1 -5
- package/src/core/runtime/__tests__/createWsUrl.test.ts +4 -16
- package/src/core/runtime/__tests__/runtime.test.ts +58 -168
- package/src/core/runtime/adapter.ts +1 -8
- package/src/core/runtime/config.ts +4 -59
- package/src/core/runtime/runtime.ts +1 -31
- package/src/core/runtime/types.ts +0 -5
- package/src/core/session/__tests__/useNotebookReplica.hook.test.tsx +5 -5
- package/src/core/session/__tests__/useNotebookSession.hook.test.tsx +125 -29
- package/src/core/session/connection-utils.ts +2 -14
- package/src/core/session/useNotebookSession.tsx +19 -12
- package/src/mount.tsx +3 -9
- package/src/utils/errors.ts +0 -7
- package/dist/feedback-button-BJvIOw-c.js +0 -371
- package/dist/toDate-5qPtZ6HL.js +0 -94
- package/src/components/editor/alerts/connecting-alert.tsx +0 -27
- package/src/core/network/__tests__/requests-lazy.test.ts +0 -322
- package/src/core/network/requests-lazy.ts +0 -222
|
@@ -1,322 +0,0 @@
|
|
|
1
|
-
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
-
|
|
3
|
-
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
4
|
-
import { requestId, uiElementId } from "@/__tests__/branded";
|
|
5
|
-
import { waitForRuntimeRunning } from "../../executions";
|
|
6
|
-
import type { RuntimeManager } from "../../runtime/runtime";
|
|
7
|
-
import { waitForConnectionOpen } from "../connection";
|
|
8
|
-
import { createLazyRequests } from "../requests-lazy";
|
|
9
|
-
import type {
|
|
10
|
-
EditRequests,
|
|
11
|
-
ExportAvailabilityResponse,
|
|
12
|
-
RunRequests,
|
|
13
|
-
} from "../types";
|
|
14
|
-
|
|
15
|
-
// Mock the connection module
|
|
16
|
-
vi.mock("../connection", async () => {
|
|
17
|
-
const { atom } = await import("jotai");
|
|
18
|
-
return {
|
|
19
|
-
connectionAtom: atom({ state: "NOT_STARTED" }),
|
|
20
|
-
waitForConnectionOpen: vi.fn().mockResolvedValue(undefined),
|
|
21
|
-
};
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
// Mock the kernel state module
|
|
25
|
-
vi.mock("../../executions", () => ({
|
|
26
|
-
waitForRuntimeRunning: vi.fn().mockResolvedValue(undefined),
|
|
27
|
-
}));
|
|
28
|
-
|
|
29
|
-
describe("createLazyRequests", () => {
|
|
30
|
-
let mockDelegate: EditRequests & RunRequests;
|
|
31
|
-
let mockRuntimeManager: RuntimeManager;
|
|
32
|
-
let mockGetRuntimeManager: () => RuntimeManager;
|
|
33
|
-
let mockInit: ReturnType<typeof vi.fn>;
|
|
34
|
-
|
|
35
|
-
beforeEach(() => {
|
|
36
|
-
vi.clearAllMocks();
|
|
37
|
-
|
|
38
|
-
// Mock init function
|
|
39
|
-
mockInit = vi.fn().mockResolvedValue(undefined);
|
|
40
|
-
|
|
41
|
-
// Mock runtime manager
|
|
42
|
-
mockRuntimeManager = {
|
|
43
|
-
init: mockInit,
|
|
44
|
-
isLazy: true,
|
|
45
|
-
} as unknown as RuntimeManager;
|
|
46
|
-
|
|
47
|
-
// Mock getter function
|
|
48
|
-
mockGetRuntimeManager = vi.fn(() => mockRuntimeManager);
|
|
49
|
-
|
|
50
|
-
// Mock delegate with some sample methods
|
|
51
|
-
mockDelegate = {
|
|
52
|
-
sendInstantiate: vi.fn().mockResolvedValue({ instantiated: true }),
|
|
53
|
-
sendFunctionRequest: vi.fn().mockResolvedValue({ result: "data" }),
|
|
54
|
-
sendRestart: vi.fn().mockResolvedValue({ restarted: true }),
|
|
55
|
-
sendInterrupt: vi.fn().mockResolvedValue({ interrupted: true }),
|
|
56
|
-
sendPdb: vi.fn().mockResolvedValue({ pdb: true }),
|
|
57
|
-
sendRunScratchpad: vi.fn().mockResolvedValue({ run: true }),
|
|
58
|
-
installExportRequirements: vi.fn().mockResolvedValue({
|
|
59
|
-
source: "server",
|
|
60
|
-
formats: [],
|
|
61
|
-
}),
|
|
62
|
-
} as unknown as EditRequests & RunRequests;
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
it("passes server-only requests through without starting a kernel", async () => {
|
|
66
|
-
const environment = { marimo: "1.2.3" };
|
|
67
|
-
mockDelegate.getEnvironmentInfo = vi
|
|
68
|
-
.fn()
|
|
69
|
-
.mockResolvedValue(environment) as EditRequests["getEnvironmentInfo"];
|
|
70
|
-
|
|
71
|
-
const lazyRequests = createLazyRequests(
|
|
72
|
-
mockDelegate,
|
|
73
|
-
mockGetRuntimeManager,
|
|
74
|
-
);
|
|
75
|
-
|
|
76
|
-
await expect(lazyRequests.getEnvironmentInfo()).resolves.toEqual(
|
|
77
|
-
environment,
|
|
78
|
-
);
|
|
79
|
-
expect(mockInit).not.toHaveBeenCalled();
|
|
80
|
-
expect(mockDelegate.getEnvironmentInfo).toHaveBeenCalledOnce();
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
it("gets export availability without starting a kernel", async () => {
|
|
84
|
-
const availability: ExportAvailabilityResponse = {
|
|
85
|
-
source: "server",
|
|
86
|
-
formats: [
|
|
87
|
-
{
|
|
88
|
-
format: "ipynb",
|
|
89
|
-
dependenciesAvailable: false,
|
|
90
|
-
missingPackages: ["nbformat"],
|
|
91
|
-
missingSetup: [],
|
|
92
|
-
},
|
|
93
|
-
],
|
|
94
|
-
};
|
|
95
|
-
mockDelegate.getExportAvailability = vi
|
|
96
|
-
.fn()
|
|
97
|
-
.mockResolvedValue(availability) as EditRequests["getExportAvailability"];
|
|
98
|
-
|
|
99
|
-
const lazyRequests = createLazyRequests(
|
|
100
|
-
mockDelegate,
|
|
101
|
-
mockGetRuntimeManager,
|
|
102
|
-
);
|
|
103
|
-
|
|
104
|
-
await expect(lazyRequests.getExportAvailability()).resolves.toEqual(
|
|
105
|
-
availability,
|
|
106
|
-
);
|
|
107
|
-
expect(mockInit).not.toHaveBeenCalled();
|
|
108
|
-
expect(mockDelegate.getExportAvailability).toHaveBeenCalledOnce();
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
it("installs export requirements without waiting for the kernel", async () => {
|
|
112
|
-
const lazyRequests = createLazyRequests(
|
|
113
|
-
mockDelegate,
|
|
114
|
-
mockGetRuntimeManager,
|
|
115
|
-
);
|
|
116
|
-
|
|
117
|
-
await lazyRequests.installExportRequirements({ format: "pdf" });
|
|
118
|
-
|
|
119
|
-
expect(mockInit).toHaveBeenCalledOnce();
|
|
120
|
-
expect(waitForConnectionOpen).toHaveBeenCalledOnce();
|
|
121
|
-
expect(waitForRuntimeRunning).not.toHaveBeenCalled();
|
|
122
|
-
expect(mockDelegate.installExportRequirements).toHaveBeenCalledWith({
|
|
123
|
-
format: "pdf",
|
|
124
|
-
});
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
it("sends instantiate without waiting for the kernel", async () => {
|
|
128
|
-
const lazyRequests = createLazyRequests(
|
|
129
|
-
mockDelegate,
|
|
130
|
-
mockGetRuntimeManager,
|
|
131
|
-
);
|
|
132
|
-
const request = {
|
|
133
|
-
objectIds: [uiElementId("obj1")],
|
|
134
|
-
values: [],
|
|
135
|
-
};
|
|
136
|
-
|
|
137
|
-
await lazyRequests.sendInstantiate(request);
|
|
138
|
-
|
|
139
|
-
expect(mockInit).toHaveBeenCalledOnce();
|
|
140
|
-
expect(waitForConnectionOpen).toHaveBeenCalledOnce();
|
|
141
|
-
expect(waitForRuntimeRunning).not.toHaveBeenCalled();
|
|
142
|
-
expect(mockDelegate.sendInstantiate).toHaveBeenCalledWith(request);
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
it("should call init once before first request", async () => {
|
|
146
|
-
const lazyRequests = createLazyRequests(
|
|
147
|
-
mockDelegate,
|
|
148
|
-
mockGetRuntimeManager,
|
|
149
|
-
);
|
|
150
|
-
|
|
151
|
-
await lazyRequests.sendRunScratchpad({ code: "code" });
|
|
152
|
-
|
|
153
|
-
expect(mockInit).toHaveBeenCalledTimes(1);
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
it("starts the kernel for datasource discovery", async () => {
|
|
157
|
-
mockDelegate.discoverDataSources = vi.fn().mockResolvedValue(null);
|
|
158
|
-
const lazyRequests = createLazyRequests(
|
|
159
|
-
mockDelegate,
|
|
160
|
-
mockGetRuntimeManager,
|
|
161
|
-
);
|
|
162
|
-
|
|
163
|
-
await lazyRequests.discoverDataSources({
|
|
164
|
-
requestId: requestId("discovery"),
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
expect(mockInit).toHaveBeenCalledOnce();
|
|
168
|
-
expect(mockDelegate.discoverDataSources).toHaveBeenCalledOnce();
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
it("should only call init once across multiple requests", async () => {
|
|
172
|
-
const lazyRequests = createLazyRequests(
|
|
173
|
-
mockDelegate,
|
|
174
|
-
mockGetRuntimeManager,
|
|
175
|
-
);
|
|
176
|
-
|
|
177
|
-
await lazyRequests.sendRunScratchpad({ code: "code" });
|
|
178
|
-
await lazyRequests.sendInstantiate({
|
|
179
|
-
objectIds: [uiElementId("obj1")],
|
|
180
|
-
values: [],
|
|
181
|
-
});
|
|
182
|
-
await lazyRequests.sendFunctionRequest({
|
|
183
|
-
functionCallId: requestId("func1"),
|
|
184
|
-
functionName: "testFunc",
|
|
185
|
-
args: {},
|
|
186
|
-
namespace: "test",
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
expect(mockInit).toHaveBeenCalledTimes(1);
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
it("should wait for connection before calling delegate method", async () => {
|
|
193
|
-
const { waitForConnectionOpen } = await import("../connection");
|
|
194
|
-
const lazyRequests = createLazyRequests(
|
|
195
|
-
mockDelegate,
|
|
196
|
-
mockGetRuntimeManager,
|
|
197
|
-
);
|
|
198
|
-
|
|
199
|
-
await lazyRequests.sendRunScratchpad({ code: "code" });
|
|
200
|
-
|
|
201
|
-
expect(waitForConnectionOpen).toHaveBeenCalled();
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
it("should call delegate method with correct arguments", async () => {
|
|
205
|
-
const lazyRequests = createLazyRequests(
|
|
206
|
-
mockDelegate,
|
|
207
|
-
mockGetRuntimeManager,
|
|
208
|
-
);
|
|
209
|
-
|
|
210
|
-
const args = { code: "code" };
|
|
211
|
-
await lazyRequests.sendRunScratchpad(args);
|
|
212
|
-
|
|
213
|
-
expect(mockDelegate.sendRunScratchpad).toHaveBeenCalledWith(args);
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
it("should return the result from delegate method", async () => {
|
|
217
|
-
const lazyRequests = createLazyRequests(
|
|
218
|
-
mockDelegate,
|
|
219
|
-
mockGetRuntimeManager,
|
|
220
|
-
);
|
|
221
|
-
|
|
222
|
-
const result = await lazyRequests.sendFunctionRequest({
|
|
223
|
-
functionCallId: requestId("func1"),
|
|
224
|
-
functionName: "testFunc",
|
|
225
|
-
args: {},
|
|
226
|
-
namespace: "test",
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
expect(result).toEqual({ result: "data" });
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
it("should wrap all methods from delegate", () => {
|
|
233
|
-
const lazyRequests = createLazyRequests(
|
|
234
|
-
mockDelegate,
|
|
235
|
-
mockGetRuntimeManager,
|
|
236
|
-
);
|
|
237
|
-
|
|
238
|
-
expect(lazyRequests.sendRunScratchpad).toBeDefined();
|
|
239
|
-
expect(lazyRequests.sendInstantiate).toBeDefined();
|
|
240
|
-
expect(lazyRequests.sendFunctionRequest).toBeDefined();
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
it("should handle errors from init", async () => {
|
|
244
|
-
const error = new Error("Init failed");
|
|
245
|
-
mockInit.mockRejectedValue(error);
|
|
246
|
-
|
|
247
|
-
const lazyRequests = createLazyRequests(
|
|
248
|
-
mockDelegate,
|
|
249
|
-
mockGetRuntimeManager,
|
|
250
|
-
);
|
|
251
|
-
|
|
252
|
-
await expect(
|
|
253
|
-
lazyRequests.sendRunScratchpad({ code: "code" }),
|
|
254
|
-
).rejects.toThrow("Init failed");
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
it("should handle errors from delegate method", async () => {
|
|
258
|
-
const error = new Error("Request failed");
|
|
259
|
-
mockDelegate.sendRunScratchpad = vi.fn().mockRejectedValue(error);
|
|
260
|
-
|
|
261
|
-
const lazyRequests = createLazyRequests(
|
|
262
|
-
mockDelegate,
|
|
263
|
-
mockGetRuntimeManager,
|
|
264
|
-
);
|
|
265
|
-
|
|
266
|
-
await expect(
|
|
267
|
-
lazyRequests.sendRunScratchpad({ code: "code" }),
|
|
268
|
-
).rejects.toThrow("Request failed");
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
describe("Memoization", () => {
|
|
272
|
-
it("should re-initialize if runtime manager changes", async () => {
|
|
273
|
-
const lazyRequests = createLazyRequests(
|
|
274
|
-
mockDelegate,
|
|
275
|
-
mockGetRuntimeManager,
|
|
276
|
-
);
|
|
277
|
-
|
|
278
|
-
// First request with first runtime manager
|
|
279
|
-
await lazyRequests.sendRunScratchpad({ code: "code" });
|
|
280
|
-
expect(mockInit).toHaveBeenCalledTimes(1);
|
|
281
|
-
|
|
282
|
-
// Create a new runtime manager
|
|
283
|
-
const mockInit2 = vi.fn().mockResolvedValue(undefined);
|
|
284
|
-
const mockRuntimeManager2 = {
|
|
285
|
-
init: mockInit2,
|
|
286
|
-
isLazy: true,
|
|
287
|
-
} as unknown as RuntimeManager;
|
|
288
|
-
mockGetRuntimeManager = vi.fn(() => mockRuntimeManager2);
|
|
289
|
-
|
|
290
|
-
// Create new lazy requests with new getter
|
|
291
|
-
const lazyRequests2 = createLazyRequests(
|
|
292
|
-
mockDelegate,
|
|
293
|
-
mockGetRuntimeManager,
|
|
294
|
-
);
|
|
295
|
-
|
|
296
|
-
// Second request with second runtime manager
|
|
297
|
-
await lazyRequests2.sendRunScratchpad({ code: "code" });
|
|
298
|
-
|
|
299
|
-
// Both inits should have been called
|
|
300
|
-
expect(mockInit).toHaveBeenCalledTimes(1);
|
|
301
|
-
expect(mockInit2).toHaveBeenCalledTimes(1);
|
|
302
|
-
});
|
|
303
|
-
|
|
304
|
-
it("should only initialize once per runtime manager instance", async () => {
|
|
305
|
-
const lazyRequests = createLazyRequests(
|
|
306
|
-
mockDelegate,
|
|
307
|
-
mockGetRuntimeManager,
|
|
308
|
-
);
|
|
309
|
-
|
|
310
|
-
// Multiple requests
|
|
311
|
-
await lazyRequests.sendRunScratchpad({ code: "code" });
|
|
312
|
-
await lazyRequests.sendInstantiate({
|
|
313
|
-
objectIds: [uiElementId("obj1")],
|
|
314
|
-
values: [],
|
|
315
|
-
});
|
|
316
|
-
|
|
317
|
-
// Init should only be called once
|
|
318
|
-
expect(mockInit).toHaveBeenCalledTimes(1);
|
|
319
|
-
expect(mockGetRuntimeManager).toHaveBeenCalledTimes(2);
|
|
320
|
-
});
|
|
321
|
-
});
|
|
322
|
-
});
|
|
@@ -1,222 +0,0 @@
|
|
|
1
|
-
/* Copyright 2026 Marimo. All rights reserved. */
|
|
2
|
-
|
|
3
|
-
import { NoKernelConnectedError } from "@/utils/errors";
|
|
4
|
-
import { Logger } from "@/utils/Logger";
|
|
5
|
-
import { Objects } from "@/utils/objects";
|
|
6
|
-
import { memoizeLastValue } from "@/utils/once";
|
|
7
|
-
import { waitForRuntimeRunning } from "../executions";
|
|
8
|
-
import type { RuntimeManager } from "../runtime/runtime";
|
|
9
|
-
import { store } from "../state/jotai";
|
|
10
|
-
import { ConnectionState } from "../session/types";
|
|
11
|
-
import { connectionAtom, waitForConnectionOpen } from "./connection";
|
|
12
|
-
import type { EditRequests, RunRequests } from "./types";
|
|
13
|
-
|
|
14
|
-
type AllRequests = EditRequests & RunRequests;
|
|
15
|
-
|
|
16
|
-
// We have various requests that act differently when called and not connected to a Kernel:
|
|
17
|
-
//
|
|
18
|
-
// - throwError: Throws NoKernelConnectedError, caught by requests-toasting.tsx
|
|
19
|
-
// and shown as a toast with a "Connect" button. Use for operations that
|
|
20
|
-
// shouldn't silently fail but also shouldn't auto-start the kernel.
|
|
21
|
-
//
|
|
22
|
-
// - dropRequest: Silently returns undefined. Only for requests where failure is
|
|
23
|
-
// expected and doesn't matter (e.g., background polling).
|
|
24
|
-
//
|
|
25
|
-
// - startConnection: Initializes the runtime and waits for connection before
|
|
26
|
-
// executing. Use for user-initiated actions that should "just work" and
|
|
27
|
-
// kick off the kernel if needed (e.g., clicking Run).
|
|
28
|
-
//
|
|
29
|
-
// - startConnectionWithoutKernel: Initializes the runtime and waits for an open
|
|
30
|
-
// connection. Use for session-scoped server requests that do not need an
|
|
31
|
-
// instantiated kernel.
|
|
32
|
-
//
|
|
33
|
-
// - waitForConnectionOpen: Waits for an existing connection but won't start one.
|
|
34
|
-
// Use for operations that depend on a running kernel but shouldn't be the
|
|
35
|
-
// trigger to start it (e.g., saving, interrupting).
|
|
36
|
-
//
|
|
37
|
-
// - serverOnly: Calls the HTTP delegate directly without touching the kernel.
|
|
38
|
-
// Use for requests served by the marimo server itself, which resolve without
|
|
39
|
-
// a session (e.g., fetching environment diagnostics).
|
|
40
|
-
|
|
41
|
-
type Action =
|
|
42
|
-
| "throwError"
|
|
43
|
-
| "dropRequest"
|
|
44
|
-
| "startConnection"
|
|
45
|
-
| "startConnectionWithoutKernel"
|
|
46
|
-
| "waitForConnectionOpen"
|
|
47
|
-
| "serverOnly";
|
|
48
|
-
|
|
49
|
-
const ACTIONS: Record<keyof AllRequests, Action> = {
|
|
50
|
-
// These will start a connection if not already connected and then wait until the connection is open
|
|
51
|
-
sendComponentValues: "startConnection",
|
|
52
|
-
sendModelValue: "startConnection",
|
|
53
|
-
sendInstantiate: "startConnectionWithoutKernel",
|
|
54
|
-
sendRunScratchpad: "startConnection",
|
|
55
|
-
saveAppConfig: "startConnection",
|
|
56
|
-
discoverDataSources: "startConnection",
|
|
57
|
-
|
|
58
|
-
// Export operations start a connection
|
|
59
|
-
exportAsHTML: "startConnection",
|
|
60
|
-
exportAsIPYNB: "startConnection",
|
|
61
|
-
exportAsMarkdown: "startConnection",
|
|
62
|
-
exportAsScript: "startConnection",
|
|
63
|
-
exportAsPDF: "startConnection",
|
|
64
|
-
readCode: "startConnection",
|
|
65
|
-
sendCopy: "throwError",
|
|
66
|
-
|
|
67
|
-
// Throw errors for operations that are not supported offline
|
|
68
|
-
sendFormat: "throwError",
|
|
69
|
-
sendRestart: "throwError",
|
|
70
|
-
|
|
71
|
-
// These wait until the connection is open, but don't start a connection
|
|
72
|
-
saveLayout: "waitForConnectionOpen",
|
|
73
|
-
invokeAiTool: "waitForConnectionOpen",
|
|
74
|
-
sendFunctionRequest: "waitForConnectionOpen",
|
|
75
|
-
|
|
76
|
-
// Session-based operations that wait for connection
|
|
77
|
-
sendRename: "waitForConnectionOpen",
|
|
78
|
-
autoExportAsHTML: "waitForConnectionOpen",
|
|
79
|
-
autoExportAsMarkdown: "waitForConnectionOpen",
|
|
80
|
-
autoExportAsIPYNB: "waitForConnectionOpen",
|
|
81
|
-
updateCellOutputs: "waitForConnectionOpen",
|
|
82
|
-
|
|
83
|
-
// Sidebar operations that wait for connection
|
|
84
|
-
listSecretKeys: "throwError",
|
|
85
|
-
writeSecret: "throwError",
|
|
86
|
-
clearCache: "throwError",
|
|
87
|
-
getCacheInfo: "throwError",
|
|
88
|
-
|
|
89
|
-
// Operations that throw errors (sessionless but not supported offline)
|
|
90
|
-
saveUserConfig: "throwError",
|
|
91
|
-
sendShutdown: "throwError",
|
|
92
|
-
getPackageList: "throwError",
|
|
93
|
-
getSandbox: "serverOnly",
|
|
94
|
-
updateManifest: "serverOnly",
|
|
95
|
-
syncSandbox: "serverOnly",
|
|
96
|
-
getDependencyTree: "throwError",
|
|
97
|
-
addPackage: "throwError",
|
|
98
|
-
removePackage: "throwError",
|
|
99
|
-
|
|
100
|
-
// Folder and file operations throw errors
|
|
101
|
-
getFileRoots: "startConnection",
|
|
102
|
-
sendListFiles: "startConnection",
|
|
103
|
-
sendSearchFiles: "startConnection",
|
|
104
|
-
sendCreateFileOrFolder: "throwError",
|
|
105
|
-
sendDeleteFileOrFolder: "throwError",
|
|
106
|
-
sendCopyFileOrFolder: "throwError",
|
|
107
|
-
sendRenameFileOrFolder: "throwError",
|
|
108
|
-
sendUpdateFile: "throwError",
|
|
109
|
-
sendFileDetails: "throwError",
|
|
110
|
-
openFile: "throwError",
|
|
111
|
-
|
|
112
|
-
// Served by the marimo server without a kernel session
|
|
113
|
-
getEnvironmentInfo: "serverOnly",
|
|
114
|
-
getExportAvailability: "serverOnly",
|
|
115
|
-
|
|
116
|
-
// Session-scoped server operations
|
|
117
|
-
installExportRequirements: "startConnectionWithoutKernel",
|
|
118
|
-
|
|
119
|
-
// Home operations throw errors
|
|
120
|
-
getRecentFiles: "startConnection",
|
|
121
|
-
getWorkspaceFiles: "startConnection",
|
|
122
|
-
getRunningNotebooks: "startConnection",
|
|
123
|
-
shutdownSession: "startConnection",
|
|
124
|
-
openTutorial: "startConnection",
|
|
125
|
-
getUsageStats: "waitForConnectionOpen",
|
|
126
|
-
|
|
127
|
-
// These wait for connection
|
|
128
|
-
sendStdin: "waitForConnectionOpen",
|
|
129
|
-
sendInterrupt: "waitForConnectionOpen",
|
|
130
|
-
sendPdb: "waitForConnectionOpen",
|
|
131
|
-
sendSetBreakpoints: "waitForConnectionOpen",
|
|
132
|
-
sendInstallMissingPackages: "waitForConnectionOpen",
|
|
133
|
-
readSnippets: "waitForConnectionOpen",
|
|
134
|
-
previewDatasetColumn: "waitForConnectionOpen",
|
|
135
|
-
previewSQLTable: "waitForConnectionOpen",
|
|
136
|
-
previewSQLTableList: "waitForConnectionOpen",
|
|
137
|
-
previewSQLSchemaList: "waitForConnectionOpen",
|
|
138
|
-
previewDataSourceConnection: "waitForConnectionOpen",
|
|
139
|
-
validateSQL: "waitForConnectionOpen",
|
|
140
|
-
listStorageEntries: "waitForConnectionOpen",
|
|
141
|
-
downloadStorage: "waitForConnectionOpen",
|
|
142
|
-
|
|
143
|
-
// Sync operations that wait for connection
|
|
144
|
-
sendCodeCompletionRequest: "waitForConnectionOpen",
|
|
145
|
-
};
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Create a lazy requests client.
|
|
149
|
-
* On any request, we will initialize the runtime manager (if not already initialized)
|
|
150
|
-
* and handle it based on the action type defined in ACTIONS.
|
|
151
|
-
*/
|
|
152
|
-
export function createLazyRequests(
|
|
153
|
-
delegate: AllRequests,
|
|
154
|
-
getRuntimeManager: () => RuntimeManager,
|
|
155
|
-
): AllRequests {
|
|
156
|
-
// Memoize the init call, just once per runtime manager
|
|
157
|
-
const initOnce = memoizeLastValue(async (runtimeManager: RuntimeManager) => {
|
|
158
|
-
store.set(connectionAtom, { state: ConnectionState.CONNECTING });
|
|
159
|
-
await runtimeManager.init();
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
// oxlint-disable-next-line typescript/no-explicit-any
|
|
163
|
-
function wrapRequest<T extends (...args: any[]) => Promise<any>>(
|
|
164
|
-
request: T,
|
|
165
|
-
key: keyof AllRequests,
|
|
166
|
-
): T {
|
|
167
|
-
const action = ACTIONS[key];
|
|
168
|
-
|
|
169
|
-
const wrapped = (async (...args) => {
|
|
170
|
-
const runtimeManager = getRuntimeManager();
|
|
171
|
-
|
|
172
|
-
if (!runtimeManager.isLazy) {
|
|
173
|
-
return request(...args);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
switch (action) {
|
|
177
|
-
case "serverOnly":
|
|
178
|
-
// Served by the marimo server itself; no kernel required
|
|
179
|
-
return request(...args);
|
|
180
|
-
|
|
181
|
-
case "dropRequest":
|
|
182
|
-
Logger.debug(
|
|
183
|
-
`Dropping request: ${key}, since not connected to a kernel.`,
|
|
184
|
-
);
|
|
185
|
-
// Silently drop the request
|
|
186
|
-
return;
|
|
187
|
-
|
|
188
|
-
case "throwError":
|
|
189
|
-
throw new NoKernelConnectedError();
|
|
190
|
-
|
|
191
|
-
case "waitForConnectionOpen":
|
|
192
|
-
// Wait for connection but don't start it
|
|
193
|
-
await waitForConnectionOpen();
|
|
194
|
-
await waitForRuntimeRunning(store);
|
|
195
|
-
return request(...args);
|
|
196
|
-
|
|
197
|
-
case "startConnectionWithoutKernel":
|
|
198
|
-
case "startConnection":
|
|
199
|
-
// Start connection and wait for it to be open
|
|
200
|
-
await initOnce(runtimeManager);
|
|
201
|
-
await waitForConnectionOpen();
|
|
202
|
-
if (action === "startConnection") {
|
|
203
|
-
await waitForRuntimeRunning(store);
|
|
204
|
-
}
|
|
205
|
-
return request(...args);
|
|
206
|
-
|
|
207
|
-
default:
|
|
208
|
-
// This should never happen if ACTIONS is complete
|
|
209
|
-
throw new Error(`Unknown action for "${key}"`);
|
|
210
|
-
}
|
|
211
|
-
}) as T;
|
|
212
|
-
return wrapped;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
return Objects.mapValues(delegate, (value, key) => {
|
|
216
|
-
return wrapRequest(value, key);
|
|
217
|
-
}) as AllRequests;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
export const visibleForTesting = {
|
|
221
|
-
ACTIONS,
|
|
222
|
-
};
|