Skip to main content

everruns_core/
background.rs

1// Background tool execution contracts.
2//
3// Decision: foreground tool execution remains the default. Tools opt into
4// detached execution with the `supports_background` hint plus a native
5// `BackgroundExecutableTool` implementation.
6
7use crate::error::Result;
8use crate::tools::ToolExecutionResult;
9use crate::traits::ToolContext;
10use async_trait::async_trait;
11use serde::{Deserialize, Serialize};
12use serde_json::Value;
13use std::sync::Arc;
14
15#[cfg(feature = "openapi")]
16use utoipa::ToSchema;
17
18/// Structured progress reported by background tools.
19#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
20#[cfg_attr(feature = "openapi", derive(ToSchema))]
21pub struct BackgroundProgress {
22    pub current: Option<u64>,
23    pub total: Option<u64>,
24    pub unit: Option<String>,
25    pub label: Option<String>,
26}
27
28/// Final result from a completed background tool.
29#[derive(Debug, Clone, Serialize, Deserialize)]
30pub struct BackgroundOutcome {
31    pub summary: String,
32    pub result: Value,
33    #[serde(default, skip_serializing_if = "Option::is_none")]
34    pub raw_output: Option<String>,
35}
36
37/// Sink for background status, output, and progress updates.
38#[async_trait]
39pub trait BackgroundEventSink: Send + Sync {
40    async fn status(&self, message: &str) -> Result<()>;
41
42    async fn output(&self, stream: &str, delta: &str) -> Result<()>;
43
44    async fn progress(&self, progress: BackgroundProgress) -> Result<()>;
45}
46
47/// Trait implemented by tools that natively support detached execution.
48#[async_trait]
49pub trait BackgroundExecutableTool: Send + Sync {
50    async fn execute_background(
51        &self,
52        arguments: Value,
53        context: ToolContext,
54        sink: Arc<dyn BackgroundEventSink>,
55    ) -> std::result::Result<BackgroundOutcome, ToolExecutionResult>;
56}