diff --git a/src-tauri/src/clients.rs b/src-tauri/src/clients.rs index 4b53d15a..cb133203 100644 --- a/src-tauri/src/clients.rs +++ b/src-tauri/src/clients.rs @@ -1032,14 +1032,6 @@ fn claude_desktop_path() -> Option { Some(real) } -fn cursor_path() -> Option { - client_config_path("cursor") -} - -fn droid_path() -> Option { - client_config_path("droid") -} - fn crush_override_path(config_dir: Option) -> Option { config_dir .filter(|p| !p.is_empty()) @@ -1085,31 +1077,6 @@ fn crush_path() -> Option { Some(current) } -fn anythingllm_path() -> Option { - client_config_path("anythingllm") -} - -fn boltai_path() -> Option { - client_config_path("boltai") -} - -/// Pi coding agent reads its Pi-owned global MCP config from ~/.pi/agent/mcp.json -/// (standard `mcpServers` shape; pi's optional `lifecycle`/`idleTimeout` keys are -/// left unset so it uses its defaults). Home-anchored, identical on every OS. -fn pi_path() -> Option { - client_config_path("pi") -} - -/// Oh My Pi (omp) is a fork of Pi with its own config directory (~/.omp). -/// Same `mcpServers` JSON format as Pi; home-anchored, identical on every OS. -fn omp_path() -> Option { - client_config_path("omp") -} - -fn vscode_path() -> Option { - client_config_path("vscode") -} - fn amp_path() -> Option { std::env::var_os("AMP_SETTINGS_FILE") .filter(|path| !path.is_empty()) @@ -1117,14 +1084,6 @@ fn amp_path() -> Option { .or_else(|| client_config_path("amp")) } -fn windsurf_path() -> Option { - client_config_path("windsurf") -} - -fn devin_cli_path() -> Option { - client_config_path("devin-cli") -} - /// Codex reads `$CODEX_HOME/config.toml` when `CODEX_HOME` is set, otherwise /// `~/.codex/config.toml`. The env *is* the Codex home directory, not its /// parent. Empty or relative values fall back: resolving them would depend @@ -1175,10 +1134,6 @@ fn grok_path() -> Option { client_config_path("grok") } -fn claude_code_path() -> Option { - client_config_path("claude-code") -} - /// Gemini CLI treats `GEMINI_CLI_HOME` as a replacement *home directory*, /// then still appends `.gemini/`. Settings live at /// `$GEMINI_CLI_HOME/.gemini/settings.json`. Empty or relative values fall @@ -1227,12 +1182,6 @@ fn qwen_code_path() -> Option { client_config_path("qwen-code") } -/// Junie stores user-scoped MCP servers at ~/.junie/mcp/mcp.json on every -/// supported platform. Project-scoped configs are intentionally left untouched. -fn junie_path() -> Option { - client_config_path("junie") -} - /// Google Antigravity reads MCP servers from `mcp_config.json` under `~/.gemini`. /// The subdir has shifted across versions (`config`, `antigravity-ide`, /// `antigravity`) and installers leave empty decoy files in the unused ones, so @@ -1250,20 +1199,10 @@ fn antigravity_path() -> Option { client_config_path("antigravity") } -fn cline_path() -> Option { - client_config_path("cline") -} - fn roo_code_path() -> Option { client_config_path("roo-code") } -/// OpenCode stores its global config at the literal -/// `~/.config/opencode/opencode.json` or `opencode.jsonc` on every supported OS. -fn opencode_path() -> Option { - client_config_path("opencode") -} - fn resolve_opencode_config_path(json_path: PathBuf) -> Result { let jsonc_path = json_path.with_extension("jsonc"); match (json_path.exists(), jsonc_path.exists()) { @@ -1286,31 +1225,6 @@ fn resolved_definition_path(def: &ClientDef) -> Result { } } -/// Kilo Code stores its global JSONC config at the literal -/// `~/.config/kilo/kilo.jsonc` on every supported OS. -fn kilo_code_path() -> Option { - client_config_path("kilo-code") -} - -/// Warp reads file-based MCP servers from `~/.warp/.mcp.json` (keyed under -/// `mcpServers`), alongside its in-app UI. The file is home-anchored on every OS. -fn warp_path() -> Option { - client_config_path("warp") -} - -/// Amazon Q Developer CLI global MCP config: `~/.aws/amazonq/mcp.json` -/// (`mcpServers`). A per-workspace `.amazonq/mcp.json` also exists; we manage the -/// global one so the gateway is available everywhere. -fn amazon_q_path() -> Option { - client_config_path("amazon-q") -} - -/// Kiro user-level MCP config: `~/.kiro/settings/mcp.json` (`mcpServers`). A -/// per-workspace `.kiro/settings/mcp.json` also exists and takes precedence. -fn kiro_path() -> Option { - client_config_path("kiro") -} - /// Kimi Code (Moonshot AI) user-level MCP config: `~/.kimi-code/mcp.json` /// (`mcpServers`). Kimi merges a per-project `.kimi-code/mcp.json` over it on /// startup; we manage the user-level file so the gateway is available @@ -1325,20 +1239,6 @@ fn kimi_code_path() -> Option { .or_else(|| client_config_path("kimi-code")) } -/// LM Studio reads MCP servers from `~/.lmstudio/mcp.json` (`mcpServers`, plain -/// JSON). The file is created by LM Studio, so the parent-dir presence check works. -fn lmstudio_path() -> Option { - client_config_path("lm-studio") -} - -/// Jan keeps MCP servers in mcp_config.json (standard `mcpServers` shape) inside -/// its data folder, `/Jan/data` on every OS (e.g. %APPDATA%\Jan\data on -/// Windows, ~/Library/Application Support/Jan/data on macOS). Jan creates the -/// folder and a default config on first launch, so the parent-dir check detects it. -fn jan_path() -> Option { - client_config_path("jan") -} - /// Goose keeps extensions (its MCP servers) in config.yaml. It resolves the dir /// via the `etcetera` "Block/goose" app strategy: ~/.config/goose on Linux, an /// app-support path on macOS, and %APPDATA%\Block\goose\config on Windows. (The @@ -1347,13 +1247,6 @@ fn goose_path() -> Option { client_config_path("goose") } -/// Zed keeps MCP ("context") servers in its main settings.json (JSONC). Windows -/// uses %APPDATA%\Zed; macOS and Linux use ~/.config/zed (not App Support). The -/// parent dir is created on install, so the default presence heuristic works. -fn zed_path() -> Option { - client_config_path("zed") -} - /// Hermes keeps MCP servers in ~/.hermes/config.yaml under the `mcp_servers:` key. /// The file is YAML and also holds the user's model and platform toolsets config, /// so it's read leniently and never wiped on a parse failure. @@ -1400,17 +1293,6 @@ fn continue_path() -> Option { client_config_path("continue") } -/// Witsy keeps MCP servers in a top-level `mcpServers` object inside its main -/// settings.json (alongside all other app settings), in the Claude-compatible -/// `{command, args, env}` shape. Electron's userData dir is "Witsy" on every OS: -/// ~/Library/Application Support/Witsy on macOS, %APPDATA%\Witsy on Windows, -/// ~/.config/Witsy on Linux. Confirmed against the app's own source -/// (src/main/mcp.ts reads/writes config.mcpServers directly) and the project's -/// file-location wiki page. -fn witsy_path() -> Option { - client_config_path("witsy") -} - fn cursor_plugins_dir() -> Option { Some(home()?.join(".cursor").join("plugins").join("cache")) } @@ -1519,7 +1401,7 @@ fn defs() -> Vec { name: "Cursor", format: Format::JsonMcpServers, uses_connectors: false, - path: cursor_path, + path: || client_config_path("cursor"), plugin_scan: Some(scan_cursor_plugins), }, ClientDef { @@ -1527,7 +1409,7 @@ fn defs() -> Vec { name: "Factory Droid", format: Format::JsonDroidMcpServers, uses_connectors: false, - path: droid_path, + path: || client_config_path("droid"), plugin_scan: None, }, ClientDef { @@ -1543,7 +1425,7 @@ fn defs() -> Vec { name: "AnythingLLM", format: Format::JsonMcpServers, uses_connectors: false, - path: anythingllm_path, + path: || client_config_path("anythingllm"), plugin_scan: None, }, ClientDef { @@ -1551,7 +1433,7 @@ fn defs() -> Vec { name: "VS Code", format: Format::JsonServers, uses_connectors: false, - path: vscode_path, + path: || client_config_path("vscode"), plugin_scan: None, }, ClientDef { @@ -1567,7 +1449,7 @@ fn defs() -> Vec { name: "Devin Desktop (Cascade)", format: Format::JsonMcpServers, uses_connectors: false, - path: windsurf_path, + path: || client_config_path("windsurf"), plugin_scan: None, }, ClientDef { @@ -1575,7 +1457,7 @@ fn defs() -> Vec { name: "Devin Local / CLI", format: Format::JsonMcpServers, uses_connectors: false, - path: devin_cli_path, + path: || client_config_path("devin-cli"), plugin_scan: None, }, ClientDef { @@ -1583,7 +1465,9 @@ fn defs() -> Vec { name: "OpenCode", format: Format::JsonOpenCodeMcp, uses_connectors: false, - path: opencode_path, + // OpenCode stores its global config at the literal + // `~/.config/opencode/opencode.json` or `opencode.jsonc` on every supported OS. + path: || client_config_path("opencode"), plugin_scan: None, }, ClientDef { @@ -1591,7 +1475,9 @@ fn defs() -> Vec { name: "Kilo Code", format: Format::JsonOpenCodeMcp, uses_connectors: false, - path: kilo_code_path, + // Kilo Code stores its global JSONC config at the literal + // `~/.config/kilo/kilo.jsonc` on every supported OS. + path: || client_config_path("kilo-code"), plugin_scan: None, }, ClientDef { @@ -1635,7 +1521,7 @@ fn defs() -> Vec { name: "Claude Code", format: Format::JsonMcpServers, uses_connectors: false, - path: claude_code_path, + path: || client_config_path("claude-code"), plugin_scan: None, }, ClientDef { @@ -1659,7 +1545,9 @@ fn defs() -> Vec { name: "JetBrains Junie", format: Format::JsonMcpServers, uses_connectors: false, - path: junie_path, + // Junie stores user-scoped MCP servers at ~/.junie/mcp/mcp.json on every + // supported platform. Project-scoped configs are intentionally left untouched. + path: || client_config_path("junie"), plugin_scan: None, }, ClientDef { @@ -1667,7 +1555,7 @@ fn defs() -> Vec { name: "Cline", format: Format::JsonMcpServers, uses_connectors: false, - path: cline_path, + path: || client_config_path("cline"), plugin_scan: None, }, ClientDef { @@ -1683,7 +1571,9 @@ fn defs() -> Vec { name: "Warp", format: Format::JsonMcpServers, uses_connectors: false, - path: warp_path, + // Warp reads file-based MCP servers from `~/.warp/.mcp.json` (keyed under + // `mcpServers`), alongside its in-app UI. The file is home-anchored on every OS. + path: || client_config_path("warp"), plugin_scan: None, }, ClientDef { @@ -1691,7 +1581,10 @@ fn defs() -> Vec { name: "Amazon Q", format: Format::JsonMcpServers, uses_connectors: false, - path: amazon_q_path, + // Amazon Q Developer CLI global MCP config: `~/.aws/amazonq/mcp.json` + // (`mcpServers`). A per-workspace `.amazonq/mcp.json` also exists; we manage the + // global one so the gateway is available everywhere. + path: || client_config_path("amazon-q"), plugin_scan: None, }, ClientDef { @@ -1699,7 +1592,9 @@ fn defs() -> Vec { name: "Kiro", format: Format::JsonMcpServers, uses_connectors: false, - path: kiro_path, + // Kiro user-level MCP config: `~/.kiro/settings/mcp.json` (`mcpServers`). A + // per-workspace `.kiro/settings/mcp.json` also exists and takes precedence. + path: || client_config_path("kiro"), plugin_scan: None, }, ClientDef { @@ -1715,7 +1610,10 @@ fn defs() -> Vec { name: "Zed", format: Format::JsonContextServers, uses_connectors: false, - path: zed_path, + // Zed keeps MCP ("context") servers in its main settings.json (JSONC). Windows + // uses %APPDATA%\Zed; macOS and Linux use ~/.config/zed (not App Support). The + // parent dir is created on install, so the default presence heuristic works. + path: || client_config_path("zed"), plugin_scan: None, }, ClientDef { @@ -1723,7 +1621,9 @@ fn defs() -> Vec { name: "LM Studio", format: Format::JsonMcpServers, uses_connectors: false, - path: lmstudio_path, + // LM Studio reads MCP servers from `~/.lmstudio/mcp.json` (`mcpServers`, plain + // JSON). The file is created by LM Studio, so the parent-dir presence check works. + path: || client_config_path("lm-studio"), plugin_scan: None, }, ClientDef { @@ -1731,7 +1631,11 @@ fn defs() -> Vec { name: "Jan", format: Format::JsonMcpServers, uses_connectors: false, - path: jan_path, + // Jan keeps MCP servers in mcp_config.json (standard `mcpServers` shape) inside + // its data folder, `/Jan/data` on every OS (e.g. %APPDATA%\Jan\data on + // Windows, ~/Library/Application Support/Jan/data on macOS). Jan creates the + // folder and a default config on first launch, so the parent-dir check detects it. + path: || client_config_path("jan"), plugin_scan: None, }, ClientDef { @@ -1739,7 +1643,7 @@ fn defs() -> Vec { name: "BoltAI", format: Format::JsonMcpServers, uses_connectors: false, - path: boltai_path, + path: || client_config_path("boltai"), plugin_scan: None, }, ClientDef { @@ -1747,7 +1651,10 @@ fn defs() -> Vec { name: "Pi", format: Format::JsonMcpServers, uses_connectors: false, - path: pi_path, + // Pi coding agent reads its Pi-owned global MCP config from ~/.pi/agent/mcp.json + // (standard `mcpServers` shape; pi's optional `lifecycle`/`idleTimeout` keys are + // left unset so it uses its defaults). Home-anchored, identical on every OS. + path: || client_config_path("pi"), plugin_scan: None, }, ClientDef { @@ -1755,7 +1662,9 @@ fn defs() -> Vec { name: "Oh My Pi", format: Format::JsonMcpServers, uses_connectors: false, - path: omp_path, + // Oh My Pi (omp) is a fork of Pi with its own config directory (~/.omp). + // Same `mcpServers` JSON format as Pi; home-anchored, identical on every OS. + path: || client_config_path("omp"), plugin_scan: None, }, ClientDef { @@ -1787,7 +1696,14 @@ fn defs() -> Vec { name: "Witsy", format: Format::JsonMcpServers, uses_connectors: false, - path: witsy_path, + // Witsy keeps MCP servers in a top-level `mcpServers` object inside its main + // settings.json (alongside all other app settings), in the Claude-compatible + // `{command, args, env}` shape. Electron's userData dir is "Witsy" on every OS: + // ~/Library/Application Support/Witsy on macOS, %APPDATA%\Witsy on Windows, + // ~/.config/Witsy on Linux. Confirmed against the app's own source + // (src/main/mcp.ts reads/writes config.mcpServers directly) and the project's + // file-location wiki page. + path: || client_config_path("witsy"), plugin_scan: None, }, ] diff --git a/src-tauri/tests/security_doc.rs b/src-tauri/tests/security_doc.rs deleted file mode 100644 index 8bfbb4ec..00000000 --- a/src-tauri/tests/security_doc.rs +++ /dev/null @@ -1,22 +0,0 @@ -//! Regression guard for SECURITY.md accuracy (SOU-41). -//! -//! SECURITY.md used to carry two materially false absolute claims: that the gateway -//! "opens no listening network port" (false in HTTP / Docker mode, which binds a -//! persistent listener, `0.0.0.0:8765` by default in the image) and that "There is no -//! telemetry" (Teams reports per-server aggregate usage to the team server). If you -//! reword the doc, keep every such statement mode-aware, not absolute, so the two -//! claims can never silently return. - -#[test] -fn security_md_has_no_stale_absolute_claims() { - let path = concat!(env!("CARGO_MANIFEST_DIR"), "/../SECURITY.md"); - let text = std::fs::read_to_string(path).unwrap_or_else(|e| panic!("read {path}: {e}")); - for banned in ["opens no listening network port", "There is no telemetry"] { - assert!( - !text.contains(banned), - "SECURITY.md re-introduced a false absolute claim: {banned:?}. Keep the \ - wording mode-aware (see SOU-41): the gateway binds a listener in HTTP/Docker \ - mode, and Teams reports aggregate usage." - ); - } -} diff --git a/src/components/ui/separator.tsx b/src/components/ui/separator.tsx deleted file mode 100644 index d7fc9faa..00000000 --- a/src/components/ui/separator.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import * as React from "react"; -import { Separator as SeparatorPrimitive } from "radix-ui"; - -import { cn } from "@/lib/utils"; - -function Separator({ - className, - orientation = "horizontal", - decorative = true, - ...props -}: React.ComponentProps) { - return ( - - ); -} - -export { Separator }; diff --git a/src/test/homebrew-cask.test.ts b/src/test/homebrew-cask.test.ts index ad69a5c9..7081b7bb 100644 --- a/src/test/homebrew-cask.test.ts +++ b/src/test/homebrew-cask.test.ts @@ -11,7 +11,6 @@ import { join } from "node:path"; // root (where vite.config.ts lives). const repoRoot = process.cwd(); const cask = readFileSync(join(repoRoot, "packaging", "homebrew", "toolport.rb"), "utf8"); -const releasing = readFileSync(join(repoRoot, "docs", "RELEASING.md"), "utf8"); const pkg = JSON.parse(readFileSync(join(repoRoot, "package.json"), "utf8")) as { version: string; }; @@ -51,17 +50,3 @@ describe("homebrew cask snapshot (packaging/homebrew/toolport.rb)", () => { ); }); }); - -describe("RELEASING.md Homebrew tap step", () => { - it("names the live tap and the workflow that bumps it", () => { - // The hashing used to be a manual `shasum` step here. It is now the tap's - // own bump.yml, which computes both digests from the published DMGs; this - // guards that the doc keeps pointing at the real mechanism. - expect(releasing).toContain("btsouth/homebrew-toolport"); - expect(releasing).toContain("Casks/toolport.rb"); - expect(releasing).toContain("bump.yml"); - expect(releasing).toContain( - "gh workflow run bump.yml --repo btsouth/homebrew-toolport", - ); - }); -}); diff --git a/src/test/linux-packaging.test.ts b/src/test/linux-packaging.test.ts index 05f20627..987b8c9e 100644 --- a/src/test/linux-packaging.test.ts +++ b/src/test/linux-packaging.test.ts @@ -441,14 +441,4 @@ describe("install.sh installs the pacman package on Arch", () => { it("still falls through to the AppImage everywhere else", () => { expect(installer).toContain("Installed the AppImage"); }); - - it("is covered by the bash installer tests, with pacman shimmed", () => { - // Without the shim, running those tests on an Arch box would exercise the - // host's real package manager mid-test. - const harness = read("scripts", "install.Tests.bash"); - expect(harness).toContain('cat > "$arch_shim/pacman"'); - expect(harness).toContain('cat > "$arch_shim/pacman-key"'); - expect(harness).toContain("no AUR helper was invoked"); - expect(harness).toContain("repository added to pacman.conf"); - }); });