diff --git a/Cargo.lock b/Cargo.lock index bfd3d0f9..e41aa170 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1026,7 +1026,7 @@ dependencies = [ "libc", "option-ext", "redox_users 0.5.2", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -1042,6 +1042,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" dependencies = [ "bitflags 2.10.0", + "block2", + "libc", "objc2", ] @@ -1222,7 +1224,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -2053,7 +2055,7 @@ dependencies = [ "js-sys", "log", "wasm-bindgen", - "windows-core 0.61.2", + "windows-core 0.62.2", ] [[package]] @@ -2631,6 +2633,7 @@ dependencies = [ "tauri-build", "tauri-plugin-autostart", "tauri-plugin-deep-link", + "tauri-plugin-dialog", "tauri-plugin-opener", "tauri-plugin-single-instance", "tauri-plugin-updater", @@ -2948,7 +2951,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -3004,7 +3007,7 @@ version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51e219e79014df21a225b1860a479e2dcd7cbd9130f4defd4bd0e191ea31d67d" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "chrono", "getrandom 0.2.17", "http", @@ -3343,7 +3346,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d8fae84b431384b68627d0f9b3b1245fcf9f46f6c0e3dc902e9dce64edd1967" dependencies = [ "libc", - "windows-sys 0.45.0", + "windows-sys 0.61.2", ] [[package]] @@ -3850,7 +3853,7 @@ dependencies = [ "once_cell", "socket2", "tracing", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -4176,6 +4179,30 @@ dependencies = [ "web-sys", ] +[[package]] +name = "rfd" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a15ad77d9e70a92437d8f74c35d99b4e4691128df018833e99f90bcd36152672" +dependencies = [ + "block2", + "dispatch2", + "glib-sys", + "gobject-sys", + "gtk-sys", + "js-sys", + "log", + "objc2", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation", + "raw-window-handle", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows-sys 0.60.2", +] + [[package]] name = "ring" version = "0.17.14" @@ -4285,7 +4312,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -4342,7 +4369,7 @@ dependencies = [ "security-framework 3.5.1", "security-framework-sys", "webpki-root-certs", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -5216,6 +5243,46 @@ dependencies = [ "windows-result 0.3.4", ] +[[package]] +name = "tauri-plugin-dialog" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9204b425d9be8d12aa60c2a83a289cf7d1caae40f57f336ed1155b3a5c0e359b" +dependencies = [ + "log", + "raw-window-handle", + "rfd", + "serde", + "serde_json", + "tauri", + "tauri-plugin", + "tauri-plugin-fs", + "thiserror 2.0.18", + "url", +] + +[[package]] +name = "tauri-plugin-fs" +version = "2.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed390cc669f937afeb8b28032ce837bac8ea023d975a2e207375ec05afaf1804" +dependencies = [ + "anyhow", + "dunce", + "glob", + "percent-encoding", + "schemars 0.8.22", + "serde", + "serde_json", + "serde_repr", + "tauri", + "tauri-plugin", + "tauri-utils", + "thiserror 2.0.18", + "toml 0.9.11+spec-1.1.0", + "url", +] + [[package]] name = "tauri-plugin-opener" version = "2.5.3" @@ -5398,7 +5465,7 @@ dependencies = [ "getrandom 0.3.4", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -6369,7 +6436,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.61.2", ] [[package]] diff --git a/apps/desktop/package.json b/apps/desktop/package.json index 086ea6f3..de84e66f 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -18,6 +18,7 @@ "dependencies": { "@monaco-editor/react": "^4.7.0", "@tauri-apps/api": "^2.10.1", + "@tauri-apps/plugin-dialog": "^2", "@tauri-apps/plugin-opener": "^2", "@tauri-apps/plugin-process": "^2", "@tauri-apps/plugin-updater": "^2", diff --git a/apps/desktop/src-tauri/Cargo.toml b/apps/desktop/src-tauri/Cargo.toml index 7fc66298..ee929579 100644 --- a/apps/desktop/src-tauri/Cargo.toml +++ b/apps/desktop/src-tauri/Cargo.toml @@ -21,6 +21,7 @@ tauri-plugin-single-instance = { version = "2", features = ["deep-link"] } tauri-plugin-deep-link = "2" tauri-plugin-updater = "2" tauri-plugin-autostart = "2" +tauri-plugin-dialog = "2" image = { version = "0.25", default-features = false, features = ["png"] } serde.workspace = true serde_json.workspace = true diff --git a/apps/desktop/src-tauri/capabilities/default.json b/apps/desktop/src-tauri/capabilities/default.json index dbd19e79..54a377ca 100644 --- a/apps/desktop/src-tauri/capabilities/default.json +++ b/apps/desktop/src-tauri/capabilities/default.json @@ -16,6 +16,7 @@ "core:window:allow-set-focus", "opener:default", "deep-link:default", - "updater:default" + "updater:default", + "dialog:default" ] } diff --git a/apps/desktop/src-tauri/src/lib.rs b/apps/desktop/src-tauri/src/lib.rs index eed65845..d1a46f67 100644 --- a/apps/desktop/src-tauri/src/lib.rs +++ b/apps/desktop/src-tauri/src/lib.rs @@ -188,6 +188,7 @@ pub fn run() { tauri::Builder::default() .plugin(tauri_plugin_opener::init()) + .plugin(tauri_plugin_dialog::init()) .plugin(tauri_plugin_deep_link::init()) .plugin(tauri_plugin_autostart::init( tauri_plugin_autostart::MacosLauncher::LaunchAgent, diff --git a/apps/desktop/src/features/servers/ServersPage.tsx b/apps/desktop/src/features/servers/ServersPage.tsx index 5ce47825..07ad188e 100644 --- a/apps/desktop/src/features/servers/ServersPage.tsx +++ b/apps/desktop/src/features/servers/ServersPage.tsx @@ -8,6 +8,7 @@ */ import { useEffect, useState, useCallback } from 'react'; +import { open } from '@tauri-apps/plugin-dialog'; import { ChevronDown, ChevronRight, @@ -17,6 +18,7 @@ import { Loader2, Clock, FileJson, + FolderOpen, } from 'lucide-react'; import { ServerActionMenu } from './ServerActionMenu'; import type { ServerViewModel, ServerDefinition, InstalledServerState, InputDefinition } from '../../types/registry'; @@ -1338,16 +1340,67 @@ export function ServersPage() { className="input w-full" /> ); - case 'password': + case 'select': return ( - handleChange(e.target.value)} - placeholder={input.placeholder || `Enter ${input.label.toLowerCase()}...`} className="input w-full" data-testid={`config-input-${input.id}`} - /> + > + + {(input.options ?? []).map((opt) => ( + + ))} + + ); + case 'file_path': + return ( +
+ handleChange(e.target.value)} + placeholder={input.placeholder || 'Select a file...'} + className="input w-full" + data-testid={`config-input-${input.id}`} + /> + +
+ ); + case 'directory_path': + return ( +
+ handleChange(e.target.value)} + placeholder={input.placeholder || 'Select a directory...'} + className="input w-full" + data-testid={`config-input-${input.id}`} + /> + +
); case 'text': default: diff --git a/apps/desktop/src/types/registry.ts b/apps/desktop/src/types/registry.ts index 4cebfb63..991b7bce 100644 --- a/apps/desktop/src/types/registry.ts +++ b/apps/desktop/src/types/registry.ts @@ -8,8 +8,10 @@ export interface InputDefinition { label: string; description?: string; /** Input type - determines how the field is rendered */ - type?: 'text' | 'password' | 'boolean' | 'number' | 'url'; + type?: 'text' | 'boolean' | 'number' | 'url' | 'select' | 'file_path' | 'directory_path'; required?: boolean; + /** Predefined options for select input type */ + options?: { value: string; label: string; description?: string }[]; secret?: boolean; placeholder?: string; /** URL to obtain credentials/values */ diff --git a/crates/mcpmux-gateway/src/pool/transport/shell_env.rs b/crates/mcpmux-gateway/src/pool/transport/shell_env.rs index bfc4c8c1..17241873 100644 --- a/crates/mcpmux-gateway/src/pool/transport/shell_env.rs +++ b/crates/mcpmux-gateway/src/pool/transport/shell_env.rs @@ -11,6 +11,7 @@ use std::ffi::OsString; use std::sync::OnceLock; +#[cfg(unix)] use tracing::{debug, info, warn}; /// Cached shell PATH, resolved once on first access. diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c094ecb7..76f79091 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -104,6 +104,9 @@ importers: '@tauri-apps/api': specifier: ^2.10.1 version: 2.10.1 + '@tauri-apps/plugin-dialog': + specifier: ^2 + version: 2.6.0 '@tauri-apps/plugin-opener': specifier: ^2 version: 2.5.2 @@ -1405,6 +1408,9 @@ packages: engines: {node: '>= 10'} hasBin: true + '@tauri-apps/plugin-dialog@2.6.0': + resolution: {integrity: sha512-q4Uq3eY87TdcYzXACiYSPhmpBA76shgmQswGkSVio4C82Sz2W4iehe9TnKYwbq7weHiL88Yw19XZm7v28+Micg==} + '@tauri-apps/plugin-opener@2.5.2': resolution: {integrity: sha512-ei/yRRoCklWHImwpCcDK3VhNXx+QXM9793aQ64YxpqVF0BDuuIlXhZgiAkc15wnPVav+IbkYhmDJIv5R326Mew==} @@ -5421,6 +5427,10 @@ snapshots: '@tauri-apps/cli-win32-ia32-msvc': 2.10.0 '@tauri-apps/cli-win32-x64-msvc': 2.10.0 + '@tauri-apps/plugin-dialog@2.6.0': + dependencies: + '@tauri-apps/api': 2.10.1 + '@tauri-apps/plugin-opener@2.5.2': dependencies: '@tauri-apps/api': 2.10.1 diff --git a/tests/ts/setup.ts b/tests/ts/setup.ts index 02b6e5d1..6f36c17a 100644 --- a/tests/ts/setup.ts +++ b/tests/ts/setup.ts @@ -24,6 +24,11 @@ vi.mock('@tauri-apps/plugin-updater', () => ({ Update: vi.fn(), })); +// Mock Tauri dialog plugin +vi.mock('@tauri-apps/plugin-dialog', () => ({ + open: vi.fn(), +})); + // Mock Tauri process plugin vi.mock('@tauri-apps/plugin-process', () => ({ relaunch: vi.fn(),