Skip to main content

crabtalk_runtime/
host.rs

1//! Host — trait for server-specific tool dispatch.
2//!
3//! The runtime crate defines this trait. The daemon implements it to provide
4//! `ask_user`, `delegate`, and per-session CWD resolution. Embedded users
5//! get [`NoHost`] with no-op defaults.
6
7use std::path::PathBuf;
8
9/// Trait for server-specific tool dispatch that the runtime cannot handle locally.
10pub trait Host: Send + Sync + Clone {
11    /// Handle `ask_user` — block until user replies.
12    fn dispatch_ask_user(
13        &self,
14        args: &str,
15        session_id: Option<u64>,
16    ) -> impl std::future::Future<Output = String> + Send {
17        let _ = (args, session_id);
18        async { "ask_user is not available in this runtime mode".to_owned() }
19    }
20
21    /// Handle `delegate` — spawn sub-agent tasks.
22    fn dispatch_delegate(
23        &self,
24        args: &str,
25        agent: &str,
26    ) -> impl std::future::Future<Output = String> + Send {
27        let _ = (args, agent);
28        async { "delegate is not available in this runtime mode".to_owned() }
29    }
30
31    /// Resolve the working directory for a session.
32    /// Returns `None` to fall back to the runtime's base cwd.
33    fn session_cwd(&self, _session_id: u64) -> Option<PathBuf> {
34        None
35    }
36
37    /// Called when an agent event occurs. The daemon uses this to broadcast
38    /// protobuf events to console subscribers. Default: no-op.
39    fn on_agent_event(&self, _agent: &str, _session_id: u64, _event: &wcore::AgentEvent) {}
40
41    /// Deliver a user reply to a pending `ask_user` tool call.
42    /// Returns `true` if a pending ask was found and resolved.
43    fn reply_to_ask(
44        &self,
45        _session: u64,
46        _content: String,
47    ) -> impl std::future::Future<Output = anyhow::Result<bool>> + Send {
48        async { Ok(false) }
49    }
50
51    /// Set the working directory override for a session.
52    fn set_session_cwd(
53        &self,
54        _session: u64,
55        _cwd: PathBuf,
56    ) -> impl std::future::Future<Output = ()> + Send {
57        async {}
58    }
59
60    /// Clear all per-session state (pending asks, CWD overrides).
61    fn clear_session_state(&self, _session: u64) -> impl std::future::Future<Output = ()> + Send {
62        async {}
63    }
64
65    /// Subscribe to agent events. Returns `None` if event broadcasting
66    /// is not supported by this host.
67    fn subscribe_events(
68        &self,
69    ) -> Option<tokio::sync::broadcast::Receiver<wcore::protocol::message::AgentEventMsg>> {
70        None
71    }
72
73    /// Handle a tool call not matched by the built-in dispatch table.
74    /// Downstream hosts override this to inject private tools.
75    fn dispatch_custom_tool(
76        &self,
77        name: &str,
78        _args: &str,
79        _agent: &str,
80        _session_id: Option<u64>,
81    ) -> impl std::future::Future<Output = String> + Send {
82        async move { format!("tool not available: {name}") }
83    }
84}
85
86/// No-op host for embedded use.
87#[derive(Clone)]
88pub struct NoHost;
89
90impl Host for NoHost {}