diff --git a/rust/Cargo.toml b/rust/Cargo.toml index effbbba7..387e690c 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -20,6 +20,14 @@ members = [ "crates/openjarvis-scheduler", ] +# Minimum supported Rust version. The workspace uses let-chains (via rig-core) +# and `is_multiple_of` (openjarvis-skills), both stabilized in Rust 1.88 — +# building on 1.86/1.87 fails with cryptic E0658 errors deep in dependencies +# (see #252). Declared here and pinned in rust-toolchain.toml so users get a +# clear "requires rustc 1.88" signal instead. +[workspace.package] +rust-version = "1.88" + [workspace.dependencies] serde = { version = "1", features = ["derive"] } serde_json = "1" diff --git a/rust/crates/openjarvis-agents/src/loop_guard.rs b/rust/crates/openjarvis-agents/src/loop_guard.rs index f41e4b5c..082b35e7 100644 --- a/rust/crates/openjarvis-agents/src/loop_guard.rs +++ b/rust/crates/openjarvis-agents/src/loop_guard.rs @@ -32,8 +32,7 @@ impl LoopGuard { // Check identical calls if self.seen_hashes.contains(&hash) { return Some(format!( - "Loop detected: identical call to '{}' with same arguments", - tool_name + "Loop detected: identical call to '{tool_name}' with same arguments" )); } self.seen_hashes.insert(hash); diff --git a/rust/crates/openjarvis-agents/src/monitor_operative.rs b/rust/crates/openjarvis-agents/src/monitor_operative.rs index 3ac60aee..7b201c4a 100644 --- a/rust/crates/openjarvis-agents/src/monitor_operative.rs +++ b/rust/crates/openjarvis-agents/src/monitor_operative.rs @@ -355,7 +355,7 @@ impl OjAgent for MonitorOperativeAgent { // Loop guard check if let Some(loop_msg) = guard.check(&action, &action_input) { return Ok(AgentResult { - content: format!("Agent stopped: {}", loop_msg), + content: format!("Agent stopped: {loop_msg}"), tool_results: all_tool_results, turns: turn, metadata: self.strategy_metadata(), @@ -379,7 +379,7 @@ impl OjAgent for MonitorOperativeAgent { let compressed = self.compress_observation(&tool_result.content); history.push(RigMessage::assistant(&text)); - current_input = format!("Observation: {}", compressed); + current_input = format!("Observation: {compressed}"); all_tool_results.push(tool_result); } else { diff --git a/rust/crates/openjarvis-agents/src/native_openhands.rs b/rust/crates/openjarvis-agents/src/native_openhands.rs index b9bb8501..f35be65c 100644 --- a/rust/crates/openjarvis-agents/src/native_openhands.rs +++ b/rust/crates/openjarvis-agents/src/native_openhands.rs @@ -202,7 +202,7 @@ impl OjAgent for NativeOpenHandsAgent { if let Some(loop_msg) = guard.check(tool_name, &args_str) { return Ok(AgentResult { - content: format!("Agent stopped: {}", loop_msg), + content: format!("Agent stopped: {loop_msg}"), tool_results: all_tool_results, turns: turn, metadata: HashMap::new(), @@ -221,7 +221,7 @@ impl OjAgent for NativeOpenHandsAgent { let obs = Self::truncate_observation(&tool_result.content, 4000); history.push(RigMessage::assistant(&text)); - current_input = format!("Output:\n{}", obs); + current_input = format!("Output:\n{obs}"); all_tool_results.push(tool_result); continue; @@ -231,7 +231,7 @@ impl OjAgent for NativeOpenHandsAgent { if let Some((action, action_input)) = Self::parse_action(&text) { if let Some(loop_msg) = guard.check(&action, &action_input) { return Ok(AgentResult { - content: format!("Agent stopped: {}", loop_msg), + content: format!("Agent stopped: {loop_msg}"), tool_results: all_tool_results, turns: turn, metadata: HashMap::new(), @@ -253,7 +253,7 @@ impl OjAgent for NativeOpenHandsAgent { let obs = Self::truncate_observation(&tool_result.content, 4000); history.push(RigMessage::assistant(&text)); - current_input = format!("Result: {}", obs); + current_input = format!("Result: {obs}"); all_tool_results.push(tool_result); continue; diff --git a/rust/crates/openjarvis-agents/src/native_react.rs b/rust/crates/openjarvis-agents/src/native_react.rs index 0f01678d..88c4fc04 100644 --- a/rust/crates/openjarvis-agents/src/native_react.rs +++ b/rust/crates/openjarvis-agents/src/native_react.rs @@ -143,7 +143,7 @@ impl OjAgent for NativeReActAgent { if let Some((action, action_input)) = Self::parse_action(&text) { if let Some(loop_msg) = guard.check(&action, &action_input) { return Ok(AgentResult { - content: format!("Agent stopped: {}", loop_msg), + content: format!("Agent stopped: {loop_msg}"), tool_results: all_tool_results, turns: turn, metadata: HashMap::new(), diff --git a/rust/crates/openjarvis-engine/src/discovery.rs b/rust/crates/openjarvis-engine/src/discovery.rs index d777a3d9..9c9b55fe 100644 --- a/rust/crates/openjarvis-engine/src/discovery.rs +++ b/rust/crates/openjarvis-engine/src/discovery.rs @@ -104,8 +104,7 @@ pub fn get_engine_static( ))), other => Err(OpenJarvisError::Engine( openjarvis_core::error::EngineError::ModelNotFound(format!( - "Unknown engine: {}", - other + "Unknown engine: {other}" )), )), } diff --git a/rust/crates/openjarvis-engine/src/llamacpp.rs b/rust/crates/openjarvis-engine/src/llamacpp.rs index f38322e0..65820c80 100644 --- a/rust/crates/openjarvis-engine/src/llamacpp.rs +++ b/rust/crates/openjarvis-engine/src/llamacpp.rs @@ -28,7 +28,7 @@ impl LlamaCppEngine { let host = if host.starts_with("http") { host } else { - format!("http://{}", host) + format!("http://{host}") }; let host = host.trim_end_matches('/').to_string(); let timeout = std::time::Duration::from_secs_f64(timeout_secs); @@ -120,8 +120,7 @@ impl InferenceEngine for LlamaCppEngine { let status = resp.status(); let body = resp.text().unwrap_or_default(); return Err(OpenJarvisError::Engine(EngineError::Http(format!( - "llama.cpp returned {}: {}", - status, body + "llama.cpp returned {status}: {body}" )))); } diff --git a/rust/crates/openjarvis-engine/src/ollama.rs b/rust/crates/openjarvis-engine/src/ollama.rs index 7056646c..832ea780 100644 --- a/rust/crates/openjarvis-engine/src/ollama.rs +++ b/rust/crates/openjarvis-engine/src/ollama.rs @@ -119,7 +119,7 @@ impl InferenceEngine for OllamaEngine { ToolCall { id: tc["id"] .as_str() - .unwrap_or(&format!("call_{}", i)) + .unwrap_or(&format!("call_{i}")) .to_string(), name: func["name"].as_str().unwrap_or("").to_string(), arguments: args, diff --git a/rust/crates/openjarvis-engine/src/openai_compat.rs b/rust/crates/openjarvis-engine/src/openai_compat.rs index bac79b33..3fd3e874 100644 --- a/rust/crates/openjarvis-engine/src/openai_compat.rs +++ b/rust/crates/openjarvis-engine/src/openai_compat.rs @@ -84,7 +84,7 @@ impl OpenAICompatEngine { if let Some(ref key) = self.api_key { headers.insert( reqwest::header::AUTHORIZATION, - format!("Bearer {}", key).parse().unwrap(), + format!("Bearer {key}").parse().unwrap(), ); } headers @@ -239,7 +239,7 @@ impl InferenceEngine for OpenAICompatEngine { if let Some(ref key) = self.api_key { headers.insert( reqwest::header::AUTHORIZATION, - format!("Bearer {}", key).parse().unwrap(), + format!("Bearer {key}").parse().unwrap(), ); } diff --git a/rust/crates/openjarvis-engine/src/rig_adapter.rs b/rust/crates/openjarvis-engine/src/rig_adapter.rs index 873086a8..b96e3f5b 100644 --- a/rust/crates/openjarvis-engine/src/rig_adapter.rs +++ b/rust/crates/openjarvis-engine/src/rig_adapter.rs @@ -107,8 +107,7 @@ fn rig_request_to_oj_messages(request: &CompletionRequest) -> Vec { .collect::>() .join("\n\n"); messages.push(Message::system(format!( - "Relevant context:\n{}", - doc_context + "Relevant context:\n{doc_context}" ))); } diff --git a/rust/crates/openjarvis-engine/src/sglang.rs b/rust/crates/openjarvis-engine/src/sglang.rs index 3c7aadd5..311ff8fa 100644 --- a/rust/crates/openjarvis-engine/src/sglang.rs +++ b/rust/crates/openjarvis-engine/src/sglang.rs @@ -24,7 +24,7 @@ impl SGLangEngine { let host = if host.starts_with("http") { host } else { - format!("http://{}", host) + format!("http://{host}") }; let host = host.trim_end_matches('/').to_string(); let timeout = std::time::Duration::from_secs_f64(timeout_secs); @@ -115,8 +115,7 @@ impl InferenceEngine for SGLangEngine { let status = resp.status(); let body = resp.text().unwrap_or_default(); return Err(OpenJarvisError::Engine(EngineError::Http(format!( - "SGLang returned {}: {}", - status, body + "SGLang returned {status}: {body}" )))); } diff --git a/rust/crates/openjarvis-engine/src/vllm.rs b/rust/crates/openjarvis-engine/src/vllm.rs index 01ef4932..7cbba17a 100644 --- a/rust/crates/openjarvis-engine/src/vllm.rs +++ b/rust/crates/openjarvis-engine/src/vllm.rs @@ -26,7 +26,7 @@ impl VLLMEngine { let host = if host.starts_with("http") { host } else { - format!("http://{}", host) + format!("http://{host}") }; let host = host.trim_end_matches('/').to_string(); let timeout = std::time::Duration::from_secs_f64(timeout_secs); @@ -70,7 +70,7 @@ impl VLLMEngine { if let Some(ref key) = self.api_key { headers.insert( reqwest::header::AUTHORIZATION, - format!("Bearer {}", key).parse().unwrap(), + format!("Bearer {key}").parse().unwrap(), ); } headers @@ -135,8 +135,7 @@ impl InferenceEngine for VLLMEngine { let status = resp.status(); let body = resp.text().unwrap_or_default(); return Err(OpenJarvisError::Engine(EngineError::Http(format!( - "vLLM returned {}: {}", - status, body + "vLLM returned {status}: {body}" )))); } @@ -231,7 +230,7 @@ impl InferenceEngine for VLLMEngine { if let Some(ref key) = self.api_key { headers.insert( reqwest::header::AUTHORIZATION, - format!("Bearer {}", key).parse().unwrap(), + format!("Bearer {key}").parse().unwrap(), ); } diff --git a/rust/crates/openjarvis-learning/src/agent_advisor.rs b/rust/crates/openjarvis-learning/src/agent_advisor.rs index 186cd3a1..0fe21852 100644 --- a/rust/crates/openjarvis-learning/src/agent_advisor.rs +++ b/rust/crates/openjarvis-learning/src/agent_advisor.rs @@ -78,8 +78,7 @@ impl AgentAdvisorPolicy { recs.push(Recommendation { rec_type: "routing".to_string(), suggestion: format!( - "Query class '{}' has {} failures — consider different model or agent", - qclass, count, + "Query class '{qclass}' has {count} failures — consider different model or agent", ), severity: "high".to_string(), }); @@ -160,7 +159,7 @@ mod tests { let traces: Vec = (0..5) .map(|i| TraceInfo { outcome: "failure".into(), - query: format!("query {}", i), + query: format!("query {i}"), tool_call_count: 8, total_latency_seconds: 2.0, }) @@ -178,7 +177,7 @@ mod tests { let traces: Vec = (0..5) .map(|i| TraceInfo { outcome: "failure".into(), - query: format!("def func_{}():", i), + query: format!("def func_{i}():"), tool_call_count: 2, total_latency_seconds: 1.0, }) diff --git a/rust/crates/openjarvis-learning/src/icl_updater.rs b/rust/crates/openjarvis-learning/src/icl_updater.rs index cf2fb544..65c57c9b 100644 --- a/rust/crates/openjarvis-learning/src/icl_updater.rs +++ b/rust/crates/openjarvis-learning/src/icl_updater.rs @@ -209,7 +209,7 @@ mod tests { fn test_max_examples_trim() { let mut policy = ICLUpdaterPolicy::new(0.0, 3, 3); for i in 0..5 { - policy.add_example(format!("q{}", i), format!("r{}", i), 0.5, HashMap::new()); + policy.add_example(format!("q{i}"), format!("r{i}"), 0.5, HashMap::new()); } assert_eq!(policy.example_db().len(), 3); assert_eq!(policy.example_db()[0].query, "q2"); diff --git a/rust/crates/openjarvis-mcp/src/server.rs b/rust/crates/openjarvis-mcp/src/server.rs index 6ce3e6f0..d5ec33e7 100644 --- a/rust/crates/openjarvis-mcp/src/server.rs +++ b/rust/crates/openjarvis-mcp/src/server.rs @@ -97,7 +97,7 @@ impl McpServer { let resp = McpResponse::error( Value::Null, -32700, - &format!("Parse error: {}", e), + &format!("Parse error: {e}"), ); serde_json::to_string(&resp).unwrap_or_default() } diff --git a/rust/crates/openjarvis-python/src/engine.rs b/rust/crates/openjarvis-python/src/engine.rs index 166e12d6..00952a40 100644 --- a/rust/crates/openjarvis-python/src/engine.rs +++ b/rust/crates/openjarvis-python/src/engine.rs @@ -93,7 +93,7 @@ impl PyEngine { ), other => { return Err(PyErr::new::( - format!("Unknown engine: {}", other), + format!("Unknown engine: {other}"), )); } }; diff --git a/rust/crates/openjarvis-python/src/scheduler.rs b/rust/crates/openjarvis-python/src/scheduler.rs index 8f6e40dd..1f7a33d5 100644 --- a/rust/crates/openjarvis-python/src/scheduler.rs +++ b/rust/crates/openjarvis-python/src/scheduler.rs @@ -20,8 +20,7 @@ impl PySchedulerStore { fn create_task(&self, name: &str, schedule_type: &str, schedule_value: &str) -> PyResult { let st = openjarvis_scheduler::ScheduleType::parse(schedule_type).ok_or_else(|| { PyErr::new::(format!( - "invalid schedule_type '{}', expected cron/interval/once", - schedule_type + "invalid schedule_type '{schedule_type}', expected cron/interval/once" )) })?; let task = self.inner.create_task(name, st, schedule_value); @@ -41,8 +40,7 @@ impl PySchedulerStore { fn update_status(&self, id: &str, status: &str) -> PyResult { let s = openjarvis_scheduler::TaskStatus::parse(status).ok_or_else(|| { PyErr::new::(format!( - "invalid status '{}', expected active/paused/cancelled/completed", - status + "invalid status '{status}', expected active/paused/cancelled/completed" )) })?; Ok(self.inner.update_status(id, s)) diff --git a/rust/crates/openjarvis-python/src/storage.rs b/rust/crates/openjarvis-python/src/storage.rs index 5a5b7502..332aff2a 100644 --- a/rust/crates/openjarvis-python/src/storage.rs +++ b/rust/crates/openjarvis-python/src/storage.rs @@ -266,8 +266,7 @@ impl PyHybridMemory { } other => { return Err(PyErr::new::(format!( - "Unknown backend key: {}. Supported: sqlite, bm25, faiss, colbert", - other + "Unknown backend key: {other}. Supported: sqlite, bm25, faiss, colbert" ))); } }; diff --git a/rust/crates/openjarvis-security/src/audit.rs b/rust/crates/openjarvis-security/src/audit.rs index 7df2a8d0..99f3d231 100644 --- a/rust/crates/openjarvis-security/src/audit.rs +++ b/rust/crates/openjarvis-security/src/audit.rs @@ -303,7 +303,7 @@ mod tests { event_type: SecurityEventType::SecretDetected, timestamp: 1000.0 + i as f64, findings: vec![], - content_preview: format!("event {}", i), + content_preview: format!("event {i}"), action_taken: "warn".into(), }; logger.log(&event).unwrap(); diff --git a/rust/crates/openjarvis-security/src/ssrf.rs b/rust/crates/openjarvis-security/src/ssrf.rs index 20ec58ac..4ca5fee4 100644 --- a/rust/crates/openjarvis-security/src/ssrf.rs +++ b/rust/crates/openjarvis-security/src/ssrf.rs @@ -135,14 +135,13 @@ pub fn check_ssrf(url_str: &str) -> Option { if BLOCKED_HOSTS.contains(canonical_host.as_str()) { return Some(format!( - "Blocked host: {} (cloud metadata endpoint)", - canonical_host + "Blocked host: {canonical_host} (cloud metadata endpoint)" )); } if let Some(ip) = literal_ip { if is_private_ip(&ip) { - return Some(format!("URL resolves to private IP: {}", ip)); + return Some(format!("URL resolves to private IP: {ip}")); } return None; } @@ -153,7 +152,7 @@ pub fn check_ssrf(url_str: &str) -> Option { _ => 80, }); - let addr_str = format!("{}:{}", canonical_host, port); + let addr_str = format!("{canonical_host}:{port}"); if let Ok(addrs) = addr_str.to_socket_addrs() { for addr in addrs { if is_private_ip(&addr.ip()) { @@ -207,7 +206,7 @@ mod tests { fn test_ipv4_mapped_ipv6_rfc1918_is_private() { for s in ["::ffff:10.0.0.1", "::ffff:172.16.0.1", "::ffff:192.168.1.1"] { let v6: Ipv6Addr = s.parse().unwrap(); - assert!(is_private_ip(&IpAddr::V6(v6)), "{} should be private", s); + assert!(is_private_ip(&IpAddr::V6(v6)), "{s} should be private"); } } @@ -244,7 +243,7 @@ mod tests { "http://[::ffff:172.16.0.1]/", ] { let result = check_ssrf(url); - assert!(result.is_some(), "{} must be blocked", url); + assert!(result.is_some(), "{url} must be blocked"); } } diff --git a/rust/crates/openjarvis-sessions/src/lib.rs b/rust/crates/openjarvis-sessions/src/lib.rs index f40c7339..aa894acf 100644 --- a/rust/crates/openjarvis-sessions/src/lib.rs +++ b/rust/crates/openjarvis-sessions/src/lib.rs @@ -230,7 +230,7 @@ impl SessionStore { params![session_id, remove_up_to as i64], ); - let summary = format!("[consolidated {} earlier messages]", remove_up_to); + let summary = format!("[consolidated {remove_up_to} earlier messages]"); let now = now_secs(); let _ = self.conn.execute( "INSERT INTO session_messages (session_id, role, content, channel, timestamp) @@ -292,15 +292,13 @@ impl SessionStore { let cutoff = now_secs() - self.max_age_hours * 3600.0; format!( "SELECT session_id FROM sessions - WHERE last_activity >= {} - ORDER BY last_activity DESC LIMIT {}", - cutoff, limit + WHERE last_activity >= {cutoff} + ORDER BY last_activity DESC LIMIT {limit}" ) } else { format!( "SELECT session_id FROM sessions - ORDER BY last_activity DESC LIMIT {}", - limit + ORDER BY last_activity DESC LIMIT {limit}" ) }; @@ -356,7 +354,7 @@ impl SessionStore { params![checkpoint_id, session_id], |row| Ok((row.get(0)?, row.get(1)?)), ) - .map_err(|e| format!("Checkpoint not found: {}", e))?; + .map_err(|e| format!("Checkpoint not found: {e}"))?; let deleted: usize = self .conn @@ -573,7 +571,7 @@ mod tests { for i in 0..10 { store - .save_message(&s.session_id, "user", &format!("msg {}", i), "irc") + .save_message(&s.session_id, "user", &format!("msg {i}"), "irc") .unwrap(); } diff --git a/rust/crates/openjarvis-tools/src/builtin/calculator.rs b/rust/crates/openjarvis-tools/src/builtin/calculator.rs index f31ac28a..5c2618c3 100644 --- a/rust/crates/openjarvis-tools/src/builtin/calculator.rs +++ b/rust/crates/openjarvis-tools/src/builtin/calculator.rs @@ -48,7 +48,7 @@ impl BaseTool for CalculatorTool { Ok(result) => Ok(ToolResult::success("calculator", result.to_string())), Err(e) => Ok(ToolResult::failure( "calculator", - format!("Error evaluating '{}': {}", expression, e), + format!("Error evaluating '{expression}': {e}"), )), } } diff --git a/rust/crates/openjarvis-tools/src/builtin/file_tools.rs b/rust/crates/openjarvis-tools/src/builtin/file_tools.rs index eca0cfc8..60bcfe8e 100644 --- a/rust/crates/openjarvis-tools/src/builtin/file_tools.rs +++ b/rust/crates/openjarvis-tools/src/builtin/file_tools.rs @@ -63,7 +63,7 @@ impl BaseTool for FileReadTool { if is_sensitive_file(path) { return Ok(ToolResult::failure( "file_read", - format!("Access denied: '{}' is a sensitive file", path_str), + format!("Access denied: '{path_str}' is a sensitive file"), )); } @@ -71,7 +71,7 @@ impl BaseTool for FileReadTool { Ok(content) => Ok(ToolResult::success("file_read", content)), Err(e) => Ok(ToolResult::failure( "file_read", - format!("Error reading '{}': {}", path_str, e), + format!("Error reading '{path_str}': {e}"), )), } } @@ -94,7 +94,7 @@ impl BaseTool for FileWriteTool { if is_sensitive_file(path) { return Ok(ToolResult::failure( "file_write", - format!("Access denied: '{}' is a sensitive file", path_str), + format!("Access denied: '{path_str}' is a sensitive file"), )); } @@ -103,7 +103,7 @@ impl BaseTool for FileWriteTool { if let Err(e) = std::fs::create_dir_all(parent) { return Ok(ToolResult::failure( "file_write", - format!("Error creating directory: {}", e), + format!("Error creating directory: {e}"), )); } } @@ -116,7 +116,7 @@ impl BaseTool for FileWriteTool { )), Err(e) => Ok(ToolResult::failure( "file_write", - format!("Error writing '{}': {}", path_str, e), + format!("Error writing '{path_str}': {e}"), )), } } diff --git a/rust/crates/openjarvis-tools/src/builtin/git_tools.rs b/rust/crates/openjarvis-tools/src/builtin/git_tools.rs index 192c157f..da7dab8d 100644 --- a/rust/crates/openjarvis-tools/src/builtin/git_tools.rs +++ b/rust/crates/openjarvis-tools/src/builtin/git_tools.rs @@ -21,7 +21,7 @@ fn run_git(args: &[&str], cwd: Option<&str>) -> Result { Err(String::from_utf8_lossy(&output.stderr).to_string()) } } - Err(e) => Err(format!("Failed to run git: {}", e)), + Err(e) => Err(format!("Failed to run git: {e}")), } } @@ -84,7 +84,7 @@ impl BaseTool for GitLogTool { fn execute(&self, params: &Value) -> Result { let cwd = params["cwd"].as_str(); let n = params["n"].as_i64().unwrap_or(10); - match run_git(&["log", "--oneline", &format!("-{}", n)], cwd) { + match run_git(&["log", "--oneline", &format!("-{n}")], cwd) { Ok(output) => Ok(ToolResult::success("git_log", output)), Err(e) => Ok(ToolResult::failure("git_log", e)), } diff --git a/rust/crates/openjarvis-tools/src/builtin/http_tools.rs b/rust/crates/openjarvis-tools/src/builtin/http_tools.rs index 8b27a88f..31ce5f7d 100644 --- a/rust/crates/openjarvis-tools/src/builtin/http_tools.rs +++ b/rust/crates/openjarvis-tools/src/builtin/http_tools.rs @@ -83,7 +83,7 @@ impl BaseTool for HttpRequestTool { } else { body }; - let content = format!("Status: {}\n{}", status, truncated); + let content = format!("Status: {status}\n{truncated}"); if status < 400 { Ok(ToolResult::success("http_request", content)) } else { @@ -92,7 +92,7 @@ impl BaseTool for HttpRequestTool { } Err(e) => Ok(ToolResult::failure( "http_request", - format!("Request failed: {}", e), + format!("Request failed: {e}"), )), } } diff --git a/rust/crates/openjarvis-tools/src/builtin/shell.rs b/rust/crates/openjarvis-tools/src/builtin/shell.rs index f5aa795b..a7bb6330 100644 --- a/rust/crates/openjarvis-tools/src/builtin/shell.rs +++ b/rust/crates/openjarvis-tools/src/builtin/shell.rs @@ -61,8 +61,7 @@ impl BaseTool for ShellExecTool { let exit_code = output.status.code().unwrap_or(-1); let content = format!( - "Exit code: {}\n--- stdout ---\n{}\n--- stderr ---\n{}", - exit_code, stdout, stderr + "Exit code: {exit_code}\n--- stdout ---\n{stdout}\n--- stderr ---\n{stderr}" ); if output.status.success() { @@ -73,7 +72,7 @@ impl BaseTool for ShellExecTool { } Err(e) => Ok(ToolResult::failure( "shell_exec", - format!("Failed to execute: {}", e), + format!("Failed to execute: {e}"), )), } } diff --git a/rust/crates/openjarvis-tools/src/executor.rs b/rust/crates/openjarvis-tools/src/executor.rs index 37a87c61..fedebd32 100644 --- a/rust/crates/openjarvis-tools/src/executor.rs +++ b/rust/crates/openjarvis-tools/src/executor.rs @@ -66,7 +66,7 @@ impl ToolExecutor { if !policy.check(aid, cap, "") { return Err(OpenJarvisError::Tool(ToolError::CapabilityDenied( aid.to_string(), - format!("{} (tool: {})", cap, tool_name), + format!("{cap} (tool: {tool_name})"), ))); } } diff --git a/rust/crates/openjarvis-tools/src/storage/knowledge_graph.rs b/rust/crates/openjarvis-tools/src/storage/knowledge_graph.rs index 1919a6fa..eabd3f4a 100644 --- a/rust/crates/openjarvis-tools/src/storage/knowledge_graph.rs +++ b/rust/crates/openjarvis-tools/src/storage/knowledge_graph.rs @@ -170,7 +170,7 @@ impl MemoryBackend for KnowledgeGraphMemory { top_k: usize, ) -> Result, OpenJarvisError> { let conn = self.conn.lock(); - let pattern = format!("%{}%", query); + let pattern = format!("%{query}%"); let mut stmt = conn .prepare( "SELECT name, entity_type, properties diff --git a/rust/crates/openjarvis-traces/src/store.rs b/rust/crates/openjarvis-traces/src/store.rs index 60506f84..fe7faaf1 100644 --- a/rust/crates/openjarvis-traces/src/store.rs +++ b/rust/crates/openjarvis-traces/src/store.rs @@ -233,8 +233,8 @@ mod tests { let store = TraceStore::in_memory().unwrap(); for i in 0..5 { let trace = Trace { - trace_id: format!("t{}", i), - query: format!("query {}", i), + trace_id: format!("t{i}"), + query: format!("query {i}"), ..Default::default() }; store.save(&trace).unwrap(); diff --git a/rust/rust-toolchain.toml b/rust/rust-toolchain.toml new file mode 100644 index 00000000..b6a8a616 --- /dev/null +++ b/rust/rust-toolchain.toml @@ -0,0 +1,10 @@ +# Pin the Rust toolchain for the openjarvis_rust workspace. +# +# The workspace requires Rust >= 1.88: rig-core uses let-chains and +# openjarvis-skills uses `is_multiple_of`, both stabilized in 1.88. On older +# stable toolchains the build fails with cryptic E0658 errors deep inside a +# transitive dependency (see #252). Pinning here makes rustup install/select a +# compatible toolchain automatically and gives a clear requirement up front. +[toolchain] +channel = "1.88" +components = ["rustfmt", "clippy"]