pub mod agent; pub mod browser; pub mod compat; pub mod config; pub mod generated_scene; pub mod llm; pub mod pipe; pub mod runtime; pub mod scene_contract; pub mod security; pub mod service; pub use browser::ws_probe::{parse_probe_args, run_probe_script, ProbeError, ProbeOutcome}; use std::path::PathBuf; use std::sync::Arc; use std::time::Duration; use agent::{handle_browser_message_with_context, AgentRuntimeContext}; use pipe::{perform_handshake, BrowserPipeTool, PipeError, StdioTransport, Transport}; use security::MacPolicy; fn default_rules_path_from_executable(executable_path: PathBuf) -> PathBuf { executable_path .parent() .map(|dir| dir.join("resources").join("rules.json")) .unwrap_or_else(|| PathBuf::from("resources").join("rules.json")) } fn default_rules_path() -> PathBuf { std::env::current_exe() .map(default_rules_path_from_executable) .unwrap_or_else(|_| PathBuf::from("resources").join("rules.json")) } pub fn run() -> Result<(), PipeError> { let runtime_context = AgentRuntimeContext::from_process_args(std::env::args_os())?; let transport = Arc::new(StdioTransport::new(std::io::stdin(), std::io::stdout())); let handshake = perform_handshake(transport.as_ref(), Duration::from_secs(5))?; let mac_policy = MacPolicy::load_from_path(default_rules_path())?; let browser_tool = BrowserPipeTool::new(transport.clone(), mac_policy, handshake.session_key) .with_response_timeout(Duration::from_secs(30)); eprintln!("sgclaw ready: agent_id={}", handshake.agent_id); loop { match transport.recv_timeout(Duration::from_secs(3600)) { Ok(message) => { handle_browser_message_with_context( transport.as_ref(), &browser_tool, &runtime_context, message, )?; } Err(PipeError::Timeout) => continue, Err(PipeError::PipeClosed) => return Ok(()), Err(err) => return Err(err), } } } #[cfg(test)] mod tests { use super::default_rules_path_from_executable; use std::path::PathBuf; #[test] fn default_rules_path_uses_executable_directory_instead_of_cwd() { let executable_path = PathBuf::from("/tmp/out/KylinRelease/sgclaw"); let resolved = default_rules_path_from_executable(executable_path); assert_eq!( resolved, PathBuf::from("/tmp/out/KylinRelease/resources/rules.json") ); } }