From 945289afe3c06724d972da7c26c036737017b232 Mon Sep 17 00:00:00 2001 From: Tal Zaccai Date: Tue, 19 May 2026 13:41:08 -0700 Subject: [PATCH 1/6] visualStudio agent: migrate to PortRegistrar + C# discovery client TS bridge: - Rewrite VisualStudioBridge as async start(port=0) factory - Add verifyClient Origin gate (loopback + absent Origin only) - Shared bridge with refcount, start/close serialization - Per-session registerPort('default', port) + idempotent release - VISUALSTUDIO_BRIDGE_PORT escape hatch for debugging C# host: - New BridgeDiscovery.cs: speaks agent-rpc discovery wire protocol over ClientWebSocket; resolves the bridge port at each reconnect - AgentBridgeClient: drop hardcoded ws://localhost:5680, call ResolveBridgePortAsync per attempt; log port on error - Env vars: AGENT_SERVER_PORT, TYPEAGENT_VS_USE_DISCOVERY, TYPEAGENT_VS_FALLBACK_PORT (all documented) Docs: README updated with new architecture diagram, port discovery section, env-var table, troubleshooting. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- ts/packages/agents/visualStudio/README.md | 52 +- .../host/csharp/Bridge/AgentBridgeClient.cs | 42 +- .../host/csharp/Bridge/BridgeDiscovery.cs | 201 +++ .../host/csharp/VisualStudioTypeAgent.csproj | 1 + ts/packages/agents/visualStudio/package.json | 2 + .../visualStudio/src/originAllowlist.ts | 52 + .../src/visualStudioActionHandler.ts | 301 ++++- ts/pnpm-lock.yaml | 1172 ++++------------- 8 files changed, 827 insertions(+), 996 deletions(-) create mode 100644 ts/packages/agents/visualStudio/host/csharp/Bridge/BridgeDiscovery.cs create mode 100644 ts/packages/agents/visualStudio/src/originAllowlist.ts diff --git a/ts/packages/agents/visualStudio/README.md b/ts/packages/agents/visualStudio/README.md index 4c430ec69a..43717dd373 100644 --- a/ts/packages/agents/visualStudio/README.md +++ b/ts/packages/agents/visualStudio/README.md @@ -17,28 +17,50 @@ for build and install instructions. +-------------------------------+ +--------------------+ | Visual Studio (VSIX) | | TypeAgent | | | | agent-server | -| +------------------------+ | WS | | -| | ChatToolWindow |<--|------->| +--------------+ | +| +------------------------+ | | | +| | ChatToolWindow |<--|--WS--->| +--------------+ | | | WebView2 | | 8999 | | dispatcher | | | | chat-ui | | | +------+-------+ | | +------------------------+ | | | | | | | +------v-------+ | | +------------------------+ | | | visualstudio | | | | AgentBridgeClient.cs |<--|---WS---|->| agent | | -| | DTEActionExecutor.cs | | 5680 | +--------------+ | +| | DTEActionExecutor.cs | | ephem. | +--------------+ | | +-----------+------------+ | +--------------------+ -| | | -| v EnvDTE | -| (Solution, Build, | -| Debugger, Editor) | +| | ^ +| | + port discovered via +| | discovery channel on 8999 +| v EnvDTE +| (Solution, Build, +| Debugger, Editor) +-------------------------------+ ``` Two WebSocket channels: -- **Chat channel** (port 8999) — WebView2 inside the VSIX talks to the dispatcher. -- **Action bridge** (port 5680) — this agent owns a `WebSocketServer`; the C# - host connects as a client and dispatches incoming actions through EnvDTE. +- **Chat channel** (port 8999) — WebView2 inside the VSIX talks to the + dispatcher. The same port also hosts the dispatcher's read-only + **discovery channel** that the bridge uses to find the action port + (see below). +- **Action bridge** (OS-assigned ephemeral port) — this agent owns a + `WebSocketServer`; the C# host connects as a client and dispatches + incoming actions through EnvDTE. The actual port is published to the + agent-server's `PortRegistrar` under `(visualStudio, default)` and + discovered by `AgentBridgeClient` on every connect attempt. + +### Port discovery + +`AgentBridgeClient` resolves the bridge port on each connect attempt by +calling `lookupPort("visualStudio", "default")` against the +agent-server's discovery channel (`ws://localhost:/`, +default 8999). Knobs: + +| Env var | Default | Purpose | +| ----------------------------------------- | ----------------------- | --------------------------------------------------------------------------- | +| `AGENT_SERVER_PORT` | `8999` | Where the dispatcher's discovery channel is hosted. | +| `TYPEAGENT_VS_USE_DISCOVERY` | `true` | Set to `false`/`0` to skip discovery and use the hardcoded fallback (5680). | +| `TYPEAGENT_VS_FALLBACK_PORT` | `5680` | Port to fall back to when discovery is disabled or returns null / fails. | +| `VISUALSTUDIO_BRIDGE_PORT` _(agent-side)_ | _(unset → OS-assigned)_ | Pin the agent's bridge to a specific port when debugging. | ## Action Categories @@ -77,7 +99,8 @@ The VSIX host has its own two-stage build (WebView2 bundle + MSBuild). See 4. **View → Other Windows → TypeAgent Chat**. The chat panel connects to `ws://localhost:8999`. Once connected, the C# bridge -auto-connects to `ws://localhost:5680`. +discovers the agent's action port via that same WS (via the discovery channel) +and auto-connects. ## Project Structure @@ -126,8 +149,11 @@ Any use of third-party trademarks or logos are subject to those third-party's po - **Chat panel never connects.** The agent-server must be running before VS opens the tool window. Check that port 8999 is reachable. - **Actions hang or error with "Host plugin not connected".** The C# bridge - could not reach port 5680 — confirm the `visualstudio-agent` is enabled in - the dispatcher and that no other process is bound to 5680. + could not reach the agent's action port. Confirm `visualstudio-agent` is + enabled in the dispatcher. Check the VS **Output → Debug** pane for + `[TypeAgent] Bridge…` lines indicating whether discovery succeeded and + which port was used. Set `TYPEAGENT_VS_USE_DISCOVERY=false` to force the + hardcoded fallback (5680) if you suspect the discovery channel itself. - **Action ran but did nothing visible.** Check the Visual Studio **Output** window and the agent-server logs; EnvDTE silently no-ops on some commands when the relevant context (e.g. an active document, an active debug session) diff --git a/ts/packages/agents/visualStudio/host/csharp/Bridge/AgentBridgeClient.cs b/ts/packages/agents/visualStudio/host/csharp/Bridge/AgentBridgeClient.cs index bf1240bb9f..c0e9b1fab3 100644 --- a/ts/packages/agents/visualStudio/host/csharp/Bridge/AgentBridgeClient.cs +++ b/ts/packages/agents/visualStudio/host/csharp/Bridge/AgentBridgeClient.cs @@ -14,10 +14,18 @@ namespace Microsoft.TypeAgent.VisualStudio.Bridge { /// - /// WebSocket client that connects to the visualstudio-agent's bridge - /// (default ws://localhost:5680). Receives BridgeRequest messages, - /// dispatches them through DTEActionExecutor, and sends BridgeResponse - /// messages back. + /// WebSocket client that connects to the visualstudio-agent's bridge. + /// Receives BridgeRequest messages, dispatches them through + /// DTEActionExecutor, and sends BridgeResponse messages back. + /// + /// Port discovery: + /// The bridge port is no longer hardcoded. On each connect attempt + /// we ask the agent-server's discovery channel where the + /// `(visualStudio, default)` allocation lives, falling back to the + /// well-known port (5680) when discovery is disabled or fails. + /// See for the wire protocol and the + /// env-var knobs (`AGENT_SERVER_PORT`, + /// `TYPEAGENT_VS_USE_DISCOVERY`, `TYPEAGENT_VS_FALLBACK_PORT`). /// /// Wire format (matches packages/agents/visualStudio/src/visualStudioActionHandler.ts): /// request: { id, actionName, parameters } @@ -25,9 +33,6 @@ namespace Microsoft.TypeAgent.VisualStudio.Bridge /// internal sealed class AgentBridgeClient : IDisposable { - // Port 5678 + 5679 are taken by the Excel agent. Keep this in sync - // with BRIDGE_PORT in packages/agents/visualStudio/src/visualStudioActionHandler.ts. - private static readonly Uri DefaultUri = new Uri("ws://localhost:5680"); private static readonly TimeSpan ReconnectDelay = TimeSpan.FromSeconds(3); private readonly AsyncPackage _package; @@ -46,9 +51,15 @@ public async Task StartAsync(CancellationToken cancellation) using var linked = CancellationTokenSource.CreateLinkedTokenSource(_cts.Token, cancellation); while (!linked.IsCancellationRequested) { + int port = 0; try { - await ConnectAndReceiveAsync(linked.Token); + // Resolve the port fresh on every attempt: the agent may + // have restarted on a different ephemeral port since the + // last loop iteration, and the standalone shell may have + // come up while we were retrying. + port = await BridgeDiscovery.ResolveBridgePortAsync(linked.Token).ConfigureAwait(false); + await ConnectAndReceiveAsync(port, linked.Token).ConfigureAwait(false); } catch (OperationCanceledException) { @@ -56,11 +67,11 @@ public async Task StartAsync(CancellationToken cancellation) } catch (Exception ex) { - Debug.WriteLine($"[TypeAgent] Bridge error: {ex.Message}"); + Debug.WriteLine($"[TypeAgent] Bridge error (port {port}): {ex.Message}"); } try { - await Task.Delay(ReconnectDelay, linked.Token); + await Task.Delay(ReconnectDelay, linked.Token).ConfigureAwait(false); } catch (OperationCanceledException) { @@ -69,11 +80,12 @@ public async Task StartAsync(CancellationToken cancellation) } } - private async Task ConnectAndReceiveAsync(CancellationToken cancellation) + private async Task ConnectAndReceiveAsync(int port, CancellationToken cancellation) { + var uri = new Uri($"ws://localhost:{port}"); _ws = new ClientWebSocket(); - await _ws.ConnectAsync(DefaultUri, cancellation); - Debug.WriteLine($"[TypeAgent] Bridge connected to {DefaultUri}"); + await _ws.ConnectAsync(uri, cancellation).ConfigureAwait(false); + Debug.WriteLine($"[TypeAgent] Bridge connected to {uri}"); var buffer = new ArraySegment(new byte[16 * 1024]); var assembly = new StringBuilder(); @@ -84,10 +96,10 @@ private async Task ConnectAndReceiveAsync(CancellationToken cancellation) WebSocketReceiveResult result; do { - result = await _ws.ReceiveAsync(buffer, cancellation); + result = await _ws.ReceiveAsync(buffer, cancellation).ConfigureAwait(false); if (result.MessageType == WebSocketMessageType.Close) { - await _ws.CloseAsync(WebSocketCloseStatus.NormalClosure, null, cancellation); + await _ws.CloseAsync(WebSocketCloseStatus.NormalClosure, null, cancellation).ConfigureAwait(false); return; } assembly.Append(Encoding.UTF8.GetString(buffer.Array!, 0, result.Count)); diff --git a/ts/packages/agents/visualStudio/host/csharp/Bridge/BridgeDiscovery.cs b/ts/packages/agents/visualStudio/host/csharp/Bridge/BridgeDiscovery.cs new file mode 100644 index 0000000000..63f513bf6e --- /dev/null +++ b/ts/packages/agents/visualStudio/host/csharp/Bridge/BridgeDiscovery.cs @@ -0,0 +1,201 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Diagnostics; +using System.Net.WebSockets; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace Microsoft.TypeAgent.VisualStudio.Bridge +{ + /// + /// Looks up the visualStudio agent's bridge port via the dispatcher's + /// discovery channel. + /// + /// Wire protocol (matches packages/agentServer/protocol/src/protocol.ts): + /// client → server: + /// { "name": "discovery", + /// "message": { "type": "invoke", "callId": N, "name": "lookupPort", + /// "args": [{ "agentName": "visualStudio", + /// "role": "default" }] } } + /// server → client: + /// { "name": "discovery", + /// "message": { "type": "invokeResult", "callId": N, + /// "result": { "port": <int|null> } } } + /// + /// Returns the port on success, or null when the agent isn't currently + /// registered (caller should retry with backoff). Throws on transport + /// failure so the outer reconnect loop can apply its own retry policy. + /// + internal static class BridgeDiscovery + { + // Env var read on every resolve so users can flip behavior without + // restarting the IDE between debugging sessions. + private const string AgentServerPortEnv = "AGENT_SERVER_PORT"; + private const string UseDiscoveryEnv = "TYPEAGENT_VS_USE_DISCOVERY"; + private const string FallbackPortEnv = "TYPEAGENT_VS_FALLBACK_PORT"; + + // Must match AGENT_SERVER_DEFAULT_PORT in agentServer/protocol. + private const int DefaultAgentServerPort = 8999; + + // Hardcoded fallback when discovery is disabled or fails before the + // agent has registered. Matches the pre-discovery hardcoded port — + // ports 5678 + 5679 are taken by the Excel agent. + private const int DefaultFallbackBridgePort = 5680; + + // Names this client uses to look itself up. Must match the role + // registered by visualStudioActionHandler.ts. + private const string AgentName = "visualStudio"; + private const string Role = "default"; + + /// + /// Resolve the bridge port. Returns the discovered port, or the + /// fallback when discovery is disabled / unreachable / returned + /// null. Never throws — callers expect a usable port. + /// + public static async Task ResolveBridgePortAsync(CancellationToken cancellation) + { + int fallback = GetFallbackPort(); + if (!IsDiscoveryEnabled()) + { + Debug.WriteLine($"[TypeAgent] Discovery disabled; using fallback port {fallback}"); + return fallback; + } + int agentServerPort = GetAgentServerPort(); + try + { + int? discovered = await LookupPortAsync(agentServerPort, cancellation).ConfigureAwait(false); + if (discovered is int p) + { + Debug.WriteLine($"[TypeAgent] Discovery resolved bridge port {p}"); + return p; + } + Debug.WriteLine($"[TypeAgent] Discovery returned null for ({AgentName}, {Role}); using fallback {fallback}"); + return fallback; + } + catch (Exception ex) + { + Debug.WriteLine($"[TypeAgent] Discovery failed ({ex.Message}); using fallback port {fallback}"); + return fallback; + } + } + + private static bool IsDiscoveryEnabled() + { + // Discovery is on by default; explicit "false"/"0" disables. + string? raw = Environment.GetEnvironmentVariable(UseDiscoveryEnv); + if (string.IsNullOrEmpty(raw)) return true; + return !(raw!.Equals("false", StringComparison.OrdinalIgnoreCase) || raw == "0"); + } + + private static int GetAgentServerPort() + { + string? raw = Environment.GetEnvironmentVariable(AgentServerPortEnv); + if (int.TryParse(raw, out int p) && p > 0 && p <= 65535) + { + return p; + } + return DefaultAgentServerPort; + } + + private static int GetFallbackPort() + { + string? raw = Environment.GetEnvironmentVariable(FallbackPortEnv); + if (int.TryParse(raw, out int p) && p > 0 && p <= 65535) + { + return p; + } + return DefaultFallbackBridgePort; + } + + private static async Task LookupPortAsync(int agentServerPort, CancellationToken cancellation) + { + var uri = new Uri($"ws://localhost:{agentServerPort}/"); + using var ws = new ClientWebSocket(); + // Cap the discovery call so a hung agent-server doesn't stall + // the whole reconnect loop. The outer AgentBridgeClient loop + // already retries on a separate cadence. + using var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(5)); + using var linked = CancellationTokenSource.CreateLinkedTokenSource(cancellation, timeout.Token); + + await ws.ConnectAsync(uri, linked.Token).ConfigureAwait(false); + + // callId is arbitrary — the server echoes it back verbatim, + // and we only have one outstanding request per socket. + const int callId = 1; + var request = new JObject + { + ["name"] = "discovery", + ["message"] = new JObject + { + ["type"] = "invoke", + ["callId"] = callId, + ["name"] = "lookupPort", + ["args"] = new JArray + { + new JObject + { + ["agentName"] = AgentName, + ["role"] = Role, + }, + }, + }, + }; + byte[] requestBytes = Encoding.UTF8.GetBytes(request.ToString(Formatting.None)); + await ws.SendAsync( + new ArraySegment(requestBytes), + WebSocketMessageType.Text, + endOfMessage: true, + linked.Token).ConfigureAwait(false); + + string responseText = await ReceiveFullMessageAsync(ws, linked.Token).ConfigureAwait(false); + try + { + await ws.CloseAsync(WebSocketCloseStatus.NormalClosure, null, CancellationToken.None).ConfigureAwait(false); + } + catch + { + // Best-effort close — the response is already in hand. + } + + var root = JObject.Parse(responseText); + string? name = root.Value("name"); + if (name != "discovery") return null; + var inner = root["message"] as JObject; + if (inner == null) return null; + string? type = inner.Value("type"); + if (type == "invokeError") + { + throw new InvalidOperationException( + inner.Value("error") ?? "Discovery returned invokeError"); + } + if (type != "invokeResult") return null; + if (inner.Value("callId") != callId) return null; + var result = inner["result"] as JObject; + if (result == null) return null; + // `port` is `int|null`; JObject returns null cleanly for both. + return result.Value("port"); + } + + private static async Task ReceiveFullMessageAsync(ClientWebSocket ws, CancellationToken cancellation) + { + var buffer = new ArraySegment(new byte[16 * 1024]); + var sb = new StringBuilder(); + WebSocketReceiveResult result; + do + { + result = await ws.ReceiveAsync(buffer, cancellation).ConfigureAwait(false); + if (result.MessageType == WebSocketMessageType.Close) + { + throw new InvalidOperationException("Discovery WS closed before response"); + } + sb.Append(Encoding.UTF8.GetString(buffer.Array!, 0, result.Count)); + } while (!result.EndOfMessage); + return sb.ToString(); + } + } +} diff --git a/ts/packages/agents/visualStudio/host/csharp/VisualStudioTypeAgent.csproj b/ts/packages/agents/visualStudio/host/csharp/VisualStudioTypeAgent.csproj index a179d13c6d..866c8f99e7 100644 --- a/ts/packages/agents/visualStudio/host/csharp/VisualStudioTypeAgent.csproj +++ b/ts/packages/agents/visualStudio/host/csharp/VisualStudioTypeAgent.csproj @@ -73,6 +73,7 @@ ChatToolWindowControl.xaml + diff --git a/ts/packages/agents/visualStudio/package.json b/ts/packages/agents/visualStudio/package.json index 166a51b414..c13640ab21 100644 --- a/ts/packages/agents/visualStudio/package.json +++ b/ts/packages/agents/visualStudio/package.json @@ -25,10 +25,12 @@ }, "dependencies": { "@typeagent/agent-sdk": "workspace:*", + "debug": "^4.4.0", "ws": "^8.20.1" }, "devDependencies": { "@typeagent/action-schema-compiler": "workspace:*", + "@types/debug": "^4.1.12", "@types/ws": "^8.5.10", "action-grammar-compiler": "workspace:*", "concurrently": "^9.1.2", diff --git a/ts/packages/agents/visualStudio/src/originAllowlist.ts b/ts/packages/agents/visualStudio/src/originAllowlist.ts new file mode 100644 index 0000000000..4b5bbb5905 --- /dev/null +++ b/ts/packages/agents/visualStudio/src/originAllowlist.ts @@ -0,0 +1,52 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +/** + * Origin allowlist for the visualStudio agent's WebSocket bridge. + * + * The only legitimate client is the in-process Visual Studio extension + * (`host/csharp/Bridge/AgentBridgeClient.cs`), which uses + * `System.Net.WebSockets.ClientWebSocket`. That client does **not** send + * an `Origin` header, so we accept missing/empty Origin. + * + * Allowed: + * - **No Origin header** — the C# `ClientWebSocket` doesn't set one. + * - `http(s)://localhost(:port)`, `http(s)://127.0.0.1(:port)`, + * `http(s)://[::1](:port)` — loopback web clients (manual debugging, + * future webview consumers). The server already binds to loopback, so + * this is OS-level restricted as well. + * + * Anything else (including arbitrary `https://example.com`) is rejected + * with HTTP 403 before the `connection` event fires. + * + * Every per-agent listener that binds to an ephemeral port via the + * PortRegistrar must gate Origin so those ports can't be dialed by + * arbitrary web pages on the same host. + * + * Kept in sync with `agents/code/src/originAllowlist.ts` and + * `agents/browser/src/agent/originAllowlist.mts`; duplicated rather than + * shared because each agent's allowed client surface differs (VS Code + * webview schemes for `code`, Chrome/Firefox extension schemes for + * `browser`, none for `visualStudio`). + */ +export function isAllowedAgentOrigin(origin: string | undefined): boolean { + if (origin === undefined || origin === "" || origin === "null") { + return true; + } + try { + const u = new URL(origin); + if (u.protocol !== "http:" && u.protocol !== "https:") { + return false; + } + // Node's URL parser preserves IPv6 brackets in `hostname` + // (e.g. `new URL("http://[::1]:8080").hostname === "[::1]"`), + // so match the bracketed form. + return ( + u.hostname === "localhost" || + u.hostname === "127.0.0.1" || + u.hostname === "[::1]" + ); + } catch { + return false; + } +} diff --git a/ts/packages/agents/visualStudio/src/visualStudioActionHandler.ts b/ts/packages/agents/visualStudio/src/visualStudioActionHandler.ts index 6f85ec3ecb..7330fda28a 100644 --- a/ts/packages/agents/visualStudio/src/visualStudioActionHandler.ts +++ b/ts/packages/agents/visualStudio/src/visualStudioActionHandler.ts @@ -4,6 +4,15 @@ // Pattern: websocket-bridge — bidirectional RPC to a host-side plugin. // The agent owns a WebSocketServer; the host plugin connects as the client. // Commands flow TypeAgent → WebSocket → plugin → response. +// +// Port handling: the bridge binds an ephemeral port (OS-assigned via +// `bind(0)`) and publishes the actual port to the PortRegistrar under +// role `"default"`. The Visual Studio extension discovers the port via +// the dispatcher's discovery channel (`AGENT_SERVER_PORT` → +// `lookupPort("visualStudio", "default")`). For local debugging the env +// var `VISUALSTUDIO_BRIDGE_PORT` pins a fixed port (useful when running +// the extension in a debugger that can't easily read the discovery +// channel). import { ActionContext, @@ -13,12 +22,13 @@ import { ActionResult, } from "@typeagent/agent-sdk"; import { createActionResultFromTextDisplay } from "@typeagent/agent-sdk/helpers/action"; -import { WebSocketServer, WebSocket } from "ws"; +import { WebSocketServer, WebSocket, RawData } from "ws"; +import { AddressInfo } from "net"; +import registerDebug from "debug"; import { VisualStudioActions } from "./visualStudioSchema.js"; +import { isAllowedAgentOrigin } from "./originAllowlist.js"; -// Port 5678 + 5679 are taken by the Excel agent (in the SecretAgents repo). -// Keep this in sync with AgentBridgeClient.cs in the VS extension host. -const BRIDGE_PORT = 5680; +const debug = registerDebug("typeagent:visualstudio:bridge"); // ---- WebSocket bridge -------------------------------------------------- @@ -31,49 +41,138 @@ type BridgeResponse = { }; class VisualStudioBridge { - private wss: WebSocketServer | undefined; private client: WebSocket | undefined; private pending = new Map void>(); - start(): void { - const wss = new WebSocketServer({ port: BRIDGE_PORT }); - wss.on("error", (err) => { - console.error( - `[visualStudio] bridge WebSocketServer failed on port ${BRIDGE_PORT}:`, - err, - ); - }); - wss.on("listening", () => { - console.log( - `[visualStudio] bridge listening on ws://localhost:${BRIDGE_PORT}`, - ); + /** + * @param wss the underlying ws server, already bound and listening. + * @param port the actually bound port (OS-assigned when caller + * passed 0, or the env-pinned value when set). + * + * Construction is private — use {@link VisualStudioBridge.start} so + * callers always get a bridge that is guaranteed to be bound before + * they read {@link port} or pass it to the registrar. + */ + private constructor( + private readonly wss: WebSocketServer, + public readonly port: number, + ) { + this.setupHandlers(); + debug(`VisualStudioBridge listening on port ${port}`); + } + + /** + * Bind a new bridge on `port`. Resolves only after the `listening` + * event so callers can synchronously read {@link port}; rejects on + * the first `error` event so bind failures (EADDRINUSE under a + * fixed-port override) surface loudly instead of being swallowed by + * an attached error handler. + * + * Pass `0` to let the OS pick a free ephemeral port; the actual port + * is then available via {@link port}. + */ + public static start(port: number = 0): Promise { + return new Promise((resolve, reject) => { + const wss = new WebSocketServer({ + port, + // Gate every upgrade on Origin so a random web page on + // the same host can't dial the ephemeral port assigned + // by the OS. `verifyClient` runs synchronously before + // the `connection` event fires; rejected requests get + // HTTP 403. The C# `ClientWebSocket` doesn't send + // Origin, which `isAllowedAgentOrigin` accepts. + verifyClient: (info, cb) => { + const origin = info.req.headers.origin as + | string + | undefined; + if (isAllowedAgentOrigin(origin)) { + cb(true); + } else { + debug(`Rejecting WS upgrade from origin ${origin}`); + cb(false, 403, "Origin not allowed"); + } + }, + }); + let settled = false; + const onError = (error: Error) => { + if (settled) { + debug("Server error after listening:", error); + return; + } + settled = true; + wss.removeListener("listening", onListening); + debug("Server bind error:", error); + reject(error); + }; + const onListening = () => { + if (settled) return; + settled = true; + wss.removeListener("error", onError); + const address = wss.address() as AddressInfo | null; + if (!address || typeof address === "string") { + wss.close(); + reject( + new Error( + "ws server.address() did not return an AddressInfo", + ), + ); + return; + } + // Re-attach a permanent error handler so post-listen + // errors are logged rather than crashing the process. + wss.on("error", (err) => { + debug("Server error:", err); + }); + resolve(new VisualStudioBridge(wss, address.port)); + }; + wss.once("error", onError); + wss.once("listening", onListening); }); - wss.on("connection", (ws) => { - console.log("[visualStudio] host plugin connected"); + } + + private setupHandlers(): void { + this.wss.on("connection", (ws: WebSocket) => { + debug("host plugin connected"); this.client = ws; - ws.on("message", (data) => { - const response = JSON.parse(data.toString()) as BridgeResponse; - this.pending.get(response.id)?.(response); - this.pending.delete(response.id); + ws.on("message", (data: RawData) => { + try { + const response = JSON.parse( + data.toString(), + ) as BridgeResponse; + this.pending.get(response.id)?.(response); + this.pending.delete(response.id); + } catch (err) { + debug("Failed to parse plugin message:", err); + } }); ws.on("close", () => { - console.log("[visualStudio] host plugin disconnected"); + debug("host plugin disconnected"); this.client = undefined; }); ws.on("error", (err) => { - console.error("[visualStudio] host plugin socket error:", err); + debug("host plugin socket error:", err); }); }); - this.wss = wss; } + /** + * Close the underlying server and resolve once the port is fully + * released — important for a rapid disable→enable cycle under a + * fixed-port override (`VISUALSTUDIO_BRIDGE_PORT`), where a + * synchronous return would race the new bind into EADDRINUSE. + */ async stop(): Promise { - return new Promise((resolve) => this.wss?.close(() => resolve())); + debug("Closing VisualStudioBridge"); + if (this.client?.readyState === WebSocket.OPEN) { + this.client.close(); + } + this.client = undefined; + return new Promise((resolve) => this.wss.close(() => resolve())); } async send(actionName: string, parameters: unknown): Promise { if (!this.client) { - throw new Error("No host plugin connected on port " + BRIDGE_PORT); + throw new Error(`No host plugin connected on port ${this.port}`); } const id = `${Date.now()}-${Math.random().toString(36).slice(2)}`; return new Promise((resolve, reject) => { @@ -97,19 +196,72 @@ class VisualStudioBridge { } } +// ---- Port resolution --------------------------------------------------- + +// Optional fixed-port override. Useful when launching the Visual Studio +// extension in a debugger that can't easily read the discovery channel, +// or when reproducing a port-specific issue. The extension's +// `UseDiscovery=false` config flag uses the same default fallback (5680) +// so the two stay in sync. +// +// Malformed values are warned and ignored — we fall through to the +// OS-assigned port. If the requested port is already in use, +// `VisualStudioBridge.start()` rejects with that error instead of +// silently rebinding. +function getBridgeBindPort(): number { + const raw = process.env["VISUALSTUDIO_BRIDGE_PORT"]; + if (raw === undefined || raw === "") return 0; + const n = Number(raw); + if (!Number.isInteger(n) || n < 0 || n > 65535) { + console.warn( + `Ignoring malformed VISUALSTUDIO_BRIDGE_PORT=${raw}; using OS-assigned port instead`, + ); + return 0; + } + debug(`VISUALSTUDIO_BRIDGE_PORT override active: ${n}`); + return n; +} + // ---- Agent lifecycle --------------------------------------------------- -type Context = { bridge: VisualStudioBridge }; +type Context = { + bridge?: VisualStudioBridge; + portRegistration?: { release: () => void }; +}; // Shared, process-singleton bridge: the VS extension only ever opens one -// WebSocket connection on port 5680, so per-session bridges would collide on -// `new WebSocketServer({ port: 5680 })` (EADDRINUSE) the moment a second -// session/conversation initializes the visualStudio agent. Created on first -// initialize, closed when the last session disables. Mirrors the pattern used -// by the code agent's CodeAgentWebSocketServer. +// WebSocket connection on the bound port, so per-session bridges would +// collide on `new WebSocketServer({ port })` (EADDRINUSE under fixed-port +// override) the moment a second session/conversation initializes the +// visualStudio agent. Created on first initialize, closed when the last +// session disables. Mirrors the pattern used by the code agent's +// `CodeAgentWebSocketServer`. let sharedBridge: VisualStudioBridge | undefined; +let sharedStartingPromise: Promise | undefined; +let sharedClosingPromise: Promise | undefined; let sharedBridgeRefCount = 0; +async function ensureSharedBridge(): Promise { + // If a previous teardown is still releasing the port, await it + // before binding again (matters under VISUALSTUDIO_BRIDGE_PORT + // override). + if (sharedClosingPromise !== undefined) { + await sharedClosingPromise; + } + if (sharedBridge !== undefined) return sharedBridge; + if (sharedStartingPromise !== undefined) return sharedStartingPromise; + sharedStartingPromise = (async () => { + try { + const bridge = await VisualStudioBridge.start(getBridgeBindPort()); + sharedBridge = bridge; + return bridge; + } finally { + sharedStartingPromise = undefined; + } + })(); + return sharedStartingPromise; +} + export function instantiate(): AppAgent { return { initializeAgentContext, @@ -120,32 +272,68 @@ export function instantiate(): AppAgent { } async function initializeAgentContext(): Promise { - if (sharedBridge === undefined) { - sharedBridge = new VisualStudioBridge(); - sharedBridge.start(); - } - sharedBridgeRefCount++; - return { bridge: sharedBridge }; + return {}; } async function updateAgentContext( - _enable: boolean, - _context: SessionContext, + enable: boolean, + context: SessionContext, _schemaName: string, -): Promise {} +): Promise { + const agentContext = context.agentContext; + if (enable) { + if (agentContext.bridge !== undefined) return; + try { + const bridge = await ensureSharedBridge(); + agentContext.bridge = bridge; + // Per-session registration: the registrar allows multiple + // entries for `(visualStudio, default)` across sessions and + // lookup returns the most recent, so each active session + // independently keeps the shared port discoverable. The + // backstop in closeSessionContext releases ours if disable + // is skipped. + agentContext.portRegistration = context.registerPort( + "default", + bridge.port, + ); + sharedBridgeRefCount++; + } catch (e) { + // Roll back per-session bookkeeping so a subsequent retry + // sees a clean slate. The shared bridge is left untouched — + // its refcount only advances on the success path below + // `registerPort`, and other sessions may still be using it. + delete agentContext.bridge; + delete agentContext.portRegistration; + throw e; + } + } else { + if (agentContext.bridge === undefined) return; + delete agentContext.bridge; + // Release this session's registration before potentially closing + // the bridge. Release is idempotent and a no-op if already + // released by the backstop. + agentContext.portRegistration?.release(); + delete agentContext.portRegistration; + + sharedBridgeRefCount = Math.max(0, sharedBridgeRefCount - 1); + if (sharedBridgeRefCount === 0 && sharedBridge !== undefined) { + const toStop = sharedBridge; + sharedBridge = undefined; + // Track the in-flight close so a rapid re-enable awaits + // port release under a fixed-port override. + sharedClosingPromise = toStop.stop().finally(() => { + sharedClosingPromise = undefined; + }); + await sharedClosingPromise; + } + } +} async function closeAgentContext( - _context: SessionContext, + context: SessionContext, ): Promise { - if (sharedBridgeRefCount === 0) { - return; - } - sharedBridgeRefCount--; - if (sharedBridgeRefCount === 0 && sharedBridge !== undefined) { - const toStop = sharedBridge; - sharedBridge = undefined; - await toStop.stop(); - } + // Defensive cleanup if updateAgentContext(false) wasn't invoked. + await updateAgentContext(false, context, ""); } async function executeAction( @@ -153,9 +341,14 @@ async function executeAction( context: ActionContext, ): Promise { const { bridge } = context.sessionContext.agentContext; + if (!bridge) { + return { + error: "visualStudio agent is not enabled in this session.", + }; + } if (!bridge.connected) { return { - error: `Host plugin not connected. Make sure the visualStudio plugin is running on port ${BRIDGE_PORT}.`, + error: `Host plugin not connected on port ${bridge.port}. Make sure the visualStudio extension is running.`, }; } try { diff --git a/ts/pnpm-lock.yaml b/ts/pnpm-lock.yaml index 732f7ef20e..87c13f6808 100644 --- a/ts/pnpm-lock.yaml +++ b/ts/pnpm-lock.yaml @@ -550,7 +550,7 @@ importers: version: 16.5.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -577,7 +577,7 @@ importers: version: 24.37.5(typescript@5.4.5) ts-node: specifier: ^10.9.1 - version: 10.9.2(@types/node@22.19.19)(typescript@5.4.5) + version: 10.9.2(@types/node@25.5.2)(typescript@5.4.5) xml2js: specifier: ^0.6.2 version: 0.6.2 @@ -759,7 +759,7 @@ importers: version: 12.0.2(webpack@5.105.0) jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -780,7 +780,7 @@ importers: version: 5.1.4(webpack-dev-server@5.2.4)(webpack@5.105.0) webpack-dev-server: specifier: ^5.2.4 - version: 5.2.4(debug@4.4.1)(tslib@2.8.1)(webpack-cli@5.1.4)(webpack@5.105.0) + version: 5.2.4(debug@4.4.1)(webpack-cli@5.1.4)(webpack@5.105.0) examples/vscodeSchemaGen: dependencies: @@ -906,7 +906,7 @@ importers: version: 12.0.2(webpack@5.105.0) jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -927,7 +927,7 @@ importers: version: 5.1.4(webpack-dev-server@5.2.4)(webpack@5.105.0) webpack-dev-server: specifier: ^5.2.4 - version: 5.2.4(debug@4.4.1)(tslib@2.8.1)(webpack-cli@5.1.4)(webpack@5.105.0) + version: 5.2.4(debug@4.4.1)(webpack-cli@5.1.4)(webpack@5.105.0) examples/workflow/adapter: dependencies: @@ -955,7 +955,7 @@ importers: version: 9.1.2 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -986,7 +986,7 @@ importers: version: 29.5.14 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -1042,7 +1042,7 @@ importers: version: 29.5.14 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -1076,7 +1076,7 @@ importers: version: 29.5.14 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -1125,7 +1125,7 @@ importers: version: 7.0.15 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -1177,7 +1177,7 @@ importers: version: 5.4.5 vite: specifier: ^5.4.0 - version: 5.4.21(@types/node@25.9.1)(less@4.3.0)(terser@5.39.2) + version: 5.4.21(@types/node@25.5.2)(less@4.3.0)(terser@5.39.2) packages/actionGrammar: dependencies: @@ -1217,7 +1217,7 @@ importers: version: 5.6.2 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -1267,7 +1267,7 @@ importers: version: 29.5.14 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) rimraf: specifier: ^6.0.1 version: 6.0.1 @@ -1321,7 +1321,7 @@ importers: version: 29.5.14 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -1349,7 +1349,7 @@ importers: version: 29.5.14 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -1450,7 +1450,7 @@ importers: version: 8.18.1 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -1627,7 +1627,7 @@ importers: version: 2.4.1 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -1966,7 +1966,7 @@ importers: version: 9.1.2 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -2067,7 +2067,7 @@ importers: version: 9.1.2 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -2158,7 +2158,7 @@ importers: version: 2.4.1 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -2257,7 +2257,7 @@ importers: version: 9.1.2 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) rimraf: specifier: ^6.0.1 version: 6.0.1 @@ -2495,7 +2495,7 @@ importers: version: 2.4.1 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -2510,7 +2510,7 @@ importers: version: 5.4.5 vite: specifier: ^6.4.2 - version: 6.4.2(@types/node@25.9.1)(jiti@2.5.1)(less@4.3.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3) + version: 6.4.2(@types/node@25.5.2)(jiti@2.5.1)(less@4.3.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3) packages/agents/montage: dependencies: @@ -2586,7 +2586,7 @@ importers: version: 12.0.2(webpack@5.105.0) jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.2.5 version: 3.5.3 @@ -2607,7 +2607,7 @@ importers: version: 5.1.4(webpack-dev-server@5.2.4)(webpack@5.105.0) webpack-dev-server: specifier: ^5.2.4 - version: 5.2.4(debug@4.4.1)(tslib@2.8.1)(webpack-cli@5.1.4)(webpack@5.105.0) + version: 5.2.4(debug@4.4.1)(webpack-cli@5.1.4)(webpack@5.105.0) packages/agents/onboarding: dependencies: @@ -2690,7 +2690,7 @@ importers: version: 9.1.2 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -2776,7 +2776,7 @@ importers: version: 9.1.2 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) rimraf: specifier: ^6.0.1 version: 6.0.1 @@ -2899,7 +2899,7 @@ importers: version: 9.1.2 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -3054,7 +3054,7 @@ importers: version: 12.0.2(webpack@5.105.0) jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -3075,7 +3075,7 @@ importers: version: 5.1.4(webpack-dev-server@5.2.4)(webpack@5.105.0) webpack-dev-server: specifier: ^5.2.4 - version: 5.2.4(debug@4.4.1)(tslib@2.8.1)(webpack-cli@5.1.4)(webpack@5.105.0) + version: 5.2.4(debug@4.4.1)(webpack-cli@5.1.4)(webpack@5.105.0) packages/agents/utility: dependencies: @@ -3121,7 +3121,7 @@ importers: version: 9.1.2 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -3168,6 +3168,9 @@ importers: '@typeagent/agent-sdk': specifier: workspace:* version: link:../../agentSdk + debug: + specifier: ^4.4.0 + version: 4.4.3(supports-color@8.1.1) ws: specifier: ^8.20.1 version: 8.20.1 @@ -3175,6 +3178,9 @@ importers: '@typeagent/action-schema-compiler': specifier: workspace:* version: link:../../actionSchemaCompiler + '@types/debug': + specifier: ^4.1.12 + version: 4.1.12 '@types/ws': specifier: ^8.5.10 version: 8.18.1 @@ -3217,7 +3223,7 @@ importers: version: 5.4.5 vite: specifier: ^5.4.10 - version: 5.4.21(@types/node@25.9.1)(less@4.3.0)(terser@5.39.2) + version: 5.4.21(@types/node@25.5.2)(less@4.3.0)(terser@5.39.2) packages/agents/weather: dependencies: @@ -3301,7 +3307,7 @@ importers: version: 16.5.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) rimraf: specifier: ^6.0.1 version: 6.0.1 @@ -3389,7 +3395,7 @@ importers: version: 8.18.1 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -3453,7 +3459,7 @@ importers: version: 16.5.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) rimraf: specifier: ^6.0.1 version: 6.0.1 @@ -3514,7 +3520,7 @@ importers: version: 2.0.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -3554,7 +3560,7 @@ importers: version: 5.6.3(webpack@5.105.0) jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -3575,7 +3581,7 @@ importers: version: 5.1.4(webpack-dev-server@5.2.4)(webpack@5.105.0) webpack-dev-server: specifier: ^5.2.4 - version: 5.2.4(debug@4.4.1)(tslib@2.8.1)(webpack-cli@5.1.4)(webpack@5.105.0) + version: 5.2.4(debug@4.4.1)(webpack-cli@5.1.4)(webpack@5.105.0) packages/chat-ui: dependencies: @@ -3678,7 +3684,7 @@ importers: version: link:../telemetry ts-node: specifier: ^10.9.1 - version: 10.9.2(@types/node@22.19.19)(typescript@5.4.5) + version: 10.9.2(@types/node@25.5.2)(typescript@5.4.5) typechat-utils: specifier: workspace:* version: link:../utils/typechatUtils @@ -3697,7 +3703,7 @@ importers: version: 29.5.14 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@22.19.19)(ts-node@10.9.2(@types/node@22.19.19)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -3706,7 +3712,7 @@ importers: version: 6.0.1 ts-jest: specifier: ^29.4.9 - version: 29.4.9(@babel/core@7.28.4)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.28.4))(jest-util@29.7.0)(jest@29.7.0(@types/node@22.19.19)(ts-node@10.9.2(@types/node@22.19.19)(typescript@5.4.5)))(typescript@5.4.5) + version: 29.4.9(@babel/core@7.28.4)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.28.4))(jest-util@29.7.0)(jest@29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)))(typescript@5.4.5) typescript: specifier: ~5.4.5 version: 5.4.5 @@ -3881,7 +3887,7 @@ importers: version: 29.5.14 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.2.5 version: 3.5.3 @@ -3890,7 +3896,7 @@ importers: version: 5.0.10 ts-jest: specifier: ^29.1.2 - version: 29.3.3(@babel/core@7.28.4)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.28.4))(jest@29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)))(typescript@5.4.5) + version: 29.3.3(@babel/core@7.28.4)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.28.4))(jest@29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)))(typescript@5.4.5) typescript: specifier: ~5.4.5 version: 5.4.5 @@ -3942,7 +3948,7 @@ importers: version: 4.0.9 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) rimraf: specifier: ^6.0.1 version: 6.0.1 @@ -4175,7 +4181,7 @@ importers: version: 16.5.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -4329,7 +4335,7 @@ importers: version: 16.5.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -4372,7 +4378,7 @@ importers: version: 29.5.14 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -4463,7 +4469,7 @@ importers: version: 29.5.14 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) rimraf: specifier: ^5.0.5 version: 5.0.10 @@ -4497,7 +4503,7 @@ importers: version: 0.11.1 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) rimraf: specifier: ^5.0.5 version: 5.0.10 @@ -4506,7 +4512,7 @@ importers: version: 5.4.5 vite: specifier: ^5.4.0 - version: 5.4.21(@types/node@25.9.1)(less@4.3.0)(terser@5.39.2) + version: 5.4.21(@types/node@25.5.2)(less@4.3.0)(terser@5.39.2) packages/interactiveApp: dependencies: @@ -4565,7 +4571,7 @@ importers: version: 16.5.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -4663,7 +4669,7 @@ importers: version: 16.5.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -4703,7 +4709,7 @@ importers: version: 12.0.2(webpack@5.105.0) jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -4724,7 +4730,7 @@ importers: version: 5.1.4(webpack-dev-server@5.2.4)(webpack@5.105.0) webpack-dev-server: specifier: ^5.2.4 - version: 5.2.4(debug@4.4.1)(tslib@2.8.1)(webpack-cli@5.1.4)(webpack@5.105.0) + version: 5.2.4(debug@4.4.1)(webpack-cli@5.1.4)(webpack@5.105.0) packages/kp: dependencies: @@ -4850,7 +4856,7 @@ importers: version: 16.5.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -4920,7 +4926,7 @@ importers: version: 16.5.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -4972,7 +4978,7 @@ importers: version: 16.5.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.2.5 version: 3.5.3 @@ -5066,7 +5072,7 @@ importers: version: 16.5.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -5250,7 +5256,7 @@ importers: devDependencies: '@electron-toolkit/tsconfig': specifier: ^1.0.1 - version: 1.0.1(@types/node@22.19.19) + version: 1.0.1(@types/node@25.5.2) '@fontsource/lato': specifier: ^5.2.5 version: 5.2.5 @@ -5286,10 +5292,10 @@ importers: version: 26.8.1(dmg-builder@26.8.1) electron-vite: specifier: ^4.0.1 - version: 4.0.1(vite@6.4.2(@types/node@22.19.19)(jiti@2.5.1)(less@4.3.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.0.1(vite@6.4.2(@types/node@25.5.2)(jiti@2.5.1)(less@4.3.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3)) jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@22.19.19)(ts-node@10.9.2(@types/node@22.19.19)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) less: specifier: ^4.2.0 version: 4.3.0 @@ -5307,7 +5313,7 @@ importers: version: 5.4.5 vite: specifier: ^6.4.2 - version: 6.4.2(@types/node@22.19.19)(jiti@2.5.1)(less@4.3.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3) + version: 6.4.2(@types/node@25.5.2)(jiti@2.5.1)(less@4.3.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3) packages/telemetry: dependencies: @@ -5338,7 +5344,7 @@ importers: version: 29.5.14 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -5372,7 +5378,7 @@ importers: version: 16.5.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -5443,7 +5449,7 @@ importers: version: 16.5.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -5471,7 +5477,7 @@ importers: version: 0.25.11 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -5502,7 +5508,7 @@ importers: version: 29.5.14 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -5551,7 +5557,7 @@ importers: version: 29.5.14 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -7778,122 +7784,20 @@ packages: peerDependencies: tslib: '2' - '@jsonjoy.com/base64@17.67.0': - resolution: {integrity: sha512-5SEsJGsm15aP8TQGkDfJvz9axgPwAEm98S5DxOuYe8e1EbfajcDmgeXXzccEjh+mLnjqEKrkBdjHWS5vFNwDdw==} - engines: {node: '>=10.0'} - peerDependencies: - tslib: '2' - - '@jsonjoy.com/buffers@1.2.1': - resolution: {integrity: sha512-12cdlDwX4RUM3QxmUbVJWqZ/mrK6dFQH4Zxq6+r1YXKXYBNgZXndx2qbCJwh3+WWkCSn67IjnlG3XYTvmvYtgA==} - engines: {node: '>=10.0'} - peerDependencies: - tslib: '2' - - '@jsonjoy.com/buffers@17.67.0': - resolution: {integrity: sha512-tfExRpYxBvi32vPs9ZHaTjSP4fHAfzSmcahOfNxtvGHcyJel+aibkPlGeBB+7AoC6hL7lXIE++8okecBxx7lcw==} - engines: {node: '>=10.0'} - peerDependencies: - tslib: '2' - - '@jsonjoy.com/codegen@1.0.0': - resolution: {integrity: sha512-E8Oy+08cmCf0EK/NMxpaJZmOxPqM+6iSe2S4nlSBrPZOORoDJILxtbSUEDKQyTamm/BVAhIGllOBNU79/dwf0g==} - engines: {node: '>=10.0'} - peerDependencies: - tslib: '2' - - '@jsonjoy.com/codegen@17.67.0': - resolution: {integrity: sha512-idnkUplROpdBOV0HMcwhsCUS5TRUi9poagdGs70A6S4ux9+/aPuKbh8+UYRTLYQHtXvAdNfQWXDqZEx5k4Dj2Q==} - engines: {node: '>=10.0'} - peerDependencies: - tslib: '2' - - '@jsonjoy.com/fs-core@4.57.2': - resolution: {integrity: sha512-SVjwklkpIV5wrynpYtuYnfYH1QF4/nDuLBX7VXdb+3miglcAgBVZb/5y0cOsehRV/9Vb+3UqhkMq3/NR3ztdkQ==} - engines: {node: '>=10.0'} - peerDependencies: - tslib: '2' - - '@jsonjoy.com/fs-fsa@4.57.2': - resolution: {integrity: sha512-fhO8+iR2I+OCw668ISDJdn1aArc9zx033sWejIyzQ8RBeXa9bDSaUeA3ix0poYOfrj1KdOzytmYNv2/uLDfV6g==} - engines: {node: '>=10.0'} - peerDependencies: - tslib: '2' - - '@jsonjoy.com/fs-node-builtins@4.57.2': - resolution: {integrity: sha512-xhiegylRmhw43Ki2HO1ZBL7DQ5ja/qpRsL29VtQ2xuUHiuDGbgf2uD4p9Qd8hJI5P6RCtGYD50IXHXVq/Ocjcg==} - engines: {node: '>=10.0'} - peerDependencies: - tslib: '2' - - '@jsonjoy.com/fs-node-to-fsa@4.57.2': - resolution: {integrity: sha512-18LmWTSONhoAPW+IWRuf8w/+zRolPFGPeGwMxlAhhfY11EKzX+5XHDBPAw67dBF5dxDErHJbl40U+3IXSDRXSQ==} - engines: {node: '>=10.0'} - peerDependencies: - tslib: '2' - - '@jsonjoy.com/fs-node-utils@4.57.2': - resolution: {integrity: sha512-rsPSJgekz43IlNbLyAM/Ab+ouYLWGp5DDBfYBNNEqDaSpsbXfthBn29Q4muFA9L0F+Z3mKo+CWlgSCXrf+mOyQ==} - engines: {node: '>=10.0'} - peerDependencies: - tslib: '2' - - '@jsonjoy.com/fs-node@4.57.2': - resolution: {integrity: sha512-nX2AdL6cOFwLdju9G4/nbRnYevmCJbh7N7hvR3gGm97Cs60uEjyd0rpR+YBS7cTg175zzl22pGKXR5USaQMvKg==} - engines: {node: '>=10.0'} - peerDependencies: - tslib: '2' - - '@jsonjoy.com/fs-print@4.57.2': - resolution: {integrity: sha512-wK9NSow48i4DbDl9F1CQE5TqnyZOJ04elU3WFG5aJ76p+YxO/ulyBBQvKsessPxdo381Bc2pcEoyPujMOhcRqQ==} - engines: {node: '>=10.0'} - peerDependencies: - tslib: '2' - - '@jsonjoy.com/fs-snapshot@4.57.2': - resolution: {integrity: sha512-GdduDZuoP5V/QCgJkx9+BZ6SC0EZ/smXAdTS7PfMqgMTGXLlt/bH/FqMYaqB9JmLf05sJPtO0XRbAwwkEEPbVw==} - engines: {node: '>=10.0'} - peerDependencies: - tslib: '2' - - '@jsonjoy.com/json-pack@1.21.0': - resolution: {integrity: sha512-+AKG+R2cfZMShzrF2uQw34v3zbeDYUqnQ+jg7ORic3BGtfw9p/+N6RJbq/kkV8JmYZaINknaEQ2m0/f693ZPpg==} - engines: {node: '>=10.0'} - peerDependencies: - tslib: '2' - - '@jsonjoy.com/json-pack@17.67.0': - resolution: {integrity: sha512-t0ejURcGaZsn1ClbJ/3kFqSOjlryd92eQY465IYrezsXmPcfHPE/av4twRSxf6WE+TkZgLY+71vCZbiIiFKA/w==} - engines: {node: '>=10.0'} - peerDependencies: - tslib: '2' - - '@jsonjoy.com/json-pointer@1.0.2': - resolution: {integrity: sha512-Fsn6wM2zlDzY1U+v4Nc8bo3bVqgfNTGcn6dMgs6FjrEnt4ZCe60o6ByKRjOGlI2gow0aE/Q41QOigdTqkyK5fg==} - engines: {node: '>=10.0'} - peerDependencies: - tslib: '2' - - '@jsonjoy.com/json-pointer@17.67.0': - resolution: {integrity: sha512-+iqOFInH+QZGmSuaybBUNdh7yvNrXvqR+h3wjXm0N/3JK1EyyFAeGJvqnmQL61d1ARLlk/wJdFKSL+LHJ1eaUA==} - engines: {node: '>=10.0'} - peerDependencies: - tslib: '2' - - '@jsonjoy.com/util@1.9.0': - resolution: {integrity: sha512-pLuQo+VPRnN8hfPqUTLTHk126wuYdXVxE6aDmjSeV4NCAgyxWbiOIeNJVtID3h1Vzpoi9m4jXezf73I6LgabgQ==} + '@jsonjoy.com/json-pack@1.0.4': + resolution: {integrity: sha512-aOcSN4MeAtFROysrbqG137b7gaDDSmVrl5mpo6sT/w+kcXpWnzhMjmY/Fh/sDx26NBxyIE7MB1seqLeCAzy9Sg==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' - '@jsonjoy.com/util@17.67.0': - resolution: {integrity: sha512-6+8xBaz1rLSohlGh68D1pdw3AwDi9xydm8QNlAFkvnavCJYSze+pxoW2VKP8p308jtlMRLs5NTHfPlZLd4w7ew==} + '@jsonjoy.com/util@1.2.0': + resolution: {integrity: sha512-4B8B+3vFsY4eo33DMKyJPlQ3sBMpPFUZK2dr3O3rXrOGKKbYG44J0XSFkDo1VOQiri5HFEhIeVvItjR2xcazmg==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' - '@leichtgewicht/ip-codec@2.0.5': - resolution: {integrity: sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==} + '@leichtgewicht/ip-codec@2.0.4': + resolution: {integrity: sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==} '@lezer/common@1.2.3': resolution: {integrity: sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA==} @@ -9197,11 +9101,8 @@ packages: '@types/express-serve-static-core@4.17.41': resolution: {integrity: sha512-OaJ7XLaelTgrvlZD8/aa0vvvxZdUmlCn6MtWeB7TkiKW70BQLc9XEPpDLPdbo52ZhXUCrznlWdCHWxJWtdyajA==} - '@types/express-serve-static-core@4.19.8': - resolution: {integrity: sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==} - - '@types/express-serve-static-core@5.1.1': - resolution: {integrity: sha512-v4zIMr/cX7/d2BpAEX3KNKL/JrT1s43s96lLvvdTmza1oEvDudCqK9aF/djc/SWgy8Yh0h30TZx5VpzqFCxk5A==} + '@types/express-serve-static-core@4.19.6': + resolution: {integrity: sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==} '@types/express@4.17.21': resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} @@ -9266,11 +9167,8 @@ packages: '@types/http-errors@2.0.4': resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==} - '@types/http-errors@2.0.5': - resolution: {integrity: sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==} - - '@types/http-proxy@1.17.17': - resolution: {integrity: sha512-ED6LB+Z1AVylNTu7hdzuBqOgMnvG/ld6wGCG8wFnAzKX5uyW2K3WD52v0gnLCTK/VLpXtKckgWuyScYK6cSPaw==} + '@types/http-proxy@1.17.14': + resolution: {integrity: sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==} '@types/istanbul-lib-coverage@2.0.6': resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} @@ -9377,14 +9275,11 @@ packages: '@types/node@22.15.18': resolution: {integrity: sha512-v1DKRfUdyW+jJhZNEI1PYy29S2YRxMV5AOO/x/SjKmW0acCIOqmbj6Haf9eHAhsPmrhlHSxEhv/1WszcLWV4cg==} - '@types/node@22.19.19': - resolution: {integrity: sha512-dyh/xO2Fh5bYrfWaaqGrRQQGkNdmYw6AmaAUvYeUMNTWQtvb796ikLdmTchRmOlOiIJ1TDXfWgVx1QkUlQ6Hew==} - '@types/node@24.12.2': resolution: {integrity: sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g==} - '@types/node@25.9.1': - resolution: {integrity: sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg==} + '@types/node@25.5.2': + resolution: {integrity: sha512-tO4ZIRKNC+MDWV4qKVZe3Ql/woTnmHDr5JD8UI5hn2pwBrHEwOEMZK7WlNb5RKB6EoJ02gwmQS9OrjuFnZYdpg==} '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} @@ -9407,9 +9302,6 @@ packages: '@types/qs@6.15.0': resolution: {integrity: sha512-JawvT8iBVWpzTrz3EGw9BTQFg3BQNmwERdKE22vlTxawwtbyUSlMppvZYKLZzB5zgACXdXxbD3m1bXaMqP/9ow==} - '@types/qs@6.15.1': - resolution: {integrity: sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw==} - '@types/range-parser@1.2.7': resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} @@ -9434,18 +9326,9 @@ packages: '@types/send@0.17.4': resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} - '@types/send@0.17.6': - resolution: {integrity: sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==} - - '@types/send@1.2.1': - resolution: {integrity: sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==} - '@types/serve-index@1.9.4': resolution: {integrity: sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==} - '@types/serve-static@1.15.10': - resolution: {integrity: sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==} - '@types/serve-static@1.15.5': resolution: {integrity: sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==} @@ -9861,15 +9744,12 @@ packages: peerDependencies: ajv: ^8.8.2 - ajv@6.15.0: - resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==} + ajv@6.14.0: + resolution: {integrity: sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==} ajv@8.18.0: resolution: {integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==} - ajv@8.20.0: - resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==} - ansi-escapes@4.3.2: resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} engines: {node: '>=8'} @@ -10155,8 +10035,8 @@ packages: bignumber.js@9.3.1: resolution: {integrity: sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==} - binary-extensions@2.3.0: - resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + binary-extensions@2.2.0: + resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} engines: {node: '>=8'} binaryextensions@4.19.0: @@ -10173,16 +10053,12 @@ packages: resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - body-parser@1.20.5: - resolution: {integrity: sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - body-parser@2.2.2: resolution: {integrity: sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==} engines: {node: '>=18'} - bonjour-service@1.3.0: - resolution: {integrity: sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA==} + bonjour-service@1.2.1: + resolution: {integrity: sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==} boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} @@ -11102,18 +10978,10 @@ packages: resolution: {integrity: sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==} engines: {node: '>=18'} - default-browser-id@5.0.1: - resolution: {integrity: sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==} - engines: {node: '>=18'} - default-browser@5.2.1: resolution: {integrity: sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==} engines: {node: '>=18'} - default-browser@5.5.0: - resolution: {integrity: sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==} - engines: {node: '>=18'} - default-gateway@6.0.3: resolution: {integrity: sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==} engines: {node: '>= 10'} @@ -11629,10 +11497,6 @@ packages: resolution: {integrity: sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==} engines: {node: '>= 0.10.0'} - express@4.22.2: - resolution: {integrity: sha512-IuL+Elrou2ZvCFHs18/CIzy2Nzvo25nZ1/D2eIZlz7c+QUayAcYoiM2BthCjs+EBHVpjYjcuLDAiCWgeIX3X1Q==} - engines: {node: '>= 0.10.0'} - express@5.2.1: resolution: {integrity: sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==} engines: {node: '>= 18'} @@ -11672,9 +11536,6 @@ packages: fast-uri@3.1.0: resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} - fast-uri@3.1.2: - resolution: {integrity: sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==} - fast-xml-builder@1.1.5: resolution: {integrity: sha512-4TJn/8FKLeslLAH3dnohXqE3QSoxkhvaMzepOIZytwJXZO69Bfz0HBdDHzOTOon6G59Zrk6VQ2bEiv1t61rfkA==} @@ -11953,12 +11814,6 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} - glob-to-regex.js@1.2.0: - resolution: {integrity: sha512-QMwlOQKU/IzqMUOAZWubUOT8Qft+Y0KQWnX9nK3ch0CJg0tTp4TvGZsTfudYKv2NzoQSyPcnA6TYeIQ3jGichQ==} - engines: {node: '>=10.0'} - peerDependencies: - tslib: '2' - glob-to-regexp@0.4.1: resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} @@ -12238,8 +12093,8 @@ packages: resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} engines: {node: '>= 0.8'} - http-parser-js@0.5.10: - resolution: {integrity: sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==} + http-parser-js@0.5.8: + resolution: {integrity: sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==} http-proxy-agent@7.0.2: resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} @@ -12422,8 +12277,8 @@ packages: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} engines: {node: '>= 0.10'} - ipaddr.js@2.4.0: - resolution: {integrity: sha512-9VGk3HGanVE6JoZXHiCpnGy5X0jYDnN4EA4lntFPj+1vIWlFhIylq2CrrCOJH9EAhc5CYhq18F2Av2tgoAPsYQ==} + ipaddr.js@2.1.0: + resolution: {integrity: sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==} engines: {node: '>= 10'} is-absolute-url@4.0.1: @@ -12553,8 +12408,8 @@ packages: resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} engines: {node: '>= 0.4'} - is-network-error@1.3.2: - resolution: {integrity: sha512-PhBY86zaxNZUuWP6h13Vu5oFe0XY6/UlKzQnYFELzGVHygP3MxmvTfYSG7GN3aIab/iWudSMgjSnG9Dq+nHrgA==} + is-network-error@1.1.0: + resolution: {integrity: sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g==} engines: {node: '>=16'} is-number-object@1.1.1: @@ -12666,10 +12521,6 @@ packages: resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} engines: {node: '>=16'} - is-wsl@3.1.1: - resolution: {integrity: sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==} - engines: {node: '>=16'} - isarray@0.0.1: resolution: {integrity: sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==} @@ -13084,8 +12935,8 @@ packages: koffi@2.11.0: resolution: {integrity: sha512-AJ6MHz9Z8OIftKu322jrKJFvy/rZTdCD4b7F457WrK71rxYV7O5PSdWsJDN0p3rY1BZaPeLHVwyt4i2Xyk8wJg==} - launch-editor@2.13.2: - resolution: {integrity: sha512-4VVDnbOpLXy/s8rdRCSXb+zfMeFR0WlJWpET1iA9CQdlZDfwyLjUuGQzXU4VeOoey6AicSAluWan7Etga6Kcmg==} + launch-editor@2.9.1: + resolution: {integrity: sha512-Gcnl4Bd+hRO9P9icCP/RVVT2o8SFlPXofuCxvA2SaZuH45whSvf5p8x5oih5ftLiVhEI4sp5xDY+R+b3zJBh5w==} layout-base@1.0.2: resolution: {integrity: sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==} @@ -13435,10 +13286,9 @@ packages: resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==} engines: {node: '>= 0.8'} - memfs@4.57.2: - resolution: {integrity: sha512-2nWzSsJzrukurSDna4Z0WywuScK4Id3tSKejgu74u8KCdW4uNrseKRSIDg75C6Yw5ZRqBe0F0EtMNlTbUq8bAQ==} - peerDependencies: - tslib: '2' + memfs@4.9.3: + resolution: {integrity: sha512-bsYSSnirtYTWi1+OPMFb0M048evMKyUYe0EbtuGQgq6BVQM1g1W8/KIUJCCvjgI/El0j6Q4WsmMiBwLUBSw8LA==} + engines: {node: '>= 4.0.0'} memory-pager@1.5.0: resolution: {integrity: sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==} @@ -13954,10 +13804,6 @@ packages: resolution: {integrity: sha512-cxN6aIDPz6rm8hbebcP7vrQNhvRcveZoJU72Y7vskh4oIm+BZwBECnx5nTmrlres1Qapvx27Qo1Auukpf8PKXw==} engines: {node: '>=18'} - open@10.2.0: - resolution: {integrity: sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==} - engines: {node: '>=18'} - open@8.4.2: resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} engines: {node: '>=12'} @@ -14033,8 +13879,8 @@ packages: resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} engines: {node: '>=10'} - p-retry@6.2.1: - resolution: {integrity: sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==} + p-retry@6.2.0: + resolution: {integrity: sha512-JA6nkq6hKyWLLasXQXUrO4z8BUZGUt/LjlJxx8Gb2+2ntodU/SS63YZ8b0LUTbQ8ZB9iwOfhEPhg4ykKnn2KsA==} engines: {node: '>=16.17'} p-timeout@3.2.0: @@ -14212,10 +14058,6 @@ packages: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} - picomatch@2.3.2: - resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==} - engines: {node: '>=8.6'} - picomatch@4.0.3: resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} engines: {node: '>=12'} @@ -14553,10 +14395,6 @@ packages: resolution: {integrity: sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==} engines: {node: '>=0.6'} - qs@6.15.2: - resolution: {integrity: sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==} - engines: {node: '>=0.6'} - querystringify@2.2.0: resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} @@ -14575,10 +14413,6 @@ packages: resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} engines: {node: '>= 0.8'} - raw-body@2.5.3: - resolution: {integrity: sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==} - engines: {node: '>= 0.8'} - raw-body@3.0.2: resolution: {integrity: sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==} engines: {node: '>= 0.10'} @@ -14953,10 +14787,6 @@ packages: resolution: {integrity: sha512-p4rRk4f23ynFEfcD9LA0xRYngj+IyGiEYyqqOak8kaN0TvNmuxC2dcVeBn62GpCeR2CpWqyHCNScTP91QbAVFg==} engines: {node: '>= 0.8.0'} - send@0.19.2: - resolution: {integrity: sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==} - engines: {node: '>= 0.8.0'} - send@1.2.1: resolution: {integrity: sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==} engines: {node: '>= 18'} @@ -14969,18 +14799,14 @@ packages: resolution: {integrity: sha512-F4LcB0UqUl1zErq+1nYEEzSHJnIwb3AF2XWB94b+afhrekOUijwooAYqFyRbjYkm2PAKBabx6oYv/xDxNi8IBw==} engines: {node: '>=20.0.0'} - serve-index@1.9.2: - resolution: {integrity: sha512-KDj11HScOaLmrPxl70KYNW1PksP4Nb/CLL2yvC+Qd2kHMPEEpfc4Re2e4FOay+bC/+XQl/7zAcWON3JVo5v3KQ==} + serve-index@1.9.1: + resolution: {integrity: sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==} engines: {node: '>= 0.8.0'} serve-static@1.16.2: resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==} engines: {node: '>= 0.8.0'} - serve-static@1.16.3: - resolution: {integrity: sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==} - engines: {node: '>= 0.8.0'} - serve-static@2.2.1: resolution: {integrity: sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==} engines: {node: '>= 18'} @@ -15037,10 +14863,6 @@ packages: shell-quote@1.8.1: resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==} - shell-quote@1.8.3: - resolution: {integrity: sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==} - engines: {node: '>= 0.4'} - shelljs@0.9.2: resolution: {integrity: sha512-S3I64fEiKgTZzKCC46zT/Ib9meqofLrQVbpSswtjFfAVDW+AZ54WTnAM/3/yENoxz/V1Cy6u3kiiEbQ4DNphvw==} engines: {node: '>=18'} @@ -15454,8 +15276,8 @@ packages: thenify@3.3.1: resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} - thingies@2.6.0: - resolution: {integrity: sha512-rMHRjmlFLM1R96UYPvpmnc3LYtdFrT33JIB7L9hetGue1qAPfn1N2LJeEjxUSidu1Iku+haLZXDuEXUHNGO/lg==} + thingies@1.21.0: + resolution: {integrity: sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g==} engines: {node: '>=10.18'} peerDependencies: tslib: ^2 @@ -15563,8 +15385,8 @@ packages: resolution: {integrity: sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==} engines: {node: '>=20'} - tree-dump@1.1.0: - resolution: {integrity: sha512-rMuvhU4MCDbcbnleZTFezWsaZXRFemSqAM+7jPnzUl1fo9w3YEKOxAeui0fz3OI4EU4hf23iyA7uQRVko+UaBA==} + tree-dump@1.0.2: + resolution: {integrity: sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' @@ -15800,12 +15622,12 @@ packages: undici-types@7.16.0: resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} + undici-types@7.18.2: + resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} + undici-types@7.24.4: resolution: {integrity: sha512-cRaY9PagdEZoRmcwzk3tUV3SVGrVQkR6bcSilav/A0vXsfpW4Lvd0BvgRMwTEDTLLGN+QdyBTG+nnvTgJhdt6w==} - undici-types@7.24.6: - resolution: {integrity: sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==} - undici@6.25.0: resolution: {integrity: sha512-ZgpWDC5gmNiuY9CnLVXEH8rl50xhRCuLNA97fAUnKi8RRuV4E6KG31pDTsLVUKnohJE0I3XDrTeEydAXRw47xg==} engines: {node: '>=18.17'} @@ -16123,8 +15945,8 @@ packages: webpack-dev-server: optional: true - webpack-dev-middleware@7.4.5: - resolution: {integrity: sha512-uxQ6YqGdE4hgDKNf7hUiPXOdtkXvBJXrfEGYSx7P7LC8hnUYGK70X6xQXUvXeNyBDDcsiQXpG2m3G9vxowaEuA==} + webpack-dev-middleware@7.4.2: + resolution: {integrity: sha512-xOO8n6eggxnwYpy1NlzUKpvrjfJTvae5/D6WOK0S2LSo7vjmo5gCM1DbLUmFqrMTJP+W/0YZNctm7jasWvLuBA==} engines: {node: '>= 18.12.0'} peerDependencies: webpack: ^5.0.0 @@ -16321,10 +16143,6 @@ packages: utf-8-validate: optional: true - wsl-utils@0.1.0: - resolution: {integrity: sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==} - engines: {node: '>=18'} - xml-name-validator@4.0.0: resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} engines: {node: '>=12'} @@ -17594,7 +17412,7 @@ snapshots: '@babel/types': 7.28.4 '@jridgewell/remapping': 2.3.5 convert-source-map: 2.0.0 - debug: 4.4.1 + debug: 4.4.3(supports-color@8.1.1) gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -18084,8 +17902,8 @@ snapshots: '@develar/schema-utils@2.6.5': dependencies: - ajv: 6.15.0 - ajv-keywords: 3.5.2(ajv@6.15.0) + ajv: 6.14.0 + ajv-keywords: 3.5.2(ajv@6.14.0) '@discoveryjs/json-ext@0.5.7': {} @@ -18114,9 +17932,9 @@ snapshots: dependencies: electron: 40.8.5 - '@electron-toolkit/tsconfig@1.0.1(@types/node@22.19.19)': + '@electron-toolkit/tsconfig@1.0.1(@types/node@25.5.2)': dependencies: - '@types/node': 22.19.19 + '@types/node': 25.5.2 '@electron/asar@3.4.1': dependencies: @@ -18941,7 +18759,7 @@ snapshots: '@jest/console@29.7.0': dependencies: '@jest/types': 29.6.3 - '@types/node': 22.19.19 + '@types/node': 22.15.18 chalk: 4.1.2 jest-message-util: 29.7.0 jest-util: 29.7.0 @@ -18982,42 +18800,7 @@ snapshots: - supports-color - ts-node - '@jest/core@29.7.0(ts-node@10.9.2(@types/node@22.19.19)(typescript@5.4.5))': - dependencies: - '@jest/console': 29.7.0 - '@jest/reporters': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 22.15.18 - ansi-escapes: 4.3.2 - chalk: 4.1.2 - ci-info: 3.9.0 - exit: 0.1.2 - graceful-fs: 4.2.11 - jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@22.15.18)(ts-node@10.9.2(@types/node@22.19.19)(typescript@5.4.5)) - jest-haste-map: 29.7.0 - jest-message-util: 29.7.0 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-resolve-dependencies: 29.7.0 - jest-runner: 29.7.0 - jest-runtime: 29.7.0 - jest-snapshot: 29.7.0 - jest-util: 29.7.0 - jest-validate: 29.7.0 - jest-watcher: 29.7.0 - micromatch: 4.0.8 - pretty-format: 29.7.0 - slash: 3.0.0 - strip-ansi: 6.0.1 - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - - ts-node - - '@jest/core@29.7.0(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5))': + '@jest/core@29.7.0(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5))': dependencies: '@jest/console': 29.7.0 '@jest/reporters': 29.7.0 @@ -19031,7 +18814,7 @@ snapshots: exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@22.15.18)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + jest-config: 29.7.0(@types/node@22.15.18)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -19096,7 +18879,7 @@ snapshots: '@jest/transform': 29.7.0 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.31 - '@types/node': 22.19.19 + '@types/node': 22.15.18 chalk: 4.1.2 collect-v8-coverage: 1.0.2 exit: 0.1.2 @@ -19210,130 +18993,19 @@ snapshots: dependencies: tslib: 2.8.1 - '@jsonjoy.com/base64@17.67.0(tslib@2.8.1)': - dependencies: - tslib: 2.8.1 - - '@jsonjoy.com/buffers@1.2.1(tslib@2.8.1)': - dependencies: - tslib: 2.8.1 - - '@jsonjoy.com/buffers@17.67.0(tslib@2.8.1)': - dependencies: - tslib: 2.8.1 - - '@jsonjoy.com/codegen@1.0.0(tslib@2.8.1)': - dependencies: - tslib: 2.8.1 - - '@jsonjoy.com/codegen@17.67.0(tslib@2.8.1)': - dependencies: - tslib: 2.8.1 - - '@jsonjoy.com/fs-core@4.57.2(tslib@2.8.1)': - dependencies: - '@jsonjoy.com/fs-node-builtins': 4.57.2(tslib@2.8.1) - '@jsonjoy.com/fs-node-utils': 4.57.2(tslib@2.8.1) - thingies: 2.6.0(tslib@2.8.1) - tslib: 2.8.1 - - '@jsonjoy.com/fs-fsa@4.57.2(tslib@2.8.1)': - dependencies: - '@jsonjoy.com/fs-core': 4.57.2(tslib@2.8.1) - '@jsonjoy.com/fs-node-builtins': 4.57.2(tslib@2.8.1) - '@jsonjoy.com/fs-node-utils': 4.57.2(tslib@2.8.1) - thingies: 2.6.0(tslib@2.8.1) - tslib: 2.8.1 - - '@jsonjoy.com/fs-node-builtins@4.57.2(tslib@2.8.1)': - dependencies: - tslib: 2.8.1 - - '@jsonjoy.com/fs-node-to-fsa@4.57.2(tslib@2.8.1)': - dependencies: - '@jsonjoy.com/fs-fsa': 4.57.2(tslib@2.8.1) - '@jsonjoy.com/fs-node-builtins': 4.57.2(tslib@2.8.1) - '@jsonjoy.com/fs-node-utils': 4.57.2(tslib@2.8.1) - tslib: 2.8.1 - - '@jsonjoy.com/fs-node-utils@4.57.2(tslib@2.8.1)': - dependencies: - '@jsonjoy.com/fs-node-builtins': 4.57.2(tslib@2.8.1) - tslib: 2.8.1 - - '@jsonjoy.com/fs-node@4.57.2(tslib@2.8.1)': - dependencies: - '@jsonjoy.com/fs-core': 4.57.2(tslib@2.8.1) - '@jsonjoy.com/fs-node-builtins': 4.57.2(tslib@2.8.1) - '@jsonjoy.com/fs-node-utils': 4.57.2(tslib@2.8.1) - '@jsonjoy.com/fs-print': 4.57.2(tslib@2.8.1) - '@jsonjoy.com/fs-snapshot': 4.57.2(tslib@2.8.1) - glob-to-regex.js: 1.2.0(tslib@2.8.1) - thingies: 2.6.0(tslib@2.8.1) - tslib: 2.8.1 - - '@jsonjoy.com/fs-print@4.57.2(tslib@2.8.1)': - dependencies: - '@jsonjoy.com/fs-node-utils': 4.57.2(tslib@2.8.1) - tree-dump: 1.1.0(tslib@2.8.1) - tslib: 2.8.1 - - '@jsonjoy.com/fs-snapshot@4.57.2(tslib@2.8.1)': - dependencies: - '@jsonjoy.com/buffers': 17.67.0(tslib@2.8.1) - '@jsonjoy.com/fs-node-utils': 4.57.2(tslib@2.8.1) - '@jsonjoy.com/json-pack': 17.67.0(tslib@2.8.1) - '@jsonjoy.com/util': 17.67.0(tslib@2.8.1) - tslib: 2.8.1 - - '@jsonjoy.com/json-pack@1.21.0(tslib@2.8.1)': + '@jsonjoy.com/json-pack@1.0.4(tslib@2.8.1)': dependencies: '@jsonjoy.com/base64': 1.1.2(tslib@2.8.1) - '@jsonjoy.com/buffers': 1.2.1(tslib@2.8.1) - '@jsonjoy.com/codegen': 1.0.0(tslib@2.8.1) - '@jsonjoy.com/json-pointer': 1.0.2(tslib@2.8.1) - '@jsonjoy.com/util': 1.9.0(tslib@2.8.1) - hyperdyperid: 1.2.0 - thingies: 2.6.0(tslib@2.8.1) - tree-dump: 1.1.0(tslib@2.8.1) - tslib: 2.8.1 - - '@jsonjoy.com/json-pack@17.67.0(tslib@2.8.1)': - dependencies: - '@jsonjoy.com/base64': 17.67.0(tslib@2.8.1) - '@jsonjoy.com/buffers': 17.67.0(tslib@2.8.1) - '@jsonjoy.com/codegen': 17.67.0(tslib@2.8.1) - '@jsonjoy.com/json-pointer': 17.67.0(tslib@2.8.1) - '@jsonjoy.com/util': 17.67.0(tslib@2.8.1) + '@jsonjoy.com/util': 1.2.0(tslib@2.8.1) hyperdyperid: 1.2.0 - thingies: 2.6.0(tslib@2.8.1) - tree-dump: 1.1.0(tslib@2.8.1) - tslib: 2.8.1 - - '@jsonjoy.com/json-pointer@1.0.2(tslib@2.8.1)': - dependencies: - '@jsonjoy.com/codegen': 1.0.0(tslib@2.8.1) - '@jsonjoy.com/util': 1.9.0(tslib@2.8.1) - tslib: 2.8.1 - - '@jsonjoy.com/json-pointer@17.67.0(tslib@2.8.1)': - dependencies: - '@jsonjoy.com/util': 17.67.0(tslib@2.8.1) + thingies: 1.21.0(tslib@2.8.1) tslib: 2.8.1 - '@jsonjoy.com/util@1.9.0(tslib@2.8.1)': + '@jsonjoy.com/util@1.2.0(tslib@2.8.1)': dependencies: - '@jsonjoy.com/buffers': 1.2.1(tslib@2.8.1) - '@jsonjoy.com/codegen': 1.0.0(tslib@2.8.1) tslib: 2.8.1 - '@jsonjoy.com/util@17.67.0(tslib@2.8.1)': - dependencies: - '@jsonjoy.com/buffers': 17.67.0(tslib@2.8.1) - '@jsonjoy.com/codegen': 17.67.0(tslib@2.8.1) - tslib: 2.8.1 - - '@leichtgewicht/ip-codec@2.0.5': {} + '@leichtgewicht/ip-codec@2.0.4': {} '@lezer/common@1.2.3': {} @@ -20581,7 +20253,7 @@ snapshots: '@secretlint/profiler': 9.3.2 '@secretlint/resolver': 9.3.2 '@secretlint/types': 9.3.2 - ajv: 8.20.0 + ajv: 8.18.0 debug: 4.4.3(supports-color@8.1.1) rc-config-loader: 4.1.3 transitivePeerDependencies: @@ -21081,7 +20753,7 @@ snapshots: '@types/accepts@1.3.7': dependencies: - '@types/node': 22.19.19 + '@types/node': 22.15.18 '@types/async@3.2.24': {} @@ -21123,13 +20795,13 @@ snapshots: '@types/bonjour@3.5.13': dependencies: - '@types/node': 22.19.19 + '@types/node': 22.15.18 '@types/cacheable-request@6.0.3': dependencies: '@types/http-cache-semantics': 4.2.0 '@types/keyv': 3.1.4 - '@types/node': 22.19.19 + '@types/node': 22.15.18 '@types/responselike': 1.0.3 '@types/chai-dom@1.11.3': @@ -21160,8 +20832,8 @@ snapshots: '@types/co-body@6.1.3': dependencies: - '@types/node': 22.19.19 - '@types/qs': 6.15.1 + '@types/node': 22.15.18 + '@types/qs': 6.15.0 '@types/command-line-args@5.2.3': {} @@ -21169,8 +20841,8 @@ snapshots: '@types/connect-history-api-fallback@1.5.4': dependencies: - '@types/express-serve-static-core': 5.1.1 - '@types/node': 22.19.19 + '@types/express-serve-static-core': 4.19.6 + '@types/node': 22.15.18 '@types/connect@3.4.38': dependencies: @@ -21183,9 +20855,9 @@ snapshots: '@types/cookies@0.9.2': dependencies: '@types/connect': 3.4.38 - '@types/express': 4.17.25 + '@types/express': 4.17.21 '@types/keygrip': 1.0.6 - '@types/node': 22.19.19 + '@types/node': 22.15.18 '@types/cors@2.8.18': dependencies: @@ -21343,19 +21015,12 @@ snapshots: '@types/range-parser': 1.2.7 '@types/send': 0.17.4 - '@types/express-serve-static-core@4.19.8': + '@types/express-serve-static-core@4.19.6': dependencies: - '@types/node': 22.19.19 - '@types/qs': 6.15.1 - '@types/range-parser': 1.2.7 - '@types/send': 1.2.1 - - '@types/express-serve-static-core@5.1.1': - dependencies: - '@types/node': 22.19.19 - '@types/qs': 6.15.1 + '@types/node': 22.15.18 + '@types/qs': 6.15.0 '@types/range-parser': 1.2.7 - '@types/send': 1.2.1 + '@types/send': 0.17.4 '@types/express@4.17.21': dependencies: @@ -21367,9 +21032,9 @@ snapshots: '@types/express@4.17.25': dependencies: '@types/body-parser': 1.19.5 - '@types/express-serve-static-core': 4.19.8 - '@types/qs': 6.15.1 - '@types/serve-static': 1.15.10 + '@types/express-serve-static-core': 4.19.6 + '@types/qs': 6.15.0 + '@types/serve-static': 1.15.5 '@types/fast-levenshtein@0.0.4': {} @@ -21396,18 +21061,18 @@ snapshots: '@types/fs-extra@9.0.13': dependencies: - '@types/node': 22.19.19 + '@types/node': 22.15.18 '@types/geojson@7946.0.16': {} '@types/glob@7.2.0': dependencies: '@types/minimatch': 5.1.2 - '@types/node': 22.19.19 + '@types/node': 22.15.18 '@types/graceful-fs@4.1.8': dependencies: - '@types/node': 22.19.19 + '@types/node': 22.15.18 '@types/har-format@1.2.15': {} @@ -21425,11 +21090,9 @@ snapshots: '@types/http-errors@2.0.4': {} - '@types/http-errors@2.0.5': {} - - '@types/http-proxy@1.17.17': + '@types/http-proxy@1.17.14': dependencies: - '@types/node': 22.19.19 + '@types/node': 22.15.18 '@types/istanbul-lib-coverage@2.0.6': {} @@ -21479,7 +21142,7 @@ snapshots: '@types/keyv@3.1.4': dependencies: - '@types/node': 22.19.19 + '@types/node': 22.15.18 '@types/koa-compose@3.2.9': dependencies: @@ -21491,10 +21154,10 @@ snapshots: '@types/content-disposition': 0.5.9 '@types/cookies': 0.9.2 '@types/http-assert': 1.5.6 - '@types/http-errors': 2.0.5 + '@types/http-errors': 2.0.4 '@types/keygrip': 1.0.6 '@types/koa-compose': 3.2.9 - '@types/node': 22.19.19 + '@types/node': 22.15.18 '@types/linkify-it@5.0.0': {} @@ -21557,18 +21220,13 @@ snapshots: dependencies: undici-types: 6.21.0 - '@types/node@22.19.19': - dependencies: - undici-types: 6.21.0 - '@types/node@24.12.2': dependencies: undici-types: 7.16.0 - '@types/node@25.9.1': + '@types/node@25.5.2': dependencies: - undici-types: 7.24.6 - optional: true + undici-types: 7.18.2 '@types/normalize-package-data@2.4.4': {} @@ -21576,7 +21234,7 @@ snapshots: '@types/plist@3.0.5': dependencies: - '@types/node': 22.19.19 + '@types/node': 22.15.18 xmlbuilder: 15.1.1 optional: true @@ -21590,8 +21248,6 @@ snapshots: '@types/qs@6.15.0': {} - '@types/qs@6.15.1': {} - '@types/range-parser@1.2.7': {} '@types/react@18.3.18': @@ -21605,7 +21261,7 @@ snapshots: '@types/responselike@1.0.3': dependencies: - '@types/node': 22.19.19 + '@types/node': 22.15.18 '@types/retry@0.12.2': {} @@ -21614,27 +21270,12 @@ snapshots: '@types/send@0.17.4': dependencies: '@types/mime': 1.3.5 - '@types/node': 22.19.19 - - '@types/send@0.17.6': - dependencies: - '@types/mime': 1.3.5 - '@types/node': 22.19.19 - - '@types/send@1.2.1': - dependencies: - '@types/node': 22.19.19 + '@types/node': 22.15.18 '@types/serve-index@1.9.4': dependencies: '@types/express': 4.17.25 - '@types/serve-static@1.15.10': - dependencies: - '@types/http-errors': 2.0.5 - '@types/node': 22.19.19 - '@types/send': 0.17.6 - '@types/serve-static@1.15.5': dependencies: '@types/http-errors': 2.0.4 @@ -21658,7 +21299,7 @@ snapshots: '@types/sockjs@0.3.36': dependencies: - '@types/node': 22.19.19 + '@types/node': 22.15.18 '@types/spotify-api@0.0.25': {} @@ -21691,7 +21332,7 @@ snapshots: '@types/ws@7.4.7': dependencies: - '@types/node': 22.19.19 + '@types/node': 22.15.18 '@types/ws@8.18.1': dependencies: @@ -21709,7 +21350,7 @@ snapshots: '@types/yauzl@2.10.3': dependencies: - '@types/node': 22.19.19 + '@types/node': 22.15.18 optional: true '@typespec/ts-http-runtime@0.2.2': @@ -22156,7 +21797,7 @@ snapshots: webpack: 5.105.0(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack-dev-server@5.2.4)(webpack@5.105.0) optionalDependencies: - webpack-dev-server: 5.2.4(debug@4.4.1)(tslib@2.8.1)(webpack-cli@5.1.4)(webpack@5.105.0) + webpack-dev-server: 5.2.4(debug@4.4.1)(webpack-cli@5.1.4)(webpack@5.105.0) '@xmldom/xmldom@0.8.10': {} @@ -22233,29 +21874,20 @@ snapshots: optionalDependencies: ajv: 8.18.0 - ajv-formats@2.1.1(ajv@8.20.0): - optionalDependencies: - ajv: 8.20.0 - ajv-formats@3.0.1(ajv@8.18.0): optionalDependencies: ajv: 8.18.0 - ajv-keywords@3.5.2(ajv@6.15.0): + ajv-keywords@3.5.2(ajv@6.14.0): dependencies: - ajv: 6.15.0 + ajv: 6.14.0 ajv-keywords@5.1.0(ajv@8.18.0): dependencies: ajv: 8.18.0 fast-deep-equal: 3.1.3 - ajv-keywords@5.1.0(ajv@8.20.0): - dependencies: - ajv: 8.20.0 - fast-deep-equal: 3.1.3 - - ajv@6.15.0: + ajv@6.14.0: dependencies: fast-deep-equal: 3.1.3 fast-json-stable-stringify: 2.1.0 @@ -22269,14 +21901,7 @@ snapshots: json-schema-traverse: 1.0.0 require-from-string: 2.0.2 - ajv@8.20.0: - dependencies: - fast-deep-equal: 3.1.3 - fast-uri: 3.1.2 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - - ansi-escapes@4.3.2: + ansi-escapes@4.3.2: dependencies: type-fest: 0.21.3 @@ -22313,7 +21938,7 @@ snapshots: anymatch@3.1.3: dependencies: normalize-path: 3.0.0 - picomatch: 2.3.2 + picomatch: 2.3.1 apache-arrow@18.1.0: dependencies: @@ -22346,7 +21971,7 @@ snapshots: builder-util-runtime: 9.5.1 chromium-pickle-js: 0.2.0 ci-info: 4.3.1 - debug: 4.4.1 + debug: 4.4.3(supports-color@8.1.1) dmg-builder: 26.8.1(electron-builder-squirrel-windows@26.8.1) dotenv: 16.5.0 dotenv-expand: 11.0.7 @@ -22617,7 +22242,7 @@ snapshots: bignumber.js@9.3.1: {} - binary-extensions@2.3.0: {} + binary-extensions@2.2.0: {} binaryextensions@4.19.0: {} @@ -22648,23 +22273,6 @@ snapshots: transitivePeerDependencies: - supports-color - body-parser@1.20.5: - dependencies: - bytes: 3.1.2 - content-type: 1.0.5 - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - http-errors: 2.0.1 - iconv-lite: 0.4.24 - on-finished: 2.4.1 - qs: 6.15.2 - raw-body: 2.5.3 - type-is: 1.6.18 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - body-parser@2.2.2: dependencies: bytes: 3.1.2 @@ -22673,13 +22281,13 @@ snapshots: http-errors: 2.0.1 iconv-lite: 0.7.2 on-finished: 2.4.1 - qs: 6.15.2 + qs: 6.15.0 raw-body: 3.0.2 type-is: 2.0.1 transitivePeerDependencies: - supports-color - bonjour-service@1.3.0: + bonjour-service@1.2.1: dependencies: fast-deep-equal: 3.1.3 multicast-dns: 7.2.5 @@ -22766,14 +22374,14 @@ snapshots: builder-util-runtime@9.3.1: dependencies: - debug: 4.4.1 + debug: 4.4.3(supports-color@8.1.1) sax: 1.3.0 transitivePeerDependencies: - supports-color builder-util-runtime@9.5.1: dependencies: - debug: 4.4.1 + debug: 4.4.3(supports-color@8.1.1) sax: 1.3.0 transitivePeerDependencies: - supports-color @@ -22786,7 +22394,7 @@ snapshots: builder-util-runtime: 9.5.1 chalk: 4.1.2 cross-spawn: 7.0.6 - debug: 4.4.1 + debug: 4.4.3(supports-color@8.1.1) fs-extra: 10.1.0 http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.6 @@ -22962,7 +22570,7 @@ snapshots: chrome-launcher@0.15.2: dependencies: - '@types/node': 22.19.19 + '@types/node': 22.15.18 escape-string-regexp: 4.0.0 is-wsl: 2.2.0 lighthouse-logger: 1.4.2 @@ -23085,7 +22693,7 @@ snapshots: dependencies: '@hapi/bourne': 3.0.0 inflation: 2.1.0 - qs: 6.15.2 + qs: 6.15.0 raw-body: 2.5.2 type-is: 1.6.18 @@ -23331,28 +22939,13 @@ snapshots: - supports-color - ts-node - create-jest@29.7.0(@types/node@22.19.19)(ts-node@10.9.2(@types/node@22.19.19)(typescript@5.4.5)): - dependencies: - '@jest/types': 29.6.3 - chalk: 4.1.2 - exit: 0.1.2 - graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@22.19.19)(ts-node@10.9.2(@types/node@22.19.19)(typescript@5.4.5)) - jest-util: 29.7.0 - prompts: 2.4.2 - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - - create-jest@29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)): + create-jest@29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)): dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + jest-config: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -23732,18 +23325,11 @@ snapshots: default-browser-id@5.0.0: {} - default-browser-id@5.0.1: {} - default-browser@5.2.1: dependencies: bundle-name: 4.1.0 default-browser-id: 5.0.0 - default-browser@5.5.0: - dependencies: - bundle-name: 4.1.0 - default-browser-id: 5.0.1 - default-gateway@6.0.3: dependencies: execa: 5.1.1 @@ -23848,7 +23434,7 @@ snapshots: dependencies: '@types/plist': 3.0.5 '@types/verror': 1.10.9 - ajv: 6.15.0 + ajv: 6.14.0 crc: 3.8.0 iconv-corefoundation: 1.1.7 plist: 3.1.0 @@ -23858,7 +23444,7 @@ snapshots: dns-packet@5.6.1: dependencies: - '@leichtgewicht/ip-codec': 2.0.5 + '@leichtgewicht/ip-codec': 2.0.4 dom-converter@0.2.0: dependencies: @@ -24004,7 +23590,7 @@ snapshots: transitivePeerDependencies: - supports-color - electron-vite@4.0.1(vite@6.4.2(@types/node@22.19.19)(jiti@2.5.1)(less@4.3.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3)): + electron-vite@4.0.1(vite@6.4.2(@types/node@25.5.2)(jiti@2.5.1)(less@4.3.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3)): dependencies: '@babel/core': 7.28.4 '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.28.4) @@ -24012,14 +23598,14 @@ snapshots: esbuild: 0.25.11 magic-string: 0.30.17 picocolors: 1.1.1 - vite: 6.4.2(@types/node@22.19.19)(jiti@2.5.1)(less@4.3.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3) + vite: 6.4.2(@types/node@25.5.2)(jiti@2.5.1)(less@4.3.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3) transitivePeerDependencies: - supports-color electron-winstaller@5.4.0: dependencies: '@electron/asar': 3.4.1 - debug: 4.4.1 + debug: 4.4.3(supports-color@8.1.1) fs-extra: 7.0.1 lodash: 4.18.1 temp: 0.9.4 @@ -24454,42 +24040,6 @@ snapshots: transitivePeerDependencies: - supports-color - express@4.22.2: - dependencies: - accepts: 1.3.8 - array-flatten: 1.1.1 - body-parser: 1.20.5 - content-disposition: 0.5.4 - content-type: 1.0.5 - cookie: 0.7.2 - cookie-signature: 1.0.7 - debug: 2.6.9 - depd: 2.0.0 - encodeurl: 2.0.0 - escape-html: 1.0.3 - etag: 1.8.1 - finalhandler: 1.3.2 - fresh: 0.5.2 - http-errors: 2.0.1 - merge-descriptors: 1.0.3 - methods: 1.1.2 - on-finished: 2.4.1 - parseurl: 1.3.3 - path-to-regexp: 0.1.13 - proxy-addr: 2.0.7 - qs: 6.15.2 - range-parser: 1.2.1 - safe-buffer: 5.2.1 - send: 0.19.2 - serve-static: 1.16.3 - setprototypeof: 1.2.0 - statuses: 2.0.2 - type-is: 1.6.18 - utils-merge: 1.0.1 - vary: 1.1.2 - transitivePeerDependencies: - - supports-color - express@5.2.1: dependencies: accepts: 2.0.0 @@ -24566,8 +24116,6 @@ snapshots: fast-uri@3.1.0: {} - fast-uri@3.1.2: {} - fast-xml-builder@1.1.5: dependencies: path-expression-matcher: 1.5.0 @@ -24883,10 +24431,6 @@ snapshots: dependencies: is-glob: 4.0.3 - glob-to-regex.js@1.2.0(tslib@2.8.1): - dependencies: - tslib: 2.8.1 - glob-to-regexp@0.4.1: {} glob@10.5.0: @@ -25283,7 +24827,7 @@ snapshots: statuses: 2.0.2 toidentifier: 1.0.1 - http-parser-js@0.5.10: {} + http-parser-js@0.5.8: {} http-proxy-agent@7.0.2: dependencies: @@ -25294,7 +24838,7 @@ snapshots: http-proxy-middleware@2.0.9(@types/express@4.17.25)(debug@4.4.1): dependencies: - '@types/http-proxy': 1.17.17 + '@types/http-proxy': 1.17.14 http-proxy: 1.18.1(debug@4.4.1) is-glob: 4.0.3 is-plain-obj: 3.0.0 @@ -25480,7 +25024,7 @@ snapshots: ipaddr.js@1.9.1: {} - ipaddr.js@2.4.0: {} + ipaddr.js@2.1.0: {} is-absolute-url@4.0.1: {} @@ -25508,7 +25052,7 @@ snapshots: is-binary-path@2.1.0: dependencies: - binary-extensions: 2.3.0 + binary-extensions: 2.2.0 is-boolean-object@1.2.2: dependencies: @@ -25588,7 +25132,7 @@ snapshots: is-negative-zero@2.0.3: {} - is-network-error@1.3.2: {} + is-network-error@1.1.0: {} is-number-object@1.1.1: dependencies: @@ -25678,10 +25222,6 @@ snapshots: dependencies: is-inside-container: 1.0.0 - is-wsl@3.1.1: - dependencies: - is-inside-container: 1.0.0 - isarray@0.0.1: {} isarray@1.0.0: {} @@ -25786,7 +25326,7 @@ snapshots: '@jest/expect': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.19.19 + '@types/node': 22.15.18 chalk: 4.1.2 co: 4.6.0 dedent: 1.7.0 @@ -25825,35 +25365,16 @@ snapshots: - supports-color - ts-node - jest-cli@29.7.0(@types/node@22.19.19)(ts-node@10.9.2(@types/node@22.19.19)(typescript@5.4.5)): + jest-cli@29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)): dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@22.19.19)(typescript@5.4.5)) + '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@22.19.19)(ts-node@10.9.2(@types/node@22.19.19)(typescript@5.4.5)) + create-jest: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) exit: 0.1.2 import-local: 3.2.0 - jest-config: 29.7.0(@types/node@22.19.19)(ts-node@10.9.2(@types/node@22.19.19)(typescript@5.4.5)) - jest-util: 29.7.0 - jest-validate: 29.7.0 - yargs: 17.7.2 - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - - jest-cli@29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)): - dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) - '@jest/test-result': 29.7.0 - '@jest/types': 29.6.3 - chalk: 4.1.2 - create-jest: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) - exit: 0.1.2 - import-local: 3.2.0 - jest-config: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + jest-config: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -25894,7 +25415,7 @@ snapshots: - babel-plugin-macros - supports-color - jest-config@29.7.0(@types/node@22.15.18)(ts-node@10.9.2(@types/node@22.19.19)(typescript@5.4.5)): + jest-config@29.7.0(@types/node@22.15.18)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)): dependencies: '@babel/core': 7.28.4 '@jest/test-sequencer': 29.7.0 @@ -25920,12 +25441,12 @@ snapshots: strip-json-comments: 3.1.1 optionalDependencies: '@types/node': 22.15.18 - ts-node: 10.9.2(@types/node@22.19.19)(typescript@5.4.5) + ts-node: 10.9.2(@types/node@25.5.2)(typescript@5.4.5) transitivePeerDependencies: - babel-plugin-macros - supports-color - jest-config@29.7.0(@types/node@22.15.18)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)): + jest-config@29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)): dependencies: '@babel/core': 7.28.4 '@jest/test-sequencer': 29.7.0 @@ -25950,70 +25471,8 @@ snapshots: slash: 3.0.0 strip-json-comments: 3.1.1 optionalDependencies: - '@types/node': 22.15.18 - ts-node: 10.9.2(@types/node@25.9.1)(typescript@5.4.5) - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - - jest-config@29.7.0(@types/node@22.19.19)(ts-node@10.9.2(@types/node@22.19.19)(typescript@5.4.5)): - dependencies: - '@babel/core': 7.28.4 - '@jest/test-sequencer': 29.7.0 - '@jest/types': 29.6.3 - babel-jest: 29.7.0(@babel/core@7.28.4) - chalk: 4.1.2 - ci-info: 3.9.0 - deepmerge: 4.3.1 - glob: 7.2.3 - graceful-fs: 4.2.11 - jest-circus: 29.7.0 - jest-environment-node: 29.7.0 - jest-get-type: 29.6.3 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-runner: 29.7.0 - jest-util: 29.7.0 - jest-validate: 29.7.0 - micromatch: 4.0.8 - parse-json: 5.2.0 - pretty-format: 29.7.0 - slash: 3.0.0 - strip-json-comments: 3.1.1 - optionalDependencies: - '@types/node': 22.19.19 - ts-node: 10.9.2(@types/node@22.19.19)(typescript@5.4.5) - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - - jest-config@29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)): - dependencies: - '@babel/core': 7.28.4 - '@jest/test-sequencer': 29.7.0 - '@jest/types': 29.6.3 - babel-jest: 29.7.0(@babel/core@7.28.4) - chalk: 4.1.2 - ci-info: 3.9.0 - deepmerge: 4.3.1 - glob: 7.2.3 - graceful-fs: 4.2.11 - jest-circus: 29.7.0 - jest-environment-node: 29.7.0 - jest-get-type: 29.6.3 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-runner: 29.7.0 - jest-util: 29.7.0 - jest-validate: 29.7.0 - micromatch: 4.0.8 - parse-json: 5.2.0 - pretty-format: 29.7.0 - slash: 3.0.0 - strip-json-comments: 3.1.1 - optionalDependencies: - '@types/node': 25.9.1 - ts-node: 10.9.2(@types/node@25.9.1)(typescript@5.4.5) + '@types/node': 25.5.2 + ts-node: 10.9.2(@types/node@25.5.2)(typescript@5.4.5) transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -26057,7 +25516,7 @@ snapshots: '@jest/environment': 29.7.0 '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.19.19 + '@types/node': 22.15.18 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -26067,7 +25526,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.8 - '@types/node': 22.19.19 + '@types/node': 22.15.18 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -26141,7 +25600,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.19.19 + '@types/node': 22.15.18 chalk: 4.1.2 emittery: 0.13.1 graceful-fs: 4.2.11 @@ -26169,7 +25628,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.19.19 + '@types/node': 22.15.18 chalk: 4.1.2 cjs-module-lexer: 1.2.3 collect-v8-coverage: 1.0.2 @@ -26234,7 +25693,7 @@ snapshots: dependencies: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.19.19 + '@types/node': 22.15.18 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -26243,13 +25702,13 @@ snapshots: jest-worker@27.5.1: dependencies: - '@types/node': 22.19.19 + '@types/node': 22.15.18 merge-stream: 2.0.0 supports-color: 8.1.1 jest-worker@29.7.0: dependencies: - '@types/node': 22.19.19 + '@types/node': 22.15.18 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -26266,24 +25725,12 @@ snapshots: - supports-color - ts-node - jest@29.7.0(@types/node@22.19.19)(ts-node@10.9.2(@types/node@22.19.19)(typescript@5.4.5)): + jest@29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)): dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@22.19.19)(typescript@5.4.5)) + '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) '@jest/types': 29.6.3 import-local: 3.2.0 - jest-cli: 29.7.0(@types/node@22.19.19)(ts-node@10.9.2(@types/node@22.19.19)(typescript@5.4.5)) - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - - jest@29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)): - dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) - '@jest/types': 29.6.3 - import-local: 3.2.0 - jest-cli: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + jest-cli: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -26562,10 +26009,10 @@ snapshots: koffi@2.11.0: {} - launch-editor@2.13.2: + launch-editor@2.9.1: dependencies: picocolors: 1.1.1 - shell-quote: 1.8.3 + shell-quote: 1.8.1 layout-base@1.0.2: {} @@ -26993,21 +26440,11 @@ snapshots: media-typer@1.1.0: {} - memfs@4.57.2(tslib@2.8.1): - dependencies: - '@jsonjoy.com/fs-core': 4.57.2(tslib@2.8.1) - '@jsonjoy.com/fs-fsa': 4.57.2(tslib@2.8.1) - '@jsonjoy.com/fs-node': 4.57.2(tslib@2.8.1) - '@jsonjoy.com/fs-node-builtins': 4.57.2(tslib@2.8.1) - '@jsonjoy.com/fs-node-to-fsa': 4.57.2(tslib@2.8.1) - '@jsonjoy.com/fs-node-utils': 4.57.2(tslib@2.8.1) - '@jsonjoy.com/fs-print': 4.57.2(tslib@2.8.1) - '@jsonjoy.com/fs-snapshot': 4.57.2(tslib@2.8.1) - '@jsonjoy.com/json-pack': 1.21.0(tslib@2.8.1) - '@jsonjoy.com/util': 1.9.0(tslib@2.8.1) - glob-to-regex.js: 1.2.0(tslib@2.8.1) - thingies: 2.6.0(tslib@2.8.1) - tree-dump: 1.1.0(tslib@2.8.1) + memfs@4.9.3: + dependencies: + '@jsonjoy.com/json-pack': 1.0.4(tslib@2.8.1) + '@jsonjoy.com/util': 1.2.0(tslib@2.8.1) + tree-dump: 1.0.2(tslib@2.8.1) tslib: 2.8.1 memory-pager@1.5.0: {} @@ -27615,13 +27052,6 @@ snapshots: is-inside-container: 1.0.0 is-wsl: 3.1.0 - open@10.2.0: - dependencies: - default-browser: 5.5.0 - define-lazy-prop: 3.0.0 - is-inside-container: 1.0.0 - wsl-utils: 0.1.0 - open@8.4.2: dependencies: define-lazy-prop: 2.0.0 @@ -27743,10 +27173,10 @@ snapshots: dependencies: aggregate-error: 3.1.0 - p-retry@6.2.1: + p-retry@6.2.0: dependencies: '@types/retry': 0.12.2 - is-network-error: 1.3.2 + is-network-error: 1.1.0 retry: 0.13.1 p-timeout@3.2.0: @@ -27920,8 +27350,6 @@ snapshots: picomatch@2.3.1: {} - picomatch@2.3.2: {} - picomatch@4.0.3: {} picomatch@4.0.4: {} @@ -28150,7 +27578,7 @@ snapshots: '@protobufjs/path': 1.1.2 '@protobufjs/pool': 1.1.0 '@protobufjs/utf8': 1.1.0 - '@types/node': 22.19.19 + '@types/node': 22.15.18 long: 5.3.2 protocol-buffers-schema@3.6.1: {} @@ -28328,10 +27756,6 @@ snapshots: dependencies: side-channel: 1.1.0 - qs@6.15.2: - dependencies: - side-channel: 1.1.0 - querystringify@2.2.0: {} queue-microtask@1.2.3: {} @@ -28347,13 +27771,6 @@ snapshots: iconv-lite: 0.4.24 unpipe: 1.0.0 - raw-body@2.5.3: - dependencies: - bytes: 3.1.2 - http-errors: 2.0.1 - iconv-lite: 0.4.24 - unpipe: 1.0.0 - raw-body@3.0.2: dependencies: bytes: 3.1.2 @@ -28443,7 +27860,7 @@ snapshots: readdirp@3.6.0: dependencies: - picomatch: 2.3.2 + picomatch: 2.3.1 readdirp@4.1.2: {} @@ -28776,9 +28193,9 @@ snapshots: schema-utils@4.3.3: dependencies: '@types/json-schema': 7.0.15 - ajv: 8.20.0 - ajv-formats: 2.1.1(ajv@8.20.0) - ajv-keywords: 5.1.0(ajv@8.20.0) + ajv: 8.18.0 + ajv-formats: 2.1.1(ajv@8.18.0) + ajv-keywords: 5.1.0(ajv@8.18.0) secretlint@9.3.2: dependencies: @@ -28864,24 +28281,6 @@ snapshots: transitivePeerDependencies: - supports-color - send@0.19.2: - dependencies: - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - encodeurl: 2.0.0 - escape-html: 1.0.3 - etag: 1.8.1 - fresh: 0.5.2 - http-errors: 2.0.1 - mime: 1.6.0 - ms: 2.1.3 - on-finished: 2.4.1 - range-parser: 1.2.1 - statuses: 2.0.2 - transitivePeerDependencies: - - supports-color - send@1.2.1: dependencies: debug: 4.4.3(supports-color@8.1.1) @@ -28905,13 +28304,13 @@ snapshots: serialize-javascript@7.0.5: {} - serve-index@1.9.2: + serve-index@1.9.1: dependencies: accepts: 1.3.8 batch: 0.6.1 debug: 2.6.9 escape-html: 1.0.3 - http-errors: 1.8.1 + http-errors: 1.6.3 mime-types: 2.1.35 parseurl: 1.3.3 transitivePeerDependencies: @@ -28926,15 +28325,6 @@ snapshots: transitivePeerDependencies: - supports-color - serve-static@1.16.3: - dependencies: - encodeurl: 2.0.0 - escape-html: 1.0.3 - parseurl: 1.3.3 - send: 0.19.2 - transitivePeerDependencies: - - supports-color - serve-static@2.2.1: dependencies: encodeurl: 2.0.0 @@ -29023,8 +28413,6 @@ snapshots: shell-quote@1.8.1: {} - shell-quote@1.8.3: {} - shelljs@0.9.2: dependencies: execa: 1.0.0 @@ -29398,7 +28786,7 @@ snapshots: table@6.9.0: dependencies: - ajv: 8.20.0 + ajv: 8.18.0 lodash.truncate: 4.4.2 slice-ansi: 4.0.0 string-width: 4.2.3 @@ -29530,7 +28918,7 @@ snapshots: dependencies: any-promise: 1.3.0 - thingies@2.6.0(tslib@2.8.1): + thingies@1.21.0(tslib@2.8.1): dependencies: tslib: 2.8.1 @@ -29634,7 +29022,7 @@ snapshots: dependencies: punycode: 2.3.1 - tree-dump@1.1.0(tslib@2.8.1): + tree-dump@1.0.2(tslib@2.8.1): dependencies: tslib: 2.8.1 @@ -29673,12 +29061,12 @@ snapshots: babel-jest: 29.7.0(@babel/core@7.28.4) esbuild: 0.27.7 - ts-jest@29.3.3(@babel/core@7.28.4)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.28.4))(jest@29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)))(typescript@5.4.5): + ts-jest@29.3.3(@babel/core@7.28.4)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.28.4))(jest@29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)))(typescript@5.4.5): dependencies: bs-logger: 0.2.6 ejs: 3.1.10 fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) + jest: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) jest-util: 29.7.0 json5: 2.2.3 lodash.memoize: 4.1.2 @@ -29693,12 +29081,12 @@ snapshots: '@jest/types': 29.6.3 babel-jest: 29.7.0(@babel/core@7.28.4) - ts-jest@29.4.9(@babel/core@7.28.4)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.28.4))(jest-util@29.7.0)(jest@29.7.0(@types/node@22.19.19)(ts-node@10.9.2(@types/node@22.19.19)(typescript@5.4.5)))(typescript@5.4.5): + ts-jest@29.4.9(@babel/core@7.28.4)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.28.4))(jest-util@29.7.0)(jest@29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)))(typescript@5.4.5): dependencies: bs-logger: 0.2.6 fast-json-stable-stringify: 2.1.0 handlebars: 4.7.9 - jest: 29.7.0(@types/node@22.19.19)(ts-node@10.9.2(@types/node@22.19.19)(typescript@5.4.5)) + jest: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) json5: 2.2.3 lodash.memoize: 4.1.2 make-error: 1.3.6 @@ -29752,14 +29140,14 @@ snapshots: yn: 3.1.1 optional: true - ts-node@10.9.2(@types/node@22.19.19)(typescript@5.4.5): + ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.9 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 22.19.19 + '@types/node': 25.5.2 acorn: 8.15.0 acorn-walk: 8.3.0 arg: 4.1.3 @@ -29770,25 +29158,6 @@ snapshots: v8-compile-cache-lib: 3.0.1 yn: 3.1.1 - ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5): - dependencies: - '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.9 - '@tsconfig/node12': 1.0.11 - '@tsconfig/node14': 1.0.3 - '@tsconfig/node16': 1.0.4 - '@types/node': 25.9.1 - acorn: 8.15.0 - acorn-walk: 8.3.0 - arg: 4.1.3 - create-require: 1.1.1 - diff: 4.0.4 - make-error: 1.3.6 - typescript: 5.4.5 - v8-compile-cache-lib: 3.0.1 - yn: 3.1.1 - optional: true - tslib@1.14.1: {} tslib@2.6.2: {} @@ -29927,10 +29296,9 @@ snapshots: undici-types@7.16.0: {} - undici-types@7.24.4: {} + undici-types@7.18.2: {} - undici-types@7.24.6: - optional: true + undici-types@7.24.4: {} undici@6.25.0: {} @@ -30080,13 +29448,13 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.2 - vite@5.4.21(@types/node@25.9.1)(less@4.3.0)(terser@5.39.2): + vite@5.4.21(@types/node@25.5.2)(less@4.3.0)(terser@5.39.2): dependencies: esbuild: 0.21.5 postcss: 8.5.14 rollup: 4.59.0 optionalDependencies: - '@types/node': 25.9.1 + '@types/node': 25.5.2 fsevents: 2.3.3 less: 4.3.0 terser: 5.39.2 @@ -30108,7 +29476,7 @@ snapshots: tsx: 4.21.0 yaml: 2.8.3 - vite@6.4.2(@types/node@22.19.19)(jiti@2.5.1)(less@4.3.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3): + vite@6.4.2(@types/node@25.5.2)(jiti@2.5.1)(less@4.3.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3): dependencies: esbuild: 0.25.11 fdir: 6.5.0(picomatch@4.0.3) @@ -30117,24 +29485,7 @@ snapshots: rollup: 4.59.0 tinyglobby: 0.2.15 optionalDependencies: - '@types/node': 22.19.19 - fsevents: 2.3.3 - jiti: 2.5.1 - less: 4.3.0 - terser: 5.39.2 - tsx: 4.21.0 - yaml: 2.8.3 - - vite@6.4.2(@types/node@25.9.1)(jiti@2.5.1)(less@4.3.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3): - dependencies: - esbuild: 0.25.11 - fdir: 6.5.0(picomatch@4.0.3) - picomatch: 4.0.3 - postcss: 8.5.14 - rollup: 4.59.0 - tinyglobby: 0.2.15 - optionalDependencies: - '@types/node': 25.9.1 + '@types/node': 25.5.2 fsevents: 2.3.3 jiti: 2.5.1 less: 4.3.0 @@ -30229,50 +29580,48 @@ snapshots: webpack: 5.105.0(webpack-cli@5.1.4) webpack-merge: 5.10.0 optionalDependencies: - webpack-dev-server: 5.2.4(debug@4.4.1)(tslib@2.8.1)(webpack-cli@5.1.4)(webpack@5.105.0) + webpack-dev-server: 5.2.4(debug@4.4.1)(webpack-cli@5.1.4)(webpack@5.105.0) - webpack-dev-middleware@7.4.5(tslib@2.8.1)(webpack@5.105.0): + webpack-dev-middleware@7.4.2(webpack@5.105.0): dependencies: colorette: 2.0.20 - memfs: 4.57.2(tslib@2.8.1) - mime-types: 3.0.2 + memfs: 4.9.3 + mime-types: 2.1.35 on-finished: 2.4.1 range-parser: 1.2.1 schema-utils: 4.3.3 optionalDependencies: webpack: 5.105.0(webpack-cli@5.1.4) - transitivePeerDependencies: - - tslib - webpack-dev-server@5.2.4(debug@4.4.1)(tslib@2.8.1)(webpack-cli@5.1.4)(webpack@5.105.0): + webpack-dev-server@5.2.4(debug@4.4.1)(webpack-cli@5.1.4)(webpack@5.105.0): dependencies: '@types/bonjour': 3.5.13 '@types/connect-history-api-fallback': 1.5.4 '@types/express': 4.17.25 - '@types/express-serve-static-core': 4.19.8 + '@types/express-serve-static-core': 4.19.6 '@types/serve-index': 1.9.4 - '@types/serve-static': 1.15.10 + '@types/serve-static': 1.15.5 '@types/sockjs': 0.3.36 '@types/ws': 8.18.1 ansi-html-community: 0.0.8 - bonjour-service: 1.3.0 + bonjour-service: 1.2.1 chokidar: 3.6.0 colorette: 2.0.20 compression: 1.8.1 connect-history-api-fallback: 2.0.0 - express: 4.22.2 + express: 4.22.1 graceful-fs: 4.2.11 http-proxy-middleware: 2.0.9(@types/express@4.17.25)(debug@4.4.1) - ipaddr.js: 2.4.0 - launch-editor: 2.13.2 - open: 10.2.0 - p-retry: 6.2.1 + ipaddr.js: 2.1.0 + launch-editor: 2.9.1 + open: 10.1.2 + p-retry: 6.2.0 schema-utils: 4.3.3 selfsigned: 5.5.0 - serve-index: 1.9.2 + serve-index: 1.9.1 sockjs: 0.3.24 spdy: 4.0.2 - webpack-dev-middleware: 7.4.5(tslib@2.8.1)(webpack@5.105.0) + webpack-dev-middleware: 7.4.2(webpack@5.105.0) ws: 8.20.1 optionalDependencies: webpack: 5.105.0(webpack-cli@5.1.4) @@ -30281,7 +29630,6 @@ snapshots: - bufferutil - debug - supports-color - - tslib - utf-8-validate webpack-merge@5.10.0: @@ -30360,7 +29708,7 @@ snapshots: websocket-driver@0.7.4: dependencies: - http-parser-js: 0.5.10 + http-parser-js: 0.5.8 safe-buffer: 5.2.1 websocket-extensions: 0.1.4 @@ -30520,10 +29868,6 @@ snapshots: ws@8.20.1: {} - wsl-utils@0.1.0: - dependencies: - is-wsl: 3.1.1 - xml-name-validator@4.0.0: {} xml-name-validator@5.0.0: {} From f94ab15155e69ce08d773ec70fb6fc4171d7d23e Mon Sep 17 00:00:00 2001 From: Tal Zaccai Date: Wed, 20 May 2026 15:05:15 -0700 Subject: [PATCH 2/6] visualStudio: drop hardcoded discovery fallback port Migrated TS clients (browser, code, coda) all return undefined on discovery failure and rely on the reconnect loop. The C# bridge client was the odd one out, silently dialing 5680 when discovery was unreachable - which in the post-migration world connects to nothing useful (the agent no longer binds 5680 by default). Changes: - BridgeDiscovery.ResolveBridgePortAsync now returns int? and throws on transport failure, matching the TS pattern. - AgentBridgeClient retries on the existing 3s reconnect cadence when discovery returns null or throws. - New TYPEAGENT_VS_BRIDGE_PORT env var pins an explicit port and bypasses discovery (mirrors CODE_WEBSOCKET_HOST). Drops the TYPEAGENT_VS_USE_DISCOVERY + TYPEAGENT_VS_FALLBACK_PORT pair whose only purpose was selecting that hardcoded fallback. - README env-var table + troubleshooting updated. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- ts/packages/agents/visualStudio/README.md | 20 +++--- .../host/csharp/Bridge/AgentBridgeClient.cs | 43 +++++++++-- .../host/csharp/Bridge/BridgeDiscovery.cs | 71 ++++++------------- .../src/visualStudioActionHandler.ts | 7 +- 4 files changed, 71 insertions(+), 70 deletions(-) diff --git a/ts/packages/agents/visualStudio/README.md b/ts/packages/agents/visualStudio/README.md index 43717dd373..e3e71eedcb 100644 --- a/ts/packages/agents/visualStudio/README.md +++ b/ts/packages/agents/visualStudio/README.md @@ -53,14 +53,15 @@ Two WebSocket channels: `AgentBridgeClient` resolves the bridge port on each connect attempt by calling `lookupPort("visualStudio", "default")` against the agent-server's discovery channel (`ws://localhost:/`, -default 8999). Knobs: +default 8999). If discovery is unreachable or the agent isn't yet +registered, the reconnect loop simply retries — there is no silent +fallback to a well-known port. Knobs: -| Env var | Default | Purpose | -| ----------------------------------------- | ----------------------- | --------------------------------------------------------------------------- | -| `AGENT_SERVER_PORT` | `8999` | Where the dispatcher's discovery channel is hosted. | -| `TYPEAGENT_VS_USE_DISCOVERY` | `true` | Set to `false`/`0` to skip discovery and use the hardcoded fallback (5680). | -| `TYPEAGENT_VS_FALLBACK_PORT` | `5680` | Port to fall back to when discovery is disabled or returns null / fails. | -| `VISUALSTUDIO_BRIDGE_PORT` _(agent-side)_ | _(unset → OS-assigned)_ | Pin the agent's bridge to a specific port when debugging. | +| Env var | Default | Purpose | +| ----------------------------------------- | ------------------------- | ------------------------------------------------------------------------------------------------ | +| `AGENT_SERVER_PORT` | `8999` | Where the dispatcher's discovery channel is hosted. | +| `TYPEAGENT_VS_BRIDGE_PORT` _(C# host)_ | _(unset → use discovery)_ | Pin the C# host to dial a specific bridge port; bypasses discovery. Useful for manual debugging. | +| `VISUALSTUDIO_BRIDGE_PORT` _(agent-side)_ | _(unset → OS-assigned)_ | Pin the agent's bridge to a specific port when debugging. | ## Action Categories @@ -152,8 +153,9 @@ Any use of third-party trademarks or logos are subject to those third-party's po could not reach the agent's action port. Confirm `visualstudio-agent` is enabled in the dispatcher. Check the VS **Output → Debug** pane for `[TypeAgent] Bridge…` lines indicating whether discovery succeeded and - which port was used. Set `TYPEAGENT_VS_USE_DISCOVERY=false` to force the - hardcoded fallback (5680) if you suspect the discovery channel itself. + which port was used. To bypass discovery for diagnostics (e.g. dial a + manually-launched bridge), set `TYPEAGENT_VS_BRIDGE_PORT` to the port + you want to dial. - **Action ran but did nothing visible.** Check the Visual Studio **Output** window and the agent-server logs; EnvDTE silently no-ops on some commands when the relevant context (e.g. an active document, an active debug session) diff --git a/ts/packages/agents/visualStudio/host/csharp/Bridge/AgentBridgeClient.cs b/ts/packages/agents/visualStudio/host/csharp/Bridge/AgentBridgeClient.cs index c0e9b1fab3..aaff568164 100644 --- a/ts/packages/agents/visualStudio/host/csharp/Bridge/AgentBridgeClient.cs +++ b/ts/packages/agents/visualStudio/host/csharp/Bridge/AgentBridgeClient.cs @@ -21,11 +21,14 @@ namespace Microsoft.TypeAgent.VisualStudio.Bridge /// Port discovery: /// The bridge port is no longer hardcoded. On each connect attempt /// we ask the agent-server's discovery channel where the - /// `(visualStudio, default)` allocation lives, falling back to the - /// well-known port (5680) when discovery is disabled or fails. + /// `(visualStudio, default)` allocation lives. If discovery is + /// unreachable or the agent isn't yet registered, the reconnect + /// loop simply retries — there is no silent fallback to a + /// well-known port. To pin a specific port (e.g. when running the + /// bridge against a manually-launched agent), set + /// `TYPEAGENT_VS_BRIDGE_PORT`; that bypasses discovery entirely. /// See for the wire protocol and the - /// env-var knobs (`AGENT_SERVER_PORT`, - /// `TYPEAGENT_VS_USE_DISCOVERY`, `TYPEAGENT_VS_FALLBACK_PORT`). + /// `AGENT_SERVER_PORT` env-var knob. /// /// Wire format (matches packages/agents/visualStudio/src/visualStudioActionHandler.ts): /// request: { id, actionName, parameters } @@ -33,6 +36,7 @@ namespace Microsoft.TypeAgent.VisualStudio.Bridge /// internal sealed class AgentBridgeClient : IDisposable { + private const string BridgePortOverrideEnv = "TYPEAGENT_VS_BRIDGE_PORT"; private static readonly TimeSpan ReconnectDelay = TimeSpan.FromSeconds(3); private readonly AsyncPackage _package; @@ -58,8 +62,19 @@ public async Task StartAsync(CancellationToken cancellation) // have restarted on a different ephemeral port since the // last loop iteration, and the standalone shell may have // come up while we were retrying. - port = await BridgeDiscovery.ResolveBridgePortAsync(linked.Token).ConfigureAwait(false); - await ConnectAndReceiveAsync(port, linked.Token).ConfigureAwait(false); + int? resolved = ResolvePortOverride() + ?? await BridgeDiscovery.ResolveBridgePortAsync(linked.Token).ConfigureAwait(false); + if (resolved is null) + { + // Discovery succeeded but the agent isn't registered + // yet — wait one reconnect cycle and try again. + Debug.WriteLine("[TypeAgent] visualStudio agent not yet registered; will retry"); + } + else + { + port = resolved.Value; + await ConnectAndReceiveAsync(port, linked.Token).ConfigureAwait(false); + } } catch (OperationCanceledException) { @@ -80,6 +95,22 @@ public async Task StartAsync(CancellationToken cancellation) } } + // Returns an explicit port override from `TYPEAGENT_VS_BRIDGE_PORT`, + // or null when the env var is unset/malformed (caller falls through + // to discovery). Mirrors `CODE_WEBSOCKET_HOST` from coda. + private static int? ResolvePortOverride() + { + string? raw = Environment.GetEnvironmentVariable(BridgePortOverrideEnv); + if (string.IsNullOrEmpty(raw)) return null; + if (int.TryParse(raw, out int p) && p > 0 && p <= 65535) + { + Debug.WriteLine($"[TypeAgent] {BridgePortOverrideEnv} override active: {p}"); + return p; + } + Debug.WriteLine($"[TypeAgent] Ignoring malformed {BridgePortOverrideEnv}={raw}"); + return null; + } + private async Task ConnectAndReceiveAsync(int port, CancellationToken cancellation) { var uri = new Uri($"ws://localhost:{port}"); diff --git a/ts/packages/agents/visualStudio/host/csharp/Bridge/BridgeDiscovery.cs b/ts/packages/agents/visualStudio/host/csharp/Bridge/BridgeDiscovery.cs index 63f513bf6e..63c34069f9 100644 --- a/ts/packages/agents/visualStudio/host/csharp/Bridge/BridgeDiscovery.cs +++ b/ts/packages/agents/visualStudio/host/csharp/Bridge/BridgeDiscovery.cs @@ -27,69 +27,48 @@ namespace Microsoft.TypeAgent.VisualStudio.Bridge /// "message": { "type": "invokeResult", "callId": N, /// "result": { "port": <int|null> } } } /// - /// Returns the port on success, or null when the agent isn't currently - /// registered (caller should retry with backoff). Throws on transport - /// failure so the outer reconnect loop can apply its own retry policy. + /// Returns the discovered port, or null when the agent isn't yet + /// registered with the agent-server (transient — caller should retry). + /// Throws on transport failure so the outer reconnect loop can apply + /// its own retry/backoff. There is intentionally no hardcoded fallback + /// port — the migrated TS clients (browser, code, coda) all return + /// "undefined" on discovery failure and rely on the reconnect loop; + /// dialing a stale well-known port would just connect to nothing. /// internal static class BridgeDiscovery { - // Env var read on every resolve so users can flip behavior without + // Read on every resolve so users can flip behavior without // restarting the IDE between debugging sessions. private const string AgentServerPortEnv = "AGENT_SERVER_PORT"; - private const string UseDiscoveryEnv = "TYPEAGENT_VS_USE_DISCOVERY"; - private const string FallbackPortEnv = "TYPEAGENT_VS_FALLBACK_PORT"; // Must match AGENT_SERVER_DEFAULT_PORT in agentServer/protocol. private const int DefaultAgentServerPort = 8999; - // Hardcoded fallback when discovery is disabled or fails before the - // agent has registered. Matches the pre-discovery hardcoded port — - // ports 5678 + 5679 are taken by the Excel agent. - private const int DefaultFallbackBridgePort = 5680; - // Names this client uses to look itself up. Must match the role // registered by visualStudioActionHandler.ts. private const string AgentName = "visualStudio"; private const string Role = "default"; /// - /// Resolve the bridge port. Returns the discovered port, or the - /// fallback when discovery is disabled / unreachable / returned - /// null. Never throws — callers expect a usable port. + /// Resolve the bridge port via discovery. Returns the discovered + /// port, or null when the agent has not yet registered (transient + /// — caller should retry on its reconnect loop). + /// Throws on transport failure (agent-server unreachable, timeout, + /// malformed response) so the caller can log and retry. /// - public static async Task ResolveBridgePortAsync(CancellationToken cancellation) + public static async Task ResolveBridgePortAsync(CancellationToken cancellation) { - int fallback = GetFallbackPort(); - if (!IsDiscoveryEnabled()) - { - Debug.WriteLine($"[TypeAgent] Discovery disabled; using fallback port {fallback}"); - return fallback; - } int agentServerPort = GetAgentServerPort(); - try + int? discovered = await LookupPortAsync(agentServerPort, cancellation).ConfigureAwait(false); + if (discovered is int p) { - int? discovered = await LookupPortAsync(agentServerPort, cancellation).ConfigureAwait(false); - if (discovered is int p) - { - Debug.WriteLine($"[TypeAgent] Discovery resolved bridge port {p}"); - return p; - } - Debug.WriteLine($"[TypeAgent] Discovery returned null for ({AgentName}, {Role}); using fallback {fallback}"); - return fallback; + Debug.WriteLine($"[TypeAgent] Discovery resolved bridge port {p}"); } - catch (Exception ex) + else { - Debug.WriteLine($"[TypeAgent] Discovery failed ({ex.Message}); using fallback port {fallback}"); - return fallback; + Debug.WriteLine($"[TypeAgent] Discovery returned null for ({AgentName}, {Role}); agent not yet registered"); } - } - - private static bool IsDiscoveryEnabled() - { - // Discovery is on by default; explicit "false"/"0" disables. - string? raw = Environment.GetEnvironmentVariable(UseDiscoveryEnv); - if (string.IsNullOrEmpty(raw)) return true; - return !(raw!.Equals("false", StringComparison.OrdinalIgnoreCase) || raw == "0"); + return discovered; } private static int GetAgentServerPort() @@ -102,16 +81,6 @@ private static int GetAgentServerPort() return DefaultAgentServerPort; } - private static int GetFallbackPort() - { - string? raw = Environment.GetEnvironmentVariable(FallbackPortEnv); - if (int.TryParse(raw, out int p) && p > 0 && p <= 65535) - { - return p; - } - return DefaultFallbackBridgePort; - } - private static async Task LookupPortAsync(int agentServerPort, CancellationToken cancellation) { var uri = new Uri($"ws://localhost:{agentServerPort}/"); diff --git a/ts/packages/agents/visualStudio/src/visualStudioActionHandler.ts b/ts/packages/agents/visualStudio/src/visualStudioActionHandler.ts index 7330fda28a..b6159d4ef7 100644 --- a/ts/packages/agents/visualStudio/src/visualStudioActionHandler.ts +++ b/ts/packages/agents/visualStudio/src/visualStudioActionHandler.ts @@ -199,10 +199,9 @@ class VisualStudioBridge { // ---- Port resolution --------------------------------------------------- // Optional fixed-port override. Useful when launching the Visual Studio -// extension in a debugger that can't easily read the discovery channel, -// or when reproducing a port-specific issue. The extension's -// `UseDiscovery=false` config flag uses the same default fallback (5680) -// so the two stay in sync. +// extension in a debugger and you want both sides on a known port — +// pair this with `TYPEAGENT_VS_BRIDGE_PORT=` on the C# host +// to bypass discovery on both ends. // // Malformed values are warned and ignored — we fall through to the // OS-assigned port. If the requested port is already in use, From 7ab05154c1bf4ed1426af2424bac0ca0b1e1a125 Mon Sep 17 00:00:00 2001 From: Tal Zaccai Date: Wed, 20 May 2026 16:00:25 -0700 Subject: [PATCH 3/6] visualStudio: address PR #2374 review comments - Bind the WebSocket bridge server to 127.0.0.1 instead of 0.0.0.0 so ephemeral ports are not reachable from the LAN even though the C# ClientWebSocket has no Origin header (review comments #1, #3). - Track in-flight send() requests with a per-request timer and clean the pending map on socket close, error, and stop. Adds a configurable timeout (VISUALSTUDIO_BRIDGE_SEND_TIMEOUT_MS, default 30s) so disconnected awaits no longer hang forever and the map cannot grow unbounded across reconnects (review comment #2 + the suppressed-low-confidence note about send() lacking a timeout). - Regenerate ts/pnpm-lock.yaml from main so the diff is limited to the new debug / @types/debug deps and pnpm's dedupe of pre-existing @types/node entries (review comment #6). Comments #4 and #5 (BridgeDiscovery.cs hardcoded fallback / XML doc mismatch) were already addressed in adf142684. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../src/visualStudioActionHandler.ts | 123 ++- ts/pnpm-lock.yaml | 971 +++++++++++++----- 2 files changed, 830 insertions(+), 264 deletions(-) diff --git a/ts/packages/agents/visualStudio/src/visualStudioActionHandler.ts b/ts/packages/agents/visualStudio/src/visualStudioActionHandler.ts index b6159d4ef7..d122a3b2f8 100644 --- a/ts/packages/agents/visualStudio/src/visualStudioActionHandler.ts +++ b/ts/packages/agents/visualStudio/src/visualStudioActionHandler.ts @@ -42,7 +42,11 @@ type BridgeResponse = { class VisualStudioBridge { private client: WebSocket | undefined; - private pending = new Map void>(); + private pending = new Map< + string, + { resolve: (r: BridgeResponse) => void; timer: NodeJS.Timeout } + >(); + private readonly sendTimeoutMs: number; /** * @param wss the underlying ws server, already bound and listening. @@ -57,8 +61,11 @@ class VisualStudioBridge { private readonly wss: WebSocketServer, public readonly port: number, ) { + this.sendTimeoutMs = resolveSendTimeoutMs(); this.setupHandlers(); - debug(`VisualStudioBridge listening on port ${port}`); + debug( + `VisualStudioBridge listening on port ${port} (sendTimeoutMs=${this.sendTimeoutMs})`, + ); } /** @@ -75,6 +82,13 @@ class VisualStudioBridge { return new Promise((resolve, reject) => { const wss = new WebSocketServer({ port, + // Bind loopback-only so the bridge isn't reachable from + // other hosts on the LAN. The Origin allowlist below + // accepts requests with no Origin header (the C# + // ClientWebSocket doesn't send one), so without an + // explicit loopback bind a remote attacker on the same + // network could otherwise drive EnvDTE actions. + host: "127.0.0.1", // Gate every upgrade on Origin so a random web page on // the same host can't dial the ephemeral port assigned // by the OS. `verifyClient` runs synchronously before @@ -139,22 +153,49 @@ class VisualStudioBridge { const response = JSON.parse( data.toString(), ) as BridgeResponse; - this.pending.get(response.id)?.(response); - this.pending.delete(response.id); + const entry = this.pending.get(response.id); + if (entry !== undefined) { + clearTimeout(entry.timer); + this.pending.delete(response.id); + entry.resolve(response); + } } catch (err) { debug("Failed to parse plugin message:", err); } }); - ws.on("close", () => { - debug("host plugin disconnected"); + const onDisconnect = (reason: string) => { + debug(`host plugin disconnected (${reason})`); this.client = undefined; - }); + // Reject every in-flight send so callers don't hang + // forever and the map can't grow unbounded across + // reconnects. `stop()` runs the same cleanup; either + // path is sufficient. + this.failPending( + new Error(`Host plugin disconnected: ${reason}`), + ); + }; + ws.on("close", () => onDisconnect("close")); ws.on("error", (err) => { debug("host plugin socket error:", err); + onDisconnect(`error: ${err.message}`); }); }); } + private failPending(error: Error): void { + if (this.pending.size === 0) return; + const entries = Array.from(this.pending.values()); + this.pending.clear(); + for (const entry of entries) { + clearTimeout(entry.timer); + entry.resolve({ + id: "", + success: false, + error: error.message, + }); + } + } + /** * Close the underlying server and resolve once the port is fully * released — important for a rapid disable→enable cycle under a @@ -167,6 +208,9 @@ class VisualStudioBridge { this.client.close(); } this.client = undefined; + // Reject any in-flight sends before the server closes; otherwise + // callers awaiting `send()` hang forever after a manual disable. + this.failPending(new Error("VisualStudioBridge stopped")); return new Promise((resolve) => this.wss.close(() => resolve())); } @@ -176,18 +220,40 @@ class VisualStudioBridge { } const id = `${Date.now()}-${Math.random().toString(36).slice(2)}`; return new Promise((resolve, reject) => { - this.pending.set(id, (res) => - res.success - ? resolve(res.result) - : reject(new Error(res.error)), - ); - this.client!.send( - JSON.stringify({ - id, - actionName, - parameters, - } satisfies BridgeRequest), - ); + // Timeout so a plugin that accepts the WS frame but never + // replies (deadlock, EnvDTE hang, killed mid-action) doesn't + // wedge the caller. The pending entry is cleared either by + // the response handler or this timer — whichever fires + // first. + const timer = setTimeout(() => { + if (this.pending.delete(id)) { + reject( + new Error( + `VS bridge action '${actionName}' timed out after ${this.sendTimeoutMs}ms`, + ), + ); + } + }, this.sendTimeoutMs); + this.pending.set(id, { + timer, + resolve: (res) => + res.success + ? resolve(res.result) + : reject(new Error(res.error)), + }); + try { + this.client!.send( + JSON.stringify({ + id, + actionName, + parameters, + } satisfies BridgeRequest), + ); + } catch (err) { + clearTimeout(timer); + this.pending.delete(id); + reject(err); + } }); } @@ -198,6 +264,25 @@ class VisualStudioBridge { // ---- Port resolution --------------------------------------------------- +const DEFAULT_SEND_TIMEOUT_MS = 30_000; + +// Per-action send() timeout. EnvDTE actions are typically subsecond, +// but a few (build/run, attach-to-process) can run for tens of seconds +// on a cold solution. Default 30s leaves headroom; override via env for +// debugging long-running actions. +function resolveSendTimeoutMs(): number { + const raw = process.env["VISUALSTUDIO_BRIDGE_SEND_TIMEOUT_MS"]; + if (raw === undefined || raw === "") return DEFAULT_SEND_TIMEOUT_MS; + const n = Number(raw); + if (!Number.isInteger(n) || n <= 0) { + console.warn( + `Ignoring malformed VISUALSTUDIO_BRIDGE_SEND_TIMEOUT_MS=${raw}; using ${DEFAULT_SEND_TIMEOUT_MS}ms`, + ); + return DEFAULT_SEND_TIMEOUT_MS; + } + return n; +} + // Optional fixed-port override. Useful when launching the Visual Studio // extension in a debugger and you want both sides on a known port — // pair this with `TYPEAGENT_VS_BRIDGE_PORT=` on the C# host diff --git a/ts/pnpm-lock.yaml b/ts/pnpm-lock.yaml index 87c13f6808..36565f0853 100644 --- a/ts/pnpm-lock.yaml +++ b/ts/pnpm-lock.yaml @@ -550,7 +550,7 @@ importers: version: 16.5.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -577,7 +577,7 @@ importers: version: 24.37.5(typescript@5.4.5) ts-node: specifier: ^10.9.1 - version: 10.9.2(@types/node@25.5.2)(typescript@5.4.5) + version: 10.9.2(@types/node@25.9.1)(typescript@5.4.5) xml2js: specifier: ^0.6.2 version: 0.6.2 @@ -759,7 +759,7 @@ importers: version: 12.0.2(webpack@5.105.0) jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -780,7 +780,7 @@ importers: version: 5.1.4(webpack-dev-server@5.2.4)(webpack@5.105.0) webpack-dev-server: specifier: ^5.2.4 - version: 5.2.4(debug@4.4.1)(webpack-cli@5.1.4)(webpack@5.105.0) + version: 5.2.4(debug@4.4.1)(tslib@2.8.1)(webpack-cli@5.1.4)(webpack@5.105.0) examples/vscodeSchemaGen: dependencies: @@ -906,7 +906,7 @@ importers: version: 12.0.2(webpack@5.105.0) jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -927,7 +927,7 @@ importers: version: 5.1.4(webpack-dev-server@5.2.4)(webpack@5.105.0) webpack-dev-server: specifier: ^5.2.4 - version: 5.2.4(debug@4.4.1)(webpack-cli@5.1.4)(webpack@5.105.0) + version: 5.2.4(debug@4.4.1)(tslib@2.8.1)(webpack-cli@5.1.4)(webpack@5.105.0) examples/workflow/adapter: dependencies: @@ -955,7 +955,7 @@ importers: version: 9.1.2 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -986,7 +986,7 @@ importers: version: 29.5.14 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -1042,7 +1042,7 @@ importers: version: 29.5.14 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -1076,7 +1076,7 @@ importers: version: 29.5.14 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -1125,7 +1125,7 @@ importers: version: 7.0.15 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -1177,7 +1177,7 @@ importers: version: 5.4.5 vite: specifier: ^5.4.0 - version: 5.4.21(@types/node@25.5.2)(less@4.3.0)(terser@5.39.2) + version: 5.4.21(@types/node@25.9.1)(less@4.3.0)(terser@5.39.2) packages/actionGrammar: dependencies: @@ -1217,7 +1217,7 @@ importers: version: 5.6.2 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -1267,7 +1267,7 @@ importers: version: 29.5.14 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) rimraf: specifier: ^6.0.1 version: 6.0.1 @@ -1321,7 +1321,7 @@ importers: version: 29.5.14 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -1349,7 +1349,7 @@ importers: version: 29.5.14 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -1450,7 +1450,7 @@ importers: version: 8.18.1 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -1627,7 +1627,7 @@ importers: version: 2.4.1 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -1966,7 +1966,7 @@ importers: version: 9.1.2 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -2067,7 +2067,7 @@ importers: version: 9.1.2 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -2158,7 +2158,7 @@ importers: version: 2.4.1 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -2257,7 +2257,7 @@ importers: version: 9.1.2 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) rimraf: specifier: ^6.0.1 version: 6.0.1 @@ -2495,7 +2495,7 @@ importers: version: 2.4.1 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -2510,7 +2510,7 @@ importers: version: 5.4.5 vite: specifier: ^6.4.2 - version: 6.4.2(@types/node@25.5.2)(jiti@2.5.1)(less@4.3.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3) + version: 6.4.2(@types/node@25.9.1)(jiti@2.5.1)(less@4.3.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3) packages/agents/montage: dependencies: @@ -2586,7 +2586,7 @@ importers: version: 12.0.2(webpack@5.105.0) jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.2.5 version: 3.5.3 @@ -2607,7 +2607,7 @@ importers: version: 5.1.4(webpack-dev-server@5.2.4)(webpack@5.105.0) webpack-dev-server: specifier: ^5.2.4 - version: 5.2.4(debug@4.4.1)(webpack-cli@5.1.4)(webpack@5.105.0) + version: 5.2.4(debug@4.4.1)(tslib@2.8.1)(webpack-cli@5.1.4)(webpack@5.105.0) packages/agents/onboarding: dependencies: @@ -2690,7 +2690,7 @@ importers: version: 9.1.2 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -2776,7 +2776,7 @@ importers: version: 9.1.2 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) rimraf: specifier: ^6.0.1 version: 6.0.1 @@ -2899,7 +2899,7 @@ importers: version: 9.1.2 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -3054,7 +3054,7 @@ importers: version: 12.0.2(webpack@5.105.0) jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -3075,7 +3075,7 @@ importers: version: 5.1.4(webpack-dev-server@5.2.4)(webpack@5.105.0) webpack-dev-server: specifier: ^5.2.4 - version: 5.2.4(debug@4.4.1)(webpack-cli@5.1.4)(webpack@5.105.0) + version: 5.2.4(debug@4.4.1)(tslib@2.8.1)(webpack-cli@5.1.4)(webpack@5.105.0) packages/agents/utility: dependencies: @@ -3121,7 +3121,7 @@ importers: version: 9.1.2 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -3223,7 +3223,7 @@ importers: version: 5.4.5 vite: specifier: ^5.4.10 - version: 5.4.21(@types/node@25.5.2)(less@4.3.0)(terser@5.39.2) + version: 5.4.21(@types/node@25.9.1)(less@4.3.0)(terser@5.39.2) packages/agents/weather: dependencies: @@ -3307,7 +3307,7 @@ importers: version: 16.5.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) rimraf: specifier: ^6.0.1 version: 6.0.1 @@ -3395,7 +3395,7 @@ importers: version: 8.18.1 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -3459,7 +3459,7 @@ importers: version: 16.5.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) rimraf: specifier: ^6.0.1 version: 6.0.1 @@ -3520,7 +3520,7 @@ importers: version: 2.0.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -3560,7 +3560,7 @@ importers: version: 5.6.3(webpack@5.105.0) jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -3581,7 +3581,7 @@ importers: version: 5.1.4(webpack-dev-server@5.2.4)(webpack@5.105.0) webpack-dev-server: specifier: ^5.2.4 - version: 5.2.4(debug@4.4.1)(webpack-cli@5.1.4)(webpack@5.105.0) + version: 5.2.4(debug@4.4.1)(tslib@2.8.1)(webpack-cli@5.1.4)(webpack@5.105.0) packages/chat-ui: dependencies: @@ -3684,7 +3684,7 @@ importers: version: link:../telemetry ts-node: specifier: ^10.9.1 - version: 10.9.2(@types/node@25.5.2)(typescript@5.4.5) + version: 10.9.2(@types/node@25.9.1)(typescript@5.4.5) typechat-utils: specifier: workspace:* version: link:../utils/typechatUtils @@ -3703,7 +3703,7 @@ importers: version: 29.5.14 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -3712,7 +3712,7 @@ importers: version: 6.0.1 ts-jest: specifier: ^29.4.9 - version: 29.4.9(@babel/core@7.28.4)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.28.4))(jest-util@29.7.0)(jest@29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)))(typescript@5.4.5) + version: 29.4.9(@babel/core@7.28.4)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.28.4))(jest-util@29.7.0)(jest@29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)))(typescript@5.4.5) typescript: specifier: ~5.4.5 version: 5.4.5 @@ -3887,7 +3887,7 @@ importers: version: 29.5.14 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.2.5 version: 3.5.3 @@ -3896,7 +3896,7 @@ importers: version: 5.0.10 ts-jest: specifier: ^29.1.2 - version: 29.3.3(@babel/core@7.28.4)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.28.4))(jest@29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)))(typescript@5.4.5) + version: 29.3.3(@babel/core@7.28.4)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.28.4))(jest@29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)))(typescript@5.4.5) typescript: specifier: ~5.4.5 version: 5.4.5 @@ -3948,7 +3948,7 @@ importers: version: 4.0.9 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) rimraf: specifier: ^6.0.1 version: 6.0.1 @@ -4181,7 +4181,7 @@ importers: version: 16.5.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -4335,7 +4335,7 @@ importers: version: 16.5.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -4378,7 +4378,7 @@ importers: version: 29.5.14 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -4469,7 +4469,7 @@ importers: version: 29.5.14 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) rimraf: specifier: ^5.0.5 version: 5.0.10 @@ -4503,7 +4503,7 @@ importers: version: 0.11.1 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) rimraf: specifier: ^5.0.5 version: 5.0.10 @@ -4512,7 +4512,7 @@ importers: version: 5.4.5 vite: specifier: ^5.4.0 - version: 5.4.21(@types/node@25.5.2)(less@4.3.0)(terser@5.39.2) + version: 5.4.21(@types/node@25.9.1)(less@4.3.0)(terser@5.39.2) packages/interactiveApp: dependencies: @@ -4571,7 +4571,7 @@ importers: version: 16.5.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -4669,7 +4669,7 @@ importers: version: 16.5.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -4709,7 +4709,7 @@ importers: version: 12.0.2(webpack@5.105.0) jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -4730,7 +4730,7 @@ importers: version: 5.1.4(webpack-dev-server@5.2.4)(webpack@5.105.0) webpack-dev-server: specifier: ^5.2.4 - version: 5.2.4(debug@4.4.1)(webpack-cli@5.1.4)(webpack@5.105.0) + version: 5.2.4(debug@4.4.1)(tslib@2.8.1)(webpack-cli@5.1.4)(webpack@5.105.0) packages/kp: dependencies: @@ -4856,7 +4856,7 @@ importers: version: 16.5.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -4926,7 +4926,7 @@ importers: version: 16.5.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -4978,7 +4978,7 @@ importers: version: 16.5.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.2.5 version: 3.5.3 @@ -5072,7 +5072,7 @@ importers: version: 16.5.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -5256,7 +5256,7 @@ importers: devDependencies: '@electron-toolkit/tsconfig': specifier: ^1.0.1 - version: 1.0.1(@types/node@25.5.2) + version: 1.0.1(@types/node@25.9.1) '@fontsource/lato': specifier: ^5.2.5 version: 5.2.5 @@ -5292,10 +5292,10 @@ importers: version: 26.8.1(dmg-builder@26.8.1) electron-vite: specifier: ^4.0.1 - version: 4.0.1(vite@6.4.2(@types/node@25.5.2)(jiti@2.5.1)(less@4.3.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3)) + version: 4.0.1(vite@6.4.2(@types/node@25.9.1)(jiti@2.5.1)(less@4.3.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3)) jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) less: specifier: ^4.2.0 version: 4.3.0 @@ -5313,7 +5313,7 @@ importers: version: 5.4.5 vite: specifier: ^6.4.2 - version: 6.4.2(@types/node@25.5.2)(jiti@2.5.1)(less@4.3.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3) + version: 6.4.2(@types/node@25.9.1)(jiti@2.5.1)(less@4.3.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3) packages/telemetry: dependencies: @@ -5344,7 +5344,7 @@ importers: version: 29.5.14 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -5378,7 +5378,7 @@ importers: version: 16.5.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -5449,7 +5449,7 @@ importers: version: 16.5.0 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -5477,7 +5477,7 @@ importers: version: 0.25.11 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -5508,7 +5508,7 @@ importers: version: 29.5.14 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -5557,7 +5557,7 @@ importers: version: 29.5.14 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + version: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -7784,20 +7784,122 @@ packages: peerDependencies: tslib: '2' - '@jsonjoy.com/json-pack@1.0.4': - resolution: {integrity: sha512-aOcSN4MeAtFROysrbqG137b7gaDDSmVrl5mpo6sT/w+kcXpWnzhMjmY/Fh/sDx26NBxyIE7MB1seqLeCAzy9Sg==} + '@jsonjoy.com/base64@17.67.0': + resolution: {integrity: sha512-5SEsJGsm15aP8TQGkDfJvz9axgPwAEm98S5DxOuYe8e1EbfajcDmgeXXzccEjh+mLnjqEKrkBdjHWS5vFNwDdw==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' - '@jsonjoy.com/util@1.2.0': - resolution: {integrity: sha512-4B8B+3vFsY4eo33DMKyJPlQ3sBMpPFUZK2dr3O3rXrOGKKbYG44J0XSFkDo1VOQiri5HFEhIeVvItjR2xcazmg==} + '@jsonjoy.com/buffers@1.2.1': + resolution: {integrity: sha512-12cdlDwX4RUM3QxmUbVJWqZ/mrK6dFQH4Zxq6+r1YXKXYBNgZXndx2qbCJwh3+WWkCSn67IjnlG3XYTvmvYtgA==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' - '@leichtgewicht/ip-codec@2.0.4': - resolution: {integrity: sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==} + '@jsonjoy.com/buffers@17.67.0': + resolution: {integrity: sha512-tfExRpYxBvi32vPs9ZHaTjSP4fHAfzSmcahOfNxtvGHcyJel+aibkPlGeBB+7AoC6hL7lXIE++8okecBxx7lcw==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/codegen@1.0.0': + resolution: {integrity: sha512-E8Oy+08cmCf0EK/NMxpaJZmOxPqM+6iSe2S4nlSBrPZOORoDJILxtbSUEDKQyTamm/BVAhIGllOBNU79/dwf0g==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/codegen@17.67.0': + resolution: {integrity: sha512-idnkUplROpdBOV0HMcwhsCUS5TRUi9poagdGs70A6S4ux9+/aPuKbh8+UYRTLYQHtXvAdNfQWXDqZEx5k4Dj2Q==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/fs-core@4.57.2': + resolution: {integrity: sha512-SVjwklkpIV5wrynpYtuYnfYH1QF4/nDuLBX7VXdb+3miglcAgBVZb/5y0cOsehRV/9Vb+3UqhkMq3/NR3ztdkQ==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/fs-fsa@4.57.2': + resolution: {integrity: sha512-fhO8+iR2I+OCw668ISDJdn1aArc9zx033sWejIyzQ8RBeXa9bDSaUeA3ix0poYOfrj1KdOzytmYNv2/uLDfV6g==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/fs-node-builtins@4.57.2': + resolution: {integrity: sha512-xhiegylRmhw43Ki2HO1ZBL7DQ5ja/qpRsL29VtQ2xuUHiuDGbgf2uD4p9Qd8hJI5P6RCtGYD50IXHXVq/Ocjcg==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/fs-node-to-fsa@4.57.2': + resolution: {integrity: sha512-18LmWTSONhoAPW+IWRuf8w/+zRolPFGPeGwMxlAhhfY11EKzX+5XHDBPAw67dBF5dxDErHJbl40U+3IXSDRXSQ==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/fs-node-utils@4.57.2': + resolution: {integrity: sha512-rsPSJgekz43IlNbLyAM/Ab+ouYLWGp5DDBfYBNNEqDaSpsbXfthBn29Q4muFA9L0F+Z3mKo+CWlgSCXrf+mOyQ==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/fs-node@4.57.2': + resolution: {integrity: sha512-nX2AdL6cOFwLdju9G4/nbRnYevmCJbh7N7hvR3gGm97Cs60uEjyd0rpR+YBS7cTg175zzl22pGKXR5USaQMvKg==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/fs-print@4.57.2': + resolution: {integrity: sha512-wK9NSow48i4DbDl9F1CQE5TqnyZOJ04elU3WFG5aJ76p+YxO/ulyBBQvKsessPxdo381Bc2pcEoyPujMOhcRqQ==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/fs-snapshot@4.57.2': + resolution: {integrity: sha512-GdduDZuoP5V/QCgJkx9+BZ6SC0EZ/smXAdTS7PfMqgMTGXLlt/bH/FqMYaqB9JmLf05sJPtO0XRbAwwkEEPbVw==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/json-pack@1.21.0': + resolution: {integrity: sha512-+AKG+R2cfZMShzrF2uQw34v3zbeDYUqnQ+jg7ORic3BGtfw9p/+N6RJbq/kkV8JmYZaINknaEQ2m0/f693ZPpg==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/json-pack@17.67.0': + resolution: {integrity: sha512-t0ejURcGaZsn1ClbJ/3kFqSOjlryd92eQY465IYrezsXmPcfHPE/av4twRSxf6WE+TkZgLY+71vCZbiIiFKA/w==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/json-pointer@1.0.2': + resolution: {integrity: sha512-Fsn6wM2zlDzY1U+v4Nc8bo3bVqgfNTGcn6dMgs6FjrEnt4ZCe60o6ByKRjOGlI2gow0aE/Q41QOigdTqkyK5fg==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/json-pointer@17.67.0': + resolution: {integrity: sha512-+iqOFInH+QZGmSuaybBUNdh7yvNrXvqR+h3wjXm0N/3JK1EyyFAeGJvqnmQL61d1ARLlk/wJdFKSL+LHJ1eaUA==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/util@1.9.0': + resolution: {integrity: sha512-pLuQo+VPRnN8hfPqUTLTHk126wuYdXVxE6aDmjSeV4NCAgyxWbiOIeNJVtID3h1Vzpoi9m4jXezf73I6LgabgQ==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/util@17.67.0': + resolution: {integrity: sha512-6+8xBaz1rLSohlGh68D1pdw3AwDi9xydm8QNlAFkvnavCJYSze+pxoW2VKP8p308jtlMRLs5NTHfPlZLd4w7ew==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@leichtgewicht/ip-codec@2.0.5': + resolution: {integrity: sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==} '@lezer/common@1.2.3': resolution: {integrity: sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA==} @@ -9101,8 +9203,11 @@ packages: '@types/express-serve-static-core@4.17.41': resolution: {integrity: sha512-OaJ7XLaelTgrvlZD8/aa0vvvxZdUmlCn6MtWeB7TkiKW70BQLc9XEPpDLPdbo52ZhXUCrznlWdCHWxJWtdyajA==} - '@types/express-serve-static-core@4.19.6': - resolution: {integrity: sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==} + '@types/express-serve-static-core@4.19.8': + resolution: {integrity: sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==} + + '@types/express-serve-static-core@5.1.1': + resolution: {integrity: sha512-v4zIMr/cX7/d2BpAEX3KNKL/JrT1s43s96lLvvdTmza1oEvDudCqK9aF/djc/SWgy8Yh0h30TZx5VpzqFCxk5A==} '@types/express@4.17.21': resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} @@ -9167,8 +9272,11 @@ packages: '@types/http-errors@2.0.4': resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==} - '@types/http-proxy@1.17.14': - resolution: {integrity: sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==} + '@types/http-errors@2.0.5': + resolution: {integrity: sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==} + + '@types/http-proxy@1.17.17': + resolution: {integrity: sha512-ED6LB+Z1AVylNTu7hdzuBqOgMnvG/ld6wGCG8wFnAzKX5uyW2K3WD52v0gnLCTK/VLpXtKckgWuyScYK6cSPaw==} '@types/istanbul-lib-coverage@2.0.6': resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} @@ -9275,11 +9383,14 @@ packages: '@types/node@22.15.18': resolution: {integrity: sha512-v1DKRfUdyW+jJhZNEI1PYy29S2YRxMV5AOO/x/SjKmW0acCIOqmbj6Haf9eHAhsPmrhlHSxEhv/1WszcLWV4cg==} + '@types/node@22.19.19': + resolution: {integrity: sha512-dyh/xO2Fh5bYrfWaaqGrRQQGkNdmYw6AmaAUvYeUMNTWQtvb796ikLdmTchRmOlOiIJ1TDXfWgVx1QkUlQ6Hew==} + '@types/node@24.12.2': resolution: {integrity: sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g==} - '@types/node@25.5.2': - resolution: {integrity: sha512-tO4ZIRKNC+MDWV4qKVZe3Ql/woTnmHDr5JD8UI5hn2pwBrHEwOEMZK7WlNb5RKB6EoJ02gwmQS9OrjuFnZYdpg==} + '@types/node@25.9.1': + resolution: {integrity: sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg==} '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} @@ -9302,6 +9413,9 @@ packages: '@types/qs@6.15.0': resolution: {integrity: sha512-JawvT8iBVWpzTrz3EGw9BTQFg3BQNmwERdKE22vlTxawwtbyUSlMppvZYKLZzB5zgACXdXxbD3m1bXaMqP/9ow==} + '@types/qs@6.15.1': + resolution: {integrity: sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw==} + '@types/range-parser@1.2.7': resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} @@ -9326,9 +9440,18 @@ packages: '@types/send@0.17.4': resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} + '@types/send@0.17.6': + resolution: {integrity: sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==} + + '@types/send@1.2.1': + resolution: {integrity: sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==} + '@types/serve-index@1.9.4': resolution: {integrity: sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==} + '@types/serve-static@1.15.10': + resolution: {integrity: sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==} + '@types/serve-static@1.15.5': resolution: {integrity: sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==} @@ -9744,12 +9867,15 @@ packages: peerDependencies: ajv: ^8.8.2 - ajv@6.14.0: - resolution: {integrity: sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==} + ajv@6.15.0: + resolution: {integrity: sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==} ajv@8.18.0: resolution: {integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==} + ajv@8.20.0: + resolution: {integrity: sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==} + ansi-escapes@4.3.2: resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} engines: {node: '>=8'} @@ -10035,8 +10161,8 @@ packages: bignumber.js@9.3.1: resolution: {integrity: sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==} - binary-extensions@2.2.0: - resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} binaryextensions@4.19.0: @@ -10053,12 +10179,16 @@ packages: resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + body-parser@1.20.5: + resolution: {integrity: sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + body-parser@2.2.2: resolution: {integrity: sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==} engines: {node: '>=18'} - bonjour-service@1.2.1: - resolution: {integrity: sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==} + bonjour-service@1.3.0: + resolution: {integrity: sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA==} boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} @@ -10978,10 +11108,18 @@ packages: resolution: {integrity: sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==} engines: {node: '>=18'} + default-browser-id@5.0.1: + resolution: {integrity: sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==} + engines: {node: '>=18'} + default-browser@5.2.1: resolution: {integrity: sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==} engines: {node: '>=18'} + default-browser@5.5.0: + resolution: {integrity: sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==} + engines: {node: '>=18'} + default-gateway@6.0.3: resolution: {integrity: sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==} engines: {node: '>= 10'} @@ -11497,6 +11635,10 @@ packages: resolution: {integrity: sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==} engines: {node: '>= 0.10.0'} + express@4.22.2: + resolution: {integrity: sha512-IuL+Elrou2ZvCFHs18/CIzy2Nzvo25nZ1/D2eIZlz7c+QUayAcYoiM2BthCjs+EBHVpjYjcuLDAiCWgeIX3X1Q==} + engines: {node: '>= 0.10.0'} + express@5.2.1: resolution: {integrity: sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==} engines: {node: '>= 18'} @@ -11536,6 +11678,9 @@ packages: fast-uri@3.1.0: resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} + fast-uri@3.1.2: + resolution: {integrity: sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==} + fast-xml-builder@1.1.5: resolution: {integrity: sha512-4TJn/8FKLeslLAH3dnohXqE3QSoxkhvaMzepOIZytwJXZO69Bfz0HBdDHzOTOon6G59Zrk6VQ2bEiv1t61rfkA==} @@ -11814,6 +11959,12 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} + glob-to-regex.js@1.2.0: + resolution: {integrity: sha512-QMwlOQKU/IzqMUOAZWubUOT8Qft+Y0KQWnX9nK3ch0CJg0tTp4TvGZsTfudYKv2NzoQSyPcnA6TYeIQ3jGichQ==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + glob-to-regexp@0.4.1: resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} @@ -12093,8 +12244,8 @@ packages: resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} engines: {node: '>= 0.8'} - http-parser-js@0.5.8: - resolution: {integrity: sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==} + http-parser-js@0.5.10: + resolution: {integrity: sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==} http-proxy-agent@7.0.2: resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} @@ -12277,8 +12428,8 @@ packages: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} engines: {node: '>= 0.10'} - ipaddr.js@2.1.0: - resolution: {integrity: sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==} + ipaddr.js@2.4.0: + resolution: {integrity: sha512-9VGk3HGanVE6JoZXHiCpnGy5X0jYDnN4EA4lntFPj+1vIWlFhIylq2CrrCOJH9EAhc5CYhq18F2Av2tgoAPsYQ==} engines: {node: '>= 10'} is-absolute-url@4.0.1: @@ -12408,8 +12559,8 @@ packages: resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} engines: {node: '>= 0.4'} - is-network-error@1.1.0: - resolution: {integrity: sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g==} + is-network-error@1.3.2: + resolution: {integrity: sha512-PhBY86zaxNZUuWP6h13Vu5oFe0XY6/UlKzQnYFELzGVHygP3MxmvTfYSG7GN3aIab/iWudSMgjSnG9Dq+nHrgA==} engines: {node: '>=16'} is-number-object@1.1.1: @@ -12521,6 +12672,10 @@ packages: resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} engines: {node: '>=16'} + is-wsl@3.1.1: + resolution: {integrity: sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==} + engines: {node: '>=16'} + isarray@0.0.1: resolution: {integrity: sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==} @@ -12935,8 +13090,8 @@ packages: koffi@2.11.0: resolution: {integrity: sha512-AJ6MHz9Z8OIftKu322jrKJFvy/rZTdCD4b7F457WrK71rxYV7O5PSdWsJDN0p3rY1BZaPeLHVwyt4i2Xyk8wJg==} - launch-editor@2.9.1: - resolution: {integrity: sha512-Gcnl4Bd+hRO9P9icCP/RVVT2o8SFlPXofuCxvA2SaZuH45whSvf5p8x5oih5ftLiVhEI4sp5xDY+R+b3zJBh5w==} + launch-editor@2.13.2: + resolution: {integrity: sha512-4VVDnbOpLXy/s8rdRCSXb+zfMeFR0WlJWpET1iA9CQdlZDfwyLjUuGQzXU4VeOoey6AicSAluWan7Etga6Kcmg==} layout-base@1.0.2: resolution: {integrity: sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==} @@ -13286,9 +13441,10 @@ packages: resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==} engines: {node: '>= 0.8'} - memfs@4.9.3: - resolution: {integrity: sha512-bsYSSnirtYTWi1+OPMFb0M048evMKyUYe0EbtuGQgq6BVQM1g1W8/KIUJCCvjgI/El0j6Q4WsmMiBwLUBSw8LA==} - engines: {node: '>= 4.0.0'} + memfs@4.57.2: + resolution: {integrity: sha512-2nWzSsJzrukurSDna4Z0WywuScK4Id3tSKejgu74u8KCdW4uNrseKRSIDg75C6Yw5ZRqBe0F0EtMNlTbUq8bAQ==} + peerDependencies: + tslib: '2' memory-pager@1.5.0: resolution: {integrity: sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==} @@ -13804,6 +13960,10 @@ packages: resolution: {integrity: sha512-cxN6aIDPz6rm8hbebcP7vrQNhvRcveZoJU72Y7vskh4oIm+BZwBECnx5nTmrlres1Qapvx27Qo1Auukpf8PKXw==} engines: {node: '>=18'} + open@10.2.0: + resolution: {integrity: sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==} + engines: {node: '>=18'} + open@8.4.2: resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} engines: {node: '>=12'} @@ -13879,8 +14039,8 @@ packages: resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} engines: {node: '>=10'} - p-retry@6.2.0: - resolution: {integrity: sha512-JA6nkq6hKyWLLasXQXUrO4z8BUZGUt/LjlJxx8Gb2+2ntodU/SS63YZ8b0LUTbQ8ZB9iwOfhEPhg4ykKnn2KsA==} + p-retry@6.2.1: + resolution: {integrity: sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==} engines: {node: '>=16.17'} p-timeout@3.2.0: @@ -14058,6 +14218,10 @@ packages: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} + picomatch@2.3.2: + resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==} + engines: {node: '>=8.6'} + picomatch@4.0.3: resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} engines: {node: '>=12'} @@ -14395,6 +14559,10 @@ packages: resolution: {integrity: sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==} engines: {node: '>=0.6'} + qs@6.15.2: + resolution: {integrity: sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==} + engines: {node: '>=0.6'} + querystringify@2.2.0: resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} @@ -14413,6 +14581,10 @@ packages: resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} engines: {node: '>= 0.8'} + raw-body@2.5.3: + resolution: {integrity: sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==} + engines: {node: '>= 0.8'} + raw-body@3.0.2: resolution: {integrity: sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==} engines: {node: '>= 0.10'} @@ -14787,6 +14959,10 @@ packages: resolution: {integrity: sha512-p4rRk4f23ynFEfcD9LA0xRYngj+IyGiEYyqqOak8kaN0TvNmuxC2dcVeBn62GpCeR2CpWqyHCNScTP91QbAVFg==} engines: {node: '>= 0.8.0'} + send@0.19.2: + resolution: {integrity: sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==} + engines: {node: '>= 0.8.0'} + send@1.2.1: resolution: {integrity: sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==} engines: {node: '>= 18'} @@ -14799,14 +14975,18 @@ packages: resolution: {integrity: sha512-F4LcB0UqUl1zErq+1nYEEzSHJnIwb3AF2XWB94b+afhrekOUijwooAYqFyRbjYkm2PAKBabx6oYv/xDxNi8IBw==} engines: {node: '>=20.0.0'} - serve-index@1.9.1: - resolution: {integrity: sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==} + serve-index@1.9.2: + resolution: {integrity: sha512-KDj11HScOaLmrPxl70KYNW1PksP4Nb/CLL2yvC+Qd2kHMPEEpfc4Re2e4FOay+bC/+XQl/7zAcWON3JVo5v3KQ==} engines: {node: '>= 0.8.0'} serve-static@1.16.2: resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==} engines: {node: '>= 0.8.0'} + serve-static@1.16.3: + resolution: {integrity: sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==} + engines: {node: '>= 0.8.0'} + serve-static@2.2.1: resolution: {integrity: sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==} engines: {node: '>= 18'} @@ -14863,6 +15043,10 @@ packages: shell-quote@1.8.1: resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==} + shell-quote@1.8.3: + resolution: {integrity: sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==} + engines: {node: '>= 0.4'} + shelljs@0.9.2: resolution: {integrity: sha512-S3I64fEiKgTZzKCC46zT/Ib9meqofLrQVbpSswtjFfAVDW+AZ54WTnAM/3/yENoxz/V1Cy6u3kiiEbQ4DNphvw==} engines: {node: '>=18'} @@ -15276,8 +15460,8 @@ packages: thenify@3.3.1: resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} - thingies@1.21.0: - resolution: {integrity: sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g==} + thingies@2.6.0: + resolution: {integrity: sha512-rMHRjmlFLM1R96UYPvpmnc3LYtdFrT33JIB7L9hetGue1qAPfn1N2LJeEjxUSidu1Iku+haLZXDuEXUHNGO/lg==} engines: {node: '>=10.18'} peerDependencies: tslib: ^2 @@ -15385,8 +15569,8 @@ packages: resolution: {integrity: sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==} engines: {node: '>=20'} - tree-dump@1.0.2: - resolution: {integrity: sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ==} + tree-dump@1.1.0: + resolution: {integrity: sha512-rMuvhU4MCDbcbnleZTFezWsaZXRFemSqAM+7jPnzUl1fo9w3YEKOxAeui0fz3OI4EU4hf23iyA7uQRVko+UaBA==} engines: {node: '>=10.0'} peerDependencies: tslib: '2' @@ -15622,12 +15806,12 @@ packages: undici-types@7.16.0: resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} - undici-types@7.18.2: - resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} - undici-types@7.24.4: resolution: {integrity: sha512-cRaY9PagdEZoRmcwzk3tUV3SVGrVQkR6bcSilav/A0vXsfpW4Lvd0BvgRMwTEDTLLGN+QdyBTG+nnvTgJhdt6w==} + undici-types@7.24.6: + resolution: {integrity: sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==} + undici@6.25.0: resolution: {integrity: sha512-ZgpWDC5gmNiuY9CnLVXEH8rl50xhRCuLNA97fAUnKi8RRuV4E6KG31pDTsLVUKnohJE0I3XDrTeEydAXRw47xg==} engines: {node: '>=18.17'} @@ -15945,8 +16129,8 @@ packages: webpack-dev-server: optional: true - webpack-dev-middleware@7.4.2: - resolution: {integrity: sha512-xOO8n6eggxnwYpy1NlzUKpvrjfJTvae5/D6WOK0S2LSo7vjmo5gCM1DbLUmFqrMTJP+W/0YZNctm7jasWvLuBA==} + webpack-dev-middleware@7.4.5: + resolution: {integrity: sha512-uxQ6YqGdE4hgDKNf7hUiPXOdtkXvBJXrfEGYSx7P7LC8hnUYGK70X6xQXUvXeNyBDDcsiQXpG2m3G9vxowaEuA==} engines: {node: '>= 18.12.0'} peerDependencies: webpack: ^5.0.0 @@ -16143,6 +16327,10 @@ packages: utf-8-validate: optional: true + wsl-utils@0.1.0: + resolution: {integrity: sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==} + engines: {node: '>=18'} + xml-name-validator@4.0.0: resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} engines: {node: '>=12'} @@ -17902,8 +18090,8 @@ snapshots: '@develar/schema-utils@2.6.5': dependencies: - ajv: 6.14.0 - ajv-keywords: 3.5.2(ajv@6.14.0) + ajv: 6.15.0 + ajv-keywords: 3.5.2(ajv@6.15.0) '@discoveryjs/json-ext@0.5.7': {} @@ -17932,9 +18120,9 @@ snapshots: dependencies: electron: 40.8.5 - '@electron-toolkit/tsconfig@1.0.1(@types/node@25.5.2)': + '@electron-toolkit/tsconfig@1.0.1(@types/node@25.9.1)': dependencies: - '@types/node': 25.5.2 + '@types/node': 25.9.1 '@electron/asar@3.4.1': dependencies: @@ -18759,7 +18947,7 @@ snapshots: '@jest/console@29.7.0': dependencies: '@jest/types': 29.6.3 - '@types/node': 22.15.18 + '@types/node': 22.19.19 chalk: 4.1.2 jest-message-util: 29.7.0 jest-util: 29.7.0 @@ -18800,7 +18988,7 @@ snapshots: - supports-color - ts-node - '@jest/core@29.7.0(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5))': + '@jest/core@29.7.0(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5))': dependencies: '@jest/console': 29.7.0 '@jest/reporters': 29.7.0 @@ -18814,7 +19002,7 @@ snapshots: exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@22.15.18)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + jest-config: 29.7.0(@types/node@22.15.18)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -18879,7 +19067,7 @@ snapshots: '@jest/transform': 29.7.0 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.31 - '@types/node': 22.15.18 + '@types/node': 22.19.19 chalk: 4.1.2 collect-v8-coverage: 1.0.2 exit: 0.1.2 @@ -18993,19 +19181,130 @@ snapshots: dependencies: tslib: 2.8.1 - '@jsonjoy.com/json-pack@1.0.4(tslib@2.8.1)': + '@jsonjoy.com/base64@17.67.0(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 + + '@jsonjoy.com/buffers@1.2.1(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 + + '@jsonjoy.com/buffers@17.67.0(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 + + '@jsonjoy.com/codegen@1.0.0(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 + + '@jsonjoy.com/codegen@17.67.0(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 + + '@jsonjoy.com/fs-core@4.57.2(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/fs-node-builtins': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.57.2(tslib@2.8.1) + thingies: 2.6.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/fs-fsa@4.57.2(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/fs-core': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.57.2(tslib@2.8.1) + thingies: 2.6.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/fs-node-builtins@4.57.2(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 + + '@jsonjoy.com/fs-node-to-fsa@4.57.2(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/fs-fsa': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.57.2(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/fs-node-utils@4.57.2(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/fs-node-builtins': 4.57.2(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/fs-node@4.57.2(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/fs-core': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-print': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-snapshot': 4.57.2(tslib@2.8.1) + glob-to-regex.js: 1.2.0(tslib@2.8.1) + thingies: 2.6.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/fs-print@4.57.2(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/fs-node-utils': 4.57.2(tslib@2.8.1) + tree-dump: 1.1.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/fs-snapshot@4.57.2(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/buffers': 17.67.0(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/json-pack': 17.67.0(tslib@2.8.1) + '@jsonjoy.com/util': 17.67.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/json-pack@1.21.0(tslib@2.8.1)': dependencies: '@jsonjoy.com/base64': 1.1.2(tslib@2.8.1) - '@jsonjoy.com/util': 1.2.0(tslib@2.8.1) + '@jsonjoy.com/buffers': 1.2.1(tslib@2.8.1) + '@jsonjoy.com/codegen': 1.0.0(tslib@2.8.1) + '@jsonjoy.com/json-pointer': 1.0.2(tslib@2.8.1) + '@jsonjoy.com/util': 1.9.0(tslib@2.8.1) + hyperdyperid: 1.2.0 + thingies: 2.6.0(tslib@2.8.1) + tree-dump: 1.1.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/json-pack@17.67.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/base64': 17.67.0(tslib@2.8.1) + '@jsonjoy.com/buffers': 17.67.0(tslib@2.8.1) + '@jsonjoy.com/codegen': 17.67.0(tslib@2.8.1) + '@jsonjoy.com/json-pointer': 17.67.0(tslib@2.8.1) + '@jsonjoy.com/util': 17.67.0(tslib@2.8.1) hyperdyperid: 1.2.0 - thingies: 1.21.0(tslib@2.8.1) + thingies: 2.6.0(tslib@2.8.1) + tree-dump: 1.1.0(tslib@2.8.1) tslib: 2.8.1 - '@jsonjoy.com/util@1.2.0(tslib@2.8.1)': + '@jsonjoy.com/json-pointer@1.0.2(tslib@2.8.1)': dependencies: + '@jsonjoy.com/codegen': 1.0.0(tslib@2.8.1) + '@jsonjoy.com/util': 1.9.0(tslib@2.8.1) tslib: 2.8.1 - '@leichtgewicht/ip-codec@2.0.4': {} + '@jsonjoy.com/json-pointer@17.67.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/util': 17.67.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/util@1.9.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/buffers': 1.2.1(tslib@2.8.1) + '@jsonjoy.com/codegen': 1.0.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/util@17.67.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/buffers': 17.67.0(tslib@2.8.1) + '@jsonjoy.com/codegen': 17.67.0(tslib@2.8.1) + tslib: 2.8.1 + + '@leichtgewicht/ip-codec@2.0.5': {} '@lezer/common@1.2.3': {} @@ -20253,7 +20552,7 @@ snapshots: '@secretlint/profiler': 9.3.2 '@secretlint/resolver': 9.3.2 '@secretlint/types': 9.3.2 - ajv: 8.18.0 + ajv: 8.20.0 debug: 4.4.3(supports-color@8.1.1) rc-config-loader: 4.1.3 transitivePeerDependencies: @@ -20753,7 +21052,7 @@ snapshots: '@types/accepts@1.3.7': dependencies: - '@types/node': 22.15.18 + '@types/node': 22.19.19 '@types/async@3.2.24': {} @@ -20795,13 +21094,13 @@ snapshots: '@types/bonjour@3.5.13': dependencies: - '@types/node': 22.15.18 + '@types/node': 22.19.19 '@types/cacheable-request@6.0.3': dependencies: '@types/http-cache-semantics': 4.2.0 '@types/keyv': 3.1.4 - '@types/node': 22.15.18 + '@types/node': 22.19.19 '@types/responselike': 1.0.3 '@types/chai-dom@1.11.3': @@ -20832,8 +21131,8 @@ snapshots: '@types/co-body@6.1.3': dependencies: - '@types/node': 22.15.18 - '@types/qs': 6.15.0 + '@types/node': 22.19.19 + '@types/qs': 6.15.1 '@types/command-line-args@5.2.3': {} @@ -20841,8 +21140,8 @@ snapshots: '@types/connect-history-api-fallback@1.5.4': dependencies: - '@types/express-serve-static-core': 4.19.6 - '@types/node': 22.15.18 + '@types/express-serve-static-core': 5.1.1 + '@types/node': 22.19.19 '@types/connect@3.4.38': dependencies: @@ -20855,9 +21154,9 @@ snapshots: '@types/cookies@0.9.2': dependencies: '@types/connect': 3.4.38 - '@types/express': 4.17.21 + '@types/express': 4.17.25 '@types/keygrip': 1.0.6 - '@types/node': 22.15.18 + '@types/node': 22.19.19 '@types/cors@2.8.18': dependencies: @@ -21015,12 +21314,19 @@ snapshots: '@types/range-parser': 1.2.7 '@types/send': 0.17.4 - '@types/express-serve-static-core@4.19.6': + '@types/express-serve-static-core@4.19.8': dependencies: - '@types/node': 22.15.18 - '@types/qs': 6.15.0 + '@types/node': 22.19.19 + '@types/qs': 6.15.1 '@types/range-parser': 1.2.7 - '@types/send': 0.17.4 + '@types/send': 1.2.1 + + '@types/express-serve-static-core@5.1.1': + dependencies: + '@types/node': 22.19.19 + '@types/qs': 6.15.1 + '@types/range-parser': 1.2.7 + '@types/send': 1.2.1 '@types/express@4.17.21': dependencies: @@ -21032,9 +21338,9 @@ snapshots: '@types/express@4.17.25': dependencies: '@types/body-parser': 1.19.5 - '@types/express-serve-static-core': 4.19.6 - '@types/qs': 6.15.0 - '@types/serve-static': 1.15.5 + '@types/express-serve-static-core': 4.19.8 + '@types/qs': 6.15.1 + '@types/serve-static': 1.15.10 '@types/fast-levenshtein@0.0.4': {} @@ -21061,18 +21367,18 @@ snapshots: '@types/fs-extra@9.0.13': dependencies: - '@types/node': 22.15.18 + '@types/node': 22.19.19 '@types/geojson@7946.0.16': {} '@types/glob@7.2.0': dependencies: '@types/minimatch': 5.1.2 - '@types/node': 22.15.18 + '@types/node': 22.19.19 '@types/graceful-fs@4.1.8': dependencies: - '@types/node': 22.15.18 + '@types/node': 22.19.19 '@types/har-format@1.2.15': {} @@ -21090,9 +21396,11 @@ snapshots: '@types/http-errors@2.0.4': {} - '@types/http-proxy@1.17.14': + '@types/http-errors@2.0.5': {} + + '@types/http-proxy@1.17.17': dependencies: - '@types/node': 22.15.18 + '@types/node': 22.19.19 '@types/istanbul-lib-coverage@2.0.6': {} @@ -21142,7 +21450,7 @@ snapshots: '@types/keyv@3.1.4': dependencies: - '@types/node': 22.15.18 + '@types/node': 22.19.19 '@types/koa-compose@3.2.9': dependencies: @@ -21154,10 +21462,10 @@ snapshots: '@types/content-disposition': 0.5.9 '@types/cookies': 0.9.2 '@types/http-assert': 1.5.6 - '@types/http-errors': 2.0.4 + '@types/http-errors': 2.0.5 '@types/keygrip': 1.0.6 '@types/koa-compose': 3.2.9 - '@types/node': 22.15.18 + '@types/node': 22.19.19 '@types/linkify-it@5.0.0': {} @@ -21220,13 +21528,17 @@ snapshots: dependencies: undici-types: 6.21.0 + '@types/node@22.19.19': + dependencies: + undici-types: 6.21.0 + '@types/node@24.12.2': dependencies: undici-types: 7.16.0 - '@types/node@25.5.2': + '@types/node@25.9.1': dependencies: - undici-types: 7.18.2 + undici-types: 7.24.6 '@types/normalize-package-data@2.4.4': {} @@ -21234,7 +21546,7 @@ snapshots: '@types/plist@3.0.5': dependencies: - '@types/node': 22.15.18 + '@types/node': 22.19.19 xmlbuilder: 15.1.1 optional: true @@ -21248,6 +21560,8 @@ snapshots: '@types/qs@6.15.0': {} + '@types/qs@6.15.1': {} + '@types/range-parser@1.2.7': {} '@types/react@18.3.18': @@ -21261,7 +21575,7 @@ snapshots: '@types/responselike@1.0.3': dependencies: - '@types/node': 22.15.18 + '@types/node': 22.19.19 '@types/retry@0.12.2': {} @@ -21270,12 +21584,27 @@ snapshots: '@types/send@0.17.4': dependencies: '@types/mime': 1.3.5 - '@types/node': 22.15.18 + '@types/node': 22.19.19 + + '@types/send@0.17.6': + dependencies: + '@types/mime': 1.3.5 + '@types/node': 22.19.19 + + '@types/send@1.2.1': + dependencies: + '@types/node': 22.19.19 '@types/serve-index@1.9.4': dependencies: '@types/express': 4.17.25 + '@types/serve-static@1.15.10': + dependencies: + '@types/http-errors': 2.0.5 + '@types/node': 22.19.19 + '@types/send': 0.17.6 + '@types/serve-static@1.15.5': dependencies: '@types/http-errors': 2.0.4 @@ -21299,7 +21628,7 @@ snapshots: '@types/sockjs@0.3.36': dependencies: - '@types/node': 22.15.18 + '@types/node': 22.19.19 '@types/spotify-api@0.0.25': {} @@ -21332,7 +21661,7 @@ snapshots: '@types/ws@7.4.7': dependencies: - '@types/node': 22.15.18 + '@types/node': 22.19.19 '@types/ws@8.18.1': dependencies: @@ -21350,7 +21679,7 @@ snapshots: '@types/yauzl@2.10.3': dependencies: - '@types/node': 22.15.18 + '@types/node': 22.19.19 optional: true '@typespec/ts-http-runtime@0.2.2': @@ -21797,7 +22126,7 @@ snapshots: webpack: 5.105.0(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack-dev-server@5.2.4)(webpack@5.105.0) optionalDependencies: - webpack-dev-server: 5.2.4(debug@4.4.1)(webpack-cli@5.1.4)(webpack@5.105.0) + webpack-dev-server: 5.2.4(debug@4.4.1)(tslib@2.8.1)(webpack-cli@5.1.4)(webpack@5.105.0) '@xmldom/xmldom@0.8.10': {} @@ -21874,20 +22203,29 @@ snapshots: optionalDependencies: ajv: 8.18.0 + ajv-formats@2.1.1(ajv@8.20.0): + optionalDependencies: + ajv: 8.20.0 + ajv-formats@3.0.1(ajv@8.18.0): optionalDependencies: ajv: 8.18.0 - ajv-keywords@3.5.2(ajv@6.14.0): + ajv-keywords@3.5.2(ajv@6.15.0): dependencies: - ajv: 6.14.0 + ajv: 6.15.0 ajv-keywords@5.1.0(ajv@8.18.0): dependencies: ajv: 8.18.0 fast-deep-equal: 3.1.3 - ajv@6.14.0: + ajv-keywords@5.1.0(ajv@8.20.0): + dependencies: + ajv: 8.20.0 + fast-deep-equal: 3.1.3 + + ajv@6.15.0: dependencies: fast-deep-equal: 3.1.3 fast-json-stable-stringify: 2.1.0 @@ -21901,6 +22239,13 @@ snapshots: json-schema-traverse: 1.0.0 require-from-string: 2.0.2 + ajv@8.20.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.2 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + ansi-escapes@4.3.2: dependencies: type-fest: 0.21.3 @@ -21938,7 +22283,7 @@ snapshots: anymatch@3.1.3: dependencies: normalize-path: 3.0.0 - picomatch: 2.3.1 + picomatch: 2.3.2 apache-arrow@18.1.0: dependencies: @@ -22242,7 +22587,7 @@ snapshots: bignumber.js@9.3.1: {} - binary-extensions@2.2.0: {} + binary-extensions@2.3.0: {} binaryextensions@4.19.0: {} @@ -22273,6 +22618,23 @@ snapshots: transitivePeerDependencies: - supports-color + body-parser@1.20.5: + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.1 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.15.2 + raw-body: 2.5.3 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + body-parser@2.2.2: dependencies: bytes: 3.1.2 @@ -22281,13 +22643,13 @@ snapshots: http-errors: 2.0.1 iconv-lite: 0.7.2 on-finished: 2.4.1 - qs: 6.15.0 + qs: 6.15.2 raw-body: 3.0.2 type-is: 2.0.1 transitivePeerDependencies: - supports-color - bonjour-service@1.2.1: + bonjour-service@1.3.0: dependencies: fast-deep-equal: 3.1.3 multicast-dns: 7.2.5 @@ -22570,7 +22932,7 @@ snapshots: chrome-launcher@0.15.2: dependencies: - '@types/node': 22.15.18 + '@types/node': 22.19.19 escape-string-regexp: 4.0.0 is-wsl: 2.2.0 lighthouse-logger: 1.4.2 @@ -22693,7 +23055,7 @@ snapshots: dependencies: '@hapi/bourne': 3.0.0 inflation: 2.1.0 - qs: 6.15.0 + qs: 6.15.2 raw-body: 2.5.2 type-is: 1.6.18 @@ -22939,13 +23301,13 @@ snapshots: - supports-color - ts-node - create-jest@29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)): + create-jest@29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)): dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + jest-config: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -23325,11 +23687,18 @@ snapshots: default-browser-id@5.0.0: {} + default-browser-id@5.0.1: {} + default-browser@5.2.1: dependencies: bundle-name: 4.1.0 default-browser-id: 5.0.0 + default-browser@5.5.0: + dependencies: + bundle-name: 4.1.0 + default-browser-id: 5.0.1 + default-gateway@6.0.3: dependencies: execa: 5.1.1 @@ -23434,7 +23803,7 @@ snapshots: dependencies: '@types/plist': 3.0.5 '@types/verror': 1.10.9 - ajv: 6.14.0 + ajv: 6.15.0 crc: 3.8.0 iconv-corefoundation: 1.1.7 plist: 3.1.0 @@ -23444,7 +23813,7 @@ snapshots: dns-packet@5.6.1: dependencies: - '@leichtgewicht/ip-codec': 2.0.4 + '@leichtgewicht/ip-codec': 2.0.5 dom-converter@0.2.0: dependencies: @@ -23590,7 +23959,7 @@ snapshots: transitivePeerDependencies: - supports-color - electron-vite@4.0.1(vite@6.4.2(@types/node@25.5.2)(jiti@2.5.1)(less@4.3.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3)): + electron-vite@4.0.1(vite@6.4.2(@types/node@25.9.1)(jiti@2.5.1)(less@4.3.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3)): dependencies: '@babel/core': 7.28.4 '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.28.4) @@ -23598,7 +23967,7 @@ snapshots: esbuild: 0.25.11 magic-string: 0.30.17 picocolors: 1.1.1 - vite: 6.4.2(@types/node@25.5.2)(jiti@2.5.1)(less@4.3.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3) + vite: 6.4.2(@types/node@25.9.1)(jiti@2.5.1)(less@4.3.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3) transitivePeerDependencies: - supports-color @@ -24040,6 +24409,42 @@ snapshots: transitivePeerDependencies: - supports-color + express@4.22.2: + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.5 + content-disposition: 0.5.4 + content-type: 1.0.5 + cookie: 0.7.2 + cookie-signature: 1.0.7 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.3.2 + fresh: 0.5.2 + http-errors: 2.0.1 + merge-descriptors: 1.0.3 + methods: 1.1.2 + on-finished: 2.4.1 + parseurl: 1.3.3 + path-to-regexp: 0.1.13 + proxy-addr: 2.0.7 + qs: 6.15.2 + range-parser: 1.2.1 + safe-buffer: 5.2.1 + send: 0.19.2 + serve-static: 1.16.3 + setprototypeof: 1.2.0 + statuses: 2.0.2 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + express@5.2.1: dependencies: accepts: 2.0.0 @@ -24116,6 +24521,8 @@ snapshots: fast-uri@3.1.0: {} + fast-uri@3.1.2: {} + fast-xml-builder@1.1.5: dependencies: path-expression-matcher: 1.5.0 @@ -24431,6 +24838,10 @@ snapshots: dependencies: is-glob: 4.0.3 + glob-to-regex.js@1.2.0(tslib@2.8.1): + dependencies: + tslib: 2.8.1 + glob-to-regexp@0.4.1: {} glob@10.5.0: @@ -24827,7 +25238,7 @@ snapshots: statuses: 2.0.2 toidentifier: 1.0.1 - http-parser-js@0.5.8: {} + http-parser-js@0.5.10: {} http-proxy-agent@7.0.2: dependencies: @@ -24838,7 +25249,7 @@ snapshots: http-proxy-middleware@2.0.9(@types/express@4.17.25)(debug@4.4.1): dependencies: - '@types/http-proxy': 1.17.14 + '@types/http-proxy': 1.17.17 http-proxy: 1.18.1(debug@4.4.1) is-glob: 4.0.3 is-plain-obj: 3.0.0 @@ -25024,7 +25435,7 @@ snapshots: ipaddr.js@1.9.1: {} - ipaddr.js@2.1.0: {} + ipaddr.js@2.4.0: {} is-absolute-url@4.0.1: {} @@ -25052,7 +25463,7 @@ snapshots: is-binary-path@2.1.0: dependencies: - binary-extensions: 2.2.0 + binary-extensions: 2.3.0 is-boolean-object@1.2.2: dependencies: @@ -25132,7 +25543,7 @@ snapshots: is-negative-zero@2.0.3: {} - is-network-error@1.1.0: {} + is-network-error@1.3.2: {} is-number-object@1.1.1: dependencies: @@ -25222,6 +25633,10 @@ snapshots: dependencies: is-inside-container: 1.0.0 + is-wsl@3.1.1: + dependencies: + is-inside-container: 1.0.0 + isarray@0.0.1: {} isarray@1.0.0: {} @@ -25326,7 +25741,7 @@ snapshots: '@jest/expect': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.15.18 + '@types/node': 22.19.19 chalk: 4.1.2 co: 4.6.0 dedent: 1.7.0 @@ -25365,16 +25780,16 @@ snapshots: - supports-color - ts-node - jest-cli@29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)): + jest-cli@29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)): dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + create-jest: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) exit: 0.1.2 import-local: 3.2.0 - jest-config: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + jest-config: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -25415,7 +25830,7 @@ snapshots: - babel-plugin-macros - supports-color - jest-config@29.7.0(@types/node@22.15.18)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)): + jest-config@29.7.0(@types/node@22.15.18)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)): dependencies: '@babel/core': 7.28.4 '@jest/test-sequencer': 29.7.0 @@ -25441,12 +25856,12 @@ snapshots: strip-json-comments: 3.1.1 optionalDependencies: '@types/node': 22.15.18 - ts-node: 10.9.2(@types/node@25.5.2)(typescript@5.4.5) + ts-node: 10.9.2(@types/node@25.9.1)(typescript@5.4.5) transitivePeerDependencies: - babel-plugin-macros - supports-color - jest-config@29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)): + jest-config@29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)): dependencies: '@babel/core': 7.28.4 '@jest/test-sequencer': 29.7.0 @@ -25471,8 +25886,8 @@ snapshots: slash: 3.0.0 strip-json-comments: 3.1.1 optionalDependencies: - '@types/node': 25.5.2 - ts-node: 10.9.2(@types/node@25.5.2)(typescript@5.4.5) + '@types/node': 25.9.1 + ts-node: 10.9.2(@types/node@25.9.1)(typescript@5.4.5) transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -25516,7 +25931,7 @@ snapshots: '@jest/environment': 29.7.0 '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.15.18 + '@types/node': 22.19.19 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -25526,7 +25941,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.8 - '@types/node': 22.15.18 + '@types/node': 22.19.19 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -25600,7 +26015,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.15.18 + '@types/node': 22.19.19 chalk: 4.1.2 emittery: 0.13.1 graceful-fs: 4.2.11 @@ -25628,7 +26043,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.15.18 + '@types/node': 22.19.19 chalk: 4.1.2 cjs-module-lexer: 1.2.3 collect-v8-coverage: 1.0.2 @@ -25693,7 +26108,7 @@ snapshots: dependencies: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.15.18 + '@types/node': 22.19.19 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -25702,13 +26117,13 @@ snapshots: jest-worker@27.5.1: dependencies: - '@types/node': 22.15.18 + '@types/node': 22.19.19 merge-stream: 2.0.0 supports-color: 8.1.1 jest-worker@29.7.0: dependencies: - '@types/node': 22.15.18 + '@types/node': 22.19.19 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -25725,12 +26140,12 @@ snapshots: - supports-color - ts-node - jest@29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)): + jest@29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)): dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) '@jest/types': 29.6.3 import-local: 3.2.0 - jest-cli: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + jest-cli: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -26009,10 +26424,10 @@ snapshots: koffi@2.11.0: {} - launch-editor@2.9.1: + launch-editor@2.13.2: dependencies: picocolors: 1.1.1 - shell-quote: 1.8.1 + shell-quote: 1.8.3 layout-base@1.0.2: {} @@ -26440,11 +26855,21 @@ snapshots: media-typer@1.1.0: {} - memfs@4.9.3: - dependencies: - '@jsonjoy.com/json-pack': 1.0.4(tslib@2.8.1) - '@jsonjoy.com/util': 1.2.0(tslib@2.8.1) - tree-dump: 1.0.2(tslib@2.8.1) + memfs@4.57.2(tslib@2.8.1): + dependencies: + '@jsonjoy.com/fs-core': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-fsa': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-node': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-node-to-fsa': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-print': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/fs-snapshot': 4.57.2(tslib@2.8.1) + '@jsonjoy.com/json-pack': 1.21.0(tslib@2.8.1) + '@jsonjoy.com/util': 1.9.0(tslib@2.8.1) + glob-to-regex.js: 1.2.0(tslib@2.8.1) + thingies: 2.6.0(tslib@2.8.1) + tree-dump: 1.1.0(tslib@2.8.1) tslib: 2.8.1 memory-pager@1.5.0: {} @@ -27052,6 +27477,13 @@ snapshots: is-inside-container: 1.0.0 is-wsl: 3.1.0 + open@10.2.0: + dependencies: + default-browser: 5.5.0 + define-lazy-prop: 3.0.0 + is-inside-container: 1.0.0 + wsl-utils: 0.1.0 + open@8.4.2: dependencies: define-lazy-prop: 2.0.0 @@ -27173,10 +27605,10 @@ snapshots: dependencies: aggregate-error: 3.1.0 - p-retry@6.2.0: + p-retry@6.2.1: dependencies: '@types/retry': 0.12.2 - is-network-error: 1.1.0 + is-network-error: 1.3.2 retry: 0.13.1 p-timeout@3.2.0: @@ -27350,6 +27782,8 @@ snapshots: picomatch@2.3.1: {} + picomatch@2.3.2: {} + picomatch@4.0.3: {} picomatch@4.0.4: {} @@ -27578,7 +28012,7 @@ snapshots: '@protobufjs/path': 1.1.2 '@protobufjs/pool': 1.1.0 '@protobufjs/utf8': 1.1.0 - '@types/node': 22.15.18 + '@types/node': 22.19.19 long: 5.3.2 protocol-buffers-schema@3.6.1: {} @@ -27756,6 +28190,10 @@ snapshots: dependencies: side-channel: 1.1.0 + qs@6.15.2: + dependencies: + side-channel: 1.1.0 + querystringify@2.2.0: {} queue-microtask@1.2.3: {} @@ -27771,6 +28209,13 @@ snapshots: iconv-lite: 0.4.24 unpipe: 1.0.0 + raw-body@2.5.3: + dependencies: + bytes: 3.1.2 + http-errors: 2.0.1 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + raw-body@3.0.2: dependencies: bytes: 3.1.2 @@ -27860,7 +28305,7 @@ snapshots: readdirp@3.6.0: dependencies: - picomatch: 2.3.1 + picomatch: 2.3.2 readdirp@4.1.2: {} @@ -28193,9 +28638,9 @@ snapshots: schema-utils@4.3.3: dependencies: '@types/json-schema': 7.0.15 - ajv: 8.18.0 - ajv-formats: 2.1.1(ajv@8.18.0) - ajv-keywords: 5.1.0(ajv@8.18.0) + ajv: 8.20.0 + ajv-formats: 2.1.1(ajv@8.20.0) + ajv-keywords: 5.1.0(ajv@8.20.0) secretlint@9.3.2: dependencies: @@ -28281,6 +28726,24 @@ snapshots: transitivePeerDependencies: - supports-color + send@0.19.2: + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.1 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.2 + transitivePeerDependencies: + - supports-color + send@1.2.1: dependencies: debug: 4.4.3(supports-color@8.1.1) @@ -28304,13 +28767,13 @@ snapshots: serialize-javascript@7.0.5: {} - serve-index@1.9.1: + serve-index@1.9.2: dependencies: accepts: 1.3.8 batch: 0.6.1 debug: 2.6.9 escape-html: 1.0.3 - http-errors: 1.6.3 + http-errors: 1.8.1 mime-types: 2.1.35 parseurl: 1.3.3 transitivePeerDependencies: @@ -28325,6 +28788,15 @@ snapshots: transitivePeerDependencies: - supports-color + serve-static@1.16.3: + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.19.2 + transitivePeerDependencies: + - supports-color + serve-static@2.2.1: dependencies: encodeurl: 2.0.0 @@ -28413,6 +28885,8 @@ snapshots: shell-quote@1.8.1: {} + shell-quote@1.8.3: {} + shelljs@0.9.2: dependencies: execa: 1.0.0 @@ -28786,7 +29260,7 @@ snapshots: table@6.9.0: dependencies: - ajv: 8.18.0 + ajv: 8.20.0 lodash.truncate: 4.4.2 slice-ansi: 4.0.0 string-width: 4.2.3 @@ -28918,7 +29392,7 @@ snapshots: dependencies: any-promise: 1.3.0 - thingies@1.21.0(tslib@2.8.1): + thingies@2.6.0(tslib@2.8.1): dependencies: tslib: 2.8.1 @@ -29022,7 +29496,7 @@ snapshots: dependencies: punycode: 2.3.1 - tree-dump@1.0.2(tslib@2.8.1): + tree-dump@1.1.0(tslib@2.8.1): dependencies: tslib: 2.8.1 @@ -29061,12 +29535,12 @@ snapshots: babel-jest: 29.7.0(@babel/core@7.28.4) esbuild: 0.27.7 - ts-jest@29.3.3(@babel/core@7.28.4)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.28.4))(jest@29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)))(typescript@5.4.5): + ts-jest@29.3.3(@babel/core@7.28.4)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.28.4))(jest@29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)))(typescript@5.4.5): dependencies: bs-logger: 0.2.6 ejs: 3.1.10 fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + jest: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) jest-util: 29.7.0 json5: 2.2.3 lodash.memoize: 4.1.2 @@ -29081,12 +29555,12 @@ snapshots: '@jest/types': 29.6.3 babel-jest: 29.7.0(@babel/core@7.28.4) - ts-jest@29.4.9(@babel/core@7.28.4)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.28.4))(jest-util@29.7.0)(jest@29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)))(typescript@5.4.5): + ts-jest@29.4.9(@babel/core@7.28.4)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.28.4))(jest-util@29.7.0)(jest@29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)))(typescript@5.4.5): dependencies: bs-logger: 0.2.6 fast-json-stable-stringify: 2.1.0 handlebars: 4.7.9 - jest: 29.7.0(@types/node@25.5.2)(ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5)) + jest: 29.7.0(@types/node@25.9.1)(ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5)) json5: 2.2.3 lodash.memoize: 4.1.2 make-error: 1.3.6 @@ -29140,14 +29614,14 @@ snapshots: yn: 3.1.1 optional: true - ts-node@10.9.2(@types/node@25.5.2)(typescript@5.4.5): + ts-node@10.9.2(@types/node@25.9.1)(typescript@5.4.5): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.9 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 25.5.2 + '@types/node': 25.9.1 acorn: 8.15.0 acorn-walk: 8.3.0 arg: 4.1.3 @@ -29296,10 +29770,10 @@ snapshots: undici-types@7.16.0: {} - undici-types@7.18.2: {} - undici-types@7.24.4: {} + undici-types@7.24.6: {} + undici@6.25.0: {} undici@7.25.0: {} @@ -29448,13 +29922,13 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.2 - vite@5.4.21(@types/node@25.5.2)(less@4.3.0)(terser@5.39.2): + vite@5.4.21(@types/node@25.9.1)(less@4.3.0)(terser@5.39.2): dependencies: esbuild: 0.21.5 postcss: 8.5.14 rollup: 4.59.0 optionalDependencies: - '@types/node': 25.5.2 + '@types/node': 25.9.1 fsevents: 2.3.3 less: 4.3.0 terser: 5.39.2 @@ -29476,7 +29950,7 @@ snapshots: tsx: 4.21.0 yaml: 2.8.3 - vite@6.4.2(@types/node@25.5.2)(jiti@2.5.1)(less@4.3.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3): + vite@6.4.2(@types/node@25.9.1)(jiti@2.5.1)(less@4.3.0)(terser@5.39.2)(tsx@4.21.0)(yaml@2.8.3): dependencies: esbuild: 0.25.11 fdir: 6.5.0(picomatch@4.0.3) @@ -29485,7 +29959,7 @@ snapshots: rollup: 4.59.0 tinyglobby: 0.2.15 optionalDependencies: - '@types/node': 25.5.2 + '@types/node': 25.9.1 fsevents: 2.3.3 jiti: 2.5.1 less: 4.3.0 @@ -29580,48 +30054,50 @@ snapshots: webpack: 5.105.0(webpack-cli@5.1.4) webpack-merge: 5.10.0 optionalDependencies: - webpack-dev-server: 5.2.4(debug@4.4.1)(webpack-cli@5.1.4)(webpack@5.105.0) + webpack-dev-server: 5.2.4(debug@4.4.1)(tslib@2.8.1)(webpack-cli@5.1.4)(webpack@5.105.0) - webpack-dev-middleware@7.4.2(webpack@5.105.0): + webpack-dev-middleware@7.4.5(tslib@2.8.1)(webpack@5.105.0): dependencies: colorette: 2.0.20 - memfs: 4.9.3 - mime-types: 2.1.35 + memfs: 4.57.2(tslib@2.8.1) + mime-types: 3.0.2 on-finished: 2.4.1 range-parser: 1.2.1 schema-utils: 4.3.3 optionalDependencies: webpack: 5.105.0(webpack-cli@5.1.4) + transitivePeerDependencies: + - tslib - webpack-dev-server@5.2.4(debug@4.4.1)(webpack-cli@5.1.4)(webpack@5.105.0): + webpack-dev-server@5.2.4(debug@4.4.1)(tslib@2.8.1)(webpack-cli@5.1.4)(webpack@5.105.0): dependencies: '@types/bonjour': 3.5.13 '@types/connect-history-api-fallback': 1.5.4 '@types/express': 4.17.25 - '@types/express-serve-static-core': 4.19.6 + '@types/express-serve-static-core': 4.19.8 '@types/serve-index': 1.9.4 - '@types/serve-static': 1.15.5 + '@types/serve-static': 1.15.10 '@types/sockjs': 0.3.36 '@types/ws': 8.18.1 ansi-html-community: 0.0.8 - bonjour-service: 1.2.1 + bonjour-service: 1.3.0 chokidar: 3.6.0 colorette: 2.0.20 compression: 1.8.1 connect-history-api-fallback: 2.0.0 - express: 4.22.1 + express: 4.22.2 graceful-fs: 4.2.11 http-proxy-middleware: 2.0.9(@types/express@4.17.25)(debug@4.4.1) - ipaddr.js: 2.1.0 - launch-editor: 2.9.1 - open: 10.1.2 - p-retry: 6.2.0 + ipaddr.js: 2.4.0 + launch-editor: 2.13.2 + open: 10.2.0 + p-retry: 6.2.1 schema-utils: 4.3.3 selfsigned: 5.5.0 - serve-index: 1.9.1 + serve-index: 1.9.2 sockjs: 0.3.24 spdy: 4.0.2 - webpack-dev-middleware: 7.4.2(webpack@5.105.0) + webpack-dev-middleware: 7.4.5(tslib@2.8.1)(webpack@5.105.0) ws: 8.20.1 optionalDependencies: webpack: 5.105.0(webpack-cli@5.1.4) @@ -29630,6 +30106,7 @@ snapshots: - bufferutil - debug - supports-color + - tslib - utf-8-validate webpack-merge@5.10.0: @@ -29708,7 +30185,7 @@ snapshots: websocket-driver@0.7.4: dependencies: - http-parser-js: 0.5.8 + http-parser-js: 0.5.10 safe-buffer: 5.2.1 websocket-extensions: 0.1.4 @@ -29868,6 +30345,10 @@ snapshots: ws@8.20.1: {} + wsl-utils@0.1.0: + dependencies: + is-wsl: 3.1.1 + xml-name-validator@4.0.0: {} xml-name-validator@5.0.0: {} From 092c87ad3cb8151d85afa27a22eea24f16ba65f7 Mon Sep 17 00:00:00 2001 From: Tal Zaccai Date: Thu, 21 May 2026 12:46:32 -0700 Subject: [PATCH 4/6] visualStudio: use shared originAllowlist helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that PR #2358 has landed the shared websocket-utils/originAllowlist helper, collapse the visualStudio agent's per-file copy into a one-line call to createAgentOriginAllowlist() (no extension schemes — the only legitimate client is the C# ClientWebSocket, which doesn't send an Origin header). Behavior unchanged. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- ts/packages/agents/visualStudio/package.json | 1 + .../visualStudio/src/originAllowlist.ts | 54 +++++-------------- ts/pnpm-lock.yaml | 3 ++ 3 files changed, 16 insertions(+), 42 deletions(-) diff --git a/ts/packages/agents/visualStudio/package.json b/ts/packages/agents/visualStudio/package.json index c13640ab21..2535cf1281 100644 --- a/ts/packages/agents/visualStudio/package.json +++ b/ts/packages/agents/visualStudio/package.json @@ -26,6 +26,7 @@ "dependencies": { "@typeagent/agent-sdk": "workspace:*", "debug": "^4.4.0", + "websocket-utils": "workspace:*", "ws": "^8.20.1" }, "devDependencies": { diff --git a/ts/packages/agents/visualStudio/src/originAllowlist.ts b/ts/packages/agents/visualStudio/src/originAllowlist.ts index 4b5bbb5905..737c289385 100644 --- a/ts/packages/agents/visualStudio/src/originAllowlist.ts +++ b/ts/packages/agents/visualStudio/src/originAllowlist.ts @@ -1,52 +1,22 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +import { createAgentOriginAllowlist } from "websocket-utils/originAllowlist"; + /** * Origin allowlist for the visualStudio agent's WebSocket bridge. * * The only legitimate client is the in-process Visual Studio extension * (`host/csharp/Bridge/AgentBridgeClient.cs`), which uses - * `System.Net.WebSockets.ClientWebSocket`. That client does **not** send - * an `Origin` header, so we accept missing/empty Origin. - * - * Allowed: - * - **No Origin header** — the C# `ClientWebSocket` doesn't set one. - * - `http(s)://localhost(:port)`, `http(s)://127.0.0.1(:port)`, - * `http(s)://[::1](:port)` — loopback web clients (manual debugging, - * future webview consumers). The server already binds to loopback, so - * this is OS-level restricted as well. - * - * Anything else (including arbitrary `https://example.com`) is rejected - * with HTTP 403 before the `connection` event fires. - * - * Every per-agent listener that binds to an ephemeral port via the - * PortRegistrar must gate Origin so those ports can't be dialed by - * arbitrary web pages on the same host. + * `System.Net.WebSockets.ClientWebSocket`. That client does **not** + * send an `Origin` header, so we rely on the shared no-Origin baseline + * documented on {@link createAgentOriginAllowlist}. * - * Kept in sync with `agents/code/src/originAllowlist.ts` and - * `agents/browser/src/agent/originAllowlist.mts`; duplicated rather than - * shared because each agent's allowed client surface differs (VS Code - * webview schemes for `code`, Chrome/Firefox extension schemes for - * `browser`, none for `visualStudio`). + * No extension scheme prefixes are accepted — anything beyond loopback + * web clients (manual debugging, future webview consumers) and + * Origin-less native clients is rejected with HTTP 403 before the + * `connection` event fires. Every per-agent listener that binds to an + * ephemeral port via the PortRegistrar must gate Origin so those ports + * can't be dialed by arbitrary web pages on the same host. */ -export function isAllowedAgentOrigin(origin: string | undefined): boolean { - if (origin === undefined || origin === "" || origin === "null") { - return true; - } - try { - const u = new URL(origin); - if (u.protocol !== "http:" && u.protocol !== "https:") { - return false; - } - // Node's URL parser preserves IPv6 brackets in `hostname` - // (e.g. `new URL("http://[::1]:8080").hostname === "[::1]"`), - // so match the bracketed form. - return ( - u.hostname === "localhost" || - u.hostname === "127.0.0.1" || - u.hostname === "[::1]" - ); - } catch { - return false; - } -} +export const isAllowedAgentOrigin = createAgentOriginAllowlist(); diff --git a/ts/pnpm-lock.yaml b/ts/pnpm-lock.yaml index 36565f0853..aafd116a33 100644 --- a/ts/pnpm-lock.yaml +++ b/ts/pnpm-lock.yaml @@ -3171,6 +3171,9 @@ importers: debug: specifier: ^4.4.0 version: 4.4.3(supports-color@8.1.1) + websocket-utils: + specifier: workspace:* + version: link:../../utils/webSocketUtils ws: specifier: ^8.20.1 version: 8.20.1 From c835d010cd2e133974680b3fef1f9eb1c0d65342 Mon Sep 17 00:00:00 2001 From: Tal Zaccai Date: Thu, 21 May 2026 16:42:55 -0700 Subject: [PATCH 5/6] visualStudio: report bridge client count via @system ports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wires the bridge's connect/disconnect signal into SessionContext.notifyClientCountChanged so the count column in @system ports shows the real number of host-plugin connections (0 or 1, since the VS extension only opens one socket) instead of "N/A". Without this hook the bridge runs but no agent ever calls the SDK method, leaving the registrar's client count undefined. Implementation mirrors the code agent's pattern for a shared, process-singleton WS server: - VisualStudioBridge exposes onClientCountChanged and getConnectedCount(); emits on connect and on the first of close/error (guarded so close+error don't double-emit). - The lifecycle code maintains sharedActiveSessions and uses the primary-session pattern (first session in insertion order publishes the global count, the rest publish 0) so the per-session entries the @system ports summing logic sees don't multiply the count across sessions registered to the SAME physical bridge. - Primary handoff on disable transfers the count to the new primary so the column doesn't go to 0 while clients are still connected. No new tests — visualStudio has no test suite today; the pattern is exercised by the existing code-agent tests in codeUpdateContext.spec.ts. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../src/visualStudioActionHandler.ts | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/ts/packages/agents/visualStudio/src/visualStudioActionHandler.ts b/ts/packages/agents/visualStudio/src/visualStudioActionHandler.ts index d122a3b2f8..2c59f04f55 100644 --- a/ts/packages/agents/visualStudio/src/visualStudioActionHandler.ts +++ b/ts/packages/agents/visualStudio/src/visualStudioActionHandler.ts @@ -48,6 +48,15 @@ class VisualStudioBridge { >(); private readonly sendTimeoutMs: number; + /** + * Invoked on every client connect/disconnect with the current count + * of OPEN clients (0 or 1 in practice — only the VS extension host + * ever dials this bridge). Set by the agent-lifecycle code; the + * bridge itself doesn't care about consumers. Errors raised by the + * callback are swallowed (the count is informational). + */ + public onClientCountChanged?: (count: number) => void; + /** * @param wss the underlying ws server, already bound and listening. * @param port the actually bound port (OS-assigned when caller @@ -148,6 +157,7 @@ class VisualStudioBridge { this.wss.on("connection", (ws: WebSocket) => { debug("host plugin connected"); this.client = ws; + this.emitClientCount(); ws.on("message", (data: RawData) => { try { const response = JSON.parse( @@ -165,7 +175,12 @@ class VisualStudioBridge { }); const onDisconnect = (reason: string) => { debug(`host plugin disconnected (${reason})`); + // Only emit/clear once even if both `close` and `error` + // fire — `client` is set to undefined on first run and + // the guard skips the second. + if (this.client !== ws) return; this.client = undefined; + this.emitClientCount(); // Reject every in-flight send so callers don't hang // forever and the map can't grow unbounded across // reconnects. `stop()` runs the same cleanup; either @@ -182,6 +197,26 @@ class VisualStudioBridge { }); } + private emitClientCount(): void { + try { + this.onClientCountChanged?.(this.getConnectedCount()); + } catch (err) { + debug("onClientCountChanged threw:", err); + } + } + + /** + * Number of currently-OPEN bridge clients (0 or 1 in practice). + * Surfaced via `@system ports` through the SessionContext's + * `notifyClientCountChanged` API. + */ + public getConnectedCount(): number { + return this.client !== undefined && + this.client.readyState === WebSocket.OPEN + ? 1 + : 0; + } + private failPending(error: Error): void { if (this.pending.size === 0) return; const entries = Array.from(this.pending.values()); @@ -324,6 +359,20 @@ let sharedBridge: VisualStudioBridge | undefined; let sharedStartingPromise: Promise | undefined; let sharedClosingPromise: Promise | undefined; let sharedBridgeRefCount = 0; +// Active sessions currently holding a `(visualStudio, default)` +// registration on the shared bridge. Insertion order picks a "primary" +// session for client-count reporting: the primary publishes the global +// count, the rest publish 0, so `@system ports` doesn't double-count +// when summing per-session entries. See codeActionHandler for the +// reference implementation. +const sharedActiveSessions = new Set>(); + +function publishClientCountFanout(count: number): void { + const primary = sharedActiveSessions.values().next().value; + for (const sc of sharedActiveSessions) { + void sc.notifyClientCountChanged("default", sc === primary ? count : 0); + } +} async function ensureSharedBridge(): Promise { // If a previous teardown is still releasing the port, await it @@ -337,6 +386,13 @@ async function ensureSharedBridge(): Promise { sharedStartingPromise = (async () => { try { const bridge = await VisualStudioBridge.start(getBridgeBindPort()); + // Fan out client-count updates to active sessions. The + // bridge fires this on every connect/disconnect; the + // primary-session pattern in `publishClientCountFanout` + // prevents the `@system ports` summing logic from + // double-counting across sessions that each registered + // the SAME physical port. + bridge.onClientCountChanged = publishClientCountFanout; sharedBridge = bridge; return bridge; } finally { @@ -381,6 +437,19 @@ async function updateAgentContext( bridge.port, ); sharedBridgeRefCount++; + sharedActiveSessions.add(context); + // Publish the current (global) count to the primary + // session (first in insertion order) and 0 to this session + // if it isn't the primary, so `@system ports` summing + // doesn't double-count. If this session is now becoming + // the primary (i.e. it's the first to enable), it gets the + // real count; otherwise it reports 0 and any future + // onClientCountChanged fanout keeps it at 0. + const primary = sharedActiveSessions.values().next().value; + void context.notifyClientCountChanged( + "default", + context === primary ? bridge.getConnectedCount() : 0, + ); } catch (e) { // Roll back per-session bookkeeping so a subsequent retry // sees a clean slate. The shared bridge is left untouched — @@ -399,6 +468,10 @@ async function updateAgentContext( agentContext.portRegistration?.release(); delete agentContext.portRegistration; + const wasPrimary = + sharedActiveSessions.values().next().value === context; + sharedActiveSessions.delete(context); + sharedBridgeRefCount = Math.max(0, sharedBridgeRefCount - 1); if (sharedBridgeRefCount === 0 && sharedBridge !== undefined) { const toStop = sharedBridge; @@ -409,6 +482,17 @@ async function updateAgentContext( sharedClosingPromise = undefined; }); await sharedClosingPromise; + } else if (wasPrimary && sharedBridge !== undefined) { + // Primary session went away — transfer the (global) count + // to the new primary so `@system ports` keeps reporting + // the real number instead of 0. + const newPrimary = sharedActiveSessions.values().next().value; + if (newPrimary !== undefined) { + void newPrimary.notifyClientCountChanged( + "default", + sharedBridge.getConnectedCount(), + ); + } } } } From b58c59958d4590a87897eb1c7efb2fdf05f545f8 Mon Sep 17 00:00:00 2001 From: Tal Zaccai Date: Thu, 21 May 2026 17:26:11 -0700 Subject: [PATCH 6/6] visualStudio: multi-client bridge so concurrent VS instances are all counted Replace single-client his.client with Map so two or more VS extensions connecting concurrently are all tracked instead of silently displacing each other. @system ports now shows the true client count for the visualStudio/default port, matching the behavior of code-agent and browser-agent. Per-request clientId tracking means a disconnect on one VS only fails the pending requests that targeted it; other VS instances stay live. send() routes to the most-recently-connected OPEN client (legacy last-wins behavior; smarter per-solution routing is future work). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../src/visualStudioActionHandler.ts | 126 +++++++++++++----- 1 file changed, 94 insertions(+), 32 deletions(-) diff --git a/ts/packages/agents/visualStudio/src/visualStudioActionHandler.ts b/ts/packages/agents/visualStudio/src/visualStudioActionHandler.ts index 2c59f04f55..762293a026 100644 --- a/ts/packages/agents/visualStudio/src/visualStudioActionHandler.ts +++ b/ts/packages/agents/visualStudio/src/visualStudioActionHandler.ts @@ -41,19 +41,34 @@ type BridgeResponse = { }; class VisualStudioBridge { - private client: WebSocket | undefined; + // Multi-client tracking. The bridge accepts every VS extension that + // dials in (insertion-order-preserving Map so we can route to the + // most-recently-connected one). Keys are synthetic ids — the VS + // extension's `ClientWebSocket` doesn't expose anything we could + // use to distinguish two parallel instances. + private clients: Map = new Map(); + private clientIdCounter = 0; + // For each in-flight request we record which clientId we sent it + // to, so a disconnect on one VS only fails the requests that + // actually targeted that instance — other VS instances keep + // running. The id itself is bridge-wide (responses are looked up + // by id alone). private pending = new Map< string, - { resolve: (r: BridgeResponse) => void; timer: NodeJS.Timeout } + { + resolve: (r: BridgeResponse) => void; + timer: NodeJS.Timeout; + clientId: string; + } >(); private readonly sendTimeoutMs: number; /** * Invoked on every client connect/disconnect with the current count - * of OPEN clients (0 or 1 in practice — only the VS extension host - * ever dials this bridge). Set by the agent-lifecycle code; the - * bridge itself doesn't care about consumers. Errors raised by the - * callback are swallowed (the count is informational). + * of OPEN clients. Set by the agent-lifecycle code; the bridge + * itself doesn't care about consumers. Errors raised by the + * callback are swallowed (the count is informational and only + * surfaces via `@system ports`). */ public onClientCountChanged?: (count: number) => void; @@ -155,8 +170,11 @@ class VisualStudioBridge { private setupHandlers(): void { this.wss.on("connection", (ws: WebSocket) => { - debug("host plugin connected"); - this.client = ws; + const clientId = `vs-${++this.clientIdCounter}`; + this.clients.set(clientId, ws); + debug( + `host plugin connected (${clientId}); total=${this.clients.size}`, + ); this.emitClientCount(); ws.on("message", (data: RawData) => { try { @@ -174,18 +192,19 @@ class VisualStudioBridge { } }); const onDisconnect = (reason: string) => { - debug(`host plugin disconnected (${reason})`); - // Only emit/clear once even if both `close` and `error` - // fire — `client` is set to undefined on first run and - // the guard skips the second. - if (this.client !== ws) return; - this.client = undefined; + // Identity-guarded so the second of {close, error} is a + // no-op (Map.delete returns false the second time). + if (!this.clients.delete(clientId)) return; + debug( + `host plugin disconnected (${clientId}, ${reason}); remaining=${this.clients.size}`, + ); this.emitClientCount(); - // Reject every in-flight send so callers don't hang - // forever and the map can't grow unbounded across - // reconnects. `stop()` runs the same cleanup; either - // path is sufficient. - this.failPending( + // Only fail the pending sends that targeted *this* + // client — other VS instances stay live and their + // pending requests must keep waiting for their own + // responses (or hit the per-request timeout). + this.failPendingForClient( + clientId, new Error(`Host plugin disconnected: ${reason}`), ); }; @@ -206,15 +225,17 @@ class VisualStudioBridge { } /** - * Number of currently-OPEN bridge clients (0 or 1 in practice). - * Surfaced via `@system ports` through the SessionContext's - * `notifyClientCountChanged` API. + * Number of currently-OPEN bridge clients. Surfaced via + * `@system ports` through the SessionContext's + * `notifyClientCountChanged` API. Multiple VS instances can + * connect concurrently and each is counted independently. */ public getConnectedCount(): number { - return this.client !== undefined && - this.client.readyState === WebSocket.OPEN - ? 1 - : 0; + let n = 0; + for (const ws of this.clients.values()) { + if (ws.readyState === WebSocket.OPEN) n++; + } + return n; } private failPending(error: Error): void { @@ -231,6 +252,23 @@ class VisualStudioBridge { } } + private failPendingForClient(clientId: string, error: Error): void { + const toFail: string[] = []; + for (const [id, entry] of this.pending) { + if (entry.clientId === clientId) toFail.push(id); + } + for (const id of toFail) { + const entry = this.pending.get(id)!; + this.pending.delete(id); + clearTimeout(entry.timer); + entry.resolve({ + id: "", + success: false, + error: error.message, + }); + } + } + /** * Close the underlying server and resolve once the port is fully * released — important for a rapid disable→enable cycle under a @@ -239,10 +277,12 @@ class VisualStudioBridge { */ async stop(): Promise { debug("Closing VisualStudioBridge"); - if (this.client?.readyState === WebSocket.OPEN) { - this.client.close(); + for (const ws of this.clients.values()) { + if (ws.readyState === WebSocket.OPEN) { + ws.close(); + } } - this.client = undefined; + this.clients.clear(); // Reject any in-flight sends before the server closes; otherwise // callers awaiting `send()` hang forever after a manual disable. this.failPending(new Error("VisualStudioBridge stopped")); @@ -250,9 +290,18 @@ class VisualStudioBridge { } async send(actionName: string, parameters: unknown): Promise { - if (!this.client) { + // Route to the most-recently-connected OPEN client. This + // preserves the legacy single-client behavior (where the + // newest connection won) when only one VS is active, and + // gives a sensible "last-wins" tiebreak for multi-VS sessions + // — RPCs like buildSolution can't sensibly broadcast (both + // VS instances would execute), and a smarter routing strategy + // (per-solution-path, user-disambiguated) is future work. + const target = this.pickTargetClient(); + if (target === undefined) { throw new Error(`No host plugin connected on port ${this.port}`); } + const [clientId, ws] = target; const id = `${Date.now()}-${Math.random().toString(36).slice(2)}`; return new Promise((resolve, reject) => { // Timeout so a plugin that accepts the WS frame but never @@ -271,13 +320,14 @@ class VisualStudioBridge { }, this.sendTimeoutMs); this.pending.set(id, { timer, + clientId, resolve: (res) => res.success ? resolve(res.result) : reject(new Error(res.error)), }); try { - this.client!.send( + ws.send( JSON.stringify({ id, actionName, @@ -292,8 +342,20 @@ class VisualStudioBridge { }); } + // Map iteration is insertion-ordered; walk in reverse so the + // newest OPEN connection wins. Returns undefined when no client + // is currently OPEN. + private pickTargetClient(): [string, WebSocket] | undefined { + const entries = Array.from(this.clients.entries()); + for (let i = entries.length - 1; i >= 0; i--) { + const [id, ws] = entries[i]; + if (ws.readyState === WebSocket.OPEN) return [id, ws]; + } + return undefined; + } + get connected(): boolean { - return this.client !== undefined; + return this.getConnectedCount() > 0; } }