From c542c38cb1816869a731ee971da16b30c8811cdf Mon Sep 17 00:00:00 2001 From: AgentA Date: Sat, 28 Mar 2026 09:10:28 -0700 Subject: [PATCH 1/7] chore: bump version to 0.32.102 --- Cargo.lock | 6 +++--- agentmuxsrv-rs/Cargo.toml | 2 +- package.json | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 4 ++-- wsh-rs/Cargo.toml | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7112b53db..b1144aba2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10,7 +10,7 @@ checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "agentmux" -version = "0.32.101" +version = "0.32.102" dependencies = [ "chrono", "dirs 5.0.1", @@ -47,7 +47,7 @@ dependencies = [ [[package]] name = "agentmuxsrv-rs" -version = "0.32.101" +version = "0.32.102" dependencies = [ "async-stream", "axum", @@ -7467,7 +7467,7 @@ dependencies = [ [[package]] name = "wsh-rs" -version = "0.32.101" +version = "0.32.102" dependencies = [ "base64 0.22.1", "clap", diff --git a/agentmuxsrv-rs/Cargo.toml b/agentmuxsrv-rs/Cargo.toml index 62c702450..566ea7a1b 100644 --- a/agentmuxsrv-rs/Cargo.toml +++ b/agentmuxsrv-rs/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "agentmuxsrv-rs" -version = "0.32.101" +version = "0.32.102" edition = "2021" description = "AgentMux Rust backend (drop-in replacement for Go agentmuxsrv)" diff --git a/package.json b/package.json index e932fd1eb..c3addcf81 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "productName": "AgentMux", "description": "Open-Source AI-Native Terminal Built for Seamless Workflows", "license": "Apache-2.0", - "version": "0.32.101", + "version": "0.32.102", "homepage": "https://github.com/agentmuxai/agentmux", "build": { "appId": "ai.agentmux.app" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 9822e0298..3a516c71c 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "agentmux" -version = "0.32.101" +version = "0.32.102" description = "AgentMux - AI-Native Terminal" authors = ["AgentMux Corp"] edition = "2021" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 56fbd0c23..fa3d6fa0c 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,8 +1,8 @@ { "$schema": "https://raw.githubusercontent.com/tauri-apps/tauri/dev/crates/tauri-config-schema/schema.json", "productName": "AgentMux", - "version": "0.32.101", - "identifier": "ai.agentmux.app.v0-32-101", + "version": "0.32.102", + "identifier": "ai.agentmux.app.v0-32-102", "build": { "devUrl": "http://localhost:5173", "frontendDist": "../dist/frontend", diff --git a/wsh-rs/Cargo.toml b/wsh-rs/Cargo.toml index 41c52dddb..0751be594 100644 --- a/wsh-rs/Cargo.toml +++ b/wsh-rs/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wsh-rs" -version = "0.32.101" +version = "0.32.102" edition = "2021" description = "Shell integration CLI for AgentMux" From 8a595a2bdd8061716493764e3a1601514ebf8342 Mon Sep 17 00:00:00 2001 From: AgentA Date: Sat, 28 Mar 2026 13:13:54 -0700 Subject: [PATCH 2/7] chore: bump version to 0.32.103 --- Cargo.lock | 6 +++--- agentmuxsrv-rs/Cargo.toml | 2 +- package-lock.json | 4 ++-- package.json | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 4 ++-- wsh-rs/Cargo.toml | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b1144aba2..9ba332d8d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10,7 +10,7 @@ checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "agentmux" -version = "0.32.102" +version = "0.32.103" dependencies = [ "chrono", "dirs 5.0.1", @@ -47,7 +47,7 @@ dependencies = [ [[package]] name = "agentmuxsrv-rs" -version = "0.32.102" +version = "0.32.103" dependencies = [ "async-stream", "axum", @@ -7467,7 +7467,7 @@ dependencies = [ [[package]] name = "wsh-rs" -version = "0.32.102" +version = "0.32.103" dependencies = [ "base64 0.22.1", "clap", diff --git a/agentmuxsrv-rs/Cargo.toml b/agentmuxsrv-rs/Cargo.toml index 566ea7a1b..bbb603388 100644 --- a/agentmuxsrv-rs/Cargo.toml +++ b/agentmuxsrv-rs/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "agentmuxsrv-rs" -version = "0.32.102" +version = "0.32.103" edition = "2021" description = "AgentMux Rust backend (drop-in replacement for Go agentmuxsrv)" diff --git a/package-lock.json b/package-lock.json index 55397748d..3edc4d028 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "agentmux", - "version": "0.32.101", + "version": "0.32.102", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "agentmux", - "version": "0.32.101", + "version": "0.32.102", "license": "Apache-2.0", "workspaces": [ "docs" diff --git a/package.json b/package.json index c3addcf81..2b49c3b8c 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "productName": "AgentMux", "description": "Open-Source AI-Native Terminal Built for Seamless Workflows", "license": "Apache-2.0", - "version": "0.32.102", + "version": "0.32.103", "homepage": "https://github.com/agentmuxai/agentmux", "build": { "appId": "ai.agentmux.app" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 3a516c71c..c90039dcf 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "agentmux" -version = "0.32.102" +version = "0.32.103" description = "AgentMux - AI-Native Terminal" authors = ["AgentMux Corp"] edition = "2021" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index fa3d6fa0c..da9f95f64 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,8 +1,8 @@ { "$schema": "https://raw.githubusercontent.com/tauri-apps/tauri/dev/crates/tauri-config-schema/schema.json", "productName": "AgentMux", - "version": "0.32.102", - "identifier": "ai.agentmux.app.v0-32-102", + "version": "0.32.103", + "identifier": "ai.agentmux.app.v0-32-103", "build": { "devUrl": "http://localhost:5173", "frontendDist": "../dist/frontend", diff --git a/wsh-rs/Cargo.toml b/wsh-rs/Cargo.toml index 0751be594..fb6f46f4a 100644 --- a/wsh-rs/Cargo.toml +++ b/wsh-rs/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wsh-rs" -version = "0.32.102" +version = "0.32.103" edition = "2021" description = "Shell integration CLI for AgentMux" From f71268762a865e66a8fe1a923c0178ea857e5e0c Mon Sep 17 00:00:00 2001 From: AgentA Date: Sat, 28 Mar 2026 13:51:15 -0700 Subject: [PATCH 3/7] chore: bump version to 0.32.104 --- Cargo.lock | 6 +++--- agentmuxsrv-rs/Cargo.toml | 2 +- package-lock.json | 4 ++-- package.json | 2 +- src-tauri/Cargo.toml | 2 +- src-tauri/tauri.conf.json | 6 +++--- wsh-rs/Cargo.toml | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9ba332d8d..eb712ed8b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10,7 +10,7 @@ checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "agentmux" -version = "0.32.103" +version = "0.32.104" dependencies = [ "chrono", "dirs 5.0.1", @@ -47,7 +47,7 @@ dependencies = [ [[package]] name = "agentmuxsrv-rs" -version = "0.32.103" +version = "0.32.104" dependencies = [ "async-stream", "axum", @@ -7467,7 +7467,7 @@ dependencies = [ [[package]] name = "wsh-rs" -version = "0.32.103" +version = "0.32.104" dependencies = [ "base64 0.22.1", "clap", diff --git a/agentmuxsrv-rs/Cargo.toml b/agentmuxsrv-rs/Cargo.toml index bbb603388..1d9843351 100644 --- a/agentmuxsrv-rs/Cargo.toml +++ b/agentmuxsrv-rs/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "agentmuxsrv-rs" -version = "0.32.103" +version = "0.32.104" edition = "2021" description = "AgentMux Rust backend (drop-in replacement for Go agentmuxsrv)" diff --git a/package-lock.json b/package-lock.json index 3edc4d028..d353abb03 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "agentmux", - "version": "0.32.102", + "version": "0.32.103", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "agentmux", - "version": "0.32.102", + "version": "0.32.103", "license": "Apache-2.0", "workspaces": [ "docs" diff --git a/package.json b/package.json index 2b49c3b8c..da838d722 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "productName": "AgentMux", "description": "Open-Source AI-Native Terminal Built for Seamless Workflows", "license": "Apache-2.0", - "version": "0.32.103", + "version": "0.32.104", "homepage": "https://github.com/agentmuxai/agentmux", "build": { "appId": "ai.agentmux.app" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index c90039dcf..79c247820 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "agentmux" -version = "0.32.103" +version = "0.32.104" description = "AgentMux - AI-Native Terminal" authors = ["AgentMux Corp"] edition = "2021" diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index da9f95f64..389ab01f2 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,13 +1,13 @@ { "$schema": "https://raw.githubusercontent.com/tauri-apps/tauri/dev/crates/tauri-config-schema/schema.json", "productName": "AgentMux", - "version": "0.32.103", - "identifier": "ai.agentmux.app.v0-32-103", + "version": "0.32.104", + "identifier": "ai.agentmux.app.v0-32-104", "build": { "devUrl": "http://localhost:5173", "frontendDist": "../dist/frontend", "beforeDevCommand": "node -e \"require('fs').rmSync('dist/frontend',{recursive:true,force:true})\" && npx vite --config vite.config.tauri.ts", - "beforeBuildCommand": "npx vite build --config vite.config.tauri.ts" + "beforeBuildCommand": "" }, "app": { "macOSPrivateApi": true, diff --git a/wsh-rs/Cargo.toml b/wsh-rs/Cargo.toml index fb6f46f4a..95ca8f3e7 100644 --- a/wsh-rs/Cargo.toml +++ b/wsh-rs/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wsh-rs" -version = "0.32.103" +version = "0.32.104" edition = "2021" description = "Shell integration CLI for AgentMux" From 82feda267d6be8af135713bec5c25d03933605b3 Mon Sep 17 00:00:00 2001 From: AgentA Date: Sat, 28 Mar 2026 14:07:57 -0700 Subject: [PATCH 4/7] feat(agent): auth URL display + CLI exe/cmd regression fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - run_cli_login returns OAuth URL synchronously (waits up to 15s); frontend displays URL in launch panel and opens browser from host - Add RunCliLogin/CancelCliLogin Tauri commands; wire frontend setAuthUrl - Fix Windows CLI versioned-install path: derive copy destination extension from source binary (.exe→.exe, .cmd→.cmd) instead of hardcoding .cmd (cf1710f broke full-package installs by copying claude.exe→claude.cmd) - Add retro doc: docs/retro-cli-exe-cmd-regression.md Co-Authored-By: Claude Sonnet 4.6 --- Cargo.toml | 4 +- agentmuxsrv-rs/src/backend/rpc_types.rs | 26 ++ agentmuxsrv-rs/src/server/websocket.rs | 351 ++++++++++++++++++++- docs/retro-cli-exe-cmd-regression.md | 85 +++++ frontend/app/store/wshclientapi.ts | 5 + frontend/app/view/agent/agent-view.tsx | 98 +++++- frontend/app/view/agent/providers/index.ts | 42 +++ frontend/types/gotypes.d.ts | 16 + package-lock.json | 4 +- src-tauri/src/commands/platform.rs | 114 +++++-- src-tauri/tauri.conf.json | 2 +- 11 files changed, 712 insertions(+), 35 deletions(-) create mode 100644 docs/retro-cli-exe-cmd-regression.md diff --git a/Cargo.toml b/Cargo.toml index cb9d38e3c..5485b6f45 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,8 +4,8 @@ members = ["src-tauri", "agentmuxsrv-rs", "wsh-rs"] [profile.release] strip = true -lto = true -codegen-units = 1 +lto = "thin" +codegen-units = 4 opt-level = "s" # Fast release profile for testing (much faster compile, slightly larger binary) diff --git a/agentmuxsrv-rs/src/backend/rpc_types.rs b/agentmuxsrv-rs/src/backend/rpc_types.rs index 41dbb7939..7996b49a2 100644 --- a/agentmuxsrv-rs/src/backend/rpc_types.rs +++ b/agentmuxsrv-rs/src/backend/rpc_types.rs @@ -156,6 +156,7 @@ pub const COMMAND_AGENT_STOP: &str = "agentstop"; pub const COMMAND_WRITE_AGENT_CONFIG: &str = "writeagentconfig"; pub const COMMAND_RESOLVE_CLI: &str = "resolvecli"; pub const COMMAND_CHECK_CLI_AUTH: &str = "checkcliauth"; +pub const COMMAND_INSTALL_SYSDEP: &str = "installsysdep"; // Block commands pub const COMMAND_MKDIR: &str = "mkdir"; @@ -537,6 +538,31 @@ pub struct RunCliLoginResult { pub raw_output: String, } +/// Data for InstallSysdepCommand — check and auto-install a system dependency. +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct CommandInstallSysdepData { + /// Dependency name: "git", "npm", "gh" + pub dep: String, + /// Block ID for streaming install progress (optional — empty = no streaming) + #[serde(default)] + pub block_id: String, +} + +/// Result from InstallSysdepCommand +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct InstallSysdepResult { + /// Whether the dep is usable after this call + pub found: bool, + /// Absolute path to the binary (empty if not found) + pub path: String, + /// Version string (empty if not found) + pub version: String, + /// "present" — already installed | "installed" — we installed it | "not_found" — missing + pub source: String, + /// Manual install instructions shown to user when auto-install is unavailable or fails + pub install_hint: String, +} + /// Matches Go's `FileDataAt` #[derive(Debug, Clone, Serialize, Deserialize)] pub struct FileDataAt { diff --git a/agentmuxsrv-rs/src/server/websocket.rs b/agentmuxsrv-rs/src/server/websocket.rs index 90d3e3409..4a1c7313f 100644 --- a/agentmuxsrv-rs/src/server/websocket.rs +++ b/agentmuxsrv-rs/src/server/websocket.rs @@ -37,10 +37,11 @@ use crate::backend::rpc_types::{ CommandAppendForgeHistoryData, CommandListForgeHistoryData, CommandSearchForgeHistoryData, CommandImportForgeFromClawData, COMMAND_SUBPROCESS_SPAWN, COMMAND_AGENT_INPUT, COMMAND_AGENT_STOP, COMMAND_WRITE_AGENT_CONFIG, - COMMAND_RESOLVE_CLI, COMMAND_CHECK_CLI_AUTH, + COMMAND_RESOLVE_CLI, COMMAND_CHECK_CLI_AUTH, COMMAND_INSTALL_SYSDEP, CommandSubprocessSpawnData, CommandAgentInputData, CommandAgentStopData, CommandWriteAgentConfigData, CommandResolveCliData, ResolveCliResult, CommandCheckCliAuthData, CheckCliAuthResult, CommandRunCliLoginData, RunCliLoginResult, + CommandInstallSysdepData, InstallSysdepResult, }; use crate::backend::storage::{ForgeAgent, ForgeContent, ForgeSkill}; use crate::backend::waveobj::{Block, TermSize, WaveObjUpdate, wave_obj_to_value}; @@ -1466,6 +1467,354 @@ fn register_handlers(engine: &Arc, state: AppState) { }), ); + // installsysdep → check and auto-install a system dependency (git, npm, gh). + // Streams install output line-by-line via WPS install_progress events. + // On Windows uses winget; macOS uses brew; Linux warns-only (shows manual instructions). + let broker_sysdep = state.broker.clone(); + engine.register_handler( + COMMAND_INSTALL_SYSDEP, + Box::new(move |data, _ctx| { + let broker = broker_sysdep.clone(); + Box::pin(async move { + let cmd: CommandInstallSysdepData = serde_json::from_value(data) + .map_err(|e| format!("installsysdep: {e}"))?; + tracing::info!(dep = %cmd.dep, "InstallSysdep"); + + // Helper: publish a progress line to the frontend log panel. + let publish = { + let broker = broker.clone(); + let block_id = cmd.block_id.clone(); + move |msg: &str| { + if !block_id.is_empty() { + crate::backend::wps::publish_install_progress(&broker, &block_id, msg); + } + } + }; + + // ── Step 1: Check PATH first ─────────────────────────────────────────────── + let which_exe = if cfg!(windows) { "where" } else { "which" }; + // On Windows, npm is a .cmd script — `where npm` returns npm.cmd path. + let path_found = tokio::process::Command::new(which_exe) + .arg(&cmd.dep) + .output() + .await + .ok() + .filter(|o| o.status.success()) + .and_then(|o| { + let raw = String::from_utf8_lossy(&o.stdout); + // `where` can return multiple lines; take the first non-empty one + raw.lines() + .map(|l| l.trim().to_string()) + .find(|l| !l.is_empty() && std::path::Path::new(l).exists()) + }); + + if let Some(path) = path_found { + let version = get_cli_version(&path).await; + tracing::info!(dep = %cmd.dep, path = %path, version = %version, "sysdep found in PATH"); + return Ok(Some(serde_json::to_value(&InstallSysdepResult { + found: true, path, version, + source: "present".to_string(), + install_hint: String::new(), + }).unwrap())); + } + + // ── Step 2: Check known install locations (post-install PATH not refreshed) ─ + // winget installs to fixed locations; PATH update only takes effect after + // shell restart. Check the known target paths directly so we can detect a + // previously-completed silent install without requiring a restart. + let known: Vec<&str> = { + #[cfg(windows)] + match cmd.dep.as_str() { + "git" => vec![ + r"C:\Program Files\Git\cmd\git.exe", + r"C:\Program Files (x86)\Git\cmd\git.exe", + ], + "npm" | "node" => vec![ + r"C:\Program Files\nodejs\npm.cmd", + r"C:\Program Files\nodejs\node.exe", + ], + "gh" => vec![ + r"C:\Program Files\GitHub CLI\gh.exe", + ], + _ => vec![], + } + #[cfg(not(windows))] + match cmd.dep.as_str() { + "git" => vec!["/usr/bin/git", "/usr/local/bin/git", "/opt/homebrew/bin/git"], + "npm" => vec!["/usr/local/bin/npm", "/opt/homebrew/bin/npm"], + "gh" => vec!["/usr/local/bin/gh", "/opt/homebrew/bin/gh"], + _ => vec![], + } + }; + for path in &known { + if std::path::Path::new(path).exists() { + let version = get_cli_version(path).await; + tracing::info!(dep = %cmd.dep, path = %path, version = %version, "sysdep found at known path"); + return Ok(Some(serde_json::to_value(&InstallSysdepResult { + found: true, + path: path.to_string(), + version, + source: "present".to_string(), + install_hint: String::new(), + }).unwrap())); + } + } + + // ── Step 3: Not found — attempt auto-install ────────────────────────────── + publish(&format!("not found — attempting automatic install of {}...", cmd.dep)); + + // Per-platform install config + struct DepInstallConfig { + /// Command + args to run the installer + install_args: Vec, + /// Executable for the installer process + installer_exe: String, + /// Expected binary path after install (to verify success) + post_install_path: String, + /// Manual instructions shown when auto-install is unavailable/fails + hint: String, + } + + #[cfg(windows)] + let install_cfg: Option = { + // Check winget is available — it ships with Windows 10 1809+ via App Installer + let winget_available = tokio::process::Command::new("winget") + .arg("--version") + .output() + .await + .map(|o| o.status.success()) + .unwrap_or(false); + + if !winget_available { + publish("winget not available — cannot auto-install"); + None + } else { + match cmd.dep.as_str() { + "git" => Some(DepInstallConfig { + installer_exe: "winget".to_string(), + install_args: vec![ + "install".to_string(), "--id".to_string(), "Git.Git".to_string(), + "-e".to_string(), "--silent".to_string(), + "--accept-package-agreements".to_string(), + "--accept-source-agreements".to_string(), + ], + post_install_path: r"C:\Program Files\Git\cmd\git.exe".to_string(), + hint: "Install manually: winget install Git.Git OR https://git-scm.com/download/win".to_string(), + }), + "npm" | "node" => Some(DepInstallConfig { + installer_exe: "winget".to_string(), + install_args: vec![ + "install".to_string(), "--id".to_string(), "OpenJS.NodeJS.LTS".to_string(), + "-e".to_string(), "--silent".to_string(), + "--accept-package-agreements".to_string(), + "--accept-source-agreements".to_string(), + ], + post_install_path: r"C:\Program Files\nodejs\npm.cmd".to_string(), + hint: "Install manually: winget install OpenJS.NodeJS.LTS OR https://nodejs.org".to_string(), + }), + "gh" => Some(DepInstallConfig { + installer_exe: "winget".to_string(), + install_args: vec![ + "install".to_string(), "--id".to_string(), "GitHub.cli".to_string(), + "-e".to_string(), "--silent".to_string(), + "--accept-package-agreements".to_string(), + "--accept-source-agreements".to_string(), + ], + post_install_path: r"C:\Program Files\GitHub CLI\gh.exe".to_string(), + hint: "Install manually: winget install GitHub.cli OR https://cli.github.com".to_string(), + }), + _ => None, + } + } + }; + + #[cfg(target_os = "macos")] + let install_cfg: Option = { + let brew_path = ["/usr/local/bin/brew", "/opt/homebrew/bin/brew"] + .iter() + .find(|p| std::path::Path::new(p).exists()) + .map(|s| s.to_string()); + + if let Some(brew) = brew_path { + match cmd.dep.as_str() { + "git" => Some(DepInstallConfig { + installer_exe: brew.clone(), + install_args: vec!["install".to_string(), "git".to_string()], + post_install_path: "/usr/local/bin/git".to_string(), + hint: "Install manually: brew install git OR xcode-select --install".to_string(), + }), + "npm" | "node" => Some(DepInstallConfig { + installer_exe: brew.clone(), + install_args: vec!["install".to_string(), "node".to_string()], + post_install_path: "/usr/local/bin/npm".to_string(), + hint: "Install manually: brew install node OR https://nodejs.org".to_string(), + }), + "gh" => Some(DepInstallConfig { + installer_exe: brew, + install_args: vec!["install".to_string(), "gh".to_string()], + post_install_path: "/usr/local/bin/gh".to_string(), + hint: "Install manually: brew install gh OR https://cli.github.com".to_string(), + }), + _ => None, + } + } else { + publish("Homebrew not found — cannot auto-install"); + None + } + }; + + #[cfg(all(not(windows), not(target_os = "macos")))] + let install_cfg: Option = { + // Linux: auto-install is too distro-specific; surface clear manual instructions + let hint = match cmd.dep.as_str() { + "git" => "sudo apt-get install -y git OR sudo dnf install -y git", + "npm"|"node"=> "sudo apt-get install -y nodejs npm OR https://nodejs.org", + "gh" => "https://github.com/cli/cli/blob/trunk/docs/install_linux.md", + _ => "see your distribution's package manager", + }; + publish(&format!("auto-install not supported on Linux — install manually:\n {}", hint)); + None + }; + + let Some(cfg) = install_cfg else { + let hint = match cmd.dep.as_str() { + "git" => "https://git-scm.com/downloads", + "npm"|"node" => "https://nodejs.org", + "gh" => "https://cli.github.com", + _ => "", + }; + return Ok(Some(serde_json::to_value(&InstallSysdepResult { + found: false, path: String::new(), version: String::new(), + source: "not_found".to_string(), + install_hint: hint.to_string(), + }).unwrap())); + }; + + // Run the installer, streaming output line-by-line to the frontend + publish(&format!("running: {} {}", cfg.installer_exe, cfg.install_args.join(" "))); + tracing::info!(dep = %cmd.dep, installer = %cfg.installer_exe, args = ?cfg.install_args, "running installer"); + + let mut child = tokio::process::Command::new(&cfg.installer_exe) + .args(&cfg.install_args) + .stdout(std::process::Stdio::piped()) + .stderr(std::process::Stdio::piped()) + .spawn() + .map_err(|e| format!("failed to spawn installer for {}: {e}", cmd.dep))?; + + let stdout_pipe = child.stdout.take(); + let stderr_pipe = child.stderr.take(); + + let (_, _, wait_result) = tokio::time::timeout( + std::time::Duration::from_secs(300), + async { + let publish_out = { + let broker = broker.clone(); + let block_id = cmd.block_id.clone(); + move |msg: String| { + if !block_id.is_empty() { + crate::backend::wps::publish_install_progress(&broker, &block_id, &msg); + } + tracing::info!(line = %msg, "sysdep installer stdout"); + } + }; + let publish_err = { + let broker = broker.clone(); + let block_id = cmd.block_id.clone(); + move |msg: String| { + if !block_id.is_empty() { + crate::backend::wps::publish_install_progress(&broker, &block_id, &msg); + } + tracing::info!(line = %msg, "sysdep installer stderr"); + } + }; + tokio::join!( + async move { + if let Some(p) = stdout_pipe { + use tokio::io::AsyncBufReadExt; + let mut r = tokio::io::BufReader::new(p).lines(); + while let Ok(Some(line)) = r.next_line().await { + if !line.trim().is_empty() { publish_out(line); } + } + } + }, + async move { + if let Some(p) = stderr_pipe { + use tokio::io::AsyncBufReadExt; + let mut r = tokio::io::BufReader::new(p).lines(); + while let Ok(Some(line)) = r.next_line().await { + if !line.trim().is_empty() { publish_err(line); } + } + } + }, + child.wait(), + ) + }, + ).await.map_err(|_| format!("installer for {} timed out after 5 minutes", cmd.dep))?; + + let exit = wait_result.map_err(|e| format!("installer wait failed: {e}"))?; + let exit_code = exit.code().unwrap_or(-1); + tracing::info!(dep = %cmd.dep, exit_code = exit_code, "installer finished"); + + if !exit.success() { + publish(&format!("install failed (exit {exit_code}) — install manually:")); + publish(&format!(" {}", cfg.hint)); + return Ok(Some(serde_json::to_value(&InstallSysdepResult { + found: false, path: String::new(), version: String::new(), + source: "not_found".to_string(), + install_hint: cfg.hint, + }).unwrap())); + } + + // ── Step 4: Verify install at known path ────────────────────────────────── + if std::path::Path::new(&cfg.post_install_path).exists() { + let version = get_cli_version(&cfg.post_install_path).await; + publish(&format!("installed {} {} at {}", cmd.dep, version, cfg.post_install_path)); + tracing::info!(dep = %cmd.dep, path = %cfg.post_install_path, version = %version, "sysdep installed"); + return Ok(Some(serde_json::to_value(&InstallSysdepResult { + found: true, + path: cfg.post_install_path, + version, + source: "installed".to_string(), + install_hint: String::new(), + }).unwrap())); + } + + // Installer exited 0 but binary not at expected path — try PATH again + let path_retry = tokio::process::Command::new(which_exe) + .arg(&cmd.dep) + .output() + .await + .ok() + .filter(|o| o.status.success()) + .and_then(|o| { + String::from_utf8_lossy(&o.stdout) + .lines() + .map(|l| l.trim().to_string()) + .find(|l| !l.is_empty() && std::path::Path::new(l).exists()) + }); + + if let Some(path) = path_retry { + let version = get_cli_version(&path).await; + publish(&format!("installed {} {} at {}", cmd.dep, version, path)); + return Ok(Some(serde_json::to_value(&InstallSysdepResult { + found: true, path, version, + source: "installed".to_string(), + install_hint: String::new(), + }).unwrap())); + } + + // Install succeeded but binary not locatable — PATH refresh needed + publish(&format!("{} was installed but is not yet in PATH.", cmd.dep)); + publish("Restart AgentMux after install to pick up the updated PATH."); + Ok(Some(serde_json::to_value(&InstallSysdepResult { + found: false, path: String::new(), version: String::new(), + source: "not_found".to_string(), + install_hint: format!("{} — restart AgentMux to apply PATH changes", cfg.hint), + }).unwrap())) + }) + }), + ); + // eventreadhistory → read persisted event history from the WPS broker let broker_history = state.broker.clone(); engine.register_handler( diff --git a/docs/retro-cli-exe-cmd-regression.md b/docs/retro-cli-exe-cmd-regression.md new file mode 100644 index 000000000..5a3bd0e3c --- /dev/null +++ b/docs/retro-cli-exe-cmd-regression.md @@ -0,0 +1,85 @@ +# Retro: Claude CLI Reverted to npm Install (`.exe` → `.cmd` regression) + +**Date:** 2026-03-28 +**Commit that introduced it:** `cf1710f` — _fix(windows): prefer .cmd wrapper for Node.js CLI detection_ +**Symptom:** Claude CLI shows `(unknown)` version; auth browser opens but CLI invocation broken; full package install ignored in favour of npm + +--- + +## What Happened + +### Before `cf1710f` +`cli_bin` (the versioned copy destination) was `/claude.exe` on Windows. +Fast-path: copies `~/.local/bin/claude.exe` → versioned dir as `.exe`. +`make_cli_cmd("claude.exe")` → runs directly as native PE. Works. + +### After `cf1710f` +`cli_bin` was changed to `/claude.cmd` on Windows (to fix npm-based providers). +Fast-path: now copies `~/.local/bin/claude.exe` → versioned dir as `claude.cmd`. +The file on disk is a PE binary with a `.cmd` filename. +`make_cli_cmd("claude.cmd")` → routes through `cmd.exe /C claude.cmd`. +`cmd.exe` tries to parse a PE binary as a batch script → fails. +`get_cli_version` returns `"unknown"`. CLI is effectively broken. + +### Why It Was a Silent Failure +- The versioned dir **file exists** (`claude.cmd`) so Step 1 (already installed check) returns early +- The path is logged as `[local install]` — looks healthy +- Only symptom visible to users: `(unknown)` version and broken CLI invocation + +--- + +## Root Cause + +`cf1710f` correctly observed that npm-installed CLIs on Windows are `.cmd` batch wrappers, +and hardcoded the versioned bin path to always use `.cmd`. But this assumption is wrong for +`claude` (Claude Code), which is a native Node.js binary installed by the Claude Code +installer at `~/.local/bin/claude.exe` — **not a `.cmd` batch wrapper**. + +The fix for codex/gemini (npm → `.cmd`) conflated **all** Windows CLI targets. + +--- + +## Affected Paths + +| Provider | Install method | Real extension | Broken as | +|-----------|-------------------------|---------------|-----------| +| `claude` | Full package installer | `.exe` | `.cmd` | +| `codex` | npm install | `.cmd` | `.cmd` ✓ | +| `gemini` | npm install | `.cmd` | `.cmd` ✓ | + +--- + +## Fix + +`cli_bin` must respect the **source extension**, not assume `.cmd`. + +Two separate versioned paths on Windows: +- `/claude.exe` — for native-exe providers (detected via known_paths or `where`) +- `/claude.cmd` — for npm-installed providers (produced by npm install step) + +The fast-path copy should determine the destination filename based on the source extension: + +```rust +// Derive destination extension from the source binary +let dest_ext = std::path::Path::new(source) + .extension() + .and_then(|e| e.to_str()) + .unwrap_or("exe"); +let cli_bin_for_copy = format!("{}/{}.{}", bin_dir, cmd.cli_command, dest_ext); +``` + +`cli_bin` (the "already installed?" check) needs to check **both** extensions: +```rust +let cli_bin_exe = format!("{}/{}.exe", bin_dir, cmd.cli_command); +let cli_bin_cmd = format!("{}/{}.cmd", bin_dir, cmd.cli_command); +``` + +`npm_bin` (npm install output) stays as `.cmd` — npm always produces `.cmd` on Windows. + +--- + +## Lesson + +When adding support for a new install method (npm → `.cmd`), the existing install method +(full package → `.exe`) must be kept in parallel. A single `cli_bin` variable cannot +serve both; they need separate paths or the copy destination must mirror the source extension. diff --git a/frontend/app/store/wshclientapi.ts b/frontend/app/store/wshclientapi.ts index da3f9b38e..60752fc9a 100644 --- a/frontend/app/store/wshclientapi.ts +++ b/frontend/app/store/wshclientapi.ts @@ -603,6 +603,11 @@ class RpcApiType { return client.wshRpcCall("runclilogin", data, opts); } + // command "installsysdep" [call] + InstallSysdepCommand(client: WshClient, data: CommandInstallSysdepData, opts?: RpcOpts): Promise { + return client.wshRpcCall("installsysdep", data, opts); + } + } export const RpcApi = new RpcApiType(); diff --git a/frontend/app/view/agent/agent-view.tsx b/frontend/app/view/agent/agent-view.tsx index b6f37f389..87707517d 100644 --- a/frontend/app/view/agent/agent-view.tsx +++ b/frontend/app/view/agent/agent-view.tsx @@ -267,6 +267,83 @@ async function runLaunchFlow( meta: { cmd: cliResult.cli_path }, }); + // Phase 1.5: System Dependency Checks + // Verify (and auto-install where possible) runtime tools the agent needs: git, npm, gh. + // Each dep is checked independently. Fatal deps block launch if install fails. + // Non-fatal deps show a warning but launch continues — tool calls will fail naturally later. + if (provider.requiredSystemDeps && provider.requiredSystemDeps.length > 0) { + log("deps", "checking system dependencies..."); + + // Subscribe to install progress events for dep installers (same channel as CLI install) + const depInstallScope = WOS.makeORef("block", blockId); + const unsubDepInstall = waveEventSubscribe({ + eventType: "install_progress", + scope: depInstallScope, + handler: (event: any) => { + const msg: string = event?.data?.message ?? ""; + if (msg) log("deps", ` ${msg}`); + }, + }); + + try { + for (const dep of provider.requiredSystemDeps) { + if (isCancelled()) break; + log(dep.name, `checking ${dep.name}...`); + let result: InstallSysdepResult; + try { + result = await RpcApi.InstallSysdepCommand(TabRpcClient, { + dep: dep.name, + block_id: blockId, + }, { timeout: 360000 }); // 6 min — winget can be slow + } catch (err: any) { + // RPC-level error (backend crashed, timeout) — treat as not found + result = { + found: false, + path: "", + version: "", + source: "not_found", + install_hint: "", + }; + log(dep.name, `check failed: ${err?.message ?? String(err)}`, "warn"); + } + + if (result.found) { + if (result.source === "installed") { + log(dep.name, `installed ${dep.name} ${result.version} at ${result.path}`); + } else { + log(dep.name, `found: ${result.path}${result.version ? ` (${result.version})` : ""}`); + } + } else { + // Dep is missing — compose a verbose, actionable message + const lines: string[] = [ + `${dep.name} not found${dep.fatal ? " — this is required" : " — optional but recommended"}`, + `why needed: ${dep.reason}`, + ]; + if (result.install_hint) { + lines.push(`install: ${result.install_hint}`); + } + if (dep.fatal) { + lines.push("restart AgentMux after installing and try again"); + } else { + lines.push("launch will continue, but tool calls requiring this dep will fail"); + } + + const level = dep.fatal ? "error" : "warn"; + for (const line of lines) { + log(dep.name, line, level); + } + + if (dep.fatal) { + unsubDepInstall(); + return "fatal"; + } + } + } + } finally { + unsubDepInstall(); + } + } + // Phase 2: Auth Check → auto-login if not authenticated log("auth", `checking ${provider.cliCommand} authentication...`); let needsLogin = false; @@ -291,14 +368,27 @@ async function runLaunchFlow( if (needsLogin) { log("auth", "not authenticated — starting login flow..."); try { - // Run from Tauri host (GUI process) so the browser opens correctly on Windows. - // Returns immediately after spawning — browser opens, frontend polls for completion. - await getApi().runCliLogin( + log("auth", "opening browser for authentication..."); + // run_cli_login: spawns `claude auth login`, waits up to 15s for the OAuth URL + // in CLI output, opens the browser from the host process, then returns the URL. + // Returns null if the URL wasn't captured (e.g. CLI exited early). + const loginUrl = await getApi().runCliLogin( cliResult.cli_path, provider.authLoginCommand, authEnv ?? {}, ); - log("auth", "a browser window should have opened — complete login there"); + + if (loginUrl) { + // Show URL in the launch panel with a copy button (setAuthUrl renders the box). + // Also open via openExternal as a redundant second attempt in case the host + // process opener failed (e.g. no default browser registered on this machine). + setAuthUrl(loginUrl); + getApi().openExternal(loginUrl); + log("auth", "browser opened — if it did not appear, use the URL shown below"); + } else { + log("auth", "browser should have opened — if it did not, run:", "warn"); + log("auth", ` ${provider.cliCommand} ${provider.authLoginCommand.join(" ")}`, "warn"); + } // Poll until authenticated, cancelled, or timed out (5 minutes) log("auth", "waiting for login to complete..."); diff --git a/frontend/app/view/agent/providers/index.ts b/frontend/app/view/agent/providers/index.ts index 6b7d1843d..91beb2139 100644 --- a/frontend/app/view/agent/providers/index.ts +++ b/frontend/app/view/agent/providers/index.ts @@ -1,6 +1,19 @@ // Copyright 2025, AgentMux Corp. // SPDX-License-Identifier: Apache-2.0 +/** A system-level dependency that must be present before an agent session can run. */ +export interface SystemDepSpec { + /** Binary name as passed to installsysdep: "git" | "npm" | "gh" */ + name: string; + /** + * If true: missing dep (after auto-install attempt) blocks launch with a fatal error. + * If false: missing dep shows a warning but launch continues — tool calls will fail later. + */ + fatal: boolean; + /** Shown to user explaining why this dep is needed. */ + reason: string; +} + export interface ProviderDefinition { id: string; displayName: string; @@ -31,6 +44,9 @@ export interface ProviderDefinition { resumeFlag: string | null; // JSON field name containing the session/thread ID in the CLI's init event. sessionIdField: string; + // System dependencies required before this provider can run useful agent sessions. + // Checked and auto-installed (where possible) in Phase 1.5 of the launch flow. + requiredSystemDeps: SystemDepSpec[]; } export const PROVIDERS: Record = { @@ -57,6 +73,18 @@ export const PROVIDERS: Record = { launchArgs: ["-p", "--output-format", "stream-json", "--verbose", "--include-partial-messages", "--dangerously-skip-permissions"], resumeFlag: "--resume", sessionIdField: "session_id", + requiredSystemDeps: [ + { + name: "git", + fatal: true, + reason: "Claude Code uses git for all repository operations (diff, log, status, commit, push). Without git, nearly all coding tasks will fail.", + }, + { + name: "npm", + fatal: false, + reason: "Claude Code executes npm commands as tools (install, run, test). Without npm, any task involving Node.js package operations will fail.", + }, + ], }, codex: { id: "codex", @@ -83,6 +111,13 @@ export const PROVIDERS: Record = { // Multi-turn is handled by re-running exec; null disables automatic --resume append. resumeFlag: null, sessionIdField: "thread_id", + requiredSystemDeps: [ + { + name: "git", + fatal: true, + reason: "Codex CLI uses git for repository operations (diff, log, commit, push).", + }, + ], }, gemini: { id: "gemini", @@ -109,6 +144,13 @@ export const PROVIDERS: Record = { launchArgs: ["--output-format", "stream-json", "--yolo", "-p", ""], resumeFlag: "-r", sessionIdField: "session_id", + requiredSystemDeps: [ + { + name: "git", + fatal: true, + reason: "Gemini CLI uses git for repository operations (diff, log, commit, push).", + }, + ], }, }; diff --git a/frontend/types/gotypes.d.ts b/frontend/types/gotypes.d.ts index ee94277f2..a81082393 100644 --- a/frontend/types/gotypes.d.ts +++ b/frontend/types/gotypes.d.ts @@ -1635,6 +1635,22 @@ declare global { raw_output: string; }; + // wshrpc.CommandInstallSysdepData + type CommandInstallSysdepData = { + dep: string; + block_id?: string; + }; + + // wshrpc.InstallSysdepResult + type InstallSysdepResult = { + found: boolean; + path: string; + version: string; + // "present" | "installed" | "not_found" + source: string; + install_hint: string; + }; + } export {} diff --git a/package-lock.json b/package-lock.json index d353abb03..f8723fbe2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "agentmux", - "version": "0.32.103", + "version": "0.32.104", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "agentmux", - "version": "0.32.103", + "version": "0.32.104", "license": "Apache-2.0", "workspaces": [ "docs" diff --git a/src-tauri/src/commands/platform.rs b/src-tauri/src/commands/platform.rs index 5310ef734..333859c23 100644 --- a/src-tauri/src/commands/platform.rs +++ b/src-tauri/src/commands/platform.rs @@ -264,22 +264,25 @@ pub async fn run_cli_login( cmd.args(&login_args) .envs(&auth_env) .stdin(std::process::Stdio::null()) - .stdout(std::process::Stdio::null()) - .stderr(std::process::Stdio::null()); + // Pipe stdout+stderr so we can extract the OAuth URL. + // The CLI always prints the URL (browser open or not) — we capture it, + // return it to the frontend, and also try to open the browser ourselves. + .stdout(std::process::Stdio::piped()) + .stderr(std::process::Stdio::piped()); - // No console window for the child process on Windows + // No console window on Windows #[cfg(windows)] cmd.creation_flags(0x08000000); // CREATE_NO_WINDOW let mut child = cmd.spawn() .map_err(|e| format!("failed to spawn {cli_path}: {e}"))?; - tracing::info!(cli = %cli_path, "run_cli_login: spawned, browser should open"); + tracing::info!(cli = %cli_path, "run_cli_login: spawned"); - // Register a cancellation channel so cancel_cli_login() can kill this child. - // If a previous login is still pending its cancel sender gets dropped here, - // which is harmless (the old oneshot receiver will see a disconnect error and - // the background task will just wait for child.wait() instead). + let stdout_pipe = child.stdout.take(); + let stderr_pipe = child.stderr.take(); + + // Register cancellation channel so cancel_cli_login() can kill this child. let (cancel_tx, cancel_rx) = tokio::sync::oneshot::channel::<()>(); { let state = app.state::(); @@ -287,32 +290,93 @@ pub async fn run_cli_login( *stored = Some(cancel_tx); } - // Background task: wait for child to exit normally, or kill it on cancel. + // Extract the first https:// URL from a line that looks like an auth URL. + fn extract_auth_url(line: &str) -> Option { + let start = line.find("https://")?; + let url: String = line[start..] + .chars() + .take_while(|c| !c.is_whitespace()) + .collect(); + if url.contains("oauth") || url.contains("authorize") || url.contains("claude.ai") { + Some(url) + } else { + None + } + } + + // Spawn concurrent readers that forward each line to a channel; the first + // OAuth URL found wins and is sent on url_tx. + let (url_tx, url_rx) = tokio::sync::oneshot::channel::(); + let url_tx = std::sync::Arc::new(std::sync::Mutex::new(Some(url_tx))); + + let tx1 = url_tx.clone(); tokio::spawn(async move { - tokio::select! { - result = child.wait() => { - match result { - Ok(status) => tracing::info!( - exit_code = status.code(), - "run_cli_login: child exited" - ), - Err(e) => tracing::warn!( - error = %e, - "run_cli_login: child wait error" - ), + if let Some(pipe) = stdout_pipe { + use tokio::io::AsyncBufReadExt; + let mut r = tokio::io::BufReader::new(pipe).lines(); + while let Ok(Some(line)) = r.next_line().await { + tracing::debug!(line = %line, "run_cli_login stdout"); + if let Some(url) = extract_auth_url(&line) { + let _ = tx1.lock().unwrap().take().map(|tx| tx.send(url)); + break; + } + } + } + }); + + let tx2 = url_tx.clone(); + tokio::spawn(async move { + if let Some(pipe) = stderr_pipe { + use tokio::io::AsyncBufReadExt; + let mut r = tokio::io::BufReader::new(pipe).lines(); + while let Ok(Some(line)) = r.next_line().await { + tracing::debug!(line = %line, "run_cli_login stderr"); + if let Some(url) = extract_auth_url(&line) { + let _ = tx2.lock().unwrap().take().map(|tx| tx.send(url)); + break; } } + } + }); + + // Wait up to 15 seconds for the URL to appear in CLI output. + // The CLI prints it almost immediately after startup (before the browser opens). + let captured_url = tokio::time::timeout( + std::time::Duration::from_secs(15), + url_rx, + ) + .await + .ok() // timeout → None + .and_then(|r| r.ok()); // channel dropped → None + + if let Some(ref url) = captured_url { + tracing::info!(url = %url, "run_cli_login: OAuth URL captured, opening browser"); + // Open the browser from the host process. + // This runs regardless of whether the CLI's own open attempt succeeded, + // making it a reliable fallback when the CLI's browser open fails. + use tauri_plugin_opener::OpenerExt; + if let Err(e) = app.opener().open_url(url, None::<&str>) { + tracing::warn!(error = %e, "run_cli_login: browser open failed"); + } + } else { + tracing::warn!("run_cli_login: no OAuth URL found in CLI output within 15s"); + } + + // Keep the child alive in the background — it has an HTTP server listening + // for the OAuth redirect callback. Kill it on cancel signal. + tokio::spawn(async move { + tokio::select! { + status = child.wait() => { + tracing::info!(exit_code = status.ok().and_then(|s| s.code()), "run_cli_login: child exited"); + } _ = cancel_rx => { - tracing::info!("run_cli_login: cancel signal received, killing child"); + tracing::info!("run_cli_login: cancel received, killing child"); let _ = child.kill().await; } } }); - // Return None immediately — URL capture is not feasible when the browser - // opens successfully (the CLI only prints the URL as a fallback when the - // browser fails to open, and does so only after the process exits). - Ok(None) + Ok(captured_url) } /// Kill the in-progress CLI login process spawned by run_cli_login. diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 389ab01f2..84d9ed51f 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -7,7 +7,7 @@ "devUrl": "http://localhost:5173", "frontendDist": "../dist/frontend", "beforeDevCommand": "node -e \"require('fs').rmSync('dist/frontend',{recursive:true,force:true})\" && npx vite --config vite.config.tauri.ts", - "beforeBuildCommand": "" + "beforeBuildCommand": "npx vite build --config vite.config.tauri.ts" }, "app": { "macOSPrivateApi": true, From b307d3c73b3abb4a526fec7573e682b0de6ffd68 Mon Sep 17 00:00:00 2001 From: AgentA Date: Sat, 28 Mar 2026 14:10:13 -0700 Subject: [PATCH 5/7] fix(windows): preserve source extension when copying CLI to versioned dir MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cf1710f hardcoded .cmd as the versioned bin destination on Windows to fix npm-based providers (codex/gemini). This broke full-package installs: claude.exe was copied into claude.cmd — a PE binary with a batch filename — causing cmd.exe /C to fail and get_cli_version to return "unknown". Fix: - Step 1 (already-installed check) now probes both .exe and .cmd candidates - Fast-path copy derives the destination extension from the source file (.exe source → .exe dest, .cmd source → .cmd dest) - Slow-path (post-npm-install) still uses .cmd since npm always produces .cmd wrappers on Windows Co-Authored-By: Claude Sonnet 4.6 --- agentmuxsrv-rs/src/server/websocket.rs | 64 ++++++++++++++++++-------- 1 file changed, 45 insertions(+), 19 deletions(-) diff --git a/agentmuxsrv-rs/src/server/websocket.rs b/agentmuxsrv-rs/src/server/websocket.rs index 4a1c7313f..5ee79b1b0 100644 --- a/agentmuxsrv-rs/src/server/websocket.rs +++ b/agentmuxsrv-rs/src/server/websocket.rs @@ -925,10 +925,18 @@ fn register_handlers(engine: &Arc, state: AppState) { ); let bin_dir = format!("{}/bin", provider_dir); - // Expected binary path. - // On Windows, Node.js CLIs installed by npm are .cmd batch wrappers, not .exe. - // Use .cmd so make_cli_cmd() routes them through cmd.exe /C correctly. - let cli_bin = if cfg!(windows) { + // On Windows, CLIs come in two flavours: + // .exe — native binary from a full package installer (e.g. claude) + // .cmd — batch wrapper from an npm install (e.g. codex, gemini) + // We keep separate candidate paths for each so Step 1 finds either, + // and the fast-path copy preserves the source extension rather than + // forcing .cmd (which would produce a PE binary named .cmd — broken). + let cli_bin_exe = if cfg!(windows) { + format!("{}/{}.exe", bin_dir, cmd.cli_command) + } else { + format!("{}/{}", bin_dir, cmd.cli_command) + }; + let cli_bin_cmd = if cfg!(windows) { format!("{}/{}.cmd", bin_dir, cmd.cli_command) } else { format!("{}/{}", bin_dir, cmd.cli_command) @@ -942,7 +950,7 @@ fn register_handlers(engine: &Arc, state: AppState) { }; // Step 1: Check if already installed in versioned directory - for candidate in [&cli_bin, &npm_bin] { + for candidate in [&cli_bin_exe, &cli_bin_cmd, &npm_bin] { if std::path::Path::new(candidate).exists() { let version = get_cli_version(candidate).await; tracing::info!( @@ -1024,19 +1032,36 @@ fn register_handlers(engine: &Arc, state: AppState) { format!("failed to create {}: {e}", bin_dir) })?; - // Fast path: copy existing binary to versioned dir (no network needed) + // Fast path: copy existing binary to versioned dir (no network needed). + // Derive the destination filename from the source extension so we never + // copy a native .exe into a .cmd path (which breaks cmd.exe invocation). if let Some(ref source) = system_bin { + let dest = { + #[cfg(windows)] + { + let src_ext = std::path::Path::new(source) + .extension() + .and_then(|e| e.to_str()) + .unwrap_or("exe") + .to_ascii_lowercase(); + format!("{}/{}.{}", bin_dir, cmd.cli_command, src_ext) + } + #[cfg(not(windows))] + { + format!("{}/{}", bin_dir, cmd.cli_command) + } + }; tracing::info!( - source = %source, target = %cli_bin, + source = %source, target = %dest, "copying existing CLI binary to versioned directory" ); - std::fs::copy(source, &cli_bin).map_err(|e| { - format!("failed to copy {} → {}: {e}", source, cli_bin) + std::fs::copy(source, &dest).map_err(|e| { + format!("failed to copy {} → {}: {e}", source, dest) })?; - let version = get_cli_version(&cli_bin).await; - tracing::info!(path = %cli_bin, version = %version, "CLI copied to versioned dir"); + let version = get_cli_version(&dest).await; + tracing::info!(path = %dest, version = %version, "CLI copied to versioned dir"); return Ok(Some(serde_json::to_value(&ResolveCliResult { - cli_path: cli_bin, + cli_path: dest, version, source: "local_install".to_string(), }).unwrap())); @@ -1289,20 +1314,21 @@ fn register_handlers(engine: &Arc, state: AppState) { cmd.cli_command, search_paths ))?; - // Copy binary to versioned directory + // Copy binary to versioned directory. + // npm always produces .cmd wrappers on Windows, so use cli_bin_cmd here. tracing::info!( source = %source_path, - target = %cli_bin, + target = %cli_bin_cmd, "copying CLI binary to versioned directory" ); - std::fs::copy(&source_path, &cli_bin).map_err(|e| { - format!("failed to copy {} → {}: {e}", source_path, cli_bin) + std::fs::copy(&source_path, &cli_bin_cmd).map_err(|e| { + format!("failed to copy {} → {}: {e}", source_path, cli_bin_cmd) })?; - let version = get_cli_version(&cli_bin).await; - tracing::info!(path = %cli_bin, version = %version, "CLI installed successfully"); + let version = get_cli_version(&cli_bin_cmd).await; + tracing::info!(path = %cli_bin_cmd, version = %version, "CLI installed successfully"); Ok(Some(serde_json::to_value(&ResolveCliResult { - cli_path: cli_bin, + cli_path: cli_bin_cmd, version, source: "installed".to_string(), }).unwrap())) From 12575b79966dafd897d8d3d1f2aa39a2d3d955db Mon Sep 17 00:00:00 2001 From: AgentA Date: Sat, 28 Mar 2026 14:42:08 -0700 Subject: [PATCH 6/7] feat(auth): add auth code paste input to login URL box MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the OAuth browser redirect to localhost fails, the auth server shows a manual authentication code. Added a paste input + Submit button below the login URL so users can enter it without leaving the app. - run_cli_login: stdin now piped; background task forwards codes via mpsc - New Tauri command: write_cli_login_stdin(code) → sends to CLI stdin - AppState: cli_login_stdin_tx replaces cli_login_stdin (Send-safe channel) - AgentDocumentView: auth code input field + Submit button (Enter or click) Co-Authored-By: Claude Sonnet 4.6 --- frontend/app/view/agent/agent-view.scss | 12 ++++ .../agent/components/AgentDocumentView.tsx | 60 ++++++++++++++----- frontend/types/custom.d.ts | 1 + frontend/util/tauri-api.ts | 3 + src-tauri/src/commands/platform.rs | 41 ++++++++++++- src-tauri/src/lib.rs | 1 + src-tauri/src/state.rs | 5 ++ 7 files changed, 108 insertions(+), 15 deletions(-) diff --git a/frontend/app/view/agent/agent-view.scss b/frontend/app/view/agent/agent-view.scss index 18f83face..4ba19ee55 100644 --- a/frontend/app/view/agent/agent-view.scss +++ b/frontend/app/view/agent/agent-view.scss @@ -104,6 +104,18 @@ &:hover { opacity: 0.85; } } + .agent-auth-code-input { + flex: 1; + padding: 3px 8px; + font-size: 11px; + background: var(--input-bg-color, rgba(0,0,0,0.3)); + color: var(--main-text-color, #fff); + border: 1px solid var(--border-color, rgba(255,255,255,0.2)); + border-radius: 3px; + outline: none; + &:focus { border-color: var(--accent-color, #4a9eff); } + } + // === Retry Login Bar === .agent-retry-bar { flex-shrink: 0; diff --git a/frontend/app/view/agent/components/AgentDocumentView.tsx b/frontend/app/view/agent/components/AgentDocumentView.tsx index 5e347fba8..03d5cf287 100644 --- a/frontend/app/view/agent/components/AgentDocumentView.tsx +++ b/frontend/app/view/agent/components/AgentDocumentView.tsx @@ -8,6 +8,7 @@ */ import { createEffect, For, Show, type Accessor, type JSX, onCleanup } from "solid-js"; +import { getApi } from "@/app/store/global"; import type { SignalPair } from "../state"; import type { DocumentNode, DocumentState, SubagentLinkNode } from "../types"; import { AgentMessageBlock } from "./AgentMessageBlock"; @@ -105,21 +106,52 @@ export const AgentDocumentView = ({ documentAtom, documentStateAtom, logLines, a )} - {(url) => ( -
-
Login URL (if browser didn't open):
-
- {url()} - + {(url) => { + let codeInput: HTMLInputElement | undefined; + return ( +
+
Login URL (if browser didn't open):
+
+ {url()} + +
+
+ Authentication Code (paste here if prompted): +
+
+ { + if (e.key === "Enter" && codeInput?.value) { + getApi().writeCliLoginStdin(codeInput.value).catch(() => {}); + codeInput.value = ""; + } + }} + /> + +
-
- )} + ); + }}
diff --git a/frontend/types/custom.d.ts b/frontend/types/custom.d.ts index 1df7ccd57..51906cc0c 100644 --- a/frontend/types/custom.d.ts +++ b/frontend/types/custom.d.ts @@ -155,6 +155,7 @@ declare global { ensureAuthDir: (providerId: string) => Promise; runCliLogin: (cliPath: string, loginArgs: string[], authEnv: Record) => Promise; cancelCliLogin: () => Promise; + writeCliLoginStdin: (code: string) => Promise; listen: (event: string, callback: (event: any) => void) => Promise<() => void>; startCrossDrag: ( dragType: "pane" | "tab", diff --git a/frontend/util/tauri-api.ts b/frontend/util/tauri-api.ts index 5261ce5be..2bf7a0f6d 100644 --- a/frontend/util/tauri-api.ts +++ b/frontend/util/tauri-api.ts @@ -393,6 +393,9 @@ export function buildTauriApi(): AppApi { cancelCliLogin: async () => { await invoke("cancel_cli_login"); }, + writeCliLoginStdin: async (code: string) => { + await invoke("write_cli_login_stdin", { code }); + }, listen: async (event: string, callback: (event: any) => void) => { const unlisten = await listen(event, callback); diff --git a/src-tauri/src/commands/platform.rs b/src-tauri/src/commands/platform.rs index 333859c23..0678848f6 100644 --- a/src-tauri/src/commands/platform.rs +++ b/src-tauri/src/commands/platform.rs @@ -263,7 +263,9 @@ pub async fn run_cli_login( let mut cmd = tokio::process::Command::new(&cli_path); cmd.args(&login_args) .envs(&auth_env) - .stdin(std::process::Stdio::null()) + // Pipe stdin so write_cli_login_stdin can forward an auth code if the + // user has to paste one manually (e.g. when the localhost redirect fails). + .stdin(std::process::Stdio::piped()) // Pipe stdout+stderr so we can extract the OAuth URL. // The CLI always prints the URL (browser open or not) — we capture it, // return it to the frontend, and also try to open the browser ourselves. @@ -284,10 +286,28 @@ pub async fn run_cli_login( // Register cancellation channel so cancel_cli_login() can kill this child. let (cancel_tx, cancel_rx) = tokio::sync::oneshot::channel::<()>(); + + // Spawn a background task that owns ChildStdin and forwards auth codes sent + // via write_cli_login_stdin(). ChildStdin is not Send, so it must stay in + // the task that spawned it — we communicate via an mpsc channel. + let (stdin_tx, mut stdin_rx) = tokio::sync::mpsc::channel::(4); { let state = app.state::(); let mut stored = state.cli_login_cancel.lock().unwrap(); *stored = Some(cancel_tx); + let mut tx_stored = state.cli_login_stdin_tx.lock().unwrap(); + *tx_stored = Some(stdin_tx); + } + + if let Some(mut stdin) = child.stdin.take() { + tokio::spawn(async move { + use tokio::io::AsyncWriteExt; + while let Some(code) = stdin_rx.recv().await { + let line = format!("{}\n", code.trim()); + if stdin.write_all(line.as_bytes()).await.is_err() { break; } + let _ = stdin.flush().await; + } + }); } // Extract the first https:// URL from a line that looks like an auth URL. @@ -379,6 +399,25 @@ pub async fn run_cli_login( Ok(captured_url) } +/// Write an auth code to the stdin of the in-progress CLI login process. +/// Called when the user manually pastes an authentication code from the browser. +#[tauri::command] +pub async fn write_cli_login_stdin(app: tauri::AppHandle, code: String) -> Result<(), String> { + let state = app.state::(); + let sender = { + let tx_stored = state.cli_login_stdin_tx.lock().unwrap(); + tx_stored.clone() + }; + if let Some(tx) = sender { + tx.send(code).await + .map_err(|e| format!("write_cli_login_stdin: send failed: {e}"))?; + tracing::info!("write_cli_login_stdin: auth code forwarded to stdin task"); + } else { + return Err("no active CLI login process".to_string()); + } + Ok(()) +} + /// Kill the in-progress CLI login process spawned by run_cli_login. /// Called when the user cancels login or closes the agent pane. #[tauri::command] diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 241f8273c..2319af698 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -50,6 +50,7 @@ pub fn run() { commands::platform::ensure_auth_dir, commands::platform::run_cli_login, commands::platform::cancel_cli_login, + commands::platform::write_cli_login_stdin, commands::platform::get_config_dir, commands::platform::ensure_settings_file, commands::platform::open_in_editor, diff --git a/src-tauri/src/state.rs b/src-tauri/src/state.rs index dfc38ee68..b496ea6f0 100644 --- a/src-tauri/src/state.rs +++ b/src-tauri/src/state.rs @@ -147,6 +147,10 @@ pub struct AppState { /// Sending on this channel signals the background task to kill the child. pub cli_login_cancel: Mutex>>, + /// Channel sender for forwarding auth codes to the in-progress CLI login stdin. + /// The background task in run_cli_login owns the ChildStdin and reads from this channel. + pub cli_login_stdin_tx: Mutex>>, + /// Windows Job Object handle — keeps backend alive until frontend exits. /// When this handle is closed (including on crash), Windows kills all assigned processes. #[cfg(target_os = "windows")] @@ -175,6 +179,7 @@ impl Default for AppState { window_instance_registry: Mutex::new(WindowInstanceRegistry::new()), active_drag: Mutex::new(None), cli_login_cancel: Mutex::new(None), + cli_login_stdin_tx: Mutex::new(None), #[cfg(target_os = "windows")] job_handle: Mutex::new(None), } From ccca11135603e901e1ccb9739ce51b1f38710673 Mon Sep 17 00:00:00 2001 From: AgentA Date: Sat, 28 Mar 2026 21:00:52 -0700 Subject: [PATCH 7/7] chore: sync package-lock.json Co-Authored-By: Claude Sonnet 4.6 --- package-lock.json | 1422 ++++++++------------------------------------- 1 file changed, 236 insertions(+), 1186 deletions(-) diff --git a/package-lock.json b/package-lock.json index f8723fbe2..2bdeecf50 100644 --- a/package-lock.json +++ b/package-lock.json @@ -379,7 +379,6 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", @@ -587,7 +586,6 @@ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/parser": "^7.28.6", @@ -915,7 +913,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=20.19.0" }, @@ -964,7 +961,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": ">=20.19.0" } @@ -976,6 +972,7 @@ "cpu": [ "ppc64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -992,6 +989,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1008,6 +1006,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1024,6 +1023,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1040,6 +1040,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1056,6 +1057,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1072,6 +1074,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1088,6 +1091,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1104,6 +1108,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1120,6 +1125,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1136,6 +1142,7 @@ "cpu": [ "ia32" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1152,6 +1159,7 @@ "cpu": [ "loong64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1168,6 +1176,7 @@ "cpu": [ "mips64el" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1184,6 +1193,7 @@ "cpu": [ "ppc64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1200,6 +1210,7 @@ "cpu": [ "riscv64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1216,6 +1227,7 @@ "cpu": [ "s390x" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1232,6 +1244,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1248,6 +1261,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1264,6 +1278,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1280,6 +1295,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1296,6 +1312,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1312,6 +1329,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1328,6 +1346,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1344,6 +1363,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1360,6 +1380,7 @@ "cpu": [ "ia32" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1376,6 +1397,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2637,6 +2659,7 @@ "version": "2.5.6", "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.6.tgz", "integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==", + "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, @@ -2676,6 +2699,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2696,6 +2720,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2716,6 +2741,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2736,6 +2762,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2756,6 +2783,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2776,6 +2804,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2796,6 +2825,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2816,6 +2846,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2836,6 +2867,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2856,6 +2888,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2876,6 +2909,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2896,6 +2930,7 @@ "cpu": [ "ia32" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2916,6 +2951,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3179,6 +3215,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3192,6 +3229,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3205,6 +3243,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3218,6 +3257,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3231,6 +3271,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3244,6 +3285,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3257,6 +3299,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3270,6 +3313,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3283,6 +3327,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3296,6 +3341,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3309,6 +3355,7 @@ "cpu": [ "loong64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3322,6 +3369,7 @@ "cpu": [ "loong64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3335,6 +3383,7 @@ "cpu": [ "ppc64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3348,6 +3397,7 @@ "cpu": [ "ppc64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3361,6 +3411,7 @@ "cpu": [ "riscv64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3374,6 +3425,7 @@ "cpu": [ "riscv64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3387,6 +3439,7 @@ "cpu": [ "s390x" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3400,6 +3453,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3413,6 +3467,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3426,6 +3481,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3439,6 +3495,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3452,6 +3509,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3465,6 +3523,7 @@ "cpu": [ "ia32" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3478,6 +3537,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3491,6 +3551,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -3775,7 +3836,6 @@ "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/core": "^7.21.3", "@svgr/babel-preset": "8.1.0", @@ -4075,8 +4135,7 @@ "version": "0.0.9", "resolved": "https://registry.npmjs.org/@table-nav/core/-/core-0.0.9.tgz", "integrity": "sha512-9LhTDDeGpjgvwKa96EeLejzXqgq9bThvF3ngdcOGjlWtxwrej4rWs4xSX5EVEEUIeA4TU2Vwe7UifrHRLgU4dw==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@table-nav/react": { "version": "0.0.9", @@ -5207,9 +5266,8 @@ "version": "22.19.13", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.13.tgz", "integrity": "sha512-akNQMv0wW5uyRpD2v2IEyRSZiR+BeGuoB6L310EgGObO44HSMNT8z1xzio28V8qOrgYaopIDNA18YgdXd+qTiw==", - "devOptional": true, + "dev": true, "license": "MIT", - "peer": true, "dependencies": { "undici-types": "~6.21.0" } @@ -5242,8 +5300,8 @@ "version": "19.2.14", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", + "dev": true, "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -5252,9 +5310,8 @@ "version": "19.2.3", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", - "devOptional": true, + "dev": true, "license": "MIT", - "peer": true, "peerDependencies": { "@types/react": "^19.2.0" } @@ -5425,7 +5482,6 @@ "integrity": "sha512-klQbnPAAiGYFyI02+znpBRLyjL4/BrBd0nyWkdC0s/6xFLkXYQ8OoRrSkqacS1ddVxf/LDyODIKbQ5TgKAf/Fg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.56.1", "@typescript-eslint/types": "8.56.1", @@ -6027,7 +6083,6 @@ "integrity": "sha512-OmwPKV8c5ecLqo+EkytN7oUeYfNmRI4uOXGIR1ybP7AK5Zz+l9R0dGfoadEuwi1aZXAL0vwuhtq3p0OL3dfqHQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=18.20.0" }, @@ -6082,7 +6137,6 @@ "integrity": "sha512-HdzDrRs+ywAqbXGKqe1i/bLtCv47plz4TvsHFH3j729OooT5VH38ctFn5aLXgECmiAKDkmH/A6kOq2Zh5DIxww==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "chalk": "^5.1.2", "loglevel": "^1.6.0", @@ -6127,8 +6181,7 @@ "resolved": "https://registry.npmjs.org/@wdio/protocols/-/protocols-9.24.0.tgz", "integrity": "sha512-ozQKYddBLT4TRvU9J+fGrhVUtx3iDAe+KNCJcTDMFMxNSdDMR2xFQdNp8HLHypspk58oXTYCvz6ZYjySthhqsw==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@wdio/repl": { "version": "9.16.2", @@ -6352,8 +6405,7 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/@xterm/xterm/-/xterm-5.5.0.tgz", "integrity": "sha512-hqJHYaQb5OptNunnyAnkHyM8aCjZ1MEIDTQu1iIbbTD/xops91NB5yq1ZK/dC2JDbVWtF23zUtl9JE2NqwT87A==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@zip.js/zip.js": { "version": "2.8.21", @@ -6392,7 +6444,6 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -6985,30 +7036,6 @@ "require-from-string": "^2.0.2" } }, - "node_modules/big-integer": { - "version": "1.6.52", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", - "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", - "dev": true, - "license": "Unlicense", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/binary": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", - "integrity": "sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffers": "~0.1.1", - "chainsaw": "~0.1.0" - }, - "engines": { - "node": "*" - } - }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -7041,13 +7068,6 @@ "integrity": "sha512-PJvH288AWQhKs2v9zyfYdPzlPqf5bXbGMmhmUIY9x4dAUGIWgomO771oBQNwJnMQSnUIXhKu6sgzpBRXTlvb8Q==", "license": "MIT" }, - "node_modules/bluebird": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", - "integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==", - "dev": true, - "license": "MIT" - }, "node_modules/boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", @@ -7105,7 +7125,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -7155,25 +7174,6 @@ "node": ">=8.0.0" } }, - "node_modules/buffer-indexof-polyfill": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", - "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/buffers": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", - "integrity": "sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==", - "dev": true, - "engines": { - "node": ">=0.2.0" - } - }, "node_modules/cac": { "version": "6.7.14", "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", @@ -7254,19 +7254,6 @@ "node": ">=18" } }, - "node_modules/chainsaw": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", - "integrity": "sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==", - "dev": true, - "license": "MIT/X11", - "dependencies": { - "traverse": ">=0.3.0 <0.4" - }, - "engines": { - "node": "*" - } - }, "node_modules/chalk": { "version": "5.6.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", @@ -7409,7 +7396,6 @@ "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-11.1.2.tgz", "integrity": "sha512-opLQzEVriiH1uUQ4Kctsd49bRoFDXGGSC4GUqj7pGyxM3RehRhvTlZJc1FL/Flew2p5uwxa1tUDWKzI4wNM8pg==", "license": "Apache-2.0", - "peer": true, "dependencies": { "@chevrotain/cst-dts-gen": "11.1.2", "@chevrotain/gast": "11.1.2", @@ -7435,7 +7421,7 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "readdirp": "^4.0.1" @@ -7447,39 +7433,6 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/chrome-launcher": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-1.2.1.tgz", - "integrity": "sha512-qmFR5PLMzHyuNJHwOloHPAHhbaNglkfeV/xDtt5b7xiFFyU1I+AZZX0PYseMuhenJSSirgxELYIbswcoc+5H4A==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@types/node": "*", - "escape-string-regexp": "^4.0.0", - "is-wsl": "^2.2.0", - "lighthouse-logger": "^2.0.1" - }, - "bin": { - "print-chrome-path": "bin/print-chrome-path.cjs" - }, - "engines": { - "node": ">=12.13.0" - } - }, - "node_modules/chromium-bidi": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-0.5.8.tgz", - "integrity": "sha512-blqh+1cEQbHBKmok3rVJkBlBxt9beKBgOsxbFgs7UJcoVbbeZ+K7+6liAsjgpc8l1Xd55cQUy14fXZdGSb4zIw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "mitt": "3.0.1", - "urlpattern-polyfill": "10.0.0" - }, - "peerDependencies": { - "devtools-protocol": "*" - } - }, "node_modules/ci-info": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz", @@ -7971,16 +7924,6 @@ "dev": true, "license": "MIT" }, - "node_modules/cross-fetch": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz", - "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==", - "dev": true, - "license": "MIT", - "dependencies": { - "node-fetch": "^2.6.12" - } - }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -8063,7 +8006,6 @@ "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.33.1.tgz", "integrity": "sha512-iJc4TwyANnOGR1OmWhsS9ayRS3s+XQ185FmuHObThD+5AeJCakAAbWv8KimMTt08xCCLNgneQwFp+JRJOr9qGQ==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10" } @@ -8473,7 +8415,6 @@ "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", "license": "ISC", - "peer": true, "engines": { "node": ">=12" } @@ -8756,7 +8697,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", - "devOptional": true, + "dev": true, "license": "Apache-2.0", "engines": { "node": ">=8" @@ -8775,476 +8716,125 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/devtools": { - "version": "8.42.0", - "resolved": "https://registry.npmjs.org/devtools/-/devtools-8.42.0.tgz", - "integrity": "sha512-Y9LRUJlGI0wjXLbeU6TEHufF9HnG2H22+/EABD0KtHlJt5AIRQnTGi8uLAJsE1aeQMF1YXd8l7ExaxBkfEBq8w==", + "node_modules/diff": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.3.tgz", + "integrity": "sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ==", "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "^22.2.0", - "@wdio/config": "8.41.0", - "@wdio/logger": "8.38.0", - "@wdio/protocols": "8.40.3", - "@wdio/types": "8.41.0", - "@wdio/utils": "8.41.0", - "chrome-launcher": "^1.0.0", - "edge-paths": "^3.0.5", - "import-meta-resolve": "^4.0.0", - "puppeteer-core": "^21.11.0", - "query-selector-shadow-dom": "^1.0.0", - "ua-parser-js": "^1.0.37", - "uuid": "^10.0.0", - "which": "^4.0.0" - }, + "license": "BSD-3-Clause", "engines": { - "node": "^16.13 || >=18" + "node": ">=0.3.1" } }, - "node_modules/devtools-protocol": { - "version": "0.0.1232444", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1232444.tgz", - "integrity": "sha512-pM27vqEfxSxRkTMnF+XCmxSEb6duO5R+t8A9DEEJgy4Wz2RVanje2mmj99B6A3zv2r/qGfYlOvYznUhuokizmg==", - "dev": true, - "license": "BSD-3-Clause", - "peer": true + "node_modules/dnd-core": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/dnd-core/-/dnd-core-16.0.1.tgz", + "integrity": "sha512-HK294sl7tbw6F6IeuK16YSBUoorvHpY8RHO+9yFfaJyCDVb6n7PRcezrOEOa2SBCqiYpemh5Jx20ZcjKdFAVng==", + "license": "MIT", + "dependencies": { + "@react-dnd/asap": "^5.0.1", + "@react-dnd/invariant": "^4.0.1", + "redux": "^4.2.0" + } }, - "node_modules/devtools/node_modules/@puppeteer/browsers": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-1.9.1.tgz", - "integrity": "sha512-PuvK6xZzGhKPvlx3fpfdM2kYY3P/hB1URtK8wA7XUJ6prn6pp22zvJHu48th0SGcHL9SutbPHrFuQgfXTFobWA==", + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, "license": "Apache-2.0", "dependencies": { - "debug": "4.3.4", - "extract-zip": "2.0.1", - "progress": "2.0.3", - "proxy-agent": "6.3.1", - "tar-fs": "3.0.4", - "unbzip2-stream": "1.4.3", - "yargs": "17.7.2" - }, - "bin": { - "browsers": "lib/cjs/main-cli.js" + "esutils": "^2.0.2" }, "engines": { - "node": ">=16.3.0" + "node": ">=6.0.0" } }, - "node_modules/devtools/node_modules/@wdio/config": { - "version": "8.41.0", - "resolved": "https://registry.npmjs.org/@wdio/config/-/config-8.41.0.tgz", - "integrity": "sha512-/6Z3sfSyhX5oVde0l01fyHimbqRYIVUDBnhDG2EMSCoC2lsaJX3Bm3IYpYHYHHFsgoDCi3B3Gv++t9dn2eSZZw==", + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", "dev": true, "license": "MIT", "dependencies": { - "@wdio/logger": "8.38.0", - "@wdio/types": "8.41.0", - "@wdio/utils": "8.41.0", - "decamelize": "^6.0.0", - "deepmerge-ts": "^5.0.0", - "glob": "^10.2.2", - "import-meta-resolve": "^4.0.0" + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" }, - "engines": { - "node": "^16.13 || >=18" + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, - "node_modules/devtools/node_modules/@wdio/logger": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/@wdio/logger/-/logger-8.38.0.tgz", - "integrity": "sha512-kcHL86RmNbcQP+Gq/vQUGlArfU6IIcbbnNp32rRIraitomZow+iEoc519rdQmSVusDozMS5DZthkgDdxK+vz6Q==", + "node_modules/dom-serializer/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^5.1.2", - "loglevel": "^1.6.0", - "loglevel-plugin-prefix": "^0.8.4", - "strip-ansi": "^7.1.0" - }, + "license": "BSD-2-Clause", "engines": { - "node": "^16.13 || >=18" + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/devtools/node_modules/@wdio/protocols": { - "version": "8.40.3", - "resolved": "https://registry.npmjs.org/@wdio/protocols/-/protocols-8.40.3.tgz", - "integrity": "sha512-wK7+eyrB3TAei8RwbdkcyoNk2dPu+mduMBOdPJjp8jf/mavd15nIUXLID1zA+w5m1Qt1DsT1NbvaeO9+aJQ33A==", + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", "dev": true, - "license": "MIT" + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" }, - "node_modules/devtools/node_modules/@wdio/types": { - "version": "8.41.0", - "resolved": "https://registry.npmjs.org/@wdio/types/-/types-8.41.0.tgz", - "integrity": "sha512-t4NaNTvJZci3Xv/yUZPH4eTL0hxrVTf5wdwNnYIBrzMnlRDbNefjQ0P7FM7ZjQCLaH92AEH6t/XanUId7Webug==", + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "@types/node": "^22.2.0" + "domelementtype": "^2.3.0" }, "engines": { - "node": "^16.13 || >=18" + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/dompurify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.1.tgz", + "integrity": "sha512-qkdCKzLNtrgPFP1Vo+98FRzJnBRGe4ffyCea9IwHB1fyxPOeNTHpLKYGd4Uk9xvNoH0ZoOjwZxNptyMwqrId1Q==", + "license": "(MPL-2.0 OR Apache-2.0)", + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" } }, - "node_modules/devtools/node_modules/@wdio/utils": { - "version": "8.41.0", - "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-8.41.0.tgz", - "integrity": "sha512-0TcTjBiax1VxtJQ/iQA0ZyYOSHjjX2ARVmEI0AMo9+AuIq+xBfnY561+v8k9GqOMPKsiH/HrK3xwjx8xCVS03g==", + "node_modules/domutils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", + "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "@puppeteer/browsers": "^1.6.0", - "@wdio/logger": "8.38.0", - "@wdio/types": "8.41.0", - "decamelize": "^6.0.0", - "deepmerge-ts": "^5.1.0", - "edgedriver": "^5.5.0", - "geckodriver": "~4.2.0", - "get-port": "^7.0.0", - "import-meta-resolve": "^4.0.0", - "locate-app": "^2.1.0", - "safaridriver": "^0.1.0", - "split2": "^4.2.0", - "wait-port": "^1.0.4" + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" }, - "engines": { - "node": "^16.13 || >=18" + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" } }, - "node_modules/devtools/node_modules/data-uri-to-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 12" - } - }, - "node_modules/devtools/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/devtools/node_modules/deepmerge-ts": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/deepmerge-ts/-/deepmerge-ts-5.1.0.tgz", - "integrity": "sha512-eS8dRJOckyo9maw9Tu5O5RUi/4inFLrnoLkBe3cPfDMx3WZioXtmOew4TXQaxq7Rhl4xjDtR7c6x8nNTxOvbFw==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/devtools/node_modules/edgedriver": { - "version": "5.6.1", - "resolved": "https://registry.npmjs.org/edgedriver/-/edgedriver-5.6.1.tgz", - "integrity": "sha512-3Ve9cd5ziLByUdigw6zovVeWJjVs8QHVmqOB0sJ0WNeVPcwf4p18GnxMmVvlFmYRloUwf5suNuorea4QzwBIOA==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "@wdio/logger": "^8.38.0", - "@zip.js/zip.js": "^2.7.48", - "decamelize": "^6.0.0", - "edge-paths": "^3.0.5", - "fast-xml-parser": "^4.4.1", - "node-fetch": "^3.3.2", - "which": "^4.0.0" - }, - "bin": { - "edgedriver": "bin/edgedriver.js" - } - }, - "node_modules/devtools/node_modules/fast-xml-parser": { - "version": "4.5.5", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.5.tgz", - "integrity": "sha512-cK9c5I/DwIOI7/Q7AlGN3DuTdwN61gwSfL8rvuVPK+0mcCNHHGxRrpiFtaZZRfRMJL3Gl8B2AFlBG6qXf03w9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - } - ], - "license": "MIT", - "dependencies": { - "strnum": "^1.0.5" - }, - "bin": { - "fxparser": "src/cli/cli.js" - } - }, - "node_modules/devtools/node_modules/geckodriver": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/geckodriver/-/geckodriver-4.2.1.tgz", - "integrity": "sha512-4m/CRk0OI8MaANRuFIahvOxYTSjlNAO2p9JmE14zxueknq6cdtB5M9UGRQ8R9aMV0bLGNVHHDnDXmoXdOwJfWg==", - "dev": true, - "hasInstallScript": true, - "license": "MPL-2.0", - "dependencies": { - "@wdio/logger": "^8.11.0", - "decamelize": "^6.0.0", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.1", - "node-fetch": "^3.3.1", - "tar-fs": "^3.0.4", - "unzipper": "^0.10.14", - "which": "^4.0.0" - }, - "bin": { - "geckodriver": "bin/geckodriver.js" - }, - "engines": { - "node": "^16.13 || >=18 || >=20" - } - }, - "node_modules/devtools/node_modules/isexe": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.5.tgz", - "integrity": "sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } - }, - "node_modules/devtools/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/devtools/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true, - "license": "MIT" - }, - "node_modules/devtools/node_modules/node-fetch": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", - "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", - "dev": true, - "license": "MIT", - "dependencies": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/node-fetch" - } - }, - "node_modules/devtools/node_modules/proxy-agent": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.3.1.tgz", - "integrity": "sha512-Rb5RVBy1iyqOtNl15Cw/llpeLH8bsb37gM1FUfKQ+Wck6xHlbAhWGUFiTRHtkjqGTA5pSHz6+0hrPW/oECihPQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.0.2", - "debug": "^4.3.4", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.2", - "lru-cache": "^7.14.1", - "pac-proxy-agent": "^7.0.1", - "proxy-from-env": "^1.1.0", - "socks-proxy-agent": "^8.0.2" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/devtools/node_modules/safaridriver": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/safaridriver/-/safaridriver-0.1.2.tgz", - "integrity": "sha512-4R309+gWflJktzPXBQCobbWEHlzC4aK3a+Ov3tz2Ib2aBxiwd11phkdIBH1l0EO22x24CJMUQkpKFumRriCSRg==", - "dev": true, - "license": "MIT" - }, - "node_modules/devtools/node_modules/strnum": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz", - "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - } - ], - "license": "MIT" - }, - "node_modules/devtools/node_modules/tar-fs": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.4.tgz", - "integrity": "sha512-5AFQU8b9qLfZCX9zp2duONhPmZv0hGYiBPJsyUdqMjzq/mqVpy/rEUSeHk1+YitmxugaptgBh5oDGU3VsAJq4w==", - "dev": true, - "license": "MIT", - "dependencies": { - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^3.1.5" - } - }, - "node_modules/devtools/node_modules/which": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz", - "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^3.1.1" - }, - "bin": { - "node-which": "bin/which.js" - }, - "engines": { - "node": "^16.13.0 || >=18.0.0" - } - }, - "node_modules/diff": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.3.tgz", - "integrity": "sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/dnd-core": { - "version": "16.0.1", - "resolved": "https://registry.npmjs.org/dnd-core/-/dnd-core-16.0.1.tgz", - "integrity": "sha512-HK294sl7tbw6F6IeuK16YSBUoorvHpY8RHO+9yFfaJyCDVb6n7PRcezrOEOa2SBCqiYpemh5Jx20ZcjKdFAVng==", - "license": "MIT", - "dependencies": { - "@react-dnd/asap": "^5.0.1", - "@react-dnd/invariant": "^4.0.1", - "redux": "^4.2.0" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "dev": true, - "license": "MIT", - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/dom-serializer/node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "BSD-2-Clause" - }, - "node_modules/domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "domelementtype": "^2.3.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/dompurify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.1.tgz", - "integrity": "sha512-qkdCKzLNtrgPFP1Vo+98FRzJnBRGe4ffyCea9IwHB1fyxPOeNTHpLKYGd4Uk9xvNoH0ZoOjwZxNptyMwqrId1Q==", - "license": "(MPL-2.0 OR Apache-2.0)", - "optionalDependencies": { - "@types/trusted-types": "^2.0.7" - } - }, - "node_modules/domutils": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", - "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/dot-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", - "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", "dev": true, "license": "MIT", "dependencies": { @@ -9265,49 +8855,6 @@ "url": "https://dotenvx.com" } }, - "node_modules/duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "readable-stream": "^2.0.2" - } - }, - "node_modules/duplexer2/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/duplexer2/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "license": "MIT" - }, - "node_modules/duplexer2/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, "node_modules/duplexify": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.3.tgz", @@ -9520,7 +9067,7 @@ "version": "0.27.3", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz", "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==", - "devOptional": true, + "dev": true, "hasInstallScript": true, "license": "MIT", "bin": { @@ -9616,7 +9163,6 @@ "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -9967,7 +9513,6 @@ "integrity": "sha512-Bkoqs+39fHwjos51qab7ZWmvZrYNBbzgSAIykH2CrgLOLhHJXzC30DP9lZq2MsmaUsbBnN5c5m8VqAhOHTrCRw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@vitest/snapshot": "^4.0.16", "deep-eql": "^5.0.2", @@ -10309,6 +9854,7 @@ "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, "license": "MIT", "engines": { "node": ">=12.0.0" @@ -10322,30 +9868,6 @@ } } }, - "node_modules/fetch-blob": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", - "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "paypal", - "url": "https://paypal.me/jimmywarting" - } - ], - "license": "MIT", - "dependencies": { - "node-domexception": "^1.0.0", - "web-streams-polyfill": "^3.0.3" - }, - "engines": { - "node": "^12.20 || >= 14.13" - } - }, "node_modules/figures": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz", @@ -10502,19 +10024,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/formdata-polyfill": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", - "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "fetch-blob": "^3.1.2" - }, - "engines": { - "node": ">=12.20.0" - } - }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -10526,6 +10035,7 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, @@ -10536,59 +10046,6 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/fstream": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", - "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", - "deprecated": "This package is no longer supported.", - "dev": true, - "license": "ISC", - "dependencies": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - }, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/fstream/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/fstream/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -10686,7 +10143,7 @@ "version": "4.13.6", "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.6.tgz", "integrity": "sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "resolve-pkg-maps": "^1.0.0" @@ -11455,7 +10912,7 @@ "version": "5.1.4", "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.4.tgz", "integrity": "sha512-p6u1bG3YSnINT5RQmx/yRZBpenIl30kVxkTLDyHLIMk0gict704Q9n+thfDI7lTRm9vXdDYutVzXhzcThxTnXA==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/import-fresh": { @@ -11656,27 +11113,11 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true, - "license": "MIT", - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -11696,7 +11137,7 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" @@ -11799,19 +11240,6 @@ "url": "https://github.com/sponsors/mesqueeb" } }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -12169,7 +11597,7 @@ "version": "2.6.1", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", - "devOptional": true, + "dev": true, "license": "MIT", "bin": { "jiti": "lib/jiti-cli.mjs" @@ -12593,22 +12021,11 @@ ], "license": "MIT" }, - "node_modules/lighthouse-logger": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-2.0.2.tgz", - "integrity": "sha512-vWl2+u5jgOQuZR55Z1WM0XDdrJT6mzMP8zHUct7xTlWhuQs+eV0g+QL0RQdFjT54zVmbhLCP8vIVpy1wGn/gCg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "debug": "^4.4.1", - "marky": "^1.2.2" - } - }, "node_modules/lightningcss": { "version": "1.31.1", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.31.1.tgz", "integrity": "sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ==", - "devOptional": true, + "dev": true, "license": "MPL-2.0", "dependencies": { "detect-libc": "^2.0.3" @@ -12641,6 +12058,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -12661,6 +12079,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -12681,6 +12100,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -12701,6 +12121,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -12721,6 +12142,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -12741,6 +12163,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -12761,6 +12184,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -12781,6 +12205,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -12801,6 +12226,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -12821,6 +12247,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -12841,6 +12268,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -12864,13 +12292,6 @@ "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, - "node_modules/listenercount": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", - "integrity": "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==", - "dev": true, - "license": "ISC" - }, "node_modules/lit": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/lit/-/lit-3.3.2.tgz", @@ -13234,13 +12655,6 @@ "node": ">= 20" } }, - "node_modules/marky": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/marky/-/marky-1.3.0.tgz", - "integrity": "sha512-ocnPZQLNpvbedwTy9kNrQEsknEfgvcLMvOtz3sFeWApDq1MXH1TqkCIx58xlpESsfwQOnuBO9beyQuNGzVvuhQ==", - "dev": true, - "license": "Apache-2.0" - }, "node_modules/mdast-util-find-and-replace": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz", @@ -13619,7 +13033,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "@types/debug": "^4.0.0", "debug": "^4.0.0", @@ -14256,8 +13669,7 @@ "url": "https://opencollective.com/unified" } ], - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/micromatch": { "version": "4.0.8", @@ -14312,16 +13724,6 @@ "node": "*" } }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/minipass": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", @@ -14339,26 +13741,6 @@ "dev": true, "license": "MIT" }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/mkdirp-classic": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "dev": true, - "license": "MIT" - }, "node_modules/mlly": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.0.tgz", @@ -14677,6 +14059,7 @@ "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, "funding": [ { "type": "github", @@ -14719,93 +14102,27 @@ "tslib": "^2.0.3" } }, - "node_modules/node-abi": { - "version": "4.26.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-4.26.0.tgz", - "integrity": "sha512-8QwIZqikRvDIkXS2S93LjzhsSPJuIbfaMETWH+Bx8oOT9Sa9UsUtBFQlc3gBNd1+QINjaTloitXr1W3dQLi9Iw==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.6.3" - }, - "engines": { - "node": ">=22.12.0" - } - }, - "node_modules/node-addon-api": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", - "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", - "license": "MIT", - "optional": true - }, - "node_modules/node-domexception": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", - "deprecated": "Use your platform's native DOMException instead", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "github", - "url": "https://paypal.me/jimmywarting" - } - ], - "license": "MIT", - "engines": { - "node": ">=10.5.0" - } - }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-fetch/node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true, - "license": "MIT" - }, - "node_modules/node-fetch/node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/node-fetch/node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "node_modules/node-abi": { + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-4.26.0.tgz", + "integrity": "sha512-8QwIZqikRvDIkXS2S93LjzhsSPJuIbfaMETWH+Bx8oOT9Sa9UsUtBFQlc3gBNd1+QINjaTloitXr1W3dQLi9Iw==", "dev": true, "license": "MIT", "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" + "semver": "^7.6.3" + }, + "engines": { + "node": ">=22.12.0" } }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "dev": true, + "license": "MIT", + "optional": true + }, "node_modules/node-releases": { "version": "2.0.27", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", @@ -14961,8 +14278,7 @@ "version": "2.14.0", "resolved": "https://registry.npmjs.org/overlayscrollbars/-/overlayscrollbars-2.14.0.tgz", "integrity": "sha512-RjV0pqc79kYhQLC3vTcLRb5GLpI1n6qh0Oua3g+bGH4EgNOJHVBGP7u0zZtxoAa0dkHlAqTTSYRb9MMmxNLjig==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/overlayscrollbars-react": { "version": "0.5.6", @@ -15327,6 +14643,7 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -15467,6 +14784,7 @@ "version": "8.5.6", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "dev": true, "funding": [ { "type": "opencollective", @@ -15518,7 +14836,6 @@ "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", "dev": true, "license": "MIT", - "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -15724,135 +15041,6 @@ "node": ">=6" } }, - "node_modules/puppeteer-core": { - "version": "21.11.0", - "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-21.11.0.tgz", - "integrity": "sha512-ArbnyA3U5SGHokEvkfWjW+O8hOxV1RSJxOgriX/3A4xZRqixt9ZFHD0yPgZQF05Qj0oAqi8H/7stDorjoHY90Q==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@puppeteer/browsers": "1.9.1", - "chromium-bidi": "0.5.8", - "cross-fetch": "4.0.0", - "debug": "4.3.4", - "devtools-protocol": "0.0.1232444", - "ws": "8.16.0" - }, - "engines": { - "node": ">=16.13.2" - } - }, - "node_modules/puppeteer-core/node_modules/@puppeteer/browsers": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-1.9.1.tgz", - "integrity": "sha512-PuvK6xZzGhKPvlx3fpfdM2kYY3P/hB1URtK8wA7XUJ6prn6pp22zvJHu48th0SGcHL9SutbPHrFuQgfXTFobWA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "debug": "4.3.4", - "extract-zip": "2.0.1", - "progress": "2.0.3", - "proxy-agent": "6.3.1", - "tar-fs": "3.0.4", - "unbzip2-stream": "1.4.3", - "yargs": "17.7.2" - }, - "bin": { - "browsers": "lib/cjs/main-cli.js" - }, - "engines": { - "node": ">=16.3.0" - } - }, - "node_modules/puppeteer-core/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/puppeteer-core/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/puppeteer-core/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true, - "license": "MIT" - }, - "node_modules/puppeteer-core/node_modules/proxy-agent": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.3.1.tgz", - "integrity": "sha512-Rb5RVBy1iyqOtNl15Cw/llpeLH8bsb37gM1FUfKQ+Wck6xHlbAhWGUFiTRHtkjqGTA5pSHz6+0hrPW/oECihPQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.0.2", - "debug": "^4.3.4", - "http-proxy-agent": "^7.0.0", - "https-proxy-agent": "^7.0.2", - "lru-cache": "^7.14.1", - "pac-proxy-agent": "^7.0.1", - "proxy-from-env": "^1.1.0", - "socks-proxy-agent": "^8.0.2" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/puppeteer-core/node_modules/tar-fs": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.4.tgz", - "integrity": "sha512-5AFQU8b9qLfZCX9zp2duONhPmZv0hGYiBPJsyUdqMjzq/mqVpy/rEUSeHk1+YitmxugaptgBh5oDGU3VsAJq4w==", - "dev": true, - "license": "MIT", - "dependencies": { - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^3.1.5" - } - }, - "node_modules/puppeteer-core/node_modules/ws": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", - "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/query-selector-shadow-dom": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/query-selector-shadow-dom/-/query-selector-shadow-dom-1.0.1.tgz", @@ -15909,7 +15097,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -15958,7 +15145,6 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz", "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", "license": "MIT", - "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -16249,7 +15435,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">= 14.18.0" @@ -16621,7 +15807,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", - "devOptional": true, + "dev": true, "license": "MIT", "funding": { "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" @@ -16728,8 +15914,8 @@ "version": "4.59.0", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz", "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", + "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/estree": "1.0.8" }, @@ -16901,9 +16087,8 @@ "version": "1.97.2", "resolved": "https://registry.npmjs.org/sass/-/sass-1.97.2.tgz", "integrity": "sha512-y5LWb0IlbO4e97Zr7c3mlpabcbBtS+ieiZ9iwDooShpFKWXf62zz5pEPdwrLYm+Bxn1fnbwFGzHuCLSA9tBmrw==", - "devOptional": true, + "dev": true, "license": "MIT", - "peer": true, "dependencies": { "chokidar": "^4.0.0", "immutable": "^5.0.2", @@ -16998,7 +16183,6 @@ "resolved": "https://registry.npmjs.org/seroval/-/seroval-1.5.1.tgz", "integrity": "sha512-OwrZRZAfhHww0WEnKHDY8OM0U/Qs8OTfIDWhUD4BLpNJUfXK4cGmjiagGze086m+mhI+V2nD0gfbHEnJjb9STA==", "license": "MIT", - "peer": true, "engines": { "node": ">=10" } @@ -17189,7 +16373,6 @@ "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.9.11.tgz", "integrity": "sha512-WEJtcc5mkh/BnHA6Yrg4whlF8g6QwpmXXRg4P2ztPmcKeHHlH4+djYecBLhSpecZY2RRECXYUwIc/C2r3yzQ4Q==", "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.1.0", "seroval": "~1.5.0", @@ -17724,8 +16907,7 @@ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.2.1.tgz", "integrity": "sha512-/tBrSQ36vCleJkAOsy9kbNTgaxvGbyOamC30PRePTQe/o1MFwEKHQk4Cn7BNGaPtjp+PuUrByJehM1hgxfq4sw==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/tailwindcss-animate": { "version": "1.0.7", @@ -17894,13 +17076,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true, - "license": "MIT" - }, "node_modules/tinybench": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", @@ -17927,6 +17102,7 @@ "version": "0.2.15", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, "license": "MIT", "dependencies": { "fdir": "^6.5.0", @@ -18048,16 +17224,6 @@ "node": ">=20" } }, - "node_modules/traverse": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", - "integrity": "sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==", - "dev": true, - "license": "MIT/X11", - "engines": { - "node": "*" - } - }, "node_modules/tree-kill": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", @@ -18195,7 +17361,7 @@ "version": "4.21.0", "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "esbuild": "~0.27.0", @@ -18215,6 +17381,7 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, @@ -18257,7 +17424,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -18290,75 +17456,12 @@ "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/ua-parser-js": { - "version": "1.0.41", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.41.tgz", - "integrity": "sha512-LbBDqdIC5s8iROCUjMbW1f5dJQTEFB1+KO9ogbvlb3nm9n4YHa5p4KTvFPWvh2Hs8gZMBuiB1/8+pdfe/tDPug==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/ua-parser-js" - }, - { - "type": "paypal", - "url": "https://paypal.me/faisalman" - }, - { - "type": "github", - "url": "https://github.com/sponsors/faisalman" - } - ], - "license": "MIT", - "bin": { - "ua-parser-js": "script/cli.js" - }, - "engines": { - "node": "*" - } - }, "node_modules/ufo": { "version": "1.6.3", "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.3.tgz", "integrity": "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==", "license": "MIT" }, - "node_modules/unbzip2-stream": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", - "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer": "^5.2.1", - "through": "^2.3.8" - } - }, - "node_modules/unbzip2-stream/node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, "node_modules/undici": { "version": "6.23.0", "resolved": "https://registry.npmjs.org/undici/-/undici-6.23.0.tgz", @@ -18373,7 +17476,7 @@ "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/unicorn-magic": { @@ -18394,7 +17497,6 @@ "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", "license": "MIT", - "peer": true, "dependencies": { "@types/unist": "^3.0.0", "bail": "^2.0.0", @@ -18505,58 +17607,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/unzipper": { - "version": "0.10.14", - "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.14.tgz", - "integrity": "sha512-ti4wZj+0bQTiX2KmKWuwj7lhV+2n//uXEotUmGuQqrbVZSEGFMbI68+c6JCQ8aAmUWYvtHEz2A8K6wXvueR/6g==", - "dev": true, - "license": "MIT", - "dependencies": { - "big-integer": "^1.6.17", - "binary": "~0.3.0", - "bluebird": "~3.4.1", - "buffer-indexof-polyfill": "~1.0.0", - "duplexer2": "~0.1.4", - "fstream": "^1.0.12", - "graceful-fs": "^4.2.2", - "listenercount": "~1.0.1", - "readable-stream": "~2.3.6", - "setimmediate": "~1.0.4" - } - }, - "node_modules/unzipper/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/unzipper/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "license": "MIT" - }, - "node_modules/unzipper/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, "node_modules/update-browserslist-db": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", @@ -18639,20 +17689,6 @@ "dev": true, "license": "MIT" }, - "node_modules/uuid": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", - "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", - "dev": true, - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", @@ -18717,8 +17753,8 @@ "version": "6.4.1", "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", + "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", @@ -18901,6 +17937,7 @@ "cpu": [ "ppc64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -18917,6 +17954,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -18933,6 +17971,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -18949,6 +17988,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -18965,6 +18005,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -18981,6 +18022,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -18997,6 +18039,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -19013,6 +18056,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -19029,6 +18073,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -19045,6 +18090,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -19061,6 +18107,7 @@ "cpu": [ "ia32" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -19077,6 +18124,7 @@ "cpu": [ "loong64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -19093,6 +18141,7 @@ "cpu": [ "mips64el" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -19109,6 +18158,7 @@ "cpu": [ "ppc64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -19125,6 +18175,7 @@ "cpu": [ "riscv64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -19141,6 +18192,7 @@ "cpu": [ "s390x" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -19157,6 +18209,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -19173,6 +18226,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -19189,6 +18243,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -19205,6 +18260,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -19221,6 +18277,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -19237,6 +18294,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -19253,6 +18311,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -19269,6 +18328,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -19285,6 +18345,7 @@ "cpu": [ "ia32" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -19301,6 +18362,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -19314,6 +18376,7 @@ "version": "0.25.12", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "dev": true, "hasInstallScript": true, "license": "MIT", "bin": { @@ -19355,6 +18418,7 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, @@ -19390,7 +18454,6 @@ "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/chai": "^5.2.2", "@vitest/expect": "3.2.4", @@ -19651,16 +18714,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/web-streams-polyfill": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", - "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, "node_modules/webdriver": { "version": "9.24.0", "resolved": "https://registry.npmjs.org/webdriver/-/webdriver-9.24.0.tgz", @@ -19700,7 +18753,6 @@ "integrity": "sha512-LTJt6Z/iDM0ne/4ytd3BykoPv9CuJ+CAILOzlwFeMGn4Mj02i4Bk2Rg9o/jeJ89f52hnv4OPmNjD0e8nzWAy5g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/node": "^20.11.30", "@types/sinonjs__fake-timers": "^8.1.5", @@ -20051,7 +19103,6 @@ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz", "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", "license": "ISC", - "peer": true, "bin": { "yaml": "bin.mjs" }, @@ -20282,7 +19333,6 @@ "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" }