Skip to main content

monoloop_loop/
tools.rs

1//! Abstract tool runtime + no-op runtime for empty registry.
2
3use monoloop_contracts::ToolExecutionId;
4use tokio::sync::oneshot;
5
6/// Start request for a tool execution (never called with EmptyToolRegistry).
7#[derive(Clone, Debug)]
8pub struct StartToolExecution {
9    /// Execution id allocated by The Loop.
10    pub execution_id: ToolExecutionId,
11    /// Tool action id from the canonical unit.
12    pub tool_action_id: String,
13    /// Tool name.
14    pub tool_name: String,
15    /// Complete payload.
16    pub request_payload: String,
17    /// Request generation that triggered dispatch.
18    pub request_generation: u64,
19}
20
21/// Runtime error.
22#[derive(Clone, Debug, thiserror::Error)]
23#[error("tool runtime: {0}")]
24pub struct ToolRuntimeError(pub String);
25
26/// Terminal from a host/runtime execution mapped for Loop outbound emission.
27#[derive(Clone, Debug)]
28pub struct ToolRuntimeTerminal {
29    /// Outcome for OutboundToolResult.
30    pub outcome: monoloop_contracts::OutboundToolOutcome,
31    /// Bounded payload.
32    pub payload: String,
33}
34
35/// Handle for a running tool.
36#[derive(Debug)]
37pub struct ToolExecutionHandle {
38    /// Execution id.
39    pub execution_id: ToolExecutionId,
40    /// Optional oneshot completion (present for real runtimes).
41    pub completion: Option<oneshot::Receiver<ToolRuntimeTerminal>>,
42}
43
44/// Abstract tool runtime.
45pub trait ToolRuntime: Send + Sync {
46    /// Start a tool execution. Must not be called when registry always unavailable.
47    fn start(&self, request: StartToolExecution) -> Result<ToolExecutionHandle, ToolRuntimeError>;
48}
49
50/// Runtime that asserts it is never started (pairs with EmptyToolRegistry).
51#[derive(Clone, Debug, Default)]
52pub struct NoToolRuntime;
53
54impl NoToolRuntime {
55    /// Create.
56    pub fn new() -> Self {
57        Self
58    }
59}
60
61impl ToolRuntime for NoToolRuntime {
62    fn start(&self, _request: StartToolExecution) -> Result<ToolExecutionHandle, ToolRuntimeError> {
63        Err(ToolRuntimeError(
64            "NoToolRuntime.start must never be called with EmptyToolRegistry".into(),
65        ))
66    }
67}