Skip to main content

codex_runtime/domain/artifact/
adapter.rs

1use std::future::Future;
2use std::pin::Pin;
3
4use crate::plugin::PluginContractVersion;
5use crate::runtime::core::Runtime;
6use serde_json::Value;
7
8use super::execution as task;
9use super::{ArtifactTaskSpec, DomainError};
10
11pub type ArtifactAdapterFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
12
13#[derive(Clone, Debug, PartialEq)]
14pub struct ArtifactTurnOutput {
15    pub turn_id: Option<String>,
16    pub output: Value,
17}
18
19pub trait ArtifactPluginAdapter: Send + Sync {
20    fn plugin_contract_version(&self) -> PluginContractVersion {
21        PluginContractVersion::CURRENT
22    }
23
24    fn start_thread<'a>(&'a self) -> ArtifactAdapterFuture<'a, Result<String, DomainError>>;
25    fn resume_thread<'a>(
26        &'a self,
27        thread_id: &'a str,
28    ) -> ArtifactAdapterFuture<'a, Result<String, DomainError>>;
29    fn run_turn<'a>(
30        &'a self,
31        thread_id: &'a str,
32        prompt: &'a str,
33        spec: &'a ArtifactTaskSpec,
34    ) -> ArtifactAdapterFuture<'a, Result<ArtifactTurnOutput, DomainError>>;
35}
36
37#[derive(Clone)]
38pub struct RuntimeArtifactAdapter {
39    runtime: Runtime,
40}
41
42impl RuntimeArtifactAdapter {
43    /// Create runtime-backed artifact adapter.
44    /// Allocation: none. Complexity: O(1).
45    pub fn new(runtime: Runtime) -> Self {
46        Self { runtime }
47    }
48}
49
50impl ArtifactPluginAdapter for RuntimeArtifactAdapter {
51    fn start_thread<'a>(&'a self) -> ArtifactAdapterFuture<'a, Result<String, DomainError>> {
52        Box::pin(async move { task::start_thread(&self.runtime).await })
53    }
54
55    fn resume_thread<'a>(
56        &'a self,
57        thread_id: &'a str,
58    ) -> ArtifactAdapterFuture<'a, Result<String, DomainError>> {
59        Box::pin(async move { task::resume_thread(&self.runtime, thread_id).await })
60    }
61
62    fn run_turn<'a>(
63        &'a self,
64        thread_id: &'a str,
65        prompt: &'a str,
66        spec: &'a ArtifactTaskSpec,
67    ) -> ArtifactAdapterFuture<'a, Result<ArtifactTurnOutput, DomainError>> {
68        Box::pin(async move {
69            let turn_params = task::build_turn_start_params(thread_id, prompt, spec)?;
70            let (turn_id, output) =
71                task::run_turn_and_collect_output(&self.runtime, thread_id, turn_params).await?;
72            Ok(ArtifactTurnOutput { turn_id, output })
73        })
74    }
75}