diff --git a/CHANGELOG.md b/CHANGELOG.md index 96da6b1..fd29102 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,21 @@ project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +## [Unreleased] + +### Added + +- **Token economy — finish the task on fewer tokens** ([`electron/tuning.js`](electron/tuning.js)). Everyone now draws from the same free tiers, so the edge is tokens per finished task, not access. Six levers, all opt-outable by env: + - **Gateway compression on by default.** The sidecar turns on OmniRoute's RTK compression when the gateway is healthy. It rewrites tool-result text — the bulk of an agent's context — with cheap heuristics, no model call, and keeps failed-command output verbatim. Measured **9,812 → 3,170 tokens (68%)** on a realistic grep result. `OMNIWORK_COMPRESSION=off` disables it. + - **Housekeeping off the main model.** Titles, memory capture and compaction summaries run on the fast free pool (`auto/best-fast`), never the session's chosen model. `OMNIWORK_UTILITY_MODEL` overrides. + - **Step-level tiers.** With `auto`, grunt work runs on the fast pool and escalates to the coding pool (`auto/best-coding`) only when the fast model stalls — two failed steps, or six steps without finishing. A pinned model never tiers. `OMNIWORK_MODEL_TIERS=off` disables. + - **Rate-limit round-robin.** A 429 cools that model for a minute and rotates to the next connected free provider for the step, without a permanent switch — so stacked free tiers share the load instead of one draining first. Hard failures still switch as before. + - **Cheap delegate verifier.** An MCP delegation ends with a PASS/FAIL grade from the utility model, so the orchestrator re-delegates only when the work fell short — the expensive path is the caller re-reading and re-issuing. + - **Prompt-cache affinity.** Every request in a session carries a stable `x-session-id`, so the gateway keeps the unchanged system+history prefix cached upstream. + - **First-run nudge.** On first launch with nothing connected, the desktop app opens the free-models panel once so the OpenRouter catalog is one click away. + +## [0.12.0] — 2026-09-15 + ### Added - **ACP server** — OmniWork now speaks the [Agent Client Protocol](https://agentclientprotocol.com) @@ -25,6 +40,50 @@ project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). skills are published as slash commands, and `session/load` replays a transcript so a crashed harness resumes where it left off. Approval modes (`ask`, `edits`, `auto`, `plan`) are exposed as ACP session modes; `ask` is the default, because in ACP the client owns the permission boundary. +- **OpenCode as an engine** — OpenCode Zen's free models (Nemotron 3 Ultra, Nemotron 3.5 + Lightning, MiMo V2.5, Ling 3.0 Flash, Big Pickle) are real, keyless and tool-capable, and Zen + serves them only to OpenCode itself. So OmniWork runs OpenCode: `electron/opencode-engine.js` + starts `opencode serve` once per process and `OpenCodeAgent` wraps a session in the same + interface as the gateway agent — text deltas, tool calls, permission prompts and errors all map + onto OmniWork's events (reasoning on its own lane, so it never reads as the reply), and the + workspace rides on the official `x-opencode-directory` header — which also scopes the event + stream, one subscription per workspace. Nemotron 3.5 Lightning is the default because it answers + in seconds; Nemotron 3 Ultra stays available by name for when strength beats speed. + `opencode/` is a model like any other in the desktop menu, ACP config options and + `delegate`; and when no gateway model answers, desktop sessions, ACP turns and MCP delegations + finish on the engine and say so. Getting OpenCode never involves npm -g or a PATH edit: a clone + brings it in as an optional dependency (`opencode-ai`, the platform binary), the installers stage + it per platform at build time next to the bundled Node runtime, and the free-models panel, + `npm run providers connect opencode`, or the ACP `opencode` auth method download the same npm + package (~45 MB) into OmniWork's data folder, verified against the sha512 pinned in + `package-lock.json` before it runs — always from a user gesture, never an agent tool call. + OmniWork launches it by absolute path wherever it landed; the server it starts is protected by a + per-process secret; a mid-session switch to the engine carries the conversation with it; + `OMNIWORK_ENGINE_FALLBACK=off` opts out of the automatic switch. +- **Free models that stay up** — the gateway's built-in keyless pool turned out to be a set of + unofficial endpoints (a scraped hobby site, a restaurant's chat widget, a CLI shim) that + providers shut off without notice; on 2026-09-15 every one of them was dead and `auto` returned + 503 after 29 attempts. OmniWork now makes the durable kind of free one click away: a + *🆓 free models* panel in the app, `npm run providers` (also `npx omniwork-providers`), MCP tools + `list_providers` / `connect_provider`, and ACP auth methods `openrouter` / `local`. OpenRouter + connects through its PKCE flow (browser sign-in, no key to paste); Ollama Cloud, Kilo, Groq, + Cerebras, NVIDIA, Gemini and Mistral take a pasted key that is exercised once before it is kept; + Ollama, LM Studio, llama.cpp and vLLM are auto-detected and registered. Whatever is connected + becomes the default fallback chain for the MCP and ACP servers and for every desktop session, + live — strongest coder first, local last — so a retired free model is a hop, not a dead turn. + All of it goes through OmniRoute's own management API on loopback; nothing new is stored. +- **Pick the model, keep the answer** — headless agents no longer live and die by one model id. + ACP sessions expose the gateway catalog as a `model` config option (`session/set_config_option`, + the older `session/set_model`, or `_meta.model` on `session/new`), and the MCP `delegate` tools + take `model` / `fallback_models`, with a `list_models` tool to choose from. Behind both is a + fallback chain (`OMNIWORK_MODEL_FALLBACKS`): when the chosen model fails — a free catalog entry + retired upstream, a provider key you don't have, a quota — the same request goes to the next + model, the one that answers sticks for the rest of the session, and the switch is reported back + (`config_option_update` on ACP, a `[model: …]` note on MCP results). When every model fails the + error names each one and why, instead of a bare `Gateway 401`. A harness can now say "this free + coder, else this paid one" and stop babysitting the catalog. A dead gateway is still reported as + such — no model on the same socket would do better — and a provider that merely rejects + streaming still gets its non-streaming retry on the same model. - **Add to chat** — highlight any text in the transcript and a small pill offers to quote it into the composer, or press `⌘L` / `Ctrl+L`. The quote lands in the prompt as visible `> ` lines you can read and edit before sending, dimmed by a highlight layer behind the diff --git a/README.md b/README.md index c508552..3388b6d 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ delegate** *inside* Claude Code or Codex. | | | |---|---| -| 🆓 **Free & keyless** | Free models via `auto` routing, out of the box. Never rate-limited (auto-fallback across providers). | +| 🆓 **Free models** | `auto` routes the gateway's free pool out of the box, and one click connects a free provider that *stays* up (OpenRouter, Ollama Cloud, Groq, Gemini…) — see [Free models that stay up](#free-models-that-stay-up). | | 🖥️ **Claude Code UI** | A clean terminal: `⏺`/`⎿` tool calls, `✻` thinking, `>` prompt, `@`-file mentions, per-turn time + token counts. | | 📁 **Projects & memory** | Sessions live under projects. Durable `MEMORY.md` per project plus a global scope — it remembers what you teach it. | | 🎓 **Skills** | Claude Code–compatible `SKILL.md` packs, loaded on demand. Ships with Anthropic's public set; the agent can write and install more. | @@ -93,10 +93,12 @@ xattr -dr com.apple.quarantine /Applications/OmniWork.app ## Use OmniWork *inside* Claude Code / Codex — token saver 🪙 Don't want to fully switch? Keep your premium agent as the orchestrator and let it **delegate the -token-heavy grunt work to OmniWork's free models.** OmniWork ships an MCP server exposing two tools: +token-heavy grunt work to OmniWork's free models.** OmniWork ships an MCP server exposing these tools: -- `delegate(task, cwd?)` — OmniWork does the subtask autonomously on free models and returns a summary + changes -- `delegate_parallel(tasks[], cwd?)` — fan a batch out to parallel free-model subagents +- `delegate(task, cwd?, model?, fallback_models?)` — OmniWork does the subtask autonomously (free models by default) and returns a summary + changes +- `delegate_parallel(tasks[], cwd?, model?, fallback_models?)` — fan a batch out to parallel subagents +- `list_models()` — what the gateway can route right now, so you can pin a model and name what to try if it fails +- `list_providers()` / `connect_provider(provider)` — see which free providers are connected and connect one (OpenRouter opens the browser; `local` registers Ollama & co.). It takes no API key on purpose: keys are pasted in the app or the terminal, never by a model. Your expensive model spends tokens on the hard reasoning; OmniWork burns **free** tokens on the mechanical work, in the same project folder. @@ -151,6 +153,58 @@ matters — free models drift on instruction details. Treat the returned summary as a **claim, not evidence**, and verify before calling the work done. `npm run connect` installs this guidance so your agent applies it automatically. +## Fewer tokens per task 🗜️ + +Free tiers are the same for everyone now, so OmniWork competes on how little it spends finishing a task. The gateway compresses tool output by default (a real grep result: **9,812 → 3,170 tokens**), housekeeping and mechanical steps run on the fast free pool while real reasoning escalates to the coding pool, a rate-limited provider rotates instead of draining, and every session reuses one id so the gateway caches its prefix. All on by default, all opt-outable: + +| Env | Default | Effect | +|-----|---------|--------| +| `OMNIWORK_COMPRESSION` | on | `off` disables gateway-side tool-output compression | +| `OMNIWORK_MODEL_TIERS` | on | `off` runs `auto` on one tier instead of fast-then-escalate | +| `OMNIWORK_UTILITY_MODEL` | `auto/best-fast` | model for titles, memory, compaction summaries | + +## Free models that stay up 🆓 + +The gateway's built-in keyless pool is a set of unofficial endpoints that providers shut off +without notice — on a bad day every one of them is gone and `auto` returns 503. So OmniWork +makes the durable kind of free easy: real free tiers behind a free account, no card. + +| Provider | Free tier | Connect | +|---|---|---| +| **OpenRouter** | 20 free models, 18 with tool calling · 20 req/min, 50 req/day (1,000/day after a one-time $10 top-up) | one click — browser sign-in, no key to paste | +| **Ollama Cloud** | DeepSeek V4, Kimi K2.6, GLM 5.1, Gemma 4 on a "light usage" tier | paste a key | +| **Kilo Gateway** | `kilo-auto/free` router + Nemotron / MiniMax `:free` | paste a key | +| **Groq** | gpt-oss-120b at 30 req/min, 1,000 req/day; Qwen 3 32B | paste a key | +| **Cerebras**, **NVIDIA NIM**, **Gemini**, **Mistral** | free developer tiers | paste a key | +| **OpenCode engine** | Zen's free models with **no account**: Nemotron 3.5 Lightning (default, answers in seconds), MiMo V2.5, Big Pickle, Ling 3.0 Flash, Nemotron 3 Ultra (strongest, ~100 s a step) | ships with a clone and with the desktop app; otherwise one click downloads it (~45 MB) | +| **Ollama / LM Studio / llama.cpp / vLLM** | whatever runs on your machine | auto-detected | + +Three ways in, all the same code path: + +- **App** — *🆓 free models* in the sidebar. Connected providers become every session's fallback chain on the spot. +- **Terminal** — `npm run providers` shows status; `npm run providers connect openrouter` opens the browser; `npm run providers connect groq `; `npm run providers connect local`; `npm run providers connect opencode` downloads the engine if a clone or installer didn't bring it. Also `npx omniwork-providers`. +- **From a harness** — the MCP server has `list_providers` / `connect_provider`; the ACP server offers `openrouter` and `local` as auth methods. + +A pasted key is exercised once before it is kept, so a bad key never lands in the pool. What is +connected becomes the default fallback chain for the MCP and ACP servers (unless you set +`OMNIWORK_MODEL_FALLBACKS` yourself), ordered strongest coder first, local last. + +**The OpenCode engine is the floor.** OpenCode Zen only serves its free tier to OpenCode itself, so +OmniWork doesn't pretend to be OpenCode — it runs it. And nobody has to install anything or touch +their PATH: `npm install` brings OpenCode in as an optional dependency (`opencode-ai`, the binary +for your platform), the desktop installers stage it per platform at build time, and if it is +missing anyway one click fetches the same npm package (~45 MB) into OmniWork's data folder — +verified against the sha512 pinned in `package-lock.json` before a byte of it runs. OmniWork +always launches it by absolute path, and the server it starts answers only requests carrying a +per-process secret. Set `OMNIWORK_ENGINE_FALLBACK=off` if a failed turn should stay failed rather +than finish on the engine. With OpenCode installed, `opencode/` +runs a session on OpenCode's own headless server (`opencode serve`, the same thing Zed and acpx +drive) and its own tools, scoped to your workspace, streamed back as OmniWork events — text as +text, the model's reasoning on its own lane, tool calls as tool calls. Pick one in the model +menu, pass `model: "opencode/nemotron-3.5-lightning-free"` to `delegate`, or do nothing: when no +gateway model answers, the turn finishes on the engine and says so. What you give up there is +OmniWork's own skills and memory — OpenCode runs its tools, not ours. + ## Drive OmniWork from OpenClaw, Zed, or any ACP harness 🔌 The MCP server makes OmniWork a *tool* your agent calls. The **ACP server** makes it a full @@ -183,14 +237,33 @@ What the harness gets: | **The Agent Deck** | `spawn_subagents` shows up as *N* live parallel tool calls, not one opaque block | | **Skills as slash commands** | Installed skills are published via `available_commands_update` | | **Modes** | `ask` (default), `edits`, `auto`, `plan` — switch with `acpx omniwork set-mode plan` | +| **Model selection** | The gateway catalog as a `model` config option — `session/set_config_option`, the older `session/set_model`, or `_meta.model` on `session/new` — with a fallback chain if the pick fails | +| **Auth methods** | `authenticate({ methodId: "openrouter" })` opens the browser for a free OpenRouter key; `"local"` registers a running Ollama / LM Studio / llama.cpp / vLLM; `"opencode"` installs OpenCode for its free Zen models | | **Resumable sessions** | `session/load` replays the transcript, so a crashed harness picks up where it left off | Modes default to **ask** because ACP's whole point is that the client owns the permission boundary. Set `OMNIWORK_ACP_MODE=auto` if you'd rather it run unattended. -By default OmniWork runs on its own bundled OmniRoute gateway (free models). To spend a different -provider's budget instead, point it elsewhere — `OMNIWORK_BASE_URL`, `OMNIWORK_API_KEY`, and -`OMNIWORK_MODEL` apply to both the ACP and MCP servers. +By default OmniWork runs on its own bundled OmniRoute gateway on `auto` (the free pool). To +pin a model — a specific coder, or a paid one you've keyed in the router dashboard — pick it per +session (ACP: the `model` config option, `session/set_model`, or `_meta.model` on +`session/new`; MCP: the `model` parameter on `delegate`) or set `OMNIWORK_MODEL`. + +Free catalogs go stale — a pinned model can 401 as "not supported" the day its provider retires +it — so a fallback chain is always in play. By default it is built from whatever free providers +are [connected](#free-models-that-stay-up), strongest coder first, local server last; +`OMNIWORK_MODEL_FALLBACKS` (or `fallback_models` / `_meta.fallbackModels`) replaces it with your +own list, in order. The same request goes to the next model, the one that answers becomes the +session's model, and the switch is reported (a `config_option_update` on ACP, a `[model: …]` +note on MCP results). If every model fails, the error names each one and why. End the chain with +a paid model when the work must complete: + +```bash +OMNIWORK_MODEL=oc/some-free-coder OMNIWORK_MODEL_FALLBACKS=auto,anthropic/claude-sonnet-5 npx omniwork-acp +``` + +To spend a different provider's budget entirely, point the servers elsewhere — `OMNIWORK_BASE_URL` +and `OMNIWORK_API_KEY` apply to both. ## Build from source @@ -262,14 +335,17 @@ Locally built `.app`s are unsigned — same right-click → Open dance as above. ## Configuration -Works with zero config. To go beyond the free tier, click **router dashboard** in the app to add -provider keys (stored encrypted, locally), or pick a specific model in the status bar. +Works with zero config. To get a free tier that stays up, use **🆓 free models** in the app (or +`npm run providers`); to add any other provider key, click **router dashboard** (keys are stored +encrypted, locally). Pick a specific model in the status bar. | Env | Default | Purpose | |-----|---------|---------| | `OMNIWORK_GATEWAY_PORT` | `20128` | Gateway port | | `OMNIWORK_WORKSPACE` | — | Open a folder on launch | | `OMNIWORK_MODEL` | `auto` | Pin a model (MCP + ACP servers) | +| `OMNIWORK_MODEL_FALLBACKS` | connected providers | Comma-separated models to try, in order, when the model fails (MCP + ACP servers). Unset: built from connected free providers; set empty to disable | +| `OMNIWORK_ENGINE_FALLBACK` | on | `off` keeps a turn that no gateway model could serve as an error instead of finishing it on the OpenCode engine | | `OMNIWORK_BASE_URL` | — | Run headless servers against another OpenAI-compatible endpoint | | `OMNIWORK_API_KEY` | `omniwork` | Key for `OMNIWORK_BASE_URL` | | `OMNIWORK_ACP_MODE` | `ask` | Starting approval mode for ACP sessions | diff --git a/electron-builder-lite.json b/electron-builder-lite.json index 5cb5e81..e8e3230 100644 --- a/electron-builder-lite.json +++ b/electron-builder-lite.json @@ -37,26 +37,48 @@ "!node_modules/@ngrok/**", "!node_modules/react-dom/**", "!node_modules/@modelcontextprotocol/**", - "!node_modules/jsdom/**" + "!node_modules/jsdom/**", + "!node_modules/opencode-ai/**", + "!node_modules/opencode-*/**" ], "extraResources": [ - { "from": "build/runtime", "to": "runtime" } + { + "from": "build/runtime", + "to": "runtime" + } ], "directories": { "output": "dist", "buildResources": "assets" }, "win": { - "target": [{ "target": "nsis", "arch": ["x64"] }], + "target": [ + { + "target": "nsis", + "arch": [ + "x64" + ] + } + ], "artifactName": "OmniWork-Lite-Setup-${version}.${ext}" }, "mac": { - "target": [{ "target": "dmg", "arch": ["x64", "arm64"] }], + "target": [ + { + "target": "dmg", + "arch": [ + "x64", + "arm64" + ] + } + ], "artifactName": "OmniWork-Lite-${version}.${ext}", "category": "public.app-category.developer-tools" }, "linux": { - "target": ["AppImage"], + "target": [ + "AppImage" + ], "artifactName": "OmniWork-Lite-${version}.${ext}", "icon": "assets/icon.png", "category": "Development" diff --git a/electron/acp-server.js b/electron/acp-server.js old mode 100644 new mode 100755 index 5fd0f80..5d291aa --- a/electron/acp-server.js +++ b/electron/acp-server.js @@ -21,8 +21,7 @@ const fs = require("node:fs"); const path = require("node:path"); const { ensureShellPath } = require("./shell-path"); -const { Agent } = require("./agent"); -const { agentEnv, ensureGateway, prewarmGateway, DATA_DIR, SKILLS_DIR } = require("./headless"); +const { agentEnv, ensureGateway, prewarmGateway, resolveModelsLive, listModels, invalidateModels, noModelHint, providers, makeAgent, isNoModelFailure, engineFallbackModel, opencode, DATA_DIR, SKILLS_DIR } = require("./headless"); const skillsApi = require("./skills"); ensureShellPath(); // ACP clients can launch us with a minimal environment too @@ -45,6 +44,12 @@ const DEFAULT_MODE = MODES.some((m) => m.id === process.env.OMNIWORK_ACP_MODE) ? process.env.OMNIWORK_ACP_MODE : "ask"; +const AUTH_METHODS = [ + { id: "openrouter", name: "Connect OpenRouter (free models)", description: "Opens your browser to create a free OpenRouter key — 20 free models, 18 with tool calling. No key to paste." }, + { id: "local", name: "Use a local model server", description: "Registers Ollama, LM Studio, llama.cpp, or vLLM if one is running on this machine." }, + { id: "opencode", name: "Get OpenCode (free Zen models, no account)", description: "Downloads OpenCode's official release (~45 MB) into OmniWork's data folder — no npm, no PATH. OmniWork then runs OpenCode's own server as an engine for its free models: Nemotron 3.5 Lightning, MiMo V2.5, Big Pickle, Ling 3.0 Flash, Nemotron 3 Ultra." }, +]; + const TOOL_KIND = { list_dir: "read", read_file: "read", read_knowledge: "read", use_skill: "read", write_file: "edit", edit_file: "edit", @@ -143,13 +148,16 @@ function persist(sess) { fs.mkdirSync(STORE_DIR, { recursive: true }); fs.writeFileSync(sessionFile(sess.id), JSON.stringify({ id: sess.id, cwd: sess.cwd, mode: sess.mode, + model: sess.agent.model, fallbackModels: sess.agent.fallbackModels, + engineSession: sess.agent.isEngine ? sess.agent.sessionID : null, messages: sess.agent.messages.slice(-200), })); } catch (e) { log("persist failed:", e.message); } } -async function buildSession({ id, cwd, mode, messages }) { +async function buildSession({ id, cwd, mode, messages, model, fallbackModels, engineSession }) { const gw = await ensureGateway(log); + const models = await resolveModelsLive(gw, { model, fallbackModels }); const sess = { id, cwd, mode: mode || DEFAULT_MODE, sink: () => {}, // replaced per turn @@ -157,20 +165,32 @@ async function buildSession({ id, cwd, mode, messages }) { pendingPermissions: new Set(), agent: null, }; - sess.agent = new Agent({ + sess.gw = gw; + attachAgent(sess, models.model, models.fallbackModels, { messages: Array.isArray(messages) && messages.length ? messages : null, sessionID: engineSession || null }); + sessions.set(id, sess); + return sess; +} + +// The session's agent: OmniWork's loop on the gateway, or the OpenCode engine +// for `opencode/…` models. Rebuilt when a model change crosses that line. +function attachAgent(sess, model, fallbackModels, { messages = null, sessionID = null } = {}) { + const gw = sess.gw; + sess.agent = makeAgent({ baseUrl: gw.baseUrl, apiKey: gw.apiKey, - model: process.env.OMNIWORK_MODEL || "auto", - workspace: cwd, + model, + fallbackModels, + messages, // the engine carries these into its first prompt; the gateway agent restores them below + sessionID, // an OpenCode session to resume + workspace: sess.cwd, canSpawn: true, approvalMode: sess.mode, approver: (callId, name, args, preview) => sess.approve(callId, name, args, preview), emit: (type, payload) => sess.sink(type, payload), - ...agentEnv(cwd), + ...agentEnv(sess.cwd), }); - if (Array.isArray(messages) && messages.length) sess.agent.messages = messages; - sessions.set(id, sess); - return sess; + if (!sess.agent.isEngine && Array.isArray(messages) && messages.length) sess.agent.messages = messages; + return sess.agent; } // Skills become ACP slash commands, so `/deep-research` in the client's prompt @@ -191,6 +211,69 @@ function pushCommands(sess) { }); } +// ── model selection ─────────────────────────────────────────────── +// The model is an ACP session config option (category "model"), so a client +// with a model picker shows the gateway's catalog and `session/set_config_option` +// switches it; the pre-config-option `session/set_model` is honored too. A +// harness without either sends `_meta.model` (and `_meta.fallbackModels`) on +// `session/new`. Whatever is chosen, the fallback chain still applies — a +// pinned model that fails falls through to the next one, and the switch is +// pushed back as a `config_option_update`. +const MAX_MODEL_OPTIONS = 300; + +async function modelOption(sess) { + const current = sess.agent.model; + const chain = sess.agent.fallbackModels; + let catalog = []; + try { catalog = await listModels(await ensureGateway(log)); } catch {} + const options = []; + const seen = new Set(); + let engine = []; + if (opencode.available()) { try { engine = await opencode.getEngine().models(); } catch {} } + for (const id of [current, ...chain, ...engine.map((m) => m.id), ...catalog]) { + if (!id || seen.has(id)) continue; + seen.add(id); + const n = chain.indexOf(id); + const notes = []; + if (n >= 0) notes.push(`Fallback #${n + 1}`); + if (id === "auto") notes.push("free pool, routed by the gateway"); + if (opencode.isEngineModel(id)) notes.push("OpenCode engine · free, no account"); + options.push({ value: id, name: id, ...(notes.length ? { description: notes.join(" · ") } : {}) }); + if (options.length >= MAX_MODEL_OPTIONS) break; + } + return { + id: "model", name: "Model", category: "model", type: "select", + description: "Model the agent runs on. If it fails (retired id, provider key, quota) OmniWork continues on the next model in its fallback chain.", + currentValue: current, options, + }; +} + +async function configOptionsFor(sess) { return [await modelOption(sess)]; } + +// What a scripted harness reads instead of parsing the option list. +function sessionMeta(sess) { + return { omniwork: { model: sess.agent.model, fallbackModels: sess.agent.fallbackModels } }; +} + +async function setModel(sess, modelId) { + const id = String(modelId == null ? "" : modelId).trim(); + if (!id) throw new RpcError(-32602, "model id is required"); + if (sess.running) throw new RpcError(-32000, "cannot change the model while a prompt is running"); + const catalog = await listModels(await ensureGateway(log)).catch(() => []); + // Not an error: passthrough providers accept ids the catalog doesn't list. + if (catalog.length && !catalog.includes(id)) log(`model ${id} is not in the gateway catalog — passing it through`); + if (Boolean(sess.agent.isEngine) !== opencode.isEngineModel(id)) { + attachAgent(sess, id, sess.agent.fallbackModels.filter((m) => m !== id), { messages: sess.agent.messages }); + } else { + sess.agent.model = id; + sess.agent.fallbackModels = sess.agent.fallbackModels.filter((m) => m !== id); + } + persist(sess); + const configOptions = await configOptionsFor(sess); + notify("session/update", { sessionId: sess.id, update: { sessionUpdate: "config_option_update", configOptions } }); + return configOptions; +} + // ── the prompt turn ─────────────────────────────────────────────── async function runTurn(sess, blocks) { const { text, images } = decodePrompt(blocks); @@ -217,6 +300,12 @@ async function runTurn(sess, blocks) { if (p.chunk) up({ sessionUpdate: "agent_message_chunk", messageId, content: { type: "text", text: p.chunk } }); break; + // The OpenCode engine streams the model's reasoning separately; ACP has + // a native lane for it. + case "reasoning_delta": + if (p.chunk) up({ sessionUpdate: "agent_thought_chunk", messageId, content: { type: "text", text: p.chunk } }); + break; + // `assistant` repeats what the deltas already streamed — dropping it // avoids showing every reply twice. case "assistant": @@ -274,10 +363,13 @@ async function runTurn(sess, blocks) { const acpId = `t${++toolSeq}`; tools.set("sub:" + p.subId, { acpId, name: "subagent", args: {} }); up({ sessionUpdate: "tool_call", toolCallId: acpId, title: `subagent: ${p.title}`, kind: "think", status: "in_progress" }); - } else if (p.kind === "tool" || p.kind === "text" || p.kind === "error") { + } else if (p.kind === "tool" || p.kind === "text" || p.kind === "error" || p.kind === "model") { const t = tools.get("sub:" + p.subId); if (!t) break; - const line = p.kind === "tool" ? `→ ${p.tool}` : p.kind === "error" ? `error: ${p.message}` : String(p.snippet || ""); + const line = p.kind === "tool" ? `→ ${p.tool}` + : p.kind === "error" ? `error: ${p.message}` + : p.kind === "model" ? `⇄ ${p.from} failed — continuing on ${p.to}` + : String(p.snippet || ""); up({ sessionUpdate: "tool_call_update", toolCallId: t.acpId, status: "in_progress", content: [{ type: "content", content: { type: "text", text: line + "\n" } }], @@ -289,6 +381,12 @@ async function runTurn(sess, blocks) { break; } + case "model_switch": + configOptionsFor(sess) + .then((configOptions) => up({ sessionUpdate: "config_option_update", configOptions })) + .catch(() => {}); + break; + case "context": up({ sessionUpdate: "usage_update", @@ -355,13 +453,30 @@ async function runTurn(sess, blocks) { try { await sess.agent.send(text, images); + // No gateway model answered, but OpenCode is installed: finish the turn on + // its engine and keep the session there. The client sees the switch as a + // message and a config_option_update, same as any other model change. + if (failure && isNoModelFailure(failure) && !sess.agent.isEngine && !sess.agent.aborted) { + const model = await engineFallbackModel(); + if (model) { + const prevFailure = failure; + failure = null; + attachAgent(sess, model, [], { messages: sess.agent.messages }); + up({ sessionUpdate: "agent_message_chunk", messageId: `sys${Date.now().toString(36)}`, content: { type: "text", text: `⇄ no gateway model answered (${prevFailure.split("\n")[0].slice(0, 120)}) — continuing on the OpenCode engine (${model})\n` } }); + configOptionsFor(sess).then((configOptions) => up({ sessionUpdate: "config_option_update", configOptions })).catch(() => {}); + await sess.agent.send(text, images); + } + } } finally { sess.sink = () => {}; sess.approve = async () => false; persist(sess); } - if (failure) throw new RpcError(-32000, failure); + if (failure) { + if (/All models failed|Gateway (401|403|429|503)/.test(failure)) failure += "\n\n" + noModelHint(); + throw new RpcError(-32000, failure); + } return { stopReason }; } @@ -380,23 +495,46 @@ const handlers = { mcpCapabilities: { http: false, sse: false }, }, agentInfo: { name: "omniwork", title: "OmniWork", version: VERSION }, - authMethods: [], + // Not required — the gateway is local and keyless — but the way an ACP + // client can give OmniWork a free provider that actually stays up. + authMethods: AUTH_METHODS, }; }, - // No auth: the gateway is local and keyless. Declared so clients that probe - // the method get a clean result instead of "unknown method". - async authenticate() { return {}; }, + // Sessions never *require* auth; `authenticate` is how a client connects a + // free provider. `openrouter` opens the user's browser for a one-click key + // (PKCE); `local` registers model servers running on this machine. + async authenticate(params) { + const methodId = params && params.methodId; + if (!methodId) return {}; + if (!AUTH_METHODS.some((m) => m.id === methodId)) throw new RpcError(-32602, `unknown auth method: ${methodId}`); + const gw = await ensureGateway(log); + const result = await providers.connect(gw, methodId, { install: true, onUrl: (url) => log("open this URL to connect OpenRouter:", url) }); + invalidateModels(); + const chain = providers.suggestChain(await listModels(gw)); + for (const sess of sessions.values()) sess.agent.fallbackModels = chain.filter((m) => m !== sess.agent.model); + log("connected", methodId, JSON.stringify(result).slice(0, 200)); + return {}; + }, async "session/new"(params) { const cwd = params && params.cwd; if (!cwd || !path.isAbsolute(cwd)) throw new RpcError(-32602, "cwd must be an absolute path"); if (!fs.existsSync(cwd)) throw new RpcError(-32602, `cwd does not exist: ${cwd}`); const id = `sess_${Date.now().toString(36)}_${++sessionSeq}`; - const sess = await buildSession({ id, cwd, mode: DEFAULT_MODE }); + const meta = (params && params._meta) || {}; + const sess = await buildSession({ + id, cwd, mode: DEFAULT_MODE, + model: meta.model, fallbackModels: meta.fallbackModels ?? meta.fallback_models, + }); persist(sess); setTimeout(() => pushCommands(sess), 0); // after we've returned the sessionId - return { sessionId: id, modes: { currentModeId: sess.mode, availableModes: MODES } }; + return { + sessionId: id, + modes: { currentModeId: sess.mode, availableModes: MODES }, + configOptions: await configOptionsFor(sess), + _meta: sessionMeta(sess), + }; }, async "session/load"(params) { @@ -408,7 +546,10 @@ const handlers = { let saved = null; try { saved = JSON.parse(fs.readFileSync(sessionFile(id), "utf8")); } catch {} if (!saved) throw new RpcError(-32602, `unknown session: ${id}`); - sess = await buildSession({ id, cwd: cwd || saved.cwd, mode: saved.mode, messages: saved.messages }); + sess = await buildSession({ + id, cwd: cwd || saved.cwd, mode: saved.mode, messages: saved.messages, + model: saved.model, fallbackModels: saved.fallbackModels, engineSession: saved.engineSession, + }); } // ACP requires the whole conversation to be replayed as updates *before* we // answer the request. @@ -428,7 +569,11 @@ const handlers = { }); } pushCommands(sess); - return { modes: { currentModeId: sess.mode, availableModes: MODES } }; + return { + modes: { currentModeId: sess.mode, availableModes: MODES }, + configOptions: await configOptionsFor(sess), + _meta: sessionMeta(sess), + }; }, async "session/prompt"(params) { @@ -451,6 +596,22 @@ const handlers = { notify("session/update", { sessionId: sess.id, update: { sessionUpdate: "current_mode_update", currentModeId: modeId } }); return {}; }, + + async "session/set_config_option"(params) { + const sess = sessions.get(params && params.sessionId); + if (!sess) throw new RpcError(-32602, `unknown session: ${params && params.sessionId}`); + const configId = params && params.configId; + if (configId !== "model") throw new RpcError(-32602, `unknown config option: ${configId}`); + return { configOptions: await setModel(sess, params.value) }; + }, + + // The pre-config-option way to pick a model; some clients still speak it. + async "session/set_model"(params) { + const sess = sessions.get(params && params.sessionId); + if (!sess) throw new RpcError(-32602, `unknown session: ${params && params.sessionId}`); + await setModel(sess, params && params.modelId); + return {}; + }, }; const notifications = { diff --git a/electron/agent.js b/electron/agent.js index a9a9ce9..9e45786 100644 --- a/electron/agent.js +++ b/electron/agent.js @@ -89,11 +89,55 @@ function subLabel(name, args) { return `${label} ${String(a || "").slice(0, 40)}`.trim(); } +const hasContent = (m) => Boolean(m && ((m.content && m.content.trim()) || (m.tool_calls && m.tool_calls.length))); + +// Accepts an array or a comma-separated string; drops blanks, dups, and the primary. +function normalizeFallbacks(list, primary) { + const raw = Array.isArray(list) ? list : String(list || "").split(","); + const out = []; + for (const m of raw) { + const id = String(m || "").trim(); + if (id && id !== primary && !out.includes(id)) out.push(id); + } + return out; +} + +// Which failures are worth trying another model for: auth, quota, a retired +// id, a provider 5xx — the gateway is fine, that model is not. A 400 counts +// only when it names the model (OmniRoute maps upstream "unsupported model" +// to 400); a malformed request or an oversized context (413) would fail the +// same way on every model, and replaying the whole conversation to each of +// them helps nobody. A dead socket propagates untouched for the same reason. +const MODEL_STATUS = new Set([401, 403, 404, 429, 500, 502, 503, 504]); +const MODEL_WORDS = /\bmodel\b|unsupported|unavailable|not (found|supported)|no such|retired|combo/i; +const isModelFailure = (err) => { + if (!err) return false; + if (err.modelFailure) return true; + const s = err.status; + if (!Number.isFinite(s)) return false; + if (MODEL_STATUS.has(s)) return true; + return (s === 400 || s === 422) && MODEL_WORDS.test(String(err.message || "")); +}; +const failureSignature = (err) => `${err.status || 0}:${String(err.message || "").replace(/^[^:]*: /, "").slice(0, 160)}`; +const tuning = require("./tuning"); + class Agent { - constructor({ baseUrl, apiKey, model, workspace, emit, mcp, memory = null, skillsDir = null, browser = null, canSpawn = true, depth = 0, approvalMode = "auto", approver = null, streaming = true }) { + constructor({ baseUrl, apiKey, model, fallbackModels = [], workspace, emit, mcp, memory = null, skillsDir = null, browser = null, canSpawn = true, depth = 0, approvalMode = "auto", approver = null, streaming = true, utilityModel, tiers, sessionId } = {}) { this.baseUrl = baseUrl.replace(/\/$/, ""); this.apiKey = apiKey; this.model = model || "auto"; + // Tried in order when `model` fails. A fallback that answers becomes the + // session's model from then on — one failed request per session, not one + // per step — and the switch is announced through `model_switch`. + this.fallbackModels = normalizeFallbacks(fallbackModels, this.model); + this.modelSwitches = []; // [{ from, to, reason }] — what callers report back + // Token economy (see electron/tuning.js). The session id is stable so the + // gateway keeps prompt-cache affinity; the utility model runs housekeeping; + // tiers run grunt work on the fast pool and escalate to the coding pool. + this.sessionId = sessionId || tuning.newSessionId(); + this.utilityModel = utilityModel || tuning.utilityModel(this.model); + this.tiers = tiers !== undefined ? tiers : tuning.tiersFor(this.model); + this.cooling = new Map(); // model -> ms timestamp it is rate-limited until this.workspace = workspace; this.emit = emit; // (event, payload) => void this.mcp = mcp || null; @@ -206,18 +250,24 @@ class Agent { // One-off model call outside the session's message history (summaries, // titles, memory capture). - async oneShot(prompt) { - const res = await fetch(`${this.baseUrl}/chat/completions`, { - method: "POST", - signal: AbortSignal.timeout(60_000), - headers: { "Content-Type": "application/json", Authorization: `Bearer ${this.apiKey}` }, - body: JSON.stringify({ model: this.model, messages: [{ role: "user", content: prompt }], temperature: 0.2 }), - }); - if (!res.ok) throw new Error(`Gateway ${res.status}`); - const data = await res.json(); - const content = data.choices?.[0]?.message?.content || ""; - this.#addUsage(data.usage, content.length); // counts only while a turn is active - return content; + async oneShot(prompt, { model = this.utilityModel } = {}) { + const call = async (m) => { + const res = await fetch(`${this.baseUrl}/chat/completions`, { + method: "POST", + signal: AbortSignal.timeout(60_000), + headers: { "Content-Type": "application/json", Authorization: `Bearer ${this.apiKey}`, "x-session-id": this.sessionId }, + body: JSON.stringify({ model: m, messages: [{ role: "user", content: prompt }], temperature: 0.2 }), + }); + if (!res.ok) { const e = new Error(`Gateway ${res.status}`); e.status = res.status; throw e; } + const data = await res.json(); + const content = data.choices?.[0]?.message?.content || ""; + this.#addUsage(data.usage, content.length); // counts only while a turn is active + return content; + }; + // Housekeeping runs on the cheap utility model; if the gateway doesn't know + // that id (e.g. a raw OpenAI base URL), fall back to the session's model once. + try { return await call(model); } + catch (e) { if (model !== this.model && (e.status === 400 || e.status === 404)) return await call(this.model); throw e; } } #emitContext() { @@ -234,31 +284,115 @@ class Agent { return force ? "Nothing to compact yet — the conversation is still short." : null; } + // One model round-trip, walking the fallback chain when the current model + // fails. Free catalogs go stale — an advertised model can 401 as "not + // supported" the day a provider retires it — and a pinned paid model can be + // out of quota. Either way the caller wants an answer, not a dead turn, so + // the next model in the chain gets the same request. When every model fails, + // the error names each one and why, which is what a driving harness needs to + // fix its configuration. async callModel() { + const now = Date.now(); + const full = [this.model, ...this.fallbackModels.filter((m) => m !== this.model)]; + // Skip models still cooling from a recent 429, unless that leaves nothing. + let chain = full.filter((m) => !(this.cooling.get(m) > now)); + if (!chain.length) chain = full; + const failures = []; + let lastErr = null; + let lastSig = null; + let transientPrimary = false; // primary only hit 429 — keep it, don't switch + for (let i = 0; i < chain.length; i++) { + const model = chain[i]; + const last = i === chain.length - 1; + let msg; + try { msg = await this.#callOnce(model); } + catch (err) { + if (this.aborted || !isModelFailure(err)) throw err; + failures.push(`${model}: ${err.message}`); + // A 429 is transient load, not a dead model: cool it for a minute and + // rotate to the next provider, but keep the primary for later steps so + // connected free tiers share the load instead of one draining first. + if (err.status === 429) { + this.cooling.set(model, Date.now() + 60_000); + if (model === this.model) transientPrimary = true; + lastErr = err; continue; + } + // Two models failing identically is the gateway talking, not the + // models; walking further would only replay the conversation again. + const sig = failureSignature(err); + if (lastSig !== null && sig === lastSig) { lastErr = err; failures.push("(stopped: the next model failed the same way — this is the gateway, not the model)"); break; } + lastSig = sig; lastErr = err; + continue; + } + // An empty reply is the other way a free provider "fails": another + // model while one is queued, otherwise an error — a blank "done" would + // hide it, and the caller may have an engine to fall back to. + if (!hasContent(msg)) { + failures.push(`${model}: empty response`); + if (!last) continue; + lastErr = new Error(`${model}: empty response`); lastErr.modelFailure = true; + break; + } + // Rotating past a rate-limited primary is temporary — don't make the + // switch permanent, so the primary is retried once its cooldown passes. + if (model !== this.model && !transientPrimary) this.#switchModel(model, failures.join("; ")); + return msg; + } + // One model, no chain: the gateway's own error, exactly as before. + if (chain.length === 1 && lastErr) throw lastErr; + const err = new Error(`All models failed:\n- ${failures.join("\n- ")}`); + err.modelFailure = true; + throw err; + } + + // Tiering: grunt work runs on the fast pool; when it stalls we bring in the + // coding pool for the rest of the turn. Both are free `auto` routing, so this + // trades a little latency for quality only when the cheap model is struggling. + #escalate(reason) { + if (!this.tiers || this.model !== this.tiers.fast) return; + this.model = this.tiers.strong; + this._tierFails = 0; + this.emit("system", { content: `⇱ escalating to the coding tier (${reason})` }); + } + + #switchModel(to, reason) { + const from = this.model; + this.model = to; + this.modelSwitches.push({ from, to, reason }); + this.emit("model_switch", { from, to, reason }); + this.emit("system", { content: `⇄ ${from} failed (${reason.slice(0, 160)}) — continuing on ${to}` }); + } + + async #callOnce(model) { // Headless callers (MCP delegation) throw the deltas away, so the streaming // attempt buys nothing — and when free `auto` routing lands on a provider // that returns an empty stream, it costs a whole second request per step. // One request per step is dramatically faster there. - if (!this.streaming) return await this.#requestModel(false); + if (!this.streaming) return await this.#requestModel(false, model); // Try streaming for a live feel. Free `auto` routing hits many providers and // some return empty streams — if that happens, fall back to a reliable // non-streaming request. let streamed = null; - try { streamed = await this.#requestModel(true); } catch { streamed = null; } - if (streamed && ((streamed.content && streamed.content.trim()) || (streamed.tool_calls && streamed.tool_calls.length))) { - return streamed; + try { streamed = await this.#requestModel(true, model); } + catch (err) { + // Auth and unknown-model rejections don't depend on streaming — don't pay + // a second request to learn the same thing. Anything else (a provider that + // rejects stream_options, a flaky 5xx) still gets the non-streaming retry. + if (err.status === 401 || err.status === 403 || err.status === 404) throw err; + streamed = null; } - return await this.#requestModel(false); + if (hasContent(streamed)) return streamed; + return await this.#requestModel(false, model); } - async #requestModel(stream) { + async #requestModel(stream, model = this.model) { const res = await fetch(`${this.baseUrl}/chat/completions`, { method: "POST", signal: this.abortCtl?.signal, - headers: { "Content-Type": "application/json", Authorization: `Bearer ${this.apiKey}` }, + headers: { "Content-Type": "application/json", Authorization: `Bearer ${this.apiKey}`, "x-session-id": this.sessionId }, body: JSON.stringify({ - model: this.model, + model, messages: this.messages, tools: this.toolSchema(), tool_choice: "auto", @@ -272,7 +406,9 @@ class Agent { }); if (!res.ok) { const body = await res.text().catch(() => ""); - throw new Error(`Gateway ${res.status}: ${body.slice(0, 500)}`); + const err = new Error(`Gateway ${res.status}: ${body.slice(0, 500)}`); + err.status = res.status; + throw err; } const ctype = res.headers.get("content-type") || ""; if (stream && ctype.includes("event-stream") && res.body) { @@ -282,7 +418,7 @@ class Agent { } const data = await res.json(); const choice = data.choices && data.choices[0]; - if (!choice) throw new Error("No choices returned from gateway"); + if (!choice) { const err = new Error("No choices returned from gateway"); err.modelFailure = true; throw err; } this.#addUsage(data.usage, ((choice.message && choice.message.content) || "").length); if (choice.message && choice.message.content) this.emit("assistant_delta", { chunk: choice.message.content }); return choice.message; @@ -359,7 +495,8 @@ class Agent { const title = t.title || `subagent ${i + 1}`; this.emit("subagent", { groupId, subId, title, kind: "start" }); const child = new Agent({ - baseUrl: this.baseUrl, apiKey: this.apiKey, model: this.model, + baseUrl: this.baseUrl, apiKey: this.apiKey, model: this.model, fallbackModels: this.fallbackModels, + utilityModel: this.utilityModel, tiers: this.tiers, workspace: this.workspace, mcp: this.mcp, browser: this.browser, canSpawn: false, depth: this.depth + 1, // Nobody reads a subagent's token-by-token output — only its tool // labels and final summary. Skipping the stream attempt halves the @@ -369,6 +506,7 @@ class Agent { if (type === "tool_call") this.emit("subagent", { groupId, subId, kind: "tool", tool: subLabel(payload.name, payload.args) }); else if (type === "assistant") this.emit("subagent", { groupId, subId, kind: "text", snippet: String(payload.content || "").slice(0, 160) }); else if (type === "error") this.emit("subagent", { groupId, subId, kind: "error", message: payload.message }); + else if (type === "model_switch") this.emit("subagent", { groupId, subId, kind: "model", from: payload.from, to: payload.to }); }, }); try { await child.send(t.prompt || t.task || title); } @@ -388,6 +526,10 @@ class Agent { this.turnUndo = new Map(); this.undoAvailable = false; this.turnStats = { startedAt: Date.now(), inTokens: 0, outTokens: 0, estimated: false }; + // Start each turn on the fast tier (grunt work is cheap); escalation below + // brings in the coding tier if the fast model stalls. + if (this.tiers && [tuning.AUTO, this.tiers.fast, this.tiers.strong].includes(this.model)) this.model = this.tiers.fast; + this._tierFails = 0; // Refresh the system prompt with current project instructions (AGENTS.md, etc.). const mem = this.loadProjectMemory(); this.messages[0] = { @@ -412,6 +554,11 @@ class Agent { if (note) this.emit("system", { content: "⛁ " + note }); } catch {} this.#emitContext(); + // Escalate when the fast tier shows trouble late in the turn, or as a hard + // backstop deep in — not on raw step count, so a fast model steadily + // editing many files stays cheap instead of jumping to the coding tier. + if (step >= 8 && this._tierFails > 0) this.#escalate("stalling on the fast tier"); + else if (step >= Math.floor(MAX_STEPS / 2)) this.#escalate("halfway through the step budget"); this.emit("thinking", { step }); let msg; @@ -504,6 +651,8 @@ class Agent { this.emit("tool_result", { id: call.id, name, result }); this.messages.push({ role: "tool", tool_call_id: call.id, content: result }); + if (tuning.toolFailed(result)) { if (++this._tierFails >= 2) this.#escalate("two failed steps in a row"); } + else this._tierFails = 0; } } this.emit("error", { message: `Reached max steps (${MAX_STEPS}) without finishing.` }); diff --git a/electron/headless.js b/electron/headless.js index 8667414..15f4c34 100644 --- a/electron/headless.js +++ b/electron/headless.js @@ -12,6 +12,9 @@ const path = require("node:path"); const { Gateway, PORT } = require("./sidecar"); const { ProjectManager } = require("./projects"); const { BrowserManager } = require("./browser"); +const providers = require("./providers"); +const { Agent } = require("./agent"); +const opencode = require("./opencode-engine"); const HOST = "127.0.0.1"; @@ -93,8 +96,105 @@ async function ensureGateway(log = () => {}) { finally { booting = null; } } +// ── models ──────────────────────────────────────────────────────── +// Which model a headless agent runs on, and what to try if it fails. An +// explicit choice (a delegate call's `model`, an ACP session's config) wins +// over the env, which wins over `auto` — the gateway's free pool. The fallback +// chain is what lets a harness pin a specific coding model and still get an +// answer when that model is retired, out of quota, or behind a provider key it +// doesn't have: "free first, paid if needed" is spelled as a chain that ends in +// a paid model. +function parseModelList(v) { + const raw = Array.isArray(v) ? v : String(v || "").split(","); + return raw.map((m) => String(m || "").trim()).filter(Boolean); +} + +function resolveModels({ model, fallbackModels } = {}) { + const primary = String(model || process.env.OMNIWORK_MODEL || "auto").trim() || "auto"; + const chain = parseModelList(fallbackModels != null ? fallbackModels : process.env.OMNIWORK_MODEL_FALLBACKS); + return { model: primary, fallbackModels: chain.filter((m) => m !== primary) }; +} + +// The gateway's catalog, cached briefly: an ACP client asks for it on every +// session, and it only changes when someone adds a provider key. +let modelCache = { at: 0, ids: [] }; +async function listModels(gw) { + if (Date.now() - modelCache.at < 30_000) return modelCache.ids; + let ids = modelCache.ids; + try { + const res = await fetch(`${gw.baseUrl}/models`, { + headers: { Authorization: `Bearer ${gw.apiKey}` }, + signal: AbortSignal.timeout(5000), + }); + if (res.ok) { + const data = await res.json(); + ids = (data.data || []).map((m) => m && m.id).filter((id) => typeof id === "string" && id); + } + } catch {} + modelCache = { at: Date.now(), ids }; + return ids; +} + +// The chain a headless agent falls back to when the caller named none: the +// best model of every connected free provider, then any local server. Set +// OMNIWORK_MODEL_FALLBACKS (even to empty) to take over the decision. +let chainCache = { at: 0, chain: [] }; +async function defaultFallbacks(gw) { + if (Date.now() - chainCache.at < 30_000) return chainCache.chain; + const chain = providers.suggestChain(await listModels(gw)); + chainCache = { at: Date.now(), chain }; + return chain; +} + +// Connecting a provider changes both caches; call this right after. +function invalidateModels() { modelCache = { at: 0, ids: [] }; chainCache = { at: 0, chain: [] }; } + +async function resolveModelsLive(gw, opts = {}) { + const r = resolveModels(opts); + const decided = opts.fallbackModels != null || process.env.OMNIWORK_MODEL_FALLBACKS != null; + if (!decided) r.fallbackModels = (await defaultFallbacks(gw)).filter((m) => m !== r.model); + return r; +} + +// What to tell a caller whose every model failed. The built-in free pool is +// the usual culprit, and the fix is one connection away. +function noModelHint() { + const oc = opencode.available() + ? "OpenCode is installed, so `opencode/…` models are available as an engine — pick one, or let the fallback switch to it." + : `Getting OpenCode (${opencode.INSTALL_COMMAND}, a ~45 MB download) adds its free Zen models as an engine that needs no account at all.`; + return "No model answered. The gateway's built-in free pool is unreliable (its keyless endpoints get shut off upstream) — connect a real free provider once: run `npm run providers` in the omniwork checkout (or `npx omniwork-providers`), use the free-models panel in the OmniWork app, or the OpenRouter auth method on ACP. " + oc; +} + +// ── agents ──────────────────────────────────────────────────────── +// `opencode/` runs on the OpenCode engine (OpenCode's own server and +// tools, on Zen's free models); anything else on OmniWork's loop via the gateway. +function makeAgent(opts) { + return opencode.isEngineModel(opts.model) ? new opencode.OpenCodeAgent(opts) : new Agent(opts); +} + +// A turn that ended because no model answered — as opposed to a tool error, +// a cancel, or a model that answered badly. +// A rate limit (429) is deliberately not one: it clears by itself, and it +// must not silently move a pinned paid model's conversation to a free tier. +const isNoModelFailure = (msg) => /All models failed|Gateway (401|403|404|503)|No choices returned|empty response/.test(String(msg || "")); + +// The engine's best free model, when OpenCode is installed; null otherwise. +async function engineFallbackModel() { + // OMNIWORK_ENGINE_FALLBACK=off keeps a failed turn failed rather than + // finishing it on OpenCode's free tier. + if (/^(0|off|false|no)$/i.test(String(process.env.OMNIWORK_ENGINE_FALLBACK || ""))) return null; + if (!opencode.available()) return null; + try { + const list = await opencode.getEngine().models(); + return list.length ? list[0].id : `${opencode.PREFIX}nemotron-3.5-lightning-free`; + } catch { return null; } +} + + module.exports = { DATA_DIR, SKILLS_DIR, GLOBAL_MEMORY_DIR, browser, projects, agentEnv, ensureGateway, prewarmGateway, + resolveModels, resolveModelsLive, listModels, defaultFallbacks, invalidateModels, noModelHint, providers, + makeAgent, isNoModelFailure, engineFallbackModel, opencode, }; diff --git a/electron/main.js b/electron/main.js index fa5b9f1..ca88518 100644 --- a/electron/main.js +++ b/electron/main.js @@ -24,7 +24,7 @@ let projects = null; let browser = null; let scheduler = null; -const state = { model: "auto", approval: "auto", copyOnSelect: true, lastWorkspace: null, gateway: { state: "boot" } }; +const state = { model: "auto", approval: "auto", copyOnSelect: true, sawProviders: false, lastWorkspace: null, gateway: { state: "boot" } }; function prefsPath() { return path.join(app.getPath("userData"), "prefs.json"); } function loadPrefs() { @@ -32,7 +32,7 @@ function loadPrefs() { return {}; } function savePrefs() { - try { fs.writeFileSync(prefsPath(), JSON.stringify({ workspace: state.lastWorkspace, model: state.model, approval: state.approval, copyOnSelect: state.copyOnSelect }, null, 2)); } catch {} + try { fs.writeFileSync(prefsPath(), JSON.stringify({ workspace: state.lastWorkspace, model: state.model, approval: state.approval, sawProviders: state.sawProviders, copyOnSelect: state.copyOnSelect }, null, 2)); } catch {} } function send(channel, payload) { if (win && !win.isDestroyed()) win.webContents.send(channel, payload); } function activeWorkspace() { @@ -74,6 +74,7 @@ async function boot() { state.model = prefs.model || "auto"; state.approval = ["auto", "ask", "edits", "plan"].includes(prefs.approval) ? prefs.approval : "auto"; state.copyOnSelect = prefs.copyOnSelect !== false; + state.sawProviders = prefs.sawProviders === true; createWindow(); @@ -98,6 +99,17 @@ async function boot() { }); sessions.setModel(state.model); sessions.setApprovalMode(state.approval); + applyFallbacks().then(async () => { + // First launch, nothing connected: open the free-models panel once so the + // giant OpenRouter catalog is one click away instead of buried in the rail. + if (state.sawProviders) return; + try { + const st = await providers.status(gateway, { detectLocal: false }); + if (!st || st.error || st.anyConnected) { state.sawProviders = true; savePrefs(); return; } + setTimeout(() => send("providers:suggest", {}), 1500); + } catch {} + state.sawProviders = true; savePrefs(); + }); // Restore saved sessions; start a fresh one only if none were persisted. const restored = sessions.restore(); if (!restored) sessions.create({ workspace: state.lastWorkspace, title: "Main" }); @@ -126,13 +138,56 @@ ipcMain.handle("app:setModel", (_e, model) => { state.model = model; if (session ipcMain.handle("app:copy", (_e, text) => { const t = String(text || ""); if (t) clipboard.writeText(t); return true; }); ipcMain.handle("app:setCopyOnSelect", (_e, on) => { state.copyOnSelect = !!on; savePrefs(); return state.copyOnSelect; }); ipcMain.handle("gateway:openDashboard", () => { if (gateway) shell.openExternal(gateway.dashboardUrl()); return true; }); + +// ── IPC: free providers ───────────────────────────────────────────── +// The built-in keyless pool comes and goes; a connected free provider stays. +// Whatever is connected becomes every session's fallback chain, live. +const providers = require("./providers"); +const opencodeEngine = require("./opencode-engine"); +async function applyFallbacks() { + if (!gateway || !sessions) return []; + try { + const res = await fetch(`${gateway.baseUrl}/models`, { signal: AbortSignal.timeout(6000) }); + const ids = ((await res.json()).data || []).map((m) => m.id).filter(Boolean); + const chain = providers.suggestChain(ids); + sessions.setFallbacks(chain); + return chain; + } catch { return []; } +} +ipcMain.handle("providers:status", async () => { + if (!gateway || !gateway.ready) return null; + try { return await providers.status(gateway); } catch (e) { return { error: e.message }; } +}); +ipcMain.handle("providers:connect", async (_e, { provider, apiKey }) => { + if (!gateway) throw new Error("gateway not ready"); + // `install: true`: the click in the panel is the user's explicit gesture for the ~140 MB OpenCode download. + const result = await providers.connect(gateway, provider, { apiKey, install: true, open: (url) => shell.openExternal(url) }); + const chain = await applyFallbacks(); + return { ...result, chain }; +}); +ipcMain.handle("providers:remove", async (_e, provider) => { + if (!gateway) return 0; + const n = await providers.removeProvider(gateway, provider); + await applyFallbacks(); + return n; +}); +// Only the catalog's own "get a key" pages — never an arbitrary URL from the renderer. +ipcMain.handle("app:openUrl", (_e, url) => { + const allowed = providers.CATALOG.some((p) => p.keyUrl === url); + if (allowed) shell.openExternal(url); + return allowed; +}); ipcMain.handle("models:list", async () => { if (!gateway) return []; + let ids = []; try { const res = await fetch(`${gateway.baseUrl}/models`, { signal: AbortSignal.timeout(4000) }); const data = await res.json(); - return (data.data || []).map((m) => m.id).filter(Boolean); - } catch { return []; } + ids = (data.data || []).map((m) => m.id).filter(Boolean); + } catch {} + // OpenCode's free models, when it is installed — run on its own engine. + try { if (opencodeEngine.available()) ids.push(...(await opencodeEngine.getEngine().models()).map((m) => m.id)); } catch {} + return ids; }); // ── IPC: sessions (Cowork) ────────────────────────────────────────── diff --git a/electron/mcp-server.js b/electron/mcp-server.js old mode 100644 new mode 100755 index 229ee16..b662843 --- a/electron/mcp-server.js +++ b/electron/mcp-server.js @@ -15,9 +15,9 @@ const fs = require("node:fs"); const { ensureShellPath } = require("./shell-path"); -const { Agent } = require("./agent"); -const { agentEnv, browser, ensureGateway, prewarmGateway, SKILLS_DIR } = require("./headless"); +const { agentEnv, browser, ensureGateway, prewarmGateway, resolveModelsLive, listModels, invalidateModels, noModelHint, providers, makeAgent, isNoModelFailure, engineFallbackModel, opencode, SKILLS_DIR } = require("./headless"); const skillsApi = require("./skills"); +const tuning = require("./tuning"); ensureShellPath(); // MCP clients can launch us with a minimal environment too @@ -29,48 +29,130 @@ const log = (...a) => process.stderr.write("[omniwork-mcp] " + a.join(" ") + "\n const DELEGATE_TIMEOUT_MS = Number(process.env.OMNIWORK_DELEGATE_TIMEOUT_MS || 600_000); // Run one delegated task; capture a change log + final summary. -async function runDelegate({ task, cwd, progress }) { +async function runDelegate({ task, cwd, model, fallbackModels, progress }) { const gw = await ensureGateway(log); const workspace = cwd && fs.existsSync(cwd) ? cwd : process.cwd(); const changes = []; let steps = 0; - const agent = new Agent({ - baseUrl: gw.baseUrl, apiKey: gw.apiKey, model: process.env.OMNIWORK_MODEL || "auto", + let failure = null; + const emit = (type, p) => { + if (type === "thinking") progress(++steps, "thinking…"); + else if (type === "error") failure = String(p.message || ""); + else if (type === "tool_call") { + const a = p.args || {}; + const file = a.path || a.filePath || a.file; + if (/^(write_file|write)$/.test(p.name)) changes.push(`wrote ${file}`); + else if (/^(edit_file|edit|patch)$/.test(p.name)) changes.push(`edited ${file}`); + else if (/^(run_command|bash)$/.test(p.name)) changes.push(`ran: ${String(a.command).slice(0, 80)}`); + progress(steps, `${p.name} ${String(file || a.command || a.query || a.pattern || "").slice(0, 60)}`.trim()); + } + }; + const build = (models) => makeAgent({ + baseUrl: gw.baseUrl, apiKey: gw.apiKey, ...models, workspace, canSpawn: true, ...agentEnv(workspace), // The caller sees a single tool result, never the token stream. streaming: false, - emit: (type, p) => { - if (type === "thinking") progress(++steps, "thinking…"); - else if (type === "tool_call") { - if (p.name === "write_file") changes.push(`wrote ${p.args.path}`); - else if (p.name === "edit_file") changes.push(`edited ${p.args.path}`); - else if (p.name === "run_command") changes.push(`ran: ${String(p.args.command).slice(0, 80)}`); - progress(steps, `${p.name} ${String(p.args.path || p.args.command || p.args.query || "").slice(0, 60)}`.trim()); - } - }, + emit, }); + let agent = build(await resolveModelsLive(gw, { model, fallbackModels })); let timedOut = false; + let engineNote = ""; const timer = setTimeout(() => { timedOut = true; agent.abort(); }, DELEGATE_TIMEOUT_MS); - try { await agent.send(task); } - finally { clearTimeout(timer); } + try { + await agent.send(task); + // No gateway model answered, but OpenCode is installed: run the same task on + // its engine instead of returning a dead delegation. + if (failure && !agent.lastText && isNoModelFailure(failure) && !agent.isEngine && !timedOut) { + const engineModel = await engineFallbackModel(); + if (engineModel) { + engineNote = `\n\n[model: no gateway model answered (${failure.split("\n")[0].slice(0, 100)}) — ran on the OpenCode engine, ${engineModel}]`; + failure = null; + agent = build({ model: engineModel, fallbackModels: [] }); + await agent.send(task); + } + } + } finally { clearTimeout(timer); } + // A turn that produced nothing but an error is an error, not "(no summary)". + // When the error is "no model answered" it comes with the way out. + if (failure && !agent.lastText) { + throw new Error(isNoModelFailure(failure) ? `${failure}\n\n${noModelHint()}` : failure); + } const summary = agent.lastText || "(no summary)"; const changeLog = changes.length ? `\n\nChanges:\n- ${changes.join("\n- ")}` : ""; const note = timedOut ? `\n\n[stopped after ${Math.round(DELEGATE_TIMEOUT_MS / 1000)}s — this is partial work]` : ""; - return `${summary}${changeLog}${note}`; + // A cheap PASS/FAIL gate on the utility model, so the orchestrator re-delegates + // only when the work actually fell short — the expensive path is the caller + // re-reading and re-issuing, and this cuts it when the task already succeeded. + const verifyNote = (timedOut || !tuning.shouldVerify(task, changes.length > 0)) ? "" : await verifyDelegate(agent, task, summary, changeLog).catch(() => ""); + return `${summary}${changeLog}${modelNote(agent)}${engineNote}${verifyNote}${note}`; +} + +async function verifyDelegate(agent, task, summary, changeLog) { + if (!agent || typeof agent.oneShot !== "function" || !summary || summary === "(no summary)") return ""; + const prompt = + "You are grading whether a coding agent completed a task. Reply with exactly PASS or FAIL, then a dash and one short reason.\n\n" + + `TASK:\n${String(task).slice(0, 1500)}\n\nAGENT SUMMARY:\n${String(summary).slice(0, 1500)}${changeLog.slice(0, 600)}`; + let out = ""; + try { out = String(await agent.oneShot(prompt)).trim(); } catch { return ""; } + const m = /^(PASS|FAIL)\b[\s-]*(.*)$/i.exec(out.split("\n")[0] || ""); + if (!m) return ""; + const verdict = m[1].toUpperCase(); + return `\n\n[verify: ${verdict}${m[2] ? " — " + m[2].slice(0, 140) : ""}]`; +} + +// The caller asked for a model; if it got a different one, it should know. +function modelNote(agent) { + if (!agent.modelSwitches.length) return ""; + const hops = agent.modelSwitches.map((s) => `${s.from} failed (${s.reason.slice(0, 120)})`).join("; "); + return `\n\n[model: ran on ${agent.model} — ${hops}]`; } +// The catalog, grouped by provider prefix so a long list reads at a glance. +async function listModelsText() { + const ids = await listModels(await ensureGateway(log)); + if (!ids.length) return "The gateway returned no models (is it still starting? retry in a few seconds)."; + const groups = new Map(); + for (const id of ids) { + const i = id.indexOf("/"); + const p = i > 0 ? id.slice(0, i) : "(other)"; + if (!groups.has(p)) groups.set(p, []); + groups.get(p).push(id); + } + const lines = [`${ids.length} models. \`auto\` routes the free pool; a provider prefix pins one. Models behind a provider key you haven't added will fail — put them in fallback_models after a free one, or use them alone only if the key is configured in the router dashboard.`, ""]; + for (const [p, list] of groups) lines.push(`## ${p} (${list.length})`, list.join(", "), ""); + if (opencode.available()) { + let engine = []; + try { engine = await opencode.getEngine().models(); } catch (e) { lines.push(`## opencode (engine)`, `could not list: ${e.message}`, ""); } + if (engine.length) lines.push(`## opencode (engine — free, no account; runs on OpenCode's own server and tools)`, engine.map((m) => m.id).join(", "), ""); + } else { + lines.push(`## opencode (engine) — not present yet`, `${opencode.INSTALL_COMMAND} (a ~45 MB download the user runs) adds its free Zen models (Nemotron 3.5 Lightning, MiMo V2.5, Big Pickle, Ling 3.0 Flash, Nemotron 3 Ultra) as an engine that needs no account.`, ""); + } + return lines.join("\n").trim(); +} + +const MODEL_PARAM = { + type: "string", + description: "Model id to run on (see list_models). Default: OMNIWORK_MODEL, else 'auto' (the free pool).", +}; +const FALLBACK_PARAM = { + type: "array", items: { type: "string" }, + description: "Tried in order if the model fails (retired id, no provider key, quota). Default: OMNIWORK_MODEL_FALLBACKS. End with a paid model you have a key for when the task must complete.", +}; + const TOOLS = [ { name: "delegate", description: - "Delegate ONE coding/research subtask to OmniWork, which executes it autonomously on FREE models (reads/writes/edits files, runs commands, browses the web) in the given working directory and returns a summary + change list. The agent has OmniWork's installed skills and remembers facts saved to its memory across delegations. USE for: mechanical/boilerplate work, scaffolding, repetitive edits, read-heavy research, anything cheap to verify. DON'T use for: tasks needing the current conversation's context (delegates start cold — write fully self-contained instructions), tiny tasks (~30s overhead), precision-critical specs, or destructive/hard-to-undo changes. Always pass cwd. Verify the result yourself — the summary is a claim, not evidence.", + "Delegate ONE coding/research subtask to OmniWork, which executes it autonomously (reads/writes/edits files, runs commands, browses the web) — on free models by default, or on the model you pick — in the given working directory and returns a summary + change list. The agent has OmniWork's installed skills and remembers facts saved to its memory across delegations. USE for: mechanical/boilerplate work, scaffolding, repetitive edits, read-heavy research, anything cheap to verify. DON'T use for: tasks needing the current conversation's context (delegates start cold — write fully self-contained instructions), tiny tasks (~30s overhead), precision-critical specs, or destructive/hard-to-undo changes. Always pass cwd. Verify the result yourself — the summary is a claim, not evidence.", inputSchema: { type: "object", properties: { task: { type: "string", description: "Full, self-contained instruction. Include every fact the agent needs — it cannot see your conversation." }, cwd: { type: "string", description: "Absolute working directory. Always pass this explicitly." }, + model: MODEL_PARAM, + fallback_models: FALLBACK_PARAM, }, required: ["task"], }, @@ -78,16 +160,42 @@ const TOOLS = [ { name: "delegate_parallel", description: - "Delegate MANY independent subtasks at once; OmniWork fans them out to parallel free-model subagents and returns all summaries. USE instead of N sequential delegate calls whenever tasks don't depend on each other (write N files, refactor N modules, research N topics). Each task must be fully self-contained.", + "Delegate MANY independent subtasks at once; OmniWork fans them out to parallel subagents (free models by default, or the model you pick) and returns all summaries. USE instead of N sequential delegate calls whenever tasks don't depend on each other (write N files, refactor N modules, research N topics). Each task must be fully self-contained.", inputSchema: { type: "object", properties: { tasks: { type: "array", items: { type: "string" }, description: "Independent, self-contained subtask instructions." }, cwd: { type: "string", description: "Absolute working directory. Always pass this explicitly." }, + model: MODEL_PARAM, + fallback_models: FALLBACK_PARAM, }, required: ["tasks"], }, }, + { + name: "list_providers", + description: + "Show which free model providers are connected to OmniWork's gateway, the fallback chain delegations will use, local model servers detected on this machine, and how to connect more. USE when a delegation reports 'All models failed' or before relying on OmniWork for unattended work — the built-in keyless pool is unreliable, a connected provider is not.", + inputSchema: { type: "object", properties: {}, required: [] }, + }, + { + name: "connect_provider", + description: + "Connect a free model provider to OmniWork's gateway so delegations always have a model. provider='openrouter' OPENS THE USER'S BROWSER for a one-click sign-in (PKCE; the user completes it, no key passes through here) — tell the user before calling. provider='local' registers any Ollama / LM Studio / llama.cpp / vLLM server running on this machine. provider='opencode' reports the OpenCode engine. Key-based providers (ollama-cloud, kilo-gateway, groq, cerebras, nvidia, gemini, mistral) cannot be connected from this tool: this tool takes no API key, on purpose — a key pasted by a model would route the user's code through whoever supplied it. Tell the user to paste it in the OmniWork app's free-models panel or run 'npm run providers connect '.", + inputSchema: { + type: "object", + properties: { + provider: { type: "string", description: "openrouter | local | opencode" }, + }, + required: ["provider"], + }, + }, + { + name: "list_models", + description: + "List the model ids OmniWork's gateway can route right now, grouped by provider. USE before pinning a model in delegate/delegate_parallel, or when a pinned model failed — free catalogs change as providers retire models.", + inputSchema: { type: "object", properties: {}, required: [] }, + }, { name: "web_search", description: @@ -115,22 +223,69 @@ const TOOLS = [ ]; async function callTool(name, args, progress = () => {}) { - if (name === "delegate") return await runDelegate({ task: args.task, cwd: args.cwd, progress }); + if (name === "delegate") return await runDelegate({ task: args.task, cwd: args.cwd, model: args.model, fallbackModels: args.fallback_models, progress }); + if (name === "list_models") return await listModelsText(); + if (name === "list_providers") return providers.describe(await providers.status(await ensureGateway(log))); + if (name === "connect_provider") { + const gw = await ensureGateway(log); + if (args.provider === "opencode") { + if (opencode.available()) { + const list = await opencode.getEngine().models().catch(() => []); + return `OpenCode is installed (${opencode.version() || "?"}). Engine models: ${list.map((m) => m.id).join(", ") || "(none listed yet)"}. Pass one as \`model\` to delegate, or rely on the automatic fallback.`; + } + return `OpenCode is not present yet. It is a ~45 MB download, so it needs the user's own gesture (not a tool call): ${opencode.INSTALL_COMMAND} in the omniwork checkout, or the Download button in the app's free-models panel. Afterwards its free Zen models appear as opencode/… in list_models and become the automatic fallback.`; + } + if (!["openrouter", "local"].includes(args.provider)) { + const p = providers.CATALOG.find((c) => c.id === args.provider); + return p + ? `${p.name} needs an API key, and this tool takes none — a key supplied by a model would route the user's code through whoever supplied it. Ask the user to create one at ${p.keyUrl} and paste it in the OmniWork app's free-models panel, or run: npm run providers connect ${p.id} ` + : `unknown provider: ${args.provider} (this tool connects openrouter, local, or opencode)`; + } + let url = null; + const result = await providers.connect(gw, args.provider, { + onUrl: (u) => { url = u; progress(0, "waiting for the OpenRouter sign-in in the browser…"); }, + }); + invalidateModels(); + const st = await providers.status(gw, { detectLocal: false }); + const head = result.added + ? (result.added.length + ? `Registered local: ${result.added.map((a) => `${a.name} (${a.models.length} models)`).join(", ")}.` + : `No local model server is running (${result.skipped.map((s) => s.name).join(", ")} checked).`) + : `Connected ${result.name} — ${result.models} models now routable.`; + return `${head}${url ? `\n(sign-in URL was ${url})` : ""}\nFallback chain now: ${st.chain.length ? st.chain.join(" → ") : "(empty)"}`; + } if (name === "delegate_parallel") { const gw = await ensureGateway(log); const workspace = args.cwd && fs.existsSync(args.cwd) ? args.cwd : process.cwd(); let done = 0; const tasks = (args.tasks || []).map((t, i) => ({ title: `task ${i + 1}`, prompt: t })); - const agent = new Agent({ - baseUrl: gw.baseUrl, apiKey: gw.apiKey, model: process.env.OMNIWORK_MODEL || "auto", + const switched = []; + const agent = makeAgent({ + baseUrl: gw.baseUrl, apiKey: gw.apiKey, ...(await resolveModelsLive(gw, { model: args.model, fallbackModels: args.fallback_models })), workspace, canSpawn: true, ...agentEnv(workspace), streaming: false, emit: (type, p) => { if (type !== "subagent") return; if (p.kind === "done") progress(++done, `${done}/${tasks.length} subagents finished`, tasks.length); else if (p.kind === "tool") progress(done, `${p.title || "subagent"}: ${p.tool}`, tasks.length); + else if (p.kind === "model") { switched.push(`${p.from} → ${p.to}`); progress(done, `${p.title || "subagent"}: model ${p.from} failed, continuing on ${p.to}`, tasks.length); } }, }); - return await agent.runSubagents(tasks); + if (agent.isEngine) { + // The engine has no in-loop subagents; each task gets its own session. + const results = await Promise.all(tasks.map(async (t) => { + const one = makeAgent({ + baseUrl: gw.baseUrl, apiKey: gw.apiKey, model: agent.model, fallbackModels: [], + workspace, canSpawn: false, ...agentEnv(workspace), streaming: false, + emit: (type, p) => { if (type === "tool_call") progress(done, `${t.title}: ${p.name}`, tasks.length); }, + }); + await one.send(t.prompt); + progress(++done, `${done}/${tasks.length} engine sessions finished`, tasks.length); + return `## ${t.title}\n${one.lastText || "(no summary returned)"}`; + })); + return results.join("\n\n---\n\n"); + } + const out = await agent.runSubagents(tasks); + return switched.length ? `${out}\n\n[model: some subagents fell back — ${[...new Set(switched)].join(", ")}]` : out; } if (name === "web_search") return await browser.search(args.query); if (name === "browse_page") return await browser.open(args.url); diff --git a/electron/opencode-engine.js b/electron/opencode-engine.js new file mode 100644 index 0000000..b685d85 --- /dev/null +++ b/electron/opencode-engine.js @@ -0,0 +1,588 @@ +"use strict"; +// OpenCode as an engine inside OmniWork. +// +// OpenCode Zen's free models (Nemotron 3 Ultra, Nemotron 3.5 Lightning, +// MiMo V2.5, Ling 3.0 Flash, Big Pickle…) are real, keyless, tool-capable, and +// generous — and Zen refuses them to anything that isn't OpenCode ("OpenCode's +// free tier can only be used in OpenCode"). We don't fake being OpenCode; we +// run it. `opencode serve` is the headless server OpenCode ships for exactly +// this — Zed and acpx drive it the same way — and its sessions do the work on +// those models with OpenCode's own tools, scoped to our workspace through the +// `x-opencode-directory` header the official SDK uses. +// +// One server per OmniWork process, started on first use, killed on exit. +// `OpenCodeAgent` wraps a server session in the same interface `Agent` has, so +// the desktop app, the MCP server, and the ACP server can run a session on +// `opencode/` without knowing the difference. + +const { spawn, execFileSync } = require("node:child_process"); +const crypto = require("node:crypto"); +const fs = require("node:fs"); +const os = require("node:os"); +const path = require("node:path"); + +const PROVIDER_IDS = ["opencode", "opencode-go"]; +const PREFIX = "opencode/"; + +// ── locating / getting the binary ──────────────────────────────── +// Nobody should have to touch their PATH. The binary is looked for where each +// way of getting OmniWork puts it, and spawned by absolute path: +// 1. OMNIWORK_OPENCODE_BIN an explicit override +// 2. /resources/runtime/opencode the packaged desktop app (staged per platform at build time) +// 3. node_modules/opencode-- a clone after `npm install` (opencode-ai is an optional dependency) +// 4. ~/.omniwork/engine/opencode downloaded on first use from OpenCode's GitHub release +// 5. ~/.opencode/bin, npm's global bin, Homebrew, and the PATH — an install the user already has +const REPO_ROOT = path.join(__dirname, ".."); +const DOWNLOAD_DIR = path.join(os.homedir(), ".omniwork", "engine", "opencode"); +const RELEASES = "https://github.com/anomalyco/opencode/releases/download"; + +function target() { + const platform = process.platform === "win32" ? "windows" : process.platform === "darwin" ? "darwin" : "linux"; + const arch = process.arch === "arm64" ? "arm64" : "x64"; + return { platform, arch }; +} +const exeName = () => (process.platform === "win32" ? "opencode.exe" : "opencode"); + +function candidates() { + const exe = exeName(); + const { platform, arch } = target(); + const list = []; + if (process.env.OMNIWORK_OPENCODE_BIN) list.push(process.env.OMNIWORK_OPENCODE_BIN); + if (process.resourcesPath) list.push(path.join(process.resourcesPath, "runtime", "opencode", exe)); + const pkg = `opencode-${platform}-${arch}`; + for (const root of [REPO_ROOT, path.join(REPO_ROOT, "node_modules", "opencode-ai")]) { + list.push(path.join(root, "node_modules", pkg, "bin", exe)); + list.push(path.join(root, "node_modules", `${pkg}-baseline`, "bin", exe)); + } + list.push(path.join(REPO_ROOT, "node_modules", "opencode-ai", "bin", "opencode.exe")); // the package's postinstall copy (that name on every OS) + list.push(path.join(DOWNLOAD_DIR, exe)); + const npmPrefix = process.env.npm_config_prefix || process.env.NPM_CONFIG_PREFIX; + list.push( + path.join(os.homedir(), ".opencode", "bin", exe), + "/opt/homebrew/bin/opencode", "/usr/local/bin/opencode", + path.join(os.homedir(), ".bun", "bin", exe), + path.join(os.homedir(), ".npm-global", "bin", exe), + path.join(os.homedir(), ".npm", "bin", exe), + ...(npmPrefix ? [path.join(npmPrefix, "bin", exe)] : []), + ...(process.platform === "win32" ? [path.join(process.env.APPDATA || "", "npm", "node_modules", "opencode-ai", "bin", "opencode.exe")] : []), + ); + for (const dir of String(process.env.PATH || "").split(path.delimiter)) if (dir) list.push(path.join(dir, exe)); + return list; +} + +function findBinary() { + for (const c of candidates()) { try { fs.accessSync(c, fs.constants.X_OK); return c; } catch {} } + return null; +} +const available = () => Boolean(findBinary()); + +// The version OmniWork ships and downloads: whatever package.json pins for +// opencode-ai, so a clone and a download agree. +function pinnedVersion() { + try { + const pkg = JSON.parse(fs.readFileSync(path.join(REPO_ROOT, "package.json"), "utf8")); + const v = (pkg.optionalDependencies || {})["opencode-ai"] || (pkg.dependencies || {})["opencode-ai"] || ""; + return v.replace(/^[^0-9]*/, "") || "1.18.31"; + } catch { return "1.18.31"; } +} +function platformPackage(t = target()) { return `opencode-${t.platform}-${t.arch}`; } +const exeFor = (pkg) => (pkg.includes("windows") ? "opencode.exe" : "opencode"); + +// The download is verified against the sha512 npm recorded for that package in +// package-lock.json — a hash that ships with the repo, pinned with the version. +// OpenCode's GitHub releases publish no checksums; the npm registry tarball of +// the same binary comes with one. This is the only download path. +function lockEntry(pkg) { + const lock = JSON.parse(fs.readFileSync(path.join(REPO_ROOT, "package-lock.json"), "utf8")); + const e = lock.packages && lock.packages[`node_modules/${pkg}`]; + if (!e || !e.integrity || !e.resolved) throw new Error(`package-lock.json has no pinned integrity for ${pkg} — run npm install to refresh it`); + return { integrity: e.integrity, resolved: e.resolved, version: e.version }; +} +const INSTALL_COMMAND = "npm run providers connect opencode"; +const INSTALL_SCRIPT = "curl -fsSL https://opencode.ai/install | bash"; + +function version() { + const bin = findBinary(); + if (!bin) return null; + try { return execFileSync(bin, ["--version"], { encoding: "utf8", timeout: 15_000 }).trim().split("\n").pop(); } + catch { return "installed"; } +} + +// Fetch the platform package (~45 MB) into `dir`, verify its hash, unpack just +// the binary. Only ever run from an explicit user gesture — a click, a typed +// command, an ACP auth method — never a tool call. +async function download({ pkg = platformPackage(), dir = DOWNLOAD_DIR, entry = null, onProgress = () => {} } = {}) { + const { Readable, Transform } = require("node:stream"); + const { pipeline } = require("node:stream/promises"); + const tar = require("tar"); + const { integrity, resolved: url, version: ver } = entry || lockEntry(pkg); + const [algo, expected] = String(integrity).split("-", 2); + if (!/^sha(256|384|512)$/.test(algo) || !expected) throw new Error(`unusable integrity string for ${pkg}`); + const exe = exeFor(pkg); + fs.mkdirSync(dir, { recursive: true }); + const archive = path.join(dir, `${pkg}.tgz`); + onProgress({ phase: "download", detail: `Downloading OpenCode v${ver} (${pkg})…`, url }); + const res = await fetch(url); + if (!res.ok || !res.body) throw new Error(`OpenCode download failed: HTTP ${res.status} for ${url}`); + const total = Number(res.headers.get("content-length")) || 0; + let received = 0; + const hash = crypto.createHash(algo); + const meter = new Transform({ transform(chunk, _enc, cb) { received += chunk.length; hash.update(chunk); onProgress({ phase: "download", received, total }); cb(null, chunk); } }); + try { + await pipeline(Readable.fromWeb(res.body), meter, fs.createWriteStream(archive + ".part")); + const digest = hash.digest("base64"); + if (digest !== expected) throw new Error(`OpenCode download failed integrity check (${algo} mismatch for ${pkg}) — not installed`); + fs.renameSync(archive + ".part", archive); + onProgress({ phase: "extract", detail: "Verified. Unpacking…" }); + const want = new RegExp(`^package/bin/${exe.replace(".", "\\.")}$`); + await tar.x({ file: archive, cwd: dir, strip: 2, filter: (p) => want.test(p) }); + } finally { + fs.rmSync(archive + ".part", { force: true }); + fs.rmSync(archive, { force: true }); + } + const bin = path.join(dir, exe); + if (!fs.existsSync(bin)) throw new Error(`OpenCode package unpacked but ${bin} is missing`); + if (process.platform !== "win32") fs.chmodSync(bin, 0o755); + if (pkg === platformPackage()) { + const v = execFileSync(bin, ["--version"], { encoding: "utf8", timeout: 20_000 }).trim().split("\n").pop(); + onProgress({ phase: "done", detail: `OpenCode ${v} ready` }); + } else { + onProgress({ phase: "done", detail: `OpenCode ${ver} (${pkg}) staged` }); + } + return bin; +} + +// One entry point every surface calls; concurrent callers share one download. +let installing = null; +async function install({ log = () => {} } = {}) { + const found = findBinary(); + if (found) return found; + if (installing) return installing; + let lastPct = -1; + installing = download({ onProgress: (p) => { + if (p.detail) log(p.detail); + else if (p.total) { const pct = Math.floor((p.received / p.total) * 100); if (pct !== lastPct && pct % 10 === 0) { lastPct = pct; log(`${pct}%`); } } + } }); + try { return await installing; } + finally { installing = null; } +} + +// ── the server ──────────────────────────────────────────────────── +class Engine { + constructor({ bin = findBinary(), log = () => {} } = {}) { + this.bin = bin; + this.log = log; + this.proc = null; + this.baseUrl = null; + this.starting = null; + this.listeners = new Map(); // sessionID -> Set + this.pumps = new Map(); // directory -> { ctl, refs, ready } for its event stream + this.modelsCache = { at: 0, list: [] }; + // Loopback is not an authorization boundary: the server only answers + // requests carrying this per-process secret (OpenCode's own basic auth). + this.username = "omniwork"; + this.password = crypto.randomBytes(24).toString("hex"); + } + + async start() { + if (this.baseUrl) return this.baseUrl; + if (this.starting) return this.starting; + if (!this.bin) throw new Error(`OpenCode is not installed — run: ${INSTALL_COMMAND}`); + this.starting = new Promise((resolve, reject) => { + // OpenCode snapshots the whole session directory with `git add --all` + // before every message so its UI can revert. Scoped to a home folder that + // is three minutes per turn (measured: 174 s → 4 s without). OmniWork has + // its own undo, so engine sessions run with snapshots off — merged into + // any config the user already passes by env. + let extra = { snapshot: false }; + if (process.env.OPENCODE_CONFIG_CONTENT) { try { extra = { ...JSON.parse(process.env.OPENCODE_CONFIG_CONTENT), ...extra }; } catch {} } + const env = { + ...process.env, + OPENCODE_DISABLE_AUTOUPDATE: "1", + OPENCODE_DISABLE_TERMINAL_TITLE: "1", + OPENCODE_DISABLE_PRUNE: "1", + OPENCODE_EXPERIMENTAL_DISABLE_FILEWATCHER: "1", + OPENCODE_CONFIG_CONTENT: JSON.stringify(extra), + OPENCODE_SERVER_USERNAME: this.username, + OPENCODE_SERVER_PASSWORD: this.password, + }; + // A neutral cwd: the workspace comes per request, never from where we + // happened to start. + const proc = spawn(this.bin, ["serve", "--port", "0", "--hostname", "127.0.0.1"], { cwd: os.tmpdir(), env, stdio: ["ignore", "pipe", "pipe"] }); + this.proc = proc; + let buf = ""; + const timer = setTimeout(() => { try { proc.kill(); } catch {} reject(new Error("opencode serve did not report a port within 60s")); }, 60_000); + const onLine = (line) => { + const m = /listening on (http:\/\/[^\s]+)/.exec(line); + if (m && !this.baseUrl) { + this.baseUrl = m[1].replace(/\/$/, ""); + clearTimeout(timer); + resolve(this.baseUrl); + } else if (/error/i.test(line)) this.log("[opencode]", line.slice(0, 200)); + }; + const feed = (d) => { buf += d; let i; while ((i = buf.indexOf("\n")) >= 0) { onLine(buf.slice(0, i)); buf = buf.slice(i + 1); } }; + proc.stdout.on("data", feed); + proc.stderr.on("data", feed); + proc.on("error", (e) => { clearTimeout(timer); reject(e); }); + proc.on("exit", (code) => { + clearTimeout(timer); + if (this.proc !== proc) return; // a server we already replaced + const was = this.baseUrl; + this.baseUrl = null; this.proc = null; this.starting = null; + for (const p of this.pumps.values()) p.ctl.abort(); + this.pumps.clear(); + if (!was) reject(new Error(`opencode serve exited with ${code} before listening`)); + else this.log("[opencode] server exited", code); + }); + }); + try { return await this.starting; } + finally { this.starting = null; } + } + + stop() { + if (this.proc) { try { this.proc.kill(); } catch {} } + this.proc = null; this.baseUrl = null; + for (const p of this.pumps.values()) p.ctl.abort(); + this.pumps.clear(); + } + + #auth() { return "Basic " + Buffer.from(`${this.username}:${this.password}`).toString("base64"); } + + async #req(method, p, { body, directory, timeoutMs = 30_000, signal } = {}) { + const base = await this.start(); + const headers = { "Content-Type": "application/json", Authorization: this.#auth() }; + if (directory) headers["x-opencode-directory"] = encodeURIComponent(directory); + const res = await fetch(base + p, { + method, headers, + body: body ? JSON.stringify(body) : undefined, + // A prompt runs as long as the task takes; everything else gets a deadline. + signal: signal || (timeoutMs > 0 ? AbortSignal.timeout(timeoutMs) : undefined), + }); + const text = await res.text().catch(() => ""); + let json = null; try { json = JSON.parse(text); } catch {} + if (!res.ok) throw new Error(`opencode ${method} ${p}: ${res.status} ${(json && json.error && (json.error.message || json.error.type)) || text.slice(0, 200)}`); + return json; + } + + // OpenCode's event stream is scoped to a directory — without the header it + // carries only server heartbeats — so there is one subscription per + // workspace, fanned out per session, kept alive for the life of the server. + async #pump(directory, ctl, onConnected) { + const base = this.baseUrl; + while (this.baseUrl === base && !ctl.signal.aborted) { + try { + const res = await fetch(`${base}/event`, { signal: ctl.signal, headers: { Accept: "text/event-stream", Authorization: this.#auth(), "x-opencode-directory": encodeURIComponent(directory) } }); + if (onConnected) { onConnected(); onConnected = null; } + const reader = res.body.getReader(); + const dec = new TextDecoder(); + let buf = ""; + for (;;) { + const { value, done } = await reader.read(); + if (done) break; + buf += dec.decode(value, { stream: true }); + let i; + while ((i = buf.indexOf("\n\n")) >= 0) { + const chunk = buf.slice(0, i); buf = buf.slice(i + 2); + for (const line of chunk.split("\n")) { + if (!line.startsWith("data:")) continue; + let ev; try { ev = JSON.parse(line.slice(5).trim()); } catch { continue; } + const sid = ev && ev.properties && ev.properties.sessionID; + const set = sid && this.listeners.get(sid); + if (set) for (const fn of set) { try { fn(ev); } catch {} } + } + } + } + } catch {} + if (this.baseUrl === base && !ctl.signal.aborted) await new Promise((r) => setTimeout(r, 500)); + } + } + + // Make sure the workspace's event stream is connected before a prompt goes + // out — the first tool part can arrive within milliseconds. + // Streams are ref-counted per workspace: the last subscriber leaving closes + // the connection, so a long-lived server that has touched many workspaces + // holds no idle sockets. + ensurePump(directory) { + if (!this.pumps.has(directory)) { + const ctl = new AbortController(); + const ready = new Promise((resolve) => { this.#pump(directory, ctl, resolve); setTimeout(resolve, 3000); }); + this.pumps.set(directory, { ctl, refs: 0, ready }); + } + return this.pumps.get(directory).ready; + } + + subscribe(sessionID, fn, directory) { + if (!this.listeners.has(sessionID)) this.listeners.set(sessionID, new Set()); + this.listeners.get(sessionID).add(fn); + const pump = directory ? this.pumps.get(directory) : null; + if (pump) pump.refs++; + return () => { + const s = this.listeners.get(sessionID); + if (s) { s.delete(fn); if (!s.size) this.listeners.delete(sessionID); } + if (pump && --pump.refs <= 0 && this.pumps.get(directory) === pump) { pump.ctl.abort(); this.pumps.delete(directory); } + }; + } + + async health() { return await this.#req("GET", "/global/health", { timeoutMs: 5000 }); } + + // Free models on OpenCode's own providers: `opencode/` in OmniWork terms. + async models({ force = false } = {}) { + if (!force && Date.now() - this.modelsCache.at < 300_000) return this.modelsCache.list; + const data = await this.#req("GET", "/provider", { timeoutMs: 20_000 }); + const list = []; + for (const prov of (data && data.all) || []) { + if (!PROVIDER_IDS.includes(prov.id)) continue; + for (const [id, m] of Object.entries(prov.models || {})) { + const cost = m && m.cost; + const free = cost && Number(cost.input) === 0 && Number(cost.output) === 0; + if (!free) continue; + list.push({ id: `${PREFIX}${id}`, providerID: prov.id, modelID: id, name: m.name || id, tools: m.tool_call !== false, context: m.limit && m.limit.context }); + } + } + // Strongest coders first: Nemotron Ultra, then the rest in catalog order. + list.sort((a, b) => rank(a.modelID) - rank(b.modelID)); + this.modelsCache = { at: Date.now(), list }; + return list; + } + + async createSession({ directory, title, permission }) { + const body = { title }; + if (permission) body.permission = permission; + const s = await this.#req("POST", "/session", { body, directory }); + return s.id; + } + async prompt(sessionID, { directory, providerID, modelID, text, signal }) { + return await this.#req("POST", `/session/${sessionID}/message`, { + body: { model: { providerID, modelID }, parts: [{ type: "text", text }] }, + directory, signal, timeoutMs: 0, + }); + } + async abort(sessionID, directory) { return await this.#req("POST", `/session/${sessionID}/abort`, { directory, timeoutMs: 5000 }).catch(() => false); } + async replyPermission(sessionID, permissionID, response, directory) { + return await this.#req("POST", `/session/${sessionID}/permissions/${permissionID}`, { body: { response }, directory, timeoutMs: 5000 }); + } + async diff(sessionID, directory) { return await this.#req("GET", `/session/${sessionID}/diff`, { directory, timeoutMs: 10_000 }).catch(() => []); } +} + +// Measured 2026-09-15 on a one-line reply: Lightning 4s, MiMo 5s, Big Pickle +// 6s, Ling 3s, Ultra ~100s per step. Ultra is the strongest and stays +// available by name; the default has to answer in seconds. +const RANK = ["nemotron-3.5-lightning", "mimo-v2.5", "big-pickle", "ling-3.0-flash", "nemotron-3-ultra"]; +function rank(id) { const i = RANK.findIndex((r) => id.startsWith(r)); return i < 0 ? RANK.length : i; } + +// The server must not outlive the process that started it. `exit` covers a +// normal end; a SIGTERM/SIGINT (a harness killing its agent, Ctrl-C) skips the +// exit hook unless we turn it into one. +let shared = null; +function getEngine(opts) { + if (!shared) { + shared = new Engine(opts); + process.on("exit", () => shared && shared.stop()); + // Electron's app.quit path runs "exit" itself; a raw signal handler there + // would skip its cleanup. Headless servers get one that exits the way the + // shell expects (128 + signal number). + if (!process.versions.electron) { + const codes = { SIGHUP: 129, SIGINT: 130, SIGTERM: 143 }; + for (const sig of Object.keys(codes)) { + if (process.listenerCount(sig) === 0) process.on(sig, () => { if (shared) shared.stop(); process.exit(codes[sig]); }); + } + } + } + return shared; +} + +// ── the agent ───────────────────────────────────────────────────── +// Same surface as electron/agent.js's Agent, backed by an OpenCode session. +// Events map one-to-one: text deltas → assistant_delta, tool parts → +// tool_call / tool_result, permission requests → the approver, session errors +// → error. What OmniWork can't offer here is its own skills and memory — +// OpenCode runs its own tools — which is the honest price of the free tier. +class OpenCodeAgent { + constructor({ model, workspace, emit, approvalMode = "auto", approver = null, engine = getEngine(), fallbackModels = [], messages = null, sessionID = null }) { + this.engine = engine; + this.model = model || `${PREFIX}nemotron-3.5-lightning-free`; + this.fallbackModels = fallbackModels; // accepted for interface parity; the engine picks its own + this.workspace = workspace; + this.emit = emit; + this.approvalMode = approvalMode; + this.approver = approver; + // A conversation handed over from another agent is carried into the first + // prompt, so a mid-session switch does not forget what was said. + this.messages = Array.isArray(messages) && messages.length ? messages.slice() : [{ role: "system", content: "(OpenCode engine session)" }]; + this.carryOver = !sessionID && this.messages.some((m) => m.role === "user"); + this.lastText = ""; + this.modelSwitches = []; + this.contextTokens = 200_000; + this.memory = null; + this.sessionID = sessionID || null; // OpenCode's own id — persisted by callers that resume sessions + this.aborted = false; + this.undoAvailable = false; + this.turnStats = null; + } + + get isEngine() { return true; } + setWorkspace(dir) { this.workspace = dir; this.sessionID = null; } + abort() { this.aborted = true; if (this.sessionID) this.engine.abort(this.sessionID, this.workspace); } + async compactNow() { return null; } + async oneShot(prompt) { + const { providerID, modelID } = this.#target(); + const sid = await this.engine.createSession({ directory: this.workspace, title: "oneshot", permission: [{ permission: "*", pattern: "*", action: "deny" }] }); + const res = await this.engine.prompt(sid, { directory: this.workspace, providerID, modelID, text: prompt }); + return textOf(res); + } + undo() { return "Undo isn't available for OpenCode engine sessions — use git."; } + + #target() { + const id = this.model.startsWith(PREFIX) ? this.model.slice(PREFIX.length) : this.model; + // opencode-go models are namespaced by the engine's provider list; default provider is Zen. + const cached = this.engine.modelsCache.list.find((m) => m.modelID === id); + return { providerID: cached ? cached.providerID : "opencode", modelID: id }; + } + + // OpenCode's per-session ruleset: an ordered list of {permission, pattern, + // action}, mirroring OmniWork's approval modes. + #permission() { + const rule = (permission, action) => ({ permission, pattern: "*", action }); + if (this.approvalMode === "auto") return [rule("*", "allow")]; + if (this.approvalMode === "plan") return [rule("*", "ask"), rule("read", "allow"), rule("edit", "deny"), rule("write", "deny"), rule("bash", "deny")]; + if (this.approvalMode === "edits") return [rule("*", "ask"), rule("read", "allow"), rule("edit", "allow"), rule("write", "allow")]; + return [rule("*", "ask"), rule("read", "allow")]; + } + + async send(userText, images) { + this.aborted = false; + this.turnStats = { startedAt: Date.now(), inTokens: 0, outTokens: 0, estimated: true }; + let text = images && images.length ? `${userText}\n\n(${images.length} image(s) attached — not forwarded to the OpenCode engine)` : userText; + if (this.carryOver) { text = carriedContext(this.messages) + text; this.carryOver = false; } + this.messages.push({ role: "user", content: userText }); + this.emit("thinking", { step: 0 }); + + // The model's provider (Zen vs Go) comes from the catalog; make sure it is loaded. + if (!this.engine.modelsCache.list.length) { try { await this.engine.models(); } catch {} } + const { providerID, modelID } = this.#target(); + let unsubscribe = () => {}; + let streamedText = ""; + const partType = new Map(); // partID -> "text" | "reasoning" | … (deltas don't say) + const held = new Map(); // partID -> delta text that arrived before the part's type + const seen = new Map(); // callID -> "called" | "done" + const flush = (partID, type, delta) => { + if (type === "text") { streamedText += delta; this.emit("assistant_delta", { chunk: delta }); } + else if (type === "reasoning") this.emit("reasoning_delta", { chunk: delta }); + }; + try { + if (!this.sessionID) this.sessionID = await this.engine.createSession({ directory: this.workspace, title: `OmniWork · ${path.basename(this.workspace || "")}`, permission: this.#permission() }); + const sid = this.sessionID; + await this.engine.ensurePump(this.workspace); + unsubscribe = this.engine.subscribe(sid, (ev) => { + const p = ev.properties || {}; + switch (ev.type) { + // A delta only names its part; the part's type came (or comes) with a + // message.part.updated. Reasoning streams on field "text" too, so a + // delta is held until its part is known and never mistaken for the reply. + case "message.part.delta": { + if (p.field !== "text" || !p.delta) break; + const type = partType.get(p.partID); + if (type) flush(p.partID, type, p.delta); + else held.set(p.partID, (held.get(p.partID) || "") + p.delta); + break; + } + case "message.part.updated": { + const part = p.part || {}; + if (part.id && part.type && !partType.has(part.id)) { + partType.set(part.id, part.type); + if (held.has(part.id)) { flush(part.id, part.type, held.get(part.id)); held.delete(part.id); } + } + if (part.type !== "tool") break; + const st = part.state || {}; + const id = part.callID || part.id; + // Tool input streams in; announce the call once its arguments exist + // (or it finished), never with an empty object. + const hasInput = st.input && Object.keys(st.input).length > 0; + if (!seen.has(id) && (hasInput || st.status === "completed" || st.status === "error")) { + seen.set(id, "called"); + this.emit("tool_call", { id, name: part.tool, args: st.input || {} }); + } + if (seen.get(id) === "called" && (st.status === "completed" || st.status === "error")) { + seen.set(id, "done"); + this.emit("tool_result", { id, result: st.status === "error" ? `Error in ${part.tool}: ${st.error || "failed"}` : String(st.output ?? st.title ?? "") }); + } + break; + } + case "permission.asked": + this.#onPermission(sid, p); + break; + case "session.error": + this.emit("system", { content: `OpenCode: ${(p.error && (p.error.data && p.error.data.message || p.error.name)) || "error"}` }); + break; + } + }, this.workspace); + + const res = await this.engine.prompt(sid, { directory: this.workspace, providerID, modelID, text }); + if (this.aborted) { this.emit("aborted", this.#stats()); return; } + const err = res && res.info && res.info.error; + if (err) { + const msg = (err.data && err.data.message) || err.name || "OpenCode session error"; + this.emit("error", { message: `OpenCode (${modelID}): ${msg}` }); + return; + } + const out = textOf(res); + this.lastText = out; + this.messages.push({ role: "assistant", content: out }); + // Clients that render only the stream (ACP) must still see the whole + // answer when the event feed lagged behind the response. + if (out && !streamedText) this.emit("assistant_delta", { chunk: out }); + else if (out && out.startsWith(streamedText) && out.length > streamedText.length) this.emit("assistant_delta", { chunk: out.slice(streamedText.length) }); + if (out) this.emit("assistant", { content: out }); + this.emit("done", this.#stats()); + } catch (e) { + if (this.aborted) { this.emit("aborted", this.#stats()); return; } + this.emit("error", { message: e.message }); + } finally { + unsubscribe(); + } + } + + async #onPermission(sid, p) { + let response = "reject"; + try { + if (this.approvalMode === "auto") response = "once"; + else if (this.approver) { + const name = p.permission || "tool"; + const args = { ...(p.metadata || {}), patterns: p.patterns }; + response = (await this.approver(p.id, name, args, null)) ? "once" : "reject"; + } + } catch {} + await this.engine.replyPermission(sid, p.id, response, this.workspace).catch(() => {}); + } + + #stats() { const s = this.turnStats; return s ? { elapsedMs: Date.now() - s.startedAt, inTokens: 0, outTokens: 0, estimated: true } : {}; } + + async runSubagents() { return "Subagents aren't available on the OpenCode engine — delegate the pieces separately."; } + loadProjectMemory() { return ""; } +} + +// The last turns of a conversation another model handled, as a preface for +// the engine's first prompt. Bounded so a long session does not become the +// whole prompt. +function carriedContext(messages, { turns = 20, perMessage = 600, total = 8000 } = {}) { + const recent = messages.filter((m) => m.role === "user" || m.role === "assistant").slice(-turns); + const lines = []; + let size = 0; + for (const m of recent) { + const body = typeof m.content === "string" ? m.content : Array.isArray(m.content) ? m.content.filter((c) => c && c.type === "text").map((c) => c.text).join("\n") : ""; + const line = `${m.role === "user" ? "User" : "Assistant"}: ${String(body).replace(/\s+/g, " ").trim().slice(0, perMessage)}`; + if (size + line.length > total) break; + lines.push(line); size += line.length; + } + if (!lines.length) return ""; + return `Context — this conversation was handled by another model until now. Recent turns:\n${lines.join("\n")}\n\nContinue from here. New message:\n`; +} + +function textOf(res) { + const parts = (res && res.parts) || []; + return parts.filter((p) => p && p.type === "text" && !p.synthetic).map((p) => p.text || "").join("").trim(); +} + +const isEngineModel = (id) => typeof id === "string" && id.startsWith(PREFIX); + +module.exports = { PREFIX, findBinary, candidates, available, version, install, download, lockEntry, platformPackage, pinnedVersion, target, DOWNLOAD_DIR, INSTALL_COMMAND, INSTALL_SCRIPT, Engine, getEngine, OpenCodeAgent, isEngineModel }; diff --git a/electron/preload.js b/electron/preload.js index f3171c1..8f13eb7 100644 --- a/electron/preload.js +++ b/electron/preload.js @@ -52,11 +52,15 @@ contextBridge.exposeInMainWorld("omniwork", { listModels: () => ipcRenderer.invoke("models:list"), setModel: (model) => ipcRenderer.invoke("app:setModel", model), openDashboard: () => ipcRenderer.invoke("gateway:openDashboard"), + providersStatus: () => ipcRenderer.invoke("providers:status"), + providersConnect: (provider, apiKey) => ipcRenderer.invoke("providers:connect", { provider, apiKey }), + providersRemove: (provider) => ipcRenderer.invoke("providers:remove", provider), + openUrl: (url) => ipcRenderer.invoke("app:openUrl", url), copyText: (text) => ipcRenderer.invoke("app:copy", text), setCopyOnSelect: (on) => ipcRenderer.invoke("app:setCopyOnSelect", on), on: (channel, cb) => { - const allowed = new Set(["session:event", "sessions:list", "gateway:status", "mcp:list", "skills:list"]); + const allowed = new Set(["session:event", "sessions:list", "gateway:status", "mcp:list", "skills:list", "providers:suggest"]); if (!allowed.has(channel)) return () => {}; const listener = (_e, payload) => cb(payload); ipcRenderer.on(channel, listener); diff --git a/electron/providers.js b/electron/providers.js new file mode 100644 index 0000000..173f78a --- /dev/null +++ b/electron/providers.js @@ -0,0 +1,418 @@ +"use strict"; +// Free-model providers for the gateway: what to connect, how to connect it in +// as few clicks as possible, and which connected models a headless agent +// should fall back to. +// +// Why this exists: OmniRoute's out-of-the-box "free" pool is a handful of +// unofficial keyless endpoints (a scraped hobby site, a restaurant's chat +// widget, a CLI shim) that vanish without notice — on a bad day every one is +// gone and `auto` has nothing left to route. The providers here are the +// opposite: real free tiers with published limits, behind a free account key. +// OmniRoute already speaks to all of them; this module gets the key in with +// one click (OpenRouter through its PKCE flow, the rest by paste), registers +// local model servers it finds running, and turns "what's connected" into the +// fallback chain the ACP/MCP servers and the desktop app use. + +const crypto = require("node:crypto"); +const http = require("node:http"); +const { spawn } = require("node:child_process"); +const opencode = require("./opencode-engine"); + +// Ordered by how good a fallback each is: strongest free coders first, the +// widest catalogs before the narrow ones. `prefer` lists model ids (without +// the gateway's alias prefix) in the order we'd pick them for a coding agent. +const CATALOG = [ + { + id: "openrouter", alias: "openrouter", name: "OpenRouter", connect: "pkce", + keyUrl: "https://openrouter.ai/settings/keys", + free: "20 free models (18 with tool calling) — 20 req/min, 50 req/day; 1,000/day after a one-time $10 top-up", + prefer: ["cohere/north-mini-code:free", "nvidia/nemotron-3-super-120b-a12b:free", "google/gemma-4-31b-it:free", "nvidia/nemotron-3.5-lightning:free"], + preferPattern: /:free$/, + }, + { + id: "ollama-cloud", alias: "ollamacloud", name: "Ollama Cloud", connect: "key", + keyUrl: "https://ollama.com/settings/keys", + free: "free 'light usage' tier — DeepSeek V4, Kimi K2.6, GLM 5.1, Gemma 4 (sign in, no card)", + prefer: ["deepseek-v4-flash", "glm-5.1", "gemma4:31b", "kimi-k2.6"], + }, + { + id: "kilo-gateway", alias: "kg", name: "Kilo Gateway", connect: "key", + keyUrl: "https://app.kilo.ai", + free: "kilo-auto/free router plus Nemotron 3 Super and MiniMax M2.5 :free (free account)", + prefer: ["kilo-auto/free", "nvidia/nemotron-3-super-120b-a12b:free", "minimax/minimax-m2.5:free"], + }, + { + id: "groq", alias: "groq", name: "Groq", connect: "key", + keyUrl: "https://console.groq.com/keys", + free: "gpt-oss-120b at 30 req/min, 1,000 req/day; Qwen 3 32B, Llama 3.3 70B — very fast", + prefer: ["openai/gpt-oss-120b", "qwen/qwen3-32b", "llama-3.3-70b-versatile"], + }, + { + id: "cerebras", alias: "cerebras", name: "Cerebras", connect: "key", + keyUrl: "https://cloud.cerebras.ai", + free: "free tier on gpt-oss-120b, GLM 4.7, Gemma 4 — fastest inference around", + prefer: ["gpt-oss-120b", "zai-glm-4.7", "gemma-4-31b"], + }, + { + id: "nvidia", alias: "nvidia", name: "NVIDIA NIM", connect: "key", + keyUrl: "https://build.nvidia.com/settings/api-keys", + free: "developer tier, ~40 req/min — Qwen 3.5, GLM 5.2, Gemma 4", + prefer: ["qwen/qwen3.5-122b-a10b", "z-ai/glm-5.2", "google/gemma-4-31b-it"], + }, + { + id: "gemini", alias: "gemini", name: "Google Gemini", connect: "key", + keyUrl: "https://aistudio.google.com/apikey", + free: "Gemini Flash and Flash-Lite free tier (Google account, no card)", + prefer: ["gemini-2.5-flash", "gemini-3-flash-preview", "gemini-2.5-flash-lite"], + }, + { + id: "mistral", alias: "mistral", name: "Mistral", connect: "key", + keyUrl: "https://console.mistral.ai/api-keys", + free: "free tier incl. Codestral (phone verification)", + prefer: ["codestral-latest"], + }, +]; + +// Local OpenAI-compatible servers, probed on their default ports. Slower and +// smaller than the cloud tiers, so they sit at the end of the chain — but a +// local model is the only thing that is *always* there. +const LOCAL = [ + { id: "ollama-local", alias: "ollama", name: "Ollama", url: "http://127.0.0.1:11434/v1" }, + { id: "lm-studio", alias: "lmstudio", name: "LM Studio", url: "http://127.0.0.1:1234/v1" }, + { id: "llama-cpp", alias: "llamacpp", name: "llama.cpp", url: "http://127.0.0.1:8080/v1" }, + { id: "vllm", alias: "vllm", name: "vLLM", url: "http://127.0.0.1:8000/v1" }, +]; + +const MAX_CHAIN = 6; + +// ── gateway management API ──────────────────────────────────────── +// OmniRoute's dashboard API, served openly on loopback. `gw.baseUrl` is the +// OpenAI-compatible `/v1` URL the agents use; the management API lives beside it. +function origin(gw) { return String(gw.baseUrl).replace(/\/v1\/?$/, ""); } + +async function call(gw, method, path, body, timeoutMs = 10_000) { + const res = await fetch(origin(gw) + path, { + method, + headers: { "Content-Type": "application/json", Authorization: `Bearer ${gw.apiKey || "omniwork"}` }, + body: body ? JSON.stringify(body) : undefined, + signal: AbortSignal.timeout(timeoutMs), + }); + const text = await res.text().catch(() => ""); + let json = null; + try { json = JSON.parse(text); } catch {} + if (!res.ok) { + const msg = (json && json.error && (json.error.message || json.error)) || text.slice(0, 200) || `HTTP ${res.status}`; + const err = new Error(`gateway ${method} ${path}: ${typeof msg === "string" ? msg : JSON.stringify(msg)}`); + err.status = res.status; + throw err; + } + return json; +} + +async function connections(gw) { + const data = await call(gw, "GET", "/api/providers"); + return (data && data.connections) || []; +} + +async function modelIds(gw) { + const data = await call(gw, "GET", "/v1/models", null, 8000); + return ((data && data.data) || []).map((m) => m && m.id).filter((id) => typeof id === "string" && id); +} + +async function addConnection(gw, { provider, name, apiKey, baseUrl }) { + const body = { provider, authType: "apikey", name, apiKey }; + if (baseUrl) body.providerSpecificData = { baseUrl }; + const data = await call(gw, "POST", "/api/providers", body); + return data && data.connection; +} + +// The connections a provider had before a new one was added. While the new +// key is being proven they are paused (the gateway would otherwise route the +// proof request to whichever connection it likes); on success they are +// removed, on failure they come back. A bad paste never leaves the user with +// less than they had. The new connection's own id is never in this list. +async function twinsOf(gw, provider, keepId) { + return (await connections(gw)).filter((c) => c.provider === provider && c.id !== keepId); +} +async function setActive(gw, conns, isActive) { + for (const c of conns) await call(gw, "PATCH", `/api/providers/${c.id}`, { isActive }).catch(() => {}); +} +async function retire(gw, conns) { + for (const c of conns) await call(gw, "DELETE", `/api/providers/${c.id}`).catch(() => {}); + return conns.length; +} + +// The gateway discovers a passthrough provider's models asynchronously after +// the connection lands — a few seconds for a local server. Anyone computing +// "what's routable now" right after a connect has to wait for that. +async function waitForModels(gw, alias, { timeoutMs = 12_000 } = {}) { + const until = Date.now() + timeoutMs; + let ids = []; + while (Date.now() < until) { + ids = await modelIds(gw).catch(() => []); + if (ids.some((id) => id.startsWith(alias + "/"))) return ids; + await new Promise((r) => setTimeout(r, 500)); + } + return ids; +} + +async function removeProvider(gw, provider) { + const mine = (await connections(gw)).filter((c) => c.provider === provider); + for (const c of mine) await call(gw, "DELETE", `/api/providers/${c.id}`); + return mine.length; +} + +// ── what's connected, what to fall back to ──────────────────────── +function entry(id) { return CATALOG.find((p) => p.id === id) || LOCAL.find((l) => l.id === id) || null; } + +function modelsFor(p, ids) { + const prefix = p.alias + "/"; + return ids.filter((id) => id.startsWith(prefix)).map((id) => id.slice(prefix.length)); +} + +// The fallback chain: for each connected provider, in catalog order, the best +// model it exposes right now — the preferred ids first, then anything the +// provider's free pattern matches, then whatever it lists. Local servers +// close the chain. Capped so a turn that hits every failure still ends. +function suggestChain(ids, { max = MAX_CHAIN } = {}) { + const chain = []; + for (const p of [...CATALOG, ...LOCAL]) { + const have = modelsFor(p, ids); + if (!have.length) continue; + const pick = (p.prefer || []).find((m) => have.includes(m)) + || (p.preferPattern ? have.find((m) => p.preferPattern.test(m)) : null) + || have[0]; + chain.push(`${p.alias}/${pick}`); + if (chain.length >= max) break; + } + return chain; +} + +async function probeLocal(url, timeoutMs = 1500) { + try { + const res = await fetch(`${url}/models`, { signal: AbortSignal.timeout(timeoutMs) }); + if (!res.ok) return null; + const data = await res.json(); + return ((data && data.data) || []).map((m) => m && m.id).filter(Boolean); + } catch { return null; } +} + +async function status(gw, { detectLocal = true, candidates = LOCAL } = {}) { + const [conns, ids] = await Promise.all([connections(gw), modelIds(gw)]); + const connected = (id) => conns.some((c) => c.provider === id && c.isActive !== false); + const providers = CATALOG.map((p) => ({ + id: p.id, name: p.name, connect: p.connect, keyUrl: p.keyUrl, free: p.free, + connected: connected(p.id), models: modelsFor(p, ids).length, + })); + const local = []; + for (const l of candidates) { + const running = detectLocal ? await probeLocal(l.url) : null; + local.push({ id: l.id, name: l.name, url: l.url, connected: connected(l.id), running: running != null, runningModels: running || [], models: modelsFor(l, ids).length }); + } + // The OpenCode engine: free Zen models with no account, if OpenCode is + // installed. Listing them starts its server once per process. + const oc = { installed: opencode.available(), version: null, models: [], installCommand: opencode.INSTALL_COMMAND, installScript: opencode.INSTALL_SCRIPT }; + if (oc.installed) { + oc.version = opencode.version(); + try { oc.models = (await opencode.getEngine().models()).map((m) => m.id); } catch (e) { oc.error = e.message; } + } + return { + providers, local, opencode: oc, + chain: suggestChain(ids), + freePool: ids.filter((id) => id === "auto" || id.startsWith("auto/")).length, + anyConnected: providers.some((p) => p.connected) || local.some((l) => l.connected) || oc.models.length > 0, + }; +} + +// ── connecting ──────────────────────────────────────────────────── +// A key that the provider rejects is worse than no key: the pool would keep +// trying it. So a pasted key is exercised once before it's kept. +async function verifyModel(gw, modelId) { + const res = await fetch(`${gw.baseUrl}/chat/completions`, { + method: "POST", + headers: { "Content-Type": "application/json", Authorization: `Bearer ${gw.apiKey || "omniwork"}` }, + body: JSON.stringify({ model: modelId, messages: [{ role: "user", content: "Reply with the single word READY." }], max_tokens: 8 }), + signal: AbortSignal.timeout(45_000), + }); + if (res.ok) return true; + const body = await res.text().catch(() => ""); + const err = new Error(`${modelId} answered HTTP ${res.status}: ${body.slice(0, 200)}`); + err.status = res.status; + throw err; +} + +async function connectWithKey(gw, providerId, apiKey, { verify = true } = {}) { + const p = CATALOG.find((c) => c.id === providerId); + if (!p) throw new Error(`unknown provider: ${providerId} (known: ${CATALOG.map((c) => c.id).join(", ")})`); + const key = String(apiKey || "").trim(); + if (!key) throw new Error(`${p.name} needs an API key — create one at ${p.keyUrl}`); + // Add first, prove it, then retire what it replaces — the working + // connection the user already had is never the casualty of a bad paste. + const conn = await addConnection(gw, { provider: p.id, name: p.name, apiKey: key }); + const newId = conn && conn.id; + const twins = await twinsOf(gw, p.id, newId); + await setActive(gw, twins, false); + const undo = async () => { await setActive(gw, twins, true); if (newId) await call(gw, "DELETE", `/api/providers/${newId}`).catch(() => {}); }; + const ids = await waitForModels(gw, p.alias); + const have = modelsFor(p, ids); + const model = (p.prefer || []).find((m) => have.includes(m)) || (p.preferPattern ? have.find((m) => p.preferPattern.test(m)) : null) || have[0]; + if (!model) { + await undo(); + throw new Error(`${p.name} accepted the key but listed no models within 12 s — nothing was changed. Check the key at ${p.keyUrl} and try again.`); + } + if (verify) { + try { await verifyModel(gw, `${p.alias}/${model}`); } + catch (e) { + // 401/403 is the key itself; anything else (quota, a flaky model) is + // not a reason to throw the key away. + if (e.status === 401 || e.status === 403) { + await undo(); + throw new Error(`${p.name} rejected that key (${e.message}). Nothing was changed — check it at ${p.keyUrl}.`); + } + } + } + await retire(gw, twins); + return { provider: p.id, name: p.name, models: have.length, chain: suggestChain(ids) }; +} + +async function connectLocal(gw, { candidates = LOCAL, only = null } = {}) { + const added = []; + const skipped = []; + for (const l of candidates) { + if (only && l.id !== only) continue; + const running = await probeLocal(l.url); + if (!running) { skipped.push({ id: l.id, name: l.name, reason: "not running" }); continue; } + const conn = await addConnection(gw, { provider: l.id, name: l.name, apiKey: "local", baseUrl: l.url }); + await retire(gw, await twinsOf(gw, l.id, conn && conn.id)); + added.push({ id: l.id, name: l.name, url: l.url, models: running }); + } + const ids = added.length ? await waitForModels(gw, added[added.length - 1].alias || entry(added[added.length - 1].id).alias) : await modelIds(gw); + return { added, skipped, chain: suggestChain(ids) }; +} + +// OpenRouter's PKCE flow: the browser creates a key for us — no dashboard, +// no copy-paste. A loopback server catches the redirect; the code is only +// useful together with our verifier, so a stray callback can't mint a key. +function b64url(buf) { return Buffer.from(buf).toString("base64url"); } + +function defaultOpen(url) { + const cmd = process.platform === "darwin" ? ["open", [url]] + : process.platform === "win32" ? ["cmd", ["/c", "start", "", url.replace(/&/g, "^&")]] + : ["xdg-open", [url]]; + try { + const child = spawn(cmd[0], cmd[1], { stdio: "ignore", detached: true }); + child.on("error", () => {}); // no opener on this box: the URL is printed by the caller anyway + child.unref(); + return true; + } catch { return false; } +} + +const DONE_PAGE = (ok) => `OmniWork + +
${ok ? "✅" : "❌"}
+

${ok ? "OpenRouter is connected to OmniWork. You can close this tab." : "OpenRouter did not return a code. Close this tab and try again."}

`; + +async function connectOpenRouter(gw, { open = defaultOpen, onUrl = () => {}, authBase = "https://openrouter.ai", timeoutMs = 300_000, label = "OmniWork" } = {}) { + const verifier = b64url(crypto.randomBytes(48)); + const challenge = b64url(crypto.createHash("sha256").update(verifier).digest()); + + const server = http.createServer(); + await new Promise((resolve, reject) => { server.once("error", reject); server.listen(0, "127.0.0.1", resolve); }); + const port = server.address().port; + // A nonce in the callback path: OpenRouter redirects to the callback URL + // verbatim, so a stray request to the port (a web page probing localhost) + // cannot end or hijack the sign-in — only the real redirect has the path. + const nonce = b64url(crypto.randomBytes(16)); + const callbackPath = `/callback/${nonce}`; + const callback = `http://127.0.0.1:${port}${callbackPath}`; + const url = `${authBase}/auth?callback_url=${encodeURIComponent(callback)}&code_challenge=${challenge}&code_challenge_method=S256&key_label=${encodeURIComponent(label)}`; + + const exchange = async (code) => { + const res = await fetch(`${authBase}/api/v1/auth/keys`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ code, code_verifier: verifier, code_challenge_method: "S256" }), + signal: AbortSignal.timeout(30_000), + }); + if (!res.ok) throw new Error(`OpenRouter key exchange failed: HTTP ${res.status} ${(await res.text().catch(() => "")).slice(0, 200)}`); + const data = await res.json(); + if (!data || !data.key) throw new Error("OpenRouter key exchange returned no key"); + return data.key; + }; + + let key; + try { + key = await new Promise((resolve, reject) => { + const timer = setTimeout(() => reject(new Error("timed out waiting for the OpenRouter sign-in (5 min)")), timeoutMs); + let settled = false; + server.on("request", async (req, res) => { + const u = new URL(req.url, "http://127.0.0.1"); + if (u.pathname !== callbackPath || settled) { res.writeHead(404); res.end(); return; } + const c = u.searchParams.get("code"); + if (!c) { res.writeHead(400, { "Content-Type": "text/html; charset=utf-8" }); res.end(DONE_PAGE(false)); return; } + settled = true; + clearTimeout(timer); + // The browser sees "connected" only once the key really exists. + try { + const k = await exchange(c); + res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" }); res.end(DONE_PAGE(true)); + resolve(k); + } catch (e) { + res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" }); res.end(DONE_PAGE(false)); + reject(e); + } + }); + onUrl(url); + Promise.resolve().then(() => open(url)).catch((e) => { clearTimeout(timer); reject(new Error(`could not open the browser: ${e.message}. Open this URL yourself: ${url}`)); }); + }); + } finally { + server.close(); + } + return await connectWithKey(gw, "openrouter", key, { verify: false }); +} + +// One entry point for every surface (CLI, MCP tool, ACP auth method, desktop). +async function connect(gw, providerId, { apiKey, open, onUrl, authBase, install = false, log } = {}) { + if (providerId === "opencode") { + if (!opencode.available()) { + if (!install) throw new Error(`OpenCode is not present yet — run: ${opencode.INSTALL_COMMAND} (downloads ~45 MB; or: ${opencode.INSTALL_SCRIPT})`); + await opencode.install({ log }); + } + const models = await opencode.getEngine().models({ force: true }); + return { provider: "opencode", name: "OpenCode engine", engine: true, version: opencode.version(), models: models.length, modelIds: models.map((m) => m.id), chain: suggestChain(await modelIds(gw)) }; + } + if (providerId === "local") return await connectLocal(gw); + if (LOCAL.some((l) => l.id === providerId)) return await connectLocal(gw, { only: providerId }); + if (providerId === "openrouter" && !apiKey) return await connectOpenRouter(gw, { open, onUrl, authBase }); + return await connectWithKey(gw, providerId, apiKey); +} + +// Human-readable status, shared by the CLI and the MCP tool. +function describe(st) { + const lines = []; + const on = [...st.providers.filter((p) => p.connected), ...st.local.filter((l) => l.connected)]; + lines.push(on.length + ? `Connected: ${on.map((p) => `${p.name} (${p.models} models)`).join(", ")}.` + : "No free provider connected yet — the gateway's built-in keyless pool is unreliable (its endpoints get shut off upstream), so connect at least one."); + lines.push(st.chain.length ? `Fallback chain: ${st.chain.join(" → ")}` : "Fallback chain: (empty — nothing connected)"); + lines.push(""); + lines.push("Free providers (free account, no card):"); + for (const p of st.providers) { + lines.push(`- ${p.connected ? "✓" : "○"} ${p.id} — ${p.name}: ${p.free}. ${p.connect === "pkce" ? "Connect: one click, no key to paste." : `Key: ${p.keyUrl}`}`); + } + const oc = st.opencode; + if (oc) { + lines.push(""); + lines.push(oc.installed + ? `OpenCode engine: installed (${oc.version || "?"}) — ${oc.models.length ? `free models, no account: ${oc.models.join(", ")}` : (oc.error ? `could not list models: ${oc.error}` : "no free models listed")}. Runs OpenCode's own server; the automatic fallback when nothing else answers.` + : `OpenCode engine: not present yet. ${oc.installCommand} downloads OpenCode's official release (~45 MB, no npm, no PATH) and adds Zen's free models (Nemotron 3.5 Lightning, MiMo V2.5, Big Pickle, Ling 3.0 Flash, Nemotron 3 Ultra) with no account at all.`); + } + const running = st.local.filter((l) => l.running); + lines.push(""); + lines.push(running.length + ? `Local model servers running: ${running.map((l) => `${l.name}${l.connected ? " (connected)" : ` — ${l.runningModels.length} models, not connected yet`}`).join("; ")}` + : "Local model servers: none running (Ollama on :11434, LM Studio on :1234, llama.cpp on :8080, vLLM on :8000 are auto-detected)."); + return lines.join("\n"); +} + +module.exports = { CATALOG, LOCAL, status, describe, connect, connectWithKey, connectOpenRouter, connectLocal, removeProvider, suggestChain, connections, modelIds, waitForModels, defaultOpen }; diff --git a/electron/sessions.js b/electron/sessions.js index 6622d4e..d2a4688 100644 --- a/electron/sessions.js +++ b/electron/sessions.js @@ -9,6 +9,7 @@ const os = require("node:os"); const fs = require("node:fs"); const path = require("node:path"); const { Agent } = require("./agent"); +const opencode = require("./opencode-engine"); const { saveMemory, memoryFile } = require("./memory"); let counter = 0; @@ -34,6 +35,7 @@ class SessionManager { this.sessions = new Map(); this.activeId = null; this.model = "auto"; + this.fallbackModels = []; // tried in order when `model` fails — see providers.suggestChain this.approvalMode = "auto"; // "auto" | "ask" this.pendingApprovals = new Map(); // callId -> resolve this._saveTimer = null; @@ -115,6 +117,7 @@ class SessionManager { baseUrl: this.gateway.baseUrl, apiKey: this.gateway.apiKey, model: this.model, + fallbackModels: this.fallbackModels, workspace: sess.workspace, mcp: this.mcp, memory: this.projects ? { globalDir: this.globalMemoryDir, projectDir: this.projects.memoryDir(sess.projectId), knowledgeDir: this.projects.knowledgeDir(sess.projectId), instructionsFile: this.projects.instructionsFile(sess.projectId) } : null, @@ -131,6 +134,10 @@ class SessionManager { }), emit: (type, payload) => this.#onAgentEvent(id, type, payload), }); + if (opencode.isEngineModel(this.model)) { + const base = sess.agent; + sess.agent = new opencode.OpenCodeAgent({ model: this.model, workspace: sess.workspace, approvalMode: base.approvalMode, approver: base.approver, emit: base.emit }); + } if (this._ctxTokens) sess.agent.contextTokens = this._ctxTokens; } @@ -185,9 +192,9 @@ class SessionManager { #onAgentEvent(id, type, payload) { const sess = this.sessions.get(id); if (!sess) return; - if (type === "error") sess.status = "error"; + if (type === "error") { sess.status = "error"; sess.lastError = String(payload && payload.message || ""); } else if (type === "done" || type === "aborted") sess.status = "done"; - if (type !== "assistant_delta" && type !== "tool_stream" && type !== "thinking" && type !== "approval_request" && type !== "context" && type !== "stats") { + if (type !== "assistant_delta" && type !== "reasoning_delta" && type !== "tool_stream" && type !== "thinking" && type !== "approval_request" && type !== "context" && type !== "stats") { sess.transcript.push({ type, ...payload }); if (sess.transcript.length > 4000) sess.transcript.splice(0, 1000); } @@ -253,6 +260,19 @@ class SessionManager { this.emit(id, "user", { content: shown, pastes: ev.pastes }); try { await sess.agent.send(text, images); + // Nothing on the gateway answered, but OpenCode is installed: finish the + // turn on its engine rather than hand the user a dead prompt. The switch + // sticks for the session and is written into the transcript. + if (sess.status === "error" && !sess.agent.isEngine && opencode.available() && /All models failed|Gateway (401|403|404|429|503)|No choices returned/.test(sess.lastError || "")) { + let model = `${opencode.PREFIX}nemotron-3.5-lightning-free`; + try { const list = await opencode.getEngine().models(); if (list.length) model = list[0].id; } catch {} + const prev = sess.agent; + sess.agent = new opencode.OpenCodeAgent({ model, workspace: sess.workspace, approvalMode: prev.approvalMode, approver: prev.approver, emit: prev.emit, messages: prev.messages }); + this.#onAgentEvent(id, "system", { content: `⇄ no gateway model answered — continuing on the OpenCode engine (${model})` }); + sess.status = "running"; + this.#pushList(); + await sess.agent.send(text, images); + } } catch (e) { sess.status = "error"; this.emit(id, "error", { message: e.message }); @@ -328,9 +348,28 @@ class SessionManager { this.save(); } + // The chain applies to live agents too: connecting a provider mid-session + // should rescue the very next turn, not the next session. + setFallbacks(list) { + this.fallbackModels = Array.isArray(list) ? list.slice() : []; + for (const s of this.sessions.values()) { + if (s.agent) s.agent.fallbackModels = this.fallbackModels.filter((m) => m !== s.agent.model); + } + } + setModel(model) { this.model = model; - for (const s of this.sessions.values()) if (s.agent) s.agent.model = model; + for (const s of this.sessions.values()) { + if (!s.agent) continue; + // Crossing between the gateway loop and the OpenCode engine is a new + // agent, not a field change; within one, it's just the model id. + if (Boolean(s.agent.isEngine) !== opencode.isEngineModel(model)) { + // Never leave a running agent behind: it would keep emitting into a + // session whose Stop now points at the new one. + if (s.status === "running") s.agent.abort(); + this.#buildAgent(s); + } else s.agent.model = model; + } this.refreshContextLimit(); } diff --git a/electron/sidecar.js b/electron/sidecar.js index deb4dc8..d15c3b8 100644 --- a/electron/sidecar.js +++ b/electron/sidecar.js @@ -14,6 +14,7 @@ const net = require("node:net"); const path = require("node:path"); const fs = require("node:fs"); const crypto = require("node:crypto"); +const tuning = require("./tuning"); const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); @@ -152,6 +153,13 @@ class Gateway { return false; } + // Turn on gateway-side token savings once it is healthy (compression). A PUT, + // idempotent and best-effort — never blocks or fails a boot. + #applyTuning() { + if (this._tuned) return; this._tuned = true; + tuning.enableCompression(this.baseUrl, this.apiKey, (...a) => { if (process.env.OMNIWORK_DEV) process.stderr.write("[sidecar] " + a.join(" ") + "\n"); }).catch(() => {}); + } + async start() { this.status("boot", "Launching OmniRoute…"); this._stopped = false; @@ -160,6 +168,7 @@ class Gateway { this.ready = true; this.adopted = true; // not ours to kill on shutdown this.status("ready", "OmniRoute · free models"); + this.#applyTuning(); this.#watchdog(); // adopted gateways can die under us (their owner exits) return this.baseUrl; } @@ -203,6 +212,7 @@ class Gateway { this.ready = true; this.adopted = true; // not ours to kill on shutdown this.status("ready", "OmniRoute · free models"); + this.#applyTuning(); this.#watchdog(); return this.baseUrl; } @@ -240,6 +250,7 @@ class Gateway { try { await this.#waitHealthy(); if (this._stopped) { this.#killProc(); throw new Error("gateway start aborted by shutdown"); } + this.#applyTuning(); this.#watchdog(); return this.baseUrl; } catch (e) { diff --git a/electron/tools.js b/electron/tools.js index 705b75f..24ef1ab 100644 --- a/electron/tools.js +++ b/electron/tools.js @@ -7,7 +7,7 @@ const path = require("node:path"); const { spawn } = require("node:child_process"); const MAX_READ_BYTES = 400 * 1024; // don't blow up context on huge files -const MAX_OUTPUT_CHARS = 30000; +const MAX_OUTPUT_CHARS = 48000; function confine(workspace, target) { const abs = path.resolve(workspace, target); @@ -113,9 +113,15 @@ const TOOL_SCHEMA = [ }, ]; +// Keep the head AND the tail. A head-only cut drops the end of a command's +// output — which is exactly where the error message and the [exit code N] +// marker live — so the model (and the escalation heuristic) lose the signal +// that the command failed. The gateway's RTK pass then compresses what remains. function truncate(s) { if (s.length <= MAX_OUTPUT_CHARS) return s; - return s.slice(0, MAX_OUTPUT_CHARS) + `\n… [truncated ${s.length - MAX_OUTPUT_CHARS} chars]`; + const tail = Math.min(8000, Math.floor(MAX_OUTPUT_CHARS / 4)); // room for errors + exit code + const head = MAX_OUTPUT_CHARS - tail; + return s.slice(0, head) + `\n… [truncated ${s.length - MAX_OUTPUT_CHARS} chars]\n` + s.slice(-tail); } // Prefer the user's login shell so commands see the same aliases, PATH and diff --git a/electron/tuning.js b/electron/tuning.js new file mode 100644 index 0000000..d5c5e71 --- /dev/null +++ b/electron/tuning.js @@ -0,0 +1,100 @@ +"use strict"; +// Token economy — how OmniWork finishes a task on fewer tokens than a +// competitor that only cheats its way to a free tier. Every lever here is +// opt-outable by env, and none of it changes *which* provider answers, only +// how little we spend getting the answer. +// +// 1. gateway-side compression (RTK) rewrites tool-result text — the bulk of +// an agent's context — with cheap heuristics, no model call. +// 2. housekeeping (titles, memory, compaction summaries) runs on the fast +// free pool, never the session's chosen model. +// 3. mechanical steps run on the fast pool and escalate to the coding pool +// only when the fast model gets stuck. +// 6. a stable per-session id lets the gateway keep prompt-cache affinity, so +// the unchanged system+history prefix is cached upstream. + +const crypto = require("node:crypto"); + +const AUTO = "auto"; +const FAST = "auto/best-fast"; // free "fast" routing combo — grunt work +const STRONG = "auto/best-coding"; // free "coding" routing combo — real reasoning + +const off = (v) => /^(0|off|false|no)$/i.test(String(v ?? "")); + +// ── 1: compression, enabled once per gateway when it turns healthy ── +const compressionOn = () => !off(process.env.OMNIWORK_COMPRESSION); + +// The richest payload we're confident the strict settings schema accepts, +// then a proven-minimal fallback so a schema drift never leaves compression off. +const COMPRESSION_RICH = { + enabled: true, defaultMode: "rtk", + engines: { rtk: { enabled: true, level: "standard" } }, + rtkConfig: { + intensity: "standard", + applyToToolResults: true, // tool output is the bulk of an agent's context + applyToCodeBlocks: true, + rawOutputRetention: "failures", // keep failed-command output verbatim for debugging + deduplicateThreshold: 3, // collapse blocks that repeat 3+ times + enableGrouping: true, // fold near-identical lines (grep/log spew) + stripCodeComments: true, // comments rarely change the model's decision + preserveDocstrings: true, // …but docstrings often carry the contract + }, + preserveSystemPromptMode: "whenNoCache", mcpDescriptionCompressionEnabled: true, +}; +const COMPRESSION_MIN = { enabled: true, defaultMode: "rtk", preserveSystemPromptMode: "whenNoCache" }; + +function originOf(baseUrl) { return String(baseUrl).replace(/\/v1\/?$/, ""); } + +async function enableCompression(baseUrl, apiKey, log = () => {}) { + if (!compressionOn()) { log("compression: disabled by env"); return false; } + const url = originOf(baseUrl) + "/api/settings/compression"; + const headers = { "Content-Type": "application/json", Authorization: `Bearer ${apiKey || "omniwork"}` }; + for (const body of [COMPRESSION_RICH, COMPRESSION_MIN]) { + try { + const res = await fetch(url, { method: "PUT", headers, body: JSON.stringify(body), signal: AbortSignal.timeout(8000) }); + if (res.ok) { log(`compression on (rtk, ${body === COMPRESSION_RICH ? "standard" : "default"})`); return true; } + log(`compression PUT ${res.status} — ${body === COMPRESSION_RICH ? "retrying minimal" : "gave up"}`); + } catch (e) { log("compression enable failed: " + e.message); return false; } + } + return false; +} + +// ── 2: the cheap model for housekeeping ── +function utilityModel(primary) { + if (process.env.OMNIWORK_UTILITY_MODEL) return process.env.OMNIWORK_UTILITY_MODEL; + // Only ever redirect the auto pools; a pinned model's owner may have reasons + // (a keyed provider, a local server) we shouldn't second-guess, and an engine + // model's oneShot is already local and cheap. + return primary === AUTO || primary === FAST || primary === STRONG ? FAST : primary; +} + +// ── 3: step-level tiers, on for `auto`, off for a pinned model ── +function tiersFor(primary, opt) { + if (opt === false || off(process.env.OMNIWORK_MODEL_TIERS)) return null; + if (primary !== AUTO) return null; // respect an explicit choice + return { fast: FAST, strong: STRONG }; +} + +// A tool result that means the step failed — the signal to escalate. +function toolFailed(result) { + const s = String(result || ""); + if (/^(Error in |Failed to |Failed to start|Search failed|Browse failed|Install failed|❌|⏸)/.test(s)) return true; + // A non-zero exit code, wherever it lands (head+tail truncation keeps the tail). + if (/\[exit code ([1-9]\d*)\]/.test(s)) return true; + // Shell error lines, anchored so the words don't false-positive inside output. + // A real shell error ends with the phrase; prose that merely mentions it keeps going. + return /(^|\n)[^\n]*: (No such file or directory|command not found|Permission denied)(\n|$)/.test(s) + || /\bENOENT\b/.test(s); +} + +// Verifying a delegation costs a (cheap) model call, so only spend it when the +// task actually changed something or its wording implies it should have. A +// read-only research delegation is self-evident from its summary. +function shouldVerify(task, changed) { + if (changed) return true; + return /\b(create|write|edit|modify|fix|add|implement|refactor|rename|delete|remove|update|install|generate|build|migrat)/i.test(String(task || "")); +} + +const newSessionId = () => crypto.randomUUID(); + +module.exports = { AUTO, FAST, STRONG, compressionOn, enableCompression, utilityModel, tiersFor, toolFailed, shouldVerify, newSessionId }; diff --git a/package-lock.json b/package-lock.json index 5c74103..c003539 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,24 +1,29 @@ { "name": "omniwork", - "version": "0.11.1", + "version": "0.12.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "omniwork", - "version": "0.11.1", + "version": "0.12.0", "license": "MIT", "dependencies": { - "omniroute": "^3.8.48", + "omniroute": "^3.8.50", "tar": "^7.5.22" }, "bin": { - "omniwork-mcp": "electron/mcp-server.js" + "omniwork-acp": "electron/acp-server.js", + "omniwork-mcp": "electron/mcp-server.js", + "omniwork-providers": "scripts/providers.js" }, "devDependencies": { "cross-env": "^7.0.3", "electron": "^33.4.11", "electron-builder": "^25.1.8" + }, + "optionalDependencies": { + "opencode-ai": "1.18.31" } }, "node_modules/@alcalzone/ansi-tokenize": { @@ -79,37 +84,36 @@ } }, "node_modules/@atjsh/llmlingua-2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@atjsh/llmlingua-2/-/llmlingua-2-2.0.3.tgz", - "integrity": "sha512-UJJFMbzYldkZ4qX5CrSZtmytOnXf6aXhmr1sBhbpVMHdmQG+7GCnrx5rIwPSOmozXD9KiPv5nnV6pvzxdtHdYQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@atjsh/llmlingua-2/-/llmlingua-2-3.0.0.tgz", + "integrity": "sha512-SpRg3zzjATSTjbJV/3ldzDGba0yFjlcnCZ0x3QPJnrUm13PHCvlhwKlgET+BAM5SHFD3n6BsFTwsZUxDBwOyDw==", "license": "MIT", "optional": true, "dependencies": { "es-toolkit": "^1.38.0" }, "peerDependencies": { - "@huggingface/transformers": "*", - "@tensorflow/tfjs": "*", + "@huggingface/transformers": "^4.2.0", "js-tiktoken": "*" } }, "node_modules/@aws-sdk/client-bedrock-runtime": { - "version": "3.1093.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-bedrock-runtime/-/client-bedrock-runtime-3.1093.0.tgz", - "integrity": "sha512-CpXch6f8k+Cwjh/dLXwmoYc44ELmDlXFMPHAZBe6wDN4TDKNskgk9M6LUuizMvN1OHfvQcoGtvy8Oc/G3RNvLg==", + "version": "3.1133.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-bedrock-runtime/-/client-bedrock-runtime-3.1133.0.tgz", + "integrity": "sha512-4yieaqZc7JI396eBjccci390QyLK9CW5S+6fIxiLZEYSGCPD6hrJEleVJkmH4hFBFFx4Q6KPaDScMC/FUYaQtA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.976.0", - "@aws-sdk/credential-provider-node": "^3.972.71", - "@aws-sdk/eventstream-handler-node": "^3.972.29", - "@aws-sdk/middleware-eventstream": "^3.972.24", - "@aws-sdk/middleware-websocket": "^3.972.42", - "@aws-sdk/token-providers": "3.1093.0", - "@aws-sdk/types": "^3.974.2", - "@smithy/core": "^3.29.4", - "@smithy/fetch-http-handler": "^5.6.6", - "@smithy/node-http-handler": "^4.9.6", - "@smithy/types": "^4.16.1", + "@aws-sdk/core": "^3.978.0", + "@aws-sdk/credential-provider-node": "^3.972.83", + "@aws-sdk/eventstream-handler-node": "^3.972.34", + "@aws-sdk/middleware-eventstream": "^3.972.29", + "@aws-sdk/middleware-websocket": "^3.972.53", + "@aws-sdk/token-providers": "3.1133.0", + "@aws-sdk/types": "^3.974.5", + "@smithy/core": "^3.33.3", + "@smithy/fetch-http-handler": "^5.7.2", + "@smithy/node-http-handler": "^4.11.3", + "@smithy/types": "^4.17.2", "tslib": "^2.6.2" }, "engines": { @@ -117,17 +121,17 @@ } }, "node_modules/@aws-sdk/core": { - "version": "3.976.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.976.0.tgz", - "integrity": "sha512-0cjRaEdlVoOrsNb9pP5q1Syyc8pXw5xSj2Np2ryReRTr9FppIIRVSdZK4lbnfmc2Hvgux/xBOUU6baB7z8//uA==", + "version": "3.978.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.978.0.tgz", + "integrity": "sha512-2yX9LUmxPklVjSGTb8dfnWRJSiFQ3TeH2nn7G1mdKHTfnabzF0+gfrS8rYfLWmZrQ8A3mEcxMJjRc51dL5KWaA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "^3.974.2", - "@aws-sdk/xml-builder": "^3.972.36", + "@aws-sdk/types": "^3.974.5", + "@aws-sdk/xml-builder": "^3.972.40", "@aws/lambda-invoke-store": "^0.3.0", - "@smithy/core": "^3.29.4", - "@smithy/signature-v4": "^5.6.5", - "@smithy/types": "^4.16.1", + "@smithy/core": "^3.33.3", + "@smithy/signature-v4": "^5.6.12", + "@smithy/types": "^4.17.2", "bowser": "^2.11.0", "tslib": "^2.6.2" }, @@ -136,15 +140,15 @@ } }, "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.972.60", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.60.tgz", - "integrity": "sha512-BAkxdoe7tpDDqCghGpuOeHQRbm/2znVvOQm0AvpQbA2tbfMN46doN4zx65fv85ImP3KADwc2zQPmbrlI9MPfMg==", + "version": "3.972.71", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.71.tgz", + "integrity": "sha512-JN+JHruYZw3GUZB8YGAlDk4wTDPOEAEEdEzj5nS0xodWR4smzHsN7PnK2j6IeOsDIj2aqua5DSbhXl9Gtf90FQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.976.0", - "@aws-sdk/types": "^3.974.2", - "@smithy/core": "^3.29.4", - "@smithy/types": "^4.16.1", + "@aws-sdk/core": "^3.978.0", + "@aws-sdk/types": "^3.974.5", + "@smithy/core": "^3.33.3", + "@smithy/types": "^4.17.2", "tslib": "^2.6.2" }, "engines": { @@ -152,17 +156,17 @@ } }, "node_modules/@aws-sdk/credential-provider-http": { - "version": "3.972.62", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.62.tgz", - "integrity": "sha512-g/0fGqKTb9xpKdd9AtpmV5Eo3DFKbnkpA2+w0peISSlu7NfAoWOuYBFxsu+yWBtxU89ka55ezoZBCbFaS8pjYQ==", + "version": "3.972.73", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.73.tgz", + "integrity": "sha512-uyYYnJOnlis8uQzaYGPd7N1JoioCoNpXgnkXYixsWJXHXgXyYi8WXJSDfofxJeWfQIGWLe2Nwyq60Uc7MZdVOg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.976.0", - "@aws-sdk/types": "^3.974.2", - "@smithy/core": "^3.29.4", - "@smithy/fetch-http-handler": "^5.6.6", - "@smithy/node-http-handler": "^4.9.6", - "@smithy/types": "^4.16.1", + "@aws-sdk/core": "^3.978.0", + "@aws-sdk/types": "^3.974.5", + "@smithy/core": "^3.33.3", + "@smithy/fetch-http-handler": "^5.7.2", + "@smithy/node-http-handler": "^4.11.3", + "@smithy/types": "^4.17.2", "tslib": "^2.6.2" }, "engines": { @@ -170,23 +174,23 @@ } }, "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.973.5", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.973.5.tgz", - "integrity": "sha512-ylubazcRfq2TVus/qXucSXeC42Qdjp5HQxTu68K/BsdMiZlcSLD1zkpoCgApXZX1Y6YJhtGGs7ZHhO/GuIgBlw==", + "version": "3.973.16", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.973.16.tgz", + "integrity": "sha512-i++ly+0Uxa+u3ebSSyr0S/3CFhFJDxCXT3+Zj+mW2bXenEx5bKGCdTIKFu39SgXBNhWDjex/8cXUx9MUTMCrTw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.976.0", - "@aws-sdk/credential-provider-env": "^3.972.60", - "@aws-sdk/credential-provider-http": "^3.972.62", - "@aws-sdk/credential-provider-login": "^3.972.67", - "@aws-sdk/credential-provider-process": "^3.972.60", - "@aws-sdk/credential-provider-sso": "^3.973.4", - "@aws-sdk/credential-provider-web-identity": "^3.972.66", - "@aws-sdk/nested-clients": "^3.997.34", - "@aws-sdk/types": "^3.974.2", - "@smithy/core": "^3.29.4", - "@smithy/credential-provider-imds": "^4.4.9", - "@smithy/types": "^4.16.1", + "@aws-sdk/core": "^3.978.0", + "@aws-sdk/credential-provider-env": "^3.972.71", + "@aws-sdk/credential-provider-http": "^3.972.73", + "@aws-sdk/credential-provider-login": "^3.972.78", + "@aws-sdk/credential-provider-process": "^3.972.71", + "@aws-sdk/credential-provider-sso": "^3.973.15", + "@aws-sdk/credential-provider-web-identity": "^3.972.77", + "@aws-sdk/nested-clients": "^3.997.45", + "@aws-sdk/types": "^3.974.5", + "@smithy/core": "^3.33.3", + "@smithy/credential-provider-imds": "^4.4.16", + "@smithy/types": "^4.17.2", "tslib": "^2.6.2" }, "engines": { @@ -194,16 +198,16 @@ } }, "node_modules/@aws-sdk/credential-provider-login": { - "version": "3.972.67", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.67.tgz", - "integrity": "sha512-CCygIKJ9YbI3n84OClSaSppkgKKHVj2TGT33c6FRORZrYNZQ1POmD+ip0FLYokiJAK7sSdc3YVkOsBm90oxWMQ==", + "version": "3.972.78", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.78.tgz", + "integrity": "sha512-eUtswnXu0+Ii9ieRK+0L7aPFV3Z/dnW2VntJzjBP9xs8s+8p5nBNuymIXtXwZ+5r5+XJP3e32nMkuZ/r0HozEA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.976.0", - "@aws-sdk/nested-clients": "^3.997.34", - "@aws-sdk/types": "^3.974.2", - "@smithy/core": "^3.29.4", - "@smithy/types": "^4.16.1", + "@aws-sdk/core": "^3.978.0", + "@aws-sdk/nested-clients": "^3.997.45", + "@aws-sdk/types": "^3.974.5", + "@smithy/core": "^3.33.3", + "@smithy/types": "^4.17.2", "tslib": "^2.6.2" }, "engines": { @@ -211,21 +215,21 @@ } }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.972.71", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.71.tgz", - "integrity": "sha512-HIg7Q2osBzajQwL+1Vkyh2E7Gim3eTNb9RHIsOxDGjW0eZg4oEKtRs5sioCnc73ilhaOm4gX2lHVF8J7+nt2rg==", + "version": "3.972.83", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.83.tgz", + "integrity": "sha512-jdso7ejzfRnatxMUZK4S/U6KbaDPCvfIV4XL+IQAPFDBt5rj5Fq595euqlK8Le4lNCMFR9oUpt+1l0aMgaayOQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/credential-provider-env": "^3.972.60", - "@aws-sdk/credential-provider-http": "^3.972.62", - "@aws-sdk/credential-provider-ini": "^3.973.5", - "@aws-sdk/credential-provider-process": "^3.972.60", - "@aws-sdk/credential-provider-sso": "^3.973.4", - "@aws-sdk/credential-provider-web-identity": "^3.972.66", - "@aws-sdk/types": "^3.974.2", - "@smithy/core": "^3.29.4", - "@smithy/credential-provider-imds": "^4.4.9", - "@smithy/types": "^4.16.1", + "@aws-sdk/credential-provider-env": "^3.972.71", + "@aws-sdk/credential-provider-http": "^3.972.73", + "@aws-sdk/credential-provider-ini": "^3.973.16", + "@aws-sdk/credential-provider-process": "^3.972.71", + "@aws-sdk/credential-provider-sso": "^3.973.15", + "@aws-sdk/credential-provider-web-identity": "^3.972.77", + "@aws-sdk/types": "^3.974.5", + "@smithy/core": "^3.33.3", + "@smithy/credential-provider-imds": "^4.4.16", + "@smithy/types": "^4.17.2", "tslib": "^2.6.2" }, "engines": { @@ -233,15 +237,15 @@ } }, "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.972.60", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.60.tgz", - "integrity": "sha512-YIo3f99hM43QdYG8hDzwGemnR/pU95b0kramqSJUTleCqaB7+HwKf7YZFHqvOgTqZTPx/mRmNIqoDRr3U0Z3Tw==", + "version": "3.972.71", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.71.tgz", + "integrity": "sha512-lYmXJa4gvq4xN1lrT5NiP5vIYYKcGWAdj8y+8o6dlcateB5eF3Dn8DtmjjHKfMBrTPAMr2pebIiX/UOj8c1/UA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.976.0", - "@aws-sdk/types": "^3.974.2", - "@smithy/core": "^3.29.4", - "@smithy/types": "^4.16.1", + "@aws-sdk/core": "^3.978.0", + "@aws-sdk/types": "^3.974.5", + "@smithy/core": "^3.33.3", + "@smithy/types": "^4.17.2", "tslib": "^2.6.2" }, "engines": { @@ -249,17 +253,17 @@ } }, "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.973.4", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.973.4.tgz", - "integrity": "sha512-BPdmL8sSBOCv4ngZ+3LHxyc3CNqDCEK37CHioCk7zGrTMY5sUtkH8q+o6qA80nn6w3/fyBPGNE7OIRlmoOxRQA==", + "version": "3.973.15", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.973.15.tgz", + "integrity": "sha512-6Jhcf4v0pSFdjk1EW2kvzuEBKD+UZ2uNcHUIglKKLndD20YhvkL2kdmDOV5/j4mYuWWwe/a1FQ1aomU86/Cg5Q==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.976.0", - "@aws-sdk/nested-clients": "^3.997.34", - "@aws-sdk/token-providers": "3.1092.0", - "@aws-sdk/types": "^3.974.2", - "@smithy/core": "^3.29.4", - "@smithy/types": "^4.16.1", + "@aws-sdk/core": "^3.978.0", + "@aws-sdk/nested-clients": "^3.997.45", + "@aws-sdk/token-providers": "3.1129.0", + "@aws-sdk/types": "^3.974.5", + "@smithy/core": "^3.33.3", + "@smithy/types": "^4.17.2", "tslib": "^2.6.2" }, "engines": { @@ -267,16 +271,16 @@ } }, "node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers": { - "version": "3.1092.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.1092.0.tgz", - "integrity": "sha512-hBYUAr6iBLNFcsiWTgtBb0stdSw39VOUq4Sp4A5caCNf66BAZplWN4FleKrVpJx5li2YgdnK2DqoFSMWC642FQ==", + "version": "3.1129.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.1129.0.tgz", + "integrity": "sha512-Sbl3rpzQdsG4ZK2zh0JWUYyZPKKorJlVOddA2T0DVbKJFrsW8J6wgnslxxUH04+WaBMr4A1HzJZvZX0xUvkniA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.976.0", - "@aws-sdk/nested-clients": "^3.997.34", - "@aws-sdk/types": "^3.974.2", - "@smithy/core": "^3.29.4", - "@smithy/types": "^4.16.1", + "@aws-sdk/core": "^3.978.0", + "@aws-sdk/nested-clients": "^3.997.45", + "@aws-sdk/types": "^3.974.5", + "@smithy/core": "^3.33.3", + "@smithy/types": "^4.17.2", "tslib": "^2.6.2" }, "engines": { @@ -284,16 +288,16 @@ } }, "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.972.66", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.66.tgz", - "integrity": "sha512-kSAziJboOmZmsR9/MTbiNjowl2BPes1bQuJpne4qAZ62ubi8fjfr/aupJSQje6udBoYxXTQbsL0e0kby2la3ng==", + "version": "3.972.77", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.77.tgz", + "integrity": "sha512-uylIQSUWpfLuH2LovxEEfwzJGM/SabLOfLMg6YXu/E8jJEKUdpdILCVCQCdFvHyu/7dLJOHPMfrSwduxO56NkQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.976.0", - "@aws-sdk/nested-clients": "^3.997.34", - "@aws-sdk/types": "^3.974.2", - "@smithy/core": "^3.29.4", - "@smithy/types": "^4.16.1", + "@aws-sdk/core": "^3.978.0", + "@aws-sdk/nested-clients": "^3.997.45", + "@aws-sdk/types": "^3.974.5", + "@smithy/core": "^3.33.3", + "@smithy/types": "^4.17.2", "tslib": "^2.6.2" }, "engines": { @@ -301,14 +305,14 @@ } }, "node_modules/@aws-sdk/eventstream-handler-node": { - "version": "3.972.29", - "resolved": "https://registry.npmjs.org/@aws-sdk/eventstream-handler-node/-/eventstream-handler-node-3.972.29.tgz", - "integrity": "sha512-t3tKQRTVXsI2QNPE3CaNjHl0wRO9Xi3acZkAyti2RQsiFmZ9Gi0kArX2ighlRJ1BtDVuul413gThAgzyTfgmWA==", + "version": "3.972.34", + "resolved": "https://registry.npmjs.org/@aws-sdk/eventstream-handler-node/-/eventstream-handler-node-3.972.34.tgz", + "integrity": "sha512-cTeVzpu1xEAkryTZBYhGwnQ6gOGyp8ZYZvmn0Sg/nI/ABmy/CRHHxPDJDUi9PxwxUtGGaatvfRUB3FCgT/rSWw==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "^3.974.2", - "@smithy/core": "^3.29.4", - "@smithy/types": "^4.16.1", + "@aws-sdk/types": "^3.974.5", + "@smithy/core": "^3.33.3", + "@smithy/types": "^4.17.2", "tslib": "^2.6.2" }, "engines": { @@ -316,14 +320,14 @@ } }, "node_modules/@aws-sdk/middleware-eventstream": { - "version": "3.972.24", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-eventstream/-/middleware-eventstream-3.972.24.tgz", - "integrity": "sha512-oykin4mDWxNOuYQ7SF1cHzgYeuFEkF4cdRwgvjFFbIklkx09qIFBiOgsORafG9sXZFO3TayMmQuAQYgADXhI8w==", + "version": "3.972.29", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-eventstream/-/middleware-eventstream-3.972.29.tgz", + "integrity": "sha512-dlRzHCgyB8W6hLuDC5pcT5q+ziPt00n4QGgGBE17ucLVU4zMa6lsbuUdQ2Pm75Z5VA8GF+R/+SgrRcaTdIzSIQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "^3.974.2", - "@smithy/core": "^3.29.4", - "@smithy/types": "^4.16.1", + "@aws-sdk/types": "^3.974.5", + "@smithy/core": "^3.33.3", + "@smithy/types": "^4.17.2", "tslib": "^2.6.2" }, "engines": { @@ -331,17 +335,17 @@ } }, "node_modules/@aws-sdk/middleware-websocket": { - "version": "3.972.42", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-websocket/-/middleware-websocket-3.972.42.tgz", - "integrity": "sha512-dw+GP8DC7QC2C8tUoK7DI8BnrNAjz8tb+uBHSrD2qJvxkCf58kTtFr98pljSrk+umU4n4HDW4eU2k7C2dWMzsg==", + "version": "3.972.53", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-websocket/-/middleware-websocket-3.972.53.tgz", + "integrity": "sha512-bIrDaMENQmYRBHntOiOheqkiw5+fhKW4Lqb+mS1uqF0VwvdWI22fW2HFgWrng66CmYd+4k8ePlpj38sEfTuMLQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.976.0", - "@aws-sdk/types": "^3.974.2", - "@smithy/core": "^3.29.4", - "@smithy/fetch-http-handler": "^5.6.6", - "@smithy/signature-v4": "^5.6.5", - "@smithy/types": "^4.16.1", + "@aws-sdk/core": "^3.978.0", + "@aws-sdk/types": "^3.974.5", + "@smithy/core": "^3.33.3", + "@smithy/fetch-http-handler": "^5.7.2", + "@smithy/signature-v4": "^5.6.12", + "@smithy/types": "^4.17.2", "tslib": "^2.6.2" }, "engines": { @@ -349,18 +353,18 @@ } }, "node_modules/@aws-sdk/nested-clients": { - "version": "3.997.34", - "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.997.34.tgz", - "integrity": "sha512-Y9REVrSwmLM+Qy6sZJ7ofMC2S3Hr3tPP/4CzL5U1olPP7OGoF+6+Px0E49cVQBtSxJtyeLJMf0UaBErfeSahAA==", + "version": "3.997.45", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.997.45.tgz", + "integrity": "sha512-mooq9Q+jLa18VoM7HouczmslZU60iiB0aKc/Ztnq/luIL1ud0z4DnYprLR/ZO1gp331S9tJctM1HZr7u6YKBXQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.976.0", - "@aws-sdk/signature-v4-multi-region": "^3.996.41", - "@aws-sdk/types": "^3.974.2", - "@smithy/core": "^3.29.4", - "@smithy/fetch-http-handler": "^5.6.6", - "@smithy/node-http-handler": "^4.9.6", - "@smithy/types": "^4.16.1", + "@aws-sdk/core": "^3.978.0", + "@aws-sdk/signature-v4-multi-region": "^3.996.46", + "@aws-sdk/types": "^3.974.5", + "@smithy/core": "^3.33.3", + "@smithy/fetch-http-handler": "^5.7.2", + "@smithy/node-http-handler": "^4.11.3", + "@smithy/types": "^4.17.2", "tslib": "^2.6.2" }, "engines": { @@ -368,14 +372,14 @@ } }, "node_modules/@aws-sdk/signature-v4-multi-region": { - "version": "3.996.41", - "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.996.41.tgz", - "integrity": "sha512-QMUytg+FQMGouc8gHS00KoYih3+N6cqmVI/pQGOIo7Nr7OpQaiXjSYOuL+vsPZ1tymY4LAQ8MYcHJmws5LRxng==", + "version": "3.996.46", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.996.46.tgz", + "integrity": "sha512-L+2xZTye/2T96f3lwCws0Zw6GG2JHZW9e8FpVgGBeeExSKyeoZ6CWRpBml/7DNiK/O26jrgPM9F+Ay8VkgzUWQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "^3.974.2", - "@smithy/signature-v4": "^5.6.5", - "@smithy/types": "^4.16.1", + "@aws-sdk/types": "^3.974.5", + "@smithy/signature-v4": "^5.6.12", + "@smithy/types": "^4.17.2", "tslib": "^2.6.2" }, "engines": { @@ -383,16 +387,16 @@ } }, "node_modules/@aws-sdk/token-providers": { - "version": "3.1093.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.1093.0.tgz", - "integrity": "sha512-0TOm0RAnnsgV3eaG/xh/PlMxtmpv8hvdAjVReQvmOMhBgIKdYuc3Iz318GvnDNNgf3pUoV5zUaLVeGz4jp3shw==", + "version": "3.1133.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.1133.0.tgz", + "integrity": "sha512-CwH8Dc1ACC+G+CGBOjRhQLUI8o7c+O8Q1fsXHeot2Vi5VSD6UPVsKAqoWiFj7yW/r+QB5kN4QWWV9GWi810LfQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.976.0", - "@aws-sdk/nested-clients": "^3.997.34", - "@aws-sdk/types": "^3.974.2", - "@smithy/core": "^3.29.4", - "@smithy/types": "^4.16.1", + "@aws-sdk/core": "^3.978.0", + "@aws-sdk/nested-clients": "^3.997.45", + "@aws-sdk/types": "^3.974.5", + "@smithy/core": "^3.33.3", + "@smithy/types": "^4.17.2", "tslib": "^2.6.2" }, "engines": { @@ -400,12 +404,12 @@ } }, "node_modules/@aws-sdk/types": { - "version": "3.974.2", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.974.2.tgz", - "integrity": "sha512-3W6IUtSxFbH6X7Wb7DzGCV5QiFQsd0g8bOfntpmDxQlzBoKWUMBu/JPQR0DwkE+Hpnxd6db1tXbOwdeHddG6cA==", + "version": "3.974.5", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.974.5.tgz", + "integrity": "sha512-LkwLL2BLbC6wNNm4JaH9mbEqBMdOZCct6VAYqhdN4U1xrWM+fUJQEfbHwQgDypapOWTRtlk25akb5afM0P8CIQ==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.16.1", + "@smithy/types": "^4.17.2", "tslib": "^2.6.2" }, "engines": { @@ -413,12 +417,12 @@ } }, "node_modules/@aws-sdk/xml-builder": { - "version": "3.972.36", - "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.972.36.tgz", - "integrity": "sha512-RdGmS1GLrtaTOLE1ElSluMldNrpk9Emq6uYs8SS8iHlu5xTAmM9rRkM91o48+rIRryBtyO9t+uLYCoMG6jVMVA==", + "version": "3.972.40", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.972.40.tgz", + "integrity": "sha512-wlFmCIGUlwF4zx/kncw+bmxTQh1HeSJq4mYV/V5cZUSJadDP3kXvGW8Rn21cimj/7y9ju+47oYWXi97vF7czaA==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.16.1", + "@smithy/types": "^4.17.2", "tslib": "^2.6.2" }, "engines": { @@ -449,13 +453,13 @@ } }, "node_modules/@babel/generator": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.7.tgz", - "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==", + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.8.tgz", + "integrity": "sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.29.7", - "@babel/types": "^7.29.7", + "@babel/parser": "^7.29.8", + "@babel/types": "^7.29.8", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" @@ -505,12 +509,12 @@ } }, "node_modules/@babel/parser": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", - "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.8.tgz", + "integrity": "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==", "license": "MIT", "dependencies": { - "@babel/types": "^7.29.7" + "@babel/types": "^7.29.8" }, "bin": { "parser": "bin/babel-parser.js" @@ -543,17 +547,17 @@ } }, "node_modules/@babel/traverse": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.7.tgz", - "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==", + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.8.tgz", + "integrity": "sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==", "license": "MIT", "dependencies": { "@babel/code-frame": "^7.29.7", - "@babel/generator": "^7.29.7", + "@babel/generator": "^7.29.8", "@babel/helper-globals": "^7.29.7", - "@babel/parser": "^7.29.7", + "@babel/parser": "^7.29.8", "@babel/template": "^7.29.7", - "@babel/types": "^7.29.7", + "@babel/types": "^7.29.8", "debug": "^4.3.1" }, "engines": { @@ -561,9 +565,9 @@ } }, "node_modules/@babel/types": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", - "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz", + "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.29.7", @@ -1356,10 +1360,35 @@ "node": ">= 10.0.0" } }, + "node_modules/@eloqnt/config": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@eloqnt/config/-/config-0.1.0.tgz", + "integrity": "sha512-SLR6ZSHxu6XdZtmOz3xRmC3gsY/sCzqtLMD1gxbW2I3XXPBbupwL5RZbkLU/NcZm74AKZrIUPfz3CtEJfxUKqQ==", + "license": "MIT" + }, + "node_modules/@eloqnt/format-json": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@eloqnt/format-json/-/format-json-0.1.0.tgz", + "integrity": "sha512-4Pkb+HyzgWNJXoU48aJhUyNZSjZvMGooPCNG1ZFmBm55xTiNNPQCNXH66Ob6sXS6RvbWZrRpCf+Uo/Jz9K9g+A==", + "license": "MIT", + "dependencies": { + "@eloqnt/config": "^0.1.0" + } + }, + "node_modules/@eloqnt/format-po": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@eloqnt/format-po/-/format-po-0.1.0.tgz", + "integrity": "sha512-odgtuICWs67GdkNqY51/d2vaIukuOdlGalKASUGkI5c4cyWOmv/WIVyk5gZyn3xr614RzwWp57s9WB40lRLlBw==", + "license": "MIT", + "dependencies": { + "@eloqnt/config": "^0.1.0", + "po-parser": "^2.2.0" + } + }, "node_modules/@emnapi/runtime": { - "version": "1.11.2", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.2.tgz", - "integrity": "sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA==", + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz", + "integrity": "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==", "license": "MIT", "optional": true, "dependencies": { @@ -1391,15 +1420,6 @@ "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==", "license": "MIT" }, - "node_modules/@emotion/babel-plugin/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/@emotion/babel-plugin/node_modules/stylis": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", @@ -1533,9 +1553,9 @@ "license": "MIT" }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", - "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz", + "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==", "cpu": [ "ppc64" ], @@ -1549,9 +1569,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", - "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.2.tgz", + "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==", "cpu": [ "arm" ], @@ -1565,9 +1585,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", - "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz", + "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==", "cpu": [ "arm64" ], @@ -1581,9 +1601,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", - "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.2.tgz", + "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==", "cpu": [ "x64" ], @@ -1597,9 +1617,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", - "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz", + "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==", "cpu": [ "arm64" ], @@ -1613,9 +1633,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", - "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz", + "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==", "cpu": [ "x64" ], @@ -1629,9 +1649,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", - "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz", + "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==", "cpu": [ "arm64" ], @@ -1645,9 +1665,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", - "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz", + "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==", "cpu": [ "x64" ], @@ -1661,9 +1681,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", - "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz", + "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==", "cpu": [ "arm" ], @@ -1677,9 +1697,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", - "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz", + "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==", "cpu": [ "arm64" ], @@ -1693,9 +1713,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", - "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz", + "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==", "cpu": [ "ia32" ], @@ -1709,9 +1729,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", - "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz", + "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==", "cpu": [ "loong64" ], @@ -1725,9 +1745,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", - "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz", + "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==", "cpu": [ "mips64el" ], @@ -1741,9 +1761,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", - "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz", + "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==", "cpu": [ "ppc64" ], @@ -1757,9 +1777,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", - "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz", + "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==", "cpu": [ "riscv64" ], @@ -1773,9 +1793,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", - "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz", + "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==", "cpu": [ "s390x" ], @@ -1789,9 +1809,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", - "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz", + "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==", "cpu": [ "x64" ], @@ -1805,9 +1825,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", - "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz", + "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==", "cpu": [ "arm64" ], @@ -1821,9 +1841,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", - "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz", + "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==", "cpu": [ "x64" ], @@ -1837,9 +1857,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", - "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz", + "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==", "cpu": [ "arm64" ], @@ -1853,9 +1873,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", - "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz", + "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==", "cpu": [ "x64" ], @@ -1869,9 +1889,9 @@ } }, "node_modules/@esbuild/openharmony-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", - "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz", + "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==", "cpu": [ "arm64" ], @@ -1885,9 +1905,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", - "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz", + "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==", "cpu": [ "x64" ], @@ -1901,9 +1921,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", - "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz", + "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==", "cpu": [ "arm64" ], @@ -1917,9 +1937,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", - "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz", + "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==", "cpu": [ "ia32" ], @@ -1933,9 +1953,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", - "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz", + "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==", "cpu": [ "x64" ], @@ -1993,24 +2013,24 @@ "license": "MIT" }, "node_modules/@formatjs/icu-messageformat-parser": { - "version": "3.5.15", - "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-3.5.15.tgz", - "integrity": "sha512-5o4grXKotAB3JqQuisLApHG43g17N+paoRTa92Jiz35Zvfemq0cVf4EDvuxyHAzmsJji7igaEowicLO/VmfJ8Q==", + "version": "3.5.19", + "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-3.5.19.tgz", + "integrity": "sha512-a5PAqgd3QPUge635SxrjPLIlTErcGwm3AMyTdmZXl0IqWXTdCx9AnuioEmvEZAV2HpeFdynLPXMvHv7dXGEWWw==", "license": "MIT", "dependencies": { - "@formatjs/icu-skeleton-parser": "2.1.11" + "@formatjs/icu-skeleton-parser": "2.1.12" } }, "node_modules/@formatjs/icu-skeleton-parser": { - "version": "2.1.11", - "resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-2.1.11.tgz", - "integrity": "sha512-j8cUmOJzVgkHuS0QiQ6ga76UIoLOFSAMWhs7aZJztH3aAdCOAE6vpC8KVvFB4cU10ON0y2/5oOVmPJ43s2lTwA==", + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-2.1.12.tgz", + "integrity": "sha512-ca7tZMLpfHX3sUD7hP6gE/qr6Iq89EDd3ZLeRhbsB7r0UD55DGJq+tmFLzrGrnx5StahUevQmQQVtbDRHsfDHA==", "license": "MIT" }, "node_modules/@formatjs/intl-localematcher": { - "version": "0.8.13", - "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.8.13.tgz", - "integrity": "sha512-kHEAFOkeJSPNi7c5PaKaRjxcBrJwzzt81ifUu+8uve1EDW/VJl83KsxmqgqNZLzcFEhSliZGvx3+pk/RH0IOmg==", + "version": "0.8.14", + "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.8.14.tgz", + "integrity": "sha512-8O7V38QmbB11+ryJ3KM/znrzXtiqgpXzqNoqDsndHZZ5/zDKTTL+cf5F0mzXkQEwhx8IlWnqYvEovf2S5EwLTw==", "license": "MIT", "dependencies": { "@formatjs/fast-memoize": "3.1.7" @@ -2033,9 +2053,9 @@ } }, "node_modules/@fumadocs/tailwind": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@fumadocs/tailwind/-/tailwind-0.1.1.tgz", - "integrity": "sha512-BnPe52UxSaG8yKlHMKBxXw8h6GpK5qO55ci6+Qd5JnquTvIw6SpfbC1P+qAi82PuPWv1KZAWY8bxRk4+x9ctXw==", + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@fumadocs/tailwind/-/tailwind-0.1.2.tgz", + "integrity": "sha512-VppeXgIRXjZMgpf2qijj1hcfxyeYl1s0ok8k6N3jyjiX64M7sDwnt2zGPd6dbfDybgbBvDw6C6J1e42gB5NzsA==", "license": "MIT", "peerDependencies": { "tailwindcss": "^4.0.0" @@ -2046,6 +2066,12 @@ } } }, + "node_modules/@fumari/image-size": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@fumari/image-size/-/image-size-0.1.1.tgz", + "integrity": "sha512-iaiV2wyzJ4mW358NX4CX3yGit+WjKYzpaQ+rldK9BjL/5jFpeV6ruWnZVq7MEyMn3Gd0DLi8g/79NZAAQaGscw==", + "license": "MIT" + }, "node_modules/@gar/promisify": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", @@ -2066,56 +2092,37 @@ } }, "node_modules/@huggingface/jinja": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@huggingface/jinja/-/jinja-0.4.1.tgz", - "integrity": "sha512-3WXbMFaPkk03LRCM0z0sylmn8ddDm4ubjU7X+Hg4M2GOuMklwoGAFXp9V2keq7vltoB/c7McE5aHUVVddAewsw==", + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/@huggingface/jinja/-/jinja-0.5.10.tgz", + "integrity": "sha512-SgS1D1bglQ94ceD4ZCL6eayUDy9uV1xuyk61OjgSxU5GJh7upqZCKII0JoTYMc6wWsg3JUgaPRX0ElQzXPk3Cw==", "license": "MIT", "optional": true, "engines": { "node": ">=18" } }, + "node_modules/@huggingface/tokenizers": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@huggingface/tokenizers/-/tokenizers-0.1.3.tgz", + "integrity": "sha512-8rF/RRT10u+kn7YuUbUg0OF30K8rjTc78aHpxT+qJ1uWSqxT1MHi8+9ltwYfkFYJzT/oS+qw3JVfHtNMGAdqyA==", + "license": "Apache-2.0", + "optional": true + }, "node_modules/@huggingface/transformers": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/@huggingface/transformers/-/transformers-3.5.2.tgz", - "integrity": "sha512-mfRXkmcL99+ibpjM++pvZmc2h3po8i1ZgSRI5Rtgh++P15GU0lY8UQteYt/w5V+GQw+Jpao93MoipcePzh3mKg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@huggingface/transformers/-/transformers-4.2.0.tgz", + "integrity": "sha512-8BRCoBMH0XsWaEIamuR0LrJGAfftgHAfb2Vrffy0VKlSAE/MnUJ5/h/zTfEP3fDIft+nk7TqB8xXEyABGitBjQ==", "license": "Apache-2.0", "optional": true, "dependencies": { - "@huggingface/jinja": "^0.4.1", - "onnxruntime-node": "1.21.0", - "onnxruntime-web": "1.22.0-dev.20250409-89f8206ba4", - "sharp": "^0.34.1" - } - }, - "node_modules/@iconify/types": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", - "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==", - "license": "MIT" - }, - "node_modules/@iconify/utils": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-3.1.4.tgz", - "integrity": "sha512-b1S7B1k9ohZ+iNTi2ATxbRYG9fTrJmUT0rc46bvVnNxqNRGW7dyo/vRREwyniI5IRN2RSJHDcm+s3BjWrSAjHw==", - "license": "MIT", - "dependencies": { - "@antfu/install-pkg": "^1.1.0", - "@iconify/types": "^2.0.0", - "import-meta-resolve": "^4.2.0" - } - }, - "node_modules/@img/colour": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", - "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=18" + "@huggingface/jinja": "^0.5.6", + "@huggingface/tokenizers": "^0.1.3", + "onnxruntime-node": "1.24.3", + "onnxruntime-web": "1.26.0-dev.20260416-b7804b056c", + "sharp": "^0.34.5" } }, - "node_modules/@img/sharp-darwin-arm64": { + "node_modules/@huggingface/transformers/node_modules/@img/sharp-darwin-arm64": { "version": "0.34.5", "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", @@ -2137,7 +2144,7 @@ "@img/sharp-libvips-darwin-arm64": "1.2.4" } }, - "node_modules/@img/sharp-darwin-x64": { + "node_modules/@huggingface/transformers/node_modules/@img/sharp-darwin-x64": { "version": "0.34.5", "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", @@ -2159,7 +2166,7 @@ "@img/sharp-libvips-darwin-x64": "1.2.4" } }, - "node_modules/@img/sharp-libvips-darwin-arm64": { + "node_modules/@huggingface/transformers/node_modules/@img/sharp-libvips-darwin-arm64": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", @@ -2175,7 +2182,7 @@ "url": "https://opencollective.com/libvips" } }, - "node_modules/@img/sharp-libvips-darwin-x64": { + "node_modules/@huggingface/transformers/node_modules/@img/sharp-libvips-darwin-x64": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", @@ -2191,7 +2198,7 @@ "url": "https://opencollective.com/libvips" } }, - "node_modules/@img/sharp-libvips-linux-arm": { + "node_modules/@huggingface/transformers/node_modules/@img/sharp-libvips-linux-arm": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", @@ -2207,7 +2214,7 @@ "url": "https://opencollective.com/libvips" } }, - "node_modules/@img/sharp-libvips-linux-arm64": { + "node_modules/@huggingface/transformers/node_modules/@img/sharp-libvips-linux-arm64": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", @@ -2223,7 +2230,7 @@ "url": "https://opencollective.com/libvips" } }, - "node_modules/@img/sharp-libvips-linux-ppc64": { + "node_modules/@huggingface/transformers/node_modules/@img/sharp-libvips-linux-ppc64": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", @@ -2239,7 +2246,7 @@ "url": "https://opencollective.com/libvips" } }, - "node_modules/@img/sharp-libvips-linux-riscv64": { + "node_modules/@huggingface/transformers/node_modules/@img/sharp-libvips-linux-riscv64": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", @@ -2255,7 +2262,7 @@ "url": "https://opencollective.com/libvips" } }, - "node_modules/@img/sharp-libvips-linux-s390x": { + "node_modules/@huggingface/transformers/node_modules/@img/sharp-libvips-linux-s390x": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", @@ -2271,7 +2278,7 @@ "url": "https://opencollective.com/libvips" } }, - "node_modules/@img/sharp-libvips-linux-x64": { + "node_modules/@huggingface/transformers/node_modules/@img/sharp-libvips-linux-x64": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", @@ -2287,7 +2294,7 @@ "url": "https://opencollective.com/libvips" } }, - "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "node_modules/@huggingface/transformers/node_modules/@img/sharp-libvips-linuxmusl-arm64": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", @@ -2303,7 +2310,7 @@ "url": "https://opencollective.com/libvips" } }, - "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "node_modules/@huggingface/transformers/node_modules/@img/sharp-libvips-linuxmusl-x64": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", @@ -2319,7 +2326,7 @@ "url": "https://opencollective.com/libvips" } }, - "node_modules/@img/sharp-linux-arm": { + "node_modules/@huggingface/transformers/node_modules/@img/sharp-linux-arm": { "version": "0.34.5", "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", @@ -2341,7 +2348,7 @@ "@img/sharp-libvips-linux-arm": "1.2.4" } }, - "node_modules/@img/sharp-linux-arm64": { + "node_modules/@huggingface/transformers/node_modules/@img/sharp-linux-arm64": { "version": "0.34.5", "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", @@ -2363,7 +2370,7 @@ "@img/sharp-libvips-linux-arm64": "1.2.4" } }, - "node_modules/@img/sharp-linux-ppc64": { + "node_modules/@huggingface/transformers/node_modules/@img/sharp-linux-ppc64": { "version": "0.34.5", "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", @@ -2385,7 +2392,7 @@ "@img/sharp-libvips-linux-ppc64": "1.2.4" } }, - "node_modules/@img/sharp-linux-riscv64": { + "node_modules/@huggingface/transformers/node_modules/@img/sharp-linux-riscv64": { "version": "0.34.5", "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", @@ -2407,7 +2414,7 @@ "@img/sharp-libvips-linux-riscv64": "1.2.4" } }, - "node_modules/@img/sharp-linux-s390x": { + "node_modules/@huggingface/transformers/node_modules/@img/sharp-linux-s390x": { "version": "0.34.5", "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", @@ -2429,7 +2436,7 @@ "@img/sharp-libvips-linux-s390x": "1.2.4" } }, - "node_modules/@img/sharp-linux-x64": { + "node_modules/@huggingface/transformers/node_modules/@img/sharp-linux-x64": { "version": "0.34.5", "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", @@ -2451,7 +2458,7 @@ "@img/sharp-libvips-linux-x64": "1.2.4" } }, - "node_modules/@img/sharp-linuxmusl-arm64": { + "node_modules/@huggingface/transformers/node_modules/@img/sharp-linuxmusl-arm64": { "version": "0.34.5", "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", @@ -2473,7 +2480,7 @@ "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" } }, - "node_modules/@img/sharp-linuxmusl-x64": { + "node_modules/@huggingface/transformers/node_modules/@img/sharp-linuxmusl-x64": { "version": "0.34.5", "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", @@ -2495,7 +2502,7 @@ "@img/sharp-libvips-linuxmusl-x64": "1.2.4" } }, - "node_modules/@img/sharp-wasm32": { + "node_modules/@huggingface/transformers/node_modules/@img/sharp-wasm32": { "version": "0.34.5", "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", @@ -2514,7 +2521,7 @@ "url": "https://opencollective.com/libvips" } }, - "node_modules/@img/sharp-win32-arm64": { + "node_modules/@huggingface/transformers/node_modules/@img/sharp-win32-arm64": { "version": "0.34.5", "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", @@ -2533,7 +2540,7 @@ "url": "https://opencollective.com/libvips" } }, - "node_modules/@img/sharp-win32-ia32": { + "node_modules/@huggingface/transformers/node_modules/@img/sharp-win32-ia32": { "version": "0.34.5", "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", @@ -2552,7 +2559,7 @@ "url": "https://opencollective.com/libvips" } }, - "node_modules/@img/sharp-win32-x64": { + "node_modules/@huggingface/transformers/node_modules/@img/sharp-win32-x64": { "version": "0.34.5", "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", @@ -2571,81 +2578,643 @@ "url": "https://opencollective.com/libvips" } }, - "node_modules/@ioredis/commands": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.10.0.tgz", - "integrity": "sha512-UmeW7z4LfctwoQ5wkhVzgq8tXkreED2xZGpX+Bg+zA+WJFZCT6c062AfCK/Dfk81xZnnwdhJCUMkitihRaoC2Q==", - "license": "MIT" - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "license": "ISC", + "node_modules/@huggingface/transformers/node_modules/sharp": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", + "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", + "hasInstallScript": true, + "license": "Apache-2.0", + "optional": true, "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + "@img/colour": "^1.0.0", + "detect-libc": "^2.1.2", + "semver": "^7.7.3" }, "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.34.5", + "@img/sharp-darwin-x64": "0.34.5", + "@img/sharp-libvips-darwin-arm64": "1.2.4", + "@img/sharp-libvips-darwin-x64": "1.2.4", + "@img/sharp-libvips-linux-arm": "1.2.4", + "@img/sharp-libvips-linux-arm64": "1.2.4", + "@img/sharp-libvips-linux-ppc64": "1.2.4", + "@img/sharp-libvips-linux-riscv64": "1.2.4", + "@img/sharp-libvips-linux-s390x": "1.2.4", + "@img/sharp-libvips-linux-x64": "1.2.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", + "@img/sharp-libvips-linuxmusl-x64": "1.2.4", + "@img/sharp-linux-arm": "0.34.5", + "@img/sharp-linux-arm64": "0.34.5", + "@img/sharp-linux-ppc64": "0.34.5", + "@img/sharp-linux-riscv64": "0.34.5", + "@img/sharp-linux-s390x": "0.34.5", + "@img/sharp-linux-x64": "0.34.5", + "@img/sharp-linuxmusl-arm64": "0.34.5", + "@img/sharp-linuxmusl-x64": "0.34.5", + "@img/sharp-wasm32": "0.34.5", + "@img/sharp-win32-arm64": "0.34.5", + "@img/sharp-win32-ia32": "0.34.5", + "@img/sharp-win32-x64": "0.34.5" } }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true, + "node_modules/@iconify/types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", + "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==", "license": "MIT" }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, + "node_modules/@iconify/utils": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-3.1.4.tgz", + "integrity": "sha512-b1S7B1k9ohZ+iNTi2ATxbRYG9fTrJmUT0rc46bvVnNxqNRGW7dyo/vRREwyniI5IRN2RSJHDcm+s3BjWrSAjHw==", "license": "MIT", "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" + "@antfu/install-pkg": "^1.1.0", + "@iconify/types": "^2.0.0", + "import-meta-resolve": "^4.2.0" + } + }, + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.4.tgz", + "integrity": "sha512-Uhfl4V4lhP2nbUVF9+hyH1+luj86f1gUFeo8ALYxFoULoU+G87D43BfeMP8XHsk9boxAnCY/bf2EHwhA7MuGsA==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.3.3" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.4.tgz", + "integrity": "sha512-hWniXY3bG5qKpkKrAwPe4y+VTPmf086YQAnkxWh7uA1YrlRouWGa0M0Mxj3ZjnXFkv7/TD1bTy9lGUK26vRvWw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=12" + "node": ">=20.9.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.3.3" } }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "license": "MIT", + "node_modules/@img/sharp-freebsd-wasm32": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.4.tgz", + "integrity": "sha512-lIsKw/BU+kjB4eZjxrYrZmwOJYi3Ajrv66iAlBmUPyKc3HpnloevB1g3wxGD9P/5BbQ1brBGl65VRRrCvQDEqA==", + "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" + "@img/sharp-wasm32": "0.35.4" }, "engines": { - "node": ">=12" + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.3.tgz", + "integrity": "sha512-suTBPTDGrI9WodccaDdwZItTSaBYASlBk1NSfElSHrUfzu3szG6lvIF58+WiFvnfzuK8ZBFS5zE00PxqxnRiPg==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.3.tgz", + "integrity": "sha512-FVJZ5mITMobmXIz/hPDTw0EintTW5H3WfrxwLqEqjiIihlu+hVRyGrFQ60xl0Lxn7Bt3zdpevPaQi0HEzqz9fw==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.3.tgz", + "integrity": "sha512-3rbU4vqXXc3hY/OiXdl52xZvT0F1yEngWfvqudtPJg/KkyiaQw2DRsFrNzpmLvfavbwOq3qXn36GP8obHRULQA==", + "cpu": [ + "arm" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.3.tgz", + "integrity": "sha512-0DaL0A6Xu6sQSQFwe4iVCrKWU2cCTItnRsYsCdxAMm9NF6twAA9BKnoqy4hqz4+azQ0JHuA26qiUKsf1XJ/v5A==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.3.tgz", + "integrity": "sha512-cdn1OvUBwsXhbC0zSzJnNzf5MZ/mTrobawDvNXBTxe8VtqKAm0sRuEY2Evzovb/w9JMk4TvRxqt1mekSuJz64w==", + "cpu": [ + "ppc64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.3.tgz", + "integrity": "sha512-HjPVx7yKz+0lqdhDlTw1tt90wamBoxhiXpvl1XZpJLiHH4RCJ5yDTqH+VlYPv2fwFs89JFw4c1IexYOcQUi4IQ==", + "cpu": [ + "riscv64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.3.tgz", + "integrity": "sha512-neWLh+3yCNThxnfy3c4BbVBeGgt9aftno+XbT56iK28RgeDs3UOFWviLWlUu0bArYVYJaFDK+RRohbicUNCm8Q==", + "cpu": [ + "s390x" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.3.tgz", + "integrity": "sha512-4vKmvAst9nrowcqquKFAyZJUDolUaIp8uRiN0mWFguJ1IplC9/pitXtlnnlU4aa/eJw3J7i67V+pwUL+wZGdsA==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.3.tgz", + "integrity": "sha512-Y9kQaLMuNoB0bPYOOdcZMaseNrFpPodIWWMrx+CZyydf2xn68j9WYc6sWWRrDwNkzCQjKYfc68L7jKjGlHMibw==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.3.tgz", + "integrity": "sha512-fj8Mv0HHfD1Rr+4I68+3agJynxDWtBFgicTbSOb9Bke6pIwzGcJ+RX/yHjmiEGFMCavY/dxvem7MyNaJF+wDiw==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.4.tgz", + "integrity": "sha512-7OAS8gI0EReKGVN2HssHlM6umJgxF5VI3xN0p9FA91p/YO+ou5hiNghLdZ5BEHztwaaK5+bLKRf8x/o2L2nk9A==", + "cpu": [ + "arm" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.3.3" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.4.tgz", + "integrity": "sha512-De4jpEnAU8Hd5oT0j1G3uL4ZvTuipVMn7YC6vPaJhy6/7EwEae0SVAoBrUMYQbkLGDm85taVWwuPc1a44LTzCQ==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.3.3" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.4.tgz", + "integrity": "sha512-2oYZJeIl4kCcMGk4ouZVjnkCtFrpQFlNEtJ6GbxzhHQchwH0NH/qEb9ykmOl29dqwMq+JhFdZn+1ak2FKhI9fQ==", + "cpu": [ + "ppc64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.3.3" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.4.tgz", + "integrity": "sha512-cPbNChoRURAWdebDIHSenxRpgEdy7JkPydSnUxRm9VvKD7m0/xVaR/8Fzlu81pk5nHEvHH87UZUA7cTtwnbJSA==", + "cpu": [ + "riscv64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.3.3" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.4.tgz", + "integrity": "sha512-RY0JFY8Fd6RonCBtHz+DvadaPkXDSI1AUn6yWL9TipqkZ1vY8w8evqdgyDFnkm4/K1ve1TvZiaePP5oSd4+WVQ==", + "cpu": [ + "s390x" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.3.3" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.4.tgz", + "integrity": "sha512-9qvvEAuk8k89TfWUoX2htWjbAMX8p+NxCppjpcg5k6xMsjhBQPTsoIh36h9Qde4WRuGpJeYnOjdosDn/cnv+OA==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.3.3" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.4.tgz", + "integrity": "sha512-KB5jxpfWQTr0nc3xdHtWChdbifHrBGsd2SM62Eyxrl8afikm+f5qGBU75SJIZBT/S1MC8XyacdlXBMSWq6OURA==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.3.3" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.4.tgz", + "integrity": "sha512-f+eZJZIQNEEd26RPSW+76chwOf1XtA2Y/O+5ocVyLliHkeih3e+jhLVBdNTd2rS3IbNXK8+ug93Vf5ZXtF5Lxg==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.3.3" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.4.tgz", + "integrity": "sha512-zQnl4Kwp7Q6NHsENtU2T/00Zi+w3AQNwz3+UaTyVBy2FpXrzXzGjndpK61onhZjRtRpQXxCTeqw19bVyXOh7jA==", + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.11.3" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-webcontainers-wasm32": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.4.tgz", + "integrity": "sha512-ESfNkywmCfPNyaZjxooddJQiQ+l/nTpGEOGthxiLnIHXC/CmcBixnfwUleX9mCz9ovrUUvKMap/pm8RYbzfwaA==", + "cpu": [ + "wasm32" + ], + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@img/sharp-wasm32": "0.35.4" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.4.tgz", + "integrity": "sha512-iNdlBX9gLVvqe2I3uIJSIKTq6wckP/DYxZtcqxm09x5Gi24DnFBmPAWZmr60ZyYMG0xlzo6goG3670ar+RXvRw==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.4.tgz", + "integrity": "sha512-kqRsbaa5CS6KHlpxnN7WhE6vAAugXyZButpRdvDWetlv6Qv4N9WTcrWzF7tXfB9T7MsoadqdI8hmwLq6UlLvtw==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.4.tgz", + "integrity": "sha512-XtmnYhBcrORsJ4XJngyzr/EWP0hRZLAZRFaApdKuviyqF78+ylxh2y06ZmtULAMOnObJ3ucpN0AcwSWnMowTRg==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@ioredis/commands": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.10.0.tgz", + "integrity": "sha512-UmeW7z4LfctwoQ5wkhVzgq8tXkreED2xZGpX+Bg+zA+WJFZCT6c062AfCK/Dfk81xZnnwdhJCUMkitihRaoC2Q==", + "license": "MIT" + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" }, "funding": { "url": "https://github.com/chalk/wrap-ansi?sponsor=1" @@ -2683,9 +3252,9 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz", + "integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==", "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { @@ -2699,11 +3268,12 @@ } }, "node_modules/@lobehub/icons": { - "version": "5.14.0", - "resolved": "https://registry.npmjs.org/@lobehub/icons/-/icons-5.14.0.tgz", - "integrity": "sha512-ZQADILVrprfGOGw6YfFl2IDbb8C+DLIHtkkdEjI0J2lP3jPS+s3qQ2t4DPjoNqhGF/fdpU7a2dEFusSe/G1d0w==", + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/@lobehub/icons/-/icons-5.18.0.tgz", + "integrity": "sha512-DIIdEYJfyJ93v1/OrsR7NVU0LGcoHh07I5tHx/HTFuBcYEiOJ/aUQwbnNXwVAhoXBWSSOwmmuFrF4UoNcQ0qnw==", "license": "MIT", "workspaces": [ + "*", "packages/*" ], "dependencies": { @@ -2795,52 +3365,15 @@ "optionalDependencies": { "graceful-fs": "^4.1.6" } - }, - "node_modules/@malept/flatpak-bundler/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/@mdx-js/mdx": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.1.1.tgz", - "integrity": "sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdx": "^2.0.0", - "acorn": "^8.0.0", - "collapse-white-space": "^2.0.0", - "devlop": "^1.0.0", - "estree-util-is-identifier-name": "^3.0.0", - "estree-util-scope": "^1.0.0", - "estree-walker": "^3.0.0", - "hast-util-to-jsx-runtime": "^2.0.0", - "markdown-extensions": "^2.0.0", - "recma-build-jsx": "^1.0.0", - "recma-jsx": "^1.0.0", - "recma-stringify": "^1.0.0", - "rehype-recma": "^1.0.0", - "remark-mdx": "^3.0.0", - "remark-parse": "^11.0.0", - "remark-rehype": "^11.0.0", - "source-map": "^0.7.0", - "unified": "^11.0.0", - "unist-util-position-from-estree": "^2.0.0", - "unist-util-stringify-position": "^4.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" + }, + "node_modules/@malept/flatpak-bundler/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" } }, "node_modules/@mermaid-js/parser": { @@ -2852,6 +3385,12 @@ "@chevrotain/types": "~11.1.2" } }, + "node_modules/@mixmark-io/domino": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@mixmark-io/domino/-/domino-2.2.0.tgz", + "integrity": "sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw==", + "license": "BSD-2-Clause" + }, "node_modules/@modelcontextprotocol/sdk": { "version": "1.29.0", "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.29.0.tgz", @@ -2916,15 +3455,15 @@ } }, "node_modules/@next/env": { - "version": "16.2.11", - "resolved": "https://registry.npmjs.org/@next/env/-/env-16.2.11.tgz", - "integrity": "sha512-0do5A3BJ2gxWr0ZCMcD6BhW+e595jyxdTl3rXTS6lOtD8ektMiW6CO+EPwt1Eca1DBnm90r/7GdiKWBKxH++DA==", + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/@next/env/-/env-16.3.1.tgz", + "integrity": "sha512-35G3xwkQUb2oETSDjFXGrVugknoayLFBh7vSE+yAcl9IP2zT9wyGwq7297AYHR11kJld807t5f8AJBs6WBzXsQ==", "license": "MIT" }, "node_modules/@next/swc-darwin-arm64": { - "version": "16.2.11", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.2.11.tgz", - "integrity": "sha512-wryL4pjKmDwGv2ox6+GZDFxvmtSRLqApBR8kL1j4+vhB7Z5vJC/zAnXpiR9Xkfzl0AS8WLMnsuGV/UKI67/rrw==", + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.3.1.tgz", + "integrity": "sha512-ABMIu2zQ7cnNIHm5ivKGwZwUrm0pAai3yiJ/gK/rF1c1VP9UOnj7XECbMKFdVKp9I9eMYq9NoDs1WXOoowxzJw==", "cpu": [ "arm64" ], @@ -2938,9 +3477,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "16.2.11", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.2.11.tgz", - "integrity": "sha512-aZl2j4f/fLyjQvOhv0Oe9UaMAQHolYpKhctsoYzplSumKJKPUmgjcf6545aBtysLTcu994TREd0+pSgNE4ohmg==", + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.3.1.tgz", + "integrity": "sha512-gNG21e/UnrroeScbY/QndUEdl0mF1FRibW7BBeYUz/5ABCepjqDdEdgr592vpzMtCn/m7FTjYq3TN4TpyDnutw==", "cpu": [ "x64" ], @@ -2954,9 +3493,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "16.2.11", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.2.11.tgz", - "integrity": "sha512-5jEriyEnH/LWFy27L2ZG0XaLlyEJIjhsImEsiS9P563PKEVp2BVups/xfOucIrsvVntp11oNcZwjHvaDPYVB5g==", + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.3.1.tgz", + "integrity": "sha512-6B6Lw016iwNUQuaJoraMMTLh6TwHzFUtxipSScD1F3YyymcrRWkobodRS2ftIOkF5vrs4zNlyUrTC5YZQ9Lz5w==", "cpu": [ "arm64" ], @@ -2970,9 +3509,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "16.2.11", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.2.11.tgz", - "integrity": "sha512-eIjcpx2fnnFSSkZDbTxy74KnokUXDjfoLClpWelfgHLf621aTqswhwXQ7GkD5K5rplrS6LZ/Bj+mVuvzluBOEg==", + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.3.1.tgz", + "integrity": "sha512-JUiPXZKK9wOhjf4MgDiH29GZLxfqOesbLtHq2pDxwH/WwscTRV2ToymnOTh1egzaZf0ueUf8T2+CeYTGHjW0Iw==", "cpu": [ "arm64" ], @@ -2986,9 +3525,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "16.2.11", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.2.11.tgz", - "integrity": "sha512-8WgzpaWMs46qJT9kiV47cje86L0x/Mu9t8/Gwj+pnbgW3rETVfCnaScPjlYUwNScpOozdcIMHWmAvuZJUonR2w==", + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.3.1.tgz", + "integrity": "sha512-Uog9jsrmIRIL/lfvIp9htmskSNC7JcQsMVucXL2V2YY1y/D9IUN3LPEafqy0zRJ2cIU1SQ0V6F6TlffQ+pLAGg==", "cpu": [ "x64" ], @@ -3002,9 +3541,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "16.2.11", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.2.11.tgz", - "integrity": "sha512-I3UgPds7G4ZYnTb/H+5GBGuUT2DhAk6j0mL6A4s63RjFs74wB2hOWP0vaxsK+3NJraExt3eYEPQ/UtT0x/64Nw==", + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.3.1.tgz", + "integrity": "sha512-6yy3FT13KgUFOj5H8bl8w/6nKiJwHIvbtwh1V+1acsu+7y4tJjnemSa6mhsh53BeoVrlozE+fMgZhXH46WmjMA==", "cpu": [ "x64" ], @@ -3018,9 +3557,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "16.2.11", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.2.11.tgz", - "integrity": "sha512-n89CjtcThnjrwgJMAiI5xbqwLY51zvwC9tSlArmVndAJLYVl9T9UAdlkXTmZvE++idoXe8KdglQlhNRdUp1c6g==", + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.3.1.tgz", + "integrity": "sha512-iOoN1QecUoGNZik536U/vtK43YwgyrCsGIkth52yIkl612n+0C9MjSnJbQAikISpb+WYRooBVhaDlUW7iZoKog==", "cpu": [ "arm64" ], @@ -3034,9 +3573,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "16.2.11", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.2.11.tgz", - "integrity": "sha512-md8CLNggS1Dx9pUgApzps5uAf+N8GN9xywzmNx9vHAWo94HtBwCCqkSnhIrdfQe83Dhz8Lfo/20Nb1Zxal092w==", + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.3.1.tgz", + "integrity": "sha512-d/k+PpAriUPaeMJJOG7HUSdqfEX46FEPWU1p3/nm2ACmXhj9hFEWdFODUBIpkuijXYkfL90qZzTqVPRp4BW/hw==", "cpu": [ "x64" ], @@ -3319,15 +3858,6 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/@orama/orama": { - "version": "3.1.18", - "resolved": "https://registry.npmjs.org/@orama/orama/-/orama-3.1.18.tgz", - "integrity": "sha512-a61ljmRVVyG5MC/698C8/FfFDw5a8LOIvyOLW5fztgUXqUpc1jOfQzOitSCbge657OgXXThmY3Tk8fpiDb4UcA==", - "license": "Apache-2.0", - "engines": { - "node": ">= 20.0.0" - } - }, "node_modules/@parcel/watcher": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.6.0.tgz", @@ -3902,20 +4432,20 @@ "license": "MIT" }, "node_modules/@radix-ui/react-accordion": { - "version": "1.2.18", - "resolved": "https://registry.npmjs.org/@radix-ui/react-accordion/-/react-accordion-1.2.18.tgz", - "integrity": "sha512-CGuUFvhjScXBF/bhjaU9xlgai2ikYqJRazXhMzngoUaZI7QaxAw24Ae3S/pR0b69p8GqW6i+CKJmx9JPNnZ4QQ==", + "version": "1.2.20", + "resolved": "https://registry.npmjs.org/@radix-ui/react-accordion/-/react-accordion-1.2.20.tgz", + "integrity": "sha512-jDhG9FvAEnlhnjrsINbNXcUa4G+L1KqSkJSunkbKEzFRcAb52jvM0PjPxPRvhe1HNc5F5yc0yzzWeeqlH4yBIg==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.7", - "@radix-ui/react-collapsible": "1.1.18", - "@radix-ui/react-collection": "1.1.13", - "@radix-ui/react-compose-refs": "1.1.4", - "@radix-ui/react-context": "1.2.1", - "@radix-ui/react-direction": "1.1.3", - "@radix-ui/react-id": "1.1.3", - "@radix-ui/react-primitive": "2.1.8", - "@radix-ui/react-use-controllable-state": "1.2.5" + "@radix-ui/react-collapsible": "1.1.20", + "@radix-ui/react-collection": "1.1.15", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.2.2", + "@radix-ui/react-direction": "1.1.4", + "@radix-ui/react-id": "1.1.4", + "@radix-ui/react-primitive": "2.1.10", + "@radix-ui/react-use-controllable-state": "1.2.6" }, "peerDependencies": { "@types/react": "*", @@ -3933,12 +4463,12 @@ } }, "node_modules/@radix-ui/react-arrow": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.13.tgz", - "integrity": "sha512-0Q310knIY0K+mkmncU9FxLggfW7V49Ok2oY+iu27KkERTsQXxYCIC8XW5QoK4w7Jp1z00vT5xj3oxTcn7QlcTg==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.15.tgz", + "integrity": "sha512-v4zggRcjadnI+ClKDuijlQEW4tw3NoaeHc/PwpKnLoLLKNUG4InLegkstooLcRIUWCs+8L22dGURCVuFfOKfnA==", "license": "MIT", "dependencies": { - "@radix-ui/react-primitive": "2.1.8" + "@radix-ui/react-primitive": "2.1.10" }, "peerDependencies": { "@types/react": "*", @@ -3956,19 +4486,19 @@ } }, "node_modules/@radix-ui/react-collapsible": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.18.tgz", - "integrity": "sha512-aNMp8humfYzWERz5gxGb/eLNkB0ZthypLbNlNolzdgzFTeN78e/rnn9rxCdOaSsg/zClTOJ/OkjXYx9PUEPATw==", + "version": "1.1.20", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.20.tgz", + "integrity": "sha512-mcGesGplBnzN2sbvJETzpCNfSMyPnb29q1GRLU+Ib7bJrpIG2ywmRoh2V5VbA2uNvKikKUlVbAPks7JDjz4A8Q==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.7", - "@radix-ui/react-compose-refs": "1.1.4", - "@radix-ui/react-context": "1.2.1", - "@radix-ui/react-id": "1.1.3", - "@radix-ui/react-presence": "1.1.9", - "@radix-ui/react-primitive": "2.1.8", - "@radix-ui/react-use-controllable-state": "1.2.5", - "@radix-ui/react-use-layout-effect": "1.1.3" + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.2.2", + "@radix-ui/react-id": "1.1.4", + "@radix-ui/react-presence": "1.1.10", + "@radix-ui/react-primitive": "2.1.10", + "@radix-ui/react-use-controllable-state": "1.2.6", + "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", @@ -3986,15 +4516,15 @@ } }, "node_modules/@radix-ui/react-collection": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.13.tgz", - "integrity": "sha512-Q8xYqNRFObXPmi45bFSkGdM2JA5hjBeYGFqzg6lZR3wp6b+cciraVq8DdneTabtws+uOYqjmsvmKOufk/M9Cyg==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.15.tgz", + "integrity": "sha512-9W+B9NPF0NaaPh/1NJd3+KqsnlLqU9H7T2rvww+fp+T/evVXdNAyYcnfRQZFOjkR1ajQp3yORlqnI8soawLvNA==", "license": "MIT", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.4", - "@radix-ui/react-context": "1.2.1", - "@radix-ui/react-primitive": "2.1.8", - "@radix-ui/react-slot": "1.3.1" + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.2.2", + "@radix-ui/react-primitive": "2.1.10", + "@radix-ui/react-slot": "1.3.3" }, "peerDependencies": { "@types/react": "*", @@ -4012,9 +4542,9 @@ } }, "node_modules/@radix-ui/react-compose-refs": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.4.tgz", - "integrity": "sha512-pWJo6lQAfR6uy1n7ii7PaCc9dLPwTXDYbQpORZU5B548Aqvl2pP1SM1vJGKyxIFqZMHRopRO4CQYX2iXAIB5jA==", + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.5.tgz", + "integrity": "sha512-+48PbAAbq3didjJxa+OaWY2ZwgAKsNiRGyeHKszblZMQ+kcpd9pAaT11cMkGEie0vsOi3QdeTE6d5Fe3Gn61kA==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -4027,9 +4557,9 @@ } }, "node_modules/@radix-ui/react-context": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.2.1.tgz", - "integrity": "sha512-EraVbFjiIjibpLr6EjvEDmSCYJU2SlKDMiO+qEK/D9GOWnQoAQlpQo2occGYC1UM9MBeEx5Bek3UtW/Qi57vAg==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.2.2.tgz", + "integrity": "sha512-RHCUGwKHDr0hDGg4X7ma4JG4/+12qxw8rkh5QKdDldlCvtja6nUx1Ef/8HVrJze81lEsgLQlqjzjGNHantgnQA==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -4042,24 +4572,24 @@ } }, "node_modules/@radix-ui/react-dialog": { - "version": "1.1.21", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.21.tgz", - "integrity": "sha512-h+7qMDDmZJ8qTSPrwNyKb/PACY0ehtN8QOBlCz+C2C1jgehKekdhmHddG9YQk8BF/sHJqglPjte+jA1Jrp9HcA==", + "version": "1.1.23", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.23.tgz", + "integrity": "sha512-Ksw4WeROkO4rC9k/onilX/Ao2Cr1ku1unMNH+XSCcP4jSXYu7HDsg9n4ojMjVb22XpYjAQ9qfrFlVbru1vXDUA==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.7", - "@radix-ui/react-compose-refs": "1.1.4", - "@radix-ui/react-context": "1.2.1", - "@radix-ui/react-dismissable-layer": "1.1.17", - "@radix-ui/react-focus-guards": "1.1.5", - "@radix-ui/react-focus-scope": "1.1.14", - "@radix-ui/react-id": "1.1.3", - "@radix-ui/react-portal": "1.1.15", - "@radix-ui/react-presence": "1.1.9", - "@radix-ui/react-primitive": "2.1.8", - "@radix-ui/react-slot": "1.3.1", - "@radix-ui/react-use-controllable-state": "1.2.5", - "@radix-ui/react-use-layout-effect": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.2.2", + "@radix-ui/react-dismissable-layer": "1.1.19", + "@radix-ui/react-focus-guards": "1.1.6", + "@radix-ui/react-focus-scope": "1.1.16", + "@radix-ui/react-id": "1.1.4", + "@radix-ui/react-portal": "1.1.17", + "@radix-ui/react-presence": "1.1.10", + "@radix-ui/react-primitive": "2.1.10", + "@radix-ui/react-slot": "1.3.3", + "@radix-ui/react-use-controllable-state": "1.2.6", + "@radix-ui/react-use-layout-effect": "1.1.4", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.7.2" }, @@ -4079,9 +4609,9 @@ } }, "node_modules/@radix-ui/react-direction": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.3.tgz", - "integrity": "sha512-OdgAA/xb6WOQMKNn0mtbYoruMG6YMaBOnq+evWxSpMmiEMBdeFZawnIWRfPPeVXCRm+0lnN8jpJLjhD7/UIxWw==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.4.tgz", + "integrity": "sha512-5pzg4FGQNpExhnhT2zlrP1wZFaYCd1K0nYWoFAdcYoYK868IEigqMX3B3f8yIoRlAhAeDWciLI6ZdCKHF9P4Vg==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -4094,16 +4624,16 @@ } }, "node_modules/@radix-ui/react-dismissable-layer": { - "version": "1.1.17", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.17.tgz", - "integrity": "sha512-QAXwa38pG0xNAYh1pjdSaf86NrkqsMoDNmget/Y7X8O8E/C3Iqlj9GAPE4DfX9BPLXc7WH2TWSzMRnIoCdcjzQ==", + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.19.tgz", + "integrity": "sha512-8g4pfOL9HoKKLWGiypT+dphVqjFfmcXO5GBnhsG6zI+lxAx/8feQpr+1LSN8Re3hiZ+XkLNS4O9ztK11/LzQ6w==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.7", - "@radix-ui/react-compose-refs": "1.1.4", - "@radix-ui/react-primitive": "2.1.8", - "@radix-ui/react-use-callback-ref": "1.1.3", - "@radix-ui/react-use-effect-event": "0.0.4" + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-primitive": "2.1.10", + "@radix-ui/react-use-callback-ref": "1.1.4", + "@radix-ui/react-use-effect-event": "0.0.5" }, "peerDependencies": { "@types/react": "*", @@ -4121,9 +4651,9 @@ } }, "node_modules/@radix-ui/react-focus-guards": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.5.tgz", - "integrity": "sha512-UQvlB7L/BYh3P8MLvwZnQkH521EDos40Rwnbt5+Qpg4Vbk0z3xJjRUmR6+aka4aT1IQQXFdO5bNPoE7cvFl5xQ==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.6.tgz", + "integrity": "sha512-RNOJjfZMTyBM6xYmV3IVGXkPjIhcBAuv48POevAXwrGJhkWZ9p1rFoIS1JFooPuT193AZmRsCPhpoVJxx6OPoQ==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -4136,14 +4666,14 @@ } }, "node_modules/@radix-ui/react-focus-scope": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.14.tgz", - "integrity": "sha512-/x4htnJfmW53MplkrePaDpf1o/rN1C++g88WpVobULXbSyC19NtLkXmewuJ/HCaceSmfKDNL5gOXcBGnuAvnvQ==", + "version": "1.1.16", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.16.tgz", + "integrity": "sha512-wmRZ2WWLvmt6KHy2rNPOdPUjwq5xOHY02+m+udwJTn0aNIox/rkskAvJTyTLGhPK6KgrUjlJUJpgmx/+wFiFIQ==", "license": "MIT", "dependencies": { - "@radix-ui/react-compose-refs": "1.1.4", - "@radix-ui/react-primitive": "2.1.8", - "@radix-ui/react-use-callback-ref": "1.1.3" + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-primitive": "2.1.10", + "@radix-ui/react-use-callback-ref": "1.1.4" }, "peerDependencies": { "@types/react": "*", @@ -4161,12 +4691,12 @@ } }, "node_modules/@radix-ui/react-id": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.3.tgz", - "integrity": "sha512-f/Wxm0ctyMymUJK0fqTSQlm85rbzdAkoNbPXJQ5+6caowVO8Yx+NWGjGz/oGhs/D+WIbbQpOrU0hU2Li2/42xQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.4.tgz", + "integrity": "sha512-TMQp2llA+RYn7JcjnrMnz7wN4pcVttPZnRZo52PLQsoLVKzNlVwUeHmfePgTgRluXFvlD3GD5g5MOVVTJCO0qA==", "license": "MIT", "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.3" + "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", @@ -4179,25 +4709,25 @@ } }, "node_modules/@radix-ui/react-navigation-menu": { - "version": "1.2.20", - "resolved": "https://registry.npmjs.org/@radix-ui/react-navigation-menu/-/react-navigation-menu-1.2.20.tgz", - "integrity": "sha512-in/exCQPatmmBmQZrtQkK4UrysEp8VGEuw5o8Bx3ozxbfg7DBb4H5j3DgxGz4N59J02NRVzhsWFtujZgy5ue3w==", + "version": "1.2.22", + "resolved": "https://registry.npmjs.org/@radix-ui/react-navigation-menu/-/react-navigation-menu-1.2.22.tgz", + "integrity": "sha512-ou7iLEJ+yrhQndkkA4U21XIdS/CS45F4iXIkTZcb6/Ne9EMsOuDudVmCwmDnfFZZ+y1FZqXRNSIgBy+YMvZVZg==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.7", - "@radix-ui/react-collection": "1.1.13", - "@radix-ui/react-compose-refs": "1.1.4", - "@radix-ui/react-context": "1.2.1", - "@radix-ui/react-direction": "1.1.3", - "@radix-ui/react-dismissable-layer": "1.1.17", - "@radix-ui/react-id": "1.1.3", - "@radix-ui/react-presence": "1.1.9", - "@radix-ui/react-primitive": "2.1.8", - "@radix-ui/react-use-callback-ref": "1.1.3", - "@radix-ui/react-use-controllable-state": "1.2.5", - "@radix-ui/react-use-layout-effect": "1.1.3", - "@radix-ui/react-use-previous": "1.1.3", - "@radix-ui/react-visually-hidden": "1.2.9" + "@radix-ui/react-collection": "1.1.15", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.2.2", + "@radix-ui/react-direction": "1.1.4", + "@radix-ui/react-dismissable-layer": "1.1.19", + "@radix-ui/react-id": "1.1.4", + "@radix-ui/react-presence": "1.1.10", + "@radix-ui/react-primitive": "2.1.10", + "@radix-ui/react-use-callback-ref": "1.1.4", + "@radix-ui/react-use-controllable-state": "1.2.6", + "@radix-ui/react-use-layout-effect": "1.1.4", + "@radix-ui/react-use-previous": "1.1.4", + "@radix-ui/react-visually-hidden": "1.2.11" }, "peerDependencies": { "@types/react": "*", @@ -4215,25 +4745,24 @@ } }, "node_modules/@radix-ui/react-popover": { - "version": "1.1.21", - "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.21.tgz", - "integrity": "sha512-+AJ7P5oRcFqFtv7MaCD8fOuK3l5qQBAMdWEOnUOYd3JfHOeIUe7TnHHSSP15CtWwH4KrotyDCTzodOIoONh8vw==", + "version": "1.1.23", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.23.tgz", + "integrity": "sha512-mw58MrBlyHWFisTOYignD0vf/3gdcgAR+9of1s9G/38CbFiUwH1nCDkc0AUM9IrXFgN5Ue8n45j9WCgyM1sbiQ==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.7", - "@radix-ui/react-compose-refs": "1.1.4", - "@radix-ui/react-context": "1.2.1", - "@radix-ui/react-dismissable-layer": "1.1.17", - "@radix-ui/react-focus-guards": "1.1.5", - "@radix-ui/react-focus-scope": "1.1.14", - "@radix-ui/react-id": "1.1.3", - "@radix-ui/react-popper": "1.3.5", - "@radix-ui/react-portal": "1.1.15", - "@radix-ui/react-presence": "1.1.9", - "@radix-ui/react-primitive": "2.1.8", - "@radix-ui/react-slot": "1.3.1", - "@radix-ui/react-use-controllable-state": "1.2.5", - "@radix-ui/react-use-layout-effect": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.2.2", + "@radix-ui/react-dismissable-layer": "1.1.19", + "@radix-ui/react-focus-guards": "1.1.6", + "@radix-ui/react-focus-scope": "1.1.16", + "@radix-ui/react-id": "1.1.4", + "@radix-ui/react-popper": "1.3.7", + "@radix-ui/react-portal": "1.1.17", + "@radix-ui/react-presence": "1.1.10", + "@radix-ui/react-primitive": "2.1.10", + "@radix-ui/react-slot": "1.3.3", + "@radix-ui/react-use-controllable-state": "1.2.6", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.7.2" }, @@ -4253,20 +4782,20 @@ } }, "node_modules/@radix-ui/react-popper": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.3.5.tgz", - "integrity": "sha512-6hLng2Rs45IZcvZ31BNvMeaFEMMEbtsog4xPcb8LZrGfyoV9fdAXqB9UKhLpTHtL0+E2DhSr6VW54Tehd6ksAQ==", + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.3.7.tgz", + "integrity": "sha512-UsJrrd7w4wuKKTdvd/DNERVlwSlUcyXzjhyDwBk+3aPOsCjOY6ZSbxuw8E6lZTjjfP8Cpd0J8VVkrYUWyGYXyg==", "license": "MIT", "dependencies": { "@floating-ui/react-dom": "^2.0.0", - "@radix-ui/react-arrow": "1.1.13", - "@radix-ui/react-compose-refs": "1.1.4", - "@radix-ui/react-context": "1.2.1", - "@radix-ui/react-primitive": "2.1.8", - "@radix-ui/react-use-callback-ref": "1.1.3", - "@radix-ui/react-use-layout-effect": "1.1.3", - "@radix-ui/react-use-rect": "1.1.3", - "@radix-ui/react-use-size": "1.1.3", + "@radix-ui/react-arrow": "1.1.15", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.2.2", + "@radix-ui/react-primitive": "2.1.10", + "@radix-ui/react-use-callback-ref": "1.1.4", + "@radix-ui/react-use-layout-effect": "1.1.4", + "@radix-ui/react-use-rect": "1.1.4", + "@radix-ui/react-use-size": "1.1.4", "@radix-ui/rect": "1.1.3" }, "peerDependencies": { @@ -4285,13 +4814,13 @@ } }, "node_modules/@radix-ui/react-portal": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.15.tgz", - "integrity": "sha512-kAfBVJUKNNKZuyGQXXG6rKolAV2KAmxxVkPXJgoq9dEFTl39286RufHQFNTL8rzha4vP8159BJ6hMGpB+bqv7A==", + "version": "1.1.17", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.17.tgz", + "integrity": "sha512-vKQLcWypUnwZVvfV7UkGahH2g6ySe8M8R+zYBwPrv5byZ9QAW6cQVvNKo7GgmD+p8aYb6D9JBuvy8/WhOno2wQ==", "license": "MIT", "dependencies": { - "@radix-ui/react-primitive": "2.1.8", - "@radix-ui/react-use-layout-effect": "1.1.3" + "@radix-ui/react-primitive": "2.1.10", + "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", @@ -4309,12 +4838,12 @@ } }, "node_modules/@radix-ui/react-presence": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.9.tgz", - "integrity": "sha512-LTi1v05bprIb8/GSY/GWusI0jfsYjQ3CD3Nin8o7jVxnpHzVQfzjOQJoJTQkE9bdmOnsS7SFdhkXiBv8PrYnxw==", + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.10.tgz", + "integrity": "sha512-3wyzCQ6+ubRA+D4uv9m95JYLXxmOHp05qjrkjeA7uKHHtjpPggQzc6DAb0URl7j67oR0K2foO4ip27TiX037Bw==", "license": "MIT", "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.3" + "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", @@ -4332,12 +4861,12 @@ } }, "node_modules/@radix-ui/react-primitive": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.8.tgz", - "integrity": "sha512-DOlK1BdcIeYYUcFkSYFka4v1h95XTov93b0jCgW1EEiZuIhdwHY2NlE1teLIh+p0uBsuZI5A+voay+iVWpprfA==", + "version": "2.1.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.10.tgz", + "integrity": "sha512-MucOnzh6hR5mid6VpkbglRAMYMjKLqRnGBbjXkzjK52fuQDd1qbkx78a5P40mkcnVXJdEVxm26E9OPAiUq7nBg==", "license": "MIT", "dependencies": { - "@radix-ui/react-slot": "1.3.1" + "@radix-ui/react-slot": "1.3.3" }, "peerDependencies": { "@types/react": "*", @@ -4355,22 +4884,22 @@ } }, "node_modules/@radix-ui/react-roving-focus": { - "version": "1.1.17", - "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.17.tgz", - "integrity": "sha512-YdJmjETw7Py+4Nziv71jgZ6fH7xQgB5p+pQ5rV8Iufyrm0RHSijec/UV1zPfQoK/YcfzB9nOl/2bi1zf1SjRMQ==", + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.19.tgz", + "integrity": "sha512-V9jI6hDjT7l3jsCQD9bLNvDLM3tH/gdbOTp7Tefp3hbbgCGQoK7tUvrWiRlcoBHIZ809ElXwNQwVo0B98LuTXQ==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.7", - "@radix-ui/react-collection": "1.1.13", - "@radix-ui/react-compose-refs": "1.1.4", - "@radix-ui/react-context": "1.2.1", - "@radix-ui/react-direction": "1.1.3", - "@radix-ui/react-id": "1.1.3", - "@radix-ui/react-primitive": "2.1.8", - "@radix-ui/react-use-callback-ref": "1.1.3", - "@radix-ui/react-use-controllable-state": "1.2.5", - "@radix-ui/react-use-is-hydrated": "0.1.2", - "@radix-ui/react-use-layout-effect": "1.1.3" + "@radix-ui/react-collection": "1.1.15", + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.2.2", + "@radix-ui/react-direction": "1.1.4", + "@radix-ui/react-id": "1.1.4", + "@radix-ui/react-primitive": "2.1.10", + "@radix-ui/react-use-callback-ref": "1.1.4", + "@radix-ui/react-use-controllable-state": "1.2.6", + "@radix-ui/react-use-is-hydrated": "0.1.3", + "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", @@ -4388,20 +4917,20 @@ } }, "node_modules/@radix-ui/react-scroll-area": { - "version": "1.2.16", - "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.16.tgz", - "integrity": "sha512-kEcmCenIJ+W5xlCv1u9VKDdPmzzGyfrJwEneY+02GH+lJRXrGpkiTkyjrfkspuRw6DXt4uduwT5c4xD8HTv27Q==", + "version": "1.2.18", + "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.18.tgz", + "integrity": "sha512-Zn5Cd171wxsO3Dfg8HaW6RifTb9CYTKQJHs/G4+LN1GfmJpaQMZQyQxMprVPHpaz7QY4l9BxK2JwQuzHsXC8nA==", "license": "MIT", "dependencies": { "@radix-ui/number": "1.1.3", "@radix-ui/primitive": "1.1.7", - "@radix-ui/react-compose-refs": "1.1.4", - "@radix-ui/react-context": "1.2.1", - "@radix-ui/react-direction": "1.1.3", - "@radix-ui/react-presence": "1.1.9", - "@radix-ui/react-primitive": "2.1.8", - "@radix-ui/react-use-callback-ref": "1.1.3", - "@radix-ui/react-use-layout-effect": "1.1.3" + "@radix-ui/react-compose-refs": "1.1.5", + "@radix-ui/react-context": "1.2.2", + "@radix-ui/react-direction": "1.1.4", + "@radix-ui/react-presence": "1.1.10", + "@radix-ui/react-primitive": "2.1.10", + "@radix-ui/react-use-callback-ref": "1.1.4", + "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", @@ -4419,13 +4948,12 @@ } }, "node_modules/@radix-ui/react-slot": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.3.1.tgz", - "integrity": "sha512-Bu/aAQHFFh6/QAvXAeUMurJ9fbW0JUIqlojU/yBXZ7cAVqy75Y7JYYyuCr9zLNF0p4WWoJYV54CTUIf4l7FzTw==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.3.3.tgz", + "integrity": "sha512-qx7oqnYbxnK9kYI9m317qmFmEgo6ywqWvbTogdj7cL9p3/yx4M48p7Rnw5z3H890cL/ow/EeWJsuTykeZVXP5Q==", "license": "MIT", "dependencies": { - "@radix-ui/primitive": "1.1.7", - "@radix-ui/react-compose-refs": "1.1.4" + "@radix-ui/react-compose-refs": "1.1.5" }, "peerDependencies": { "@types/react": "*", @@ -4438,19 +4966,19 @@ } }, "node_modules/@radix-ui/react-tabs": { - "version": "1.1.19", - "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.19.tgz", - "integrity": "sha512-4wbGf98pX2ZwYqHMVB/dakeMPyH4xSJ9MSDaCCWXlIpYt0VYY6mtZxKSTiGS/F3tk0yrEYmXE1V8uwG7TxDCcQ==", + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.21.tgz", + "integrity": "sha512-UKxJlZid7FVtsk/WTxj4i4uSEgj2Au+KBbS7SQyTlzMhhn+86Cz3tISZdTa87bfEfcuvZezf2ZsxD4xuEKtkog==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.7", - "@radix-ui/react-context": "1.2.1", - "@radix-ui/react-direction": "1.1.3", - "@radix-ui/react-id": "1.1.3", - "@radix-ui/react-presence": "1.1.9", - "@radix-ui/react-primitive": "2.1.8", - "@radix-ui/react-roving-focus": "1.1.17", - "@radix-ui/react-use-controllable-state": "1.2.5" + "@radix-ui/react-context": "1.2.2", + "@radix-ui/react-direction": "1.1.4", + "@radix-ui/react-id": "1.1.4", + "@radix-ui/react-presence": "1.1.10", + "@radix-ui/react-primitive": "2.1.10", + "@radix-ui/react-roving-focus": "1.1.19", + "@radix-ui/react-use-controllable-state": "1.2.6" }, "peerDependencies": { "@types/react": "*", @@ -4468,9 +4996,9 @@ } }, "node_modules/@radix-ui/react-use-callback-ref": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.3.tgz", - "integrity": "sha512-AUS7HoBBAncIsGMLNG+CcpLuJ+JIBbZzmyM8Qdb1eIThX0AlhSSC6wn40xfBlPE+ypx/vSSiRWnklUAjy3U3UA==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.4.tgz", + "integrity": "sha512-R6OUY2e2fA6Yn6s+VSx5KBV6Nx8LQEhu+cz7LCej18rQ1HLyg9PSC9jP/ZNx0o6FAIK9c0F1kHylzSxKsdlkrQ==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -4483,14 +5011,14 @@ } }, "node_modules/@radix-ui/react-use-controllable-state": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.5.tgz", - "integrity": "sha512-UB1dXpxvHjR48poyKdKdTm7jT0kp3elkUKdKQiOkirlbYumqXinSJtrjDsr9maXNPvL12bKI4CDSmydms/9Aeg==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.6.tgz", + "integrity": "sha512-uEQJGT97ZA/TgP/Hydw47lHu+/vQj6z/0jA+WeTbK1o9Rx45GImjpD0tc3W5ad3D6XTSR6e1yEO0FvGq6WQfVQ==", "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.7", - "@radix-ui/react-use-effect-event": "0.0.4", - "@radix-ui/react-use-layout-effect": "1.1.3" + "@radix-ui/react-use-effect-event": "0.0.5", + "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", @@ -4503,12 +5031,12 @@ } }, "node_modules/@radix-ui/react-use-effect-event": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.4.tgz", - "integrity": "sha512-XYcfa6wlXDCwQtePuEiPmXLSAhGL4DWtedSyRgGbG3y10mw+OnrLp6SyeY1gJFMiYF0Dx0nMAX9InylKbLEFQQ==", + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.5.tgz", + "integrity": "sha512-7cshFL8HGS/7HEiHH+9kL9HBwp2sa9yX18Knwek6KYWmXwM7pegMgta2AXMQKI+rq3JnfSj9x8wYqFMTdG1Jgg==", "license": "MIT", "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.3" + "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", @@ -4521,9 +5049,9 @@ } }, "node_modules/@radix-ui/react-use-is-hydrated": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-is-hydrated/-/react-use-is-hydrated-0.1.2.tgz", - "integrity": "sha512-2+gAVu9uaSLbopCTvvuWX9MIgEOlyqXC1Ok+KLCO7cZPSHLENs7dL0KbFQUGFIcFKmDW/bmaQRJtd8E3cnMRUw==", + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-is-hydrated/-/react-use-is-hydrated-0.1.3.tgz", + "integrity": "sha512-umO/aJ+82CpOnhDZUTbILCQf7kU/g0iv+oGs/Q8jw7IkhWBzaEP4sA268PhFAJTFetbwp3ICc6ktpI4TqtxcIw==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -4536,9 +5064,9 @@ } }, "node_modules/@radix-ui/react-use-layout-effect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.3.tgz", - "integrity": "sha512-rDiah9wvtqihWtWz02XreeRKIxt2EJF8y5D9rtY9l5A2zxePAtcPiOMpDugNRw5bFHz+1/8viVoc7ZVKiJknCw==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.4.tgz", + "integrity": "sha512-K20DkRkUwDnxEYMBPcg3Y6voLkEy5p5QQmszZgLngKKiC7dzBR/aEuK3w1qlx2JWDUNH6FluahYdgR3BP+QbYw==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -4551,9 +5079,9 @@ } }, "node_modules/@radix-ui/react-use-previous": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.3.tgz", - "integrity": "sha512-kbefNKla5AGhgvMqrg/qS7mYVLXTEHQLqoFIS03nKN2dAfQQ5PK5Tp+2LxS7BV6a6l4HHv4jTg6rtV2Uajwe2w==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.4.tgz", + "integrity": "sha512-XoSLhbRbqxFtgJoi2fNHA3C6pDlY34x508vUpUGoFZfvePfHXHbE1lC4FYFMnJWgiCRroSTw6fOsXQoVS9RwZg==", "license": "MIT", "peerDependencies": { "@types/react": "*", @@ -4566,9 +5094,9 @@ } }, "node_modules/@radix-ui/react-use-rect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.3.tgz", - "integrity": "sha512-W0GSYZFKEfi6raMiMEfJSngvVbFDIyxtW5JuVg5NoQBY59l0dVQVGLbhog/tOdwq0qtZ+TXuX1ikSNan4/IZXA==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.4.tgz", + "integrity": "sha512-cSOCh6JlkmfjLyNcLiu2nB4v+nm+dkZ+Q5KHWk/soo4U7ZLiEQFKHK9/YmtBHjfCEaU43IBKQOc4/uJmCaiCTQ==", "license": "MIT", "dependencies": { "@radix-ui/rect": "1.1.3" @@ -4584,12 +5112,12 @@ } }, "node_modules/@radix-ui/react-use-size": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.3.tgz", - "integrity": "sha512-jJq6tQQLvO/z4uWbztjwPV+1a/+H4rCaWypasLB/ac8DEdd6+p7dIm7o3F6P2KZPGkPMqD4s5424EdAdoU+GLA==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.4.tgz", + "integrity": "sha512-D3anSY15EJoxrihpsXI6SMrmmonnQtR2ni7arO+Lfdg3O95b9hNXxONk8jA5C8ANdF/h5HMAxejgs8PWJ6rlhw==", "license": "MIT", "dependencies": { - "@radix-ui/react-use-layout-effect": "1.1.3" + "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", @@ -4602,12 +5130,12 @@ } }, "node_modules/@radix-ui/react-visually-hidden": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.9.tgz", - "integrity": "sha512-seuZXNZVCz1kLSQMRO/TdNOSahBI3S5nXE4jzO7u7aFRWQlMAnwyrr8vKMkEU115fCLEyzR2YyjnP+aRMxK34w==", + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.11.tgz", + "integrity": "sha512-NFS86RYYZb4/exihaESBGOpMJFz8MGLAfu3mOBSGByVnVPC9JPASfYubxd/8KbkQK0sYAv8lVQDEQukDX/qXvQ==", "license": "MIT", "dependencies": { - "@radix-ui/react-primitive": "2.1.8" + "@radix-ui/react-primitive": "2.1.10" }, "peerDependencies": { "@types/react": "*", @@ -4631,9 +5159,9 @@ "license": "MIT" }, "node_modules/@rc-component/util": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/@rc-component/util/-/util-1.12.0.tgz", - "integrity": "sha512-AEjPL8JVdohIITaiXokyjL9WQ6tKWWjAYK9QU16tGNE9JaQABBQy+hA4H2Lup5MgXy9yY3iLrbZJheuU13hTdQ==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@rc-component/util/-/util-1.13.0.tgz", + "integrity": "sha512-IXf2zBfZrbQGT+G8LxnoICDBGnMHIPIiq5HCRn3EDfKUx28x1rnbZBj46ULJf4sM8ImTG1SepqfNBdxZziqQ4w==", "license": "MIT", "dependencies": { "is-mobile": "^5.0.0", @@ -4677,15 +5205,15 @@ "license": "MIT" }, "node_modules/@shikijs/core": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-4.3.1.tgz", - "integrity": "sha512-ANMDxuaPsNMdDC1m4vfvhlDmJweMwkE5XitTwrq2rWHx5jM+dlm4MmHt2PP6t0uejfR77SuhrhJ0zEijIF/uhA==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-4.4.3.tgz", + "integrity": "sha512-QCR4q2ZO/ILJEuwiBMel4wdcTDb1JGwfjKTxPDF6x8ixOaluPrVqIn06C99AcRPhmYlBR56d/Fb+GN58GzExpg==", "license": "MIT", "dependencies": { - "@shikijs/primitive": "4.3.1", - "@shikijs/types": "4.3.1", + "@shikijs/primitive": "4.4.3", + "@shikijs/types": "4.4.3", "@shikijs/vscode-textmate": "^10.0.2", - "@types/hast": "^3.0.4", + "@types/hast": "^3.0.5", "hast-util-to-html": "^9.0.5" }, "engines": { @@ -4693,12 +5221,12 @@ } }, "node_modules/@shikijs/engine-javascript": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-4.3.1.tgz", - "integrity": "sha512-JBItcnPuYq7jVJdZo/vMj94r+szT7XEjHFX+mvFDGSEIbVAXAGyHAHzhbWzpGOwYidCZrErJLLgn2PVeiokHnQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-4.4.3.tgz", + "integrity": "sha512-FbOjFJp9VLdo1Wevs10BBtVxiTWwNLqZh5Gkhjgda/ioL15YOgeSl9n+6XMa3qRlPQzfhFNe641SrynFHYG0nQ==", "license": "MIT", "dependencies": { - "@shikijs/types": "4.3.1", + "@shikijs/types": "4.4.3", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.6" }, @@ -4707,12 +5235,12 @@ } }, "node_modules/@shikijs/engine-oniguruma": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-4.3.1.tgz", - "integrity": "sha512-OXyNMzg0pews+msMj4cHeqT4xiYKKvbnn6VbdAXxfoFl3SSx4fJTc8FadECuc5/H9p3BzhNAoAUXKwAu9rWYhg==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-4.4.3.tgz", + "integrity": "sha512-EcOQkxdxGQrc1Row/cC2c96/v1dbZqGnEVu1qTuT/MJmp6+cXCvQussowVmCv5Tqr3KuY3c7IbM6HTW3LJ1k9w==", "license": "MIT", "dependencies": { - "@shikijs/types": "4.3.1", + "@shikijs/types": "4.4.3", "@shikijs/vscode-textmate": "^10.0.2" }, "engines": { @@ -4720,51 +5248,51 @@ } }, "node_modules/@shikijs/langs": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-4.3.1.tgz", - "integrity": "sha512-m0l9nsDqgBHvbZbk7A0/kXz/impK3uB/c6rAn6Gpg/uPtdZRQ+alsN/17MU5thb68XTj/4DxkZAotrM0GGSpDQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-4.4.3.tgz", + "integrity": "sha512-ePic0yfAJGOF83D5wBHK/00EjK65oahBYxFk5epgq33WRv7X9UuxLEV8PtR0szC0z8dl7INIpIodB99JRFlR+A==", "license": "MIT", "dependencies": { - "@shikijs/types": "4.3.1" + "@shikijs/types": "4.4.3" }, "engines": { "node": ">=20" } }, "node_modules/@shikijs/primitive": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@shikijs/primitive/-/primitive-4.3.1.tgz", - "integrity": "sha512-CXQRQOYy1leqQ8ceTeJdmXv/bsUY++6QyLpXJ94LZAAYj5X2SKRdc5ipguv4NPyGVKItB2PPwUpRNe0Sjh5S1A==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/primitive/-/primitive-4.4.3.tgz", + "integrity": "sha512-m0wBeLDQDeIxRdUmrCPdQqfuUamDwRL5isCfYbguKD6NiaKpVbsv+3J81DyIKgNW5h4WAIIr8T4EkgQrBBxvaQ==", "license": "MIT", "dependencies": { - "@shikijs/types": "4.3.1", + "@shikijs/types": "4.4.3", "@shikijs/vscode-textmate": "^10.0.2", - "@types/hast": "^3.0.4" + "@types/hast": "^3.0.5" }, "engines": { "node": ">=20" } }, "node_modules/@shikijs/themes": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-4.3.1.tgz", - "integrity": "sha512-dgpoJ4WqNi2yTmizQHBJ5zcX6j2lE6icN/0yt4l1kkf16jrY/pwPLoTb1ETsWMz0OBLf9ZNvwmxft+cH+N9qSA==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-4.4.3.tgz", + "integrity": "sha512-w8UHjeUnIR965KMWJHUPXOc2mNJUnK3vpVLYLvw5IYU2mnTTJ89E24OrJDBNiJDQ0qzb0tc4l7mrIXx5cFeIyw==", "license": "MIT", "dependencies": { - "@shikijs/types": "4.3.1" + "@shikijs/types": "4.4.3" }, "engines": { "node": ">=20" } }, "node_modules/@shikijs/types": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-4.3.1.tgz", - "integrity": "sha512-CHFxE0jztBIZRHH6gxXE7DXUCFXjReEGxZ/j0rfSLGKZuwp2xBYycEP14875DSa9KLL/6700oxIq6oO6ef9K2g==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-4.4.3.tgz", + "integrity": "sha512-UEJxmRR++MAGR6hugn0vgVS2W/6lWAts84FFSrnlH9sP0LNol7E5+NQ792pH8liWUhyMyjhTgSUH3k7iD7tc5g==", "license": "MIT", "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", - "@types/hast": "^3.0.4" + "@types/hast": "^3.0.5" }, "engines": { "node": ">=20" @@ -4789,12 +5317,12 @@ } }, "node_modules/@smithy/core": { - "version": "3.29.7", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.29.7.tgz", - "integrity": "sha512-BiEE2bnnGoPKdlGe3L+gOYORDHFGPuYVRLP7iUow/Sflm0B4hC4XY3FC1MRuc7ltzpW2xNnXopKi34TTkULlKQ==", + "version": "3.34.1", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.34.1.tgz", + "integrity": "sha512-dLcOUxz8YCv1RZUMKq6GbyUf95pLbrqh34bPvpCZ1+CByFF31BEAFewZjsGCnVsZTKdThNENfGyAgk2TJqVwSw==", "license": "Apache-2.0", "dependencies": { - "@smithy/types": "^4.16.1", + "@smithy/types": "^4.18.0", "tslib": "^2.6.2" }, "engines": { @@ -4802,13 +5330,13 @@ } }, "node_modules/@smithy/credential-provider-imds": { - "version": "4.4.12", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.4.12.tgz", - "integrity": "sha512-ZZPDbl/aRp77aycuoMlo3BTayT4CE2a3uoqETYZU5ySnVbhpl5IJiY7dCZedn+ZusyDLqVv44IvKBiXd2/nK0Q==", + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.5.2.tgz", + "integrity": "sha512-A9uSdn72ozbRUSit0eib0TW7nXuNPlaeM0zcGkJ+nE6tFcSDbnmtwoxbTCFBukVQcszDAyvsd7+rTduPTXpygg==", "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.29.7", - "@smithy/types": "^4.16.1", + "@smithy/core": "^3.33.2", + "@smithy/types": "^4.17.2", "tslib": "^2.6.2" }, "engines": { @@ -4816,13 +5344,13 @@ } }, "node_modules/@smithy/fetch-http-handler": { - "version": "5.6.9", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.6.9.tgz", - "integrity": "sha512-EJktha5m5MXCwzdXrlWyqb9UCNHNFKlg+PmTpRsdX3dncJPTiqYleM9OKj2mLgdVJHR01d2tU4alG+z2NdH5rQ==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.8.0.tgz", + "integrity": "sha512-ycSJu3tFAQ4v04CBB0agqFMVsSQ1iG3yw+SpgxRqKfaURpQD4CZ8Wn0zPMmSnOuTpTh65Vz+EA0rMrw089wvkA==", "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.29.7", - "@smithy/types": "^4.16.1", + "@smithy/core": "^3.33.3", + "@smithy/types": "^4.18.0", "tslib": "^2.6.2" }, "engines": { @@ -4830,13 +5358,13 @@ } }, "node_modules/@smithy/node-http-handler": { - "version": "4.9.9", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.9.9.tgz", - "integrity": "sha512-xVBZ3hptB99iNO9XyWqEhC7KD9bP9UPXhuy3h5Y2ItCfBv160D9IIC/Fmmp3EbnWwit4C+KVqlSE+E29Nk/pPg==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.12.1.tgz", + "integrity": "sha512-ThMkboGeONWXAelq9FvGsuJC4rOi+qyC4/zhUF58xYpxUg5sQKx2VXZYJmtNjr4dSuBJ1HeJXETQILCz3wOHvw==", "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.29.7", - "@smithy/types": "^4.16.1", + "@smithy/core": "^3.33.3", + "@smithy/types": "^4.18.0", "tslib": "^2.6.2" }, "engines": { @@ -4844,13 +5372,13 @@ } }, "node_modules/@smithy/signature-v4": { - "version": "5.6.8", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.6.8.tgz", - "integrity": "sha512-iGBm6hIwD2MGvVRSgrjVWa4FXtXDq3akxu0DCpnkmBo0xtEHZ/siMRt7ycfZAefYr2UdywUgmGtoRLaq5u56pg==", + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.7.3.tgz", + "integrity": "sha512-7ImGm+FkHRLcBaRttIAMZ6bzJZWb2cJGoYjq46F2UjycujWzrL9GEN9h4w7eQyXJYnltrUhxbbieBAIRrdqpow==", "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.29.7", - "@smithy/types": "^4.16.1", + "@smithy/core": "^3.33.3", + "@smithy/types": "^4.17.2", "tslib": "^2.6.2" }, "engines": { @@ -4858,9 +5386,9 @@ } }, "node_modules/@smithy/types": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.16.1.tgz", - "integrity": "sha512-0JFs3V2y2M9tKW5na/qxe69Zv+uxLMO7QBbhxF/FHu/Gp2NFZAAL9tWl9PU02xxo07pb3G9FTyjNc6D5uZrJIg==", + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.18.0.tgz", + "integrity": "sha512-CgB6HHWer/vrKps24ulRIbpcpb7K4xAU7SkZ7YHzBPlwHsvsrCJFEXK421s+cJzX+ZrqtA/TuU5w1HzI7k9N8A==", "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" @@ -4882,14 +5410,14 @@ "license": "MIT" }, "node_modules/@swc/core": { - "version": "1.15.46", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.15.46.tgz", - "integrity": "sha512-Ri3em2mBpq3h2zSPliCYl63otDGqek8PPEfv2nWgRQEbZ/VBCNyypVTVQ6cEbTCXBhy+WE2T3fQb08moIyuYaw==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.16.2.tgz", + "integrity": "sha512-95I4kiSMeveI/Mhi+tE4fiWcWLUMfzfKrk0jtr8LRMqHgOgq+xHS+zExkDqoO4b5OeeuXHMWVdD5MeP3X6sULw==", "hasInstallScript": true, "license": "Apache-2.0", "dependencies": { "@swc/counter": "^0.1.3", - "@swc/types": "^0.1.27" + "@swc/types": "^0.1.28" }, "engines": { "node": ">=10" @@ -4899,18 +5427,18 @@ "url": "https://opencollective.com/swc" }, "optionalDependencies": { - "@swc/core-darwin-arm64": "1.15.46", - "@swc/core-darwin-x64": "1.15.46", - "@swc/core-linux-arm-gnueabihf": "1.15.46", - "@swc/core-linux-arm64-gnu": "1.15.46", - "@swc/core-linux-arm64-musl": "1.15.46", - "@swc/core-linux-ppc64-gnu": "1.15.46", - "@swc/core-linux-s390x-gnu": "1.15.46", - "@swc/core-linux-x64-gnu": "1.15.46", - "@swc/core-linux-x64-musl": "1.15.46", - "@swc/core-win32-arm64-msvc": "1.15.46", - "@swc/core-win32-ia32-msvc": "1.15.46", - "@swc/core-win32-x64-msvc": "1.15.46" + "@swc/core-darwin-arm64": "1.16.2", + "@swc/core-darwin-x64": "1.16.2", + "@swc/core-linux-arm-gnueabihf": "1.16.2", + "@swc/core-linux-arm64-gnu": "1.16.2", + "@swc/core-linux-arm64-musl": "1.16.2", + "@swc/core-linux-ppc64-gnu": "1.16.2", + "@swc/core-linux-s390x-gnu": "1.16.2", + "@swc/core-linux-x64-gnu": "1.16.2", + "@swc/core-linux-x64-musl": "1.16.2", + "@swc/core-win32-arm64-msvc": "1.16.2", + "@swc/core-win32-ia32-msvc": "1.16.2", + "@swc/core-win32-x64-msvc": "1.16.2" }, "peerDependencies": { "@swc/helpers": ">=0.5.17" @@ -4922,9 +5450,9 @@ } }, "node_modules/@swc/core-darwin-arm64": { - "version": "1.15.46", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.15.46.tgz", - "integrity": "sha512-IsISIT22EfktVJrlvIpnAxG2u/A9aob9l99HMlx80x72WlFmFPk1V3UhkEzx86eJP8hw049KTFv/RISho2cq2Q==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.16.2.tgz", + "integrity": "sha512-i/j0HNbnn79qnTVPicvay92Nark8fW8NQqn1e2mGERjUXNpBV0+SwQxlRpk2zBhn6laJ8PDI6Kn1nHZhnz3LCA==", "cpu": [ "arm64" ], @@ -4938,9 +5466,9 @@ } }, "node_modules/@swc/core-darwin-x64": { - "version": "1.15.46", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.15.46.tgz", - "integrity": "sha512-4Tj4ppVIPCmUMpmGFiGtyEriwLyJ+yi/US4WfBrP/ok8COGddDZXLEzQETnKyK46mjvr1v0jevrS23zjoff7vA==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.16.2.tgz", + "integrity": "sha512-HrwqHyEyHVXO3qTk8EkNK7/b6sOZSEoNh+pot6RdE5x0LbNqfo8LtJUvi3UTXr+5ja/o5HbJdW80eCXo+NjbiA==", "cpu": [ "x64" ], @@ -4954,9 +5482,9 @@ } }, "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.15.46", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.15.46.tgz", - "integrity": "sha512-i8tUGnNjyOgMmfmgFSg4aeJLQoFyfpIHK5FjpQAwpRyQIqEUB2w1e8zIDQzY1WhOxx8NoS1S5iUL813Un4Sf5A==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.16.2.tgz", + "integrity": "sha512-MdXi83Z/gGp1LIrg+h7HKxiul/z/Bty/ZJSvYAFqDl9zteC1XLSAZdScquKtXPp50rdyXqritTDCqQBhwVfZKA==", "cpu": [ "arm" ], @@ -4970,9 +5498,9 @@ } }, "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.15.46", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.15.46.tgz", - "integrity": "sha512-c0OnhqzdhfOvv6qhNCcByepB+sNYOGZyhtr2Qa6ZCHvAWTYhSRw4j/u92Stue9PbZ/6q74b9nHzi76+kVzqQHQ==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.16.2.tgz", + "integrity": "sha512-/jcTmK6Ktz3owM3YtiKvjofV6p3VpHnYzTIrOGwDIOsDigRAAVuZ8east33wYO/7UTdKYFlyHNnJNT0WJqOA3Q==", "cpu": [ "arm64" ], @@ -4986,9 +5514,9 @@ } }, "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.15.46", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.15.46.tgz", - "integrity": "sha512-imyRpNEcUzFQFV2LE4jL68ErvmKEuZCbvZru77iQREunJ+bR4i658cupTgtG1mLYM3F1Tzy3Sb9xYb02KghWTg==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.16.2.tgz", + "integrity": "sha512-4gFarKaFnlJTSlJYKmMhV4u+3YE4uYfiydpBoYjmgQhCf9lAieOq+WilZaK9vVSHeqLuQpTEiGULZqAdsRX5Dw==", "cpu": [ "arm64" ], @@ -5002,9 +5530,9 @@ } }, "node_modules/@swc/core-linux-ppc64-gnu": { - "version": "1.15.46", - "resolved": "https://registry.npmjs.org/@swc/core-linux-ppc64-gnu/-/core-linux-ppc64-gnu-1.15.46.tgz", - "integrity": "sha512-ctEfcl/HcUeomK33cbySiHZm98GEDIxTm1EkpBsYCiHxElYBzvTXVeuQT2YwbUXn9XCrjiw4ipyUNk33k26qRg==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/@swc/core-linux-ppc64-gnu/-/core-linux-ppc64-gnu-1.16.2.tgz", + "integrity": "sha512-syqSLGd6KlZ1PciNzs6bIUlhOuFztZufebOHaERjc4N4SqNZxyqYd4I+jj/EfOYnpe0kNjccn9HJLN1p5dz3+w==", "cpu": [ "ppc64" ], @@ -5018,9 +5546,9 @@ } }, "node_modules/@swc/core-linux-s390x-gnu": { - "version": "1.15.46", - "resolved": "https://registry.npmjs.org/@swc/core-linux-s390x-gnu/-/core-linux-s390x-gnu-1.15.46.tgz", - "integrity": "sha512-DxlMdnt84TtRVTv7WL/thWyz9+QU8QZNNoAP9rrk0P68LziuhfePp8MjQ44zIprpTHTsEwyziIuGUUN5iSC1bQ==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/@swc/core-linux-s390x-gnu/-/core-linux-s390x-gnu-1.16.2.tgz", + "integrity": "sha512-ZBBLK+ewGyXLzWeMS7wbKtWBdnif6etn7xvPY/iOfbdsjX/+bgkp1pQt2lWF2wlu2hXYZuhJ/tHZE/QR8/apzg==", "cpu": [ "s390x" ], @@ -5034,9 +5562,9 @@ } }, "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.15.46", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.15.46.tgz", - "integrity": "sha512-SKxI7J6t90XPl8hRUqtJi9NfGdunN/E/vZMc7Bc0figeRdOPDBT+Tm8g7cx9xM0T0mewh2l+8dewa3Am27/P+A==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.16.2.tgz", + "integrity": "sha512-LyHJgxCA4Tje0ysBMbEb0tt/ie8kgUKoFE3JAKFhpevmTmhYEoC0H9s47WuDsqiFckF1ITUguZIXJG6K5e0dvg==", "cpu": [ "x64" ], @@ -5050,9 +5578,9 @@ } }, "node_modules/@swc/core-linux-x64-musl": { - "version": "1.15.46", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.15.46.tgz", - "integrity": "sha512-qj9T6B7bosI0VEsrWOVXZN1OXxS8Tp63ywyrLxNdOycnUtLdkgYcoBsN5y8ImnDDsnwrEWZOy1e+J4xSe7mA3Q==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.16.2.tgz", + "integrity": "sha512-PghXJlVM1cgtLfNUR1vxFo1z+PDRAe8cWAJlZZ7spmeiN7BospGXg/MHUg7oNSgwSX7Zo//YKv9P5yD9apsFJQ==", "cpu": [ "x64" ], @@ -5066,9 +5594,9 @@ } }, "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.15.46", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.15.46.tgz", - "integrity": "sha512-8p7l4c3LU+eA5g9Et1JPhNeMC1oQwXTGU+uah8DPIBX7YXzqswvaBtyKVmXefVGi/DJU1x3YJsc3mbAp9aWzSQ==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.16.2.tgz", + "integrity": "sha512-StTOSefYBxemvNYYUI3UmO1a8y+hSPjjfHogC2TEHL+Z1PlEBim/XtLas5rS04jAzT9RrNmbtX911SZ42H9jSQ==", "cpu": [ "arm64" ], @@ -5082,9 +5610,9 @@ } }, "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.15.46", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.15.46.tgz", - "integrity": "sha512-tUEnfr3Bn9u6FOjUb3PN9p+09qZC2j+wNDLKHzXXZn22rqGcUqR/ohCRSS+nG9B9+X+U+3FewNEHJkTmdIvMjQ==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.16.2.tgz", + "integrity": "sha512-fycER209DYIzsibpTMC+chND05OfOjgztWL9U8OE6/uUlsOUZH3eh98isBLEnOymYUhlJLEt5++W1+KL/FOh5Q==", "cpu": [ "ia32" ], @@ -5098,9 +5626,9 @@ } }, "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.15.46", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.15.46.tgz", - "integrity": "sha512-Vux7UDzBJYQggSuPfcl2w9iu+IJpgpRCxHzgCaVkELnAXAE4XZMOTX9HNcaNiwfeIDqdu2rkr69RuDm6wY8neA==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.16.2.tgz", + "integrity": "sha512-cSd1z6ivSrJPVr+moVwOHWjeKy6TpO4/Shwcv5KCrKYXCccxwh4pRy1C3fDioNx2PF1jPZWHKZjtXt+Be9VbaQ==", "cpu": [ "x64" ], @@ -5129,9 +5657,9 @@ } }, "node_modules/@swc/types": { - "version": "0.1.27", - "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.27.tgz", - "integrity": "sha512-K6h3iUlqeM946U4sXFYeahefR1YBbXJvko+hv8WS8/0BNJ4OHiHRywMnQUJCqkR7Y9+hqQ1TvEpiKqUhz7NEFg==", + "version": "0.1.28", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.28.tgz", + "integrity": "sha512-V6Mnml8v09QALx6K0elJ7o9K/MkVDtW3t6L+7Ou/JcWtb3xwId2AH4FeOceySd2JaO87IMw4+6vSZxLm34LPbw==", "license": "Apache-2.0", "dependencies": { "@swc/counter": "^0.1.3" @@ -5150,131 +5678,10 @@ "node": ">=10" } }, - "node_modules/@tensorflow/tfjs": { - "version": "4.22.0", - "resolved": "https://registry.npmjs.org/@tensorflow/tfjs/-/tfjs-4.22.0.tgz", - "integrity": "sha512-0TrIrXs6/b7FLhLVNmfh8Sah6JgjBPH4mZ8JGb7NU6WW+cx00qK5BcAZxw7NCzxj6N8MRAIfHq+oNbPUNG5VAg==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@tensorflow/tfjs-backend-cpu": "4.22.0", - "@tensorflow/tfjs-backend-webgl": "4.22.0", - "@tensorflow/tfjs-converter": "4.22.0", - "@tensorflow/tfjs-core": "4.22.0", - "@tensorflow/tfjs-data": "4.22.0", - "@tensorflow/tfjs-layers": "4.22.0", - "argparse": "^1.0.10", - "chalk": "^4.1.0", - "core-js": "3.29.1", - "regenerator-runtime": "^0.13.5", - "yargs": "^16.0.3" - }, - "bin": { - "tfjs-custom-module": "dist/tools/custom_module/cli.js" - } - }, - "node_modules/@tensorflow/tfjs-backend-cpu": { - "version": "4.22.0", - "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-backend-cpu/-/tfjs-backend-cpu-4.22.0.tgz", - "integrity": "sha512-1u0FmuLGuRAi8D2c3cocHTASGXOmHc/4OvoVDENJayjYkS119fcTcQf4iHrtLthWyDIPy3JiPhRrZQC9EwnhLw==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@types/seedrandom": "^2.4.28", - "seedrandom": "^3.0.5" - }, - "engines": { - "yarn": ">= 1.3.2" - }, - "peerDependencies": { - "@tensorflow/tfjs-core": "4.22.0" - } - }, - "node_modules/@tensorflow/tfjs-backend-webgl": { - "version": "4.22.0", - "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-backend-webgl/-/tfjs-backend-webgl-4.22.0.tgz", - "integrity": "sha512-H535XtZWnWgNwSzv538czjVlbJebDl5QTMOth4RXr2p/kJ1qSIXE0vZvEtO+5EC9b00SvhplECny2yDewQb/Yg==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@tensorflow/tfjs-backend-cpu": "4.22.0", - "@types/offscreencanvas": "~2019.3.0", - "@types/seedrandom": "^2.4.28", - "seedrandom": "^3.0.5" - }, - "engines": { - "yarn": ">= 1.3.2" - }, - "peerDependencies": { - "@tensorflow/tfjs-core": "4.22.0" - } - }, - "node_modules/@tensorflow/tfjs-converter": { - "version": "4.22.0", - "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-converter/-/tfjs-converter-4.22.0.tgz", - "integrity": "sha512-PT43MGlnzIo+YfbsjM79Lxk9lOq6uUwZuCc8rrp0hfpLjF6Jv8jS84u2jFb+WpUeuF4K33ZDNx8CjiYrGQ2trQ==", - "license": "Apache-2.0", - "optional": true, - "peerDependencies": { - "@tensorflow/tfjs-core": "4.22.0" - } - }, - "node_modules/@tensorflow/tfjs-core": { - "version": "4.22.0", - "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-core/-/tfjs-core-4.22.0.tgz", - "integrity": "sha512-LEkOyzbknKFoWUwfkr59vSB68DMJ4cjwwHgicXN0DUi3a0Vh1Er3JQqCI1Hl86GGZQvY8ezVrtDIvqR1ZFW55A==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@types/long": "^4.0.1", - "@types/offscreencanvas": "~2019.7.0", - "@types/seedrandom": "^2.4.28", - "@webgpu/types": "0.1.38", - "long": "4.0.0", - "node-fetch": "~2.6.1", - "seedrandom": "^3.0.5" - }, - "engines": { - "yarn": ">= 1.3.2" - } - }, - "node_modules/@tensorflow/tfjs-core/node_modules/@types/offscreencanvas": { - "version": "2019.7.3", - "resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.7.3.tgz", - "integrity": "sha512-ieXiYmgSRXUDeOntE1InxjWyvEelZGP63M+cGuquuRLuIKKT1osnkXjxev9B7d1nXSug5vpunx+gNlbVxMlC9A==", - "license": "MIT", - "optional": true - }, - "node_modules/@tensorflow/tfjs-data": { - "version": "4.22.0", - "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-data/-/tfjs-data-4.22.0.tgz", - "integrity": "sha512-dYmF3LihQIGvtgJrt382hSRH4S0QuAp2w1hXJI2+kOaEqo5HnUPG0k5KA6va+S1yUhx7UBToUKCBHeLHFQRV4w==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@types/node-fetch": "^2.1.2", - "node-fetch": "~2.6.1", - "string_decoder": "^1.3.0" - }, - "peerDependencies": { - "@tensorflow/tfjs-core": "4.22.0", - "seedrandom": "^3.0.5" - } - }, - "node_modules/@tensorflow/tfjs-layers": { - "version": "4.22.0", - "resolved": "https://registry.npmjs.org/@tensorflow/tfjs-layers/-/tfjs-layers-4.22.0.tgz", - "integrity": "sha512-lybPj4ZNj9iIAPUj7a8ZW1hg8KQGfqWLlCZDi9eM/oNKCCAgchiyzx8OrYoWmRrB+AM6VNEeIT+2gZKg5ReihA==", - "license": "Apache-2.0 AND MIT", - "optional": true, - "peerDependencies": { - "@tensorflow/tfjs-core": "4.22.0" - } - }, "node_modules/@toon-format/toon": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@toon-format/toon/-/toon-2.3.1.tgz", - "integrity": "sha512-sWqEMeAJGMda9qRrfPKrX3C4c33CO9SJuvJzzrcBEn5sbDB+k6pSLkDsfN0rVnLQwR97MV3sDgVbcxQNsq8xVw==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@toon-format/toon/-/toon-4.1.1.tgz", + "integrity": "sha512-SGCkS7IjVpwRmGPgnY8ENKpAf0EdAnZDOQkvFW0d2cgOpdn9FEFl7sTgryESyypXrWr0YajHGpwsAUX4zw9ZvA==", "license": "MIT" }, "node_modules/@tootallnate/once": { @@ -5619,13 +6026,6 @@ "@types/node": "*" } }, - "node_modules/@types/long": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", - "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==", - "license": "MIT", - "optional": true - }, "node_modules/@types/mdast": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", @@ -5657,24 +6057,6 @@ "undici-types": "~8.3.0" } }, - "node_modules/@types/node-fetch": { - "version": "2.6.13", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.13.tgz", - "integrity": "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==", - "license": "MIT", - "optional": true, - "dependencies": { - "@types/node": "*", - "form-data": "^4.0.4" - } - }, - "node_modules/@types/offscreencanvas": { - "version": "2019.3.0", - "resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.3.0.tgz", - "integrity": "sha512-esIJx9bQg+QYF0ra8GnvfianIY8qWB0GBx54PK5Eps6m+xTj86KLavHv6qDhzKcu5UUOgNfJ2pWaIIV7TRUd9Q==", - "license": "MIT", - "optional": true - }, "node_modules/@types/parse-json": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", @@ -5703,74 +6085,204 @@ "@types/node": "*" } }, - "node_modules/@types/seedrandom": { - "version": "2.4.34", - "resolved": "https://registry.npmjs.org/@types/seedrandom/-/seedrandom-2.4.34.tgz", - "integrity": "sha512-ytDiArvrn/3Xk6/vtylys5tlY6eo7Ane0hvcx++TKo6RxQXuVfW0AF/oeWqAj9dN29SyhtawuXstgmPlwNcv/A==", + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "license": "MIT" + }, + "node_modules/@types/use-sync-external-store": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", + "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==", + "license": "MIT" + }, + "node_modules/@types/verror": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.11.tgz", + "integrity": "sha512-RlDm9K7+o5stv0Co8i8ZRGxDbrTxhJtgjqjFyVh/tXQyl/rYtTKlnTvZ88oSTeYREWurwx20Js4kTuKCsFkUtg==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/@types/yauzl": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.3.tgz", + "integrity": "sha512-60YRaenCQcVjYEKOcG824+DRGGIQ3VKErcBoAEDJZz5bKIs2ZG+X/H9Nk+Q6EVkwJk5QNApxbrc5QtBSwtrXAg==", + "license": "ISC" + }, + "node_modules/@upsetjs/venn.js": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@upsetjs/venn.js/-/venn.js-2.0.0.tgz", + "integrity": "sha512-WbBhLrooyePuQ1VZxrJjtLvTc4NVfpOyKx0sKqioq9bX1C1m7Jgykkn8gLrtwumBioXIqam8DLxp88Adbue6Hw==", + "license": "MIT", + "optionalDependencies": { + "d3-selection": "^3.0.0", + "d3-transition": "^3.0.1" + } + }, + "node_modules/@wreq-js/binding-android-arm64": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@wreq-js/binding-android-arm64/-/binding-android-arm64-3.2.0.tgz", + "integrity": "sha512-PRsy18Z+0fftLeDvFTQwpgdepihRk6oVzdQWt92hEdarI7DexhgDJvvZfDsylMp7GDfsys9sFks8nIAi4n7eKQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@wreq-js/binding-darwin-arm64": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@wreq-js/binding-darwin-arm64/-/binding-darwin-arm64-3.2.0.tgz", + "integrity": "sha512-TGbgqj7YKp6m2p79hyLtTBatKgU8SKEVL5e903KGSeSDKkLbgk8knFoZ2MakhJnlqKZhvLPCNLT7A3AStwIoHQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@wreq-js/binding-darwin-x64": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@wreq-js/binding-darwin-x64/-/binding-darwin-x64-3.2.0.tgz", + "integrity": "sha512-89JkGsik49nUcQR7HfO6M+Na3whkhAQBghVFWn+vGmz32RzTX+HVy6q7wThjN+XGT+xvn9ZQpzTie3B292S50g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@wreq-js/binding-linux-arm64-gnu": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@wreq-js/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-3.2.0.tgz", + "integrity": "sha512-WXqMK7AtOxMJAdwDpnAdDq0NZqf6wuRucKCQWQSLdSTUyTEuGo2anRkUsZwqvHbLrkWCTXNfl1hAfA+wIk/4kw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@wreq-js/binding-linux-arm64-musl": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@wreq-js/binding-linux-arm64-musl/-/binding-linux-arm64-musl-3.2.0.tgz", + "integrity": "sha512-YSMWs3BNBCNhWvIAUHWyp2K/L17qxfaRTl+t97ykOIOIKZSduNYZn/Yn3hTNtpbdfrTmNMG9pltEcbixFKS4xQ==", + "cpu": [ + "arm64" + ], "license": "MIT", - "optional": true + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.0.0" + } }, - "node_modules/@types/trusted-types": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", - "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "node_modules/@wreq-js/binding-linux-x64-gnu": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@wreq-js/binding-linux-x64-gnu/-/binding-linux-x64-gnu-3.2.0.tgz", + "integrity": "sha512-6N7C1uc1qieM23rdKR5k07hfS50hVFExVHzLhHiWbmk9NyqBj0xyj2Mh5ThIrvz/or/6Pe79P8D7UWbl4aJTkw==", + "cpu": [ + "x64" + ], "license": "MIT", - "optional": true - }, - "node_modules/@types/unist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", - "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", - "license": "MIT" - }, - "node_modules/@types/use-sync-external-store": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", - "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==", - "license": "MIT" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.0.0" + } }, - "node_modules/@types/verror": { - "version": "1.10.11", - "resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.11.tgz", - "integrity": "sha512-RlDm9K7+o5stv0Co8i8ZRGxDbrTxhJtgjqjFyVh/tXQyl/rYtTKlnTvZ88oSTeYREWurwx20Js4kTuKCsFkUtg==", - "dev": true, + "node_modules/@wreq-js/binding-linux-x64-musl": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@wreq-js/binding-linux-x64-musl/-/binding-linux-x64-musl-3.2.0.tgz", + "integrity": "sha512-0h0xJsmhVlmh+vHs9dYMIp5lpkKGNZrSedkl2Mh9XmR5slBahTcHT7oEEclhV+aNcY3V2Afmmqfil5huL+yDpA==", + "cpu": [ + "x64" + ], "license": "MIT", - "optional": true + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.0.0" + } }, - "node_modules/@types/yauzl": { - "version": "2.10.3", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", - "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", - "dev": true, + "node_modules/@wreq-js/binding-win32-arm64-msvc": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@wreq-js/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-3.2.0.tgz", + "integrity": "sha512-6bfaVFfbI61s5YLgQL+43uURk/VuOu7TPlUwY1l0Q9yJdWzD+Jpdokgl5cEiY2a0FEAw8Q4LqPI+XZT3YAMnQA==", + "cpu": [ + "arm64" + ], "license": "MIT", "optional": true, - "dependencies": { - "@types/node": "*" + "os": [ + "win32" + ], + "engines": { + "node": ">=20.0.0" } }, - "node_modules/@ungap/structured-clone": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.3.tgz", - "integrity": "sha512-60YRaenCQcVjYEKOcG824+DRGGIQ3VKErcBoAEDJZz5bKIs2ZG+X/H9Nk+Q6EVkwJk5QNApxbrc5QtBSwtrXAg==", - "license": "ISC" - }, - "node_modules/@upsetjs/venn.js": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@upsetjs/venn.js/-/venn.js-2.0.0.tgz", - "integrity": "sha512-WbBhLrooyePuQ1VZxrJjtLvTc4NVfpOyKx0sKqioq9bX1C1m7Jgykkn8gLrtwumBioXIqam8DLxp88Adbue6Hw==", + "node_modules/@wreq-js/binding-win32-x64-msvc": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@wreq-js/binding-win32-x64-msvc/-/binding-win32-x64-msvc-3.2.0.tgz", + "integrity": "sha512-w4aktLElPgBXkWC/v9Ti9np6jBjYOzIyqmzgT41V/zuDq/V+V7s/13f9OzcX5hObH2WOpajo0KeljTJ2aRExNQ==", + "cpu": [ + "x64" + ], "license": "MIT", - "optionalDependencies": { - "d3-selection": "^3.0.0", - "d3-transition": "^3.0.1" + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20.0.0" } }, - "node_modules/@webgpu/types": { - "version": "0.1.38", - "resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.38.tgz", - "integrity": "sha512-7LrhVKz2PRh+DD7+S+PVaFd5HxaWQvoMqBbsV9fNJO1pjUs1P8bM2vQVNfk+3URTqbuTI7gkXi0rfsN0IadoBA==", - "license": "BSD-3-Clause", - "optional": true - }, "node_modules/@xmldom/xmldom": { "version": "0.9.10", "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.9.10.tgz", @@ -5782,12 +6294,12 @@ } }, "node_modules/@xyflow/react": { - "version": "12.11.2", - "resolved": "https://registry.npmjs.org/@xyflow/react/-/react-12.11.2.tgz", - "integrity": "sha512-eLAlDWJfWnQEhJwGMjlWdAXO9eYllKpliUmPQlAmOLxz6mExXuzMVDUKLMquixgkrtmMFFtug3jGKmYYld12cA==", + "version": "12.11.6", + "resolved": "https://registry.npmjs.org/@xyflow/react/-/react-12.11.6.tgz", + "integrity": "sha512-9XsEJNHjatKYndszKTF/bsU7FOP9dJ6V/EQwzy3oMdtqgBuUq7BjKSwkEo+C7s4qHstHQfwwoHA3E8QfpPxZZQ==", "license": "MIT", "dependencies": { - "@xyflow/system": "0.0.79", + "@xyflow/system": "0.0.82", "classcat": "^5.0.3", "zustand": "^4.4.0" }, @@ -5835,9 +6347,9 @@ } }, "node_modules/@xyflow/system": { - "version": "0.0.79", - "resolved": "https://registry.npmjs.org/@xyflow/system/-/system-0.0.79.tgz", - "integrity": "sha512-czLyOh91NF0hIzbNzwi8I6GlqG23BHh2435OddfI6uiaLH3xdrdygO93gqgH1Bv9mhy8XPFQJOBn1FTq4LvEWA==", + "version": "0.0.82", + "resolved": "https://registry.npmjs.org/@xyflow/system/-/system-0.0.82.tgz", + "integrity": "sha512-4DKnL3CGtCGLRSmgDqaajRVgeksMXq/Yw4wPfdMfm7JvdIiWHGzVYOfFUztiATwdBXZqUU6HhehwUdbV9G23PQ==", "license": "MIT", "dependencies": { "@types/d3-drag": "^3.0.7", @@ -5851,144 +6363,6 @@ "d3-zoom": "^3.0.0" } }, - "node_modules/@yuku-analyzer/binding-darwin-arm64": { - "version": "0.6.12", - "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-darwin-arm64/-/binding-darwin-arm64-0.6.12.tgz", - "integrity": "sha512-9rpIP7IeybjyvWUf6WnU24h1qo+JdxIHr1o3yb06HoE8tM3S/Jh5RrUw9aw5P9BKSIvSPbLyVlItX7PcD3o5bQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@yuku-analyzer/binding-darwin-x64": { - "version": "0.6.12", - "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-darwin-x64/-/binding-darwin-x64-0.6.12.tgz", - "integrity": "sha512-ELLhNT4FGnqY8yh0W3cSs9rGMSeUyhib1aYD84RupjlfsrDTrQRoDhWu01Dv6xCfYgASYaj1Abntk91A7njNag==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@yuku-analyzer/binding-freebsd-x64": { - "version": "0.6.12", - "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-freebsd-x64/-/binding-freebsd-x64-0.6.12.tgz", - "integrity": "sha512-s76XocUMlK9liTyipALFb2K64ku35u/wg238A0NW8U5CUDsuIe/8tu5TzdLjJAGxnd0IV+gBneDt9cJJzLeFRQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@yuku-analyzer/binding-linux-arm-gnu": { - "version": "0.6.12", - "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-linux-arm-gnu/-/binding-linux-arm-gnu-0.6.12.tgz", - "integrity": "sha512-hm8Tq0umop3RGu6dOMF61q69tYn1bDp1CeYD5ZjuGFQJclp0moVtjzY4z0bzusicKeZ9+k5LRroR0p5HWC2hDw==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@yuku-analyzer/binding-linux-arm-musl": { - "version": "0.6.12", - "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-linux-arm-musl/-/binding-linux-arm-musl-0.6.12.tgz", - "integrity": "sha512-CxtPKLddogHAB3ZHVWaUl+U8jx0pdriTSbQ1K/orlDqU0GDhg8LuIRyUscP7r2/62fGGMzkc119fE71I4Nl1Fg==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@yuku-analyzer/binding-linux-arm64-gnu": { - "version": "0.6.12", - "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.6.12.tgz", - "integrity": "sha512-EOyLcpAmF5qAVDKmKvV7xt8oBGeWQ92CqFI4s7h7TRlrF6TfGRrh8PwawGn92gFploNLAYj/1Z9Q1gVvwGgG9g==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@yuku-analyzer/binding-linux-arm64-musl": { - "version": "0.6.12", - "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.6.12.tgz", - "integrity": "sha512-T3eCYy6bMnVRMQEYAbDcpj08/XM93dBTtnn/DDocJN21RARe+KCzWKeL26J3yd3bOW3WVjVLq09BfdpAGB0buQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@yuku-analyzer/binding-linux-x64-gnu": { - "version": "0.6.12", - "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.6.12.tgz", - "integrity": "sha512-1Y+noIuvnDugIVsoIr5NduZqX7KuFTzICSkvG8RW3OKK9URVeTOicKK217i44ABZSSZJ7A0E7vzifapx0c9VDw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@yuku-analyzer/binding-linux-x64-musl": { - "version": "0.6.12", - "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-linux-x64-musl/-/binding-linux-x64-musl-0.6.12.tgz", - "integrity": "sha512-woN/GuG95Fd6bp+ZQfmiFrZnoA2hdu3vfVSc89A8LElnYpzFaJM81sOZp8f3tVOVUJxbt7KAUiCLwSy34MJKqA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@yuku-analyzer/binding-win32-arm64": { - "version": "0.6.12", - "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-win32-arm64/-/binding-win32-arm64-0.6.12.tgz", - "integrity": "sha512-8OVFnKbK+lgsL6MqILPLpzlsa00K4KiKsdbHH94hpGcrqaz1jv+k0Y7ujSaoYTWw5Bb7Lr9GJ3L1n1hT2sXoYA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@yuku-analyzer/binding-win32-x64": { - "version": "0.6.12", - "resolved": "https://registry.npmjs.org/@yuku-analyzer/binding-win32-x64/-/binding-win32-x64-0.6.12.tgz", - "integrity": "sha512-3w8w1Xc5njwgbGTcn3JfDxWuQnFvtSll1D8gBlk4U8CI5v7ibKOMIdABucCXH8WtsRREG0ME5Vn0i422eX3zLQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@yuku-toolchain/types": { - "version": "0.6.11", - "resolved": "https://registry.npmjs.org/@yuku-toolchain/types/-/types-0.6.11.tgz", - "integrity": "sha512-i1JYFNJaKNCgyJ/nVoR8GK7wvlXF+ShYzFHBauWcvg8IoiXInK7pVziHcgNz/MWLPNr/Mb/CtmXccrJMkKqSHQ==", - "license": "MIT" - }, "node_modules/7zip-bin": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-5.2.0.tgz", @@ -6016,25 +6390,14 @@ "node": ">= 0.6" } }, - "node_modules/acorn": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz", - "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==", + "node_modules/adm-zip": { + "version": "0.5.18", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.18.tgz", + "integrity": "sha512-ufJnssQGbxzLNS1Ho9bCtX4rQKCCvoVuDLHoJyc3F9dOGDB4BkWs2Ci0kv53lqocAEQ/Cbi+I2XCsNYGqVYqng==", "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, + "optional": true, "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + "node": ">=12.0" } }, "node_modules/agent-base": { @@ -6298,13 +6661,6 @@ "electron-builder-squirrel-windows": "25.1.8" } }, - "node_modules/app-builder-lib/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, "node_modules/app-builder-lib/node_modules/chownr": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", @@ -6462,14 +6818,10 @@ } }, "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "license": "MIT", - "optional": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" }, "node_modules/aria-hidden": { "version": "1.2.6", @@ -6519,15 +6871,6 @@ "node": ">=8" } }, - "node_modules/astring": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/astring/-/astring-1.9.0.tgz", - "integrity": "sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==", - "license": "MIT", - "bin": { - "astring": "bin/astring" - } - }, "node_modules/async": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", @@ -6593,13 +6936,13 @@ } }, "node_modules/axios": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.18.1.tgz", - "integrity": "sha512-3nTvFlvpn9Zu/RkHUqtc7/+al4UpRW5az71ap5zccp6e8RAYEzhMTecX8Dz1wWDYrPpUoB1HAQEGEAEvUr7S9g==", + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.20.0.tgz", + "integrity": "sha512-r8aOh8j9cGKpgQAqpzrUHnSIc6a59Y3Xf/cv8sy1DrHCkZHzQGEuoq1tARk6qSyDdtQGSDgpb9kFlruzPvrgwg==", "license": "MIT", "dependencies": { "follow-redirects": "^1.16.0", - "form-data": "^4.0.5", + "form-data": "^4.0.6", "https-proxy-agent": "^5.0.1", "proxy-from-env": "^2.1.0" } @@ -6686,9 +7029,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.11.1", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.1.tgz", - "integrity": "sha512-HYXq73DDpCtNzOmrFsm9eSwCvWCql0RzqjpDzXN9EadiLJ4DNat0nsZ/Bzmy+Ud12mb4/zKDY0cQ805ZzN+i0A==", + "version": "2.11.24", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.24.tgz", + "integrity": "sha512-hYrgxie335U08WqICoGqKRzV1HFXv6zdxwJE4ekCb80CM9a0SVVsN4QPwT67RraRo+9h8IATk6uxHJw7QSkdOg==", "license": "Apache-2.0", "bin": { "baseline-browser-mapping": "dist/cli.cjs" @@ -6707,28 +7050,26 @@ } }, "node_modules/better-sqlite3": { - "version": "12.11.1", - "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-12.11.1.tgz", - "integrity": "sha512-dq9AtApgg5PGFtBzPFSBl3HZQjHok5gaQCM6zh2Yk0aSmDCs1CbnVI8/HgASQkNKsWFpseIO9beg5xxpYhbIfA==", - "hasInstallScript": true, + "version": "13.0.3", + "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-13.0.3.tgz", + "integrity": "sha512-RbOBxmLBG8uvFUc15X9+9SFemKcQ0WBuISBVkpuiaUB2qblC8UWlHEjdWVoZ8AdhSwmoEgsiXKfopX0CQxaACQ==", "license": "MIT", "optional": true, "dependencies": { - "bindings": "^1.5.0", - "prebuild-install": "^7.1.1" + "node-addon-api": "^8.0.0" }, "engines": { - "node": "20.x || 22.x || 23.x || 24.x || 25.x || 26.x" + "node": ">=22" } }, - "node_modules/bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "node_modules/better-sqlite3/node_modules/node-addon-api": { + "version": "8.9.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.9.2.tgz", + "integrity": "sha512-VijLXbi3UACN69I0JVXJsX4tjACjNoQDgv2gTF6sx2wWEi8tkSg2eX8p5gSIFi8z2+DL3oHmY6OyKce38SDolg==", "license": "MIT", "optional": true, - "dependencies": { - "file-uri-to-path": "1.0.0" + "engines": { + "node": "^18 || ^20 || >= 21" } }, "node_modules/bl": { @@ -7051,13 +7392,6 @@ "node": ">= 14" } }, - "node_modules/builder-util/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, "node_modules/builder-util/node_modules/fs-extra": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", @@ -7410,9 +7744,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001806", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001806.tgz", - "integrity": "sha512-72Cuvd95zbSYPKq6Fhg8eDJRlzgWDf7/mtoZv6Qe/DYNCEBdNxoA3+rZAU2ZhGCpZlns3EssFavaZomckT5Uuw==", + "version": "1.0.30001810", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001810.tgz", + "integrity": "sha512-TITQPUkaz+aVk5GL6NhOdwk1aEaNTSDPsGFWrTuhKGtjTF70jL/Oht2W4c6rXUe5fu7Ie19VIahAXHIIiWWNeg==", "funding": [ { "type": "opencollective", @@ -7504,21 +7838,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/chokidar": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", - "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", - "license": "MIT", - "dependencies": { - "readdirp": "^5.0.0" - }, - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/chownr": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", @@ -7861,13 +8180,16 @@ "node": ">=0.10.0" } }, - "node_modules/cnfast": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/cnfast/-/cnfast-0.0.8.tgz", - "integrity": "sha512-EjXKMfGfdwtV4AcNSQ6AwQaVzpC1B7IxeiwA3FlhTXz+YFlMKVi4c1JX9tgD2QOlahQXjB8KUXrBaYG+3v871Q==", + "node_modules/cn": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/cn/-/cn-0.2.6.tgz", + "integrity": "sha512-+i4L0zUGgRcEnhsxueVrP7iBGxBx5iD0WOTYg1MwFEu2ZyCmH5Ov2V1cul2Ht5UchRQQgftCf4be/RxspuW6QQ==", "license": "MIT", "bin": { - "cnfast": "bin/cli.js" + "cn": "bin/cn.mjs" + }, + "engines": { + "node": ">=20" } }, "node_modules/code-excerpt": { @@ -7882,16 +8204,6 @@ "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, - "node_modules/collapse-white-space": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-2.1.0.tgz", - "integrity": "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -8136,18 +8448,6 @@ "node": ">=6.6.0" } }, - "node_modules/core-js": { - "version": "3.29.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.29.1.tgz", - "integrity": "sha512-+jwgnhg6cQxKYIIjGtAHq2nwUOolo9eoFZ4sHfUH09BLXBgxnH4gA0zEd+t+BO2cNB8idaBtZFcFTRjQJRJmAw==", - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, "node_modules/core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -8209,6 +8509,18 @@ "buffer": "^5.1.0" } }, + "node_modules/cron-parser": { + "version": "5.10.1", + "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-5.10.1.tgz", + "integrity": "sha512-pKRrRagItwk9rGIStcUyMxFX34x56zoX3KDf9HJ4ttwkXIK1qxK63EvXvEDmlxI9AdPJ+Y7TEKRftRlW5eSS7A==", + "license": "MIT", + "dependencies": { + "luxon": "^3.7.2" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/cross-env": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", @@ -8249,9 +8561,9 @@ "license": "MIT" }, "node_modules/csv-stringify": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/csv-stringify/-/csv-stringify-6.8.1.tgz", - "integrity": "sha512-tZ6X6TKQyQgCo5OptXcyAbfN1pwmoxEqELPQ7KFazNErx7kiVsDK8o+VYRXhfMl4N9vvOOLXuioquR2MeP847A==", + "version": "6.8.3", + "resolved": "https://registry.npmjs.org/csv-stringify/-/csv-stringify-6.8.3.tgz", + "integrity": "sha512-gIeSCvq5F4VtXV3naV3VAewLhBkiZBz+PPhTOA8H3Y8h/ELa+R1ml0GZck/4/Nzo9ep2lvOluilJ6MJlbZsKMA==", "license": "MIT" }, "node_modules/cytoscape": { @@ -8851,9 +9163,9 @@ } }, "node_modules/default-browser": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.5.0.tgz", - "integrity": "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==", + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.5.1.tgz", + "integrity": "sha512-m1pAzaJgZ/gssEqlOhJkPJp8Xly7QyW6xcrkUa2KKcDeDSEMP7X8xipU3snUcfisTQx0w1AGae+9UtJSfVnXGw==", "license": "MIT", "dependencies": { "bundle-name": "^4.1.0", @@ -9096,13 +9408,6 @@ "dmg-license": "^1.0.11" } }, - "node_modules/dmg-builder/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, "node_modules/dmg-builder/node_modules/fs-extra": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", @@ -9231,9 +9536,9 @@ "optional": true }, "node_modules/dompurify": { - "version": "3.4.12", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.12.tgz", - "integrity": "sha512-zQvGet8Z2sWbQhCmfFz/T5QWH2oBmjnqK3qvOjaqaNLrLEF912WamU+ohnTp0TCep/MFVHpdJuCZEdFOdTnEFg==", + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.15.tgz", + "integrity": "sha512-EUBjM+B+lkDE41iE82DDSCfkoPGfXx8IxFxPMjNzm/Uk4xDet77rTN9wqlxlVg71kK7XGuUMv6wUxJUwwv+Xyw==", "license": "(MPL-2.0 OR Apache-2.0)", "optionalDependencies": { "@types/trusted-types": "^2.0.7" @@ -9776,42 +10081,10 @@ "license": "MIT", "optional": true }, - "node_modules/esast-util-from-estree": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/esast-util-from-estree/-/esast-util-from-estree-2.0.0.tgz", - "integrity": "sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==", - "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "devlop": "^1.0.0", - "estree-util-visit": "^2.0.0", - "unist-util-position-from-estree": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/esast-util-from-js": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/esast-util-from-js/-/esast-util-from-js-2.0.1.tgz", - "integrity": "sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==", - "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "acorn": "^8.0.0", - "esast-util-from-estree": "^2.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/esbuild": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", - "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz", + "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==", "hasInstallScript": true, "license": "MIT", "bin": { @@ -9821,32 +10094,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.28.1", - "@esbuild/android-arm": "0.28.1", - "@esbuild/android-arm64": "0.28.1", - "@esbuild/android-x64": "0.28.1", - "@esbuild/darwin-arm64": "0.28.1", - "@esbuild/darwin-x64": "0.28.1", - "@esbuild/freebsd-arm64": "0.28.1", - "@esbuild/freebsd-x64": "0.28.1", - "@esbuild/linux-arm": "0.28.1", - "@esbuild/linux-arm64": "0.28.1", - "@esbuild/linux-ia32": "0.28.1", - "@esbuild/linux-loong64": "0.28.1", - "@esbuild/linux-mips64el": "0.28.1", - "@esbuild/linux-ppc64": "0.28.1", - "@esbuild/linux-riscv64": "0.28.1", - "@esbuild/linux-s390x": "0.28.1", - "@esbuild/linux-x64": "0.28.1", - "@esbuild/netbsd-arm64": "0.28.1", - "@esbuild/netbsd-x64": "0.28.1", - "@esbuild/openbsd-arm64": "0.28.1", - "@esbuild/openbsd-x64": "0.28.1", - "@esbuild/openharmony-arm64": "0.28.1", - "@esbuild/sunos-x64": "0.28.1", - "@esbuild/win32-arm64": "0.28.1", - "@esbuild/win32-ia32": "0.28.1", - "@esbuild/win32-x64": "0.28.1" + "@esbuild/aix-ppc64": "0.28.2", + "@esbuild/android-arm": "0.28.2", + "@esbuild/android-arm64": "0.28.2", + "@esbuild/android-x64": "0.28.2", + "@esbuild/darwin-arm64": "0.28.2", + "@esbuild/darwin-x64": "0.28.2", + "@esbuild/freebsd-arm64": "0.28.2", + "@esbuild/freebsd-x64": "0.28.2", + "@esbuild/linux-arm": "0.28.2", + "@esbuild/linux-arm64": "0.28.2", + "@esbuild/linux-ia32": "0.28.2", + "@esbuild/linux-loong64": "0.28.2", + "@esbuild/linux-mips64el": "0.28.2", + "@esbuild/linux-ppc64": "0.28.2", + "@esbuild/linux-riscv64": "0.28.2", + "@esbuild/linux-s390x": "0.28.2", + "@esbuild/linux-x64": "0.28.2", + "@esbuild/netbsd-arm64": "0.28.2", + "@esbuild/netbsd-x64": "0.28.2", + "@esbuild/openbsd-arm64": "0.28.2", + "@esbuild/openbsd-x64": "0.28.2", + "@esbuild/openharmony-arm64": "0.28.2", + "@esbuild/sunos-x64": "0.28.2", + "@esbuild/win32-arm64": "0.28.2", + "@esbuild/win32-ia32": "0.28.2", + "@esbuild/win32-x64": "0.28.2" } }, "node_modules/escalade": { @@ -9901,22 +10174,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/estree-util-build-jsx": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/estree-util-build-jsx/-/estree-util-build-jsx-3.0.1.tgz", - "integrity": "sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ==", - "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "devlop": "^1.0.0", - "estree-util-is-identifier-name": "^3.0.0", - "estree-walker": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/estree-util-is-identifier-name": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", @@ -9927,35 +10184,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/estree-util-scope": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/estree-util-scope/-/estree-util-scope-1.0.0.tgz", - "integrity": "sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "devlop": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/estree-util-to-js": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/estree-util-to-js/-/estree-util-to-js-2.0.0.tgz", - "integrity": "sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==", - "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "astring": "^1.8.0", - "source-map": "^0.7.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/estree-util-value-to-estree": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/estree-util-value-to-estree/-/estree-util-value-to-estree-3.5.0.tgz", @@ -9968,29 +10196,6 @@ "url": "https://github.com/sponsors/remcohaszing" } }, - "node_modules/estree-util-visit": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/estree-util-visit/-/estree-util-visit-2.0.0.tgz", - "integrity": "sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==", - "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0" - } - }, "node_modules/etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", @@ -10228,13 +10433,6 @@ "integrity": "sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA==", "license": "MIT" }, - "node_modules/file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "license": "MIT", - "optional": true - }, "node_modules/filelist": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.6.tgz", @@ -10418,24 +10616,20 @@ } }, "node_modules/framer-motion": { - "version": "12.42.2", - "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.42.2.tgz", - "integrity": "sha512-5XY9luDiu0oHfHBjpDthFMh0ES+122w6p/papSJBweMkO8Sn+PW2QaEgRblQBpWFnuvZS5qvarpt/hO2pjGmnw==", + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-13.3.0.tgz", + "integrity": "sha512-nry9figMPgd/7tTy9zzGRsD+kJ9tjZ74sKJ3jFBa7j6DTBIM04T6eBgneFLXCB0151wychIxsiojPlcG4JxeoA==", "license": "MIT", "dependencies": { - "motion-dom": "^12.42.2", - "motion-utils": "^12.39.0", + "motion-dom": "^13.3.0", + "motion-utils": "^13.3.0", "tslib": "^2.4.0" }, "peerDependencies": { - "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "peerDependenciesMeta": { - "@emotion/is-prop-valid": { - "optional": true - }, "react": { "optional": true }, @@ -10530,33 +10724,35 @@ } }, "node_modules/fumadocs-core": { - "version": "16.12.0", - "resolved": "https://registry.npmjs.org/fumadocs-core/-/fumadocs-core-16.12.0.tgz", - "integrity": "sha512-zWzZg0dwAxwrZkEGUnWRzfQvkIJO+Qr6z5pgW7tkc6J+eWKGd/W0/YFM/kV1lcKZqQYwwNl7wfA2D13F73KNpA==", + "version": "16.15.11", + "resolved": "https://registry.npmjs.org/fumadocs-core/-/fumadocs-core-16.15.11.tgz", + "integrity": "sha512-7pfXOorTguSZz39d4s9KZhTJxlwUJ0mpzwTbkKDQuwfwPyagvFnTCJS3+92VXTu3HW10tShE2o8U2U0DANsNww==", "license": "MIT", "dependencies": { - "@orama/orama": "^3.1.18", + "@fumari/image-size": "^0.1.1", "estree-util-value-to-estree": "^3.5.0", "github-slugger": "^2.0.0", "hast-util-to-estree": "^3.1.3", "hast-util-to-jsx-runtime": "^2.3.6", "mdast-util-mdx": "^3.0.0", "mdast-util-to-markdown": "^2.1.2", - "npm-to-yarn": "3.1.0", + "npm-to-yarn": "3.2.0", "remark": "^15.0.1", "remark-gfm": "^4.0.1", "remark-rehype": "^11.1.2", "scroll-into-view-if-needed": "^3.1.0", - "shiki": "^4.3.1", + "shiki": "^4.4.3", "tinyglobby": "^0.2.17", "unified": "^11.0.5", "unist-util-visit": "^5.1.0", "vfile": "^6.0.3", - "yaml": "^2.9.0" + "yaml": "^2.9.0", + "zbsearch": "^4.0.0" }, "peerDependencies": { "@mdx-js/mdx": "*", "@mixedbread/sdk": "0.x.x", + "@modelcontextprotocol/server": "2.x.x", "@orama/core": "1.x.x", "@oramacloud/client": "2.x.x", "@tanstack/react-router": "1.x.x", @@ -10581,6 +10777,9 @@ "@mixedbread/sdk": { "optional": true }, + "@modelcontextprotocol/server": { + "optional": true + }, "@orama/core": { "optional": true }, @@ -10632,99 +10831,9 @@ } }, "node_modules/fumadocs-core/node_modules/yaml": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", - "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", - "license": "ISC", - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14.6" - }, - "funding": { - "url": "https://github.com/sponsors/eemeli" - } - }, - "node_modules/fumadocs-mdx": { - "version": "15.2.0", - "resolved": "https://registry.npmjs.org/fumadocs-mdx/-/fumadocs-mdx-15.2.0.tgz", - "integrity": "sha512-+yBP8QYw5wA9LF5eVdMhwbP7KT1OF4B/YfC6PZoD2jz0amZi1B+6QHTI6XoRRSTmhWrI4cL5LU1DspW0itk+NA==", - "license": "MIT", - "dependencies": { - "@mdx-js/mdx": "^3.1.1", - "@standard-schema/spec": "^1.1.0", - "chokidar": "^5.0.0", - "esbuild": "^0.28.1", - "estree-util-value-to-estree": "^3.5.0", - "github-slugger": "^2.0.0", - "magic-string": "^0.30.21", - "mdast-util-mdx": "^3.0.0", - "picocolors": "^1.1.1", - "picomatch": "^4.0.5", - "tinyexec": "^1.2.4", - "tinyglobby": "^0.2.17", - "unified": "^11.0.5", - "unist-util-remove-position": "^5.0.0", - "unist-util-visit": "^5.1.0", - "vfile": "^6.0.3", - "yaml": "^2.9.0", - "yuku-analyzer": "^0.6.3", - "zod": "^4.4.3" - }, - "bin": { - "fumadocs-mdx": "bin.js" - }, - "peerDependencies": { - "@fumadocs/satteri": "0.x.x", - "@types/mdast": "*", - "@types/mdx": "*", - "@types/react": "*", - "fumadocs-core": "^16.7.0", - "mdast-util-directive": "*", - "next": "^15.3.0 || ^16.0.0", - "react": "^19.2.0", - "rolldown": "*", - "satteri": "^0.9.4", - "vite": "7.x.x || 8.x.x" - }, - "peerDependenciesMeta": { - "@fumadocs/satteri": { - "optional": true - }, - "@types/mdast": { - "optional": true - }, - "@types/mdx": { - "optional": true - }, - "@types/react": { - "optional": true - }, - "mdast-util-directive": { - "optional": true - }, - "next": { - "optional": true - }, - "react": { - "optional": true - }, - "rolldown": { - "optional": true - }, - "satteri": { - "optional": true - }, - "vite": { - "optional": true - } - } - }, - "node_modules/fumadocs-mdx/node_modules/yaml": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", - "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.1.tgz", + "integrity": "sha512-3NxN8+78OdzbT7C/WjGsyfPAtJaN3FNDsWxv7Y7mcDsT/oOmgW8BpyQQFFBnvZE3j9Y2Sdz1ULFLezL7Eb2yFw==", "license": "ISC", "bin": { "yaml": "bin.mjs" @@ -10737,38 +10846,38 @@ } }, "node_modules/fumadocs-ui": { - "version": "16.12.0", - "resolved": "https://registry.npmjs.org/fumadocs-ui/-/fumadocs-ui-16.12.0.tgz", - "integrity": "sha512-l0MsyUgH4fmk7+XeELRMTuHqEELNKuP5eqXYgpykhieSM4lqRx9KMjRFXdQDmDhKvh2jg/YSDgg4eIAOh5slXA==", + "version": "16.15.11", + "resolved": "https://registry.npmjs.org/fumadocs-ui/-/fumadocs-ui-16.15.11.tgz", + "integrity": "sha512-H+9zEA9yYWZE5/H8NwueU43KgadhQUlSyEjculum97LlsccAoSgbKvMrFJa0mR1oOrUYYXQmDIR8wG/QbKQe3A==", "license": "MIT", "dependencies": { "@fuma-translate/react": "^1.0.2", - "@fumadocs/tailwind": "0.1.1", - "@radix-ui/react-accordion": "^1.2.17", - "@radix-ui/react-collapsible": "^1.1.17", - "@radix-ui/react-dialog": "^1.1.20", - "@radix-ui/react-direction": "^1.1.2", - "@radix-ui/react-navigation-menu": "^1.2.19", - "@radix-ui/react-popover": "^1.1.20", - "@radix-ui/react-presence": "^1.1.8", - "@radix-ui/react-scroll-area": "^1.2.15", - "@radix-ui/react-slot": "^1.3.0", - "@radix-ui/react-tabs": "^1.1.18", + "@fumadocs/tailwind": "0.1.2", + "@radix-ui/react-accordion": "^1.2.20", + "@radix-ui/react-collapsible": "^1.1.20", + "@radix-ui/react-dialog": "^1.1.23", + "@radix-ui/react-direction": "^1.1.4", + "@radix-ui/react-navigation-menu": "^1.2.22", + "@radix-ui/react-popover": "^1.1.23", + "@radix-ui/react-presence": "^1.1.10", + "@radix-ui/react-scroll-area": "^1.2.18", + "@radix-ui/react-slot": "^1.3.3", + "@radix-ui/react-tabs": "^1.1.21", "class-variance-authority": "^0.7.1", - "cnfast": "^0.0.8", - "lucide-react": "^1.25.0", - "motion": "^12.42.2", + "cn": "^0.2.6", + "lucide-react": "^1.43.0", + "motion": "^13.2.0", "next-themes": "^0.4.6", "react-remove-scroll": "^2.7.2", "rehype-raw": "^7.0.0", "scroll-into-view-if-needed": "^3.1.0", - "shiki": "^4.3.1", + "shiki": "^4.4.3", "unist-util-visit": "^5.1.0" }, "peerDependencies": { "@types/mdx": "*", "@types/react": "*", - "fumadocs-core": "16.12.0", + "fumadocs-core": "16.15.11", "next": "16.x.x", "react": "^19.2.0", "react-dom": "^19.2.0", @@ -11742,9 +11851,9 @@ } }, "node_modules/icu-minify": { - "version": "4.13.3", - "resolved": "https://registry.npmjs.org/icu-minify/-/icu-minify-4.13.3.tgz", - "integrity": "sha512-dCbcvYH4YBgR+SgCtnXGIquuc6JkS7e4n+5mmgseQ5z81KJIWbs5ucBjnrE72HFct6Ddr2yWjX6o1j8DT7MI5w==", + "version": "4.14.5", + "resolved": "https://registry.npmjs.org/icu-minify/-/icu-minify-4.14.5.tgz", + "integrity": "sha512-5RQ5fP5inR+VZRTR4KwYBzy217ua4E9lxBT+zFHZcJv0dTOtRs9xXECSIWMQHAfmd0Hq2RXSSP2Gmyw/oQQY6A==", "funding": [ { "type": "individual", @@ -12012,15 +12121,30 @@ } }, "node_modules/intl-messageformat": { - "version": "11.2.12", - "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-11.2.12.tgz", - "integrity": "sha512-KW70Xxfcvy7vV3qODfvShWkFDPMqKDAa4N+hSyVBWGNtVhTUFYaqlD/l88DaYPKiVcPP4rPQ3qnH7i5K82Mg7g==", + "version": "11.2.15", + "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-11.2.15.tgz", + "integrity": "sha512-W4VNytsXyWgW5lvVchmsb9xgA5rSKqoflu3/IQ9UCtB0z4R+Bx9MoEkwFT/+30RCl/KzUoH0QGGe9lppF5SuvQ==", "license": "BSD-3-Clause", "dependencies": { "@formatjs/fast-memoize": "3.1.7", - "@formatjs/icu-messageformat-parser": "3.5.15" + "@formatjs/icu-messageformat-parser": "3.5.18" + } + }, + "node_modules/intl-messageformat/node_modules/@formatjs/icu-messageformat-parser": { + "version": "3.5.18", + "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-3.5.18.tgz", + "integrity": "sha512-wX1efcL8d7K5QapOTRsP/OLTA/kpwe4LwqWyNxDNg5iRs8i9jJbCyxB5P8jc4KOW5oiLzz2DJr+BRY5xMV9+bA==", + "license": "MIT", + "dependencies": { + "@formatjs/icu-skeleton-parser": "2.1.11" } }, + "node_modules/intl-messageformat/node_modules/@formatjs/icu-skeleton-parser": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-2.1.11.tgz", + "integrity": "sha512-j8cUmOJzVgkHuS0QiQ6ga76UIoLOFSAMWhs7aZJztH3aAdCOAE6vpC8KVvFB4cU10ON0y2/5oOVmPJ43s2lTwA==", + "license": "MIT" + }, "node_modules/ioredis": { "version": "5.11.1", "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.11.1.tgz", @@ -12408,9 +12532,9 @@ } }, "node_modules/jose": { - "version": "6.2.4", - "resolved": "https://registry.npmjs.org/jose/-/jose-6.2.4.tgz", - "integrity": "sha512-N8acGzVsQy6M/fjFcxtysNc4Q379TcM5dM/qKkNtsHFji88yANnXTr7BLeP75iPnFwBfQzM/jg2BZ9+HZrHCZA==", + "version": "6.2.12", + "resolved": "https://registry.npmjs.org/jose/-/jose-6.2.12.tgz", + "integrity": "sha512-9NiFmJEex0sy2Dk58j2UGBSHgUs2ypF9eZSu4L6vjOX3Dp96Sw1F3uL+H+D1sx02jZZdzUT0HgvCy59CuvXcWw==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/panva" @@ -12442,9 +12566,9 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-5.2.1.tgz", - "integrity": "sha512-zfLtNfQqxVqq3uaTqSkh4x4hZw3KHobGUA0fJUj4wawW8bsQLTVqpHdXSIzidh7o+4lEW36tANuAGdaFx6Zgnw==", + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-5.4.2.tgz", + "integrity": "sha512-m+aqu+LwO1O6sIopafj8HUVl5aawITwZQe/yHpMCKjaWBaA/d07B/QdMb3529REftiU+RMMHL3Vlsw3hON7vWg==", "funding": [ { "type": "github", @@ -12463,12 +12587,6 @@ "js-yaml": "bin/js-yaml.mjs" } }, - "node_modules/js-yaml/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "license": "Python-2.0" - }, "node_modules/jsesc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", @@ -12656,9 +12774,9 @@ } }, "node_modules/long": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", "license": "Apache-2.0", "optional": true }, @@ -12718,21 +12836,21 @@ "license": "ISC" }, "node_modules/lucide-react": { - "version": "1.26.0", - "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-1.26.0.tgz", - "integrity": "sha512-raglYVR2+VkMfJL158krjVmE+rV5ST2lzA/KQm1FRSjMHT4MnWaegHxoVEpmc2So3nOEhp9oGejJwAPX8MoAjg==", + "version": "1.46.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-1.46.0.tgz", + "integrity": "sha512-Bv+FZXgZPrxc/NCl1e7JJVQFLdiCxYgxNVhqoV7X0p6I8ADJo8DxBnK1auH0fZz4AmqOJ3jgneL4f1i8LJQRAA==", "license": "ISC", "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, - "node_modules/magic-string": { - "version": "0.30.21", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", - "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "node_modules/luxon": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.7.2.tgz", + "integrity": "sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==", "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" + "engines": { + "node": ">=12" } }, "node_modules/make-fetch-happen": { @@ -12845,18 +12963,6 @@ "dev": true, "license": "ISC" }, - "node_modules/markdown-extensions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/markdown-extensions/-/markdown-extensions-2.0.0.tgz", - "integrity": "sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==", - "license": "MIT", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/markdown-table": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", @@ -12867,6 +12973,18 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/marked": { + "version": "18.0.13", + "resolved": "https://registry.npmjs.org/marked/-/marked-18.0.13.tgz", + "integrity": "sha512-xTxVzZsBFwunP6HDmtBkabUQEYArnP7/rMDGmPj9SlrKlQ4i8MdYVow+nJL0eOqwpUqhzBoTBRADGN6uYwPyOw==", + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 20" + } + }, "node_modules/marked-terminal": { "version": "7.3.0", "resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-7.3.0.tgz", @@ -12914,9 +13032,9 @@ } }, "node_modules/material-symbols": { - "version": "0.45.9", - "resolved": "https://registry.npmjs.org/material-symbols/-/material-symbols-0.45.9.tgz", - "integrity": "sha512-CuNJwHm/c13L2NDGvap4k90iFBZFoMQrjBU+GHO/9bh9sUOe5tm3WHFPLa3BEWukMw6dAxwu5PvtlfWh3NppYA==", + "version": "0.46.0", + "resolved": "https://registry.npmjs.org/material-symbols/-/material-symbols-0.46.0.tgz", + "integrity": "sha512-YxmTXwOhLOI6EupAwFfxFERbaDe61dG/tveOSy2HecndGKqvJ74WqXrrXLNWpIGDkk6TDpieuQPDS+hA7+z3Ig==", "license": "Apache-2.0" }, "node_modules/math-intrinsics": { @@ -13411,75 +13529,7 @@ "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-footnote": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", - "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-strikethrough": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", - "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-table": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz", - "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==", - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-tagfilter": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", - "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", - "license": "MIT", - "dependencies": { + "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" }, "funding": { @@ -13487,15 +13537,18 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/micromark-extension-gfm-task-list-item": { + "node_modules/micromark-extension-gfm-footnote": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", - "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", "license": "MIT", "dependencies": { "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" }, @@ -13504,60 +13557,34 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/micromark-extension-mdx-expression": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.1.tgz", - "integrity": "sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], + "node_modules/micromark-extension-gfm-strikethrough": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", + "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", "license": "MIT", "dependencies": { - "@types/estree": "^1.0.0", "devlop": "^1.0.0", - "micromark-factory-mdx-expression": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-extension-mdx-jsx": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-3.0.2.tgz", - "integrity": "sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "devlop": "^1.0.0", - "estree-util-is-identifier-name": "^3.0.0", - "micromark-factory-mdx-expression": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-events-to-acorn": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "vfile-message": "^4.0.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" } }, - "node_modules/micromark-extension-mdx-md": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-mdx-md/-/micromark-extension-mdx-md-2.0.0.tgz", - "integrity": "sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==", + "node_modules/micromark-extension-gfm-table": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.2.tgz", + "integrity": "sha512-pRzm4kDTu0MjlmBkxmS9yYhw60nncfcEwu9NNdPFSQEFXS95ZKyIIyTSHu/o3ReBUrLKYEq+7YaXCRn/bPB4MA==", "license": "MIT", "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" }, "funding": { @@ -13565,19 +13592,12 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/micromark-extension-mdxjs": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs/-/micromark-extension-mdxjs-3.0.0.tgz", - "integrity": "sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==", + "node_modules/micromark-extension-gfm-tagfilter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", + "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", "license": "MIT", "dependencies": { - "acorn": "^8.0.0", - "acorn-jsx": "^5.0.0", - "micromark-extension-mdx-expression": "^3.0.0", - "micromark-extension-mdx-jsx": "^3.0.0", - "micromark-extension-mdx-md": "^2.0.0", - "micromark-extension-mdxjs-esm": "^3.0.0", - "micromark-util-combine-extensions": "^2.0.0", "micromark-util-types": "^2.0.0" }, "funding": { @@ -13585,21 +13605,17 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/micromark-extension-mdxjs-esm": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-3.0.0.tgz", - "integrity": "sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==", + "node_modules/micromark-extension-gfm-task-list-item": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", + "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", "license": "MIT", "dependencies": { - "@types/estree": "^1.0.0", "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", - "micromark-util-events-to-acorn": "^2.0.0", "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unist-util-position-from-estree": "^2.0.0", - "vfile-message": "^4.0.0" + "micromark-util-types": "^2.0.0" }, "funding": { "type": "opencollective", @@ -13649,33 +13665,6 @@ "micromark-util-types": "^2.0.0" } }, - "node_modules/micromark-factory-mdx-expression": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-2.0.3.tgz", - "integrity": "sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "devlop": "^1.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-events-to-acorn": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unist-util-position-from-estree": "^2.0.0", - "vfile-message": "^4.0.0" - } - }, "node_modules/micromark-factory-space": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", @@ -13877,31 +13866,6 @@ ], "license": "MIT" }, - "node_modules/micromark-util-events-to-acorn": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-2.0.3.tgz", - "integrity": "sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "@types/unist": "^3.0.0", - "devlop": "^1.0.0", - "estree-util-visit": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "vfile-message": "^4.0.0" - } - }, "node_modules/micromark-util-html-tag-name": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", @@ -14379,19 +14343,19 @@ "optional": true }, "node_modules/monaco-editor": { - "version": "0.55.1", - "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.55.1.tgz", - "integrity": "sha512-jz4x+TJNFHwHtwuV9vA9rMujcZRb0CEilTEwG2rRSpe/A7Jdkuj8xPKttCgOh+v/lkHy7HsZ64oj+q3xoAFl9A==", + "version": "0.56.0", + "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.56.0.tgz", + "integrity": "sha512-sXboRm3BeBeLm938eaiyLMe0OxzfXIlZvbv4ir/jVgQy1zDhWjgmny0WoN45fuDKhCCQsYMbBJrv/A6jd8aCUg==", "license": "MIT", "dependencies": { - "dompurify": "3.2.7", + "dompurify": "3.4.8", "marked": "14.0.0" } }, "node_modules/monaco-editor/node_modules/dompurify": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.7.tgz", - "integrity": "sha512-WhL/YuveyGXJaerVlMYGWhvQswa7myDG17P7Vu65EWC05o8vfeNbvNf4d/BOvH99+ZW+LlQsc1GDKMa1vNK6dw==", + "version": "3.4.8", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.8.tgz", + "integrity": "sha512-yb1cEmaOum7wFvOCSQxyfgVlv5D47Rc30iZWoMpbDIWTnJ6grDDQyu2KFJzB2k7u0pMuJcQ1zphH//fFnw2tjQ==", "license": "(MPL-2.0 OR Apache-2.0)", "optionalDependencies": { "@types/trusted-types": "^2.0.7" @@ -14410,23 +14374,19 @@ } }, "node_modules/motion": { - "version": "12.42.2", - "resolved": "https://registry.npmjs.org/motion/-/motion-12.42.2.tgz", - "integrity": "sha512-Atvv11yUKIid41cVrRBDVX5m8tF8kNpExRSlbpt6APClhDjtwQssgFHhQzejxw7/7YYbjHSPKBVbHo05BuJT5Q==", + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/motion/-/motion-13.3.0.tgz", + "integrity": "sha512-WHLzq1EQCoJO9S+HSDl9WlJYUpCsSAGYPoI0R4qO9ZScx7uLhpYzpoF8iobYvG248idzkl35pAShfWftEUjsdQ==", "license": "MIT", "dependencies": { - "framer-motion": "^12.42.2", + "framer-motion": "^13.3.0", "tslib": "^2.4.0" }, "peerDependencies": { - "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "peerDependenciesMeta": { - "@emotion/is-prop-valid": { - "optional": true - }, "react": { "optional": true }, @@ -14436,18 +14396,18 @@ } }, "node_modules/motion-dom": { - "version": "12.42.2", - "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.42.2.tgz", - "integrity": "sha512-5gIMWLp/PycBtJRJWRgjxke5n8dlvkSn2DrYW+tr3XcqAZY1xZh6BJyooJXCM8wdfM7wfMjkBJNLge1CKPUIRA==", + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-13.3.0.tgz", + "integrity": "sha512-AmAnB6pHdZ1vHGzWzuzteG6Q3j1lHKeX/lbST6jGlgm0cjvLUgaCk1xhOuPMOy5SgovN6wnnUdwFrkcsus7Ftg==", "license": "MIT", "dependencies": { - "motion-utils": "^12.39.0" + "motion-utils": "^13.3.0" } }, "node_modules/motion-utils": { - "version": "12.39.0", - "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.39.0.tgz", - "integrity": "sha512-8nadJAJjTtqRkmRF36FoJTrywK9nnFmnPwnSMyxaOCU7GDjN9RTMJIxx9De8ErM+vpPhMccr/6fo5WciyQLnMQ==", + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-13.3.0.tgz", + "integrity": "sha512-sgSschQp7EseHInIlR7hBbMuvet3RA0bs28KPZAXJcGKGdxHGvh1ogpYDilY3bOMtl73EqPNmp75sAKHYPU5sg==", "license": "MIT" }, "node_modules/ms": { @@ -14468,9 +14428,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.16", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.16.tgz", - "integrity": "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==", + "version": "3.3.19", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.19.tgz", + "integrity": "sha512-Y2tUNy4ouw6tq5oDSKeQYGOyhkUBhNOcGV/02KC+6kd9eDGqdZd++mjMiIDilrBYvjEnCYvVtsuHCuP+okSfug==", "funding": [ { "type": "github", @@ -14502,16 +14462,16 @@ } }, "node_modules/next": { - "version": "16.2.11", - "resolved": "https://registry.npmjs.org/next/-/next-16.2.11.tgz", - "integrity": "sha512-B339zaqbyK8cmxhoAvLrcwoabwCP1wz21zSzfqxqXAemTu2BXnH7tQnfcglKv1vnMUIDBc+Hth7XODQriTZiRQ==", + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/next/-/next-16.3.1.tgz", + "integrity": "sha512-hsAp0i7Rh+/dhe7DGIeN2YlpLM1DP4MNxti9EtDMtqcO612X81MvvEj388/oTce9U1EcEIOWDlGq0zRwrBKvuA==", "license": "MIT", "dependencies": { - "@next/env": "16.2.11", - "@swc/helpers": "0.5.15", + "@next/env": "16.3.1", + "@swc/helpers": "0.5.23", "baseline-browser-mapping": "^2.9.19", "caniuse-lite": "^1.0.30001579", - "postcss": "8.4.31", + "postcss": "8.5.23", "styled-jsx": "5.1.6" }, "bin": { @@ -14521,15 +14481,15 @@ "node": ">=20.9.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "16.2.11", - "@next/swc-darwin-x64": "16.2.11", - "@next/swc-linux-arm64-gnu": "16.2.11", - "@next/swc-linux-arm64-musl": "16.2.11", - "@next/swc-linux-x64-gnu": "16.2.11", - "@next/swc-linux-x64-musl": "16.2.11", - "@next/swc-win32-arm64-msvc": "16.2.11", - "@next/swc-win32-x64-msvc": "16.2.11", - "sharp": "^0.34.5" + "@next/swc-darwin-arm64": "16.3.1", + "@next/swc-darwin-x64": "16.3.1", + "@next/swc-linux-arm64-gnu": "16.3.1", + "@next/swc-linux-arm64-musl": "16.3.1", + "@next/swc-linux-x64-gnu": "16.3.1", + "@next/swc-linux-x64-musl": "16.3.1", + "@next/swc-win32-arm64-msvc": "16.3.1", + "@next/swc-win32-x64-msvc": "16.3.1", + "sharp": "^0.35.3" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", @@ -14555,9 +14515,9 @@ } }, "node_modules/next-intl": { - "version": "4.13.3", - "resolved": "https://registry.npmjs.org/next-intl/-/next-intl-4.13.3.tgz", - "integrity": "sha512-+bAjmPLsRFG/YAN1ged7wVCbuYvYjEW06ApBRdM7VbtNfXYN1iBFNh28Bi1sX5xGSFvAsGCBC1K2Zjtvn1AMvQ==", + "version": "4.14.5", + "resolved": "https://registry.npmjs.org/next-intl/-/next-intl-4.14.5.tgz", + "integrity": "sha512-9sPJh5ITJbP28HZ5obuFAMC4RwW/mhEvHiGVHXPWL0uRbF2RrjHWz8PcUmLaH2oca79ak2ayQz+uRSALZN9xSw==", "funding": [ { "type": "individual", @@ -14566,29 +14526,26 @@ ], "license": "MIT", "dependencies": { + "@eloqnt/config": "^0.1.0", + "@eloqnt/format-json": "^0.1.0", + "@eloqnt/format-po": "^0.1.0", "@formatjs/intl-localematcher": "^0.8.1", "@parcel/watcher": "^2.4.1", - "@swc/core": "^1.15.2", - "icu-minify": "^4.13.3", + "@swc/core": "~1.16.0", + "icu-minify": "^4.14.5", "negotiator": "^1.0.0", - "next-intl-swc-plugin-extractor": "^4.13.3", - "po-parser": "^2.1.1", - "use-intl": "^4.13.3" + "next-intl-swc-plugin-extractor": "4.14.5", + "use-intl": "^4.14.5" }, "peerDependencies": { "next": "^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } } }, "node_modules/next-intl-swc-plugin-extractor": { - "version": "4.13.3", - "resolved": "https://registry.npmjs.org/next-intl-swc-plugin-extractor/-/next-intl-swc-plugin-extractor-4.13.3.tgz", - "integrity": "sha512-Oy86w/VRwqOu6sHEXwthEGhgnQszS79e47i3Kkzv4r+Yfz9ilZMSen8Sp8vtAwuc1nAZPrN13IbsLC5jmc9fVQ==", + "version": "4.14.5", + "resolved": "https://registry.npmjs.org/next-intl-swc-plugin-extractor/-/next-intl-swc-plugin-extractor-4.14.5.tgz", + "integrity": "sha512-dbpsjHmwbqn795z7eDI7HHL+jxyvZ5CNF40sbGx+nkjM4pCs7HdTzGQnQ84mjF/WWZa/w9pJ6M74prh+3vnbGQ==", "license": "MIT" }, "node_modules/next-themes": { @@ -14601,15 +14558,6 @@ "react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc" } }, - "node_modules/next/node_modules/@swc/helpers": { - "version": "0.5.15", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", - "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.8.0" - } - }, "node_modules/node-abi": { "version": "3.94.0", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.94.0.tgz", @@ -14655,27 +14603,6 @@ "node": ">=18" } }, - "node_modules/node-fetch": { - "version": "2.6.13", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.13.tgz", - "integrity": "sha512-StxNAxh15zr77QvvkmveSQ8uCQ4+v5FkvNTj0OESmiHu+VRi/gXArXtkWMElOsOUNLtUEvI4yS+rdtOHZTwlQA==", - "license": "MIT", - "optional": true, - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, "node_modules/node-gyp": { "version": "9.4.1", "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.1.tgz", @@ -14811,9 +14738,9 @@ } }, "node_modules/npm-to-yarn": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/npm-to-yarn/-/npm-to-yarn-3.1.0.tgz", - "integrity": "sha512-9gNsO/JB3LeWOZXBX09cKMsCPwVcu1ExIf+GUuTN9G+0zZvLIK0nU9+lE9jue3MSKAxPdrh0rO072mWNvciqeQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/npm-to-yarn/-/npm-to-yarn-3.2.0.tgz", + "integrity": "sha512-K1HmQeZT2HrjpsR6KgqbN2FAXL2NrJJmNUSD9ck7HGTVu1JKXox8n9SB+tjbU8m8JGLF4OscrroPepew/L7/Xw==", "license": "MIT", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -14871,9 +14798,9 @@ } }, "node_modules/omniglyph": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/omniglyph/-/omniglyph-1.3.1.tgz", - "integrity": "sha512-6QnZCoXYczjsPN2x+XpbimimjO6kCoSZUzsdSvoKjtw28U1U724VgLICBNaLX4FFs5jd7SrYNNs9Aee2iIkcoA==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/omniglyph/-/omniglyph-1.4.0.tgz", + "integrity": "sha512-4zAqDW9pBb2i+fiGOVLIKbdecZeo55UmKQoLku1apxo3TSA4gfqcMo2MqQpal1VicckUwTbexFLasW7qngXUHA==", "license": "MIT", "dependencies": { "gpt-tokenizer": "^3.4.0" @@ -14886,118 +14813,111 @@ } }, "node_modules/omniroute": { - "version": "3.8.48", - "resolved": "https://registry.npmjs.org/omniroute/-/omniroute-3.8.48.tgz", - "integrity": "sha512-nCewYpHDJATK0bAiXXakwLgoA6CfdBorS9FNPaAOInCeAydhhwPfkWGtf8VbyI/06S/nKT1IyOqRkMQDgU3NVA==", + "version": "3.8.50", + "resolved": "https://registry.npmjs.org/omniroute/-/omniroute-3.8.50.tgz", + "integrity": "sha512-qK6REDWQYGh8lwGwDgFMsBqAMXnxIePudr8cSuSYeB9iIlywNhDJxHKt6Cwa31lPci8jXE5bbvl+az0lvyt0Mg==", "hasInstallScript": true, "license": "MIT", "workspaces": [ - "open-sse" + "open-sse", + "packages/browser-pool" ], "dependencies": { - "@aws-sdk/client-bedrock-runtime": "^3.1073.0", + "@aws-sdk/client-bedrock-runtime": "^3.1112.0", "@dnd-kit/core": "^6.3.1", "@dnd-kit/sortable": "^10.0.0", "@dnd-kit/utilities": "^3.2.2", - "@lobehub/icons": "^5.8.0", + "@lobehub/icons": "^5.16.0", "@modelcontextprotocol/sdk": "^1.29.0", "@monaco-editor/react": "^4.7.0", "@ngrok/ngrok": "^1.7.0", "@swc/helpers": "0.5.23", - "@toon-format/toon": "^2.3.0", + "@toon-format/toon": "^4.1.1", "@types/mdx": "^2.0.13", - "@xyflow/react": "^12.11.1", - "axios": "^1.16.1", + "@xyflow/react": "^12.11.3", + "axios": "^1.19.0", "bcryptjs": "^3.0.3", "bottleneck": "^2.19.5", "clsx": "^2.1.1", "commander": "^15.0.0", - "csv-stringify": "^6.7.0", - "dompurify": "^3.4.11", + "cron-parser": "^5.10.0", + "csv-stringify": "^6.8.3", + "dompurify": "^3.4.13", "express": "^5.2.1", "fetch-socks": "^1.3.3", "fflate": "^0.8.3", - "fumadocs-core": "^16.10.5", - "fumadocs-mdx": "^15.0.7", - "fumadocs-ui": "^16.10.5", + "fumadocs-core": "^16.14.4", + "fumadocs-ui": "^16.14.4", "http-proxy-middleware": "^4.0.0", "https-proxy-agent": "^9.0.0", "ink": "^7.0.3", "ink-spinner": "^5.0.0", "ink-text-input": "^6.0.0", "ioredis": "^5.10.1", - "jose": "^6.2.3", - "js-yaml": "^5.0.0", + "jose": "^6.2.9", + "js-yaml": "^5.3.0", "jsonc-parser": "^3.3.1", "lowdb": "^7.0.1", "lucide-react": "^1.21.0", - "marked": "^18.0.4", + "marked": "^18.0.9", "marked-terminal": "^7.3.0", - "material-symbols": "^0.45.2", + "material-symbols": "^0.46.0", "mermaid": "^11.15.0", - "monaco-editor": "^0.55.1", - "next": "^16.2.6", - "next-intl": "^4.12.0", + "monaco-editor": "^0.56.0", + "next": "16.3.1", + "next-intl": "^4.13.7", "next-themes": "^0.4.6", "node-machine-id": "^1.1.12", - "omniglyph": "^1.0.2", - "open": "^11.0.0", + "omniglyph": "^1.4.0", + "open": "^11.0.1", "ora": "^9.4.1", "parse5": "^8.0.1", "pino": "^10.3.1", "pino-abstract-transport": "^3.0.0", "pino-pretty": "^13.1.3", - "playwright": "1.61.1", - "react": "19.2.7", - "react-dom": "19.2.7", + "playwright": "1.62.1", + "react": "19.2.8", + "react-dom": "19.2.8", "react-is": "^19.2.6", "react-markdown": "^10.1.0", "react-reconciler": "^0.33.0", "recharts": "^3.8.1", "safe-regex": "^2.1.1", "selfsigned": "^5.5.0", + "sharp": "^0.35.3", + "smol-toml": "1.8.0", "socks": "^2.8.7", - "sql.js": "^1.14.1", - "sqlite-vec": "^0.1.9", + "sql.js": "^1.14.2", "tailwind-merge": "^3.6.0", - "tsx": "^4.23.0", - "undici": "^8.3.0", + "tsx": "^4.23.12", + "turndown": "7.2.4", + "turndown-plugin-gfm": "1.0.2", + "undici": "^8.10.0", "update-notifier": "^7.3.1", "uuid": "^14.0.0", - "ws": "^8.18.0", + "ws": "^8.21.3", "xxhash-wasm": "^1.1.0", "yazl": "^3.3.1", "zod": "^4.4.3", - "zustand": "^5.0.13" + "zustand": "^5.0.15" }, "bin": { "omniroute": "bin/omniroute.mjs", "omniroute-reset-password": "bin/reset-password.mjs" }, "engines": { - "node": ">=22.0.0 <23 || >=24.0.0 <27" + "node": ">=22.22.2 <23 || >=24.0.0 <27" }, "optionalDependencies": { - "@atjsh/llmlingua-2": "2.0.3", - "@huggingface/transformers": "3.5.2", - "@tensorflow/tfjs": "4.22.0", - "better-sqlite3": "^12.10.0", + "@atjsh/llmlingua-2": "3.0.0", + "@huggingface/transformers": "^4.2.0", + "better-sqlite3": "^13.0.2", "js-tiktoken": "^1.0.20", "keytar": "^7.9.0", + "onnxruntime-node": "1.24.3", + "sqlite-vec": "^0.1.9", "tls-client-node": "^0.2.0", - "wreq-js": "^2.3.1" - } - }, - "node_modules/omniroute/node_modules/marked": { - "version": "18.0.7", - "resolved": "https://registry.npmjs.org/marked/-/marked-18.0.7.tgz", - "integrity": "sha512-iDVQ5ldaiKXn6b2JroX5kgRfmwgqolW7NpaEzTl1k/2Zh1njIEN9yniyLV/mOvWwtsE8OGgkjsCYvijuPk1dtA==", - "license": "MIT", - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 20" + "wreq-js": "^3.0.0" } }, "node_modules/on-exit-leak-free": { @@ -15063,16 +14983,16 @@ } }, "node_modules/onnxruntime-common": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/onnxruntime-common/-/onnxruntime-common-1.21.0.tgz", - "integrity": "sha512-Q632iLLrtCAVOTO65dh2+mNbQir/QNTVBG3h/QdZBpns7mZ0RYbLRBgGABPbpU9351AgYy7SJf1WaeVwMrBFPQ==", + "version": "1.24.3", + "resolved": "https://registry.npmjs.org/onnxruntime-common/-/onnxruntime-common-1.24.3.tgz", + "integrity": "sha512-GeuPZO6U/LBJXvwdaqHbuUmoXiEdeCjWi/EG7Y1HNnDwJYuk6WUbNXpF6luSUY8yASul3cmUlLGrCCL1ZgVXqA==", "license": "MIT", "optional": true }, "node_modules/onnxruntime-node": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/onnxruntime-node/-/onnxruntime-node-1.21.0.tgz", - "integrity": "sha512-NeaCX6WW2L8cRCSqy3bInlo5ojjQqu2fD3D+9W5qb5irwxhEyWKXeH2vZ8W9r6VxaMPUan+4/7NDwZMtouZxEw==", + "version": "1.24.3", + "resolved": "https://registry.npmjs.org/onnxruntime-node/-/onnxruntime-node-1.24.3.tgz", + "integrity": "sha512-JH7+czbc8ALA819vlTgcV+Q214/+VjGeBHDjX81+ZCD0PCVCIFGFNtT0V4sXG/1JXypKPgScQcB3ij/hk3YnTg==", "hasInstallScript": true, "license": "MIT", "optional": true, @@ -15082,52 +15002,45 @@ "linux" ], "dependencies": { + "adm-zip": "^0.5.16", "global-agent": "^3.0.0", - "onnxruntime-common": "1.21.0", - "tar": "^7.0.1" + "onnxruntime-common": "1.24.3" } }, "node_modules/onnxruntime-web": { - "version": "1.22.0-dev.20250409-89f8206ba4", - "resolved": "https://registry.npmjs.org/onnxruntime-web/-/onnxruntime-web-1.22.0-dev.20250409-89f8206ba4.tgz", - "integrity": "sha512-0uS76OPgH0hWCPrFKlL8kYVV7ckM7t/36HfbgoFw6Nd0CZVVbQC4PkrR8mBX8LtNUFZO25IQBqV2Hx2ho3FlbQ==", + "version": "1.26.0-dev.20260416-b7804b056c", + "resolved": "https://registry.npmjs.org/onnxruntime-web/-/onnxruntime-web-1.26.0-dev.20260416-b7804b056c.tgz", + "integrity": "sha512-MD6Ss4GSpQBo6zqoJzyT9LRbKYs7x/JVN23FT24EcEvlqF4VuzPOeH6X38orZPKHQDbprn7K+SBpu0/mj2CQiw==", "license": "MIT", "optional": true, "dependencies": { "flatbuffers": "^25.1.24", "guid-typescript": "^1.0.9", "long": "^5.2.3", - "onnxruntime-common": "1.22.0-dev.20250409-89f8206ba4", + "onnxruntime-common": "1.24.0-dev.20251116-b39e144322", "platform": "^1.3.6", "protobufjs": "^7.2.4" } }, - "node_modules/onnxruntime-web/node_modules/long": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", - "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", - "license": "Apache-2.0", - "optional": true - }, "node_modules/onnxruntime-web/node_modules/onnxruntime-common": { - "version": "1.22.0-dev.20250409-89f8206ba4", - "resolved": "https://registry.npmjs.org/onnxruntime-common/-/onnxruntime-common-1.22.0-dev.20250409-89f8206ba4.tgz", - "integrity": "sha512-vDJMkfCfb0b1A836rgHj+ORuZf4B4+cc2bASQtpeoJLueuFc5DuYwjIZUBrSvx/fO5IrLjLz+oTrB3pcGlhovQ==", + "version": "1.24.0-dev.20251116-b39e144322", + "resolved": "https://registry.npmjs.org/onnxruntime-common/-/onnxruntime-common-1.24.0-dev.20251116-b39e144322.tgz", + "integrity": "sha512-BOoomdHYmNRL5r4iQ4bMvsl2t0/hzVQ3OM3PHD0gxeXu1PmggqBv3puZicEUVOA3AtHHYmqZtjMj9FOfGrATTw==", "license": "MIT", "optional": true }, "node_modules/open": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/open/-/open-11.0.0.tgz", - "integrity": "sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw==", + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/open/-/open-11.0.4.tgz", + "integrity": "sha512-++Zlftm0kVLPmzC06t6epuWmcRMDbI4z5P3NNX979WA/k23+NtSOynEGzsVfZwguKw2mi5umVgnBlJQMwRz4Pg==", "license": "MIT", "dependencies": { - "default-browser": "^5.4.0", + "default-browser": "^5.5.1", "define-lazy-prop": "^3.0.0", "is-in-ssh": "^1.0.0", "is-inside-container": "^1.0.0", - "powershell-utils": "^0.1.0", - "wsl-utils": "^0.3.0" + "powershell-utils": "^0.2.1", + "wsl-utils": "^1.0.0" }, "engines": { "node": ">=20" @@ -15136,6 +15049,184 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/opencode-ai": { + "version": "1.18.31", + "resolved": "https://registry.npmjs.org/opencode-ai/-/opencode-ai-1.18.31.tgz", + "integrity": "sha512-J95feefeWwtIaw3irx76WjzWcgQXxmuHmDVphvs5ep9X30fBJ6T6bFhw50i9Kx50MG/xPn5w2pafXIfNtdry9w==", + "cpu": [ + "arm64", + "x64" + ], + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin", + "linux", + "win32" + ], + "bin": { + "opencode": "bin/opencode.exe" + }, + "optionalDependencies": { + "opencode-darwin-arm64": "1.18.31", + "opencode-darwin-x64": "1.18.31", + "opencode-darwin-x64-baseline": "1.18.31", + "opencode-linux-arm64": "1.18.31", + "opencode-linux-arm64-musl": "1.18.31", + "opencode-linux-x64": "1.18.31", + "opencode-linux-x64-baseline": "1.18.31", + "opencode-linux-x64-baseline-musl": "1.18.31", + "opencode-linux-x64-musl": "1.18.31", + "opencode-windows-arm64": "1.18.31", + "opencode-windows-x64": "1.18.31", + "opencode-windows-x64-baseline": "1.18.31" + } + }, + "node_modules/opencode-darwin-arm64": { + "version": "1.18.31", + "resolved": "https://registry.npmjs.org/opencode-darwin-arm64/-/opencode-darwin-arm64-1.18.31.tgz", + "integrity": "sha512-IN642oFENleWVDNqMnXi8NQLsZnA8hMswJ6X+GWz+CfBFuCpotjDb5OHgE2HBdC6r5wjG6v0mATb+Mn8xXCp1A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/opencode-darwin-x64": { + "version": "1.18.31", + "resolved": "https://registry.npmjs.org/opencode-darwin-x64/-/opencode-darwin-x64-1.18.31.tgz", + "integrity": "sha512-xrw512dou9Drxs/1yH4CHEt/kvrSl8j1Ulez0wTOsW0lWZaATJMnlfHBjagWzv+QWIC4nz/cBgYzjn3JvxS7zQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/opencode-darwin-x64-baseline": { + "version": "1.18.31", + "resolved": "https://registry.npmjs.org/opencode-darwin-x64-baseline/-/opencode-darwin-x64-baseline-1.18.31.tgz", + "integrity": "sha512-4/4UMyPhsIeHln3AT3bxBvrWC+cmbOcdGOeBfoeOQIWcNZ3ycSvFnoJdLX969p9CtR6oNtroaQoNKZHgzSqg6A==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/opencode-linux-arm64": { + "version": "1.18.31", + "resolved": "https://registry.npmjs.org/opencode-linux-arm64/-/opencode-linux-arm64-1.18.31.tgz", + "integrity": "sha512-tLTZlOeWz4u48WQWg7PhKTn4gIXPHf7xaiWSHcmci1O3qKXEDLv/TaMzmqIuMChdwtflu2PSNIC00W+Hij/IkA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/opencode-linux-arm64-musl": { + "version": "1.18.31", + "resolved": "https://registry.npmjs.org/opencode-linux-arm64-musl/-/opencode-linux-arm64-musl-1.18.31.tgz", + "integrity": "sha512-qeEg7HsYupDeLkFqr+QNIgcE4kVRPycb/7ymyYUffSg+z2A6fU065pvU6uaZ+LjIzdJaZHUe1wDQvrSP/EJAqg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/opencode-linux-x64": { + "version": "1.18.31", + "resolved": "https://registry.npmjs.org/opencode-linux-x64/-/opencode-linux-x64-1.18.31.tgz", + "integrity": "sha512-gTJ5nGNq+KJblwmeusEdz8YFwvkV7a3xTOV9EKKEmsv0Lkbajq/oQO9jEC0sMiS66mjHDOrhLgIUxSVqfLBM8g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/opencode-linux-x64-baseline": { + "version": "1.18.31", + "resolved": "https://registry.npmjs.org/opencode-linux-x64-baseline/-/opencode-linux-x64-baseline-1.18.31.tgz", + "integrity": "sha512-T/hyCHb7gSCuJzLDXs8YfEhjelUes2zkWFPTGEdBPqV/eKrKbEo9U1YdA/WvntjXv0I6k+blZEID54QIcF7Djw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/opencode-linux-x64-baseline-musl": { + "version": "1.18.31", + "resolved": "https://registry.npmjs.org/opencode-linux-x64-baseline-musl/-/opencode-linux-x64-baseline-musl-1.18.31.tgz", + "integrity": "sha512-gZ9TkeoIkckNZjDRreHj0sQk91uRQTgeuMCIZgSKewHN1fq/jjQHMzSAI0HevPEov9O2cDRRzPBF4cppzc+AYg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/opencode-linux-x64-musl": { + "version": "1.18.31", + "resolved": "https://registry.npmjs.org/opencode-linux-x64-musl/-/opencode-linux-x64-musl-1.18.31.tgz", + "integrity": "sha512-TxKfcJII53MZ17NSrJ0p51wx0dJtZrX8By60N5O5/M+eP0oO4jCXKIkdBpP/Bku44gm8QZkTNLBWpPc2OTJweg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/opencode-windows-arm64": { + "version": "1.18.31", + "resolved": "https://registry.npmjs.org/opencode-windows-arm64/-/opencode-windows-arm64-1.18.31.tgz", + "integrity": "sha512-K+Dh5r5yLQJ6Maeo1+JhQr27Un6lzUIWEp3LGoeXSfLkcSqi7ueTecGbg7HAbtEIY5a9j3yNCS3//AjgTcZa+w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/opencode-windows-x64": { + "version": "1.18.31", + "resolved": "https://registry.npmjs.org/opencode-windows-x64/-/opencode-windows-x64-1.18.31.tgz", + "integrity": "sha512-1Za7uKeGLonNUkUIGHD7xfV5omi7ju/7z2WYfS5YvDLTr1iU/W1PPVHzHXiwiyV4gMxsWGwHHLubWdH99D7pSA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/opencode-windows-x64-baseline": { + "version": "1.18.31", + "resolved": "https://registry.npmjs.org/opencode-windows-x64-baseline/-/opencode-windows-x64-baseline-1.18.31.tgz", + "integrity": "sha512-wz5K8SpL+GTKez4BpYX1AbhRwBY7AVt+95ijWZrow84ibLTDoZ1skEsN5UUcQJ8LYeC+o1Vq0xi4A5kLGfvQ0w==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/ora": { "version": "9.4.1", "resolved": "https://registry.npmjs.org/ora/-/ora-9.4.1.tgz", @@ -15516,9 +15607,9 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", - "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz", + "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", "license": "MIT", "engines": { "node": ">=12" @@ -15622,33 +15713,33 @@ "optional": true }, "node_modules/playwright": { - "version": "1.61.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.61.1.tgz", - "integrity": "sha512-DWnY5o3YbLWK4GovuAVwpqL+1VwGNdUGrRr++8j8PtQQzvAVZUIMjKQ90fY689sEJZJBbZVw1rXaOKSTitkzPQ==", + "version": "1.62.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.62.1.tgz", + "integrity": "sha512-0M+L3LAD8/nm554LOla9Ayx0j0tmFZ0FBcoQ7F1VuVHpM/XpiC8RcDzBQB8W5+hA8L22THxELzeF+2WcUzvcLg==", "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.61.1" + "playwright-core": "1.62.1" }, "bin": { "playwright": "cli.js" }, "engines": { - "node": ">=18" + "node": ">=20" }, "optionalDependencies": { "fsevents": "2.3.2" } }, "node_modules/playwright-core": { - "version": "1.61.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.61.1.tgz", - "integrity": "sha512-h7Qlt6m4REp25qvIdvbDtVmD4LqVXfpRxhORv9L0jzETM05p4fuPJ3dKyuSXQxDSbXnmS79HAgi9589lGSpLkg==", + "version": "1.62.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.62.1.tgz", + "integrity": "sha512-wPYSwEBJY9GHraISXqyqtx0na0LpO3XEX7jNDhntbex7tzUS7kLnZsOlFruFJB4Hi/rhDMjXGqHewDZ68nYZVw==", "license": "Apache-2.0", "bin": { "playwright-core": "cli.js" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/plist": { @@ -15667,9 +15758,9 @@ } }, "node_modules/po-parser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/po-parser/-/po-parser-2.1.1.tgz", - "integrity": "sha512-ECF4zHLbUItpUgE3OTtLKlPjeBN+fKEczj2zYjDfCGOzicNs0GK3Vg2IoAYwx7LH/XYw43fZQP6xnZ4TkNxSLQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/po-parser/-/po-parser-2.2.0.tgz", + "integrity": "sha512-NdTrKgh0oO7+y+RFX8KKhOB438x/j94UGXEFzl/7pHH0JjWSn42iJ9tgmPksIO6n1JKDHmNDcejPJfKspljB9g==", "license": "MIT" }, "node_modules/points-on-curve": { @@ -15701,9 +15792,9 @@ } }, "node_modules/postcss": { - "version": "8.4.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", - "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "version": "8.5.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.23.tgz", + "integrity": "sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==", "funding": [ { "type": "opencollective", @@ -15720,18 +15811,18 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "nanoid": "^3.3.16", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12 || >=14" } }, "node_modules/powershell-utils": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/powershell-utils/-/powershell-utils-0.1.0.tgz", - "integrity": "sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A==", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/powershell-utils/-/powershell-utils-0.2.1.tgz", + "integrity": "sha512-C+y9x90UElAddDZmV4qOx9W53B61PO7cIqWz2dQsWlwswuq4mr8NEwytdGKboYbQlGZ3awrkTeNvcZiZNHnQ8A==", "license": "MIT", "engines": { "node": ">=20" @@ -15832,9 +15923,9 @@ "license": "ISC" }, "node_modules/protobufjs": { - "version": "7.6.5", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.5.tgz", - "integrity": "sha512-/FPD0nUc9jH6rfFjji9IBqOz4pcSE3CsT1m7Ep6Mdb0LxSUMj8hgl6GomOvZzpNpAqqGaXA0P3VSrZLFzIhQrw==", + "version": "7.6.6", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.6.tgz", + "integrity": "sha512-dYDWdjSl5RNb7SgPxGQcRU+GtvP7s2fpkrY0r432PcOIaZ0/rBcxEZnQN67iJhFuQiVw754JDoPruPCNdGsbjg==", "hasInstallScript": true, "license": "BSD-3-Clause", "optional": true, @@ -15855,13 +15946,6 @@ "node": ">=12.0.0" } }, - "node_modules/protobufjs/node_modules/long": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", - "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", - "license": "Apache-2.0", - "optional": true - }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -16042,30 +16126,30 @@ } }, "node_modules/react": { - "version": "19.2.7", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.7.tgz", - "integrity": "sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==", + "version": "19.2.8", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.8.tgz", + "integrity": "sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==", "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/react-dom": { - "version": "19.2.7", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.7.tgz", - "integrity": "sha512-t0BRVXvbiE/o20Hfw669rLbMCDWtYZLvmJigy2f0MxsXF+71pxhR3xOkspmsO8h3ZlNzyibAmtCa3l4lYKk6gQ==", + "version": "19.2.8", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.8.tgz", + "integrity": "sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==", "license": "MIT", "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { - "react": "^19.2.7" + "react": "^19.2.8" } }, "node_modules/react-is": { - "version": "19.2.8", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.8.tgz", - "integrity": "sha512-s5un28nYxKJw5gvUHyW5PCC28CvBqLu9r3cWgzHT4Vo/5fqqkFcdRYsGcKf50WMPpjjFZS5d76fn3YCo2njKwQ==", + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.3.0.tgz", + "integrity": "sha512-UpMYezM4v5/18F28aC66AEsjXIgE02kyEMH6yLdgLXu/UTfa1Ntwck/nNLrbqJsEXW7gPb0coNO9FQse9WTovA==", "license": "MIT" }, "node_modules/react-markdown": { @@ -16230,19 +16314,6 @@ "node": ">= 6" } }, - "node_modules/readdirp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", - "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", - "license": "MIT", - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/real-require": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", @@ -16282,73 +16353,6 @@ "react-is": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, - "node_modules/recma-build-jsx": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/recma-build-jsx/-/recma-build-jsx-1.0.0.tgz", - "integrity": "sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "estree-util-build-jsx": "^3.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/recma-jsx": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/recma-jsx/-/recma-jsx-1.0.1.tgz", - "integrity": "sha512-huSIy7VU2Z5OLv6oFLosQGGDqPqdO1iq6bWNAdhzMxSJP7RAso4fCZ1cKu8j9YHCZf3TPrq4dw3okhrylgcd7w==", - "license": "MIT", - "dependencies": { - "acorn-jsx": "^5.0.0", - "estree-util-to-js": "^2.0.0", - "recma-parse": "^1.0.0", - "recma-stringify": "^1.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - }, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/recma-parse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/recma-parse/-/recma-parse-1.0.0.tgz", - "integrity": "sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "esast-util-from-js": "^2.0.0", - "unified": "^11.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/recma-stringify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/recma-stringify/-/recma-stringify-1.0.0.tgz", - "integrity": "sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "estree-util-to-js": "^2.0.0", - "unified": "^11.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/redis-errors": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", @@ -16391,13 +16395,6 @@ "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", "license": "Apache-2.0" }, - "node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", - "license": "MIT", - "optional": true - }, "node_modules/regex": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/regex/-/regex-6.1.0.tgz", @@ -16473,21 +16470,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/rehype-recma": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/rehype-recma/-/rehype-recma-1.0.0.tgz", - "integrity": "sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "@types/hast": "^3.0.0", - "hast-util-to-estree": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/remark": { "version": "15.0.1", "resolved": "https://registry.npmjs.org/remark/-/remark-15.0.1.tgz", @@ -16522,20 +16504,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/remark-mdx": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.1.tgz", - "integrity": "sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg==", - "license": "MIT", - "dependencies": { - "mdast-util-mdx": "^3.0.0", - "micromark-extension-mdxjs": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/remark-parse": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", @@ -16892,13 +16860,6 @@ ], "license": "BSD-3-Clause" }, - "node_modules/seedrandom": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz", - "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==", - "license": "MIT", - "optional": true - }, "node_modules/selfsigned": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-5.5.0.tgz", @@ -17019,48 +16980,52 @@ "license": "ISC" }, "node_modules/sharp": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", - "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", - "hasInstallScript": true, + "version": "0.35.4", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.4.tgz", + "integrity": "sha512-n++8XWcj+jCOr2IOl7h8LbKnGBDY4aPbmprMONBNFdn0ImXqpGVv5zliDs0V9HbmbCQLpbuo2ej9rAoOQTvMDA==", "license": "Apache-2.0", - "optional": true, "dependencies": { - "@img/colour": "^1.0.0", + "@img/colour": "^1.1.0", "detect-libc": "^2.1.2", - "semver": "^7.7.3" + "semver": "^7.8.5" }, "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-darwin-arm64": "0.34.5", - "@img/sharp-darwin-x64": "0.34.5", - "@img/sharp-libvips-darwin-arm64": "1.2.4", - "@img/sharp-libvips-darwin-x64": "1.2.4", - "@img/sharp-libvips-linux-arm": "1.2.4", - "@img/sharp-libvips-linux-arm64": "1.2.4", - "@img/sharp-libvips-linux-ppc64": "1.2.4", - "@img/sharp-libvips-linux-riscv64": "1.2.4", - "@img/sharp-libvips-linux-s390x": "1.2.4", - "@img/sharp-libvips-linux-x64": "1.2.4", - "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", - "@img/sharp-libvips-linuxmusl-x64": "1.2.4", - "@img/sharp-linux-arm": "0.34.5", - "@img/sharp-linux-arm64": "0.34.5", - "@img/sharp-linux-ppc64": "0.34.5", - "@img/sharp-linux-riscv64": "0.34.5", - "@img/sharp-linux-s390x": "0.34.5", - "@img/sharp-linux-x64": "0.34.5", - "@img/sharp-linuxmusl-arm64": "0.34.5", - "@img/sharp-linuxmusl-x64": "0.34.5", - "@img/sharp-wasm32": "0.34.5", - "@img/sharp-win32-arm64": "0.34.5", - "@img/sharp-win32-ia32": "0.34.5", - "@img/sharp-win32-x64": "0.34.5" + "@img/sharp-darwin-arm64": "0.35.4", + "@img/sharp-darwin-x64": "0.35.4", + "@img/sharp-freebsd-wasm32": "0.35.4", + "@img/sharp-libvips-darwin-arm64": "1.3.3", + "@img/sharp-libvips-darwin-x64": "1.3.3", + "@img/sharp-libvips-linux-arm": "1.3.3", + "@img/sharp-libvips-linux-arm64": "1.3.3", + "@img/sharp-libvips-linux-ppc64": "1.3.3", + "@img/sharp-libvips-linux-riscv64": "1.3.3", + "@img/sharp-libvips-linux-s390x": "1.3.3", + "@img/sharp-libvips-linux-x64": "1.3.3", + "@img/sharp-libvips-linuxmusl-arm64": "1.3.3", + "@img/sharp-libvips-linuxmusl-x64": "1.3.3", + "@img/sharp-linux-arm": "0.35.4", + "@img/sharp-linux-arm64": "0.35.4", + "@img/sharp-linux-ppc64": "0.35.4", + "@img/sharp-linux-riscv64": "0.35.4", + "@img/sharp-linux-s390x": "0.35.4", + "@img/sharp-linux-x64": "0.35.4", + "@img/sharp-linuxmusl-arm64": "0.35.4", + "@img/sharp-linuxmusl-x64": "0.35.4", + "@img/sharp-webcontainers-wasm32": "0.35.4", + "@img/sharp-win32-arm64": "0.35.4", + "@img/sharp-win32-ia32": "0.35.4", + "@img/sharp-win32-x64": "0.35.4" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, "node_modules/shebang-command": { @@ -17085,19 +17050,19 @@ } }, "node_modules/shiki": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-4.3.1.tgz", - "integrity": "sha512-oR+qDVi2OjX1tmDpyv+3KviX01KzO6Af+0NNnKnsp9491UEGz2YpxTuJboS/6VhYpTdqzmuJBuiTlrAWWJAssw==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-4.4.3.tgz", + "integrity": "sha512-Mb/GvXPHBAXdgGIcnfU5L3ldpn1XcxrGkPHwqgRx17/I2XRfqlFKk2vGkHWINn1kdXvzJZeuO3is6I9KLPFm0g==", "license": "MIT", "dependencies": { - "@shikijs/core": "4.3.1", - "@shikijs/engine-javascript": "4.3.1", - "@shikijs/engine-oniguruma": "4.3.1", - "@shikijs/langs": "4.3.1", - "@shikijs/themes": "4.3.1", - "@shikijs/types": "4.3.1", + "@shikijs/core": "4.4.3", + "@shikijs/engine-javascript": "4.4.3", + "@shikijs/engine-oniguruma": "4.4.3", + "@shikijs/langs": "4.4.3", + "@shikijs/themes": "4.4.3", + "@shikijs/types": "4.4.3", "@shikijs/vscode-textmate": "^10.0.2", - "@types/hast": "^3.0.4" + "@types/hast": "^3.0.5" }, "engines": { "node": ">=20" @@ -17291,6 +17256,18 @@ "npm": ">= 3.0.0" } }, + "node_modules/smol-toml": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.8.0.tgz", + "integrity": "sha512-kCZr2V3ch9i00x8zXRhjUNVcjG9ijES5dDudkXvUVCT5QlJNQWElSJdZqyPemffHoLNUYwOcou0Fy+ojN0uHSQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 18" + }, + "funding": { + "url": "https://github.com/sponsors/cyyynthia" + } + }, "node_modules/socks": { "version": "2.8.9", "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.9.tgz", @@ -17343,12 +17320,12 @@ } }, "node_modules/source-map": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", - "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", "license": "BSD-3-Clause", "engines": { - "node": ">= 12" + "node": ">=0.10.0" } }, "node_modules/source-map-js": { @@ -17400,17 +17377,10 @@ "node": ">= 10.x" } }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "license": "BSD-3-Clause", - "optional": true - }, "node_modules/sql.js": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/sql.js/-/sql.js-1.14.1.tgz", - "integrity": "sha512-gcj8zBWU5cFsi9WUP+4bFNXAyF1iRpA3LLyS/DP5xlrNzGmPIizUeBggKa8DbDwdqaKwUcTEnChtd2grWo/x/A==", + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/sql.js/-/sql.js-1.14.2.tgz", + "integrity": "sha512-3ZGPovObMFrdw79zrUHbfdE/DLIsy8jdNdssmMSQuRAymedU6q84asPt0kgiqrdMYlPegDItiIMfmIXzZnYFcw==", "license": "MIT" }, "node_modules/sqlite-vec": { @@ -17418,6 +17388,7 @@ "resolved": "https://registry.npmjs.org/sqlite-vec/-/sqlite-vec-0.1.9.tgz", "integrity": "sha512-L7XJWRIBNvR9O5+vh1FQ+IGkh/3D2AzVksW5gdtk28m78Hy8skFD0pqReKH1Yp0/BUKRGcffgKvyO/EON5JXpA==", "license": "MIT OR Apache", + "optional": true, "optionalDependencies": { "sqlite-vec-darwin-arm64": "0.1.9", "sqlite-vec-darwin-x64": "0.1.9", @@ -18161,13 +18132,6 @@ "node": ">=16" } }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "license": "MIT", - "optional": true - }, "node_modules/trim-lines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", @@ -18214,9 +18178,9 @@ "license": "0BSD" }, "node_modules/tsx": { - "version": "4.23.1", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.1.tgz", - "integrity": "sha512-GQHnkIfxyx1wYCOS/wonik5MVRZU9hi1TEZmzGZSCJB1y9YgoZ8H6itNE/u4suE+yLmOzuE4E5S4TZ/ZX2wcWQ==", + "version": "4.23.13", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.23.13.tgz", + "integrity": "sha512-BL5MGkRln6aDYhb0xbQlEAGw743BaZYWdbWtdJOBriYJboKgUUYCadFp2/FpBBZquBC/ezNBn7wMMPx7FDZUDw==", "license": "MIT", "dependencies": { "esbuild": "~0.28.0" @@ -18276,6 +18240,25 @@ "node": "*" } }, + "node_modules/turndown": { + "version": "7.2.4", + "resolved": "https://registry.npmjs.org/turndown/-/turndown-7.2.4.tgz", + "integrity": "sha512-I8yFsfRzmzK0WV1pNNOA4A7y4RDfFxPRxb3t+e3ui14qSGOxGtiSP6GjeX+Y6CHb7HYaFj7ECUD7VE5kQMZWGQ==", + "license": "MIT", + "dependencies": { + "@mixmark-io/domino": "^2.2.0" + }, + "engines": { + "node": ">=18", + "npm": ">=9" + } + }, + "node_modules/turndown-plugin-gfm": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/turndown-plugin-gfm/-/turndown-plugin-gfm-1.0.2.tgz", + "integrity": "sha512-vwz9tfvF7XN/jE0dGoBei3FXWuvll78ohzCZQuOb+ZjWrs3a0XhQVomJEb2Qh4VHTPNRO4GPZh0V7VRbiWwkRg==", + "license": "MIT" + }, "node_modules/type-fest": { "version": "5.8.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.8.0.tgz", @@ -18337,9 +18320,9 @@ } }, "node_modules/undici": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-8.8.0.tgz", - "integrity": "sha512-ubshXMXwF3MQIMF1y/WxZdNBnjEKeSg2wF5mcGUtU55YTw34tnVVpKRlLf7ruDXZ5344KokPVX4RBx1wJm64Bw==", + "version": "8.10.2", + "resolved": "https://registry.npmjs.org/undici/-/undici-8.10.2.tgz", + "integrity": "sha512-/y4/bH9YNU5hi9NIrpOuvGXFcxrj3CMrV+/AYpowAYTpHn8gX/XPFjNy766FPoYY0miQhdW977JFWKGNhBdwyQ==", "license": "MIT", "engines": { "node": ">=22.19.0" @@ -18432,33 +18415,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/unist-util-position-from-estree": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unist-util-position-from-estree/-/unist-util-position-from-estree-2.0.0.tgz", - "integrity": "sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-remove-position": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz", - "integrity": "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-visit": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/unist-util-stringify-position": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", @@ -18603,9 +18559,9 @@ } }, "node_modules/use-intl": { - "version": "4.13.3", - "resolved": "https://registry.npmjs.org/use-intl/-/use-intl-4.13.3.tgz", - "integrity": "sha512-e1qMU4PokNEU7K1TtKROSl3Sv7JLsKh7GyNjuhKZVB444Qfv0qHjet59IZF6GtYE+VwGbhgWqDWfGTnuDPe2Bg==", + "version": "4.14.5", + "resolved": "https://registry.npmjs.org/use-intl/-/use-intl-4.14.5.tgz", + "integrity": "sha512-NNGSInks18BAasPgnMrnahNkEZSkWpbWE70IcEDWPUZwS39tVuDB/Vo6J3FaDnYwwKioR33JfWFOzEFnhuJcJw==", "funding": [ { "type": "individual", @@ -18616,7 +18572,7 @@ "dependencies": { "@formatjs/fast-memoize": "^3.1.0", "@schummar/icu-type-parser": "1.21.5", - "icu-minify": "^4.13.3", + "icu-minify": "^4.14.5", "intl-messageformat": "^11.1.0" }, "peerDependencies": { @@ -18799,24 +18755,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "license": "BSD-2-Clause", - "optional": true - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "license": "MIT", - "optional": true, - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, "node_modules/when-exit": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/when-exit/-/when-exit-2.1.5.tgz", @@ -19028,25 +18966,30 @@ "license": "ISC" }, "node_modules/wreq-js": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/wreq-js/-/wreq-js-2.3.1.tgz", - "integrity": "sha512-vaKasaKeskrDKEuuO5Q5uamEG9a6FrF5ZSicH7TCvYS4RxF7/gzaU/vYqwJzcs+uydyJPVWY1KCvfVCgp0tiGA==", - "cpu": [ - "x64", - "arm64" - ], + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/wreq-js/-/wreq-js-3.2.0.tgz", + "integrity": "sha512-dawhEbhvd5hxivKZSvv/mAQGO3mwZYESyctOvIIZ/H3DvQJzUM2UoFQsij0fg7hIClQ/GEQgg+2259UcFwhpMQ==", "license": "MIT", "optional": true, - "os": [ - "darwin", - "linux", - "win32" - ] + "engines": { + "node": ">=20.0.0" + }, + "optionalDependencies": { + "@wreq-js/binding-android-arm64": "3.2.0", + "@wreq-js/binding-darwin-arm64": "3.2.0", + "@wreq-js/binding-darwin-x64": "3.2.0", + "@wreq-js/binding-linux-arm64-gnu": "3.2.0", + "@wreq-js/binding-linux-arm64-musl": "3.2.0", + "@wreq-js/binding-linux-x64-gnu": "3.2.0", + "@wreq-js/binding-linux-x64-musl": "3.2.0", + "@wreq-js/binding-win32-arm64-msvc": "3.2.0", + "@wreq-js/binding-win32-x64-msvc": "3.2.0" + } }, "node_modules/ws": { - "version": "8.21.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.1.tgz", - "integrity": "sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw==", + "version": "8.21.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.3.tgz", + "integrity": "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==", "license": "MIT", "engines": { "node": ">=10.0.0" @@ -19065,9 +19008,9 @@ } }, "node_modules/wsl-utils": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.3.1.tgz", - "integrity": "sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-1.0.0.tgz", + "integrity": "sha512-Hl0ZOAs672vg+06kfujwRhoS6/jehvULrlFkuF2dRu6pHgA8U06h3xqNIqNNU1LTXPcedxByAR4GS6pwQK0mgA==", "license": "MIT", "dependencies": { "is-wsl": "^3.1.0", @@ -19080,6 +19023,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/wsl-utils/node_modules/powershell-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/powershell-utils/-/powershell-utils-0.1.0.tgz", + "integrity": "sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A==", + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/xdg-basedir": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-5.1.0.tgz", @@ -19273,44 +19228,15 @@ "integrity": "sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ==", "license": "MIT" }, - "node_modules/yuku-analyzer": { - "version": "0.6.12", - "resolved": "https://registry.npmjs.org/yuku-analyzer/-/yuku-analyzer-0.6.12.tgz", - "integrity": "sha512-0zu/gwv6nKA3wm2GMjM1iczw9rbt77ijEyR5tXpPQ8AZcXIpXlll66BXOtMHgYudLn91bJx0ybhpARoJWm5/dw==", - "license": "MIT", - "dependencies": { - "@yuku-toolchain/types": "0.6.11", - "yuku-ast": "0.6.11" - }, - "optionalDependencies": { - "@yuku-analyzer/binding-darwin-arm64": "0.6.12", - "@yuku-analyzer/binding-darwin-x64": "0.6.12", - "@yuku-analyzer/binding-freebsd-x64": "0.6.12", - "@yuku-analyzer/binding-linux-arm-gnu": "0.6.12", - "@yuku-analyzer/binding-linux-arm-musl": "0.6.12", - "@yuku-analyzer/binding-linux-arm64-gnu": "0.6.12", - "@yuku-analyzer/binding-linux-arm64-musl": "0.6.12", - "@yuku-analyzer/binding-linux-x64-gnu": "0.6.12", - "@yuku-analyzer/binding-linux-x64-musl": "0.6.12", - "@yuku-analyzer/binding-win32-arm64": "0.6.12", - "@yuku-analyzer/binding-win32-x64": "0.6.12" - } - }, - "node_modules/yuku-ast": { - "version": "0.6.11", - "resolved": "https://registry.npmjs.org/yuku-ast/-/yuku-ast-0.6.11.tgz", - "integrity": "sha512-ZfXkFYVsDewS45+kv3WiA/qNB73CRfxFDEQwfnRMUAR4AD5zRI7PRqxmI2U3Jz/oG41GneTVW6mxDOQal0lgeA==", - "license": "MIT", - "dependencies": { - "@yuku-toolchain/types": "0.6.8" + "node_modules/zbsearch": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/zbsearch/-/zbsearch-4.0.0.tgz", + "integrity": "sha512-gm4zfO31n2ZdruTTRQoWVWO4Q2+zrDt2GlrvIc+5JulRQNAm4IanCxER82vQ7Ug96FYkGqWUJBXFe1kGAcDWaQ==", + "license": "Apache-2.0", + "engines": { + "node": ">= 20.0.0" } }, - "node_modules/yuku-ast/node_modules/@yuku-toolchain/types": { - "version": "0.6.8", - "resolved": "https://registry.npmjs.org/@yuku-toolchain/types/-/types-0.6.8.tgz", - "integrity": "sha512-AbUd1775RVkOxJkh8hkldIWoU6kRMTCsZFSZq8Ny53q7GkbaVe5UCfleNZ3RWCoz/ZKE8qwfeB7Cj0xqhLWsKA==", - "license": "MIT" - }, "node_modules/zod": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", @@ -19330,9 +19256,9 @@ } }, "node_modules/zustand": { - "version": "5.0.14", - "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.14.tgz", - "integrity": "sha512-/8tAspM5LMPr28b3fwLYrtdj77ECpfZviaP75CMTnwO8ISyaE4GDIG/9rDDYq/cH9D2Xw2A2RXglLInmVBQB/g==", + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.15.tgz", + "integrity": "sha512-MpSEjRiBkA9crSYeOUH32rJC7SVqAbm0Fqcqge/bUi2PPoLcBWKOsG+C8mevmpr8TwXHBVkChbbJiyvkE+i/3A==", "license": "MIT", "engines": { "node": ">=12.20.0" diff --git a/package.json b/package.json index c9b8eb4..fc211ed 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "omniwork", - "version": "0.11.2", + "version": "0.12.0", "description": "Open-source Claude Code / Cowork-style desktop agent with OmniRoute baked in. Download, open, and code with free AI models — zero setup.", "author": "OmniWork contributors", "license": "MIT", @@ -19,6 +19,7 @@ "doctor": "node scripts/doctor.js", "setup": "node scripts/setup.js", "connect": "node scripts/connect.js", + "providers": "node scripts/providers.js", "test:boot": "node test/boot.js", "test:smoke": "node test/smoke.js", "test:cowork": "node test/cowork.js", @@ -34,16 +35,21 @@ "test:approvals": "node test/approvals.js", "test:selection": "node test/selection.js", "test:acp": "node test/acp.js", + "test:fallback": "node test/fallback.js", + "test:providers": "node test/providers.js", + "test:opencode": "node test/opencode.js", + "test:tuning": "node test/tuning.js", "test:sidecar": "node test/sidecar.js", "mcp": "node electron/mcp-server.js", "acp": "node electron/acp-server.js" }, "bin": { "omniwork-mcp": "electron/mcp-server.js", - "omniwork-acp": "electron/acp-server.js" + "omniwork-acp": "electron/acp-server.js", + "omniwork-providers": "scripts/providers.js" }, "dependencies": { - "omniroute": "^3.8.48", + "omniroute": "^3.8.50", "tar": "^7.5.22" }, "build": { @@ -65,7 +71,9 @@ "!node_modules/omniroute/dist/node_modules/typescript/**", "!node_modules/omniroute/dist/node_modules/playwright-core/**", "!node_modules/omniroute/dist/node_modules/@img/**", - "!node_modules/omniroute/dist/node_modules/@ngrok/**" + "!node_modules/omniroute/dist/node_modules/@ngrok/**", + "!node_modules/opencode-ai/**", + "!node_modules/opencode-*/**" ], "extraResources": [ { @@ -118,5 +126,8 @@ "cross-env": "^7.0.3", "electron": "^33.4.11", "electron-builder": "^25.1.8" + }, + "optionalDependencies": { + "opencode-ai": "1.18.31" } } diff --git a/renderer/app.js b/renderer/app.js index 3060148..c851e1d 100644 --- a/renderer/app.js +++ b/renderer/app.js @@ -14,6 +14,7 @@ const stub = { listDir: async () => ({ root: null, entries: [] }), readFile: async () => ({ content: "" }), getState: async () => ({ model: "auto", sessions: [], activeId: null, mcp: [] }), setModel: async () => {}, openDashboard: async () => {}, on: () => () => {}, + providersStatus: async () => null, providersConnect: async () => ({}), providersRemove: async () => 0, openUrl: async () => false, copyText: async () => {}, setCopyOnSelect: async () => {}, }; const api = window.omniwork || stub; @@ -432,6 +433,7 @@ api.on("sessions:list", (p) => { }); api.on("mcp:list", (p) => renderMcp(p.servers)); api.on("skills:list", (p) => { skillsCache = p.skills || []; }); +api.on("providers:suggest", () => { const m = $("providers-modal"); if (m && m.classList.contains("hidden")) { m.classList.remove("hidden"); renderProviders(); addSystem("🆓 Connect a free provider for far more models — OpenRouter signs you in with one click."); } }); api.on("gateway:status", (s) => { const d = $("gw-dot"); d.className = "s-dot " + (s.state === "ready" ? "ok" : s.state === "error" ? "err" : "boot"); @@ -1015,6 +1017,73 @@ async function addFromForm() { await api.addMcp(name, conf); } $("add-mcp").addEventListener("click", openModal); + +// ── Free providers ─────────────────────────────────────────────── +async function renderProviders() { + const st = await api.providersStatus(); + const list = $("prov-list"); const local = $("prov-local"); const status = $("prov-status"); + list.innerHTML = ""; local.innerHTML = ""; + if (!st || st.error) { status.textContent = st && st.error ? "Gateway error: " + st.error : "Gateway still starting — try again in a moment."; return; } + const on = st.providers.filter((p) => p.connected); + status.textContent = on.length + ? `Connected: ${on.map((p) => p.name).join(", ")} · fallback chain: ${st.chain.join(" → ") || "(empty)"}` + : "Nothing connected yet — pick one below (all free, no card)."; + st.providers.forEach((p) => { + const row = document.createElement("div"); row.className = "prow"; + const act = p.connected + ? `${p.models} models ` + : p.connect === "pkce" + ? `` + : ``; + row.innerHTML = `
${p.connected ? '✓' : ""}${esc(p.name)}
${esc(p.free)}
${act}
`; + list.appendChild(row); + }); + if (st.opencode) { + const oc = st.opencode; + const row = document.createElement("div"); row.className = "prow"; + const act = oc.installed + ? `${oc.models.length} free models · engine` + : ``; + row.innerHTML = `
${oc.installed ? '✓' : ""}OpenCode engine
${oc.installed ? esc(oc.models.join(", ") || "no free models listed") : "Zen's free models with no account: Nemotron 3 Ultra, Nemotron 3.5 Lightning, MiMo V2.5, Ling 3.0 Flash, Big Pickle. Runs OpenCode's own server as an engine."}
${act}
`; + local.appendChild(row); + } + const running = st.local.filter((l) => l.running); + if (!running.length) { + local.insertAdjacentHTML("beforeend", '
No local model server running. Ollama (:11434), LM Studio (:1234), llama.cpp (:8080) and vLLM (:8000) are detected automatically.
'); + } + running.forEach((l) => { + const row = document.createElement("div"); row.className = "prow"; + row.innerHTML = `
${l.connected ? '✓' : ""}${esc(l.name)}
${esc(l.runningModels.slice(0, 4).join(", "))}${l.runningModels.length > 4 ? " …" : ""}
${l.connected ? 'connected' : ``}
`; + local.appendChild(row); + }); +} +async function connectProvider(id, key) { + const modal = $("providers-modal"); modal.classList.add("prow-busy"); + try { + const r = await api.providersConnect(id, key); + addSystem(r.engine ? `🆓 OpenCode engine ready (${r.version || "installed"}) — ${r.models} free models: ${(r.modelIds || []).join(", ")}` + : r.added ? `🆓 local model server${r.added.length ? "s registered: " + r.added.map((a) => a.name).join(", ") : ": none running"}` + : `🆓 ${r.name} connected — ${r.models} models · fallback chain: ${(r.chain || []).join(" → ") || "(empty)"}`); + await populateModels(); + } catch (e) { addSystem("🆓 " + (e.message || String(e)).replace(/^Error invoking remote method '[^']+': Error: /, "")); } + modal.classList.remove("prow-busy"); + renderProviders(); +} +$("free-models").addEventListener("click", () => { $("providers-modal").classList.remove("hidden"); renderProviders(); }); +$("prov-close").addEventListener("click", () => $("providers-modal").classList.add("hidden")); +$("providers-modal").addEventListener("click", async (e) => { + if (e.target.id === "providers-modal") { $("providers-modal").classList.add("hidden"); return; } + const t = e.target; + if (t.dataset.url) { api.openUrl(t.dataset.url); return; } + if (t.dataset.remove) { await api.providersRemove(t.dataset.remove); await populateModels(); renderProviders(); return; } + if (t.dataset.connect) { + const input = $("providers-modal").querySelector(`input[data-key="${t.dataset.connect}"]`); + connectProvider(t.dataset.connect, input ? input.value.trim() : undefined); + } +}); +$("providers-modal").addEventListener("keydown", (e) => { + if (e.key === "Enter" && e.target.dataset && e.target.dataset.key) connectProvider(e.target.dataset.key, e.target.value.trim()); +}); $("m-cancel").addEventListener("click", closeModal); $("modal").addEventListener("click", (e) => { if (e.target.id === "modal") closeModal(); }); $("m-add").addEventListener("click", addFromForm); diff --git a/renderer/index.html b/renderer/index.html index 97c9007..68a47a7 100644 --- a/renderer/index.html +++ b/renderer/index.html @@ -26,6 +26,7 @@
+
@@ -114,6 +115,21 @@ + + +