diff --git a/apps/labs/electron/main.mjs b/apps/labs/electron/main.mjs
new file mode 100644
index 000000000..7118e3ec4
--- /dev/null
+++ b/apps/labs/electron/main.mjs
@@ -0,0 +1,54 @@
+import { app, BrowserWindow, shell } from "electron";
+import path from "node:path";
+import { fileURLToPath } from "node:url";
+
+const __dirname = path.dirname(fileURLToPath(import.meta.url));
+const rendererUrl = process.env.LABS_RENDERER_URL || "";
+
+let mainWindow = null;
+
+function createWindow() {
+ mainWindow = new BrowserWindow({
+ width: 1480,
+ height: 980,
+ minWidth: 1080,
+ minHeight: 720,
+ backgroundColor: "#141211",
+ titleBarStyle: "hiddenInset",
+ webPreferences: {
+ preload: path.join(__dirname, "preload.mjs"),
+ contextIsolation: true,
+ nodeIntegration: false,
+ webSecurity: false,
+ },
+ });
+
+ mainWindow.webContents.setWindowOpenHandler(({ url }) => {
+ shell.openExternal(url).catch(() => undefined);
+ return { action: "deny" };
+ });
+
+ if (rendererUrl) {
+ mainWindow.loadURL(rendererUrl).catch(() => undefined);
+ } else {
+ mainWindow
+ .loadFile(path.join(__dirname, "..", "dist", "index.html"))
+ .catch(() => undefined);
+ }
+}
+
+app.whenReady().then(() => {
+ createWindow();
+
+ app.on("activate", () => {
+ if (BrowserWindow.getAllWindows().length === 0) {
+ createWindow();
+ }
+ });
+});
+
+app.on("window-all-closed", () => {
+ if (process.platform !== "darwin") {
+ app.quit();
+ }
+});
diff --git a/apps/labs/electron/preload.mjs b/apps/labs/electron/preload.mjs
new file mode 100644
index 000000000..7894a68d6
--- /dev/null
+++ b/apps/labs/electron/preload.mjs
@@ -0,0 +1,6 @@
+import { contextBridge } from "electron";
+
+contextBridge.exposeInMainWorld("openworkLabsDesktop", {
+ isDesktop: true,
+ platform: process.platform,
+});
diff --git a/apps/labs/index.html b/apps/labs/index.html
new file mode 100644
index 000000000..00b6df582
--- /dev/null
+++ b/apps/labs/index.html
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+ OpenWork Labs
+
+
+
+
+
+
diff --git a/apps/labs/package.json b/apps/labs/package.json
new file mode 100644
index 000000000..240c4373e
--- /dev/null
+++ b/apps/labs/package.json
@@ -0,0 +1,30 @@
+{
+ "name": "@openwork/labs",
+ "private": true,
+ "version": "0.0.1",
+ "type": "module",
+ "main": "electron/main.mjs",
+ "scripts": {
+ "dev": "node ./scripts/dev.mjs",
+ "build": "vite build",
+ "preview": "vite preview --host 0.0.0.0 --port 3340 --strictPort",
+ "typecheck": "tsc -p tsconfig.json --noEmit",
+ "start": "electron ./electron/main.mjs"
+ },
+ "dependencies": {
+ "@opencode-ai/sdk": "^1.1.31",
+ "@tanstack/react-virtual": "^3.13.23",
+ "react": "19.2.4",
+ "react-dom": "19.2.4",
+ "streamdown": "^2.5.0"
+ },
+ "devDependencies": {
+ "@types/node": "^25.4.0",
+ "@types/react": "19.2.14",
+ "@types/react-dom": "19.2.3",
+ "@vitejs/plugin-react": "^5.0.4",
+ "electron": "^41.1.1",
+ "typescript": "^5.9.3",
+ "vite": "^7.1.12"
+ }
+}
diff --git a/apps/labs/pr/openwork-labs-template-starter.png b/apps/labs/pr/openwork-labs-template-starter.png
new file mode 100644
index 000000000..dd18b7e81
Binary files /dev/null and b/apps/labs/pr/openwork-labs-template-starter.png differ
diff --git a/apps/labs/scripts/dev.mjs b/apps/labs/scripts/dev.mjs
new file mode 100644
index 000000000..f557b2a37
--- /dev/null
+++ b/apps/labs/scripts/dev.mjs
@@ -0,0 +1,84 @@
+import { spawn } from "node:child_process";
+
+const rendererPort = 3340;
+const rendererUrl = `http://127.0.0.1:${rendererPort}`;
+
+const children = [];
+let shuttingDown = false;
+
+function cleanup(exitCode = 0) {
+ if (shuttingDown) return;
+ shuttingDown = true;
+
+ for (const child of children) {
+ if (!child.killed) {
+ child.kill("SIGTERM");
+ }
+ }
+
+ setTimeout(() => process.exit(exitCode), 120);
+}
+
+function spawnLogged(command, args, env = process.env) {
+ const child = spawn(command, args, {
+ stdio: "inherit",
+ env,
+ shell: process.platform === "win32",
+ });
+ children.push(child);
+ return child;
+}
+
+async function waitForRenderer(url, timeoutMs = 30_000) {
+ const startedAt = Date.now();
+ while (Date.now() - startedAt < timeoutMs) {
+ try {
+ const response = await fetch(url);
+ if (response.ok) return;
+ } catch {
+ // Ignore until the server is ready.
+ }
+ await new Promise((resolve) => setTimeout(resolve, 250));
+ }
+
+ throw new Error(`Timed out waiting for ${url}`);
+}
+
+process.on("SIGINT", () => cleanup(0));
+process.on("SIGTERM", () => cleanup(0));
+
+const vite = spawnLogged("pnpm", [
+ "exec",
+ "vite",
+ "--host",
+ "0.0.0.0",
+ "--port",
+ String(rendererPort),
+ "--strictPort",
+]);
+
+vite.on("exit", (code) => {
+ if (!shuttingDown) {
+ cleanup(code ?? 1);
+ }
+});
+
+try {
+ await waitForRenderer(rendererUrl);
+} catch (error) {
+ console.error(error instanceof Error ? error.message : String(error));
+ cleanup(1);
+}
+
+const electron = spawnLogged(
+ "pnpm",
+ ["exec", "electron", "./electron/main.mjs"],
+ {
+ ...process.env,
+ LABS_RENDERER_URL: rendererUrl,
+ },
+);
+
+electron.on("exit", (code) => {
+ cleanup(code ?? 0);
+});
diff --git a/apps/labs/src/app.tsx b/apps/labs/src/app.tsx
new file mode 100644
index 000000000..08421dcec
--- /dev/null
+++ b/apps/labs/src/app.tsx
@@ -0,0 +1,948 @@
+import { useEffect, useMemo, useRef, useState } from "react";
+import { useVirtualizer } from "@tanstack/react-virtual";
+import { Streamdown } from "streamdown";
+import type { Message, Part, Session } from "@opencode-ai/sdk/v2/client";
+
+import { fetchTemplateProfile, builtInTemplates } from "./templates";
+import { workspaceNameFromUrl } from "./opencode";
+import type {
+ LabsStarter,
+ LabsTemplateProfile,
+ MessageWithParts,
+ SeedMessage,
+ WorkspaceConnectionStatus,
+} from "./types";
+import { useLabsApp } from "./use-labs-app";
+
+const DEFAULT_EMPTY_STATE = {
+ title: "Where are my workspaces, what chats do I have, and how do I start from something useful?",
+ body: "Connect a workspace, then open a template or start typing.",
+};
+
+const synthesizeSeedMessages = (seedMessages: SeedMessage[]) =>
+ seedMessages.map((seed, index) => ({
+ info: {
+ id: `seed-${index}`,
+ sessionID: `seed-session-${index}`,
+ role: seed.role,
+ time: {
+ created: index,
+ },
+ } as Message,
+ parts: [
+ {
+ id: `seed-part-${index}`,
+ messageID: `seed-${index}`,
+ sessionID: `seed-session-${index}`,
+ type: "text",
+ text: seed.text,
+ } as Part,
+ ],
+ })) satisfies MessageWithParts[];
+
+const formatRelativeTime = (timestampMs?: number | null) => {
+ if (!timestampMs) return "Just now";
+ const delta = Date.now() - timestampMs;
+ if (delta < 60_000) return `${Math.max(1, Math.round(delta / 1000))}s ago`;
+ if (delta < 60 * 60_000) return `${Math.max(1, Math.round(delta / 60_000))}m ago`;
+ if (delta < 24 * 60 * 60_000) return `${Math.max(1, Math.round(delta / (60 * 60_000)))}h ago`;
+ return new Date(timestampMs).toLocaleDateString();
+};
+
+const sessionTitle = (session: Session | null | undefined) => {
+ const title = typeof session?.title === "string" ? session.title.trim() : "";
+ return title || "Untitled chat";
+};
+
+const workspaceInitials = (value: string) =>
+ value
+ .split(/\s+/)
+ .filter(Boolean)
+ .slice(0, 2)
+ .map((part) => part.charAt(0).toUpperCase())
+ .join("") || "OW";
+
+const connectionLabel = (status: WorkspaceConnectionStatus) => {
+ if (status === "connected") return "Live";
+ if (status === "connecting") return "Checking";
+ return "Offline";
+};
+
+export function App() {
+ const labs = useLabsApp();
+ const [composerText, setComposerText] = useState("");
+ const [workspaceModalOpen, setWorkspaceModalOpen] = useState(false);
+ const [templateModalOpen, setTemplateModalOpen] = useState(false);
+ const [templateUrl, setTemplateUrl] = useState("");
+ const [templateBusy, setTemplateBusy] = useState(false);
+ const [templateError, setTemplateError] = useState(null);
+ const [previewTemplate, setPreviewTemplate] = useState(null);
+ const [selectedTemplateId, setSelectedTemplateId] = useState(builtInTemplates[0]?.id ?? "");
+ const [templateTargetMode, setTemplateTargetMode] = useState<"current" | "existing" | "new">("current");
+ const [templateWorkspaceId, setTemplateWorkspaceId] = useState("");
+ const [newWorkspaceName, setNewWorkspaceName] = useState("");
+ const [newWorkspaceUrl, setNewWorkspaceUrl] = useState("");
+ const [newWorkspaceToken, setNewWorkspaceToken] = useState("");
+ const [workspaceForm, setWorkspaceForm] = useState({
+ name: "",
+ baseUrl: "",
+ token: "",
+ });
+
+ const activeWorkspace = labs.activeWorkspace;
+ const activeSessions = labs.activeSessions;
+ const selectedSessionId = labs.selectedSessionId;
+ const selectedSession = useMemo(
+ () => activeSessions.find((session) => session.id === selectedSessionId) ?? null,
+ [activeSessions, selectedSessionId],
+ );
+ const activeConnection = activeWorkspace
+ ? labs.state.connectionByWorkspaceId[activeWorkspace.id] ?? {
+ status: "disconnected",
+ message: "Not connected",
+ }
+ : null;
+ const selectedSessionMessages = selectedSessionId
+ ? labs.state.messagesBySessionId[selectedSessionId] ?? []
+ : [];
+ const selectedSeedMessages = selectedSessionId
+ ? labs.state.seedMessagesBySessionId[selectedSessionId] ?? []
+ : [];
+ const visibleMessages = useMemo(() => {
+ if (selectedSessionMessages.length > 0) return selectedSessionMessages;
+ if (selectedSeedMessages.length > 0) return synthesizeSeedMessages(selectedSeedMessages);
+ return [] as MessageWithParts[];
+ }, [selectedSeedMessages, selectedSessionMessages]);
+ const sessionBusy = selectedSessionId
+ ? labs.state.statusBySessionId[selectedSessionId] === "busy"
+ : false;
+ const emptyState = activeWorkspace?.template?.blueprint.emptyState ?? DEFAULT_EMPTY_STATE;
+ const starterCards = activeWorkspace?.template?.blueprint.emptyState.starters ?? [];
+
+ const templateLibrary = useMemo(() => {
+ const merged = [...builtInTemplates, ...labs.state.templates];
+ const seen = new Set();
+ return merged.filter((template) => {
+ const key = template.sourceUrl || template.id;
+ if (seen.has(key)) return false;
+ seen.add(key);
+ return true;
+ });
+ }, [labs.state.templates]);
+
+ const displayTemplates = useMemo(() => {
+ if (!previewTemplate) return templateLibrary;
+ return [previewTemplate, ...templateLibrary.filter((template) => template.id !== previewTemplate.id)];
+ }, [previewTemplate, templateLibrary]);
+
+ const selectedTemplate =
+ displayTemplates.find((template) => template.id === selectedTemplateId) ?? displayTemplates[0] ?? null;
+
+ useEffect(() => {
+ if (selectedTemplate) {
+ setSelectedTemplateId(selectedTemplate.id);
+ }
+ }, [selectedTemplate]);
+
+ useEffect(() => {
+ if (!templateModalOpen) return;
+ if (labs.activeWorkspace) {
+ setTemplateTargetMode("current");
+ setTemplateWorkspaceId(labs.activeWorkspace.id);
+ setNewWorkspaceName("");
+ setNewWorkspaceUrl("");
+ setNewWorkspaceToken("");
+ } else if (labs.state.workspaces.length > 0) {
+ setTemplateTargetMode("existing");
+ setTemplateWorkspaceId(labs.state.workspaces[0]?.id ?? "");
+ } else {
+ setTemplateTargetMode("new");
+ }
+ }, [labs.activeWorkspace, labs.state.workspaces, templateModalOpen]);
+
+ const handleAddWorkspace = () => {
+ setWorkspaceForm({
+ name: activeWorkspace?.name ?? "",
+ baseUrl: activeWorkspace?.baseUrl ?? "",
+ token: activeWorkspace?.token ?? "",
+ });
+ setWorkspaceModalOpen(true);
+ };
+
+ const handleWorkspaceSave = () => {
+ if (!workspaceForm.baseUrl.trim()) return;
+ const workspaceId = labs.saveWorkspace(workspaceForm);
+ setWorkspaceModalOpen(false);
+ labs.setActiveWorkspace(workspaceId);
+ };
+
+ const handleFetchTemplate = async () => {
+ setTemplateBusy(true);
+ setTemplateError(null);
+ try {
+ const template = await fetchTemplateProfile(templateUrl);
+ setPreviewTemplate(template);
+ setSelectedTemplateId(template.id);
+ } catch (error) {
+ setTemplateError(error instanceof Error ? error.message : String(error));
+ } finally {
+ setTemplateBusy(false);
+ }
+ };
+
+ const handleApplyTemplate = async () => {
+ if (!selectedTemplate) return;
+
+ let workspaceId = activeWorkspace?.id ?? null;
+ if (templateTargetMode === "existing") {
+ workspaceId = templateWorkspaceId || null;
+ }
+ if (templateTargetMode === "new") {
+ if (!newWorkspaceUrl.trim()) {
+ setTemplateError("Add a server URL so Labs knows where to create the starter chats.");
+ return;
+ }
+ workspaceId = labs.saveWorkspace({
+ name: newWorkspaceName,
+ baseUrl: newWorkspaceUrl,
+ token: newWorkspaceToken,
+ });
+ }
+
+ if (!workspaceId) {
+ setTemplateError("Choose where this template should land.");
+ return;
+ }
+
+ await labs.applyTemplateToWorkspace(workspaceId, selectedTemplate);
+ labs.setActiveWorkspace(workspaceId);
+ setTemplateModalOpen(false);
+ };
+
+ const handleSend = async () => {
+ if (!activeWorkspace || !composerText.trim()) return;
+ const sessionId = await labs.sendPrompt(activeWorkspace.id, selectedSessionId, composerText);
+ if (sessionId) {
+ setComposerText("");
+ await labs.selectSession(activeWorkspace.id, sessionId);
+ }
+ };
+
+ const handleStarter = async (starter: LabsStarter) => {
+ if (!activeWorkspace) {
+ if (starter.kind === "action") {
+ setTemplateModalOpen(true);
+ } else {
+ setWorkspaceModalOpen(true);
+ }
+ return;
+ }
+
+ if (starter.kind === "prompt") {
+ setComposerText(starter.prompt ?? starter.title);
+ return;
+ }
+
+ if (starter.kind === "session") {
+ const materialized = activeWorkspace.template?.blueprint.materialized.find(
+ (item) => item.templateId === starter.id,
+ );
+ if (materialized) {
+ await labs.selectSession(activeWorkspace.id, materialized.sessionId);
+ return;
+ }
+
+ const sessionId = await labs.createSession(activeWorkspace.id);
+ if (sessionId && starter.prompt) {
+ await labs.sendPrompt(activeWorkspace.id, sessionId, starter.prompt);
+ await labs.selectSession(activeWorkspace.id, sessionId);
+ }
+ return;
+ }
+
+ if (starter.kind === "action") {
+ const nextAction = labs.openTemplateActionForStarter(activeWorkspace.id, starter.action);
+ if (nextAction === "template-library") {
+ setTemplateModalOpen(true);
+ }
+ }
+ };
+
+ const handleCopyTemplateLink = async () => {
+ if (!activeWorkspace?.template?.sourceUrl) return;
+ try {
+ await navigator.clipboard.writeText(activeWorkspace.template.sourceUrl);
+ } catch {
+ // Ignore clipboard failures in the web fallback.
+ }
+ };
+
+ const noWorkspaces = labs.state.workspaces.length === 0;
+ const noSelectedSession = !selectedSessionId;
+ const showStarterSurface = visibleMessages.length === 0;
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+ {labs.state.error ? (
+
+ {labs.state.error}
+
+
+ ) : null}
+
+
+ {noWorkspaces ? (
+ setTemplateModalOpen(true)} />
+ ) : showStarterSurface ? (
+
+ ) : (
+
+ )}
+
+
+
+
+
+
+ {workspaceModalOpen ? (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ) : null}
+
+ {templateModalOpen ? (
+
+
+
+
+ setTemplateUrl(event.target.value)}
+ placeholder="Paste a share.openworklabs.com bundle link"
+ />
+
+
+ {templateError ?
{templateError}
: null}
+
+
+ {displayTemplates.map((template) => (
+
+ ))}
+
+
+
+
+ {selectedTemplate ? (
+ <>
+
+
+
Template
+
{selectedTemplate.name}
+
{selectedTemplate.description}
+
+
+
+
+
+
+
+
+
+ session.title)} />
+
+
+
+
+
+ >
+ ) : null}
+
+
+
+
+
+
+
+
+ ) : null}
+
+ );
+}
+
+function OnboardingPanel(props: {
+ onAddWorkspace: () => void;
+ onOpenTemplates: () => void;
+}) {
+ return (
+
+
+
OpenWork Labs
+
Calm, session-first chat for real workspaces.
+
+ Labs keeps the surface small: workspaces on the left, chats in the middle, templates when you need a useful starting point.
+
+
+
+
+
+
+
+
+
+
Multi-workspace
+
One OpenCode server per workspace.
+
Switch contexts instantly and let background workspaces keep quietly receiving updates.
+
+
+
Shared templates
+
Use starter chats you can trust.
+
Preview the template before you apply it, then land it into the workspace that needs it.
+
+
+
+ );
+}
+
+function StarterSurface(props: {
+ title: string;
+ body: string;
+ starters: LabsStarter[];
+ recommendation: string[];
+ onStarter: (starter: LabsStarter) => void;
+}) {
+ return (
+
+
+
Start here
+
{props.title}
+
{props.body}
+
+
+ {props.recommendation.length > 0 ? (
+
+ {props.recommendation.map((item) => (
+
+ {item}
+
+ ))}
+
+ ) : null}
+
+
+ {props.starters.map((starter) => (
+
+ ))}
+
+
+ );
+}
+
+function MessageTimeline(props: { messages: MessageWithParts[]; busy: boolean }) {
+ const parentRef = useRef(null);
+ const shouldStickToBottomRef = useRef(true);
+
+ const virtualizer = useVirtualizer({
+ count: props.messages.length,
+ getScrollElement: () => parentRef.current,
+ estimateSize: () => 132,
+ overscan: 6,
+ useFlushSync: false,
+ getItemKey: (index) => props.messages[index]?.info.id ?? `message-${index}`,
+ });
+
+ useEffect(() => {
+ const element = parentRef.current;
+ if (!element) return;
+
+ const onScroll = () => {
+ const remaining = element.scrollHeight - element.scrollTop - element.clientHeight;
+ shouldStickToBottomRef.current = remaining < 160;
+ };
+
+ onScroll();
+ element.addEventListener("scroll", onScroll);
+ return () => element.removeEventListener("scroll", onScroll);
+ }, []);
+
+ useEffect(() => {
+ if (!shouldStickToBottomRef.current) return;
+ const element = parentRef.current;
+ if (!element) return;
+ element.scrollTop = element.scrollHeight;
+ }, [props.busy, props.messages]);
+
+ return (
+
+
+ {virtualizer.getVirtualItems().map((row) => {
+ const message = props.messages[row.index];
+ const isUser = message.info.role === "user";
+ return (
+
+
+
+ {isUser ? "You" : "Labs"}
+ {formatRelativeTime(message.info.time?.created)}
+
+
+ {message.parts.map((part) => (
+
+ ))}
+
+
+
+ );
+ })}
+
+
+ );
+}
+
+function MessagePart(props: { part: Part; busy: boolean }) {
+ const record = props.part as Part & Record;
+
+ if (record.type === "text") {
+ return (
+
+ {String(record.text ?? "")}
+
+ );
+ }
+
+ if (record.type === "reasoning") {
+ return (
+
+ Thinking
+ {String(record.text ?? "")}
+
+ );
+ }
+
+ if (record.type === "tool") {
+ const state = (record.state as Record | undefined) ?? {};
+ return (
+
+
+ {String(record.tool ?? "Tool")}
+ {String(state.status ?? "running")}
+
+ {state.output ?
{String(state.output)}
: null}
+
+ );
+ }
+
+ return {JSON.stringify(record, null, 2)};
+}
+
+function ModalFrame(props: {
+ title: string;
+ subtitle: string;
+ large?: boolean;
+ children: React.ReactNode;
+}) {
+ return (
+
+
+
+
+
OpenWork Labs
+
{props.title}
+
{props.subtitle}
+
+
+ {props.children}
+
+
+ );
+}
+
+function TemplateChecklist(props: { title: string; items: string[] }) {
+ return (
+
+
{props.title}
+
+ {props.items.length > 0 ? (
+ props.items.map((item) => - {item}
)
+ ) : (
+ - Nothing extra yet
+ )}
+
+
+ );
+}
+
+function TemplateStat(props: { label: string; value: string }) {
+ return (
+
+ {props.label}
+ {props.value}
+
+ );
+}
diff --git a/apps/labs/src/main.tsx b/apps/labs/src/main.tsx
new file mode 100644
index 000000000..318990cd9
--- /dev/null
+++ b/apps/labs/src/main.tsx
@@ -0,0 +1,13 @@
+import React from "react";
+import ReactDOM from "react-dom/client";
+
+import { App } from "./app";
+
+import "streamdown/styles.css";
+import "./styles.css";
+
+ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
+
+
+ ,
+);
diff --git a/apps/labs/src/opencode.ts b/apps/labs/src/opencode.ts
new file mode 100644
index 000000000..cf7087125
--- /dev/null
+++ b/apps/labs/src/opencode.ts
@@ -0,0 +1,131 @@
+import { createOpencodeClient } from "@opencode-ai/sdk/v2/client";
+
+import type { LabsWorkspace, NormalizedLabsEvent } from "./types";
+
+const REQUEST_TIMEOUT_MS = 12_000;
+
+function stripTrailingSlash(input: string) {
+ return input.replace(/\/+$/, "");
+}
+
+function withInferredProtocol(input: string) {
+ if (/^[a-z]+:\/\//i.test(input)) return input;
+ if (/^(localhost|127\.0\.0\.1|0\.0\.0\.0)(:\d+)?(\/|$)/i.test(input)) {
+ return `http://${input}`;
+ }
+ return `https://${input}`;
+}
+
+export function normalizeOpencodeBaseUrl(input: string) {
+ const trimmed = input.trim();
+ if (!trimmed) return "";
+
+ try {
+ const url = new URL(withInferredProtocol(trimmed));
+ const path = stripTrailingSlash(url.pathname || "");
+ url.pathname = path.endsWith("/opencode") ? path : `${path || ""}/opencode`;
+ return stripTrailingSlash(url.toString());
+ } catch {
+ return "";
+ }
+}
+
+export function workspaceNameFromUrl(baseUrl: string) {
+ try {
+ const url = new URL(baseUrl);
+ const label = url.hostname.replace(/^www\./, "").split(".")[0] ?? "";
+ return label
+ .split(/[-_]/g)
+ .filter(Boolean)
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
+ .join(" ");
+ } catch {
+ return "";
+ }
+}
+
+export function describeError(error: unknown): string {
+ if (error instanceof Error && error.message.trim()) return error.message.trim();
+ if (typeof error === "string" && error.trim()) return error.trim();
+ try {
+ return JSON.stringify(error);
+ } catch {
+ return "Unknown error";
+ }
+}
+
+async function fetchWithTimeout(
+ fetchImpl: typeof globalThis.fetch,
+ input: RequestInfo | URL,
+ init?: RequestInit,
+ timeoutMs = REQUEST_TIMEOUT_MS,
+) {
+ const controller = new AbortController();
+ const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
+
+ try {
+ return await fetchImpl(input, {
+ ...init,
+ signal: init?.signal ?? controller.signal,
+ });
+ } catch (error) {
+ if (error instanceof Error && error.name === "AbortError") {
+ throw new Error("Request timed out.");
+ }
+ throw error;
+ } finally {
+ clearTimeout(timeoutId);
+ }
+}
+
+export function createLabsClient(workspace: LabsWorkspace) {
+ const baseUrl = normalizeOpencodeBaseUrl(workspace.baseUrl);
+ const headers = workspace.token?.trim()
+ ? {
+ Authorization: `Bearer ${workspace.token.trim()}`,
+ }
+ : undefined;
+
+ return createOpencodeClient({
+ baseUrl,
+ headers,
+ fetch: (input: RequestInfo | URL, init?: RequestInit) =>
+ fetchWithTimeout(globalThis.fetch, input, init),
+ });
+}
+
+export function unwrap(result: unknown): T {
+ if (result && typeof result === "object") {
+ const record = result as Record;
+ if ("data" in record) {
+ if (record.data !== undefined) return record.data as T;
+ throw new Error(describeError(record.error));
+ }
+ }
+
+ return result as T;
+}
+
+export function normalizeLabsEvent(raw: unknown): NormalizedLabsEvent | null {
+ if (!raw || typeof raw !== "object") return null;
+
+ const record = raw as Record;
+ if (typeof record.type === "string") {
+ return {
+ type: record.type,
+ properties: record.properties,
+ };
+ }
+
+ if (record.payload && typeof record.payload === "object") {
+ const payload = record.payload as Record;
+ if (typeof payload.type === "string") {
+ return {
+ type: payload.type,
+ properties: payload.properties,
+ };
+ }
+ }
+
+ return null;
+}
diff --git a/apps/labs/src/styles.css b/apps/labs/src/styles.css
new file mode 100644
index 000000000..a342afa12
--- /dev/null
+++ b/apps/labs/src/styles.css
@@ -0,0 +1,1037 @@
+:root {
+ color-scheme: dark;
+ font-family: Inter, "IBM Plex Sans", system-ui, sans-serif;
+ --background: #121212;
+ --foreground: #ededed;
+ --card: #1a1a1a;
+ --card-foreground: #ededed;
+ --muted: #202020;
+ --muted-foreground: #9ca3af;
+ --border: #262626;
+ --input: #262626;
+ --primary: #3b82f6;
+ --primary-foreground: #f8fbff;
+ --radius: 1rem;
+ --labs-app-bg: #efebe2;
+ --labs-surface: #121212;
+ --labs-sidebar: rgba(253, 250, 244, 0.82);
+ --labs-sidebar-strong: rgba(252, 248, 240, 0.94);
+ --labs-sidebar-copy: #5f635d;
+ --labs-border: rgba(32, 29, 22, 0.1);
+ --labs-surface-border: rgba(255, 255, 255, 0.06);
+ --labs-surface-muted: #9ca3af;
+ --labs-hover: rgba(255, 255, 255, 0.04);
+ --labs-active: rgba(255, 255, 255, 0.08);
+ --labs-accent: #3b82f6;
+ --labs-accent-strong: #2563eb;
+ --labs-accent-soft: rgba(59, 130, 246, 0.12);
+ --labs-shell-shadow: 0 32px 90px -44px rgba(28, 21, 12, 0.4);
+ --labs-card-shadow: 0 18px 48px -36px rgba(0, 0, 0, 0.28);
+}
+
+* {
+ box-sizing: border-box;
+}
+
+html,
+body,
+#root {
+ min-height: 100%;
+}
+
+body {
+ margin: 0;
+ background:
+ radial-gradient(circle at top left, rgba(39, 104, 240, 0.14), transparent 26%),
+ radial-gradient(circle at bottom right, rgba(236, 155, 54, 0.14), transparent 28%),
+ linear-gradient(180deg, #f4efe7 0%, #ece6db 100%);
+ color: #181614;
+}
+
+button,
+input,
+textarea,
+select {
+ font: inherit;
+}
+
+button {
+ cursor: pointer;
+}
+
+code,
+pre,
+.workspace-chip-label,
+.status-pill,
+.recommendation-pill,
+.session-row-meta,
+.template-stat strong {
+ font-family: "IBM Plex Mono", "SFMono-Regular", ui-monospace, monospace;
+}
+
+.labs-shell {
+ position: relative;
+ min-height: 100vh;
+ display: grid;
+ grid-template-columns: 72px 288px minmax(0, 1fr);
+ gap: 20px;
+ padding: 20px;
+ overflow: hidden;
+}
+
+.labs-glow {
+ position: fixed;
+ pointer-events: none;
+ border-radius: 999px;
+ filter: blur(90px);
+ opacity: 0.6;
+}
+
+.labs-glow-a {
+ top: -140px;
+ left: -100px;
+ width: 340px;
+ height: 340px;
+ background: rgba(59, 130, 246, 0.2);
+}
+
+.labs-glow-b {
+ right: -120px;
+ bottom: 30px;
+ width: 300px;
+ height: 300px;
+ background: rgba(245, 158, 11, 0.18);
+}
+
+.workspace-rail,
+.session-sidebar-shell,
+.thread-shell,
+.modal-frame,
+.onboarding-card,
+.starter-card,
+.template-card,
+.template-checklist,
+.template-target-panel {
+ box-shadow: var(--labs-shell-shadow);
+}
+
+.workspace-rail {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 18px;
+ padding: 20px 10px;
+ border-radius: 32px;
+ background: rgba(17, 17, 17, 0.96);
+ border: 1px solid rgba(255, 255, 255, 0.04);
+}
+
+.workspace-rail-header {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 4px;
+}
+
+.wordmark-mark {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 40px;
+ height: 40px;
+ border-radius: 14px;
+ background: linear-gradient(180deg, rgba(59, 130, 246, 0.24), rgba(37, 99, 235, 0.42));
+ color: #f8fbff;
+ font-size: 0.82rem;
+ font-weight: 700;
+ letter-spacing: 0.18em;
+}
+
+.wordmark-copy {
+ font-size: 0.7rem;
+ letter-spacing: 0.2em;
+ text-transform: uppercase;
+ color: rgba(255, 255, 255, 0.7);
+}
+
+.workspace-rail-stack {
+ display: flex;
+ flex: 1;
+ flex-direction: column;
+ align-items: center;
+ gap: 12px;
+ width: 100%;
+}
+
+.workspace-chip,
+.workspace-add {
+ position: relative;
+ width: 52px;
+ min-height: 52px;
+ border: 0;
+ border-radius: 16px;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ color: rgba(255, 255, 255, 0.92);
+ background: rgba(255, 255, 255, 0.06);
+ transition: transform 160ms ease, background-color 160ms ease;
+}
+
+.workspace-chip:hover,
+.workspace-add:hover {
+ transform: translateY(-1px);
+ background: rgba(255, 255, 255, 0.1);
+}
+
+.workspace-chip.active {
+ background: rgba(255, 255, 255, 0.14);
+}
+
+.workspace-chip-indicator {
+ position: absolute;
+ left: -9px;
+ width: 3px;
+ height: 24px;
+ border-radius: 999px;
+ background: var(--workspace-color, var(--labs-accent));
+ opacity: 0;
+ transition: opacity 160ms ease;
+}
+
+.workspace-chip.active .workspace-chip-indicator {
+ opacity: 1;
+}
+
+.workspace-chip-label {
+ font-size: 0.82rem;
+ letter-spacing: 0.08em;
+}
+
+.workspace-chip-badge {
+ position: absolute;
+ top: -4px;
+ right: -3px;
+ display: inline-flex;
+ min-width: 18px;
+ height: 18px;
+ align-items: center;
+ justify-content: center;
+ border-radius: 999px;
+ background: var(--workspace-color, var(--labs-accent));
+ color: #fff;
+ font-size: 0.66rem;
+ font-weight: 700;
+}
+
+.workspace-add {
+ margin-top: auto;
+ font-size: 1.5rem;
+ line-height: 1;
+}
+
+.session-sidebar {
+ min-width: 0;
+}
+
+.session-sidebar-shell {
+ display: flex;
+ min-height: calc(100vh - 40px);
+ flex-direction: column;
+ gap: 18px;
+ padding: 22px;
+ border-radius: 32px;
+ background: var(--labs-sidebar);
+ backdrop-filter: blur(18px);
+ border: 1px solid var(--labs-border);
+}
+
+.sidebar-header,
+.thread-header,
+.template-card,
+.template-card-grid,
+.modal-header,
+.onboarding-actions,
+.starter-copy {
+ display: flex;
+ align-items: flex-start;
+ justify-content: space-between;
+ gap: 16px;
+}
+
+.sidebar-header h1,
+.thread-header h2,
+.modal-header h2,
+.template-card h2,
+.starter-copy h2,
+.onboarding-card h1,
+.onboarding-card h2,
+.template-list-item strong {
+ margin: 8px 0 0;
+ color: #171512;
+ line-height: 1.04;
+ letter-spacing: -0.03em;
+}
+
+.sidebar-header h1,
+.thread-header h2,
+.modal-header h2,
+.template-card h2,
+.starter-copy h2 {
+ font-size: clamp(1.45rem, 2.6vw, 2.15rem);
+}
+
+.sidebar-header p,
+.thread-header p,
+.connection-copy,
+.template-card p,
+.template-list-item p,
+.template-checklist li,
+.template-target-panel,
+.starter-copy p,
+.starter-card p,
+.modal-header p,
+.onboarding-card p,
+.sidebar-empty p {
+ margin: 0;
+ color: var(--labs-sidebar-copy);
+ line-height: 1.6;
+}
+
+.eyebrow {
+ margin: 0;
+ font-size: 0.68rem;
+ font-weight: 700;
+ letter-spacing: 0.18em;
+ text-transform: uppercase;
+ color: #72746e;
+}
+
+.connection-pill-row,
+.sidebar-actions,
+.recommendation-row,
+.composer-actions,
+.modal-actions,
+.target-toggle-row,
+.template-fetch-row {
+ display: flex;
+ gap: 12px;
+}
+
+.connection-pill-row {
+ align-items: center;
+}
+
+.status-pill,
+.recommendation-pill {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: 999px;
+ padding: 8px 12px;
+ font-size: 0.72rem;
+ letter-spacing: 0.06em;
+}
+
+.status-pill {
+ border: 1px solid rgba(32, 29, 22, 0.1);
+ background: rgba(255, 255, 255, 0.7);
+ color: #4e514d;
+}
+
+.status-pill.connected {
+ background: rgba(20, 184, 166, 0.12);
+ color: #0f766e;
+}
+
+.status-pill.connecting {
+ background: rgba(59, 130, 246, 0.12);
+ color: #1d4ed8;
+}
+
+.status-pill.disconnected {
+ background: rgba(239, 68, 68, 0.12);
+ color: #b91c1c;
+}
+
+.connection-copy {
+ font-size: 0.92rem;
+}
+
+.sidebar-actions {
+ flex-wrap: wrap;
+}
+
+.primary-button,
+.secondary-button,
+.ghost-button,
+.target-toggle {
+ border: 0;
+ border-radius: 999px;
+ padding: 11px 16px;
+ font-size: 0.92rem;
+ transition: transform 160ms ease, background-color 160ms ease, box-shadow 160ms ease;
+}
+
+.primary-button {
+ background: var(--labs-accent);
+ color: #fff;
+ box-shadow: 0 10px 22px -18px rgba(37, 99, 235, 0.6);
+}
+
+.primary-button:hover:not(:disabled),
+.secondary-button:hover:not(:disabled),
+.ghost-button:hover:not(:disabled),
+.target-toggle:hover:not(:disabled) {
+ transform: translateY(-1px);
+}
+
+.secondary-button,
+.ghost-button,
+.target-toggle {
+ background: rgba(255, 255, 255, 0.72);
+ color: #181614;
+ border: 1px solid rgba(32, 29, 22, 0.08);
+}
+
+.ghost-button {
+ background: transparent;
+}
+
+.target-toggle.active {
+ background: rgba(59, 130, 246, 0.12);
+ color: #1d4ed8;
+}
+
+.primary-button:disabled,
+.secondary-button:disabled,
+.ghost-button:disabled,
+.target-toggle:disabled,
+.workspace-add:disabled,
+.workspace-chip:disabled,
+.starter-card:disabled {
+ cursor: not-allowed;
+ opacity: 0.5;
+ transform: none;
+}
+
+.template-card.compact {
+ padding: 18px;
+}
+
+.template-card,
+.template-checklist,
+.template-target-panel,
+.starter-card,
+.onboarding-card,
+.template-list-item,
+.error-banner,
+.sidebar-empty {
+ border: 1px solid rgba(32, 29, 22, 0.08);
+ border-radius: 24px;
+ background: var(--labs-sidebar-strong);
+}
+
+.template-card,
+.template-target-panel,
+.onboarding-card,
+.error-banner,
+.sidebar-empty {
+ padding: 20px;
+}
+
+.template-card-grid,
+.onboarding-grid,
+.starter-grid,
+.template-stat-grid {
+ display: grid;
+ gap: 16px;
+}
+
+.template-card-grid,
+.onboarding-grid {
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+}
+
+.template-checklist ul {
+ margin: 14px 0 0;
+ padding-left: 18px;
+}
+
+.template-checklist li + li {
+ margin-top: 8px;
+}
+
+.template-stat-grid {
+ width: min(320px, 100%);
+ grid-template-columns: repeat(3, minmax(0, 1fr));
+}
+
+.template-stat {
+ border-radius: 18px;
+ border: 1px solid rgba(32, 29, 22, 0.08);
+ background: rgba(255, 255, 255, 0.7);
+ padding: 14px;
+}
+
+.template-stat span {
+ display: block;
+ font-size: 0.76rem;
+ color: #767873;
+}
+
+.template-stat strong {
+ display: block;
+ margin-top: 6px;
+ color: #171512;
+ font-size: 0.92rem;
+}
+
+.session-list {
+ display: flex;
+ flex: 1;
+ min-height: 0;
+ flex-direction: column;
+ gap: 10px;
+ overflow: auto;
+ padding-right: 4px;
+}
+
+.session-row {
+ width: 100%;
+ border: 0;
+ border-radius: 16px;
+ padding: 15px 16px;
+ text-align: left;
+ background: transparent;
+ transition: background-color 160ms ease;
+}
+
+.session-row:hover {
+ background: rgba(24, 22, 19, 0.06);
+}
+
+.session-row.active {
+ background: rgba(24, 22, 19, 0.08);
+}
+
+.session-row-title {
+ display: block;
+ color: #151311;
+ font-size: 0.95rem;
+ font-weight: 600;
+}
+
+.session-row-meta,
+.session-row-status {
+ display: inline-flex;
+ margin-top: 6px;
+ font-size: 0.72rem;
+ color: #6f726b;
+}
+
+.session-row-status {
+ margin-left: 8px;
+ color: #1d4ed8;
+}
+
+.thread-stage {
+ min-width: 0;
+}
+
+.thread-shell {
+ display: grid;
+ min-height: calc(100vh - 40px);
+ grid-template-rows: auto auto minmax(0, 1fr) auto;
+ gap: 18px;
+ padding: 24px;
+ border-radius: 36px;
+ background:
+ radial-gradient(circle at top right, rgba(59, 130, 246, 0.12), transparent 24%),
+ linear-gradient(180deg, #131313 0%, #111111 100%);
+ border: 1px solid var(--labs-surface-border);
+ color: var(--labs-foreground);
+}
+
+.thread-header h2,
+.thread-header p,
+.starter-copy h2,
+.starter-copy p,
+.starter-card strong,
+.starter-card p,
+.stream-markdown,
+.message-meta,
+.tool-card,
+.reasoning-card,
+.reasoning-body,
+.part-fallback,
+.error-banner,
+.onboarding-card.primary-surface h1,
+.onboarding-card.primary-surface p {
+ color: var(--foreground);
+}
+
+.thread-header .eyebrow,
+.message-meta,
+.starter-copy .eyebrow,
+.starter-card .eyebrow,
+.onboarding-card.primary-surface .eyebrow,
+.error-banner span {
+ color: var(--labs-surface-muted);
+}
+
+.thread-actions {
+ display: flex;
+ gap: 12px;
+}
+
+.thread-actions .secondary-button,
+.composer-actions .secondary-button {
+ background: rgba(255, 255, 255, 0.06);
+ border-color: rgba(255, 255, 255, 0.06);
+ color: #ededed;
+}
+
+.thread-actions .secondary-button:hover:not(:disabled),
+.composer-actions .secondary-button:hover:not(:disabled) {
+ background: rgba(255, 255, 255, 0.1);
+}
+
+.error-banner {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 12px;
+ background: rgba(239, 68, 68, 0.08);
+ border-color: rgba(239, 68, 68, 0.2);
+}
+
+.error-banner .ghost-button {
+ color: #ededed;
+ border-color: rgba(255, 255, 255, 0.08);
+}
+
+.thread-body {
+ min-height: 0;
+}
+
+.starter-surface,
+.onboarding-panel {
+ display: flex;
+ min-height: 100%;
+ flex-direction: column;
+ justify-content: center;
+ gap: 22px;
+ padding: 24px;
+}
+
+.recommendation-row {
+ flex-wrap: wrap;
+}
+
+.recommendation-pill {
+ background: rgba(255, 255, 255, 0.06);
+ color: #c3cad5;
+}
+
+.starter-grid {
+ grid-template-columns: repeat(3, minmax(0, 1fr));
+}
+
+.starter-card {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 10px;
+ padding: 18px;
+ text-align: left;
+ background: rgba(255, 255, 255, 0.04);
+ border-color: rgba(255, 255, 255, 0.06);
+}
+
+.starter-card:hover {
+ background: rgba(255, 255, 255, 0.06);
+}
+
+.starter-card strong {
+ font-size: 0.98rem;
+}
+
+.starter-card p {
+ font-size: 0.88rem;
+ color: #b0b7c2;
+}
+
+.message-scroll-region {
+ height: 100%;
+ overflow: auto;
+ padding-right: 8px;
+}
+
+.message-virtual-spacer {
+ position: relative;
+ width: 100%;
+}
+
+.message-row {
+ position: absolute;
+ left: 0;
+ width: 100%;
+ padding: 0 0 18px;
+}
+
+.message-card {
+ max-width: min(860px, 100%);
+ border-radius: 24px;
+ border: 1px solid rgba(255, 255, 255, 0.06);
+ padding: 18px 20px;
+ background: rgba(255, 255, 255, 0.03);
+}
+
+.message-row[data-user="true"] {
+ display: flex;
+ justify-content: flex-end;
+}
+
+.message-card.user {
+ background: rgba(59, 130, 246, 0.12);
+ border-color: rgba(59, 130, 246, 0.24);
+}
+
+.message-meta {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: 12px;
+ font-size: 0.78rem;
+}
+
+.message-parts > * + * {
+ margin-top: 14px;
+}
+
+.stream-markdown {
+ font-size: 0.95rem;
+ line-height: 1.7;
+}
+
+.stream-markdown p {
+ margin: 0 0 0.9rem;
+}
+
+.stream-markdown p:last-child {
+ margin-bottom: 0;
+}
+
+.stream-markdown ul,
+.stream-markdown ol {
+ margin: 0.6rem 0 0.9rem;
+ padding-left: 1.2rem;
+}
+
+.stream-markdown code {
+ padding: 0.12rem 0.36rem;
+ border-radius: 0.42rem;
+ background: rgba(255, 255, 255, 0.08);
+}
+
+.stream-markdown pre {
+ overflow: auto;
+ border-radius: 18px;
+ background: rgba(0, 0, 0, 0.24);
+ padding: 14px;
+}
+
+.tool-card,
+.reasoning-card,
+.part-fallback {
+ border-radius: 18px;
+ border: 1px solid rgba(255, 255, 255, 0.06);
+ background: rgba(255, 255, 255, 0.04);
+ padding: 14px;
+}
+
+.tool-card-header {
+ display: flex;
+ justify-content: space-between;
+ gap: 12px;
+ margin-bottom: 10px;
+}
+
+.tool-card p,
+.reasoning-body,
+.part-fallback {
+ margin: 0;
+ color: #c5ccd6;
+ line-height: 1.6;
+}
+
+.reasoning-card summary {
+ cursor: pointer;
+ color: #e5e7eb;
+}
+
+.composer-shell {
+ padding-top: 4px;
+}
+
+.composer-label {
+ display: inline-block;
+ margin-bottom: 10px;
+ font-size: 0.72rem;
+ letter-spacing: 0.18em;
+ text-transform: uppercase;
+ color: #8a90a1;
+}
+
+.composer-frame {
+ display: grid;
+ gap: 14px;
+ border-radius: 28px;
+ border: 1px solid rgba(255, 255, 255, 0.06);
+ background: rgba(255, 255, 255, 0.04);
+ padding: 16px;
+}
+
+.composer-input,
+.modal-field input,
+.modal-field select,
+.template-fetch-row input {
+ width: 100%;
+ border-radius: 16px;
+ border: 1px solid rgba(32, 29, 22, 0.08);
+ padding: 14px 16px;
+ background: rgba(255, 255, 255, 0.9);
+ color: #181614;
+ outline: none;
+ transition: border-color 160ms ease, box-shadow 160ms ease;
+}
+
+.composer-input {
+ min-height: 110px;
+ resize: vertical;
+ border-color: rgba(255, 255, 255, 0.06);
+ background: rgba(0, 0, 0, 0.16);
+ color: #ededed;
+}
+
+.composer-input::placeholder {
+ color: #9da3b1;
+}
+
+.composer-input:focus,
+.modal-field input:focus,
+.modal-field select:focus,
+.template-fetch-row input:focus {
+ border-color: rgba(59, 130, 246, 0.45);
+ box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.12);
+}
+
+.composer-actions {
+ justify-content: flex-end;
+}
+
+.modal-backdrop {
+ position: fixed;
+ inset: 0;
+ z-index: 30;
+ display: grid;
+ place-items: center;
+ padding: 24px;
+ background: rgba(10, 10, 10, 0.38);
+ backdrop-filter: blur(10px);
+}
+
+.modal-frame {
+ width: min(720px, 100%);
+ max-height: calc(100vh - 48px);
+ overflow: auto;
+ padding: 24px;
+ border-radius: 32px;
+ border: 1px solid rgba(32, 29, 22, 0.08);
+ background: rgba(251, 248, 241, 0.96);
+}
+
+.modal-frame.large {
+ width: min(1180px, 100%);
+}
+
+.modal-field-grid {
+ display: grid;
+ gap: 14px;
+ margin-top: 16px;
+}
+
+.compact-grid {
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+}
+
+.modal-field {
+ display: grid;
+ gap: 8px;
+}
+
+.modal-field span {
+ font-size: 0.8rem;
+ color: #6a6f69;
+}
+
+.template-modal-layout {
+ display: grid;
+ gap: 18px;
+ grid-template-columns: minmax(0, 320px) minmax(0, 1fr);
+ margin-top: 16px;
+}
+
+.template-catalog,
+.template-preview-panel {
+ display: grid;
+ gap: 16px;
+}
+
+.template-fetch-row {
+ align-items: center;
+}
+
+.field-error {
+ margin: 0;
+ color: #b91c1c;
+ font-size: 0.88rem;
+}
+
+.template-list {
+ display: grid;
+ gap: 10px;
+ max-height: 520px;
+ overflow: auto;
+ padding-right: 4px;
+}
+
+.template-list-item {
+ padding: 16px;
+ text-align: left;
+}
+
+.template-list-item.active {
+ background: rgba(59, 130, 246, 0.12);
+ border-color: rgba(59, 130, 246, 0.18);
+}
+
+.template-preview-panel > * + * {
+ margin-top: 0;
+}
+
+.template-target-panel {
+ display: grid;
+ gap: 16px;
+}
+
+.modal-actions {
+ justify-content: flex-end;
+ margin-top: 20px;
+}
+
+.onboarding-card.primary-surface {
+ background:
+ radial-gradient(circle at top right, rgba(59, 130, 246, 0.16), transparent 28%),
+ linear-gradient(180deg, rgba(19, 19, 19, 0.96), rgba(17, 17, 17, 0.98));
+ border-color: rgba(255, 255, 255, 0.06);
+}
+
+.onboarding-card.primary-surface p {
+ color: #a8b0bc;
+}
+
+@media (max-width: 1100px) {
+ .labs-shell {
+ grid-template-columns: 72px minmax(240px, 280px) minmax(0, 1fr);
+ }
+
+ .starter-grid,
+ .template-card-grid,
+ .onboarding-grid {
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+ }
+}
+
+@media (max-width: 900px) {
+ .labs-shell {
+ grid-template-columns: 1fr;
+ grid-template-rows: auto auto minmax(0, 1fr);
+ }
+
+ .workspace-rail {
+ flex-direction: row;
+ justify-content: flex-start;
+ min-height: auto;
+ overflow: auto;
+ }
+
+ .workspace-rail-stack {
+ flex-direction: row;
+ justify-content: flex-start;
+ }
+
+ .workspace-add {
+ margin-top: 0;
+ margin-left: auto;
+ }
+
+ .session-sidebar-shell,
+ .thread-shell {
+ min-height: auto;
+ }
+
+ .template-modal-layout {
+ grid-template-columns: 1fr;
+ }
+}
+
+@media (max-width: 640px) {
+ .labs-shell {
+ gap: 14px;
+ padding: 14px;
+ }
+
+ .workspace-rail,
+ .session-sidebar-shell,
+ .thread-shell,
+ .modal-frame {
+ border-radius: 24px;
+ }
+
+ .session-sidebar-shell,
+ .thread-shell,
+ .modal-frame,
+ .starter-surface,
+ .onboarding-card,
+ .template-card,
+ .template-target-panel,
+ .error-banner {
+ padding: 18px;
+ }
+
+ .starter-grid,
+ .template-card-grid,
+ .onboarding-grid,
+ .compact-grid,
+ .template-stat-grid {
+ grid-template-columns: 1fr;
+ }
+
+ .thread-actions,
+ .sidebar-actions,
+ .composer-actions,
+ .modal-actions,
+ .target-toggle-row,
+ .template-fetch-row,
+ .connection-pill-row {
+ flex-direction: column;
+ align-items: stretch;
+ }
+
+ .message-card {
+ max-width: 100%;
+ }
+}
diff --git a/apps/labs/src/templates.ts b/apps/labs/src/templates.ts
new file mode 100644
index 000000000..c02113277
--- /dev/null
+++ b/apps/labs/src/templates.ts
@@ -0,0 +1,463 @@
+import type {
+ LabsBlueprint,
+ LabsBlueprintSessionTemplate,
+ LabsStarter,
+ LabsTemplateProfile,
+ MaterializedSessionBinding,
+ SeedMessage,
+} from "./types";
+
+const DEFAULT_EMPTY_STATE = {
+ title: "What do you want to do?",
+ body: "Pick a starting point or just type below.",
+};
+
+type BundleWorkspace = Record;
+
+function asRecord(value: unknown): Record | null {
+ return value && typeof value === "object" && !Array.isArray(value)
+ ? (value as Record)
+ : null;
+}
+
+function cloneRecord(value: T): T {
+ return JSON.parse(JSON.stringify(value));
+}
+
+function readString(value: unknown) {
+ return typeof value === "string" ? value.trim() : "";
+}
+
+function slugify(value: string) {
+ const compact = value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-");
+ return compact.replace(/^-+|-+$/g, "") || "template";
+}
+
+function normalizeSeedMessage(value: unknown): SeedMessage | null {
+ const record = asRecord(value);
+ if (!record) return null;
+
+ const text = readString(record.text);
+ if (!text) return null;
+
+ return {
+ role: readString(record.role) === "user" ? "user" : "assistant",
+ text,
+ };
+}
+
+function normalizeStarter(value: unknown, index: number): LabsStarter | null {
+ const record = asRecord(value);
+ if (!record) return null;
+
+ const title = readString(record.title);
+ const description = readString(record.description);
+ const kind = readString(record.kind) || "prompt";
+ if (!title) return null;
+
+ return {
+ id: readString(record.id) || `starter-${index + 1}`,
+ kind: kind === "session" || kind === "action" ? kind : "prompt",
+ title,
+ description,
+ prompt: readString(record.prompt) || undefined,
+ action: readString(record.action) || undefined,
+ };
+}
+
+function normalizeBlueprintSession(
+ value: unknown,
+ index: number,
+): LabsBlueprintSessionTemplate | null {
+ const record = asRecord(value);
+ if (!record) return null;
+
+ const title = readString(record.title);
+ const messages = Array.isArray(record.messages)
+ ? record.messages
+ .map(normalizeSeedMessage)
+ .filter((item): item is SeedMessage => Boolean(item))
+ : [];
+
+ if (!title && messages.length === 0) return null;
+
+ return {
+ id: readString(record.id) || `template-session-${index + 1}`,
+ title: title || `Starter session ${index + 1}`,
+ messages,
+ openOnFirstLoad: record.openOnFirstLoad === true,
+ };
+}
+
+function normalizeMaterializedSessions(value: unknown): MaterializedSessionBinding[] {
+ const record = asRecord(value);
+ const sessions = asRecord(record?.sessions);
+ const items = Array.isArray(sessions?.items) ? sessions?.items : [];
+
+ return items
+ .map((item) => {
+ const next = asRecord(item);
+ if (!next) return null;
+ const templateId = readString(next.templateId);
+ const sessionId = readString(next.sessionId);
+ if (!templateId || !sessionId) return null;
+ return { templateId, sessionId } satisfies MaterializedSessionBinding;
+ })
+ .filter((item): item is MaterializedSessionBinding => Boolean(item));
+}
+
+function sanitizeOpenworkConfig(value: unknown) {
+ const record = asRecord(value);
+ if (!record) return null;
+
+ const next = cloneRecord(record);
+ const blueprint = asRecord(next.blueprint);
+ const materialized = asRecord(blueprint?.materialized);
+ if (materialized && "sessions" in materialized) {
+ delete materialized.sessions;
+ }
+ if (blueprint && materialized && Object.keys(materialized).length === 0) {
+ delete blueprint.materialized;
+ }
+ return next;
+}
+
+function normalizeBlueprint(value: unknown, preset: string): LabsBlueprint {
+ const record = asRecord(value);
+ const emptyState = asRecord(record?.emptyState);
+ const starters = Array.isArray(emptyState?.starters)
+ ? emptyState.starters
+ .map(normalizeStarter)
+ .filter((item): item is LabsStarter => Boolean(item))
+ : [];
+ const sessions = Array.isArray(record?.sessions)
+ ? record.sessions
+ .map((item, index) => normalizeBlueprintSession(item, index))
+ .filter((item): item is LabsBlueprintSessionTemplate => Boolean(item))
+ : [];
+
+ return {
+ emptyState: {
+ title: readString(emptyState?.title) || defaultEmptyTitle(preset),
+ body: readString(emptyState?.body) || defaultEmptyBody(preset),
+ starters,
+ },
+ sessions,
+ materialized: normalizeMaterializedSessions(record?.materialized),
+ };
+}
+
+function presetFromWorkspace(workspace: BundleWorkspace | null) {
+ const openwork = asRecord(workspace?.openwork);
+ const workspaceConfig = asRecord(openwork?.workspace);
+ return readString(workspaceConfig?.preset) || "starter";
+}
+
+function defaultEmptyTitle(preset: string) {
+ if (preset === "automation") return "What do you want to automate?";
+ if (preset === "minimal") return "Start with a task";
+ return DEFAULT_EMPTY_STATE.title;
+}
+
+function defaultEmptyBody(preset: string) {
+ if (preset === "automation") {
+ return "Start from a reusable workflow or type your own task below.";
+ }
+ if (preset === "minimal") {
+ return "Ask a question about this workspace or use a starter prompt.";
+ }
+ return DEFAULT_EMPTY_STATE.body;
+}
+
+function describeIncludedItems(workspace: BundleWorkspace | null) {
+ if (!workspace) return [] as string[];
+
+ const skills = Array.isArray(workspace.skills) ? workspace.skills.length : 0;
+ const commands = Array.isArray(workspace.commands) ? workspace.commands.length : 0;
+ const files = Array.isArray(workspace.files) ? workspace.files.length : 0;
+ const hasOpenCodeConfig = Boolean(asRecord(workspace.opencode));
+ const hasOpenWorkConfig = Boolean(asRecord(workspace.openwork));
+
+ return [
+ ...(skills > 0 ? [`${skills} shared skill${skills === 1 ? "" : "s"}`] : []),
+ ...(commands > 0 ? [`${commands} reusable command${commands === 1 ? "" : "s"}`] : []),
+ ...(files > 0 ? [`${files} template file${files === 1 ? "" : "s"}`] : []),
+ ...(hasOpenCodeConfig ? ["Included OpenCode defaults"] : []),
+ ...(hasOpenWorkConfig ? ["Included workspace behavior"] : []),
+ ];
+}
+
+function describeRecommendedDefaults(workspace: BundleWorkspace | null, preset: string) {
+ const openwork = asRecord(workspace?.openwork);
+ const opencode = asRecord(workspace?.opencode);
+ const defaults: string[] = [];
+
+ defaults.push(
+ preset === "automation"
+ ? "Automation-ready workspace posture"
+ : preset === "minimal"
+ ? "Minimal starter workspace posture"
+ : "Starter workspace posture",
+ );
+
+ if (readString(asRecord(opencode)?.model)) {
+ defaults.push("Default model recommendation included");
+ }
+
+ if (Array.isArray(asRecord(openwork?.blueprint)?.sessions)) {
+ defaults.push("Starter chats ready on first load");
+ }
+
+ return Array.from(new Set(defaults));
+}
+
+type WorkspaceProfileBundle = {
+ schemaVersion: number;
+ type: string;
+ name?: string;
+ description?: string;
+ workspace?: BundleWorkspace;
+};
+
+export function profileFromWorkspaceProfileBundle(
+ value: unknown,
+ options: { source: "builtin" | "shared"; sourceUrl?: string | null } = {
+ source: "shared",
+ },
+): LabsTemplateProfile {
+ const record = asRecord(value) as WorkspaceProfileBundle | null;
+ if (!record) {
+ throw new Error("Invalid template bundle.");
+ }
+
+ if (record.schemaVersion !== 1 || record.type !== "workspace-profile") {
+ throw new Error("Only workspace-profile bundles can be used in Labs.");
+ }
+
+ const workspace = asRecord(record.workspace);
+ if (!workspace) {
+ throw new Error("Workspace profile bundle is missing workspace data.");
+ }
+
+ const preset = presetFromWorkspace(workspace);
+ const openwork = sanitizeOpenworkConfig(workspace.openwork);
+ const blueprint = normalizeBlueprint(asRecord(openwork)?.blueprint, preset);
+ const sourceUrl = options.sourceUrl?.trim() || null;
+ const name = readString(record.name) || "Shared workspace template";
+
+ return {
+ id: sourceUrl ? `shared:${sourceUrl}` : `${options.source}:${slugify(name)}`,
+ source: options.source,
+ sourceUrl,
+ dataUrl: sourceUrl,
+ name,
+ description:
+ readString(record.description) ||
+ "Start from a guided workspace with reusable defaults, starter chats, and calm onboarding.",
+ preset,
+ recommendedDefaults: describeRecommendedDefaults(workspace, preset),
+ includedItems: describeIncludedItems(workspace),
+ starterCount: blueprint.emptyState.starters.length,
+ starterSessionCount: blueprint.sessions.length,
+ blueprint,
+ };
+}
+
+export function coerceBundleDataUrl(input: string) {
+ const trimmed = input.trim();
+ if (!trimmed) return "";
+
+ const url = new URL(trimmed);
+ const pathname = url.pathname.replace(/\/+$/, "");
+ if (pathname.endsWith("/data")) {
+ return url.toString();
+ }
+ if (/\/b\/[^/]+$/i.test(pathname)) {
+ url.pathname = `${pathname}/data`;
+ url.search = "";
+ return url.toString();
+ }
+ return url.toString();
+}
+
+export async function fetchTemplateProfile(bundleUrl: string) {
+ const dataUrl = coerceBundleDataUrl(bundleUrl);
+ if (!dataUrl) {
+ throw new Error("Enter a bundle URL to preview a shared template.");
+ }
+
+ const response = await fetch(dataUrl, {
+ headers: {
+ Accept: "application/json",
+ },
+ });
+
+ if (!response.ok) {
+ throw new Error(`Template fetch failed with status ${response.status}.`);
+ }
+
+ const payload = (await response.json()) as WorkspaceProfileBundle;
+ const profile = profileFromWorkspaceProfileBundle(payload, {
+ source: "shared",
+ sourceUrl: dataUrl,
+ });
+
+ return {
+ ...profile,
+ sourceUrl: bundleUrl.trim(),
+ dataUrl,
+ } satisfies LabsTemplateProfile;
+}
+
+export const builtInTemplates: LabsTemplateProfile[] = [
+ {
+ id: "builtin:weekly-client-follow-up",
+ source: "builtin",
+ sourceUrl: null,
+ dataUrl: null,
+ name: "Weekly Client Follow-up",
+ description:
+ "Start from a guided workspace for planning, drafting, and tracking weekly client outreach.",
+ preset: "starter",
+ recommendedDefaults: [
+ "Calm starter copy for non-technical operators",
+ "Seeded follow-up conversations ready on first load",
+ "Reusable outreach prompts already framed",
+ ],
+ includedItems: ["2 starter chats", "3 starter actions", "Follow-up workflow defaults"],
+ starterCount: 3,
+ starterSessionCount: 2,
+ blueprint: {
+ emptyState: {
+ title: "What do you want to send this week?",
+ body: "Start from a follow-up workflow or type your own request.",
+ starters: [
+ {
+ id: "draft-follow-ups",
+ kind: "prompt",
+ title: "Draft this week's follow-ups",
+ description: "Generate first-pass outreach messages with the right tone.",
+ prompt:
+ "Help me draft this week's client follow-ups. Ask who I should prioritize, then propose concise email drafts.",
+ },
+ {
+ id: "review-client-list",
+ kind: "session",
+ title: "Review my client list",
+ description: "Open a guided chat for prioritizing this week's outreach.",
+ prompt:
+ "Help me review this week's client list, group the most important follow-ups, and suggest the strongest next action for each.",
+ },
+ {
+ id: "use-template",
+ kind: "action",
+ title: "Use a shared template",
+ description: "Open the template library and pick another ready-made workspace.",
+ action: "open-template-library",
+ },
+ ],
+ },
+ sessions: [
+ {
+ id: "welcome-client-follow-up",
+ title: "Welcome to Client Follow-ups",
+ openOnFirstLoad: true,
+ messages: [
+ {
+ role: "assistant",
+ text:
+ "Welcome to your weekly client follow-up workspace. I can help you prioritize who needs attention, draft thoughtful messages, and turn loose notes into a clean outreach plan.",
+ },
+ {
+ role: "assistant",
+ text:
+ "Start with the client you care most about, or pick one of the starter actions below to move faster.",
+ },
+ ],
+ },
+ {
+ id: "review-contacts",
+ title: "Review this week's contacts",
+ openOnFirstLoad: false,
+ messages: [
+ {
+ role: "assistant",
+ text:
+ "Paste your client list, CRM export, or rough notes and I will help you group contacts into follow-ups, warm check-ins, and low-priority replies.",
+ },
+ ],
+ },
+ ],
+ materialized: [],
+ },
+ },
+ {
+ id: "builtin:browser-automation-walkthrough",
+ source: "builtin",
+ sourceUrl: null,
+ dataUrl: null,
+ name: "Browser Automation Walkthrough",
+ description:
+ "Give Susan a calmer starting point for browser-based repetitive work without dropping her into tooling details.",
+ preset: "automation",
+ recommendedDefaults: [
+ "Automation-first starter posture",
+ "Browser workflow orientation included",
+ "Session starters already framed as guided tasks",
+ ],
+ includedItems: ["2 starter chats", "2 starter actions", "Automation workspace defaults"],
+ starterCount: 2,
+ starterSessionCount: 2,
+ blueprint: {
+ emptyState: {
+ title: "What should the browser do for you?",
+ body: "Choose a walkthrough or describe the repetitive task in your own words.",
+ starters: [
+ {
+ id: "map-browser-workflow",
+ kind: "prompt",
+ title: "Map the workflow first",
+ description: "Turn a repetitive browser task into a step-by-step automation plan.",
+ prompt:
+ "Help me map a repetitive browser task into a reliable automation. Start by asking what site I use and which steps feel repetitive.",
+ },
+ {
+ id: "start-browser-session",
+ kind: "session",
+ title: "Start the browser walkthrough",
+ description: "Open a guided conversation for browser automation work.",
+ prompt:
+ "Walk me through setting up browser automation for a repetitive task. Keep the explanation simple and focused on what I will see next.",
+ },
+ ],
+ },
+ sessions: [
+ {
+ id: "browser-welcome",
+ title: "Welcome to Browser Automation",
+ openOnFirstLoad: true,
+ messages: [
+ {
+ role: "assistant",
+ text:
+ "This workspace is tuned for browser automation. Tell me what you click through repeatedly and I will help translate it into a cleaner workflow.",
+ },
+ ],
+ },
+ {
+ id: "browser-checklist",
+ title: "Browser task checklist",
+ openOnFirstLoad: false,
+ messages: [
+ {
+ role: "assistant",
+ text:
+ "A good automation checklist has three parts: what page to open, what information to read, and what action should happen next. Share any one of those to begin.",
+ },
+ ],
+ },
+ ],
+ materialized: [],
+ },
+ },
+];
diff --git a/apps/labs/src/types.ts b/apps/labs/src/types.ts
new file mode 100644
index 000000000..11ce896ff
--- /dev/null
+++ b/apps/labs/src/types.ts
@@ -0,0 +1,127 @@
+import type { Message, Part, Session } from "@opencode-ai/sdk/v2/client";
+
+export type WorkspaceConnectionStatus = "connecting" | "connected" | "disconnected";
+export type SessionRunStatus = "idle" | "busy";
+export type TemplateSource = "builtin" | "shared";
+export type StarterKind = "prompt" | "session" | "action";
+export type SeedMessageRole = "assistant" | "user";
+
+export type SeedMessage = {
+ role: SeedMessageRole;
+ text: string;
+};
+
+export type LabsStarter = {
+ id: string;
+ kind: StarterKind;
+ title: string;
+ description: string;
+ prompt?: string;
+ action?: string;
+};
+
+export type LabsBlueprintSessionTemplate = {
+ id: string;
+ title: string;
+ messages: SeedMessage[];
+ openOnFirstLoad: boolean;
+};
+
+export type MaterializedSessionBinding = {
+ templateId: string;
+ sessionId: string;
+};
+
+export type LabsBlueprint = {
+ emptyState: {
+ title: string;
+ body: string;
+ starters: LabsStarter[];
+ };
+ sessions: LabsBlueprintSessionTemplate[];
+ materialized: MaterializedSessionBinding[];
+};
+
+export type LabsTemplateProfile = {
+ id: string;
+ source: TemplateSource;
+ sourceUrl: string | null;
+ dataUrl: string | null;
+ name: string;
+ description: string;
+ preset: string;
+ recommendedDefaults: string[];
+ includedItems: string[];
+ starterCount: number;
+ starterSessionCount: number;
+ blueprint: LabsBlueprint;
+};
+
+export type WorkspaceTemplateBinding = {
+ id: string;
+ source: TemplateSource;
+ sourceUrl: string | null;
+ dataUrl: string | null;
+ name: string;
+ description: string;
+ preset: string;
+ recommendedDefaults: string[];
+ importedAt: number;
+ blueprint: LabsBlueprint;
+};
+
+export type LabsWorkspace = {
+ id: string;
+ name: string;
+ baseUrl: string;
+ token?: string | null;
+ color: string;
+ template?: WorkspaceTemplateBinding | null;
+};
+
+export type MessageWithParts = {
+ info: Message;
+ parts: Part[];
+};
+
+export type ConnectionSnapshot = {
+ status: WorkspaceConnectionStatus;
+ message?: string | null;
+};
+
+export type LabsState = {
+ workspaces: LabsWorkspace[];
+ activeWorkspaceId: string | null;
+ sessionsByWorkspaceId: Record;
+ selectedSessionIdByWorkspaceId: Record;
+ messagesBySessionId: Record;
+ statusBySessionId: Record;
+ connectionByWorkspaceId: Record;
+ seedMessagesBySessionId: Record;
+ loadingMessagesBySessionId: Record;
+ unreadByWorkspaceId: Record;
+ templates: LabsTemplateProfile[];
+ error: string | null;
+};
+
+export type PersistedLabsState = {
+ workspaces: LabsWorkspace[];
+ activeWorkspaceId: string | null;
+ selectedSessionIdByWorkspaceId: Record;
+ seedMessagesBySessionId: Record;
+ templates: LabsTemplateProfile[];
+};
+
+export type NormalizedLabsEvent = {
+ type: string;
+ properties?: unknown;
+};
+
+declare global {
+ interface Window {
+ openworkLabsDesktop?: {
+ isDesktop: boolean;
+ platform: string | null;
+ };
+ }
+}
diff --git a/apps/labs/src/use-labs-app.ts b/apps/labs/src/use-labs-app.ts
new file mode 100644
index 000000000..28c0138aa
--- /dev/null
+++ b/apps/labs/src/use-labs-app.ts
@@ -0,0 +1,1262 @@
+import { useCallback, useEffect, useMemo, useReducer, useRef } from "react";
+import type { Message, Part, Session } from "@opencode-ai/sdk/v2/client";
+
+import {
+ createLabsClient,
+ describeError,
+ normalizeLabsEvent,
+ normalizeOpencodeBaseUrl,
+ unwrap,
+ workspaceNameFromUrl,
+} from "./opencode";
+import type {
+ ConnectionSnapshot,
+ LabsState,
+ LabsTemplateProfile,
+ LabsWorkspace,
+ MessageWithParts,
+ PersistedLabsState,
+ SeedMessage,
+ SessionRunStatus,
+ WorkspaceTemplateBinding,
+} from "./types";
+
+const STORAGE_KEY = "openwork.labs.state.v1";
+const HEALTH_POLL_MS = 20_000;
+const SESSION_LIMIT = 200;
+const WORKSPACE_COLORS = [
+ "#3b82f6",
+ "#f97316",
+ "#14b8a6",
+ "#eab308",
+ "#ef4444",
+ "#8b5cf6",
+ "#22c55e",
+ "#06b6d4",
+];
+
+const isDesktopRuntime = () =>
+ typeof window !== "undefined" && Boolean(window.openworkLabsDesktop?.isDesktop);
+
+type Action =
+ | { type: "app/set-error"; error: string | null }
+ | { type: "workspace/upsert"; workspace: LabsWorkspace }
+ | { type: "workspace/remove"; workspaceId: string }
+ | { type: "workspace/set-active"; workspaceId: string | null }
+ | { type: "workspace/set-connection"; workspaceId: string; connection: ConnectionSnapshot }
+ | { type: "workspace/set-sessions"; workspaceId: string; sessions: Session[] }
+ | { type: "workspace/upsert-session"; workspaceId: string; session: Session }
+ | { type: "workspace/remove-session"; workspaceId: string; sessionId: string }
+ | { type: "workspace/set-selected-session"; workspaceId: string; sessionId: string | null }
+ | { type: "workspace/clear-unread"; workspaceId: string }
+ | { type: "workspace/increment-unread"; workspaceId: string }
+ | {
+ type: "workspace/bind-template";
+ workspaceId: string;
+ template: WorkspaceTemplateBinding;
+ }
+ | {
+ type: "workspace/record-materialized";
+ workspaceId: string;
+ templateId: string;
+ sessionId: string;
+ }
+ | { type: "session/set-loading"; sessionId: string; loading: boolean }
+ | { type: "session/set-status"; sessionId: string; status: SessionRunStatus }
+ | { type: "session/set-messages"; sessionId: string; messages: MessageWithParts[] }
+ | { type: "session/upsert-message"; sessionId: string; message: Message }
+ | { type: "session/remove-message"; sessionId: string; messageId: string }
+ | { type: "session/upsert-part"; sessionId: string; part: Part }
+ | {
+ type: "session/append-part-delta";
+ sessionId: string;
+ messageId: string;
+ partId: string;
+ field: string;
+ delta: string;
+ }
+ | { type: "session/remove-part"; sessionId: string; messageId: string; partId: string }
+ | { type: "session/set-seed-messages"; sessionId: string; messages: SeedMessage[] }
+ | { type: "template/upsert"; template: LabsTemplateProfile };
+
+type WorkspaceInput = {
+ id?: string | null;
+ name?: string | null;
+ baseUrl: string;
+ token?: string | null;
+};
+
+type Controller = {
+ state: LabsState;
+ activeWorkspace: LabsWorkspace | null;
+ activeSessions: Session[];
+ selectedSessionId: string | null;
+ saveWorkspace: (input: WorkspaceInput) => string;
+ removeWorkspace: (workspaceId: string) => void;
+ setActiveWorkspace: (workspaceId: string) => void;
+ selectSession: (workspaceId: string, sessionId: string) => Promise;
+ createSession: (workspaceId: string, options?: { title?: string; seedMessages?: SeedMessage[] }) => Promise;
+ sendPrompt: (workspaceId: string, sessionId: string | null, prompt: string) => Promise;
+ abortSession: (workspaceId: string, sessionId: string | null) => Promise;
+ applyTemplateToWorkspace: (workspaceId: string, template: LabsTemplateProfile) => Promise;
+ clearError: () => void;
+ openTemplateActionForStarter: (workspaceId: string, action: string | undefined) => string | null;
+ refreshWorkspace: (workspaceId: string) => Promise;
+};
+
+type WorkspaceConnectionEntry = {
+ cleanup: () => void;
+ configKey: string;
+};
+
+function randomId() {
+ return typeof crypto !== "undefined" && typeof crypto.randomUUID === "function"
+ ? crypto.randomUUID()
+ : `labs-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
+}
+
+function sessionActivity(session: Session) {
+ return session.time?.updated ?? session.time?.created ?? 0;
+}
+
+function sortSessions(list: Session[] | unknown) {
+ const safeList = Array.isArray(list) ? list : [];
+ return safeList
+ .slice()
+ .sort((left, right) => {
+ const delta = sessionActivity(right) - sessionActivity(left);
+ if (delta !== 0) return delta;
+ return left.id.localeCompare(right.id);
+ });
+}
+
+function upsertSession(list: Session[], next: Session) {
+ const existingIndex = list.findIndex((session) => session.id === next.id);
+ if (existingIndex === -1) return sortSessions([...list, next]);
+ const copy = list.slice();
+ copy[existingIndex] = next;
+ return sortSessions(copy);
+}
+
+function sortMessages(list: MessageWithParts[] | unknown) {
+ const safeList = Array.isArray(list) ? list : [];
+ return safeList
+ .slice()
+ .sort((left, right) => {
+ const delta = (left.info.time?.created ?? 0) - (right.info.time?.created ?? 0);
+ if (delta !== 0) return delta;
+ return left.info.id.localeCompare(right.info.id);
+ });
+}
+
+function upsertMessage(list: MessageWithParts[], next: Message) {
+ const existing = list.find((entry) => entry.info.id === next.id);
+ if (!existing) {
+ return sortMessages([...list, { info: next, parts: [] }]);
+ }
+
+ return list.map((entry) =>
+ entry.info.id === next.id
+ ? {
+ ...entry,
+ info: next,
+ }
+ : entry,
+ );
+}
+
+function removeMessage(list: MessageWithParts[], messageId: string) {
+ return list.filter((entry) => entry.info.id !== messageId);
+}
+
+function upsertPart(list: MessageWithParts[], part: Part) {
+ return list.map((entry) => {
+ if (entry.info.id !== part.messageID) return entry;
+
+ const existingIndex = entry.parts.findIndex((candidate) => candidate.id === part.id);
+ if (existingIndex === -1) {
+ return {
+ ...entry,
+ parts: [...entry.parts, part],
+ };
+ }
+
+ const nextParts = entry.parts.slice();
+ nextParts[existingIndex] = part;
+ return {
+ ...entry,
+ parts: nextParts,
+ };
+ });
+}
+
+function appendPartDelta(
+ list: MessageWithParts[],
+ messageId: string,
+ partId: string,
+ field: string,
+ delta: string,
+) {
+ if (!delta) return list;
+
+ return list.map((entry) => {
+ if (entry.info.id !== messageId) return entry;
+ return {
+ ...entry,
+ parts: entry.parts.map((part) => {
+ if (part.id !== partId) return part;
+
+ const current = (part as Record)[field];
+ const nextValue = `${typeof current === "string" ? current : ""}${delta}`;
+ return {
+ ...(part as Record),
+ [field]: nextValue,
+ } as Part;
+ }),
+ };
+ });
+}
+
+function removePart(list: MessageWithParts[], messageId: string, partId: string) {
+ return list.map((entry) =>
+ entry.info.id === messageId
+ ? {
+ ...entry,
+ parts: entry.parts.filter((part) => part.id !== partId),
+ }
+ : entry,
+ );
+}
+
+function pickWorkspaceColor(seed: string) {
+ const hash = seed.split("").reduce((total, char) => total + char.charCodeAt(0), 0);
+ return WORKSPACE_COLORS[hash % WORKSPACE_COLORS.length];
+}
+
+function createInitialState(): LabsState {
+ if (typeof window === "undefined") {
+ return {
+ workspaces: [],
+ activeWorkspaceId: null,
+ sessionsByWorkspaceId: {},
+ selectedSessionIdByWorkspaceId: {},
+ messagesBySessionId: {},
+ statusBySessionId: {},
+ connectionByWorkspaceId: {},
+ seedMessagesBySessionId: {},
+ loadingMessagesBySessionId: {},
+ unreadByWorkspaceId: {},
+ templates: [],
+ error: null,
+ };
+ }
+
+ try {
+ const raw = window.localStorage.getItem(STORAGE_KEY);
+ const parsed = raw ? (JSON.parse(raw) as Partial) : null;
+ const workspaces = Array.isArray(parsed?.workspaces) ? parsed!.workspaces! : [];
+
+ return {
+ workspaces,
+ activeWorkspaceId: parsed?.activeWorkspaceId ?? workspaces[0]?.id ?? null,
+ sessionsByWorkspaceId: {},
+ selectedSessionIdByWorkspaceId: parsed?.selectedSessionIdByWorkspaceId ?? {},
+ messagesBySessionId: {},
+ statusBySessionId: {},
+ connectionByWorkspaceId: {},
+ seedMessagesBySessionId: parsed?.seedMessagesBySessionId ?? {},
+ loadingMessagesBySessionId: {},
+ unreadByWorkspaceId: {},
+ templates: Array.isArray(parsed?.templates) ? parsed!.templates! : [],
+ error: null,
+ };
+ } catch {
+ return {
+ workspaces: [],
+ activeWorkspaceId: null,
+ sessionsByWorkspaceId: {},
+ selectedSessionIdByWorkspaceId: {},
+ messagesBySessionId: {},
+ statusBySessionId: {},
+ connectionByWorkspaceId: {},
+ seedMessagesBySessionId: {},
+ loadingMessagesBySessionId: {},
+ unreadByWorkspaceId: {},
+ templates: [],
+ error: null,
+ };
+ }
+}
+
+function reducer(state: LabsState, action: Action): LabsState {
+ switch (action.type) {
+ case "app/set-error":
+ return {
+ ...state,
+ error: action.error,
+ };
+
+ case "workspace/upsert": {
+ const existingIndex = state.workspaces.findIndex((workspace) => workspace.id === action.workspace.id);
+ const nextWorkspaces =
+ existingIndex === -1
+ ? [...state.workspaces, action.workspace]
+ : state.workspaces.map((workspace) =>
+ workspace.id === action.workspace.id ? action.workspace : workspace,
+ );
+ return {
+ ...state,
+ workspaces: nextWorkspaces,
+ activeWorkspaceId: state.activeWorkspaceId ?? action.workspace.id,
+ };
+ }
+
+ case "workspace/remove": {
+ const nextWorkspaces = state.workspaces.filter((workspace) => workspace.id !== action.workspaceId);
+ const nextSessionsByWorkspaceId = { ...state.sessionsByWorkspaceId };
+ const removedSessions = nextSessionsByWorkspaceId[action.workspaceId] ?? [];
+ delete nextSessionsByWorkspaceId[action.workspaceId];
+
+ const nextSelectedSessionIdByWorkspaceId = { ...state.selectedSessionIdByWorkspaceId };
+ delete nextSelectedSessionIdByWorkspaceId[action.workspaceId];
+
+ const nextUnreadByWorkspaceId = { ...state.unreadByWorkspaceId };
+ delete nextUnreadByWorkspaceId[action.workspaceId];
+
+ const nextConnectionByWorkspaceId = { ...state.connectionByWorkspaceId };
+ delete nextConnectionByWorkspaceId[action.workspaceId];
+
+ const nextMessagesBySessionId = { ...state.messagesBySessionId };
+ const nextStatusBySessionId = { ...state.statusBySessionId };
+ const nextSeedMessagesBySessionId = { ...state.seedMessagesBySessionId };
+ const nextLoadingMessagesBySessionId = { ...state.loadingMessagesBySessionId };
+ removedSessions.forEach((session) => {
+ delete nextMessagesBySessionId[session.id];
+ delete nextStatusBySessionId[session.id];
+ delete nextSeedMessagesBySessionId[session.id];
+ delete nextLoadingMessagesBySessionId[session.id];
+ });
+
+ return {
+ ...state,
+ workspaces: nextWorkspaces,
+ activeWorkspaceId:
+ state.activeWorkspaceId === action.workspaceId
+ ? nextWorkspaces[0]?.id ?? null
+ : state.activeWorkspaceId,
+ sessionsByWorkspaceId: nextSessionsByWorkspaceId,
+ selectedSessionIdByWorkspaceId: nextSelectedSessionIdByWorkspaceId,
+ messagesBySessionId: nextMessagesBySessionId,
+ statusBySessionId: nextStatusBySessionId,
+ connectionByWorkspaceId: nextConnectionByWorkspaceId,
+ seedMessagesBySessionId: nextSeedMessagesBySessionId,
+ loadingMessagesBySessionId: nextLoadingMessagesBySessionId,
+ unreadByWorkspaceId: nextUnreadByWorkspaceId,
+ };
+ }
+
+ case "workspace/set-active":
+ return {
+ ...state,
+ activeWorkspaceId: action.workspaceId,
+ };
+
+ case "workspace/set-connection":
+ return {
+ ...state,
+ connectionByWorkspaceId: {
+ ...state.connectionByWorkspaceId,
+ [action.workspaceId]: action.connection,
+ },
+ };
+
+ case "workspace/set-sessions":
+ return {
+ ...state,
+ sessionsByWorkspaceId: {
+ ...state.sessionsByWorkspaceId,
+ [action.workspaceId]: sortSessions(action.sessions),
+ },
+ };
+
+ case "workspace/upsert-session":
+ return {
+ ...state,
+ sessionsByWorkspaceId: {
+ ...state.sessionsByWorkspaceId,
+ [action.workspaceId]: upsertSession(
+ state.sessionsByWorkspaceId[action.workspaceId] ?? [],
+ action.session,
+ ),
+ },
+ };
+
+ case "workspace/remove-session": {
+ const nextSessions = (state.sessionsByWorkspaceId[action.workspaceId] ?? []).filter(
+ (session) => session.id !== action.sessionId,
+ );
+ const nextMessages = { ...state.messagesBySessionId };
+ delete nextMessages[action.sessionId];
+
+ const nextStatuses = { ...state.statusBySessionId };
+ delete nextStatuses[action.sessionId];
+
+ const nextSeedMessages = { ...state.seedMessagesBySessionId };
+ delete nextSeedMessages[action.sessionId];
+
+ const nextLoading = { ...state.loadingMessagesBySessionId };
+ delete nextLoading[action.sessionId];
+
+ return {
+ ...state,
+ sessionsByWorkspaceId: {
+ ...state.sessionsByWorkspaceId,
+ [action.workspaceId]: nextSessions,
+ },
+ selectedSessionIdByWorkspaceId: {
+ ...state.selectedSessionIdByWorkspaceId,
+ [action.workspaceId]:
+ state.selectedSessionIdByWorkspaceId[action.workspaceId] === action.sessionId
+ ? nextSessions[0]?.id ?? null
+ : state.selectedSessionIdByWorkspaceId[action.workspaceId] ?? null,
+ },
+ messagesBySessionId: nextMessages,
+ statusBySessionId: nextStatuses,
+ seedMessagesBySessionId: nextSeedMessages,
+ loadingMessagesBySessionId: nextLoading,
+ };
+ }
+
+ case "workspace/set-selected-session":
+ return {
+ ...state,
+ selectedSessionIdByWorkspaceId: {
+ ...state.selectedSessionIdByWorkspaceId,
+ [action.workspaceId]: action.sessionId,
+ },
+ };
+
+ case "workspace/clear-unread":
+ return {
+ ...state,
+ unreadByWorkspaceId: {
+ ...state.unreadByWorkspaceId,
+ [action.workspaceId]: 0,
+ },
+ };
+
+ case "workspace/increment-unread":
+ return {
+ ...state,
+ unreadByWorkspaceId: {
+ ...state.unreadByWorkspaceId,
+ [action.workspaceId]: (state.unreadByWorkspaceId[action.workspaceId] ?? 0) + 1,
+ },
+ };
+
+ case "workspace/bind-template":
+ return {
+ ...state,
+ workspaces: state.workspaces.map((workspace) =>
+ workspace.id === action.workspaceId
+ ? {
+ ...workspace,
+ template: action.template,
+ }
+ : workspace,
+ ),
+ };
+
+ case "workspace/record-materialized":
+ return {
+ ...state,
+ workspaces: state.workspaces.map((workspace) => {
+ if (workspace.id !== action.workspaceId || !workspace.template) return workspace;
+ const existing = workspace.template.blueprint.materialized.find(
+ (item) => item.templateId === action.templateId,
+ );
+ const materialized = existing
+ ? workspace.template.blueprint.materialized.map((item) =>
+ item.templateId === action.templateId
+ ? { templateId: action.templateId, sessionId: action.sessionId }
+ : item,
+ )
+ : [
+ ...workspace.template.blueprint.materialized,
+ { templateId: action.templateId, sessionId: action.sessionId },
+ ];
+ return {
+ ...workspace,
+ template: {
+ ...workspace.template,
+ blueprint: {
+ ...workspace.template.blueprint,
+ materialized,
+ },
+ },
+ };
+ }),
+ };
+
+ case "session/set-loading":
+ return {
+ ...state,
+ loadingMessagesBySessionId: {
+ ...state.loadingMessagesBySessionId,
+ [action.sessionId]: action.loading,
+ },
+ };
+
+ case "session/set-status":
+ return {
+ ...state,
+ statusBySessionId: {
+ ...state.statusBySessionId,
+ [action.sessionId]: action.status,
+ },
+ };
+
+ case "session/set-messages":
+ return {
+ ...state,
+ messagesBySessionId: {
+ ...state.messagesBySessionId,
+ [action.sessionId]: sortMessages(action.messages),
+ },
+ };
+
+ case "session/upsert-message":
+ return {
+ ...state,
+ messagesBySessionId: {
+ ...state.messagesBySessionId,
+ [action.sessionId]: upsertMessage(
+ state.messagesBySessionId[action.sessionId] ?? [],
+ action.message,
+ ),
+ },
+ };
+
+ case "session/remove-message":
+ return {
+ ...state,
+ messagesBySessionId: {
+ ...state.messagesBySessionId,
+ [action.sessionId]: removeMessage(
+ state.messagesBySessionId[action.sessionId] ?? [],
+ action.messageId,
+ ),
+ },
+ };
+
+ case "session/upsert-part":
+ return {
+ ...state,
+ messagesBySessionId: {
+ ...state.messagesBySessionId,
+ [action.sessionId]: upsertPart(
+ state.messagesBySessionId[action.sessionId] ?? [],
+ action.part,
+ ),
+ },
+ };
+
+ case "session/append-part-delta":
+ return {
+ ...state,
+ messagesBySessionId: {
+ ...state.messagesBySessionId,
+ [action.sessionId]: appendPartDelta(
+ state.messagesBySessionId[action.sessionId] ?? [],
+ action.messageId,
+ action.partId,
+ action.field,
+ action.delta,
+ ),
+ },
+ };
+
+ case "session/remove-part":
+ return {
+ ...state,
+ messagesBySessionId: {
+ ...state.messagesBySessionId,
+ [action.sessionId]: removePart(
+ state.messagesBySessionId[action.sessionId] ?? [],
+ action.messageId,
+ action.partId,
+ ),
+ },
+ };
+
+ case "session/set-seed-messages":
+ return {
+ ...state,
+ seedMessagesBySessionId: {
+ ...state.seedMessagesBySessionId,
+ [action.sessionId]: action.messages,
+ },
+ };
+
+ case "template/upsert": {
+ const existingIndex = state.templates.findIndex((template) => template.id === action.template.id);
+ const templates =
+ existingIndex === -1
+ ? [action.template, ...state.templates]
+ : state.templates.map((template) =>
+ template.id === action.template.id ? action.template : template,
+ );
+ return {
+ ...state,
+ templates,
+ };
+ }
+
+ default:
+ return state;
+ }
+}
+
+function persistState(state: LabsState) {
+ if (typeof window === "undefined") return;
+
+ const next: PersistedLabsState = {
+ workspaces: state.workspaces,
+ activeWorkspaceId: state.activeWorkspaceId,
+ selectedSessionIdByWorkspaceId: state.selectedSessionIdByWorkspaceId,
+ seedMessagesBySessionId: state.seedMessagesBySessionId,
+ templates: state.templates,
+ };
+
+ try {
+ window.localStorage.setItem(STORAGE_KEY, JSON.stringify(next));
+ } catch {
+ // Ignore storage failures.
+ }
+}
+
+export function useLabsApp(): Controller {
+ const [state, dispatch] = useReducer(reducer, undefined, createInitialState);
+ const stateRef = useRef(state);
+ const clientsRef = useRef(new Map>());
+ const connectionsRef = useRef(new Map());
+ const activeWorkspaceIdRef = useRef(state.activeWorkspaceId);
+
+ useEffect(() => {
+ stateRef.current = state;
+ activeWorkspaceIdRef.current = state.activeWorkspaceId;
+ persistState(state);
+ }, [state]);
+
+ const getWorkspace = useCallback((workspaceId: string) => {
+ return stateRef.current.workspaces.find((workspace) => workspace.id === workspaceId) ?? null;
+ }, []);
+
+ const getClient = useCallback((workspaceId: string) => {
+ return clientsRef.current.get(workspaceId) ?? null;
+ }, []);
+
+ const loadSessionMessages = useCallback(async (workspaceId: string, sessionId: string) => {
+ const client = getClient(workspaceId);
+ if (!client) return;
+
+ dispatch({ type: "session/set-loading", sessionId, loading: true });
+
+ try {
+ const messages = unwrap(
+ await client.session.messages({ sessionID: sessionId, limit: SESSION_LIMIT }),
+ );
+ dispatch({ type: "session/set-messages", sessionId, messages });
+ } catch (error) {
+ dispatch({ type: "app/set-error", error: describeError(error) });
+ } finally {
+ dispatch({ type: "session/set-loading", sessionId, loading: false });
+ }
+ }, [getClient]);
+
+ const loadWorkspaceSessions = useCallback(async (workspaceId: string) => {
+ const client = getClient(workspaceId);
+ if (!client) return;
+
+ try {
+ const sessions = unwrap(
+ await client.session.list({ roots: false, limit: SESSION_LIMIT }),
+ );
+ dispatch({ type: "workspace/set-sessions", workspaceId, sessions });
+
+ const current = stateRef.current.selectedSessionIdByWorkspaceId[workspaceId] ?? null;
+ const nextSelected = current || sessions[0]?.id || null;
+ if (nextSelected) {
+ dispatch({
+ type: "workspace/set-selected-session",
+ workspaceId,
+ sessionId: nextSelected,
+ });
+
+ if (stateRef.current.activeWorkspaceId === workspaceId) {
+ await loadSessionMessages(workspaceId, nextSelected);
+ }
+ }
+ } catch (error) {
+ dispatch({
+ type: "workspace/set-connection",
+ workspaceId,
+ connection: {
+ status: "disconnected",
+ message: describeError(error),
+ },
+ });
+ }
+ }, [getClient, loadSessionMessages]);
+
+ const refreshWorkspace = useCallback(async (workspaceId: string) => {
+ const client = getClient(workspaceId);
+ if (!client) return;
+
+ dispatch({
+ type: "workspace/set-connection",
+ workspaceId,
+ connection: {
+ status: "connecting",
+ message: "Checking server status...",
+ },
+ });
+
+ try {
+ const health = unwrap<{ healthy?: boolean }>(await client.global.health());
+ if (health?.healthy === false) {
+ throw new Error("Server reported unhealthy state.");
+ }
+
+ dispatch({
+ type: "workspace/set-connection",
+ workspaceId,
+ connection: {
+ status: "connected",
+ message: "Connected",
+ },
+ });
+ await loadWorkspaceSessions(workspaceId);
+ } catch (error) {
+ dispatch({
+ type: "workspace/set-connection",
+ workspaceId,
+ connection: {
+ status: "disconnected",
+ message: describeError(error),
+ },
+ });
+ }
+ }, [getClient, loadWorkspaceSessions]);
+
+ const handleEvent = useCallback((workspaceId: string, event: { type: string; properties?: unknown }) => {
+ if (event.type === "session.updated" || event.type === "session.created") {
+ const info = (event.properties as { info?: Session } | undefined)?.info;
+ if (info?.id) {
+ dispatch({ type: "workspace/upsert-session", workspaceId, session: info });
+ }
+ return;
+ }
+
+ if (event.type === "session.deleted") {
+ const info = (event.properties as { info?: Session } | undefined)?.info;
+ if (info?.id) {
+ dispatch({ type: "workspace/remove-session", workspaceId, sessionId: info.id });
+ }
+ return;
+ }
+
+ if (event.type === "session.status" || event.type === "session.idle") {
+ const sessionId =
+ event.type === "session.idle"
+ ? (event.properties as { sessionID?: string } | undefined)?.sessionID
+ : (event.properties as { sessionID?: string } | undefined)?.sessionID;
+ if (sessionId) {
+ dispatch({
+ type: "session/set-status",
+ sessionId,
+ status:
+ event.type === "session.idle" ||
+ (event.properties as { status?: string } | undefined)?.status === "idle"
+ ? "idle"
+ : "busy",
+ });
+ }
+ return;
+ }
+
+ if (event.type === "message.updated") {
+ const message = (event.properties as { info?: Message } | undefined)?.info;
+ if (!message?.id || !message.sessionID) return;
+
+ dispatch({ type: "session/upsert-message", sessionId: message.sessionID, message });
+
+ const current = stateRef.current;
+ if (
+ message.role === "assistant" &&
+ (current.activeWorkspaceId !== workspaceId ||
+ current.selectedSessionIdByWorkspaceId[workspaceId] !== message.sessionID)
+ ) {
+ dispatch({ type: "workspace/increment-unread", workspaceId });
+ }
+ return;
+ }
+
+ if (event.type === "message.removed") {
+ const properties = event.properties as { sessionID?: string; messageID?: string } | undefined;
+ if (properties?.sessionID && properties.messageID) {
+ dispatch({
+ type: "session/remove-message",
+ sessionId: properties.sessionID,
+ messageId: properties.messageID,
+ });
+ }
+ return;
+ }
+
+ if (event.type === "message.part.updated") {
+ const part = (event.properties as { part?: Part } | undefined)?.part;
+ if (part?.id && part.sessionID && part.messageID) {
+ dispatch({ type: "session/upsert-part", sessionId: part.sessionID, part });
+ }
+ return;
+ }
+
+ if (event.type === "message.part.delta") {
+ const properties = event.properties as
+ | {
+ sessionID?: string;
+ messageID?: string;
+ partID?: string;
+ field?: string;
+ delta?: string;
+ }
+ | undefined;
+ if (
+ properties?.sessionID &&
+ properties.messageID &&
+ properties.partID &&
+ properties.field &&
+ typeof properties.delta === "string"
+ ) {
+ dispatch({
+ type: "session/append-part-delta",
+ sessionId: properties.sessionID,
+ messageId: properties.messageID,
+ partId: properties.partID,
+ field: properties.field,
+ delta: properties.delta,
+ });
+ }
+ return;
+ }
+
+ if (event.type === "message.part.removed") {
+ const properties = event.properties as
+ | {
+ sessionID?: string;
+ messageID?: string;
+ partID?: string;
+ }
+ | undefined;
+ if (properties?.sessionID && properties.messageID && properties.partID) {
+ dispatch({
+ type: "session/remove-part",
+ sessionId: properties.sessionID,
+ messageId: properties.messageID,
+ partId: properties.partID,
+ });
+ }
+ }
+ }, []);
+
+ const connectWorkspace = useCallback((workspace: LabsWorkspace) => {
+ if (!isDesktopRuntime()) {
+ dispatch({
+ type: "workspace/set-connection",
+ workspaceId: workspace.id,
+ connection: {
+ status: "disconnected",
+ message: "Web preview is visual-only. Use the Electron app for live connections.",
+ },
+ });
+ return;
+ }
+
+ const normalizedBaseUrl = normalizeOpencodeBaseUrl(workspace.baseUrl);
+ const configKey = `${normalizedBaseUrl}::${workspace.token?.trim() ?? ""}`;
+ const existing = connectionsRef.current.get(workspace.id);
+ if (existing && existing.configKey === configKey) {
+ return;
+ }
+
+ existing?.cleanup();
+ connectionsRef.current.delete(workspace.id);
+ clientsRef.current.delete(workspace.id);
+
+ if (!normalizedBaseUrl) {
+ dispatch({
+ type: "workspace/set-connection",
+ workspaceId: workspace.id,
+ connection: {
+ status: "disconnected",
+ message: "Enter a valid server URL.",
+ },
+ });
+ return;
+ }
+
+ const client = createLabsClient({
+ ...workspace,
+ baseUrl: normalizedBaseUrl,
+ });
+ clientsRef.current.set(workspace.id, client);
+
+ dispatch({
+ type: "workspace/set-connection",
+ workspaceId: workspace.id,
+ connection: {
+ status: "connecting",
+ message: "Connecting...",
+ },
+ });
+
+ const controller = new AbortController();
+ let healthTimer = 0;
+ let cancelled = false;
+
+ const runHealthCheck = async () => {
+ if (cancelled) return;
+ await refreshWorkspace(workspace.id);
+ };
+
+ void runHealthCheck();
+ healthTimer = window.setInterval(() => {
+ void runHealthCheck();
+ }, HEALTH_POLL_MS);
+
+ void (async () => {
+ let reconnectDelay = 1_000;
+ while (!controller.signal.aborted) {
+ try {
+ const subscription = await client.event.subscribe(undefined, { signal: controller.signal });
+ reconnectDelay = 1_000;
+ for await (const raw of subscription.stream) {
+ if (controller.signal.aborted) return;
+ const event = normalizeLabsEvent(raw);
+ if (event) handleEvent(workspace.id, event);
+ }
+ } catch (error) {
+ if (controller.signal.aborted) return;
+ dispatch({
+ type: "workspace/set-connection",
+ workspaceId: workspace.id,
+ connection: {
+ status: "disconnected",
+ message: describeError(error),
+ },
+ });
+ await new Promise((resolve) => setTimeout(resolve, reconnectDelay));
+ reconnectDelay = Math.min(reconnectDelay * 2, 8_000);
+ }
+ }
+ })();
+
+ connectionsRef.current.set(workspace.id, {
+ configKey,
+ cleanup: () => {
+ cancelled = true;
+ controller.abort();
+ window.clearInterval(healthTimer);
+ },
+ });
+ }, [handleEvent, refreshWorkspace]);
+
+ useEffect(() => {
+ const nextIds = new Set(state.workspaces.map((workspace) => workspace.id));
+
+ for (const [workspaceId, entry] of connectionsRef.current.entries()) {
+ if (!nextIds.has(workspaceId)) {
+ entry.cleanup();
+ connectionsRef.current.delete(workspaceId);
+ clientsRef.current.delete(workspaceId);
+ }
+ }
+
+ state.workspaces.forEach((workspace) => connectWorkspace(workspace));
+
+ return () => {
+ for (const entry of connectionsRef.current.values()) {
+ entry.cleanup();
+ }
+ connectionsRef.current.clear();
+ clientsRef.current.clear();
+ };
+ }, [connectWorkspace, state.workspaces]);
+
+ useEffect(() => {
+ const workspaceId = state.activeWorkspaceId;
+ if (!workspaceId) return;
+
+ dispatch({ type: "workspace/clear-unread", workspaceId });
+
+ const selectedSessionId =
+ state.selectedSessionIdByWorkspaceId[workspaceId] ?? state.sessionsByWorkspaceId[workspaceId]?.[0]?.id ?? null;
+ if (!selectedSessionId) return;
+
+ if (!state.messagesBySessionId[selectedSessionId] && !state.loadingMessagesBySessionId[selectedSessionId]) {
+ void loadSessionMessages(workspaceId, selectedSessionId);
+ }
+ }, [
+ loadSessionMessages,
+ state.activeWorkspaceId,
+ state.loadingMessagesBySessionId,
+ state.messagesBySessionId,
+ state.selectedSessionIdByWorkspaceId,
+ state.sessionsByWorkspaceId,
+ ]);
+
+ const saveWorkspace = useCallback((input: WorkspaceInput) => {
+ const normalizedBaseUrl = normalizeOpencodeBaseUrl(input.baseUrl);
+ const name = input.name?.trim() || workspaceNameFromUrl(normalizedBaseUrl) || "Untitled workspace";
+ const id = input.id?.trim() || `workspace-${randomId()}`;
+ const existing = stateRef.current.workspaces.find((workspace) => workspace.id === id) ?? null;
+
+ const workspace: LabsWorkspace = {
+ id,
+ name,
+ baseUrl: normalizedBaseUrl,
+ token: input.token?.trim() || null,
+ color: existing?.color ?? pickWorkspaceColor(id),
+ template: existing?.template ?? null,
+ };
+
+ dispatch({ type: "workspace/upsert", workspace });
+ dispatch({ type: "workspace/set-active", workspaceId: id });
+ return id;
+ }, []);
+
+ const removeWorkspace = useCallback((workspaceId: string) => {
+ const existing = connectionsRef.current.get(workspaceId);
+ existing?.cleanup();
+ connectionsRef.current.delete(workspaceId);
+ clientsRef.current.delete(workspaceId);
+ dispatch({ type: "workspace/remove", workspaceId });
+ }, []);
+
+ const setActiveWorkspace = useCallback((workspaceId: string) => {
+ dispatch({ type: "workspace/set-active", workspaceId });
+ }, []);
+
+ const selectSession = useCallback(async (workspaceId: string, sessionId: string) => {
+ dispatch({ type: "workspace/set-selected-session", workspaceId, sessionId });
+ dispatch({ type: "workspace/clear-unread", workspaceId });
+ await loadSessionMessages(workspaceId, sessionId);
+ }, [loadSessionMessages]);
+
+ const createSession = useCallback(async (
+ workspaceId: string,
+ options?: { title?: string; seedMessages?: SeedMessage[] },
+ ) => {
+ const client = getClient(workspaceId);
+ if (!client) {
+ dispatch({ type: "app/set-error", error: "Add a valid workspace URL before creating a chat." });
+ return null;
+ }
+
+ try {
+ const created = unwrap(await client.session.create({}));
+ let session = created;
+ const nextTitle = options?.title?.trim();
+ if (nextTitle) {
+ try {
+ session = unwrap(await client.session.update({ sessionID: created.id, title: nextTitle }));
+ } catch {
+ session = {
+ ...created,
+ title: nextTitle,
+ } as Session;
+ }
+ }
+
+ dispatch({ type: "workspace/upsert-session", workspaceId, session });
+ dispatch({ type: "workspace/set-selected-session", workspaceId, sessionId: session.id });
+ dispatch({ type: "workspace/set-active", workspaceId });
+ dispatch({ type: "session/set-messages", sessionId: session.id, messages: [] });
+
+ if (options?.seedMessages?.length) {
+ dispatch({
+ type: "session/set-seed-messages",
+ sessionId: session.id,
+ messages: options.seedMessages,
+ });
+ }
+
+ return session.id;
+ } catch (error) {
+ dispatch({ type: "app/set-error", error: describeError(error) });
+ return null;
+ }
+ }, [getClient]);
+
+ const sendPrompt = useCallback(async (
+ workspaceId: string,
+ sessionId: string | null,
+ prompt: string,
+ ) => {
+ const trimmed = prompt.trim();
+ if (!trimmed) return sessionId;
+
+ const client = getClient(workspaceId);
+ if (!client) {
+ dispatch({ type: "app/set-error", error: "Connect a workspace before sending a prompt." });
+ return null;
+ }
+
+ let resolvedSessionId = sessionId;
+ if (!resolvedSessionId) {
+ resolvedSessionId = await createSession(workspaceId);
+ }
+ if (!resolvedSessionId) return null;
+
+ dispatch({ type: "session/set-status", sessionId: resolvedSessionId, status: "busy" });
+
+ try {
+ await unwrap(
+ await client.session.promptAsync({
+ sessionID: resolvedSessionId,
+ parts: [{ type: "text", text: trimmed }],
+ }),
+ );
+ return resolvedSessionId;
+ } catch (error) {
+ dispatch({ type: "session/set-status", sessionId: resolvedSessionId, status: "idle" });
+ dispatch({ type: "app/set-error", error: describeError(error) });
+ return null;
+ }
+ }, [createSession, getClient]);
+
+ const abortSession = useCallback(async (workspaceId: string, sessionId: string | null) => {
+ if (!sessionId) return;
+ const client = getClient(workspaceId);
+ if (!client) return;
+
+ try {
+ await client.session.abort({ sessionID: sessionId });
+ dispatch({ type: "session/set-status", sessionId, status: "idle" });
+ } catch (error) {
+ dispatch({ type: "app/set-error", error: describeError(error) });
+ }
+ }, [getClient]);
+
+ const applyTemplateToWorkspace = useCallback(async (workspaceId: string, template: LabsTemplateProfile) => {
+ dispatch({ type: "template/upsert", template });
+
+ const binding: WorkspaceTemplateBinding = {
+ id: template.id,
+ source: template.source,
+ sourceUrl: template.sourceUrl,
+ dataUrl: template.dataUrl,
+ name: template.name,
+ description: template.description,
+ preset: template.preset,
+ recommendedDefaults: template.recommendedDefaults,
+ importedAt: Date.now(),
+ blueprint: {
+ ...template.blueprint,
+ materialized: [],
+ },
+ };
+
+ dispatch({
+ type: "workspace/bind-template",
+ workspaceId,
+ template: binding,
+ });
+
+ const client = getClient(workspaceId);
+ if (!client) {
+ dispatch({
+ type: "app/set-error",
+ error: "Template saved. Connect the workspace to materialize the starter chats.",
+ });
+ return;
+ }
+
+ const existingWorkspace = getWorkspace(workspaceId);
+ const existingMaterialized = existingWorkspace?.template?.blueprint.materialized ?? [];
+ const createdOrExisting: Array<{ templateId: string; sessionId: string }> = [];
+
+ for (const templateSession of template.blueprint.sessions) {
+ const existing = existingMaterialized.find((item) => item.templateId === templateSession.id);
+ if (existing) {
+ createdOrExisting.push(existing);
+ continue;
+ }
+
+ const sessionId = await createSession(workspaceId, {
+ title: templateSession.title,
+ seedMessages: templateSession.messages,
+ });
+ if (!sessionId) continue;
+
+ dispatch({
+ type: "workspace/record-materialized",
+ workspaceId,
+ templateId: templateSession.id,
+ sessionId,
+ });
+ createdOrExisting.push({ templateId: templateSession.id, sessionId });
+ }
+
+ const preferredTemplate =
+ template.blueprint.sessions.find((session) => session.openOnFirstLoad) ??
+ template.blueprint.sessions[0] ??
+ null;
+
+ if (preferredTemplate) {
+ const preferred = createdOrExisting.find((item) => item.templateId === preferredTemplate.id);
+ if (preferred) {
+ await selectSession(workspaceId, preferred.sessionId);
+ }
+ }
+ }, [createSession, getClient, getWorkspace, selectSession]);
+
+ const clearError = useCallback(() => {
+ dispatch({ type: "app/set-error", error: null });
+ }, []);
+
+ const openTemplateActionForStarter = useCallback(
+ (_workspaceId: string, action: string | undefined) => {
+ if (!action) return null;
+ if (action === "open-template-library") return "template-library";
+ return null;
+ },
+ [],
+ );
+
+ const activeWorkspace = useMemo(
+ () => state.workspaces.find((workspace) => workspace.id === state.activeWorkspaceId) ?? null,
+ [state.activeWorkspaceId, state.workspaces],
+ );
+
+ return {
+ state,
+ activeWorkspace,
+ activeSessions: activeWorkspace ? state.sessionsByWorkspaceId[activeWorkspace.id] ?? [] : [],
+ selectedSessionId: activeWorkspace
+ ? state.selectedSessionIdByWorkspaceId[activeWorkspace.id] ?? null
+ : null,
+ saveWorkspace,
+ removeWorkspace,
+ setActiveWorkspace,
+ selectSession,
+ createSession,
+ sendPrompt,
+ abortSession,
+ applyTemplateToWorkspace,
+ clearError,
+ openTemplateActionForStarter,
+ refreshWorkspace,
+ };
+}
diff --git a/apps/labs/tsconfig.json b/apps/labs/tsconfig.json
new file mode 100644
index 000000000..2957d0dfd
--- /dev/null
+++ b/apps/labs/tsconfig.json
@@ -0,0 +1,17 @@
+{
+ "compilerOptions": {
+ "target": "ES2022",
+ "useDefineForClassFields": true,
+ "module": "ESNext",
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
+ "jsx": "react-jsx",
+ "moduleResolution": "Bundler",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+ "strict": true,
+ "skipLibCheck": true,
+ "types": ["vite/client"]
+ },
+ "include": ["src", "vite.config.ts"]
+}
diff --git a/apps/labs/vite.config.ts b/apps/labs/vite.config.ts
new file mode 100644
index 000000000..9760f3bb3
--- /dev/null
+++ b/apps/labs/vite.config.ts
@@ -0,0 +1,19 @@
+import { defineConfig } from "vite";
+import react from "@vitejs/plugin-react";
+
+export default defineConfig({
+ plugins: [react()],
+ server: {
+ host: "0.0.0.0",
+ port: 3340,
+ strictPort: true,
+ },
+ preview: {
+ host: "0.0.0.0",
+ port: 3340,
+ strictPort: true,
+ },
+ build: {
+ target: "es2022",
+ },
+});
diff --git a/package.json b/package.json
index d14d067f2..984ef542f 100644
--- a/package.json
+++ b/package.json
@@ -4,6 +4,7 @@
"version": "0.0.0",
"scripts": {
"dev": "OPENWORK_DEV_MODE=1 pnpm --filter @openwork/desktop dev",
+ "dev:labs": "pnpm --filter @openwork/labs dev",
"dev:windows": ".\\scripts\\dev-windows.cmd",
"dev:windows:x64": ".\\scripts\\dev-windows.cmd x64",
"dev:ui": "OPENWORK_DEV_MODE=1 pnpm --filter @openwork/app dev",
@@ -15,10 +16,13 @@
"dev:den-docker": "bash packaging/docker/den-dev-up.sh",
"dev:headless-web": "OPENWORK_DEV_MODE=1 bun scripts/dev-headless-web.ts",
"build": "node scripts/build.mjs",
+ "build:labs": "pnpm --filter @openwork/labs build",
"build:ui": "pnpm --filter @openwork/app build",
"build:web": "pnpm --filter @openwork-ee/den-web build",
"preview": "pnpm --filter @openwork/app preview",
+ "preview:labs": "pnpm --filter @openwork/labs preview",
"typecheck": "pnpm --filter @openwork/app typecheck",
+ "typecheck:labs": "pnpm --filter @openwork/labs typecheck",
"test:health": "pnpm --filter @openwork/app test:health",
"test:sessions": "pnpm --filter @openwork/app test:sessions",
"test:refactor": "pnpm --filter @openwork/app test:refactor",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 8f6ef8ed4..9850c43a9 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -114,6 +114,46 @@ importers:
specifier: ^2.0.0
version: 2.9.6
+ apps/labs:
+ dependencies:
+ '@opencode-ai/sdk':
+ specifier: ^1.1.31
+ version: 1.1.39
+ '@tanstack/react-virtual':
+ specifier: ^3.13.23
+ version: 3.13.23(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
+ react:
+ specifier: 19.2.4
+ version: 19.2.4
+ react-dom:
+ specifier: 19.2.4
+ version: 19.2.4(react@19.2.4)
+ streamdown:
+ specifier: ^2.5.0
+ version: 2.5.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
+ devDependencies:
+ '@types/node':
+ specifier: ^25.4.0
+ version: 25.4.0
+ '@types/react':
+ specifier: 19.2.14
+ version: 19.2.14
+ '@types/react-dom':
+ specifier: 19.2.3
+ version: 19.2.3(@types/react@19.2.14)
+ '@vitejs/plugin-react':
+ specifier: ^5.0.4
+ version: 5.2.0(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2))
+ electron:
+ specifier: ^41.1.1
+ version: 41.1.1
+ typescript:
+ specifier: ^5.9.3
+ version: 5.9.3
+ vite:
+ specifier: ^7.1.12
+ version: 7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2)
+
apps/opencode-router:
dependencies:
'@opencode-ai/sdk':
@@ -629,6 +669,9 @@ packages:
resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
engines: {node: '>=6.0.0'}
+ '@antfu/install-pkg@1.1.0':
+ resolution: {integrity: sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==}
+
'@aws-crypto/crc32@5.2.0':
resolution: {integrity: sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==}
engines: {node: '>=16.0.0'}
@@ -989,6 +1032,24 @@ packages:
'@better-fetch/fetch@1.1.21':
resolution: {integrity: sha512-/ImESw0sskqlVR94jB+5+Pxjf+xBwDZF/N5+y2/q4EqD7IARUTSpPfIo8uf39SYpCxyOCtbyYpUrZ3F/k0zT4A==}
+ '@braintree/sanitize-url@7.1.2':
+ resolution: {integrity: sha512-jigsZK+sMF/cuiB7sERuo9V7N9jx+dhmHHnQyDSVdpZwVutaBu7WvNYqMDLSgFgfB30n452TP3vjDAvFC973mA==}
+
+ '@chevrotain/cst-dts-gen@11.1.2':
+ resolution: {integrity: sha512-XTsjvDVB5nDZBQB8o0o/0ozNelQtn2KrUVteIHSlPd2VAV2utEb6JzyCJaJ8tGxACR4RiBNWy5uYUHX2eji88Q==}
+
+ '@chevrotain/gast@11.1.2':
+ resolution: {integrity: sha512-Z9zfXR5jNZb1Hlsd/p+4XWeUFugrHirq36bKzPWDSIacV+GPSVXdk+ahVWZTwjhNwofAWg/sZg58fyucKSQx5g==}
+
+ '@chevrotain/regexp-to-ast@11.1.2':
+ resolution: {integrity: sha512-nMU3Uj8naWer7xpZTYJdxbAs6RIv/dxYzkYU8GSwgUtcAAlzjcPfX1w+RKRcYG8POlzMeayOQ/znfwxEGo5ulw==}
+
+ '@chevrotain/types@11.1.2':
+ resolution: {integrity: sha512-U+HFai5+zmJCkK86QsaJtoITlboZHBqrVketcO2ROv865xfCMSFpELQoz1GkX5GzME8pTa+3kbKrZHQtI0gdbw==}
+
+ '@chevrotain/utils@11.1.2':
+ resolution: {integrity: sha512-4mudFAQ6H+MqBTfqLmU7G1ZwRzCLfJEooL/fsF6rCX5eePMbGhoy5n4g+G4vlh2muDcsCTJtL+uKbOzWxs5LHA==}
+
'@codemirror/autocomplete@6.20.0':
resolution: {integrity: sha512-bOwvTOIJcG5FVo5gUUupiwYh8MioPLQ4UcqbcRf7UQ98X90tCa9E1kZ3Z7tqwpZxYyOvh1YTYbmZE9RTfTp5hg==}
@@ -1034,6 +1095,10 @@ packages:
'@drizzle-team/brocli@0.10.2':
resolution: {integrity: sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w==}
+ '@electron/get@2.0.3':
+ resolution: {integrity: sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==}
+ engines: {node: '>=12'}
+
'@emnapi/runtime@1.8.1':
resolution: {integrity: sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==}
@@ -1520,6 +1585,12 @@ packages:
'@iarna/toml@2.2.5':
resolution: {integrity: sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==}
+ '@iconify/types@2.0.0':
+ resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==}
+
+ '@iconify/utils@3.1.0':
+ resolution: {integrity: sha512-Zlzem1ZXhI1iHeeERabLNzBHdOa4VhQbqAcOQaMKuTuyZCpwKbC2R4Dd0Zo3g9EAc+Y4fiarO8HIHRAth7+skw==}
+
'@img/colour@1.1.0':
resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==}
engines: {node: '>=18'}
@@ -1824,6 +1895,9 @@ packages:
'@marijn/find-cluster-break@1.0.2':
resolution: {integrity: sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==}
+ '@mermaid-js/parser@1.1.0':
+ resolution: {integrity: sha512-gxK9ZX2+Fex5zu8LhRQoMeMPEHbc73UKZ0FQ54YrQtUxE1VVhMwzeNtKRPAu5aXks4FasbMe4xB4bWrmq6Jlxw==}
+
'@next/env@14.2.5':
resolution: {integrity: sha512-/zZGkrTOsraVfYjGP8uM0p6r0BDT6xWpkjdVbcz66PJVSpwXX3yNiRycxAuDfBKGWBrZBXRuK/YVlkNgxHGwmA==}
@@ -2417,6 +2491,10 @@ packages:
cpu: [x64]
os: [win32]
+ '@sindresorhus/is@4.6.0':
+ resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==}
+ engines: {node: '>=10'}
+
'@slack/logger@4.0.0':
resolution: {integrity: sha512-Wz7QYfPAlG/DR+DfABddUZeNgoeY7d1J39OCR2jR+v7VBsB8ezulDK5szTnDDPDwLH5IWhLvXIHlCFZV7MSKgA==}
engines: {node: '>= 18', npm: '>= 8.6.0'}
@@ -2688,6 +2766,10 @@ packages:
'@swc/helpers@0.5.5':
resolution: {integrity: sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==}
+ '@szmarczak/http-timer@4.0.6':
+ resolution: {integrity: sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==}
+ engines: {node: '>=10'}
+
'@tailwindcss/node@4.1.18':
resolution: {integrity: sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ==}
@@ -2778,6 +2860,12 @@ packages:
peerDependencies:
vite: ^5.2.0 || ^6 || ^7
+ '@tanstack/react-virtual@3.13.23':
+ resolution: {integrity: sha512-XnMRnHQ23piOVj2bzJqHrRrLg4r+F86fuBcwteKfbIjJrtGxb4z7tIvPVAe4B+4UVwo9G4Giuz5fmapcrnZ0OQ==}
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+ react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+
'@tanstack/solid-virtual@3.13.19':
resolution: {integrity: sha512-4uCuwY/nfQzoxuJCOroEGgRQkoDuzRE4wVdDq47InQ9WPQ+1dkBUyE7k7frcTPy+l1yjCCmLGdq9h9GQyofVHw==}
peerDependencies:
@@ -2786,6 +2874,9 @@ packages:
'@tanstack/virtual-core@3.13.19':
resolution: {integrity: sha512-/BMP7kNhzKOd7wnDeB8NrIRNLwkf5AhCYCvtfZV2GXWbBieFm/el0n6LOAXlTi6ZwHICSNnQcIxRCWHrLzDY+g==}
+ '@tanstack/virtual-core@3.13.23':
+ resolution: {integrity: sha512-zSz2Z2HNyLjCplANTDyl3BcdQJc2k1+yyFoKhNRmCr7V7dY8o8q5m8uFTI1/Pg1kL+Hgrz6u3Xo6eFUB7l66cg==}
+
'@tauri-apps/api@2.10.1':
resolution: {integrity: sha512-hKL/jWf293UDSUN09rR69hrToyIXBb8CjGaWC7gfinvnQrBVvnLr08FeFi38gxtugAVyVcTa5/FD/Xnkb1siBw==}
@@ -2923,12 +3014,132 @@ packages:
'@types/babel__traverse@7.28.0':
resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==}
+ '@types/cacheable-request@6.0.3':
+ resolution: {integrity: sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==}
+
+ '@types/d3-array@3.2.2':
+ resolution: {integrity: sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==}
+
+ '@types/d3-axis@3.0.6':
+ resolution: {integrity: sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==}
+
+ '@types/d3-brush@3.0.6':
+ resolution: {integrity: sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==}
+
+ '@types/d3-chord@3.0.6':
+ resolution: {integrity: sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==}
+
+ '@types/d3-color@3.1.3':
+ resolution: {integrity: sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==}
+
+ '@types/d3-contour@3.0.6':
+ resolution: {integrity: sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==}
+
+ '@types/d3-delaunay@6.0.4':
+ resolution: {integrity: sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==}
+
+ '@types/d3-dispatch@3.0.7':
+ resolution: {integrity: sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA==}
+
+ '@types/d3-drag@3.0.7':
+ resolution: {integrity: sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==}
+
+ '@types/d3-dsv@3.0.7':
+ resolution: {integrity: sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==}
+
+ '@types/d3-ease@3.0.2':
+ resolution: {integrity: sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==}
+
+ '@types/d3-fetch@3.0.7':
+ resolution: {integrity: sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==}
+
+ '@types/d3-force@3.0.10':
+ resolution: {integrity: sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==}
+
+ '@types/d3-format@3.0.4':
+ resolution: {integrity: sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==}
+
+ '@types/d3-geo@3.1.0':
+ resolution: {integrity: sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==}
+
+ '@types/d3-hierarchy@3.1.7':
+ resolution: {integrity: sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==}
+
+ '@types/d3-interpolate@3.0.4':
+ resolution: {integrity: sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==}
+
+ '@types/d3-path@3.1.1':
+ resolution: {integrity: sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==}
+
+ '@types/d3-polygon@3.0.2':
+ resolution: {integrity: sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==}
+
+ '@types/d3-quadtree@3.0.6':
+ resolution: {integrity: sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==}
+
+ '@types/d3-random@3.0.3':
+ resolution: {integrity: sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==}
+
+ '@types/d3-scale-chromatic@3.1.0':
+ resolution: {integrity: sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==}
+
+ '@types/d3-scale@4.0.9':
+ resolution: {integrity: sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==}
+
+ '@types/d3-selection@3.0.11':
+ resolution: {integrity: sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==}
+
+ '@types/d3-shape@3.1.8':
+ resolution: {integrity: sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==}
+
+ '@types/d3-time-format@4.0.3':
+ resolution: {integrity: sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==}
+
+ '@types/d3-time@3.0.4':
+ resolution: {integrity: sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==}
+
+ '@types/d3-timer@3.0.2':
+ resolution: {integrity: sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==}
+
+ '@types/d3-transition@3.0.9':
+ resolution: {integrity: sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==}
+
+ '@types/d3-zoom@3.0.8':
+ resolution: {integrity: sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==}
+
+ '@types/d3@7.4.3':
+ resolution: {integrity: sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==}
+
+ '@types/debug@4.1.13':
+ resolution: {integrity: sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==}
+
+ '@types/estree-jsx@1.0.5':
+ resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==}
+
'@types/estree@1.0.8':
resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
+ '@types/geojson@7946.0.16':
+ resolution: {integrity: sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==}
+
+ '@types/hast@3.0.4':
+ resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==}
+
+ '@types/http-cache-semantics@4.2.0':
+ resolution: {integrity: sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==}
+
+ '@types/keyv@3.1.4':
+ resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==}
+
+ '@types/mdast@4.0.4':
+ resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==}
+
'@types/minimatch@5.1.2':
resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==}
+ '@types/ms@2.1.0':
+ resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==}
+
'@types/node@16.9.1':
resolution: {integrity: sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==}
@@ -2938,6 +3149,9 @@ packages:
'@types/node@22.19.7':
resolution: {integrity: sha512-MciR4AKGHWl7xwxkBa6xUGxQJ4VBOmPTF7sL+iGzuahOFaO0jHCsuEfS80pan1ef4gWId1oWOweIhrDEYLuaOw==}
+ '@types/node@24.12.0':
+ resolution: {integrity: sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ==}
+
'@types/node@25.4.0':
resolution: {integrity: sha512-9wLpoeWuBlcbBpOY3XmzSTG3oscB6xjBEEtn+pYXTfhyXhIxC5FsBer2KTopBlvKEiW9l13po9fq+SJY/5lkhw==}
@@ -2958,12 +3172,33 @@ packages:
'@types/react@19.2.14':
resolution: {integrity: sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==}
+ '@types/responselike@1.0.3':
+ resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==}
+
'@types/retry@0.12.0':
resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==}
+ '@types/trusted-types@2.0.7':
+ resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==}
+
+ '@types/unist@2.0.11':
+ resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==}
+
+ '@types/unist@3.0.3':
+ resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==}
+
'@types/ws@8.18.1':
resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==}
+ '@types/yauzl@2.10.3':
+ resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==}
+
+ '@ungap/structured-clone@1.3.0':
+ resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==}
+
+ '@upsetjs/venn.js@2.0.0':
+ resolution: {integrity: sha512-WbBhLrooyePuQ1VZxrJjtLvTc4NVfpOyKx0sKqioq9bX1C1m7Jgykkn8gLrtwumBioXIqam8DLxp88Adbue6Hw==}
+
'@vercel/blob@0.27.3':
resolution: {integrity: sha512-WizeAxzOTmv0JL7wOaxvLIU/KdBcrclM1ZUOdSlIZAxsTTTe1jsyBthStLby0Ueh7FnmKYAjLz26qRJTk5SDkQ==}
engines: {node: '>=16.14'}
@@ -3057,6 +3292,9 @@ packages:
solid-js:
optional: true
+ bail@2.0.2:
+ resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==}
+
balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
@@ -3149,6 +3387,10 @@ packages:
bmp-ts@1.0.9:
resolution: {integrity: sha512-cTEHk2jLrPyi+12M3dhpEbnnPOsaZuq7C45ylbbQIiWgDFZq4UVYPEY5mlqjvsj/6gJv9qX5sa+ebDzLXT28Vw==}
+ boolean@3.2.0:
+ resolution: {integrity: sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==}
+ deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
+
botid@1.5.11:
resolution: {integrity: sha512-KOO1A3+/vFVJk5aFoG3sNwiogKFPVR+x4aw4gQ1b2e0XoE+i5xp48/EZn+WqR07jRHeDGwHWQUOtV5WVm7xiww==}
peerDependencies:
@@ -3175,6 +3417,9 @@ packages:
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true
+ buffer-crc32@0.2.13:
+ resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==}
+
buffer-from@1.1.2:
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
@@ -3229,6 +3474,14 @@ packages:
resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
engines: {node: '>=8'}
+ cacheable-lookup@5.0.4:
+ resolution: {integrity: sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==}
+ engines: {node: '>=10.6.0'}
+
+ cacheable-request@7.0.4:
+ resolution: {integrity: sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==}
+ engines: {node: '>=8'}
+
call-bind-apply-helpers@1.0.2:
resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
engines: {node: '>= 0.4'}
@@ -3240,6 +3493,29 @@ packages:
caniuse-lite@1.0.30001764:
resolution: {integrity: sha512-9JGuzl2M+vPL+pz70gtMF9sHdMFbY9FJaQBi186cHKH3pSzDvzoUJUPV6fqiKIMyXbud9ZLg4F3Yza1vJ1+93g==}
+ ccount@2.0.1:
+ resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==}
+
+ character-entities-html4@2.1.0:
+ resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==}
+
+ character-entities-legacy@3.0.0:
+ resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==}
+
+ character-entities@2.0.2:
+ resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==}
+
+ character-reference-invalid@2.0.1:
+ resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==}
+
+ chevrotain-allstar@0.3.1:
+ resolution: {integrity: sha512-b7g+y9A0v4mxCW1qUhf3BSVPg+/NvGErk/dOkrDaHA0nQIQGAtrOjlX//9OQtRlSCy+x9rfB5N8yC71lH1nvMw==}
+ peerDependencies:
+ chevrotain: ^11.0.0
+
+ chevrotain@11.1.2:
+ resolution: {integrity: sha512-opLQzEVriiH1uUQ4Kctsd49bRoFDXGGSC4GUqj7pGyxM3RehRhvTlZJc1FL/Flew2p5uwxa1tUDWKzI4wNM8pg==}
+
chokidar@3.6.0:
resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
engines: {node: '>= 8.10.0'}
@@ -3262,6 +3538,13 @@ packages:
resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
engines: {node: '>=12'}
+ clone-response@1.0.3:
+ resolution: {integrity: sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==}
+
+ clsx@2.1.1:
+ resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==}
+ engines: {node: '>=6'}
+
color-convert@2.0.1:
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
engines: {node: '>=7.0.0'}
@@ -3273,6 +3556,9 @@ packages:
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
engines: {node: '>= 0.8'}
+ comma-separated-tokens@2.0.3:
+ resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==}
+
commander@12.1.0:
resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==}
engines: {node: '>=18'}
@@ -3281,6 +3567,14 @@ packages:
resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
engines: {node: '>= 6'}
+ commander@7.2.0:
+ resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==}
+ engines: {node: '>= 10'}
+
+ commander@8.3.0:
+ resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==}
+ engines: {node: '>= 12'}
+
confbox@0.1.8:
resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==}
@@ -3291,6 +3585,12 @@ packages:
convert-source-map@2.0.0:
resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
+ cose-base@1.0.3:
+ resolution: {integrity: sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==}
+
+ cose-base@2.2.0:
+ resolution: {integrity: sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==}
+
crelt@1.0.6:
resolution: {integrity: sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==}
@@ -3302,6 +3602,165 @@ packages:
csstype@3.2.3:
resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
+ cytoscape-cose-bilkent@4.1.0:
+ resolution: {integrity: sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==}
+ peerDependencies:
+ cytoscape: ^3.2.0
+
+ cytoscape-fcose@2.2.0:
+ resolution: {integrity: sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==}
+ peerDependencies:
+ cytoscape: ^3.2.0
+
+ cytoscape@3.33.1:
+ resolution: {integrity: sha512-iJc4TwyANnOGR1OmWhsS9ayRS3s+XQ185FmuHObThD+5AeJCakAAbWv8KimMTt08xCCLNgneQwFp+JRJOr9qGQ==}
+ engines: {node: '>=0.10'}
+
+ d3-array@2.12.1:
+ resolution: {integrity: sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==}
+
+ d3-array@3.2.4:
+ resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==}
+ engines: {node: '>=12'}
+
+ d3-axis@3.0.0:
+ resolution: {integrity: sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==}
+ engines: {node: '>=12'}
+
+ d3-brush@3.0.0:
+ resolution: {integrity: sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==}
+ engines: {node: '>=12'}
+
+ d3-chord@3.0.1:
+ resolution: {integrity: sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==}
+ engines: {node: '>=12'}
+
+ d3-color@3.1.0:
+ resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==}
+ engines: {node: '>=12'}
+
+ d3-contour@4.0.2:
+ resolution: {integrity: sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==}
+ engines: {node: '>=12'}
+
+ d3-delaunay@6.0.4:
+ resolution: {integrity: sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==}
+ engines: {node: '>=12'}
+
+ d3-dispatch@3.0.1:
+ resolution: {integrity: sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==}
+ engines: {node: '>=12'}
+
+ d3-drag@3.0.0:
+ resolution: {integrity: sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==}
+ engines: {node: '>=12'}
+
+ d3-dsv@3.0.1:
+ resolution: {integrity: sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==}
+ engines: {node: '>=12'}
+ hasBin: true
+
+ d3-ease@3.0.1:
+ resolution: {integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==}
+ engines: {node: '>=12'}
+
+ d3-fetch@3.0.1:
+ resolution: {integrity: sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==}
+ engines: {node: '>=12'}
+
+ d3-force@3.0.0:
+ resolution: {integrity: sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==}
+ engines: {node: '>=12'}
+
+ d3-format@3.1.2:
+ resolution: {integrity: sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==}
+ engines: {node: '>=12'}
+
+ d3-geo@3.1.1:
+ resolution: {integrity: sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==}
+ engines: {node: '>=12'}
+
+ d3-hierarchy@3.1.2:
+ resolution: {integrity: sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==}
+ engines: {node: '>=12'}
+
+ d3-interpolate@3.0.1:
+ resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==}
+ engines: {node: '>=12'}
+
+ d3-path@1.0.9:
+ resolution: {integrity: sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==}
+
+ d3-path@3.1.0:
+ resolution: {integrity: sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==}
+ engines: {node: '>=12'}
+
+ d3-polygon@3.0.1:
+ resolution: {integrity: sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==}
+ engines: {node: '>=12'}
+
+ d3-quadtree@3.0.1:
+ resolution: {integrity: sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==}
+ engines: {node: '>=12'}
+
+ d3-random@3.0.1:
+ resolution: {integrity: sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==}
+ engines: {node: '>=12'}
+
+ d3-sankey@0.12.3:
+ resolution: {integrity: sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==}
+
+ d3-scale-chromatic@3.1.0:
+ resolution: {integrity: sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==}
+ engines: {node: '>=12'}
+
+ d3-scale@4.0.2:
+ resolution: {integrity: sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==}
+ engines: {node: '>=12'}
+
+ d3-selection@3.0.0:
+ resolution: {integrity: sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==}
+ engines: {node: '>=12'}
+
+ d3-shape@1.3.7:
+ resolution: {integrity: sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==}
+
+ d3-shape@3.2.0:
+ resolution: {integrity: sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==}
+ engines: {node: '>=12'}
+
+ d3-time-format@4.1.0:
+ resolution: {integrity: sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==}
+ engines: {node: '>=12'}
+
+ d3-time@3.1.0:
+ resolution: {integrity: sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==}
+ engines: {node: '>=12'}
+
+ d3-timer@3.0.1:
+ resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==}
+ engines: {node: '>=12'}
+
+ d3-transition@3.0.1:
+ resolution: {integrity: sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==}
+ engines: {node: '>=12'}
+ peerDependencies:
+ d3-selection: 2 - 3
+
+ d3-zoom@3.0.0:
+ resolution: {integrity: sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==}
+ engines: {node: '>=12'}
+
+ d3@7.9.0:
+ resolution: {integrity: sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==}
+ engines: {node: '>=12'}
+
+ dagre-d3-es@7.0.14:
+ resolution: {integrity: sha512-P4rFMVq9ESWqmOgK+dlXvOtLwYg0i7u0HBGJER0LZDJT2VHIPAMZ/riPxqJceWMStH5+E61QxFra9kIS3AqdMg==}
+
+ dayjs@1.11.20:
+ resolution: {integrity: sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ==}
+
debug@4.4.3:
resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
engines: {node: '>=6.0'}
@@ -3311,9 +3770,31 @@ packages:
supports-color:
optional: true
+ decode-named-character-reference@1.3.0:
+ resolution: {integrity: sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==}
+
+ decompress-response@6.0.0:
+ resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==}
+ engines: {node: '>=10'}
+
+ defer-to-connect@2.0.1:
+ resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==}
+ engines: {node: '>=10'}
+
+ define-data-property@1.1.4:
+ resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==}
+ engines: {node: '>= 0.4'}
+
+ define-properties@1.2.1:
+ resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==}
+ engines: {node: '>= 0.4'}
+
defu@6.1.4:
resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==}
+ delaunator@5.1.0:
+ resolution: {integrity: sha512-AGrQ4QSgssa1NGmWmLPqN5NY2KajF5MqxetNEO+o0n3ZwZZeTmt7bBnvzHWrmkZFxGgr4HdyFgelzgi06otLuQ==}
+
delayed-stream@1.0.0:
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
engines: {node: '>=0.4.0'}
@@ -3322,10 +3803,20 @@ packages:
resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==}
engines: {node: '>=0.10'}
+ dequal@2.0.3:
+ resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
+ engines: {node: '>=6'}
+
detect-libc@2.1.2:
resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
engines: {node: '>=8'}
+ detect-node@2.1.0:
+ resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==}
+
+ devlop@1.1.0:
+ resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==}
+
didyoumean@1.2.2:
resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==}
@@ -3336,6 +3827,9 @@ packages:
dlv@1.1.3:
resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==}
+ dompurify@3.3.3:
+ resolution: {integrity: sha512-Oj6pzI2+RqBfFG+qOaOLbFXLQ90ARpcGG6UePL82bJLtdsa6CYJD7nmiU8MW9nQNOtCHV3lZ/Bzq1X0QYbBZCA==}
+
dotenv@16.6.1:
resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==}
engines: {node: '>=12'}
@@ -3447,9 +3941,17 @@ packages:
electron-to-chromium@1.5.267:
resolution: {integrity: sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==}
+ electron@41.1.1:
+ resolution: {integrity: sha512-8bgvDhBjli+3Z2YCKgzzoBPh6391pr7Xv2h/tTJG4ETgvPvUxZomObbZLs31mUzYb6VrlcDDd9cyWyNKtPm3tA==}
+ engines: {node: '>= 12.20.55'}
+ hasBin: true
+
emoji-regex@8.0.0:
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
+ end-of-stream@1.4.5:
+ resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==}
+
enhanced-resolve@5.18.4:
resolution: {integrity: sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==}
engines: {node: '>=10.13.0'}
@@ -3458,6 +3960,10 @@ packages:
resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==}
engines: {node: '>=0.12'}
+ env-paths@2.2.1:
+ resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==}
+ engines: {node: '>=6'}
+
es-define-property@1.0.1:
resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==}
engines: {node: '>= 0.4'}
@@ -3474,6 +3980,9 @@ packages:
resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==}
engines: {node: '>= 0.4'}
+ es6-error@4.1.1:
+ resolution: {integrity: sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==}
+
esbuild-register@3.6.0:
resolution: {integrity: sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==}
peerDependencies:
@@ -3498,6 +4007,17 @@ packages:
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
engines: {node: '>=6'}
+ escape-string-regexp@4.0.0:
+ resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
+ engines: {node: '>=10'}
+
+ escape-string-regexp@5.0.0:
+ resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==}
+ engines: {node: '>=12'}
+
+ estree-util-is-identifier-name@3.0.0:
+ resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==}
+
event-target-shim@5.0.1:
resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==}
engines: {node: '>=6'}
@@ -3519,6 +4039,14 @@ packages:
resolution: {integrity: sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==}
engines: {node: '>=0.10.0'}
+ extend@3.0.2:
+ resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
+
+ extract-zip@2.0.1:
+ resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==}
+ engines: {node: '>= 10.17.0'}
+ hasBin: true
+
fast-glob@3.3.3:
resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==}
engines: {node: '>=8.6.0'}
@@ -3533,6 +4061,9 @@ packages:
fastq@1.20.1:
resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==}
+ fd-slicer@1.1.0:
+ resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==}
+
fdir@6.5.0:
resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
engines: {node: '>=12.0.0'}
@@ -3593,6 +4124,10 @@ packages:
react-dom:
optional: true
+ fs-extra@8.1.0:
+ resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==}
+ engines: {node: '>=6 <7 || >=8'}
+
fs.realpath@1.0.0:
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
@@ -3631,6 +4166,10 @@ packages:
resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==}
engines: {node: '>= 0.4'}
+ get-stream@5.2.0:
+ resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==}
+ engines: {node: '>=8'}
+
get-tsconfig@4.13.1:
resolution: {integrity: sha512-EoY1N2xCn44xU6750Sx7OjOIT59FkmstNc3X6y5xpz7D5cBtZRe/3pSlTkDJgqsOk3WwZPkWfonhhUJfttQo3w==}
@@ -3650,10 +4189,22 @@ packages:
engines: {node: '>=16 || 14 >=14.17'}
deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me
+ global-agent@3.0.0:
+ resolution: {integrity: sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==}
+ engines: {node: '>=10.0'}
+
+ globalthis@1.0.4:
+ resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==}
+ engines: {node: '>= 0.4'}
+
gopd@1.2.0:
resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
engines: {node: '>= 0.4'}
+ got@11.8.6:
+ resolution: {integrity: sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==}
+ engines: {node: '>=10.19.0'}
+
graceful-fs@4.2.11:
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
@@ -3661,6 +4212,12 @@ packages:
resolution: {integrity: sha512-7arRRoOtOh9UwMwANZ475kJrWV6P3/EGNooeHlY0/SwZv4t3ZZ3Uiz9cAXK8Zg9xSdgmm8T21kx6n7SZaWvOcw==}
engines: {node: ^12.20.0 || >=14.13.1}
+ hachure-fill@0.5.2:
+ resolution: {integrity: sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==}
+
+ has-property-descriptors@1.0.2:
+ resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==}
+
has-symbols@1.1.0:
resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==}
engines: {node: '>= 0.4'}
@@ -3673,6 +4230,30 @@ packages:
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
engines: {node: '>= 0.4'}
+ hast-util-from-parse5@8.0.3:
+ resolution: {integrity: sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==}
+
+ hast-util-parse-selector@4.0.0:
+ resolution: {integrity: sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==}
+
+ hast-util-raw@9.1.0:
+ resolution: {integrity: sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw==}
+
+ hast-util-sanitize@5.0.2:
+ resolution: {integrity: sha512-3yTWghByc50aGS7JlGhk61SPenfE/p1oaFeNwkOOyrscaOkMGrcW9+Cy/QAIOBpZxP1yqDIzFMR0+Np0i0+usg==}
+
+ hast-util-to-jsx-runtime@2.3.6:
+ resolution: {integrity: sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==}
+
+ hast-util-to-parse5@8.0.1:
+ resolution: {integrity: sha512-MlWT6Pjt4CG9lFCjiz4BH7l9wmrMkfkJYCxFwKQic8+RTZgWPuWxwAfjJElsXkex7DJjfSJsQIt931ilUgmwdA==}
+
+ hast-util-whitespace@3.0.0:
+ resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==}
+
+ hastscript@9.0.1:
+ resolution: {integrity: sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==}
+
homedir-polyfill@1.0.3:
resolution: {integrity: sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==}
engines: {node: '>=0.10.0'}
@@ -3684,6 +4265,23 @@ packages:
html-entities@2.3.3:
resolution: {integrity: sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==}
+ html-url-attributes@3.0.1:
+ resolution: {integrity: sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==}
+
+ html-void-elements@3.0.0:
+ resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==}
+
+ http-cache-semantics@4.2.0:
+ resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==}
+
+ http2-wrapper@1.0.3:
+ resolution: {integrity: sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==}
+ engines: {node: '>=10.19.0'}
+
+ iconv-lite@0.6.3:
+ resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
+ engines: {node: '>=0.10.0'}
+
iconv-lite@0.7.2:
resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==}
engines: {node: '>=0.10.0'}
@@ -3700,6 +4298,22 @@ packages:
inherits@2.0.4:
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
+ inline-style-parser@0.2.7:
+ resolution: {integrity: sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==}
+
+ internmap@1.0.1:
+ resolution: {integrity: sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==}
+
+ internmap@2.0.3:
+ resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==}
+ engines: {node: '>=12'}
+
+ is-alphabetical@2.0.1:
+ resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==}
+
+ is-alphanumerical@2.0.1:
+ resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==}
+
is-binary-path@2.1.0:
resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
engines: {node: '>=8'}
@@ -3712,6 +4326,9 @@ packages:
resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==}
engines: {node: '>= 0.4'}
+ is-decimal@2.0.1:
+ resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==}
+
is-electron@2.2.2:
resolution: {integrity: sha512-FO/Rhvz5tuw4MCWkpMzHFKWD2LsfHzIb7i6MdPYZ/KW7AlxawyLkqdy+jPZP1WubqEADE3O4FUENlJHDfQASRg==}
@@ -3727,6 +4344,9 @@ packages:
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
engines: {node: '>=0.10.0'}
+ is-hexadecimal@2.0.1:
+ resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==}
+
is-node-process@1.2.0:
resolution: {integrity: sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==}
@@ -3734,6 +4354,10 @@ packages:
resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
engines: {node: '>=0.12.0'}
+ is-plain-obj@4.1.0:
+ resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==}
+ engines: {node: '>=12'}
+
is-property@1.0.2:
resolution: {integrity: sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==}
@@ -3780,6 +4404,12 @@ packages:
engines: {node: '>=6'}
hasBin: true
+ json-buffer@3.0.1:
+ resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
+
+ json-stringify-safe@5.0.1:
+ resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==}
+
json5@2.2.3:
resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
engines: {node: '>=6'}
@@ -3788,10 +4418,33 @@ packages:
jsonc-parser@3.3.1:
resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==}
+ jsonfile@4.0.0:
+ resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==}
+
+ katex@0.16.44:
+ resolution: {integrity: sha512-EkxoDTk8ufHqHlf9QxGwcxeLkWRR3iOuYfRpfORgYfqc8s13bgb+YtRY59NK5ZpRaCwq1kqA6a5lpX8C/eLphQ==}
+ hasBin: true
+
+ keyv@4.5.4:
+ resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
+
+ khroma@2.1.0:
+ resolution: {integrity: sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==}
+
kysely@0.28.11:
resolution: {integrity: sha512-zpGIFg0HuoC893rIjYX1BETkVWdDnzTzF5e0kWXJFg5lE0k1/LfNWBejrcnOFu8Q2Rfq/hTDTU7XLUM8QOrpzg==}
engines: {node: '>=20.0.0'}
+ langium@4.2.1:
+ resolution: {integrity: sha512-zu9QWmjpzJcomzdJQAHgDVhLGq5bLosVak1KVa40NzQHXfqr4eAHupvnPOVXEoLkg6Ocefvf/93d//SB7du4YQ==}
+ engines: {node: '>=20.10.0', npm: '>=10.2.3'}
+
+ layout-base@1.0.2:
+ resolution: {integrity: sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==}
+
+ layout-base@2.0.1:
+ resolution: {integrity: sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==}
+
lightningcss-android-arm64@1.30.2:
resolution: {integrity: sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==}
engines: {node: '>= 12.0.0'}
@@ -3881,16 +4534,29 @@ packages:
resolution: {integrity: sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==}
engines: {node: '>=6'}
+ lodash-es@4.17.23:
+ resolution: {integrity: sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==}
+
+ lodash-es@4.18.1:
+ resolution: {integrity: sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==}
+
lodash.camelcase@4.3.0:
resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==}
long@5.3.2:
resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==}
+ longest-streak@3.1.0:
+ resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==}
+
loose-envify@1.4.0:
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
hasBin: true
+ lowercase-keys@2.0.0:
+ resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==}
+ engines: {node: '>=8'}
+
lru-cache@10.4.3:
resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
@@ -3914,15 +4580,72 @@ packages:
magic-string@0.30.21:
resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
+ markdown-table@3.0.4:
+ resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==}
+
+ marked@16.4.2:
+ resolution: {integrity: sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA==}
+ engines: {node: '>= 20'}
+ hasBin: true
+
marked@17.0.1:
resolution: {integrity: sha512-boeBdiS0ghpWcSwoNm/jJBwdpFaMnZWRzjA6SkUMYb40SVaN1x7mmfGKp0jvexGcx+7y2La5zRZsYFZI6Qpypg==}
engines: {node: '>= 20'}
hasBin: true
+ matcher@3.0.0:
+ resolution: {integrity: sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==}
+ engines: {node: '>=10'}
+
math-intrinsics@1.1.0:
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
engines: {node: '>= 0.4'}
+ mdast-util-find-and-replace@3.0.2:
+ resolution: {integrity: sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==}
+
+ mdast-util-from-markdown@2.0.3:
+ resolution: {integrity: sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==}
+
+ mdast-util-gfm-autolink-literal@2.0.1:
+ resolution: {integrity: sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==}
+
+ mdast-util-gfm-footnote@2.1.0:
+ resolution: {integrity: sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==}
+
+ mdast-util-gfm-strikethrough@2.0.0:
+ resolution: {integrity: sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==}
+
+ mdast-util-gfm-table@2.0.0:
+ resolution: {integrity: sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==}
+
+ mdast-util-gfm-task-list-item@2.0.0:
+ resolution: {integrity: sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==}
+
+ mdast-util-gfm@3.1.0:
+ resolution: {integrity: sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==}
+
+ mdast-util-mdx-expression@2.0.1:
+ resolution: {integrity: sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==}
+
+ mdast-util-mdx-jsx@3.2.0:
+ resolution: {integrity: sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==}
+
+ mdast-util-mdxjs-esm@2.0.1:
+ resolution: {integrity: sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==}
+
+ mdast-util-phrasing@4.1.0:
+ resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==}
+
+ mdast-util-to-hast@13.2.1:
+ resolution: {integrity: sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==}
+
+ mdast-util-to-markdown@2.1.2:
+ resolution: {integrity: sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==}
+
+ mdast-util-to-string@4.0.0:
+ resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==}
+
merge-anything@5.1.7:
resolution: {integrity: sha512-eRtbOb1N5iyH0tkQDAoQ4Ipsp/5qSR79Dzrz8hEPxRX10RWWR/iQXdoKmBSRCThY1Fh5EhISDtpSc93fpxUniQ==}
engines: {node: '>=12.13'}
@@ -3931,6 +4654,93 @@ packages:
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
engines: {node: '>= 8'}
+ mermaid@11.14.0:
+ resolution: {integrity: sha512-GSGloRsBs+JINmmhl0JDwjpuezCsHB4WGI4NASHxL3fHo3o/BRXTxhDLKnln8/Q0lRFRyDdEjmk1/d5Sn1Xz8g==}
+
+ micromark-core-commonmark@2.0.3:
+ resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==}
+
+ micromark-extension-gfm-autolink-literal@2.1.0:
+ resolution: {integrity: sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==}
+
+ micromark-extension-gfm-footnote@2.1.0:
+ resolution: {integrity: sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==}
+
+ micromark-extension-gfm-strikethrough@2.1.0:
+ resolution: {integrity: sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==}
+
+ micromark-extension-gfm-table@2.1.1:
+ resolution: {integrity: sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==}
+
+ micromark-extension-gfm-tagfilter@2.0.0:
+ resolution: {integrity: sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==}
+
+ micromark-extension-gfm-task-list-item@2.1.0:
+ resolution: {integrity: sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==}
+
+ micromark-extension-gfm@3.0.0:
+ resolution: {integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==}
+
+ micromark-factory-destination@2.0.1:
+ resolution: {integrity: sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==}
+
+ micromark-factory-label@2.0.1:
+ resolution: {integrity: sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==}
+
+ micromark-factory-space@2.0.1:
+ resolution: {integrity: sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==}
+
+ micromark-factory-title@2.0.1:
+ resolution: {integrity: sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==}
+
+ micromark-factory-whitespace@2.0.1:
+ resolution: {integrity: sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==}
+
+ micromark-util-character@2.1.1:
+ resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==}
+
+ micromark-util-chunked@2.0.1:
+ resolution: {integrity: sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==}
+
+ micromark-util-classify-character@2.0.1:
+ resolution: {integrity: sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==}
+
+ micromark-util-combine-extensions@2.0.1:
+ resolution: {integrity: sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==}
+
+ micromark-util-decode-numeric-character-reference@2.0.2:
+ resolution: {integrity: sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==}
+
+ micromark-util-decode-string@2.0.1:
+ resolution: {integrity: sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==}
+
+ micromark-util-encode@2.0.1:
+ resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==}
+
+ micromark-util-html-tag-name@2.0.1:
+ resolution: {integrity: sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==}
+
+ micromark-util-normalize-identifier@2.0.1:
+ resolution: {integrity: sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==}
+
+ micromark-util-resolve-all@2.0.1:
+ resolution: {integrity: sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==}
+
+ micromark-util-sanitize-uri@2.0.1:
+ resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==}
+
+ micromark-util-subtokenize@2.1.0:
+ resolution: {integrity: sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==}
+
+ micromark-util-symbol@2.0.1:
+ resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==}
+
+ micromark-util-types@2.0.2:
+ resolution: {integrity: sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==}
+
+ micromark@4.0.2:
+ resolution: {integrity: sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==}
+
micromatch@4.0.8:
resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
engines: {node: '>=8.6'}
@@ -3948,6 +4758,14 @@ packages:
engines: {node: '>=10.0.0'}
hasBin: true
+ mimic-response@1.0.1:
+ resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==}
+ engines: {node: '>=4'}
+
+ mimic-response@3.1.0:
+ resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==}
+ engines: {node: '>=10'}
+
minimatch@10.1.1:
resolution: {integrity: sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==}
engines: {node: 20 || >=22}
@@ -4084,6 +4902,10 @@ packages:
resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==}
engines: {node: '>=0.10.0'}
+ normalize-url@6.1.0:
+ resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==}
+ engines: {node: '>=10'}
+
object-assign@4.1.1:
resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
engines: {node: '>=0.10.0'}
@@ -4092,6 +4914,10 @@ packages:
resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==}
engines: {node: '>= 6'}
+ object-keys@1.1.1:
+ resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==}
+ engines: {node: '>= 0.4'}
+
omggif@1.0.10:
resolution: {integrity: sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==}
@@ -4099,6 +4925,13 @@ packages:
resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==}
engines: {node: '>=14.0.0'}
+ once@1.4.0:
+ resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
+
+ p-cancelable@2.1.1:
+ resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==}
+ engines: {node: '>=8'}
+
p-finally@1.0.0:
resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==}
engines: {node: '>=4'}
@@ -4127,6 +4960,9 @@ packages:
resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
engines: {node: '>=6'}
+ package-manager-detector@1.6.0:
+ resolution: {integrity: sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==}
+
pako@1.0.11:
resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==}
@@ -4139,6 +4975,9 @@ packages:
parse-bmfont-xml@1.1.6:
resolution: {integrity: sha512-0cEliVMZEhrFDwMh4SxIyVJpqYoOWDJ9P895tFuS+XuNzI5UBmBk5U5O4KuJdTnZpSBI4LFA2+ZiJaiwfSwlMA==}
+ parse-entities@4.0.2:
+ resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==}
+
parse-passwd@1.0.0:
resolution: {integrity: sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==}
engines: {node: '>=0.10.0'}
@@ -4146,6 +4985,9 @@ packages:
parse5@7.3.0:
resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==}
+ path-data-parser@0.1.0:
+ resolution: {integrity: sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w==}
+
path-exists@3.0.0:
resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==}
engines: {node: '>=4'}
@@ -4168,6 +5010,9 @@ packages:
resolution: {integrity: sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg==}
engines: {node: '>=8'}
+ pend@1.2.0:
+ resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==}
+
picocolors@1.1.1:
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
@@ -4232,6 +5077,12 @@ packages:
resolution: {integrity: sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==}
engines: {node: '>=14.19.0'}
+ points-on-curve@0.2.0:
+ resolution: {integrity: sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A==}
+
+ points-on-path@0.2.1:
+ resolution: {integrity: sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g==}
+
postcss-import@15.1.0:
resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==}
engines: {node: '>=14.0.0'}
@@ -4306,6 +5157,13 @@ packages:
resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==}
engines: {node: '>= 0.6.0'}
+ progress@2.0.3:
+ resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==}
+ engines: {node: '>=0.4.0'}
+
+ property-information@7.1.0:
+ resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==}
+
protobufjs@7.5.4:
resolution: {integrity: sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==}
engines: {node: '>=12.0.0'}
@@ -4313,12 +5171,19 @@ packages:
proxy-from-env@1.1.0:
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
+ pump@3.0.4:
+ resolution: {integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==}
+
queue-microtask@1.2.3:
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
quick-format-unescaped@4.0.4:
resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==}
+ quick-lru@5.1.1:
+ resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==}
+ engines: {node: '>=10'}
+
react-dom@18.2.0:
resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==}
peerDependencies:
@@ -4368,6 +5233,30 @@ packages:
resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==}
engines: {node: '>= 12.13.0'}
+ rehype-harden@1.1.8:
+ resolution: {integrity: sha512-Qn7vR1xrf6fZCrkm9TDWi/AB4ylrHy+jqsNm1EHOAmbARYA6gsnVJBq/sdBh6kmT4NEZxH5vgIjrscefJAOXcw==}
+
+ rehype-raw@7.0.0:
+ resolution: {integrity: sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==}
+
+ rehype-sanitize@6.0.0:
+ resolution: {integrity: sha512-CsnhKNsyI8Tub6L4sm5ZFsme4puGfc6pYylvXo1AeqaGbjOYyzNv3qZPwvs0oMJ39eryyeOdmxwUIo94IpEhqg==}
+
+ remark-gfm@4.0.1:
+ resolution: {integrity: sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==}
+
+ remark-parse@11.0.0:
+ resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==}
+
+ remark-rehype@11.1.2:
+ resolution: {integrity: sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==}
+
+ remark-stringify@11.0.0:
+ resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==}
+
+ remend@1.3.0:
+ resolution: {integrity: sha512-iIhggPkhW3hFImKtB10w0dz4EZbs28mV/dmbcYVonWEJ6UGHHpP+bFZnTh6GNWJONg5m+U56JrL+8IxZRdgWjw==}
+
require-directory@2.1.1:
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
engines: {node: '>=0.10.0'}
@@ -4379,6 +5268,9 @@ packages:
reselect@4.1.8:
resolution: {integrity: sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==}
+ resolve-alpn@1.2.1:
+ resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==}
+
resolve-from@5.0.0:
resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==}
engines: {node: '>=8'}
@@ -4391,6 +5283,9 @@ packages:
engines: {node: '>= 0.4'}
hasBin: true
+ responselike@2.0.1:
+ resolution: {integrity: sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==}
+
retry@0.13.1:
resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==}
engines: {node: '>= 4'}
@@ -4399,6 +5294,13 @@ packages:
resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==}
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
+ roarr@2.15.4:
+ resolution: {integrity: sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==}
+ engines: {node: '>=8.0'}
+
+ robust-predicates@3.0.3:
+ resolution: {integrity: sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA==}
+
rollup@4.55.1:
resolution: {integrity: sha512-wDv/Ht1BNHB4upNbK74s9usvl7hObDnvVzknxqY/E/O3X6rW1U1rV1aENEfJ54eFZDTNo7zv1f5N4edCluH7+A==}
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
@@ -4407,9 +5309,15 @@ packages:
rou3@0.7.12:
resolution: {integrity: sha512-iFE4hLDuloSWcD7mjdCDhx2bKcIsYbtOTpfH5MHHLSKMOUyjqQXTeZVa289uuwEGEKFoE/BAPbhaU4B774nceg==}
+ roughjs@4.6.6:
+ resolution: {integrity: sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==}
+
run-parallel@1.2.0:
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
+ rw@1.3.3:
+ resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==}
+
s-js@0.4.9:
resolution: {integrity: sha512-RtpOm+cM6O0sHg6IA70wH+UC3FZcND+rccBZpBAHzlUgNO2Bm5BN+FnM8+OBxzXdwpKWFwX11JGF0MFRkhSoIQ==}
@@ -4433,6 +5341,9 @@ packages:
scheduler@0.27.0:
resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==}
+ semver-compare@1.0.0:
+ resolution: {integrity: sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==}
+
semver@6.3.1:
resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
hasBin: true
@@ -4442,6 +5353,10 @@ packages:
engines: {node: '>=10'}
hasBin: true
+ serialize-error@7.0.1:
+ resolution: {integrity: sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==}
+ engines: {node: '>=10'}
+
seroval-plugins@1.3.3:
resolution: {integrity: sha512-16OL3NnUBw8JG1jBLUoZJsLnQq0n5Ua6aHalhJK4fMQkz1lqR7Osz1sA30trBtd9VUDc2NgkuRCn8+/pBwqZ+w==}
engines: {node: '>=10'}
@@ -4496,10 +5411,16 @@ packages:
resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==}
engines: {node: '>= 12'}
+ space-separated-tokens@2.0.2:
+ resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
+
split2@4.2.0:
resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==}
engines: {node: '>= 10.x'}
+ sprintf-js@1.1.3:
+ resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==}
+
sql-escaper@1.3.3:
resolution: {integrity: sha512-BsTCV265VpTp8tm1wyIm1xqQCS+Q9NHx2Sr+WcnUrgLrQ6yiDIvHYJV5gHxsj1lMBy2zm5twLaZao8Jd+S8JJw==}
engines: {bun: '>=1.0.0', deno: '>=2.0.0', node: '>=12.0.0'}
@@ -4511,6 +5432,12 @@ packages:
stream-browserify@3.0.0:
resolution: {integrity: sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==}
+ streamdown@2.5.0:
+ resolution: {integrity: sha512-/tTnURfIOxZK/pqJAxsfCvETG/XCJHoWnk3jq9xLcuz6CSpnjjuxSRBTTL4PKGhxiZQf0lqPxGhImdpwcZ2XwA==}
+ peerDependencies:
+ react: ^18.0.0 || ^19.0.0
+ react-dom: ^18.0.0 || ^19.0.0
+
streamsearch@1.1.0:
resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==}
engines: {node: '>=10.0.0'}
@@ -4522,6 +5449,9 @@ packages:
string_decoder@1.3.0:
resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
+ stringify-entities@4.0.4:
+ resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==}
+
strip-ansi@6.0.1:
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
engines: {node: '>=8'}
@@ -4536,6 +5466,12 @@ packages:
style-mod@4.1.3:
resolution: {integrity: sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==}
+ style-to-js@1.1.21:
+ resolution: {integrity: sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==}
+
+ style-to-object@1.0.14:
+ resolution: {integrity: sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==}
+
styled-jsx@5.1.1:
resolution: {integrity: sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==}
engines: {node: '>= 12.0.0'}
@@ -4562,15 +5498,25 @@ packages:
babel-plugin-macros:
optional: true
+ stylis@4.3.6:
+ resolution: {integrity: sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==}
+
sucrase@3.35.1:
resolution: {integrity: sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==}
engines: {node: '>=16 || 14 >=14.17'}
hasBin: true
+ sumchecker@3.0.1:
+ resolution: {integrity: sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==}
+ engines: {node: '>= 8.0'}
+
supports-preserve-symlinks-flag@1.0.0:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'}
+ tailwind-merge@3.5.0:
+ resolution: {integrity: sha512-I8K9wewnVDkL1NTGoqWmVEIlUcB9gFriAEkXkfCjX5ib8ezGxtR3xD7iZIxrfArjEsH7F1CHD4RFUtxefdqV/A==}
+
tailwindcss@3.4.7:
resolution: {integrity: sha512-rxWZbe87YJb4OcSopb7up2Ba4U82BoiSGUdoDr3Ydrg9ckxFS/YWsvhN323GMcddgU65QRy7JndC7ahhInhvlQ==}
engines: {node: '>=14.0.0'}
@@ -4610,6 +5556,10 @@ packages:
tinyexec@0.3.2:
resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==}
+ tinyexec@1.0.4:
+ resolution: {integrity: sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw==}
+ engines: {node: '>=18'}
+
tinyglobby@0.2.15:
resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==}
engines: {node: '>=12.0.0'}
@@ -4629,6 +5579,16 @@ packages:
resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
hasBin: true
+ trim-lines@3.0.1:
+ resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==}
+
+ trough@2.2.0:
+ resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==}
+
+ ts-dedent@2.2.0:
+ resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==}
+ engines: {node: '>=6.10'}
+
ts-interface-checker@0.1.13:
resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
@@ -4663,6 +5623,10 @@ packages:
resolution: {integrity: sha512-Rb4qk5YT8RUwwdXtkLpkVhNEe/lor6+WV7S5tTlLpxSz6MjV5Qi8jGNn4gS6NAvrYGA/rNrE6YUQM85sCZUDbQ==}
hasBin: true
+ type-fest@0.13.1:
+ resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==}
+ engines: {node: '>=10'}
+
typeid-js@1.2.0:
resolution: {integrity: sha512-t76ZucAnvGC60ea/HjVsB0TSoB0cw9yjnfurUgtInXQWUI/VcrlZGpO23KN3iSe8yOGUgb1zr7W7uEzJ3hSljA==}
@@ -4689,6 +5653,9 @@ packages:
undici-types@6.21.0:
resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
+ undici-types@7.16.0:
+ resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==}
+
undici-types@7.18.2:
resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==}
@@ -4696,6 +5663,28 @@ packages:
resolution: {integrity: sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==}
engines: {node: '>=14.0'}
+ unified@11.0.5:
+ resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==}
+
+ unist-util-is@6.0.1:
+ resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==}
+
+ unist-util-position@5.0.0:
+ resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==}
+
+ unist-util-stringify-position@4.0.0:
+ resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==}
+
+ unist-util-visit-parents@6.0.2:
+ resolution: {integrity: sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==}
+
+ unist-util-visit@5.1.0:
+ resolution: {integrity: sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==}
+
+ universalify@0.1.2:
+ resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==}
+ engines: {node: '>= 4.0.0'}
+
update-browserslist-db@1.2.3:
resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==}
hasBin: true
@@ -4712,6 +5701,19 @@ packages:
resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==}
hasBin: true
+ uuid@11.1.0:
+ resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==}
+ hasBin: true
+
+ vfile-location@5.0.3:
+ resolution: {integrity: sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==}
+
+ vfile-message@4.0.3:
+ resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==}
+
+ vfile@6.0.3:
+ resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==}
+
vite-plugin-solid@2.11.10:
resolution: {integrity: sha512-Yr1dQybmtDtDAHkii6hXuc1oVH9CPcS/Zb2jN/P36qqcrkNnVPsMTzQ06jyzFPFjj3U1IYKMVt/9ZqcwGCEbjw==}
peerDependencies:
@@ -4810,9 +5812,32 @@ packages:
vite:
optional: true
+ vscode-jsonrpc@8.2.0:
+ resolution: {integrity: sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==}
+ engines: {node: '>=14.0.0'}
+
+ vscode-languageserver-protocol@3.17.5:
+ resolution: {integrity: sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==}
+
+ vscode-languageserver-textdocument@1.0.12:
+ resolution: {integrity: sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==}
+
+ vscode-languageserver-types@3.17.5:
+ resolution: {integrity: sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==}
+
+ vscode-languageserver@9.0.1:
+ resolution: {integrity: sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==}
+ hasBin: true
+
+ vscode-uri@3.1.0:
+ resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==}
+
w3c-keyname@2.2.8:
resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==}
+ web-namespaces@2.0.1:
+ resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==}
+
web-tree-sitter@0.25.10:
resolution: {integrity: sha512-Y09sF44/13XvgVKgO2cNDw5rGk6s26MgoZPXLESvMXeefBf7i6/73eFurre0IsTW6E14Y0ArIzhUMmjoc7xyzA==}
peerDependencies:
@@ -4831,6 +5856,9 @@ packages:
resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
engines: {node: '>=10'}
+ wrappy@1.0.2:
+ resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
+
ws@8.19.0:
resolution: {integrity: sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==}
engines: {node: '>=10.0.0'}
@@ -4878,6 +5906,9 @@ packages:
resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==}
engines: {node: '>=12'}
+ yauzl@2.10.0:
+ resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==}
+
yoga-layout@3.2.1:
resolution: {integrity: sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ==}
@@ -4887,6 +5918,9 @@ packages:
zod@4.3.6:
resolution: {integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==}
+ zwitch@2.0.4:
+ resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
+
snapshots:
'@alloc/quick-lru@5.2.0': {}
@@ -4896,6 +5930,11 @@ snapshots:
'@jridgewell/gen-mapping': 0.3.13
'@jridgewell/trace-mapping': 0.3.31
+ '@antfu/install-pkg@1.1.0':
+ dependencies:
+ package-manager-detector: 1.6.0
+ tinyexec: 1.0.4
+
'@aws-crypto/crc32@5.2.0':
dependencies:
'@aws-crypto/util': 5.2.0
@@ -5470,8 +6509,8 @@ snapshots:
'@babel/helper-member-expression-to-functions@7.28.5':
dependencies:
- '@babel/traverse': 7.28.6
- '@babel/types': 7.28.6
+ '@babel/traverse': 7.29.0
+ '@babel/types': 7.29.0
transitivePeerDependencies:
- supports-color
@@ -5515,7 +6554,7 @@ snapshots:
'@babel/helper-optimise-call-expression@7.27.1':
dependencies:
- '@babel/types': 7.28.6
+ '@babel/types': 7.29.0
'@babel/helper-plugin-utils@7.28.6': {}
@@ -5524,7 +6563,7 @@ snapshots:
'@babel/core': 7.28.0
'@babel/helper-member-expression-to-functions': 7.28.5
'@babel/helper-optimise-call-expression': 7.27.1
- '@babel/traverse': 7.28.6
+ '@babel/traverse': 7.29.0
transitivePeerDependencies:
- supports-color
@@ -5670,6 +6709,25 @@ snapshots:
'@better-fetch/fetch@1.1.21': {}
+ '@braintree/sanitize-url@7.1.2': {}
+
+ '@chevrotain/cst-dts-gen@11.1.2':
+ dependencies:
+ '@chevrotain/gast': 11.1.2
+ '@chevrotain/types': 11.1.2
+ lodash-es: 4.17.23
+
+ '@chevrotain/gast@11.1.2':
+ dependencies:
+ '@chevrotain/types': 11.1.2
+ lodash-es: 4.17.23
+
+ '@chevrotain/regexp-to-ast@11.1.2': {}
+
+ '@chevrotain/types@11.1.2': {}
+
+ '@chevrotain/utils@11.1.2': {}
+
'@codemirror/autocomplete@6.20.0':
dependencies:
'@codemirror/language': 6.12.1
@@ -5798,6 +6856,20 @@ snapshots:
'@drizzle-team/brocli@0.10.2': {}
+ '@electron/get@2.0.3':
+ dependencies:
+ debug: 4.4.3
+ env-paths: 2.2.1
+ fs-extra: 8.1.0
+ got: 11.8.6
+ progress: 2.0.3
+ semver: 6.3.1
+ sumchecker: 3.0.1
+ optionalDependencies:
+ global-agent: 3.0.0
+ transitivePeerDependencies:
+ - supports-color
+
'@emnapi/runtime@1.8.1':
dependencies:
tslib: 2.8.1
@@ -6062,6 +7134,14 @@ snapshots:
'@iarna/toml@2.2.5': {}
+ '@iconify/types@2.0.0': {}
+
+ '@iconify/utils@3.1.0':
+ dependencies:
+ '@antfu/install-pkg': 1.1.0
+ '@iconify/types': 2.0.0
+ mlly: 1.8.2
+
'@img/colour@1.1.0': {}
'@img/sharp-darwin-arm64@0.34.5':
@@ -6413,6 +7493,10 @@ snapshots:
'@marijn/find-cluster-break@1.0.2': {}
+ '@mermaid-js/parser@1.1.0':
+ dependencies:
+ langium: 4.2.1
+
'@next/env@14.2.5': {}
'@next/env@16.1.6': {}
@@ -6937,6 +8021,8 @@ snapshots:
'@rollup/rollup-win32-x64-msvc@4.55.1':
optional: true
+ '@sindresorhus/is@4.6.0': {}
+
'@slack/logger@4.0.0':
dependencies:
'@types/node': 20.12.12
@@ -7343,6 +8429,10 @@ snapshots:
'@swc/counter': 0.1.3
tslib: 2.8.1
+ '@szmarczak/http-timer@4.0.6':
+ dependencies:
+ defer-to-connect: 2.0.1
+
'@tailwindcss/node@4.1.18':
dependencies:
'@jridgewell/remapping': 2.3.5
@@ -7411,6 +8501,12 @@ snapshots:
tailwindcss: 4.1.18
vite: 6.4.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2)
+ '@tanstack/react-virtual@3.13.23(react-dom@19.2.4(react@19.2.4))(react@19.2.4)':
+ dependencies:
+ '@tanstack/virtual-core': 3.13.23
+ react: 19.2.4
+ react-dom: 19.2.4(react@19.2.4)
+
'@tanstack/solid-virtual@3.13.19(solid-js@1.9.9)':
dependencies:
'@tanstack/virtual-core': 3.13.19
@@ -7418,6 +8514,8 @@ snapshots:
'@tanstack/virtual-core@3.13.19': {}
+ '@tanstack/virtual-core@3.13.23': {}
+
'@tauri-apps/api@2.10.1': {}
'@tauri-apps/cli-darwin-arm64@2.9.6':
@@ -7532,96 +8630,273 @@ snapshots:
dependencies:
'@babel/types': 7.28.6
- '@types/estree@1.0.8': {}
-
- '@types/minimatch@5.1.2': {}
+ '@types/cacheable-request@6.0.3':
+ dependencies:
+ '@types/http-cache-semantics': 4.2.0
+ '@types/keyv': 3.1.4
+ '@types/node': 20.12.12
+ '@types/responselike': 1.0.3
- '@types/node@16.9.1': {}
+ '@types/d3-array@3.2.2': {}
- '@types/node@20.12.12':
+ '@types/d3-axis@3.0.6':
dependencies:
- undici-types: 5.26.5
+ '@types/d3-selection': 3.0.11
- '@types/node@22.19.7':
+ '@types/d3-brush@3.0.6':
dependencies:
- undici-types: 6.21.0
+ '@types/d3-selection': 3.0.11
- '@types/node@25.4.0':
- dependencies:
- undici-types: 7.18.2
+ '@types/d3-chord@3.0.6': {}
- '@types/prop-types@15.7.15': {}
+ '@types/d3-color@3.1.3': {}
- '@types/react-dom@18.2.25':
+ '@types/d3-contour@3.0.6':
dependencies:
- '@types/react': 18.2.79
+ '@types/d3-array': 3.2.2
+ '@types/geojson': 7946.0.16
- '@types/react-dom@19.2.3(@types/react@19.2.14)':
- dependencies:
- '@types/react': 19.2.14
+ '@types/d3-delaunay@6.0.4': {}
- '@types/react@18.2.79':
- dependencies:
- '@types/prop-types': 15.7.15
- csstype: 3.2.3
+ '@types/d3-dispatch@3.0.7': {}
- '@types/react@19.2.14':
+ '@types/d3-drag@3.0.7':
dependencies:
- csstype: 3.2.3
+ '@types/d3-selection': 3.0.11
- '@types/retry@0.12.0': {}
+ '@types/d3-dsv@3.0.7': {}
- '@types/ws@8.18.1':
- dependencies:
- '@types/node': 20.12.12
+ '@types/d3-ease@3.0.2': {}
- '@vercel/blob@0.27.3':
+ '@types/d3-fetch@3.0.7':
dependencies:
- async-retry: 1.3.3
- is-buffer: 2.0.5
- is-node-process: 1.2.0
- throttleit: 2.1.0
- undici: 5.29.0
+ '@types/d3-dsv': 3.0.7
- '@vitejs/plugin-react@5.2.0(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2))':
- dependencies:
- '@babel/core': 7.29.0
- '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0)
- '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.29.0)
- '@rolldown/pluginutils': 1.0.0-rc.3
- '@types/babel__core': 7.20.5
- react-refresh: 0.18.0
- vite: 7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2)
- transitivePeerDependencies:
- - supports-color
+ '@types/d3-force@3.0.10': {}
- '@webgpu/types@0.1.69':
- optional: true
+ '@types/d3-format@3.0.4': {}
- abort-controller@3.0.0:
+ '@types/d3-geo@3.1.0':
dependencies:
- event-target-shim: 5.0.1
+ '@types/geojson': 7946.0.16
- acorn-import-attributes@1.9.5(acorn@8.16.0):
+ '@types/d3-hierarchy@3.1.7': {}
+
+ '@types/d3-interpolate@3.0.4':
dependencies:
- acorn: 8.16.0
+ '@types/d3-color': 3.1.3
- acorn@8.16.0: {}
+ '@types/d3-path@3.1.1': {}
- ansi-regex@5.0.1: {}
+ '@types/d3-polygon@3.0.2': {}
- ansi-styles@4.3.0:
- dependencies:
- color-convert: 2.0.1
+ '@types/d3-quadtree@3.0.6': {}
- any-base@1.1.0: {}
+ '@types/d3-random@3.0.3': {}
- any-promise@1.3.0: {}
+ '@types/d3-scale-chromatic@3.1.0': {}
- anymatch@3.1.3:
+ '@types/d3-scale@4.0.9':
dependencies:
- normalize-path: 3.0.0
- picomatch: 2.3.1
+ '@types/d3-time': 3.0.4
+
+ '@types/d3-selection@3.0.11': {}
+
+ '@types/d3-shape@3.1.8':
+ dependencies:
+ '@types/d3-path': 3.1.1
+
+ '@types/d3-time-format@4.0.3': {}
+
+ '@types/d3-time@3.0.4': {}
+
+ '@types/d3-timer@3.0.2': {}
+
+ '@types/d3-transition@3.0.9':
+ dependencies:
+ '@types/d3-selection': 3.0.11
+
+ '@types/d3-zoom@3.0.8':
+ dependencies:
+ '@types/d3-interpolate': 3.0.4
+ '@types/d3-selection': 3.0.11
+
+ '@types/d3@7.4.3':
+ dependencies:
+ '@types/d3-array': 3.2.2
+ '@types/d3-axis': 3.0.6
+ '@types/d3-brush': 3.0.6
+ '@types/d3-chord': 3.0.6
+ '@types/d3-color': 3.1.3
+ '@types/d3-contour': 3.0.6
+ '@types/d3-delaunay': 6.0.4
+ '@types/d3-dispatch': 3.0.7
+ '@types/d3-drag': 3.0.7
+ '@types/d3-dsv': 3.0.7
+ '@types/d3-ease': 3.0.2
+ '@types/d3-fetch': 3.0.7
+ '@types/d3-force': 3.0.10
+ '@types/d3-format': 3.0.4
+ '@types/d3-geo': 3.1.0
+ '@types/d3-hierarchy': 3.1.7
+ '@types/d3-interpolate': 3.0.4
+ '@types/d3-path': 3.1.1
+ '@types/d3-polygon': 3.0.2
+ '@types/d3-quadtree': 3.0.6
+ '@types/d3-random': 3.0.3
+ '@types/d3-scale': 4.0.9
+ '@types/d3-scale-chromatic': 3.1.0
+ '@types/d3-selection': 3.0.11
+ '@types/d3-shape': 3.1.8
+ '@types/d3-time': 3.0.4
+ '@types/d3-time-format': 4.0.3
+ '@types/d3-timer': 3.0.2
+ '@types/d3-transition': 3.0.9
+ '@types/d3-zoom': 3.0.8
+
+ '@types/debug@4.1.13':
+ dependencies:
+ '@types/ms': 2.1.0
+
+ '@types/estree-jsx@1.0.5':
+ dependencies:
+ '@types/estree': 1.0.8
+
+ '@types/estree@1.0.8': {}
+
+ '@types/geojson@7946.0.16': {}
+
+ '@types/hast@3.0.4':
+ dependencies:
+ '@types/unist': 3.0.3
+
+ '@types/http-cache-semantics@4.2.0': {}
+
+ '@types/keyv@3.1.4':
+ dependencies:
+ '@types/node': 20.12.12
+
+ '@types/mdast@4.0.4':
+ dependencies:
+ '@types/unist': 3.0.3
+
+ '@types/minimatch@5.1.2': {}
+
+ '@types/ms@2.1.0': {}
+
+ '@types/node@16.9.1': {}
+
+ '@types/node@20.12.12':
+ dependencies:
+ undici-types: 5.26.5
+
+ '@types/node@22.19.7':
+ dependencies:
+ undici-types: 6.21.0
+
+ '@types/node@24.12.0':
+ dependencies:
+ undici-types: 7.16.0
+
+ '@types/node@25.4.0':
+ dependencies:
+ undici-types: 7.18.2
+
+ '@types/prop-types@15.7.15': {}
+
+ '@types/react-dom@18.2.25':
+ dependencies:
+ '@types/react': 19.2.14
+
+ '@types/react-dom@19.2.3(@types/react@19.2.14)':
+ dependencies:
+ '@types/react': 19.2.14
+
+ '@types/react@18.2.79':
+ dependencies:
+ '@types/prop-types': 15.7.15
+ csstype: 3.2.3
+
+ '@types/react@19.2.14':
+ dependencies:
+ csstype: 3.2.3
+
+ '@types/responselike@1.0.3':
+ dependencies:
+ '@types/node': 20.12.12
+
+ '@types/retry@0.12.0': {}
+
+ '@types/trusted-types@2.0.7':
+ optional: true
+
+ '@types/unist@2.0.11': {}
+
+ '@types/unist@3.0.3': {}
+
+ '@types/ws@8.18.1':
+ dependencies:
+ '@types/node': 20.12.12
+
+ '@types/yauzl@2.10.3':
+ dependencies:
+ '@types/node': 20.12.12
+ optional: true
+
+ '@ungap/structured-clone@1.3.0': {}
+
+ '@upsetjs/venn.js@2.0.0':
+ optionalDependencies:
+ d3-selection: 3.0.0
+ d3-transition: 3.0.1(d3-selection@3.0.0)
+
+ '@vercel/blob@0.27.3':
+ dependencies:
+ async-retry: 1.3.3
+ is-buffer: 2.0.5
+ is-node-process: 1.2.0
+ throttleit: 2.1.0
+ undici: 5.29.0
+
+ '@vitejs/plugin-react@5.2.0(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2))':
+ dependencies:
+ '@babel/core': 7.29.0
+ '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0)
+ '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.29.0)
+ '@rolldown/pluginutils': 1.0.0-rc.3
+ '@types/babel__core': 7.20.5
+ react-refresh: 0.18.0
+ vite: 7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@webgpu/types@0.1.69':
+ optional: true
+
+ abort-controller@3.0.0:
+ dependencies:
+ event-target-shim: 5.0.1
+
+ acorn-import-attributes@1.9.5(acorn@8.16.0):
+ dependencies:
+ acorn: 8.16.0
+
+ acorn@8.16.0: {}
+
+ ansi-regex@5.0.1: {}
+
+ ansi-styles@4.3.0:
+ dependencies:
+ color-convert: 2.0.1
+
+ any-base@1.1.0: {}
+
+ any-promise@1.3.0: {}
+
+ anymatch@3.1.3:
+ dependencies:
+ normalize-path: 3.0.0
+ picomatch: 2.3.1
arg@5.0.2: {}
@@ -7695,6 +8970,8 @@ snapshots:
optionalDependencies:
solid-js: 1.9.9
+ bail@2.0.2: {}
+
balanced-match@1.0.2: {}
base64-js@1.5.1: {}
@@ -7739,6 +9016,9 @@ snapshots:
bmp-ts@1.0.9: {}
+ boolean@3.2.0:
+ optional: true
+
botid@1.5.11(next@14.2.5(@opentelemetry/api@1.9.0)(@playwright/test@1.58.2)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react@18.2.0):
optionalDependencies:
next: 14.2.5(@opentelemetry/api@1.9.0)(@playwright/test@1.58.2)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)
@@ -7767,6 +9047,8 @@ snapshots:
node-releases: 2.0.27
update-browserslist-db: 1.2.3(browserslist@4.28.1)
+ buffer-crc32@0.2.13: {}
+
buffer-from@1.1.2: {}
buffer@5.6.0:
@@ -7820,6 +9102,18 @@ snapshots:
cac@6.7.14: {}
+ cacheable-lookup@5.0.4: {}
+
+ cacheable-request@7.0.4:
+ dependencies:
+ clone-response: 1.0.3
+ get-stream: 5.2.0
+ http-cache-semantics: 4.2.0
+ keyv: 4.5.4
+ lowercase-keys: 2.0.0
+ normalize-url: 6.1.0
+ responselike: 2.0.1
+
call-bind-apply-helpers@1.0.2:
dependencies:
es-errors: 1.3.0
@@ -7829,6 +9123,30 @@ snapshots:
caniuse-lite@1.0.30001764: {}
+ ccount@2.0.1: {}
+
+ character-entities-html4@2.1.0: {}
+
+ character-entities-legacy@3.0.0: {}
+
+ character-entities@2.0.2: {}
+
+ character-reference-invalid@2.0.1: {}
+
+ chevrotain-allstar@0.3.1(chevrotain@11.1.2):
+ dependencies:
+ chevrotain: 11.1.2
+ lodash-es: 4.18.1
+
+ chevrotain@11.1.2:
+ dependencies:
+ '@chevrotain/cst-dts-gen': 11.1.2
+ '@chevrotain/gast': 11.1.2
+ '@chevrotain/regexp-to-ast': 11.1.2
+ '@chevrotain/types': 11.1.2
+ '@chevrotain/utils': 11.1.2
+ lodash-es: 4.17.23
+
chokidar@3.6.0:
dependencies:
anymatch: 3.1.3
@@ -7857,6 +9175,12 @@ snapshots:
strip-ansi: 6.0.1
wrap-ansi: 7.0.0
+ clone-response@1.0.3:
+ dependencies:
+ mimic-response: 1.0.1
+
+ clsx@2.1.1: {}
+
color-convert@2.0.1:
dependencies:
color-name: 1.1.4
@@ -7867,40 +9191,281 @@ snapshots:
dependencies:
delayed-stream: 1.0.0
+ comma-separated-tokens@2.0.3: {}
+
commander@12.1.0: {}
commander@4.1.1: {}
+ commander@7.2.0: {}
+
+ commander@8.3.0: {}
+
confbox@0.1.8: {}
consola@3.4.2: {}
convert-source-map@2.0.0: {}
+ cose-base@1.0.3:
+ dependencies:
+ layout-base: 1.0.2
+
+ cose-base@2.2.0:
+ dependencies:
+ layout-base: 2.0.1
+
crelt@1.0.6: {}
cssesc@3.0.0: {}
csstype@3.2.3: {}
+ cytoscape-cose-bilkent@4.1.0(cytoscape@3.33.1):
+ dependencies:
+ cose-base: 1.0.3
+ cytoscape: 3.33.1
+
+ cytoscape-fcose@2.2.0(cytoscape@3.33.1):
+ dependencies:
+ cose-base: 2.2.0
+ cytoscape: 3.33.1
+
+ cytoscape@3.33.1: {}
+
+ d3-array@2.12.1:
+ dependencies:
+ internmap: 1.0.1
+
+ d3-array@3.2.4:
+ dependencies:
+ internmap: 2.0.3
+
+ d3-axis@3.0.0: {}
+
+ d3-brush@3.0.0:
+ dependencies:
+ d3-dispatch: 3.0.1
+ d3-drag: 3.0.0
+ d3-interpolate: 3.0.1
+ d3-selection: 3.0.0
+ d3-transition: 3.0.1(d3-selection@3.0.0)
+
+ d3-chord@3.0.1:
+ dependencies:
+ d3-path: 3.1.0
+
+ d3-color@3.1.0: {}
+
+ d3-contour@4.0.2:
+ dependencies:
+ d3-array: 3.2.4
+
+ d3-delaunay@6.0.4:
+ dependencies:
+ delaunator: 5.1.0
+
+ d3-dispatch@3.0.1: {}
+
+ d3-drag@3.0.0:
+ dependencies:
+ d3-dispatch: 3.0.1
+ d3-selection: 3.0.0
+
+ d3-dsv@3.0.1:
+ dependencies:
+ commander: 7.2.0
+ iconv-lite: 0.6.3
+ rw: 1.3.3
+
+ d3-ease@3.0.1: {}
+
+ d3-fetch@3.0.1:
+ dependencies:
+ d3-dsv: 3.0.1
+
+ d3-force@3.0.0:
+ dependencies:
+ d3-dispatch: 3.0.1
+ d3-quadtree: 3.0.1
+ d3-timer: 3.0.1
+
+ d3-format@3.1.2: {}
+
+ d3-geo@3.1.1:
+ dependencies:
+ d3-array: 3.2.4
+
+ d3-hierarchy@3.1.2: {}
+
+ d3-interpolate@3.0.1:
+ dependencies:
+ d3-color: 3.1.0
+
+ d3-path@1.0.9: {}
+
+ d3-path@3.1.0: {}
+
+ d3-polygon@3.0.1: {}
+
+ d3-quadtree@3.0.1: {}
+
+ d3-random@3.0.1: {}
+
+ d3-sankey@0.12.3:
+ dependencies:
+ d3-array: 2.12.1
+ d3-shape: 1.3.7
+
+ d3-scale-chromatic@3.1.0:
+ dependencies:
+ d3-color: 3.1.0
+ d3-interpolate: 3.0.1
+
+ d3-scale@4.0.2:
+ dependencies:
+ d3-array: 3.2.4
+ d3-format: 3.1.2
+ d3-interpolate: 3.0.1
+ d3-time: 3.1.0
+ d3-time-format: 4.1.0
+
+ d3-selection@3.0.0: {}
+
+ d3-shape@1.3.7:
+ dependencies:
+ d3-path: 1.0.9
+
+ d3-shape@3.2.0:
+ dependencies:
+ d3-path: 3.1.0
+
+ d3-time-format@4.1.0:
+ dependencies:
+ d3-time: 3.1.0
+
+ d3-time@3.1.0:
+ dependencies:
+ d3-array: 3.2.4
+
+ d3-timer@3.0.1: {}
+
+ d3-transition@3.0.1(d3-selection@3.0.0):
+ dependencies:
+ d3-color: 3.1.0
+ d3-dispatch: 3.0.1
+ d3-ease: 3.0.1
+ d3-interpolate: 3.0.1
+ d3-selection: 3.0.0
+ d3-timer: 3.0.1
+
+ d3-zoom@3.0.0:
+ dependencies:
+ d3-dispatch: 3.0.1
+ d3-drag: 3.0.0
+ d3-interpolate: 3.0.1
+ d3-selection: 3.0.0
+ d3-transition: 3.0.1(d3-selection@3.0.0)
+
+ d3@7.9.0:
+ dependencies:
+ d3-array: 3.2.4
+ d3-axis: 3.0.0
+ d3-brush: 3.0.0
+ d3-chord: 3.0.1
+ d3-color: 3.1.0
+ d3-contour: 4.0.2
+ d3-delaunay: 6.0.4
+ d3-dispatch: 3.0.1
+ d3-drag: 3.0.0
+ d3-dsv: 3.0.1
+ d3-ease: 3.0.1
+ d3-fetch: 3.0.1
+ d3-force: 3.0.0
+ d3-format: 3.1.2
+ d3-geo: 3.1.1
+ d3-hierarchy: 3.1.2
+ d3-interpolate: 3.0.1
+ d3-path: 3.1.0
+ d3-polygon: 3.0.1
+ d3-quadtree: 3.0.1
+ d3-random: 3.0.1
+ d3-scale: 4.0.2
+ d3-scale-chromatic: 3.1.0
+ d3-selection: 3.0.0
+ d3-shape: 3.2.0
+ d3-time: 3.1.0
+ d3-time-format: 4.1.0
+ d3-timer: 3.0.1
+ d3-transition: 3.0.1(d3-selection@3.0.0)
+ d3-zoom: 3.0.0
+
+ dagre-d3-es@7.0.14:
+ dependencies:
+ d3: 7.9.0
+ lodash-es: 4.18.1
+
+ dayjs@1.11.20: {}
+
debug@4.4.3:
dependencies:
ms: 2.1.3
+ decode-named-character-reference@1.3.0:
+ dependencies:
+ character-entities: 2.0.2
+
+ decompress-response@6.0.0:
+ dependencies:
+ mimic-response: 3.1.0
+
+ defer-to-connect@2.0.1: {}
+
+ define-data-property@1.1.4:
+ dependencies:
+ es-define-property: 1.0.1
+ es-errors: 1.3.0
+ gopd: 1.2.0
+ optional: true
+
+ define-properties@1.2.1:
+ dependencies:
+ define-data-property: 1.1.4
+ has-property-descriptors: 1.0.2
+ object-keys: 1.1.1
+ optional: true
+
defu@6.1.4: {}
+ delaunator@5.1.0:
+ dependencies:
+ robust-predicates: 3.0.3
+
delayed-stream@1.0.0: {}
denque@2.1.0: {}
+ dequal@2.0.3: {}
+
detect-libc@2.1.2: {}
+ detect-node@2.1.0:
+ optional: true
+
+ devlop@1.1.0:
+ dependencies:
+ dequal: 2.0.3
+
didyoumean@1.2.2: {}
diff@8.0.2: {}
dlv@1.1.3: {}
+ dompurify@3.3.3:
+ optionalDependencies:
+ '@types/trusted-types': 2.0.7
+
dotenv@16.6.1: {}
dotenv@17.3.1: {}
@@ -7930,8 +9495,20 @@ snapshots:
electron-to-chromium@1.5.267: {}
+ electron@41.1.1:
+ dependencies:
+ '@electron/get': 2.0.3
+ '@types/node': 24.12.0
+ extract-zip: 2.0.1
+ transitivePeerDependencies:
+ - supports-color
+
emoji-regex@8.0.0: {}
+ end-of-stream@1.4.5:
+ dependencies:
+ once: 1.4.0
+
enhanced-resolve@5.18.4:
dependencies:
graceful-fs: 4.2.11
@@ -7939,6 +9516,8 @@ snapshots:
entities@6.0.1: {}
+ env-paths@2.2.1: {}
+
es-define-property@1.0.1: {}
es-errors@1.3.0: {}
@@ -7954,6 +9533,9 @@ snapshots:
has-tostringtag: 1.0.2
hasown: 2.0.2
+ es6-error@4.1.1:
+ optional: true
+
esbuild-register@3.6.0(esbuild@0.25.12):
dependencies:
debug: 4.4.3
@@ -8046,6 +9628,13 @@ snapshots:
escalade@3.2.0: {}
+ escape-string-regexp@4.0.0:
+ optional: true
+
+ escape-string-regexp@5.0.0: {}
+
+ estree-util-is-identifier-name@3.0.0: {}
+
event-target-shim@5.0.1: {}
eventemitter3@4.0.7: {}
@@ -8060,6 +9649,18 @@ snapshots:
dependencies:
homedir-polyfill: 1.0.3
+ extend@3.0.2: {}
+
+ extract-zip@2.0.1:
+ dependencies:
+ debug: 4.4.3
+ get-stream: 5.2.0
+ yauzl: 2.10.0
+ optionalDependencies:
+ '@types/yauzl': 2.10.3
+ transitivePeerDependencies:
+ - supports-color
+
fast-glob@3.3.3:
dependencies:
'@nodelib/fs.stat': 2.0.5
@@ -8081,6 +9682,10 @@ snapshots:
dependencies:
reusify: 1.1.0
+ fd-slicer@1.1.0:
+ dependencies:
+ pend: 1.2.0
+
fdir@6.5.0(picomatch@4.0.3):
optionalDependencies:
picomatch: 4.0.3
@@ -8132,6 +9737,12 @@ snapshots:
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
+ fs-extra@8.1.0:
+ dependencies:
+ graceful-fs: 4.2.11
+ jsonfile: 4.0.0
+ universalify: 0.1.2
+
fs.realpath@1.0.0: {}
fsevents@2.3.2:
@@ -8170,6 +9781,10 @@ snapshots:
dunder-proto: 1.0.1
es-object-atoms: 1.1.1
+ get-stream@5.2.0:
+ dependencies:
+ pump: 3.0.4
+
get-tsconfig@4.13.1:
dependencies:
resolve-pkg-maps: 1.0.0
@@ -8194,8 +9809,38 @@ snapshots:
minipass: 4.2.8
path-scurry: 1.11.1
+ global-agent@3.0.0:
+ dependencies:
+ boolean: 3.2.0
+ es6-error: 4.1.1
+ matcher: 3.0.0
+ roarr: 2.15.4
+ semver: 7.7.4
+ serialize-error: 7.0.1
+ optional: true
+
+ globalthis@1.0.4:
+ dependencies:
+ define-properties: 1.2.1
+ gopd: 1.2.0
+ optional: true
+
gopd@1.2.0: {}
+ got@11.8.6:
+ dependencies:
+ '@sindresorhus/is': 4.6.0
+ '@szmarczak/http-timer': 4.0.6
+ '@types/cacheable-request': 6.0.3
+ '@types/responselike': 1.0.3
+ cacheable-lookup: 5.0.4
+ cacheable-request: 7.0.4
+ decompress-response: 6.0.0
+ http2-wrapper: 1.0.3
+ lowercase-keys: 2.0.0
+ p-cancelable: 2.1.1
+ responselike: 2.0.1
+
graceful-fs@4.2.11: {}
grammy@1.39.3:
@@ -8208,15 +9853,101 @@ snapshots:
- encoding
- supports-color
+ hachure-fill@0.5.2: {}
+
+ has-property-descriptors@1.0.2:
+ dependencies:
+ es-define-property: 1.0.1
+ optional: true
+
has-symbols@1.1.0: {}
- has-tostringtag@1.0.2:
+ has-tostringtag@1.0.2:
+ dependencies:
+ has-symbols: 1.1.0
+
+ hasown@2.0.2:
+ dependencies:
+ function-bind: 1.1.2
+
+ hast-util-from-parse5@8.0.3:
+ dependencies:
+ '@types/hast': 3.0.4
+ '@types/unist': 3.0.3
+ devlop: 1.1.0
+ hastscript: 9.0.1
+ property-information: 7.1.0
+ vfile: 6.0.3
+ vfile-location: 5.0.3
+ web-namespaces: 2.0.1
+
+ hast-util-parse-selector@4.0.0:
+ dependencies:
+ '@types/hast': 3.0.4
+
+ hast-util-raw@9.1.0:
+ dependencies:
+ '@types/hast': 3.0.4
+ '@types/unist': 3.0.3
+ '@ungap/structured-clone': 1.3.0
+ hast-util-from-parse5: 8.0.3
+ hast-util-to-parse5: 8.0.1
+ html-void-elements: 3.0.0
+ mdast-util-to-hast: 13.2.1
+ parse5: 7.3.0
+ unist-util-position: 5.0.0
+ unist-util-visit: 5.1.0
+ vfile: 6.0.3
+ web-namespaces: 2.0.1
+ zwitch: 2.0.4
+
+ hast-util-sanitize@5.0.2:
+ dependencies:
+ '@types/hast': 3.0.4
+ '@ungap/structured-clone': 1.3.0
+ unist-util-position: 5.0.0
+
+ hast-util-to-jsx-runtime@2.3.6:
+ dependencies:
+ '@types/estree': 1.0.8
+ '@types/hast': 3.0.4
+ '@types/unist': 3.0.3
+ comma-separated-tokens: 2.0.3
+ devlop: 1.1.0
+ estree-util-is-identifier-name: 3.0.0
+ hast-util-whitespace: 3.0.0
+ mdast-util-mdx-expression: 2.0.1
+ mdast-util-mdx-jsx: 3.2.0
+ mdast-util-mdxjs-esm: 2.0.1
+ property-information: 7.1.0
+ space-separated-tokens: 2.0.2
+ style-to-js: 1.1.21
+ unist-util-position: 5.0.0
+ vfile-message: 4.0.3
+ transitivePeerDependencies:
+ - supports-color
+
+ hast-util-to-parse5@8.0.1:
+ dependencies:
+ '@types/hast': 3.0.4
+ comma-separated-tokens: 2.0.3
+ devlop: 1.1.0
+ property-information: 7.1.0
+ space-separated-tokens: 2.0.2
+ web-namespaces: 2.0.1
+ zwitch: 2.0.4
+
+ hast-util-whitespace@3.0.0:
dependencies:
- has-symbols: 1.1.0
+ '@types/hast': 3.0.4
- hasown@2.0.2:
+ hastscript@9.0.1:
dependencies:
- function-bind: 1.1.2
+ '@types/hast': 3.0.4
+ comma-separated-tokens: 2.0.3
+ hast-util-parse-selector: 4.0.0
+ property-information: 7.1.0
+ space-separated-tokens: 2.0.2
homedir-polyfill@1.0.3:
dependencies:
@@ -8226,6 +9957,21 @@ snapshots:
html-entities@2.3.3: {}
+ html-url-attributes@3.0.1: {}
+
+ html-void-elements@3.0.0: {}
+
+ http-cache-semantics@4.2.0: {}
+
+ http2-wrapper@1.0.3:
+ dependencies:
+ quick-lru: 5.1.1
+ resolve-alpn: 1.2.1
+
+ iconv-lite@0.6.3:
+ dependencies:
+ safer-buffer: 2.1.2
+
iconv-lite@0.7.2:
dependencies:
safer-buffer: 2.1.2
@@ -8245,6 +9991,19 @@ snapshots:
inherits@2.0.4: {}
+ inline-style-parser@0.2.7: {}
+
+ internmap@1.0.1: {}
+
+ internmap@2.0.3: {}
+
+ is-alphabetical@2.0.1: {}
+
+ is-alphanumerical@2.0.1:
+ dependencies:
+ is-alphabetical: 2.0.1
+ is-decimal: 2.0.1
+
is-binary-path@2.1.0:
dependencies:
binary-extensions: 2.3.0
@@ -8255,6 +10014,8 @@ snapshots:
dependencies:
hasown: 2.0.2
+ is-decimal@2.0.1: {}
+
is-electron@2.2.2: {}
is-extglob@2.1.1: {}
@@ -8265,10 +10026,14 @@ snapshots:
dependencies:
is-extglob: 2.1.1
+ is-hexadecimal@2.0.1: {}
+
is-node-process@1.2.0: {}
is-number@7.0.0: {}
+ is-plain-obj@4.1.0: {}
+
is-property@1.0.2: {}
is-stream@2.0.1: {}
@@ -8323,12 +10088,43 @@ snapshots:
jsesc@3.1.0: {}
+ json-buffer@3.0.1: {}
+
+ json-stringify-safe@5.0.1:
+ optional: true
+
json5@2.2.3: {}
jsonc-parser@3.3.1: {}
+ jsonfile@4.0.0:
+ optionalDependencies:
+ graceful-fs: 4.2.11
+
+ katex@0.16.44:
+ dependencies:
+ commander: 8.3.0
+
+ keyv@4.5.4:
+ dependencies:
+ json-buffer: 3.0.1
+
+ khroma@2.1.0: {}
+
kysely@0.28.11: {}
+ langium@4.2.1:
+ dependencies:
+ chevrotain: 11.1.2
+ chevrotain-allstar: 0.3.1(chevrotain@11.1.2)
+ vscode-languageserver: 9.0.1
+ vscode-languageserver-textdocument: 1.0.12
+ vscode-uri: 3.1.0
+
+ layout-base@1.0.2: {}
+
+ layout-base@2.0.1: {}
+
lightningcss-android-arm64@1.30.2:
optional: true
@@ -8391,14 +10187,22 @@ snapshots:
p-locate: 3.0.0
path-exists: 3.0.0
+ lodash-es@4.17.23: {}
+
+ lodash-es@4.18.1: {}
+
lodash.camelcase@4.3.0: {}
long@5.3.2: {}
+ longest-streak@3.1.0: {}
+
loose-envify@1.4.0:
dependencies:
js-tokens: 4.0.0
+ lowercase-keys@2.0.0: {}
+
lru-cache@10.4.3: {}
lru-cache@5.1.1:
@@ -8423,16 +10227,393 @@ snapshots:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.5
+ markdown-table@3.0.4: {}
+
+ marked@16.4.2: {}
+
marked@17.0.1: {}
+ matcher@3.0.0:
+ dependencies:
+ escape-string-regexp: 4.0.0
+ optional: true
+
math-intrinsics@1.1.0: {}
+ mdast-util-find-and-replace@3.0.2:
+ dependencies:
+ '@types/mdast': 4.0.4
+ escape-string-regexp: 5.0.0
+ unist-util-is: 6.0.1
+ unist-util-visit-parents: 6.0.2
+
+ mdast-util-from-markdown@2.0.3:
+ dependencies:
+ '@types/mdast': 4.0.4
+ '@types/unist': 3.0.3
+ decode-named-character-reference: 1.3.0
+ devlop: 1.1.0
+ mdast-util-to-string: 4.0.0
+ micromark: 4.0.2
+ micromark-util-decode-numeric-character-reference: 2.0.2
+ micromark-util-decode-string: 2.0.1
+ micromark-util-normalize-identifier: 2.0.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+ unist-util-stringify-position: 4.0.0
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-gfm-autolink-literal@2.0.1:
+ dependencies:
+ '@types/mdast': 4.0.4
+ ccount: 2.0.1
+ devlop: 1.1.0
+ mdast-util-find-and-replace: 3.0.2
+ micromark-util-character: 2.1.1
+
+ mdast-util-gfm-footnote@2.1.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+ devlop: 1.1.0
+ mdast-util-from-markdown: 2.0.3
+ mdast-util-to-markdown: 2.1.2
+ micromark-util-normalize-identifier: 2.0.1
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-gfm-strikethrough@2.0.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+ mdast-util-from-markdown: 2.0.3
+ mdast-util-to-markdown: 2.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-gfm-table@2.0.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+ devlop: 1.1.0
+ markdown-table: 3.0.4
+ mdast-util-from-markdown: 2.0.3
+ mdast-util-to-markdown: 2.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-gfm-task-list-item@2.0.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+ devlop: 1.1.0
+ mdast-util-from-markdown: 2.0.3
+ mdast-util-to-markdown: 2.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-gfm@3.1.0:
+ dependencies:
+ mdast-util-from-markdown: 2.0.3
+ mdast-util-gfm-autolink-literal: 2.0.1
+ mdast-util-gfm-footnote: 2.1.0
+ mdast-util-gfm-strikethrough: 2.0.0
+ mdast-util-gfm-table: 2.0.0
+ mdast-util-gfm-task-list-item: 2.0.0
+ mdast-util-to-markdown: 2.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-mdx-expression@2.0.1:
+ dependencies:
+ '@types/estree-jsx': 1.0.5
+ '@types/hast': 3.0.4
+ '@types/mdast': 4.0.4
+ devlop: 1.1.0
+ mdast-util-from-markdown: 2.0.3
+ mdast-util-to-markdown: 2.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-mdx-jsx@3.2.0:
+ dependencies:
+ '@types/estree-jsx': 1.0.5
+ '@types/hast': 3.0.4
+ '@types/mdast': 4.0.4
+ '@types/unist': 3.0.3
+ ccount: 2.0.1
+ devlop: 1.1.0
+ mdast-util-from-markdown: 2.0.3
+ mdast-util-to-markdown: 2.1.2
+ parse-entities: 4.0.2
+ stringify-entities: 4.0.4
+ unist-util-stringify-position: 4.0.0
+ vfile-message: 4.0.3
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-mdxjs-esm@2.0.1:
+ dependencies:
+ '@types/estree-jsx': 1.0.5
+ '@types/hast': 3.0.4
+ '@types/mdast': 4.0.4
+ devlop: 1.1.0
+ mdast-util-from-markdown: 2.0.3
+ mdast-util-to-markdown: 2.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ mdast-util-phrasing@4.1.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+ unist-util-is: 6.0.1
+
+ mdast-util-to-hast@13.2.1:
+ dependencies:
+ '@types/hast': 3.0.4
+ '@types/mdast': 4.0.4
+ '@ungap/structured-clone': 1.3.0
+ devlop: 1.1.0
+ micromark-util-sanitize-uri: 2.0.1
+ trim-lines: 3.0.1
+ unist-util-position: 5.0.0
+ unist-util-visit: 5.1.0
+ vfile: 6.0.3
+
+ mdast-util-to-markdown@2.1.2:
+ dependencies:
+ '@types/mdast': 4.0.4
+ '@types/unist': 3.0.3
+ longest-streak: 3.1.0
+ mdast-util-phrasing: 4.1.0
+ mdast-util-to-string: 4.0.0
+ micromark-util-classify-character: 2.0.1
+ micromark-util-decode-string: 2.0.1
+ unist-util-visit: 5.1.0
+ zwitch: 2.0.4
+
+ mdast-util-to-string@4.0.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+
merge-anything@5.1.7:
dependencies:
is-what: 4.1.16
merge2@1.4.1: {}
+ mermaid@11.14.0:
+ dependencies:
+ '@braintree/sanitize-url': 7.1.2
+ '@iconify/utils': 3.1.0
+ '@mermaid-js/parser': 1.1.0
+ '@types/d3': 7.4.3
+ '@upsetjs/venn.js': 2.0.0
+ cytoscape: 3.33.1
+ cytoscape-cose-bilkent: 4.1.0(cytoscape@3.33.1)
+ cytoscape-fcose: 2.2.0(cytoscape@3.33.1)
+ d3: 7.9.0
+ d3-sankey: 0.12.3
+ dagre-d3-es: 7.0.14
+ dayjs: 1.11.20
+ dompurify: 3.3.3
+ katex: 0.16.44
+ khroma: 2.1.0
+ lodash-es: 4.18.1
+ marked: 16.4.2
+ roughjs: 4.6.6
+ stylis: 4.3.6
+ ts-dedent: 2.2.0
+ uuid: 11.1.0
+
+ micromark-core-commonmark@2.0.3:
+ dependencies:
+ decode-named-character-reference: 1.3.0
+ devlop: 1.1.0
+ micromark-factory-destination: 2.0.1
+ micromark-factory-label: 2.0.1
+ micromark-factory-space: 2.0.1
+ micromark-factory-title: 2.0.1
+ micromark-factory-whitespace: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-chunked: 2.0.1
+ micromark-util-classify-character: 2.0.1
+ micromark-util-html-tag-name: 2.0.1
+ micromark-util-normalize-identifier: 2.0.1
+ micromark-util-resolve-all: 2.0.1
+ micromark-util-subtokenize: 2.1.0
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-extension-gfm-autolink-literal@2.1.0:
+ dependencies:
+ micromark-util-character: 2.1.1
+ micromark-util-sanitize-uri: 2.0.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-extension-gfm-footnote@2.1.0:
+ dependencies:
+ devlop: 1.1.0
+ micromark-core-commonmark: 2.0.3
+ micromark-factory-space: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-normalize-identifier: 2.0.1
+ micromark-util-sanitize-uri: 2.0.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-extension-gfm-strikethrough@2.1.0:
+ dependencies:
+ devlop: 1.1.0
+ micromark-util-chunked: 2.0.1
+ micromark-util-classify-character: 2.0.1
+ micromark-util-resolve-all: 2.0.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-extension-gfm-table@2.1.1:
+ dependencies:
+ devlop: 1.1.0
+ micromark-factory-space: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-extension-gfm-tagfilter@2.0.0:
+ dependencies:
+ micromark-util-types: 2.0.2
+
+ micromark-extension-gfm-task-list-item@2.1.0:
+ dependencies:
+ devlop: 1.1.0
+ micromark-factory-space: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-extension-gfm@3.0.0:
+ dependencies:
+ micromark-extension-gfm-autolink-literal: 2.1.0
+ micromark-extension-gfm-footnote: 2.1.0
+ micromark-extension-gfm-strikethrough: 2.1.0
+ micromark-extension-gfm-table: 2.1.1
+ micromark-extension-gfm-tagfilter: 2.0.0
+ micromark-extension-gfm-task-list-item: 2.1.0
+ micromark-util-combine-extensions: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-factory-destination@2.0.1:
+ dependencies:
+ micromark-util-character: 2.1.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-factory-label@2.0.1:
+ dependencies:
+ devlop: 1.1.0
+ micromark-util-character: 2.1.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-factory-space@2.0.1:
+ dependencies:
+ micromark-util-character: 2.1.1
+ micromark-util-types: 2.0.2
+
+ micromark-factory-title@2.0.1:
+ dependencies:
+ micromark-factory-space: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-factory-whitespace@2.0.1:
+ dependencies:
+ micromark-factory-space: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-util-character@2.1.1:
+ dependencies:
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-util-chunked@2.0.1:
+ dependencies:
+ micromark-util-symbol: 2.0.1
+
+ micromark-util-classify-character@2.0.1:
+ dependencies:
+ micromark-util-character: 2.1.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-util-combine-extensions@2.0.1:
+ dependencies:
+ micromark-util-chunked: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-util-decode-numeric-character-reference@2.0.2:
+ dependencies:
+ micromark-util-symbol: 2.0.1
+
+ micromark-util-decode-string@2.0.1:
+ dependencies:
+ decode-named-character-reference: 1.3.0
+ micromark-util-character: 2.1.1
+ micromark-util-decode-numeric-character-reference: 2.0.2
+ micromark-util-symbol: 2.0.1
+
+ micromark-util-encode@2.0.1: {}
+
+ micromark-util-html-tag-name@2.0.1: {}
+
+ micromark-util-normalize-identifier@2.0.1:
+ dependencies:
+ micromark-util-symbol: 2.0.1
+
+ micromark-util-resolve-all@2.0.1:
+ dependencies:
+ micromark-util-types: 2.0.2
+
+ micromark-util-sanitize-uri@2.0.1:
+ dependencies:
+ micromark-util-character: 2.1.1
+ micromark-util-encode: 2.0.1
+ micromark-util-symbol: 2.0.1
+
+ micromark-util-subtokenize@2.1.0:
+ dependencies:
+ devlop: 1.1.0
+ micromark-util-chunked: 2.0.1
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+
+ micromark-util-symbol@2.0.1: {}
+
+ micromark-util-types@2.0.2: {}
+
+ micromark@4.0.2:
+ dependencies:
+ '@types/debug': 4.1.13
+ debug: 4.4.3
+ decode-named-character-reference: 1.3.0
+ devlop: 1.1.0
+ micromark-core-commonmark: 2.0.3
+ micromark-factory-space: 2.0.1
+ micromark-util-character: 2.1.1
+ micromark-util-chunked: 2.0.1
+ micromark-util-combine-extensions: 2.0.1
+ micromark-util-decode-numeric-character-reference: 2.0.2
+ micromark-util-encode: 2.0.1
+ micromark-util-normalize-identifier: 2.0.1
+ micromark-util-resolve-all: 2.0.1
+ micromark-util-sanitize-uri: 2.0.1
+ micromark-util-subtokenize: 2.1.0
+ micromark-util-symbol: 2.0.1
+ micromark-util-types: 2.0.2
+ transitivePeerDependencies:
+ - supports-color
+
micromatch@4.0.8:
dependencies:
braces: 3.0.3
@@ -8446,6 +10627,10 @@ snapshots:
mime@3.0.0: {}
+ mimic-response@1.0.1: {}
+
+ mimic-response@3.1.0: {}
+
minimatch@10.1.1:
dependencies:
'@isaacs/brace-expansion': 5.0.0
@@ -8593,14 +10778,25 @@ snapshots:
normalize-range@0.1.2: {}
+ normalize-url@6.1.0: {}
+
object-assign@4.1.1: {}
object-hash@3.0.0: {}
+ object-keys@1.1.1:
+ optional: true
+
omggif@1.0.10: {}
on-exit-leak-free@2.1.2: {}
+ once@1.4.0:
+ dependencies:
+ wrappy: 1.0.2
+
+ p-cancelable@2.1.1: {}
+
p-finally@1.0.0: {}
p-limit@2.3.0:
@@ -8627,6 +10823,8 @@ snapshots:
p-try@2.2.0: {}
+ package-manager-detector@1.6.0: {}
+
pako@1.0.11: {}
parse-bmfont-ascii@1.0.6: {}
@@ -8638,12 +10836,24 @@ snapshots:
xml-parse-from-string: 1.0.1
xml2js: 0.5.0
+ parse-entities@4.0.2:
+ dependencies:
+ '@types/unist': 2.0.11
+ character-entities-legacy: 3.0.0
+ character-reference-invalid: 2.0.1
+ decode-named-character-reference: 1.3.0
+ is-alphanumerical: 2.0.1
+ is-decimal: 2.0.1
+ is-hexadecimal: 2.0.1
+
parse-passwd@1.0.0: {}
parse5@7.3.0:
dependencies:
entities: 6.0.1
+ path-data-parser@0.1.0: {}
+
path-exists@3.0.0: {}
path-expression-matcher@1.1.3: {}
@@ -8659,6 +10869,8 @@ snapshots:
peek-readable@4.1.0: {}
+ pend@1.2.0: {}
+
picocolors@1.1.1: {}
picomatch@2.3.1: {}
@@ -8720,6 +10932,13 @@ snapshots:
pngjs@7.0.0: {}
+ points-on-curve@0.2.0: {}
+
+ points-on-path@0.2.1:
+ dependencies:
+ path-data-parser: 0.1.0
+ points-on-curve: 0.2.0
+
postcss-import@15.1.0(postcss@8.4.38):
dependencies:
postcss: 8.4.38
@@ -8782,6 +11001,10 @@ snapshots:
process@0.11.10: {}
+ progress@2.0.3: {}
+
+ property-information@7.1.0: {}
+
protobufjs@7.5.4:
dependencies:
'@protobufjs/aspromise': 1.1.2
@@ -8799,10 +11022,17 @@ snapshots:
proxy-from-env@1.1.0: {}
+ pump@3.0.4:
+ dependencies:
+ end-of-stream: 1.4.5
+ once: 1.4.0
+
queue-microtask@1.2.3: {}
quick-format-unescaped@4.0.4: {}
+ quick-lru@5.1.1: {}
+
react-dom@18.2.0(react@18.2.0):
dependencies:
loose-envify: 1.4.0
@@ -8852,6 +11082,57 @@ snapshots:
real-require@0.2.0: {}
+ rehype-harden@1.1.8:
+ dependencies:
+ unist-util-visit: 5.1.0
+
+ rehype-raw@7.0.0:
+ dependencies:
+ '@types/hast': 3.0.4
+ hast-util-raw: 9.1.0
+ vfile: 6.0.3
+
+ rehype-sanitize@6.0.0:
+ dependencies:
+ '@types/hast': 3.0.4
+ hast-util-sanitize: 5.0.2
+
+ remark-gfm@4.0.1:
+ dependencies:
+ '@types/mdast': 4.0.4
+ mdast-util-gfm: 3.1.0
+ micromark-extension-gfm: 3.0.0
+ remark-parse: 11.0.0
+ remark-stringify: 11.0.0
+ unified: 11.0.5
+ transitivePeerDependencies:
+ - supports-color
+
+ remark-parse@11.0.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+ mdast-util-from-markdown: 2.0.3
+ micromark-util-types: 2.0.2
+ unified: 11.0.5
+ transitivePeerDependencies:
+ - supports-color
+
+ remark-rehype@11.1.2:
+ dependencies:
+ '@types/hast': 3.0.4
+ '@types/mdast': 4.0.4
+ mdast-util-to-hast: 13.2.1
+ unified: 11.0.5
+ vfile: 6.0.3
+
+ remark-stringify@11.0.0:
+ dependencies:
+ '@types/mdast': 4.0.4
+ mdast-util-to-markdown: 2.1.2
+ unified: 11.0.5
+
+ remend@1.3.0: {}
+
require-directory@2.1.1: {}
require-in-the-middle@8.0.1:
@@ -8863,6 +11144,8 @@ snapshots:
reselect@4.1.8: {}
+ resolve-alpn@1.2.1: {}
+
resolve-from@5.0.0: {}
resolve-pkg-maps@1.0.0: {}
@@ -8873,10 +11156,26 @@ snapshots:
path-parse: 1.0.7
supports-preserve-symlinks-flag: 1.0.0
+ responselike@2.0.1:
+ dependencies:
+ lowercase-keys: 2.0.0
+
retry@0.13.1: {}
reusify@1.1.0: {}
+ roarr@2.15.4:
+ dependencies:
+ boolean: 3.2.0
+ detect-node: 2.1.0
+ globalthis: 1.0.4
+ json-stringify-safe: 5.0.1
+ semver-compare: 1.0.0
+ sprintf-js: 1.1.3
+ optional: true
+
+ robust-predicates@3.0.3: {}
+
rollup@4.55.1:
dependencies:
'@types/estree': 1.0.8
@@ -8910,10 +11209,19 @@ snapshots:
rou3@0.7.12: {}
+ roughjs@4.6.6:
+ dependencies:
+ hachure-fill: 0.5.2
+ path-data-parser: 0.1.0
+ points-on-curve: 0.2.0
+ points-on-path: 0.2.1
+
run-parallel@1.2.0:
dependencies:
queue-microtask: 1.2.3
+ rw@1.3.3: {}
+
s-js@0.4.9: {}
safe-buffer@5.2.1: {}
@@ -8930,10 +11238,18 @@ snapshots:
scheduler@0.27.0: {}
+ semver-compare@1.0.0:
+ optional: true
+
semver@6.3.1: {}
semver@7.7.4: {}
+ serialize-error@7.0.1:
+ dependencies:
+ type-fest: 0.13.1
+ optional: true
+
seroval-plugins@1.3.3(seroval@1.3.2):
dependencies:
seroval: 1.3.2
@@ -9014,8 +11330,13 @@ snapshots:
source-map@0.7.6: {}
+ space-separated-tokens@2.0.2: {}
+
split2@4.2.0: {}
+ sprintf-js@1.1.3:
+ optional: true
+
sql-escaper@1.3.3: {}
stage-js@1.0.0-alpha.17:
@@ -9026,6 +11347,29 @@ snapshots:
inherits: 2.0.4
readable-stream: 3.6.2
+ streamdown@2.5.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4):
+ dependencies:
+ clsx: 2.1.1
+ hast-util-to-jsx-runtime: 2.3.6
+ html-url-attributes: 3.0.1
+ marked: 17.0.1
+ mermaid: 11.14.0
+ react: 19.2.4
+ react-dom: 19.2.4(react@19.2.4)
+ rehype-harden: 1.1.8
+ rehype-raw: 7.0.0
+ rehype-sanitize: 6.0.0
+ remark-gfm: 4.0.1
+ remark-parse: 11.0.0
+ remark-rehype: 11.1.2
+ remend: 1.3.0
+ tailwind-merge: 3.5.0
+ unified: 11.0.5
+ unist-util-visit: 5.1.0
+ unist-util-visit-parents: 6.0.2
+ transitivePeerDependencies:
+ - supports-color
+
streamsearch@1.1.0: {}
string-width@4.2.3:
@@ -9038,6 +11382,11 @@ snapshots:
dependencies:
safe-buffer: 5.2.1
+ stringify-entities@4.0.4:
+ dependencies:
+ character-entities-html4: 2.1.0
+ character-entities-legacy: 3.0.0
+
strip-ansi@6.0.1:
dependencies:
ansi-regex: 5.0.1
@@ -9051,6 +11400,14 @@ snapshots:
style-mod@4.1.3: {}
+ style-to-js@1.1.21:
+ dependencies:
+ style-to-object: 1.0.14
+
+ style-to-object@1.0.14:
+ dependencies:
+ inline-style-parser: 0.2.7
+
styled-jsx@5.1.1(react@18.2.0):
dependencies:
client-only: 0.0.1
@@ -9061,6 +11418,8 @@ snapshots:
client-only: 0.0.1
react: 19.2.4
+ stylis@4.3.6: {}
+
sucrase@3.35.1:
dependencies:
'@jridgewell/gen-mapping': 0.3.13
@@ -9071,8 +11430,16 @@ snapshots:
tinyglobby: 0.2.15
ts-interface-checker: 0.1.13
+ sumchecker@3.0.1:
+ dependencies:
+ debug: 4.4.3
+ transitivePeerDependencies:
+ - supports-color
+
supports-preserve-symlinks-flag@1.0.0: {}
+ tailwind-merge@3.5.0: {}
+
tailwindcss@3.4.7:
dependencies:
'@alloc/quick-lru': 5.2.0
@@ -9133,6 +11500,8 @@ snapshots:
tinyexec@0.3.2: {}
+ tinyexec@1.0.4: {}
+
tinyglobby@0.2.15:
dependencies:
fdir: 6.5.0(picomatch@4.0.3)
@@ -9151,6 +11520,12 @@ snapshots:
tree-kill@1.2.2: {}
+ trim-lines@3.0.1: {}
+
+ trough@2.2.0: {}
+
+ ts-dedent@2.2.0: {}
+
ts-interface-checker@0.1.13: {}
tslib@2.8.1: {}
@@ -9199,6 +11574,9 @@ snapshots:
'@turbo/windows-64': 2.8.20
'@turbo/windows-arm64': 2.8.20
+ type-fest@0.13.1:
+ optional: true
+
typeid-js@1.2.0:
dependencies:
uuid: 10.0.0
@@ -9215,12 +11593,49 @@ snapshots:
undici-types@6.21.0: {}
+ undici-types@7.16.0: {}
+
undici-types@7.18.2: {}
undici@5.29.0:
dependencies:
'@fastify/busboy': 2.1.1
+ unified@11.0.5:
+ dependencies:
+ '@types/unist': 3.0.3
+ bail: 2.0.2
+ devlop: 1.1.0
+ extend: 3.0.2
+ is-plain-obj: 4.1.0
+ trough: 2.2.0
+ vfile: 6.0.3
+
+ unist-util-is@6.0.1:
+ dependencies:
+ '@types/unist': 3.0.3
+
+ unist-util-position@5.0.0:
+ dependencies:
+ '@types/unist': 3.0.3
+
+ unist-util-stringify-position@4.0.0:
+ dependencies:
+ '@types/unist': 3.0.3
+
+ unist-util-visit-parents@6.0.2:
+ dependencies:
+ '@types/unist': 3.0.3
+ unist-util-is: 6.0.1
+
+ unist-util-visit@5.1.0:
+ dependencies:
+ '@types/unist': 3.0.3
+ unist-util-is: 6.0.1
+ unist-util-visit-parents: 6.0.2
+
+ universalify@0.1.2: {}
+
update-browserslist-db@1.2.3(browserslist@4.28.1):
dependencies:
browserslist: 4.28.1
@@ -9235,6 +11650,23 @@ snapshots:
uuid@10.0.0: {}
+ uuid@11.1.0: {}
+
+ vfile-location@5.0.3:
+ dependencies:
+ '@types/unist': 3.0.3
+ vfile: 6.0.3
+
+ vfile-message@4.0.3:
+ dependencies:
+ '@types/unist': 3.0.3
+ unist-util-stringify-position: 4.0.0
+
+ vfile@6.0.3:
+ dependencies:
+ '@types/unist': 3.0.3
+ vfile-message: 4.0.3
+
vite-plugin-solid@2.11.10(solid-js@1.9.9)(vite@6.4.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2)):
dependencies:
'@babel/core': 7.28.6
@@ -9284,8 +11716,27 @@ snapshots:
optionalDependencies:
vite: 6.4.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2)
+ vscode-jsonrpc@8.2.0: {}
+
+ vscode-languageserver-protocol@3.17.5:
+ dependencies:
+ vscode-jsonrpc: 8.2.0
+ vscode-languageserver-types: 3.17.5
+
+ vscode-languageserver-textdocument@1.0.12: {}
+
+ vscode-languageserver-types@3.17.5: {}
+
+ vscode-languageserver@9.0.1:
+ dependencies:
+ vscode-languageserver-protocol: 3.17.5
+
+ vscode-uri@3.1.0: {}
+
w3c-keyname@2.2.8: {}
+ web-namespaces@2.0.1: {}
+
web-tree-sitter@0.25.10: {}
webidl-conversions@3.0.1: {}
@@ -9301,6 +11752,8 @@ snapshots:
string-width: 4.2.3
strip-ansi: 6.0.1
+ wrappy@1.0.2: {}
+
ws@8.19.0: {}
xml-parse-from-string@1.0.1: {}
@@ -9332,8 +11785,15 @@ snapshots:
y18n: 5.0.8
yargs-parser: 21.1.1
+ yauzl@2.10.0:
+ dependencies:
+ buffer-crc32: 0.2.13
+ fd-slicer: 1.1.0
+
yoga-layout@3.2.1: {}
zod@3.25.76: {}
zod@4.3.6: {}
+
+ zwitch@2.0.4: {}