diff options
Diffstat (limited to 'crates/asist-app/src/registry.rs')
| -rw-r--r-- | crates/asist-app/src/registry.rs | 67 |
1 files changed, 46 insertions, 21 deletions
diff --git a/crates/asist-app/src/registry.rs b/crates/asist-app/src/registry.rs index 13bbb75..a3a10ed 100644 --- a/crates/asist-app/src/registry.rs +++ b/crates/asist-app/src/registry.rs @@ -8,11 +8,12 @@ use std::sync::Arc; use std::time::Duration; -use asist_core::config::{CameraConfig, Config, SearchConfig}; +use asist_core::config::{self as cfg, Config, SearchConfig}; use asist_core::tools::ToolRegistry; use asist_llm::LlmClient; -use asist_tools::camera::CaptureConfig; -use asist_tools::{Camera, SearchBackend, WebSearch}; +use asist_tools::{ + Camera, CameraConfig, Screen, ScreenConfig, SearchBackend, VisionTool, WebSearch, +}; /// Lo que no se pudo activar y por qué, para decírselo al usuario al arrancar /// en vez de dejarlo en silencio. @@ -38,13 +39,16 @@ pub fn build(config: &Config, llm: &Arc<LlmClient>) -> (ToolRegistry, Vec<Skippe }), } - match camera_tool(&config.camera, llm) { - Ok(Some(tool)) => registry.register(Arc::new(tool)), - Ok(None) => {} - Err(reason) => skipped.push(Skipped { - tool: "mirar_por_la_camara", - reason, - }), + // Las dos que ven comparten forma, así que se registran igual. + for (result, tool) in [ + (camera_tool(&config.camera, llm), "mirar_por_la_camara"), + (screen_tool(&config.screen, llm), "mirar_la_pantalla"), + ] { + match result { + Ok(Some(vision)) => registry.register(Arc::new(vision)), + Ok(None) => {} + Err(reason) => skipped.push(Skipped { tool, reason }), + } } (registry, skipped) @@ -98,25 +102,46 @@ fn search_tool(config: &SearchConfig) -> Result<Option<WebSearch>, String> { ))) } -fn camera_tool(config: &CameraConfig, llm: &Arc<LlmClient>) -> Result<Option<Camera>, String> { +fn camera_tool( + config: &cfg::CameraConfig, + llm: &Arc<LlmClient>, +) -> Result<Option<VisionTool>, String> { if !config.enabled { return Ok(None); } - let capture = CaptureConfig { + let source = Camera::new(CameraConfig { device: config.device.clone(), width: config.width, height: config.height, warmup_frames: config.warmup_frames, timeout: Duration::from_secs(config.timeout_secs), save_dir: (!config.save_dir.is_empty()).then(|| config.save_dir.clone().into()), - }; - // Registrar una herramienta que va a fallar siempre es peor que no tenerla: - // el modelo la llamaría, se comería el error y gastaría un turno entero. - if !Camera::available(&capture) { - return Err(format!( - "no existe {}; comprueba con «v4l2-ctl --list-devices»", - capture.device.display() - )); + }); + finish(VisionTool::camera(Box::new(source), Arc::clone(llm))) +} + +fn screen_tool( + config: &cfg::ScreenConfig, + llm: &Arc<LlmClient>, +) -> Result<Option<VisionTool>, String> { + if !config.enabled { + return Ok(None); + } + let source = Screen::new(ScreenConfig { + command: config.command.clone(), + width: config.width, + output: config.output.clone(), + timeout: Duration::from_secs(config.timeout_secs), + save_dir: (!config.save_dir.is_empty()).then(|| config.save_dir.clone().into()), + }); + finish(VisionTool::screen(Box::new(source), Arc::clone(llm))) +} + +/// Registrar una herramienta que va a fallar siempre es peor que no tenerla: +/// el modelo la llamaría, se comería el error y gastaría un turno entero. +fn finish(tool: VisionTool) -> Result<Option<VisionTool>, String> { + match tool.available() { + Ok(()) => Ok(Some(tool)), + Err(err) => Err(err.to_string()), } - Ok(Some(Camera::new(capture, Arc::clone(llm)))) } |