Skip to main content

agent_runtime_infra_adapter/
binding.rs

1use std::collections::BTreeMap;
2
3use async_trait::async_trait;
4use runtime_ports::{
5    OperationContext, PortFailure, PortFailureKind, ResolvedExecutionContext,
6    RuntimeInstanceResolver,
7};
8use runtime_types::{CallerScope, RuntimeInstanceId, WorkspaceId};
9
10#[derive(Debug, Clone)]
11pub struct RuntimeBinding {
12    pub agent_id: String,
13    pub runtime_type: String,
14    pub model: String,
15    pub workspace_id: WorkspaceId,
16    pub definition_id: String,
17    pub definition_version: String,
18    pub definition_digest: Option<String>,
19    pub metadata: BTreeMap<String, String>,
20}
21
22pub struct StaticRuntimeBindingResolver {
23    bindings: BTreeMap<RuntimeInstanceId, RuntimeBinding>,
24}
25
26impl StaticRuntimeBindingResolver {
27    pub fn new(bindings: BTreeMap<RuntimeInstanceId, RuntimeBinding>) -> Result<Self, PortFailure> {
28        if bindings.is_empty() {
29            return Err(PortFailure::new(
30                PortFailureKind::Invalid,
31                "RUNTIME_BINDINGS_EMPTY",
32                "at least one runtime binding is required",
33            ));
34        }
35        for binding in bindings.values() {
36            if !binding.agent_id.starts_with("agt_")
37                || binding.runtime_type.is_empty()
38                || binding.model.is_empty()
39                || binding.definition_id.is_empty()
40                || binding.definition_version.is_empty()
41            {
42                return Err(PortFailure::new(
43                    PortFailureKind::Invalid,
44                    "RUNTIME_BINDING_INVALID",
45                    "Infra Agent ID, runtime type, model, definition ID, and definition version are required",
46                ));
47            }
48        }
49        Ok(Self { bindings })
50    }
51}
52
53#[async_trait]
54impl RuntimeInstanceResolver for StaticRuntimeBindingResolver {
55    async fn resolve(
56        &self,
57        _: &OperationContext,
58        _: &CallerScope,
59        id: &RuntimeInstanceId,
60    ) -> Result<ResolvedExecutionContext, PortFailure> {
61        let binding = self.bindings.get(id).ok_or_else(|| {
62            PortFailure::new(
63                PortFailureKind::NotFound,
64                "RUNTIME_BINDING_NOT_FOUND",
65                "runtime binding was not found",
66            )
67        })?;
68        Ok(ResolvedExecutionContext {
69            runtime_instance_id: id.clone(),
70            agent_id: binding.agent_id.clone(),
71            runtime_type: binding.runtime_type.clone(),
72            model: binding.model.clone(),
73            workspace_id: binding.workspace_id.clone(),
74            definition_id: binding.definition_id.clone(),
75            definition_version: binding.definition_version.clone(),
76            definition_digest: binding.definition_digest.clone(),
77            metadata: binding.metadata.clone(),
78        })
79    }
80}