runmat 0.2.7
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/README.md +228 -0
- package/dist/fs/default.d.ts +7 -0
- package/dist/fs/default.d.ts.map +1 -0
- package/dist/fs/default.js +21 -0
- package/dist/fs/default.js.map +1 -0
- package/dist/fs/index.d.ts +6 -0
- package/dist/fs/index.d.ts.map +1 -0
- package/dist/fs/index.js +5 -0
- package/dist/fs/index.js.map +1 -0
- package/dist/fs/indexeddb.d.ts +16 -0
- package/dist/fs/indexeddb.d.ts.map +1 -0
- package/dist/fs/indexeddb.js +186 -0
- package/dist/fs/indexeddb.js.map +1 -0
- package/dist/fs/memory.d.ts +41 -0
- package/dist/fs/memory.d.ts.map +1 -0
- package/dist/fs/memory.js +429 -0
- package/dist/fs/memory.js.map +1 -0
- package/dist/fs/path.d.ts +5 -0
- package/dist/fs/path.d.ts.map +1 -0
- package/dist/fs/path.js +56 -0
- package/dist/fs/path.js.map +1 -0
- package/dist/fs/provider-types.d.ts +28 -0
- package/dist/fs/provider-types.d.ts.map +1 -0
- package/dist/fs/provider-types.js +2 -0
- package/dist/fs/provider-types.js.map +1 -0
- package/dist/fs/remote.d.ts +10 -0
- package/dist/fs/remote.d.ts.map +1 -0
- package/dist/fs/remote.js +200 -0
- package/dist/fs/remote.js.map +1 -0
- package/dist/fusion-plan.d.ts +15 -0
- package/dist/fusion-plan.d.ts.map +1 -0
- package/dist/fusion-plan.js +59 -0
- package/dist/fusion-plan.js.map +1 -0
- package/dist/index.d.ts +434 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +619 -0
- package/dist/index.js.map +1 -0
- package/dist/test/node-sync-xhr.d.ts +2 -0
- package/dist/test/node-sync-xhr.d.ts.map +1 -0
- package/dist/test/node-sync-xhr.js +163 -0
- package/dist/test/node-sync-xhr.js.map +1 -0
- package/dist/test/setup.d.ts +2 -0
- package/dist/test/setup.d.ts.map +1 -0
- package/dist/test/setup.js +6 -0
- package/dist/test/setup.js.map +1 -0
- package/dist/webgpu-shims.d.ts +14 -0
- package/dist/webgpu-shims.d.ts.map +1 -0
- package/dist/webgpu-shims.js +85 -0
- package/dist/webgpu-shims.js.map +1 -0
- package/dist/workspace-hover.d.ts +69 -0
- package/dist/workspace-hover.d.ts.map +1 -0
- package/dist/workspace-hover.js +168 -0
- package/dist/workspace-hover.js.map +1 -0
- package/package.json +62 -0
package/README.md
ADDED
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
# RunMat: Blazing Fast Runtime for Math
|
|
2
|
+
|
|
3
|
+
RunMat automatically fuses math operations and intelligently routes between CPU and GPU.
|
|
4
|
+
|
|
5
|
+
Write math in MATLAB syntax, and RunMat runs it blazing fast.
|
|
6
|
+
|
|
7
|
+
Runs on Windows, macOS, Linux, and Web, across NVIDIA, AMD, Apple Silicon, and Intel GPUs.
|
|
8
|
+
|
|
9
|
+
## Initialization options
|
|
10
|
+
|
|
11
|
+
`initRunMat` accepts the following options so hosts can tailor the runtime to their environment:
|
|
12
|
+
|
|
13
|
+
| Option | Type | Description |
|
|
14
|
+
| --- | --- | --- |
|
|
15
|
+
| `snapshot` | `{ bytes \| url \| stream \| fetcher }` | Preload the standard library. Streams avoid copying large buffers. |
|
|
16
|
+
| `fsProvider` | `RunMatFilesystemProvider` | Install a custom filesystem (remote, IndexedDB, etc.). Defaults to `createDefaultFsProvider()`. |
|
|
17
|
+
| `enableGpu` | `boolean` | Request GPU acceleration (auto-disabled if `navigator.gpu` is missing). |
|
|
18
|
+
| `enableJit` | `boolean` | Toggle the JIT tier. |
|
|
19
|
+
| `telemetryConsent` | `boolean` | Allow or block analytics events (profiling still returns locally). Defaults to `true`. |
|
|
20
|
+
| `telemetryId` | `string` | Existing analytics client ID to reuse. |
|
|
21
|
+
| `wgpuPowerPreference` | `"auto" \| "high-performance" \| "low-power"` | Hint for adapter selection. |
|
|
22
|
+
| `wgpuForceFallbackAdapter` | `boolean` | Force the WebGPU fallback adapter when the primary device fails. |
|
|
23
|
+
| `plotCanvas` | `HTMLCanvasElement` | Register the default plotting surface during initialization. |
|
|
24
|
+
| `scatterTargetPoints` / `surfaceVertexBudget` | `number` | Override GPU LOD heuristics for scatter/surface plots. |
|
|
25
|
+
| `emitFusionPlan` | `boolean` | Include Accelerate fusion DAG + shader metadata in every `ExecuteResult`. Defaults to `false`; toggle later via `session.setFusionPlanEnabled()`. |
|
|
26
|
+
| `language.compat` | `"matlab" \| "strict"` | Matches `[language] compat` in `.runmat`. See docs/LANGUAGE.md for more information. |
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
## Developing
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
cd bindings/ts
|
|
33
|
+
npm install
|
|
34
|
+
npm run build # runs wasm-pack + tsc
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
The build step expects `wasm-pack` to be installed locally and will output the generated glue code to `pkg/` and the typed wrapper bundle to `dist/`.
|
|
38
|
+
|
|
39
|
+
## Publishing
|
|
40
|
+
|
|
41
|
+
The `prepublishOnly` hook re-runs the full build so CI can simply execute `npm publish` once credentials are configured. The resulting tarball includes:
|
|
42
|
+
|
|
43
|
+
- `pkg/`: raw `wasm-bindgen` output for bundlers
|
|
44
|
+
- `dist/`: TypeScript-authored convenience wrapper + definitions
|
|
45
|
+
- `README.md`: usage notes
|
|
46
|
+
|
|
47
|
+
## Filesystem providers
|
|
48
|
+
|
|
49
|
+
Browser and hybrid hosts must forward filesystem requests to the runtime through a `fsProvider` object passed to `initRunMat`. The package now ships helpers for the two most common scenarios:
|
|
50
|
+
|
|
51
|
+
- `createInMemoryFsProvider(options?)` – zero-dependency, synchronous filesystem stored entirely in JS memory. Supports all RunMat file ops and is ideal for tests or ephemeral browser sessions.
|
|
52
|
+
- `createIndexedDbFsHandle(options?)` – wraps the in-memory provider and persists its state to IndexedDB. The handle exposes `.provider` (pass to `initRunMat`), `.flush()` to await persistence, and `.close()` to release the database. A convenience `createIndexedDbFsProvider` is also exported if you only need the provider.
|
|
53
|
+
- `createDefaultFsProvider()` – automatically tries IndexedDB → in-memory. `initRunMat` calls this for you when `fsProvider` is omitted.
|
|
54
|
+
- `createRemoteFsProvider({ baseUrl, authToken?, headers?, chunkBytes?, timeoutMs? })` – proxies all file ops over HTTP(S) using chunked reads/writes. Bearer tokens and custom headers are forwarded on every request so S3/proxy-style backends can enforce auth without extra glue, and large transfers stream in configurable chunks (`chunkBytes`, default 8 MiB).
|
|
55
|
+
|
|
56
|
+
Both providers implement the `RunMatFilesystemProvider` contract:
|
|
57
|
+
|
|
58
|
+
- `readFile(path) => Uint8Array | ArrayBuffer`
|
|
59
|
+
- `writeFile(path, data) => void`
|
|
60
|
+
- `removeFile(path) => void`
|
|
61
|
+
- `metadata(path) => { fileType, len, modified?, readonly? }`
|
|
62
|
+
- `readDir(path) => Array<{ path, fileName, fileType? }>`
|
|
63
|
+
|
|
64
|
+
Optional helpers such as `createDir`, `rename`, `setReadonly`, etc. unlock the full MATLAB IO surface.
|
|
65
|
+
|
|
66
|
+
See `docs/FILESYSTEM.md` in the repo for the detailed contract and backend-specific guidance.
|
|
67
|
+
|
|
68
|
+
Notes:
|
|
69
|
+
- IndexedDB quotas vary by browser (commonly 50–200 MB). For long-lived sessions consider a `dbName` per workspace and call `handle.flush()`/`handle.close()` before tab teardown; falling back to the in-memory provider avoids quota prompts but data is ephemeral.
|
|
70
|
+
- Remote providers surface server-side readonly bits via `metadata().readonly` and will propagate HTTP errors (including 401s) directly so hosts can prompt for credentials or retry. Tune `chunkBytes` for high-throughput links; the helper will stream multi-GB transfers chunk-by-chunk without buffering the entire payload.
|
|
71
|
+
|
|
72
|
+
## Snapshot loading
|
|
73
|
+
|
|
74
|
+
When calling `initRunMat`, pass a `snapshot` object to control how the initial workspace is hydrated:
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
await initRunMat({
|
|
78
|
+
snapshot: {
|
|
79
|
+
url: "https://cdn.runmat.org/snapshots/core.bin"
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
- `snapshot.bytes`: direct `Uint8Array`/`ArrayBuffer`.
|
|
85
|
+
- `snapshot.url`: the helper will stream the response via `fetch` (fewer copies than `arrayBuffer()`).
|
|
86
|
+
- `snapshot.stream`: pass a `ReadableStream` (for example `response.body`) if you already fetched the asset in JS and want wasm to consume it directly.
|
|
87
|
+
- `snapshot.fetcher`: custom async hook (`({ url }) => Promise<ArrayBuffer | Uint8Array | Response | ReadableStream>`) for bespoke CDNs or authenticated flows. Streams are forwarded without buffering.
|
|
88
|
+
|
|
89
|
+
If no snapshot is provided, the runtime boots with the minimal built-in seed.
|
|
90
|
+
|
|
91
|
+
## GPU detection
|
|
92
|
+
|
|
93
|
+
`enableGpu` defaults to `true`, but the wrapper now auto-detects whether `navigator.gpu` exists in the host. If a caller requests GPU but the browser lacks WebGPU support, the wrapper logs a warning and falls back to CPU execution automatically.
|
|
94
|
+
|
|
95
|
+
Once a session is running you can inspect the live GPU state via:
|
|
96
|
+
|
|
97
|
+
```ts
|
|
98
|
+
const session = await initRunMat();
|
|
99
|
+
const gpu = session.gpuStatus();
|
|
100
|
+
if (!gpu.active && gpu.error) {
|
|
101
|
+
console.warn("GPU init failed:", gpu.error);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (gpu.adapter) {
|
|
105
|
+
console.log("GPU backend:", gpu.adapter.name, gpu.adapter.backend, gpu.adapter.precision);
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Telemetry consent
|
|
110
|
+
|
|
111
|
+
Browser hosts must decide whether anonymous telemetry is allowed before booting the runtime. Pass `telemetryConsent: false` to `initRunMat` to opt out:
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
const session = await initRunMat({
|
|
115
|
+
telemetryConsent: false,
|
|
116
|
+
snapshot: { url: "/snapshots/core.bin" }
|
|
117
|
+
});
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
When consent is disabled the runtime simply refrains from emitting analytics events (profiling data and fusion statistics are still returned locally so performance panes work). The CLI mirrors this behavior automatically by forwarding the user’s `telemetry.enabled` setting into the session, and wasm hosts can query `session.telemetryConsent()` to keep their UI in sync.
|
|
121
|
+
|
|
122
|
+
If you already have a telemetry/analytics identifier (e.g., the ID that the surrounding UI uses), pass it via `telemetryId`. The runtime stores it internally (accessible via `session.telemetryClientId()`) so any future telemetry sinks can reuse the existing CID instead of minting a second identifier.
|
|
123
|
+
|
|
124
|
+
## Monitoring memory usage
|
|
125
|
+
|
|
126
|
+
Call `await session.memoryUsage()` to inspect the current WebAssembly heap. The method returns `{ bytes, pages }`, where `pages` are 64 KiB units. Hosts can poll this to detect runaway `memory.grow` usage and decide when to reset or dispose of sessions.
|
|
127
|
+
|
|
128
|
+
## Execution streaming & interaction
|
|
129
|
+
|
|
130
|
+
- `subscribeStdout(listener)` / `unsubscribeStdout(id)` stream stdout/stderr events as they are emitted so hosts can drive an xterm pane without waiting for `execute()` to resolve. Every `ExecuteResult` also includes the buffered `stdout` array for easy logging or replay.
|
|
131
|
+
- `ExecuteResult.warnings` exposes structured `{ identifier, message }` entries pulled from MATLAB's warning store, `stdinEvents` captures every prompt/response emitted during the run for transcript panes, and `stdinRequested` is populated when the interpreter suspends while waiting for input.
|
|
132
|
+
- Call `session.cancelExecution()` to cooperatively interrupt a long-running script (e.g., when users press the stop button). The runtime raises `MATLAB:runmat:ExecutionCancelled`, matching desktop builds.
|
|
133
|
+
- `session.setInputHandler(handler)` registers a synchronous callback for MATLAB's `input`/`pause` prompts. Handlers receive `{ kind: "line" | "keyPress", prompt, echo }` and can return a string/number/boolean, `{ kind: "keyPress" }`, or `{ error }` to reject the prompt. Returning `null`, `undefined`, `{ pending: true }`, or a Promise signals that the handler will respond asynchronously.
|
|
134
|
+
- When a handler defers, `execute()` resolves with `stdinRequested` containing `{ id, request, waitingMs }`. Call `session.resumeInput(id, value)` once the UI collects the user's response (value follows the same shape as the input handler). `waitingMs` starts at zero and grows until the prompt is satisfied so UIs can show “still waiting…” nudges without forcing a timeout. Use `session.pendingStdinRequests()` to list outstanding prompts (useful when rehydrating a UI after refresh) — each entry carries the same `waitingMs` counter.
|
|
135
|
+
|
|
136
|
+
## Workspace metadata & variable inspection
|
|
137
|
+
|
|
138
|
+
Every `ExecuteResult.workspace` now carries `{ full, version, values[] }`, where each entry exposes:
|
|
139
|
+
|
|
140
|
+
- `name`, `className`, `dtype`, `shape`, `sizeBytes` (when known) so table views can show MATLAB-style summaries.
|
|
141
|
+
- `residency`: `"cpu"`, `"gpu"`, or `"unknown"` so hosts can flag gpuArray residency without parsing class names.
|
|
142
|
+
- `preview`: small inline numeric previews (up to 16 elements) for scalars/vectors.
|
|
143
|
+
- `previewToken`: UUID that identifies this snapshot of the variable for lazy materialization.
|
|
144
|
+
|
|
145
|
+
Hosts can ask the runtime for richer previews without disturbing the MATLAB session via `await session.materializeVariable(selector, options?)`. The selector accepts either a preview token string or `{ previewToken, name }` (name is only used when no token is available). Options currently support `{ limit }` to cap numeric previews (default 4 096 elements, matching the REPL hover limit).
|
|
146
|
+
|
|
147
|
+
The Promise resolves with `{ name, className, dtype?, shape, isGpu, residency, sizeBytes?, preview?, valueText, valueJson }`. `valueJson` reuses the same summary format as `ExecuteResult.valueJson`, complete with truncation flags, so variable panes can display matrices, structs, or cell arrays without issuing textual commands. `valueText` mirrors MATLAB’s default display for quick tooltips.
|
|
148
|
+
|
|
149
|
+
Preview tokens are regenerated on every execution so stale handles naturally expire; hosts can fall back to `{ name: "A" }` selectors if they need to inspect a value that predates the latest run.
|
|
150
|
+
|
|
151
|
+
For Monaco-based editors, the package now exposes `createWorkspaceHoverProvider({ monaco, session, language })`, which registers a hover provider that shows the latest class/shape/residency data inline. Feed it every `ExecuteResult.workspace` via `hover.updateWorkspace(result.workspace)` and it will lazily call `session.materializeVariable(...)` (using the per-entry `previewToken`) whenever the inline preview is truncated. Dispose the helper whenever you tear down the Monaco instance to unregister the hover provider and clear cached previews.
|
|
152
|
+
|
|
153
|
+
## Fusion plan snapshots
|
|
154
|
+
|
|
155
|
+
Accelerate already emits detailed fusion graphs (nodes, edges, shader metadata, decision logs) and the wasm bindings expose them via `ExecuteResult.fusionPlan`. Because these payloads can be sizable, they are opt-in — pass `emitFusionPlan: true` to `initRunMat` or call `session.setFusionPlanEnabled(true)` when showing the “Fusion Plan” pane. Toggle the flag off again when the UI hides that inspector to keep executions lean.
|
|
156
|
+
|
|
157
|
+
Each snapshot mirrors the native CLI payload `{ nodes, edges, shaders, decisions }`, making it trivial to feed graph visualizers or shader viewers without scraping textual logs.
|
|
158
|
+
|
|
159
|
+
To simplify UI plumbing, use `createFusionPlanAdapter({ session, onPlanChange })`. It keeps track of whether emission is enabled, forwards `session.setFusionPlanEnabled(...)` for you, and exposes `handleExecutionResult(result)` plus a `subscribe(listener)` hook so fusion panes can update whenever `ExecuteResult.fusionPlan` changes. Call `adapter.setEnabled(true)` when the pane is visible, `adapter.setEnabled(false)` when it hides, and read the latest snapshot via `adapter.plan`.
|
|
160
|
+
|
|
161
|
+
## Plotting surfaces
|
|
162
|
+
|
|
163
|
+
RunMat plotting now renders directly into a WebGPU-backed `<canvas>` using the same renderer as the native desktop build. Provide a canvas during initialization:
|
|
164
|
+
|
|
165
|
+
```ts
|
|
166
|
+
const canvas = document.getElementById("runmat-plot") as HTMLCanvasElement;
|
|
167
|
+
await initRunMat({ plotCanvas: canvas });
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
or attach one later via the exported helpers:
|
|
171
|
+
|
|
172
|
+
```ts
|
|
173
|
+
import { attachPlotCanvas, deregisterPlotCanvas, plotRendererReady } from "@runmat/wasm";
|
|
174
|
+
|
|
175
|
+
await attachPlotCanvas(canvas);
|
|
176
|
+
if (!await plotRendererReady()) {
|
|
177
|
+
console.warn("Plotting not initialized yet.");
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Later, when the canvas is unmounted:
|
|
181
|
+
await deregisterPlotCanvas();
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Once the canvas is registered, calling `plot`, `scatter`, etc. from the RunMat REPL renders directly into that surface without any additional JS shims.
|
|
185
|
+
|
|
186
|
+
## Lifecycle
|
|
187
|
+
|
|
188
|
+
Each `RunMatSessionHandle` now exposes `session.dispose()`. Call it when tearing down the editor/REPL view so the runtime can cancel pending executions, release stdin handlers, and drop any registered plot canvases. The wrapper marks the instance as disposed and throws helpful errors if a host accidentally calls `execute()` afterwards. `dispose()` is idempotent, so repeated calls are safe.
|
|
189
|
+
|
|
190
|
+
### Plotting performance knobs
|
|
191
|
+
|
|
192
|
+
Hosts can tune the GPU level-of-detail heuristics without touching environment variables. Pass either (or both) of the following when calling `initRunMat`:
|
|
193
|
+
|
|
194
|
+
- `scatterTargetPoints`: preferred number of scatter/scatter3 points to retain per dispatch before compute-side decimation kicks in (default `250_000`).
|
|
195
|
+
- `surfaceVertexBudget`: maximum number of surface vertices to pack before LOD sampling starts (default `400_000`).
|
|
196
|
+
|
|
197
|
+
These map directly to the runtime setters (`set_scatter_target_points`, `set_surface_vertex_budget`) so native CLI builds and the wasm bindings stay in sync.
|
|
198
|
+
|
|
199
|
+
### Multi-figure canvases & events
|
|
200
|
+
|
|
201
|
+
- `registerFigureCanvas(handle, canvas)` wires a specific `<canvas>` to a MATLAB figure handle so multiple figures can render concurrently (e.g., tabs or split panes).
|
|
202
|
+
- `deregisterFigureCanvas(handle)` detaches the renderer for a given handle when a tab is hidden or destroyed, freeing GPU resources until the UI reattaches.
|
|
203
|
+
- `renderCurrentFigureScene(handle)` forces the renderer to redraw the most recent scene for that figure handle (handy after host-driven resizes or when reactivating a tab that stayed attached to an OffscreenCanvas).
|
|
204
|
+
- `onFigureEvent(listener)` registers a callback that now receives `FigureEvent { handle, kind, figure?: { layout, metadata, plots[] } }`. Metadata contains axis/grid flags, legend entries (including RGBA + plot kind), background/theme info, and optional labels. Plot descriptors enumerate every series (`kind`, `label`, `axesIndex`, `colorRgba`, `visible`). Pass `null` to unsubscribe.
|
|
205
|
+
|
|
206
|
+
The default `registerPlotCanvas` continues to serve the legacy single-canvas flow; hosts can mix both APIs as needed.
|
|
207
|
+
|
|
208
|
+
### Figure orchestration helpers
|
|
209
|
+
|
|
210
|
+
The wasm bindings now expose the same figure/axes controls that the MATLAB runtime uses so hosts can drive multi-tab canvases without issuing textual commands:
|
|
211
|
+
|
|
212
|
+
- `figure(handle?)` – selects an existing figure handle (creating it if `handle` is omitted) and returns the active handle.
|
|
213
|
+
- `newFigureHandle()` / `currentFigureHandle()` – explicit helpers for creating or querying handles when wiring UI tabs.
|
|
214
|
+
- `setHoldMode(mode)` / `hold(mode?)` / `holdOn()` / `holdOff()` – toggle MATLAB's `hold` state from JS using `"on" | "off" | "toggle"` (boolean flags also work).
|
|
215
|
+
- `configureSubplot(rows, cols, index)` / `subplot(rows, cols, index)` – mirror MATLAB's subplot grid selection so canvas layouts stay in sync with the runtime registry.
|
|
216
|
+
- `clearFigure(handle?)` / `closeFigure(handle?)` – mirror `clf`/`close` semantics. Omit the handle (or pass `undefined`) to target the current figure.
|
|
217
|
+
- `currentAxesInfo()` – returns `{ handle, axesRows, axesCols, activeIndex }` so hosts can surface the active subplot without scraping text output.
|
|
218
|
+
- `renderFigureImage({ handle?, width?, height? })` – renders the active (or specified) figure into an offscreen texture and returns a `Uint8Array` containing PNG bytes. This is ideal for gallery thumbnails, history panes, or exporting snapshots without a visible canvas. Width/height default to the renderer's internal size when omitted.
|
|
219
|
+
|
|
220
|
+
Each helper forwards directly to the new wasm exports, so the zero-copy renderer stays in lock-step with MATLAB semantics even when figure switches originate from the host UI.
|
|
221
|
+
|
|
222
|
+
When a lifecycle call fails (bad handle, invalid subplot index, etc.) the Promise rejects with a structured error object `{ code, message, ... }`. The wrapper converts that into a real `Error` (with `.code`, `.handle`, `.rows`, `.cols`, `.index` where applicable) so host UIs can surface meaningful messages without parsing MATLAB text.
|
|
223
|
+
|
|
224
|
+
If the shared WebGPU device is unavailable (adapter blocked, user disables GPU, etc.), `renderFigureImage` rejects with `code: "RenderFailure"` and a `.details` string describing the cause. Hosts should surface that warning and fall back to a placeholder thumbnail rather than attempting to draw the PNG bytes locally.
|
|
225
|
+
|
|
226
|
+
### Language compatibility mode
|
|
227
|
+
|
|
228
|
+
At runtime you can flip language compatibility mode without reinitializing via `session.setLanguageCompat("strict")` or `"matlab"`.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { RunMatFilesystemProvider } from "./provider-types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Picks the best filesystem backend available in the current runtime.
|
|
4
|
+
* Preference order: IndexedDB (browser) → in-memory fallback.
|
|
5
|
+
*/
|
|
6
|
+
export declare function createDefaultFsProvider(): Promise<RunMatFilesystemProvider>;
|
|
7
|
+
//# sourceMappingURL=default.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"default.d.ts","sourceRoot":"","sources":["../../src/fs/default.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAIpE;;;GAGG;AACH,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,wBAAwB,CAAC,CASjF"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { createInMemoryFsProvider } from "./memory.js";
|
|
2
|
+
import { createIndexedDbFsProvider } from "./indexeddb.js";
|
|
3
|
+
/**
|
|
4
|
+
* Picks the best filesystem backend available in the current runtime.
|
|
5
|
+
* Preference order: IndexedDB (browser) → in-memory fallback.
|
|
6
|
+
*/
|
|
7
|
+
export async function createDefaultFsProvider() {
|
|
8
|
+
if (supportsIndexedDb()) {
|
|
9
|
+
try {
|
|
10
|
+
return await createIndexedDbFsProvider();
|
|
11
|
+
}
|
|
12
|
+
catch (error) {
|
|
13
|
+
console.warn("[runmat] Failed to init IndexedDB provider, falling back to in-memory.", error);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return createInMemoryFsProvider();
|
|
17
|
+
}
|
|
18
|
+
function supportsIndexedDb() {
|
|
19
|
+
return typeof indexedDB !== "undefined" && typeof IDBDatabase !== "undefined";
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=default.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"default.js","sourceRoot":"","sources":["../../src/fs/default.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAE3D;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB;IAC3C,IAAI,iBAAiB,EAAE,EAAE,CAAC;QACxB,IAAI,CAAC;YACH,OAAO,MAAM,yBAAyB,EAAE,CAAC;QAC3C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,wEAAwE,EAAE,KAAK,CAAC,CAAC;QAChG,CAAC;IACH,CAAC;IACD,OAAO,wBAAwB,EAAE,CAAC;AACpC,CAAC;AAED,SAAS,iBAAiB;IACxB,OAAO,OAAO,SAAS,KAAK,WAAW,IAAI,OAAO,WAAW,KAAK,WAAW,CAAC;AAChF,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { createInMemoryFsProvider, MemoryVolume, type InMemoryFsProviderOptions, type VolumeSnapshotEntry } from "./memory.js";
|
|
2
|
+
export { createIndexedDbFsHandle, createIndexedDbFsProvider, type IndexedDbFsHandle, type IndexedDbProviderOptions } from "./indexeddb.js";
|
|
3
|
+
export { createDefaultFsProvider } from "./default.js";
|
|
4
|
+
export { createRemoteFsProvider, type RemoteProviderOptions } from "./remote.js";
|
|
5
|
+
export type { RunMatFsFileType, RunMatFilesystemDirEntry, RunMatFilesystemMetadata, RunMatFilesystemProvider } from "./provider-types.js";
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/fs/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EACxB,YAAY,EACZ,KAAK,yBAAyB,EAC9B,KAAK,mBAAmB,EACzB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,uBAAuB,EACvB,yBAAyB,EACzB,KAAK,iBAAiB,EACtB,KAAK,wBAAwB,EAC9B,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,EAAE,sBAAsB,EAAE,KAAK,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEjF,YAAY,EACV,gBAAgB,EAChB,wBAAwB,EACxB,wBAAwB,EACxB,wBAAwB,EACzB,MAAM,qBAAqB,CAAC"}
|
package/dist/fs/index.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { createInMemoryFsProvider, MemoryVolume } from "./memory.js";
|
|
2
|
+
export { createIndexedDbFsHandle, createIndexedDbFsProvider } from "./indexeddb.js";
|
|
3
|
+
export { createDefaultFsProvider } from "./default.js";
|
|
4
|
+
export { createRemoteFsProvider } from "./remote.js";
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/fs/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,wBAAwB,EACxB,YAAY,EAGb,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,uBAAuB,EACvB,yBAAyB,EAG1B,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,EAAE,sBAAsB,EAA8B,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type InMemoryFsProviderOptions } from "./memory.js";
|
|
2
|
+
import type { RunMatFilesystemProvider } from "./provider-types.js";
|
|
3
|
+
export interface IndexedDbProviderOptions extends InMemoryFsProviderOptions {
|
|
4
|
+
dbName?: string;
|
|
5
|
+
storeName?: string;
|
|
6
|
+
version?: number;
|
|
7
|
+
flushDebounceMs?: number;
|
|
8
|
+
}
|
|
9
|
+
export interface IndexedDbFsHandle {
|
|
10
|
+
provider: RunMatFilesystemProvider;
|
|
11
|
+
flush(): Promise<void>;
|
|
12
|
+
close(): void;
|
|
13
|
+
}
|
|
14
|
+
export declare function createIndexedDbFsHandle(options?: IndexedDbProviderOptions): Promise<IndexedDbFsHandle>;
|
|
15
|
+
export declare function createIndexedDbFsProvider(options?: IndexedDbProviderOptions): Promise<RunMatFilesystemProvider>;
|
|
16
|
+
//# sourceMappingURL=indexeddb.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"indexeddb.d.ts","sourceRoot":"","sources":["../../src/fs/indexeddb.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,yBAAyB,EAA4B,MAAM,aAAa,CAAC;AACrG,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAEpE,MAAM,WAAW,wBAAyB,SAAQ,yBAAyB;IACzE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,wBAAwB,CAAC;IACnC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,KAAK,IAAI,IAAI,CAAC;CACf;AAKD,wBAAsB,uBAAuB,CAC3C,OAAO,GAAE,wBAA6B,GACrC,OAAO,CAAC,iBAAiB,CAAC,CAU5B;AAED,wBAAsB,yBAAyB,CAC7C,OAAO,CAAC,EAAE,wBAAwB,GACjC,OAAO,CAAC,wBAAwB,CAAC,CAGnC"}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { MemoryVolume } from "./memory.js";
|
|
2
|
+
const DEFAULT_DB_NAME = "runmat-fs";
|
|
3
|
+
const DEFAULT_STORE_NAME = "entries";
|
|
4
|
+
export async function createIndexedDbFsHandle(options = {}) {
|
|
5
|
+
const idb = getIndexedDb();
|
|
6
|
+
const dbName = options.dbName ?? DEFAULT_DB_NAME;
|
|
7
|
+
const storeName = options.storeName ?? DEFAULT_STORE_NAME;
|
|
8
|
+
const version = options.version ?? 1;
|
|
9
|
+
const db = await openDatabase(idb, dbName, storeName, version);
|
|
10
|
+
const snapshot = await readAllEntries(db, storeName);
|
|
11
|
+
const volume = new MemoryVolume({ now: options.now });
|
|
12
|
+
volume.load(snapshot);
|
|
13
|
+
return new IndexedDbHandle(db, storeName, volume, options.flushDebounceMs ?? 25);
|
|
14
|
+
}
|
|
15
|
+
export async function createIndexedDbFsProvider(options) {
|
|
16
|
+
const handle = await createIndexedDbFsHandle(options);
|
|
17
|
+
return handle.provider;
|
|
18
|
+
}
|
|
19
|
+
class IndexedDbHandle {
|
|
20
|
+
db;
|
|
21
|
+
storeName;
|
|
22
|
+
volume;
|
|
23
|
+
flushDebounceMs;
|
|
24
|
+
provider;
|
|
25
|
+
pendingFlush = null;
|
|
26
|
+
flushTimer = null;
|
|
27
|
+
closed = false;
|
|
28
|
+
dirty = false;
|
|
29
|
+
constructor(db, storeName, volume, flushDebounceMs) {
|
|
30
|
+
this.db = db;
|
|
31
|
+
this.storeName = storeName;
|
|
32
|
+
this.volume = volume;
|
|
33
|
+
this.flushDebounceMs = flushDebounceMs;
|
|
34
|
+
this.provider = volume.createProvider(() => this.onMutate());
|
|
35
|
+
}
|
|
36
|
+
async flush() {
|
|
37
|
+
if (this.closed) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (this.flushTimer) {
|
|
41
|
+
clearTimeout(this.flushTimer);
|
|
42
|
+
this.flushTimer = null;
|
|
43
|
+
}
|
|
44
|
+
this.queueFlush();
|
|
45
|
+
if (this.pendingFlush) {
|
|
46
|
+
await this.pendingFlush;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
close() {
|
|
50
|
+
if (this.closed) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (this.flushTimer) {
|
|
54
|
+
clearTimeout(this.flushTimer);
|
|
55
|
+
this.flushTimer = null;
|
|
56
|
+
}
|
|
57
|
+
this.closed = true;
|
|
58
|
+
this.db.close();
|
|
59
|
+
}
|
|
60
|
+
scheduleFlush() {
|
|
61
|
+
if (this.closed) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (this.flushDebounceMs === 0) {
|
|
65
|
+
this.queueFlush();
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (this.flushTimer) {
|
|
69
|
+
clearTimeout(this.flushTimer);
|
|
70
|
+
}
|
|
71
|
+
this.flushTimer = setTimeout(() => {
|
|
72
|
+
this.flushTimer = null;
|
|
73
|
+
this.queueFlush();
|
|
74
|
+
}, this.flushDebounceMs);
|
|
75
|
+
}
|
|
76
|
+
queueFlush() {
|
|
77
|
+
if (this.closed || this.pendingFlush) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
this.pendingFlush = this.persistAll().finally(() => {
|
|
81
|
+
this.pendingFlush = null;
|
|
82
|
+
if (this.dirty) {
|
|
83
|
+
this.queueFlush();
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
onMutate() {
|
|
88
|
+
this.dirty = true;
|
|
89
|
+
this.scheduleFlush();
|
|
90
|
+
}
|
|
91
|
+
async persistAll() {
|
|
92
|
+
while (!this.closed) {
|
|
93
|
+
this.dirty = false;
|
|
94
|
+
const snapshot = this.volume.serialize();
|
|
95
|
+
await writeAllEntries(this.db, this.storeName, snapshot);
|
|
96
|
+
if (!this.dirty) {
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
function getIndexedDb() {
|
|
103
|
+
if (typeof indexedDB === "undefined") {
|
|
104
|
+
throw new Error("indexedDB API is unavailable in this environment");
|
|
105
|
+
}
|
|
106
|
+
return indexedDB;
|
|
107
|
+
}
|
|
108
|
+
function openDatabase(idb, dbName, storeName, version) {
|
|
109
|
+
return new Promise((resolve, reject) => {
|
|
110
|
+
const request = idb.open(dbName, version);
|
|
111
|
+
request.onupgradeneeded = () => {
|
|
112
|
+
const db = request.result;
|
|
113
|
+
if (!db.objectStoreNames.contains(storeName)) {
|
|
114
|
+
db.createObjectStore(storeName, { keyPath: "path" });
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
request.onsuccess = () => resolve(request.result);
|
|
118
|
+
request.onerror = () => reject(request.error ?? new Error("Failed to open IndexedDB database"));
|
|
119
|
+
request.onblocked = () => reject(new Error("IndexedDB upgrade was blocked by another connection"));
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
function readAllEntries(db, storeName) {
|
|
123
|
+
return new Promise((resolve, reject) => {
|
|
124
|
+
const tx = db.transaction(storeName, "readonly");
|
|
125
|
+
const store = tx.objectStore(storeName);
|
|
126
|
+
const getAll = store.getAll?.bind(store);
|
|
127
|
+
if (typeof getAll === "function") {
|
|
128
|
+
const request = getAll();
|
|
129
|
+
request.onsuccess = () => {
|
|
130
|
+
const raw = (request.result ?? []);
|
|
131
|
+
resolve(raw.map(deserializeEntry));
|
|
132
|
+
};
|
|
133
|
+
request.onerror = () => reject(request.error ?? new Error("Failed to read IndexedDB entries"));
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
const entries = [];
|
|
137
|
+
const cursor = store.openCursor();
|
|
138
|
+
cursor.onsuccess = () => {
|
|
139
|
+
const result = cursor.result;
|
|
140
|
+
if (!result) {
|
|
141
|
+
resolve(entries.map(deserializeEntry));
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
entries.push(result.value);
|
|
145
|
+
result.continue();
|
|
146
|
+
};
|
|
147
|
+
cursor.onerror = () => reject(cursor.error ?? new Error("Failed to iterate IndexedDB cursor"));
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
function writeAllEntries(db, storeName, entries) {
|
|
151
|
+
return new Promise((resolve, reject) => {
|
|
152
|
+
const tx = db.transaction(storeName, "readwrite");
|
|
153
|
+
const store = tx.objectStore(storeName);
|
|
154
|
+
const clearReq = store.clear();
|
|
155
|
+
clearReq.onerror = () => reject(clearReq.error ?? new Error("Failed to clear IndexedDB store before write"));
|
|
156
|
+
clearReq.onsuccess = () => {
|
|
157
|
+
for (const entry of entries) {
|
|
158
|
+
const record = {
|
|
159
|
+
path: entry.path,
|
|
160
|
+
kind: entry.kind,
|
|
161
|
+
readonly: entry.readonly,
|
|
162
|
+
modified: entry.modified,
|
|
163
|
+
children: entry.children ?? []
|
|
164
|
+
};
|
|
165
|
+
if (entry.kind === "file" && entry.data) {
|
|
166
|
+
record.data = entry.data.slice().buffer;
|
|
167
|
+
}
|
|
168
|
+
store.put(record);
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
tx.oncomplete = () => resolve();
|
|
172
|
+
tx.onerror = () => reject(tx.error ?? new Error("Failed to persist IndexedDB entries"));
|
|
173
|
+
tx.onabort = () => reject(tx.error ?? new Error("IndexedDB write aborted"));
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
function deserializeEntry(entry) {
|
|
177
|
+
return {
|
|
178
|
+
path: entry.path,
|
|
179
|
+
kind: entry.kind,
|
|
180
|
+
readonly: entry.readonly,
|
|
181
|
+
modified: entry.modified,
|
|
182
|
+
children: entry.children,
|
|
183
|
+
data: entry.data ? new Uint8Array(entry.data.slice(0)) : undefined
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=indexeddb.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"indexeddb.js","sourceRoot":"","sources":["../../src/fs/indexeddb.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { RunMatFilesystemDirEntry, RunMatFilesystemMetadata, RunMatFilesystemProvider } from "./provider-types.js";
|
|
2
|
+
export interface InMemoryFsProviderOptions {
|
|
3
|
+
initialFiles?: Record<string, Uint8Array | ArrayBuffer | ArrayBufferView | string>;
|
|
4
|
+
now?: () => number;
|
|
5
|
+
}
|
|
6
|
+
export interface VolumeSnapshotEntry {
|
|
7
|
+
path: string;
|
|
8
|
+
kind: "file" | "dir";
|
|
9
|
+
data?: Uint8Array;
|
|
10
|
+
readonly: boolean;
|
|
11
|
+
modified: number;
|
|
12
|
+
children?: string[];
|
|
13
|
+
}
|
|
14
|
+
export declare class MemoryVolume {
|
|
15
|
+
private readonly opts;
|
|
16
|
+
private readonly entries;
|
|
17
|
+
private readonly now;
|
|
18
|
+
private readonly encoder;
|
|
19
|
+
constructor(opts?: InMemoryFsProviderOptions);
|
|
20
|
+
createProvider(onMutate?: () => void): RunMatFilesystemProvider;
|
|
21
|
+
serialize(): VolumeSnapshotEntry[];
|
|
22
|
+
load(entries: VolumeSnapshotEntry[]): void;
|
|
23
|
+
readFile(path: string): Uint8Array;
|
|
24
|
+
writeFile(path: string, data: Uint8Array, readonly?: boolean, modified?: number): void;
|
|
25
|
+
removeFile(path: string): void;
|
|
26
|
+
metadata(path: string): RunMatFilesystemMetadata;
|
|
27
|
+
readDir(path: string): RunMatFilesystemDirEntry[];
|
|
28
|
+
canonicalize(path: string): string;
|
|
29
|
+
createDir(path: string, failOnExists?: boolean, readonly?: boolean, modified?: number): boolean;
|
|
30
|
+
createDirAll(path: string): boolean;
|
|
31
|
+
removeDir(path: string): void;
|
|
32
|
+
removeDirAll(path: string): void;
|
|
33
|
+
rename(from: string, to: string): void;
|
|
34
|
+
setReadonly(path: string, readonly: boolean): void;
|
|
35
|
+
private coerceBuffer;
|
|
36
|
+
private getFile;
|
|
37
|
+
private getDir;
|
|
38
|
+
private makeDirEntry;
|
|
39
|
+
}
|
|
40
|
+
export declare function createInMemoryFsProvider(options?: InMemoryFsProviderOptions): RunMatFilesystemProvider;
|
|
41
|
+
//# sourceMappingURL=memory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../src/fs/memory.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,wBAAwB,EACxB,wBAAwB,EACxB,wBAAwB,EACzB,MAAM,qBAAqB,CAAC;AAkB7B,MAAM,WAAW,yBAAyB;IACxC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,WAAW,GAAG,eAAe,GAAG,MAAM,CAAC,CAAC;IACnF,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;IACrB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,qBAAa,YAAY;IAKX,OAAO,CAAC,QAAQ,CAAC,IAAI;IAJjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA4B;IACpD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;gBAEhB,IAAI,GAAE,yBAA8B;IAUjE,cAAc,CAAC,QAAQ,CAAC,EAAE,MAAM,IAAI,GAAG,wBAAwB;IAI/D,SAAS,IAAI,mBAAmB,EAAE;IAwBlC,IAAI,CAAC,OAAO,EAAE,mBAAmB,EAAE,GAAG,IAAI;IA4B1C,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU;IAKlC,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,UAAQ,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI;IA6BpF,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAiB9B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,wBAAwB;IAsBhD,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,wBAAwB,EAAE;IAiBjD,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAIlC,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,UAAO,EAAE,QAAQ,UAAQ,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO;IAuB1F,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAkBnC,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAiB7B,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAgChC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI;IA0CtC,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,IAAI;IAUlD,OAAO,CAAC,YAAY;IAgBpB,OAAO,CAAC,OAAO;IASf,OAAO,CAAC,MAAM;IAYd,OAAO,CAAC,YAAY;CASrB;AAsED,wBAAgB,wBAAwB,CAAC,OAAO,CAAC,EAAE,yBAAyB,GAAG,wBAAwB,CAGtG"}
|