Skip to content

Commit 0c73263

Browse files
committed
fix: resolve TypeScript and Rust build errors and warnings
- Fixed TypeScript errors in ClaudeCodeSession.tsx: - Removed unused imports (Square, PreviewPromptDialog, etc.) - Removed unused handleOpenPreview function - Fixed unused detectedUrl state variable - Fixed TypeScript error in StreamMessage.tsx: - Removed unused useMemo import - Fixed TypeScript errors in ToolWidgets.tsx: - Prefixed unused result props with underscore in multiple widgets - Fixed Rust warnings: - Removed unused imports in commands modules - Prefixed unused variables with underscore - Added #[allow(dead_code)] for API methods intended for future use Closes #31 Closes #23 Closes #21 Closes #22
1 parent c52c29e commit 0c73263

9 files changed

Lines changed: 76 additions & 339 deletions

File tree

src-tauri/src/checkpoint/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,11 +244,13 @@ impl CheckpointPaths {
244244
self.checkpoint_dir(checkpoint_id).join("messages.jsonl")
245245
}
246246

247+
#[allow(dead_code)]
247248
pub fn file_snapshot_path(&self, _checkpoint_id: &str, file_hash: &str) -> PathBuf {
248249
// In content-addressable storage, files are stored by hash in the content pool
249250
self.files_dir.join("content_pool").join(file_hash)
250251
}
251252

