chore: add rustfmt.toml and update .gitignore#62
chore: add rustfmt.toml and update .gitignore#62vlordier wants to merge 6 commits intoLiquid4All:mainfrom
Conversation
- Tool Result Compression: smart summarization for large tool outputs (directory listings, search results, JSON data) - Request Deduplication: 500ms debounce on send button to prevent duplicate requests from rapid clicks - Config Hot Reload: poll config file for changes, reload without restart, show toast notification - Error Boundary: timeout wrapper (120s) around tool execution, graceful error messages instead of crashing agent loop
- Add 13 tests for settings.rs (AppSettings, SamplingConfig, config hot reload) - Add 12 tests for chat.rs compression functions (truncate, compress directory, search, JSON) - Total tests: 392 (up from 365) - Coverage: 42.5% (up from 39.5%)
- Add ModelStatus tests (serialization, healthy/unhealthy states) - Add SamplingOverrides serialization tests - Add InferenceClient tests for: - LM Studio URL construction and model selection - Tool call format (NativeJson vs Pythonic) - Fallback chain exhaustion (AllModelsUnavailable) - is_retriable for various HTTP status codes - Error repair from malformed tool calls - Total tests: 417 (up from 392)
- Add tests for data_dir(), cache_dir(), resolve_db_path() - Add rotate_log_file() tests (creates rotated copies, handles missing files) - Add filter_by_enabled_servers() tests (filters correctly, handles missing/invalid config) - Add resolve_vision_model() tests (returns None without config) - Add filter_tools_by_allowlist() test (doesn't panic without config) - Add load_override_file() tests (parses config, returns empty for missing) - Total tests: 430 (up from 417) - Coverage: 43.3% (up from 42.5%)
- Add src-tauri/rustfmt.toml with code formatting configuration - Add Tauri-specific entries to .gitignore (target/, gen/) - Add #[allow(dead_code)] for unused cache_dir() function
There was a problem hiding this comment.
Pull request overview
Adds Tauri scaffolding and supporting frontend/backends pieces to enable a desktop app workflow, including model/MCP server management, inference streaming, and IPC commands.
Changes:
- Added new frontend state/UI for settings/config watching and chat input behaviors.
- Added backend MCP client, inference client (streaming + config), and IPC command surface (session, env provisioning, downloads, hardware, filesystem).
- Added Tauri configuration and Rust formatting/config files.
Reviewed changes
Copilot reviewed 49 out of 57 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| src/stores/settingsStore.ts | Introduces Zustand settings store with IPC calls and config file watch/polling. |
| src/components/Chat/MessageInput.tsx | Adds chat message input with enter-to-send, debouncing, and toolbar integration. |
| src/App.tsx | Wires settings panel visibility to backend config watch and displays reload toast. |
| src-tauri/tauri.conf.json | Adds Tauri v2 app/bundle configuration including CSP and window metadata. |
| src-tauri/src/mcp_client/types.rs | Defines MCP/JSON-RPC shared types plus unit tests. |
| src-tauri/src/mcp_client/transport.rs | Implements JSON-RPC-over-stdio transport and helpers with tests. |
| src-tauri/src/mcp_client/mod.rs | Exposes MCP client module structure and re-exports. |
| src-tauri/src/mcp_client/lifecycle.rs | Adds server spawn/restart/shutdown lifecycle management with stderr capture. |
| src-tauri/src/mcp_client/errors.rs | Adds typed MCP client errors. |
| src-tauri/src/mcp_client/discovery.rs | Adds auto-discovery of MCP servers and config merging with tests. |
| src-tauri/src/mcp_client/client.rs | Adds high-level MCP client orchestration and tool execution with timeout. |
| src-tauri/src/main.rs | Adds Tauri entrypoint calling library run function. |
| src-tauri/src/inference/types.rs | Adds OpenAI-compatible request/response types and sampling overrides with tests. |
| src-tauri/src/inference/streaming.rs | Adds SSE streaming parser and non-streaming fallback parsing with tests. |
| src-tauri/src/inference/mod.rs | Defines inference module surface and re-exports. |
| src-tauri/src/inference/errors.rs | Adds typed inference errors plus helpers and tests. |
| src-tauri/src/inference/config.rs | Loads/validates model config YAML with env interpolation and tests. |
| src-tauri/src/commands/session.rs | Adds session list/load/delete and context budget IPC commands. |
| src-tauri/src/commands/python_env_startup.rs | Adds startup-time Python venv provisioning for MCP python servers. |
| src-tauri/src/commands/python_env.rs | Adds IPC commands for Python venv provisioning with progress events and tests. |
| src-tauri/src/commands/ollama.rs | Adds IPC commands for Ollama model listing/pull and llama.cpp health checks. |
| src-tauri/src/commands/model_download.rs | Adds streaming model download + SHA-256 verification commands and progress events. |
| src-tauri/src/commands/mod.rs | Registers IPC command modules and a greet placeholder. |
| src-tauri/src/commands/hardware.rs | Adds cross-platform hardware detection and recommendations. |
| src-tauri/src/commands/filesystem.rs | Adds stub filesystem browsing commands and hidden-file filtering. |
| src-tauri/src/agent_core/types.rs | Adds agent-core shared types for conversations, undo, audit, confirmation. |
| src-tauri/src/agent_core/tool_router.rs | Adds tool dispatch/confirmation/audit/undo pipeline with retry logic and tests. |
| src-tauri/src/agent_core/tool_prefilter.rs | Adds embedding-based tool prefilter (RAG) for tool selection with tests. |
| src-tauri/src/agent_core/tokens.rs | Adds token estimation utilities and safe UTF-8 truncation with tests. |
| src-tauri/src/agent_core/response_analysis.rs | Adds heuristics for incomplete/deflection response detection with tests. |
| src-tauri/src/agent_core/plan_templates.rs | Adds keyword-based plan templates for common workflows with tests. |
| src-tauri/src/agent_core/plan_parser.rs | Adds bracket + JSON plan parsers and argument extractors with tests. |
| src-tauri/src/agent_core/permissions.rs | Adds tiered permission store with persistence and tests. |
| src-tauri/src/agent_core/mod.rs | Wires agent-core module exports and re-exports. |
| src-tauri/src/agent_core/errors.rs | Adds typed agent-core errors and conversions. |
| src-tauri/rustfmt.toml | Adds Rust formatting configuration. |
| src-tauri/mcp-servers.json | Adds empty MCP servers config scaffold. |
| src-tauri/entitlements.plist | Adds macOS entitlements for process spawning/network/files. |
| src-tauri/capabilities/default.json | Adds Tauri capability permissions for shell/dialog usage. |
| src-tauri/build.rs | Adds Tauri build script entrypoint. |
| src-tauri/Cargo.toml | Adds Rust crate manifest with dependencies and release profile settings. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (interval) { | ||
| clearInterval(interval); |
There was a problem hiding this comment.
stopConfigWatch references interval, which is not defined in this scope (will throw/compile-fail). Use configWatchInterval for the null check and clearInterval call.
| if (interval) { | |
| clearInterval(interval); | |
| if (configWatchInterval) { | |
| clearInterval(configWatchInterval); |
| * Implements debouncing to prevent duplicate sends. | ||
| */ | ||
|
|
||
| import { useCallback, useRef, useState } from "react"; |
There was a problem hiding this comment.
This component uses the React namespace types (React.JSX.Element, React.KeyboardEvent) but only imports named hooks. Unless the project config provides a global React namespace for types, this will fail typechecking. Prefer importing type React (or the needed types) or switching the annotations to JSX.Element / KeyboardEvent from React types.
| import { useCallback, useRef, useState } from "react"; | |
| import { useCallback, useRef, useState } from "react"; | |
| import type React from "react"; |
| export function MessageInput({ | ||
| onSend, | ||
| disabled, | ||
| }: MessageInputProps): React.JSX.Element { |
There was a problem hiding this comment.
This component uses the React namespace types (React.JSX.Element, React.KeyboardEvent) but only imports named hooks. Unless the project config provides a global React namespace for types, this will fail typechecking. Prefer importing type React (or the needed types) or switching the annotations to JSX.Element / KeyboardEvent from React types.
| } | ||
| }, [value, disabled, onSend]); | ||
|
|
||
| const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>): void => { |
There was a problem hiding this comment.
This component uses the React namespace types (React.JSX.Element, React.KeyboardEvent) but only imports named hooks. Unless the project config provides a global React namespace for types, this will fail typechecking. Prefer importing type React (or the needed types) or switching the annotations to JSX.Element / KeyboardEvent from React types.
| // fs was overridden | ||
| assert_eq!(merged["fs"].command, "node"); | ||
| // ocr was NOT overridden — preserved from discovery | ||
| assert_eq!(merged["ocr"].command, "npx"); |
There was a problem hiding this comment.
This test hard-codes \"npx\", but ts_config() uses default_npx_command() which returns \"npx.cmd\" on Windows. This assertion will fail on Windows. Assert against default_npx_command() (or compare with ts_config(\"ocr\").command) instead of a constant.
| assert_eq!(merged["ocr"].command, "npx"); | |
| assert_eq!(merged["ocr"].command, ts_config("ocr").command); |
| // Include tool_call_id and toolResult for tool result messages | ||
| // so ToolTrace can correlate them and show results. | ||
| if let Some(ref tc_id) = m.tool_call_id { | ||
| let obj = msg.as_object_mut().unwrap(); | ||
| obj.insert( | ||
| "toolCallId".to_string(), | ||
| serde_json::Value::String(tc_id.clone()), | ||
| ); | ||
| // Include toolResult so ToolTrace can show result status | ||
| obj.insert( | ||
| "toolResult".to_string(), | ||
| serde_json::json!({ | ||
| "success": true, | ||
| "result": m.content, | ||
| "toolCallId": tc_id, | ||
| }), | ||
| ); | ||
| } |
There was a problem hiding this comment.
The emitted toolResult is always marked success: true and uses m.content as the result payload, even though the stored message has a dedicated tool_result: Option<serde_json::Value>. This will misrepresent failed tool calls and can drop structured results. Prefer populating toolResult.result from m.tool_result (and set success based on stored execution outcome, if available) rather than m.content.
| onClick={clearConfigReloadNotification} | ||
| > | ||
| <span className="toast-icon">🔄</span> | ||
| <span className="toast-message">{configReloadNotification}</span> | ||
| <button className="toast-close" aria-label="Dismiss"> |
There was a problem hiding this comment.
A clickable <div> is not keyboard-accessible by default. To meet basic accessibility expectations, use a <button> for the clickable container or add role=\"button\", tabIndex={0}, and an onKeyDown handler (Enter/Space) to trigger clearConfigReloadNotification.
| onClick={clearConfigReloadNotification} | |
| > | |
| <span className="toast-icon">🔄</span> | |
| <span className="toast-message">{configReloadNotification}</span> | |
| <button className="toast-close" aria-label="Dismiss"> | |
| role="button" | |
| tabIndex={0} | |
| onClick={clearConfigReloadNotification} | |
| onKeyDown={(event) => { | |
| if (event.key === "Enter" || event.key === " ") { | |
| event.preventDefault(); | |
| clearConfigReloadNotification(); | |
| } | |
| }} | |
| > | |
| <span className="toast-icon">🔄</span> | |
| <span className="toast-message">{configReloadNotification}</span> | |
| <button | |
| className="toast-close" | |
| aria-label="Dismiss" | |
| type="button" | |
| onClick={clearConfigReloadNotification} | |
| > |
| let http = HttpClient::builder() | ||
| .timeout(Duration::from_secs(30)) | ||
| .build() | ||
| .map_err(|e| ToolPreFilterError::RequestFailed { | ||
| reason: format!("failed to build HTTP client: {e}"), | ||
| })?; |
There was a problem hiding this comment.
embed_texts builds a new reqwest::Client on every call (including per-query calls from filter). Creating clients is relatively expensive and defeats connection pooling. Consider constructing the client once (e.g., store it in ToolEmbeddingIndex or pass an &reqwest::Client into embed_texts/filter).
chore: add header comment to rustfmt.toml
Summary
src-tauri/rustfmt.tomlwith code formatting configuration.gitignorewith Tauri-specific entries (target/, gen/)#[allow(dead_code)]for unusedcache_dir()functionChanges
Testing
cargo clippy -- -D warningspasses