@@ -10,8 +10,7 @@ use std::io::{BufRead, BufReader};
1010use std:: process:: Stdio ;
1111use std:: sync:: Mutex ;
1212use tauri:: { AppHandle , Emitter , Manager , State } ;
13- use tauri_plugin_shell:: ShellExt ;
14- use tauri_plugin_shell:: process:: CommandEvent ;
13+ // Sidecar support removed; using system binary execution only
1514use tokio:: io:: { AsyncBufReadExt , BufReader as TokioBufReader } ;
1615use tokio:: process:: Command ;
1716
@@ -766,49 +765,20 @@ pub async fn execute_agent(
766765 "--dangerously-skip-permissions" . to_string( ) ,
767766 ] ;
768767
769- // Execute based on whether we should use sidecar or system binary
770- if should_use_sidecar ( & claude_path) {
771- spawn_agent_sidecar ( app, run_id, agent_id, agent. name . clone ( ) , args, project_path, task, execution_model, db, registry) . await
772- } else {
773- spawn_agent_system ( app, run_id, agent_id, agent. name . clone ( ) , claude_path, args, project_path, task, execution_model, db, registry) . await
774- }
775- }
776-
777- /// Determines whether to use sidecar or system binary execution for agents
778- fn should_use_sidecar ( claude_path : & str ) -> bool {
779- claude_path == "claude-code"
780- }
781-
782- /// Creates a sidecar command for agent execution
783- fn create_agent_sidecar_command (
784- app : & AppHandle ,
785- args : Vec < String > ,
786- project_path : & str ,
787- ) -> Result < tauri_plugin_shell:: process:: Command , String > {
788- let mut sidecar_cmd = app
789- . shell ( )
790- . sidecar ( "claude-code" )
791- . map_err ( |e| format ! ( "Failed to create sidecar command: {}" , e) ) ?;
792-
793- // Add all arguments
794- sidecar_cmd = sidecar_cmd. args ( args) ;
795-
796- // Set working directory
797- sidecar_cmd = sidecar_cmd. current_dir ( project_path) ;
798-
799- // Pass through proxy environment variables if they exist (only uppercase)
800- for ( key, value) in std:: env:: vars ( ) {
801- if key == "HTTP_PROXY"
802- || key == "HTTPS_PROXY"
803- || key == "NO_PROXY"
804- || key == "ALL_PROXY"
805- {
806- debug ! ( "Setting proxy env var for agent sidecar: {}={}" , key, value) ;
807- sidecar_cmd = sidecar_cmd. env ( & key, & value) ;
808- }
809- }
810-
811- Ok ( sidecar_cmd)
768+ // Always use system binary execution (sidecar removed)
769+ spawn_agent_system (
770+ app,
771+ run_id,
772+ agent_id,
773+ agent. name . clone ( ) ,
774+ claude_path,
775+ args,
776+ project_path,
777+ task,
778+ execution_model,
779+ db,
780+ registry,
781+ ) . await
812782}
813783
814784/// Creates a system binary command for agent execution
@@ -832,189 +802,6 @@ fn create_agent_system_command(
832802 cmd
833803}
834804
835- /// Spawn agent using sidecar command
836- async fn spawn_agent_sidecar (
837- app : AppHandle ,
838- run_id : i64 ,
839- agent_id : i64 ,
840- agent_name : String ,
841- args : Vec < String > ,
842- project_path : String ,
843- task : String ,
844- execution_model : String ,
845- db : State < ' _ , AgentDb > ,
846- registry : State < ' _ , crate :: process:: ProcessRegistryState > ,
847- ) -> Result < i64 , String > {
848- // Build the sidecar command
849- let sidecar_cmd = create_agent_sidecar_command ( & app, args, & project_path) ?;
850-
851- // Spawn the process
852- info ! ( "🚀 Spawning Claude sidecar process..." ) ;
853- let ( mut receiver, child) = sidecar_cmd. spawn ( ) . map_err ( |e| {
854- error ! ( "❌ Failed to spawn Claude sidecar process: {}" , e) ;
855- format ! ( "Failed to spawn Claude sidecar: {}" , e)
856- } ) ?;
857-
858- // Get the PID from child
859- let pid = child. pid ( ) ;
860- let now = chrono:: Utc :: now ( ) . to_rfc3339 ( ) ;
861- info ! ( "✅ Claude sidecar process spawned successfully with PID: {}" , pid) ;
862-
863- // Update the database with PID and status
864- {
865- let conn = db. 0 . lock ( ) . map_err ( |e| e. to_string ( ) ) ?;
866- conn. execute (
867- "UPDATE agent_runs SET status = 'running', pid = ?1, process_started_at = ?2 WHERE id = ?3" ,
868- params ! [ pid as i64 , now, run_id] ,
869- ) . map_err ( |e| e. to_string ( ) ) ?;
870- info ! ( "📝 Updated database with running status and PID" ) ;
871- }
872-
873- // Get app directory for database path
874- let app_dir = app
875- . path ( )
876- . app_data_dir ( )
877- . expect ( "Failed to get app data dir" ) ;
878- let db_path = app_dir. join ( "agents.db" ) ;
879-
880- // Shared state for collecting session ID and live output
881- let session_id = std:: sync:: Arc :: new ( Mutex :: new ( String :: new ( ) ) ) ;
882- let live_output = std:: sync:: Arc :: new ( Mutex :: new ( String :: new ( ) ) ) ;
883- let _start_time = std:: time:: Instant :: now ( ) ;
884-
885- // Register the process in the registry
886- registry
887- . 0
888- . register_sidecar_process (
889- run_id,
890- agent_id,
891- agent_name,
892- pid as u32 ,
893- project_path. clone ( ) ,
894- task. clone ( ) ,
895- execution_model. clone ( ) ,
896- )
897- . map_err ( |e| format ! ( "Failed to register sidecar process: {}" , e) ) ?;
898- info ! ( "📋 Registered sidecar process in registry" ) ;
899-
900- // Handle sidecar events
901- let app_handle = app. clone ( ) ;
902- let session_id_clone = session_id. clone ( ) ;
903- let live_output_clone = live_output. clone ( ) ;
904- let registry_clone = registry. 0 . clone ( ) ;
905- let first_output = std:: sync:: Arc :: new ( std:: sync:: atomic:: AtomicBool :: new ( false ) ) ;
906- let first_output_clone = first_output. clone ( ) ;
907- let db_path_for_sidecar = db_path. clone ( ) ;
908-
909- tokio:: spawn ( async move {
910- info ! ( "📖 Starting to read Claude sidecar events..." ) ;
911- let mut line_count = 0 ;
912-
913- while let Some ( event) = receiver. recv ( ) . await {
914- match event {
915- CommandEvent :: Stdout ( line_bytes) => {
916- let line = String :: from_utf8_lossy ( & line_bytes) ;
917- line_count += 1 ;
918-
919- // Log first output
920- if !first_output_clone. load ( std:: sync:: atomic:: Ordering :: Relaxed ) {
921- info ! (
922- "🎉 First output received from Claude sidecar process! Line: {}" ,
923- line
924- ) ;
925- first_output_clone. store ( true , std:: sync:: atomic:: Ordering :: Relaxed ) ;
926- }
927-
928- if line_count <= 5 {
929- info ! ( "sidecar stdout[{}]: {}" , line_count, line) ;
930- } else {
931- debug ! ( "sidecar stdout[{}]: {}" , line_count, line) ;
932- }
933-
934- // Store live output
935- if let Ok ( mut output) = live_output_clone. lock ( ) {
936- output. push_str ( & line) ;
937- output. push ( '\n' ) ;
938- }
939-
940- // Also store in process registry
941- let _ = registry_clone. append_live_output ( run_id, & line) ;
942-
943- // Extract session ID from JSONL output
944- if let Ok ( json) = serde_json:: from_str :: < JsonValue > ( & line) {
945- if json. get ( "type" ) . and_then ( |t| t. as_str ( ) ) == Some ( "system" ) &&
946- json. get ( "subtype" ) . and_then ( |s| s. as_str ( ) ) == Some ( "init" ) {
947- if let Some ( sid) = json. get ( "session_id" ) . and_then ( |s| s. as_str ( ) ) {
948- if let Ok ( mut current_session_id) = session_id_clone. lock ( ) {
949- if current_session_id. is_empty ( ) {
950- * current_session_id = sid. to_string ( ) ;
951- info ! ( "🔑 Extracted session ID: {}" , sid) ;
952-
953- // Update database immediately with session ID
954- if let Ok ( conn) = Connection :: open ( & db_path_for_sidecar) {
955- match conn. execute (
956- "UPDATE agent_runs SET session_id = ?1 WHERE id = ?2" ,
957- params ! [ sid, run_id] ,
958- ) {
959- Ok ( rows) => {
960- if rows > 0 {
961- info ! ( "✅ Updated agent run {} with session ID immediately" , run_id) ;
962- }
963- }
964- Err ( e) => {
965- error ! ( "❌ Failed to update session ID immediately: {}" , e) ;
966- }
967- }
968- }
969- }
970- }
971- }
972- }
973- }
974-
975- // Emit the line to the frontend
976- let _ = app_handle. emit ( & format ! ( "agent-output:{}" , run_id) , & line) ;
977- let _ = app_handle. emit ( "agent-output" , & line) ;
978- }
979- CommandEvent :: Stderr ( line_bytes) => {
980- let line = String :: from_utf8_lossy ( & line_bytes) ;
981- error ! ( "sidecar stderr: {}" , line) ;
982- let _ = app_handle. emit ( & format ! ( "agent-error:{}" , run_id) , & line) ;
983- let _ = app_handle. emit ( "agent-error" , & line) ;
984- }
985- CommandEvent :: Terminated ( payload) => {
986- info ! ( "Claude sidecar process terminated with code: {:?}" , payload. code) ;
987-
988- // Get the session ID
989- let extracted_session_id = if let Ok ( sid) = session_id. lock ( ) {
990- sid. clone ( )
991- } else {
992- String :: new ( )
993- } ;
994-
995- // Update database with completion
996- if let Ok ( conn) = Connection :: open ( & db_path) {
997- let _ = conn. execute (
998- "UPDATE agent_runs SET session_id = ?1, status = 'completed', completed_at = CURRENT_TIMESTAMP WHERE id = ?2" ,
999- params ! [ extracted_session_id, run_id] ,
1000- ) ;
1001- }
1002-
1003- let success = payload. code . unwrap_or ( 1 ) == 0 ;
1004- let _ = app. emit ( "agent-complete" , success) ;
1005- let _ = app. emit ( & format ! ( "agent-complete:{}" , run_id) , success) ;
1006- break ;
1007- }
1008- _ => { }
1009- }
1010- }
1011-
1012- info ! ( "📖 Finished reading Claude sidecar events. Total lines: {}" , line_count) ;
1013- } ) ;
1014-
1015- Ok ( run_id)
1016- }
1017-
1018805/// Spawn agent using system binary command
1019806async fn spawn_agent_system (
1020807 app : AppHandle ,
0 commit comments