253+
#[allow(dead_code)]
252254
pub fn file_reference_path(&self, checkpoint_id: &str, safe_filename: &str) -> PathBuf {
253255
// References are stored per checkpoint
254256
self.files_dir.join("refs").join(checkpoint_id).join(format!("{}.json", safe_filename))

src-tauri/src/checkpoint/state.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ impl CheckpointState {
8787
/// Gets an existing CheckpointManager for a session
8888
///
8989
/// Returns None if no manager exists for the session
90+
#[allow(dead_code)]
9091
pub async fn get_manager(&self, session_id: &str) -> Option<Arc<CheckpointManager>> {
9192
let managers = self.managers.read().await;
9293
managers.get(session_id).map(Arc::clone)
@@ -103,6 +104,7 @@ impl CheckpointState {
103104
/// Clears all managers
104105
///
105106
/// This is useful for cleanup during application shutdown
107+
#[allow(dead_code)]
106108
pub async fn clear_all(&self) {
107109
let mut managers = self.managers.write().await;
108110
managers.clear();
@@ -121,11 +123,13 @@ impl CheckpointState {
121123
}
122124

123125
/// Checks if a session has an active manager
126+
#[allow(dead_code)]
124127
pub async fn has_active_manager(&self, session_id: &str) -> bool {
125128
self.get_manager(session_id).await.is_some()
126129
}
127130

128131
/// Clears all managers and returns the count that were cleared
132+
#[allow(dead_code)]
129133
pub async fn clear_all_and_count(&self) -> usize {
130134
let count = self.active_count().await;
131135
self.clear_all().await;

src-tauri/src/commands/agents.rs

Lines changed: 28 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
use crate::sandbox::profile::{ProfileBuilder, SandboxRule};
2-
use crate::sandbox::executor::{SerializedProfile, SerializedOperation};
1+
use crate::sandbox::profile::ProfileBuilder;
32
use anyhow::Result;
43
use chrono;
54
use log::{debug, error, info, warn};
@@ -8,112 +7,15 @@ use serde::{Deserialize, Serialize};
87
use serde_json::Value as JsonValue;
98
use std::path::PathBuf;
109
use std::process::Stdio;
11-
use std::sync::{Arc, Mutex};
10+
use std::sync::Mutex;
1211
use tauri::{AppHandle, Manager, State, Emitter};
1312
use tokio::io::{AsyncBufReadExt, BufReader};
1413
use tokio::process::Command;
1514

1615
/// Finds the full path to the claude binary
1716
/// This is necessary because macOS apps have a limited PATH environment
1817
fn find_claude_binary(app_handle: &AppHandle) -> Result<String, String> {
19-
log::info!("Searching for claude binary...");
20-
21-
// First check if we have a stored path in the database
22-
if let Ok(app_data_dir) = app_handle.path().app_data_dir() {
23-
let db_path = app_data_dir.join("agents.db");
24-
if db_path.exists() {
25-
if let Ok(conn) = rusqlite::Connection::open(&db_path) {
26-
if let Ok(stored_path) = conn.query_row(
27-
"SELECT value FROM app_settings WHERE key = 'claude_binary_path'",
28-
[],
29-
|row| row.get::<_, String>(0),
30-
) {
31-
log::info!("Found stored claude path in database: {}", stored_path);
32-
let path_buf = std::path::PathBuf::from(&stored_path);
33-
if path_buf.exists() && path_buf.is_file() {
34-
return Ok(stored_path);
35-
} else {
36-
log::warn!("Stored claude path no longer exists: {}", stored_path);
37-
}
38-
}
39-
}
40-
}
41-
}
42-
43-
// Common installation paths for claude
44-
let mut paths_to_check: Vec<String> = vec![
45-
"/usr/local/bin/claude".to_string(),
46-
"/opt/homebrew/bin/claude".to_string(),
47-
"/usr/bin/claude".to_string(),
48-
"/bin/claude".to_string(),
49-
];
50-
51-
// Also check user-specific paths
52-
if let Ok(home) = std::env::var("HOME") {
53-
paths_to_check.extend(vec![
54-
format!("{}/.claude/local/claude", home),
55-
format!("{}/.local/bin/claude", home),
56-
format!("{}/.npm-global/bin/claude", home),
57-
format!("{}/.yarn/bin/claude", home),
58-
format!("{}/.bun/bin/claude", home),
59-
format!("{}/bin/claude", home),
60-
// Check common node_modules locations
61-
format!("{}/node_modules/.bin/claude", home),
62-
format!("{}/.config/yarn/global/node_modules/.bin/claude", home),
63-
]);
64-
}
65-
66-
// Check each path
67-
for path in paths_to_check {
68-
let path_buf = std::path::PathBuf::from(&path);
69-
if path_buf.exists() && path_buf.is_file() {
70-
log::info!("Found claude at: {}", path);
71-
return Ok(path);
72-
}
73-
}
74-
75-
// In production builds, skip the 'which' command as it's blocked by Tauri
76-
#[cfg(not(debug_assertions))]
77-
{
78-
log::warn!("Cannot use 'which' command in production build, checking if claude is in PATH");
79-
// In production, just return "claude" and let the execution fail with a proper error
80-
// if it's not actually available. The user can then set the path manually.
81-
return Ok("claude".to_string());
82-
}
83-
84-
// Only try 'which' in development builds
85-
#[cfg(debug_assertions)]
86-
{
87-
// Fallback: try using 'which' command
88-
log::info!("Trying 'which claude' to find binary...");
89-
if let Ok(output) = std::process::Command::new("which")
90-
.arg("claude")
91-
.output()
92-
{
93-
if output.status.success() {
94-
let path = String::from_utf8_lossy(&output.stdout).trim().to_string();
95-
if !path.is_empty() {
96-
log::info!("'which' found claude at: {}", path);
97-
return Ok(path);
98-
}
99-
}
100-
}
101-
102-
// Additional fallback: check if claude is in the current PATH
103-
// This might work in dev mode
104-
if let Ok(output) = std::process::Command::new("claude")
105-
.arg("--version")
106-
.output()
107-
{
108-
if output.status.success() {
109-
log::info!("claude is available in PATH (dev mode?)");
110-
return Ok("claude".to_string());
111-
}
112-
}
113-
}
114-
115-
log::error!("Could not find claude binary in any common location");
116-
Err("Claude Code not found. Please ensure it's installed and in one of these locations: /usr/local/bin, /opt/homebrew/bin, ~/.claude/local, ~/.local/bin, or in your PATH".to_string())
18+
crate::claude_binary::find_claude_binary(app_handle)
11719
}
11820

11921
/// Represents a CC Agent stored in the database
@@ -1896,20 +1798,36 @@ pub async fn set_claude_binary_path(db: State<'_, AgentDb>, path: String) -> Res
18961798
/// Helper function to create a tokio Command with proper environment variables
18971799
/// This ensures commands like Claude can find Node.js and other dependencies
18981800
fn create_command_with_env(program: &str) -> Command {
1899-
let mut cmd = Command::new(program);
1900-
1901-
// Inherit essential environment variables from parent process
1801+
// Convert std::process::Command to tokio::process::Command
1802+
let _std_cmd = crate::claude_binary::create_command_with_env(program);
1803+
1804+
// Create a new tokio Command from the program path
1805+
let mut tokio_cmd = Command::new(program);
1806+
1807+
// Copy over all environment variables from the std::process::Command
1808+
// This is a workaround since we can't directly convert between the two types
19021809
for (key, value) in std::env::vars() {
19031810
if key == "PATH" || key == "HOME" || key == "USER"
19041811
|| key == "SHELL" || key == "LANG" || key == "LC_ALL" || key.starts_with("LC_")
19051812
|| key == "NODE_PATH" || key == "NVM_DIR" || key == "NVM_BIN"
19061813
|| key == "HOMEBREW_PREFIX" || key == "HOMEBREW_CELLAR" {
1907-
cmd.env(&key, &value);
1814+
tokio_cmd.env(&key, &value);
1815+
}
1816+
}
1817+
1818+
// Add NVM support if the program is in an NVM directory
1819+
if program.contains("/.nvm/versions/node/") {
1820+
if let Some(node_bin_dir) = std::path::Path::new(program).parent() {
1821+
let current_path = std::env::var("PATH").unwrap_or_default();
1822+
let node_bin_str = node_bin_dir.to_string_lossy();
1823+
if !current_path.contains(&node_bin_str.as_ref()) {
1824+
let new_path = format!("{}:{}", node_bin_str, current_path);
1825+
tokio_cmd.env("PATH", new_path);
1826+
}
19081827
}
19091828
}
19101829

1911-
// Ensure PATH contains common Homebrew locations so that `/usr/bin/env node` resolves
1912-
// when the application is launched from the macOS GUI (PATH is very minimal there).
1830+
// Ensure PATH contains common Homebrew locations
19131831
if let Ok(existing_path) = std::env::var("PATH") {
19141832
let mut paths: Vec<&str> = existing_path.split(':').collect();
19151833
for p in ["/opt/homebrew/bin", "/usr/local/bin", "/usr/bin", "/bin"].iter() {
@@ -1918,13 +1836,12 @@ fn create_command_with_env(program: &str) -> Command {
19181836
}
19191837
}
19201838
let joined = paths.join(":");
1921-
cmd.env("PATH", joined);
1839+
tokio_cmd.env("PATH", joined);
19221840
} else {
1923-
// Fallback: set a reasonable default PATH
1924-
cmd.env("PATH", "/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin");
1841+
tokio_cmd.env("PATH", "/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin");
19251842
}
19261843

1927-
cmd
1844+
tokio_cmd
19281845
}
19291846

19301847
/// Import an agent from JSON data

src-tauri/src/commands/claude.rs

Lines changed: 21 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ use tauri::{AppHandle, Emitter, Manager};
99
use tokio::process::{Command, Child};
1010
use tokio::sync::Mutex;
1111
use std::sync::Arc;
12-
use crate::process::ProcessHandle;
13-
use crate::checkpoint::{CheckpointResult, CheckpointDiff, SessionTimeline, Checkpoint};
1412

1513
/// Global state to track current Claude process
1614
pub struct ClaudeProcessState {
@@ -131,104 +129,7 @@ pub struct FileEntry {
131129
/// Finds the full path to the claude binary
132130
/// This is necessary because macOS apps have a limited PATH environment
133131
fn find_claude_binary(app_handle: &AppHandle) -> Result<String, String> {
134-
log::info!("Searching for claude binary...");
135-
136-
// First check if we have a stored path in the database
137-
if let Ok(app_data_dir) = app_handle.path().app_data_dir() {
138-
let db_path = app_data_dir.join("agents.db");
139-
if db_path.exists() {
140-
if let Ok(conn) = rusqlite::Connection::open(&db_path) {
141-
if let Ok(stored_path) = conn.query_row(
142-
"SELECT value FROM app_settings WHERE key = 'claude_binary_path'",
143-
[],
144-
|row| row.get::<_, String>(0),
145-
) {
146-
log::info!("Found stored claude path in database: {}", stored_path);
147-
let path_buf = PathBuf::from(&stored_path);
148-
if path_buf.exists() && path_buf.is_file() {
149-
return Ok(stored_path);
150-
} else {
151-
log::warn!("Stored claude path no longer exists: {}", stored_path);
152-
}
153-
}
154-
}
155-
}
156-
}
157-
158-
// Common installation paths for claude
159-
let mut paths_to_check: Vec<String> = vec![
160-
"/usr/local/bin/claude".to_string(),
161-
"/opt/homebrew/bin/claude".to_string(),
162-
"/usr/bin/claude".to_string(),
163-
"/bin/claude".to_string(),
164-
];
165-
166-
// Also check user-specific paths
167-
if let Ok(home) = std::env::var("HOME") {
168-
paths_to_check.extend(vec![
169-
format!("{}/.claude/local/claude", home),
170-
format!("{}/.local/bin/claude", home),
171-
format!("{}/.npm-global/bin/claude", home),
172-
format!("{}/.yarn/bin/claude", home),
173-
format!("{}/.bun/bin/claude", home),
174-
format!("{}/bin/claude", home),
175-
// Check common node_modules locations
176-
format!("{}/node_modules/.bin/claude", home),
177-
format!("{}/.config/yarn/global/node_modules/.bin/claude", home),
178-
]);
179-
}
180-
181-
// Check each path
182-
for path in paths_to_check {
183-
let path_buf = PathBuf::from(&path);
184-
if path_buf.exists() && path_buf.is_file() {
185-
log::info!("Found claude at: {}", path);
186-
return Ok(path);
187-
}
188-
}
189-
190-
// In production builds, skip the 'which' command as it's blocked by Tauri
191-
#[cfg(not(debug_assertions))]
192-
{
193-
log::warn!("Cannot use 'which' command in production build, checking if claude is in PATH");
194-
// In production, just return "claude" and let the execution fail with a proper error
195-
// if it's not actually available. The user can then set the path manually.
196-
return Ok("claude".to_string());
197-
}
198-
199-
// Only try 'which' in development builds
200-
#[cfg(debug_assertions)]
201-
{
202-
// Fallback: try using 'which' command
203-
log::info!("Trying 'which claude' to find binary...");
204-
if let Ok(output) = std::process::Command::new("which")
205-
.arg("claude")
206-
.output()
207-
{
208-
if output.status.success() {
209-
let path = String::from_utf8_lossy(&output.stdout).trim().to_string();
210-
if !path.is_empty() {
211-
log::info!("'which' found claude at: {}", path);
212-
return Ok(path);
213-
}
214-
}
215-
}
216-
217-
// Additional fallback: check if claude is in the current PATH
218-
// This might work in dev mode
219-
if let Ok(output) = std::process::Command::new("claude")
220-
.arg("--version")
221-
.output()
222-
{
223-
if output.status.success() {
224-
log::info!("claude is available in PATH (dev mode?)");
225-
return Ok("claude".to_string());
226-
}
227-
}
228-
}
229-
230-
log::error!("Could not find claude binary in any common location");
231-
Err("Claude Code not found. Please ensure it's installed and in one of these locations: /usr/local/bin, /opt/homebrew/bin, ~/.claude/local, ~/.local/bin, or in your PATH".to_string())
132+
crate::claude_binary::find_claude_binary(app_handle)
232133
}
233134

234135
/// Gets the path to the ~/.claude directory
@@ -319,22 +220,36 @@ fn extract_first_user_message(jsonl_path: &PathBuf) -> (Option<String>, Option<S
319220
/// Helper function to create a tokio Command with proper environment variables
320221
/// This ensures commands like Claude can find Node.js and other dependencies
321222
fn create_command_with_env(program: &str) -> Command {
322-
let mut cmd = Command::new(program);
223+
// Convert std::process::Command to tokio::process::Command
224+
let _std_cmd = crate::claude_binary::create_command_with_env(program);
225+
226+
// Create a new tokio Command from the program path
227+
let mut tokio_cmd = Command::new(program);
323228

324-
// Inherit essential environment variables from parent process
325-
// This is crucial for commands like Claude that need to find Node.js
229+
// Copy over all environment variables
326230
for (key, value) in std::env::vars() {
327-
// Pass through PATH and other essential environment variables
328231
if key == "PATH" || key == "HOME" || key == "USER"
329232
|| key == "SHELL" || key == "LANG" || key == "LC_ALL" || key.starts_with("LC_")
330233
|| key == "NODE_PATH" || key == "NVM_DIR" || key == "NVM_BIN"
331234
|| key == "HOMEBREW_PREFIX" || key == "HOMEBREW_CELLAR" {
332235
log::debug!("Inheriting env var: {}={}", key, value);
333-
cmd.env(&key, &value);
236+
tokio_cmd.env(&key, &value);
237+
}
238+
}
239+
240+
// Add NVM support if the program is in an NVM directory
241+
if program.contains("/.nvm/versions/node/") {
242+
if let Some(node_bin_dir) = std::path::Path::new(program).parent() {
243+
let current_path = std::env::var("PATH").unwrap_or_default();
244+
let node_bin_str = node_bin_dir.to_string_lossy();
245+
if !current_path.contains(&node_bin_str.as_ref()) {
246+
let new_path = format!("{}:{}", node_bin_str, current_path);
247+
tokio_cmd.env("PATH", new_path);
248+
}
334249
}
335250
}
336251

337-
cmd
252+
tokio_cmd
338253
}
339254

340255
/// Lists all projects in the ~/.claude/projects directory

0 commit comments

Comments
 (0)