1use chio_core::capability::{
2 governance::{GovernedApprovalToken, GovernedTransactionIntent, ThresholdApprovalProposal},
3 scope::ModelMetadata,
4 supplemental_authorization::OpaqueSupplementalAuthorization,
5 token::CapabilityToken,
6};
7use chio_kernel::dpop;
8use chio_kernel::{ChioKernel, SignedExecutionNonce, ToolCallRequest, ToolCallResponse};
9use serde_json::{json, Value};
10
11use crate::capability_bridge::{CrossProtocolCapabilityEnvelope, CrossProtocolCapabilityRef};
12use crate::discovery::DiscoveryProtocol;
13use crate::error::BridgeError;
14use crate::routing::{route_selection_metadata, RouteSelectionEvidence};
15
16#[derive(Debug, Clone)]
18pub struct CrossProtocolExecutionRequest {
19 pub origin_request_id: String,
20 pub kernel_request_id: String,
21 pub target_protocol: DiscoveryProtocol,
22 pub target_server_id: String,
23 pub target_tool_name: String,
24 pub agent_id: String,
25 pub arguments: Value,
26 pub capability: CapabilityToken,
27 pub source_envelope: Value,
28 pub dpop_proof: Option<dpop::DpopProof>,
29 pub execution_nonce: Option<SignedExecutionNonce>,
30 pub governed_intent: Option<GovernedTransactionIntent>,
31 pub approval_token: Option<GovernedApprovalToken>,
32 pub approval_tokens: Vec<GovernedApprovalToken>,
33 pub threshold_approval_proposal: Option<ThresholdApprovalProposal>,
34 pub supplemental_authorization: Option<OpaqueSupplementalAuthorization>,
35 pub model_metadata: Option<ModelMetadata>,
36}
37
38pub fn kernel_tool_call_request(request: &CrossProtocolExecutionRequest) -> ToolCallRequest {
44 ToolCallRequest {
45 request_id: request.kernel_request_id.clone(),
46 capability: request.capability.clone(),
47 tool_name: request.target_tool_name.clone(),
48 server_id: request.target_server_id.clone(),
49 agent_id: request.agent_id.clone(),
50 arguments: request.arguments.clone(),
51 dpop_proof: request.dpop_proof.clone(),
52 execution_nonce: request.execution_nonce.clone(),
53 governed_intent: request.governed_intent.clone(),
54 approval_token: request.approval_token.clone(),
55 approval_tokens: request.approval_tokens.clone(),
56 threshold_approval_proposal: request.threshold_approval_proposal.clone(),
57 supplemental_authorization: request.supplemental_authorization.clone(),
58 model_metadata: request.model_metadata.clone(),
59 federated_origin_kernel_id: None,
60 }
61}
62
63pub struct CrossProtocolTargetRequest<'a> {
65 pub kernel: &'a ChioKernel,
66 pub execution: &'a CrossProtocolExecutionRequest,
67 pub source_protocol: DiscoveryProtocol,
68 pub bridge_id: &'a str,
69 pub capability_ref: &'a CrossProtocolCapabilityRef,
70 pub capability_envelope: &'a CrossProtocolCapabilityEnvelope,
71 pub route_selection: &'a RouteSelectionEvidence,
72 pub projected_request: &'a Value,
73}
74
75#[derive(Debug, Clone)]
77pub struct TargetExecutionHop {
78 pub protocol: DiscoveryProtocol,
79 pub request_id: String,
80 pub receipt_id: Option<String>,
81}
82
83pub struct CrossProtocolTargetExecution {
85 pub response: ToolCallResponse,
86 pub protocol_result: Option<Value>,
87 pub protocol_notifications: Vec<Value>,
88 pub route_hops: Vec<TargetExecutionHop>,
89}
90
91pub trait TargetProtocolExecutor: Send + Sync {
93 fn target_protocol(&self) -> DiscoveryProtocol;
94
95 fn execute(
96 &self,
97 request: CrossProtocolTargetRequest<'_>,
98 ) -> Result<CrossProtocolTargetExecution, BridgeError>;
99}
100
101#[derive(Debug, Default, Clone, Copy)]
104pub struct OpenAiTargetExecutor;
105
106impl TargetProtocolExecutor for OpenAiTargetExecutor {
107 fn target_protocol(&self) -> DiscoveryProtocol {
108 DiscoveryProtocol::OpenAi
109 }
110
111 fn execute(
112 &self,
113 request: CrossProtocolTargetRequest<'_>,
114 ) -> Result<CrossProtocolTargetExecution, BridgeError> {
115 let route_metadata = metadata_with_source_receipt_context(
116 route_selection_metadata(request.route_selection)?,
117 &request.execution.source_envelope,
118 )?;
119 let response = request
120 .kernel
121 .evaluate_tool_call_blocking_with_metadata(
122 &kernel_tool_call_request(request.execution),
123 Some(route_metadata),
124 )
125 .map_err(BridgeError::Kernel)?;
126
127 let receipt_ref = response.receipt.id.clone();
128 let output = render_protocol_output(&response.output, response.reason.as_deref());
129
130 Ok(CrossProtocolTargetExecution {
131 response,
132 protocol_result: Some(json!({
133 "type": "function_call_output",
134 "call_id": request.execution.origin_request_id,
135 "output": output,
136 "receipt_ref": receipt_ref,
137 })),
138 protocol_notifications: Vec::new(),
139 route_hops: vec![
140 TargetExecutionHop {
141 protocol: DiscoveryProtocol::OpenAi,
142 request_id: format!("{}:openai", request.execution.kernel_request_id),
143 receipt_id: None,
144 },
145 TargetExecutionHop {
146 protocol: DiscoveryProtocol::Native,
147 request_id: request.execution.kernel_request_id.clone(),
148 receipt_id: Some(receipt_ref),
149 },
150 ],
151 })
152 }
153}
154
155pub fn metadata_with_source_receipt_context(
156 mut metadata: Value,
157 source_envelope: &Value,
158) -> Result<Value, BridgeError> {
159 let Some(receipt_context) = source_envelope.get("receipt_context").cloned() else {
160 return Ok(metadata);
161 };
162 let Some(metadata_obj) = metadata.as_object_mut() else {
163 return Err(BridgeError::InvalidRequest(
164 "receipt metadata must be a JSON object".to_string(),
165 ));
166 };
167 metadata_obj.insert("receipt_context".to_string(), receipt_context);
168 Ok(metadata)
169}
170
171fn render_protocol_output(
172 output: &Option<chio_kernel::ToolCallOutput>,
173 reason: Option<&str>,
174) -> String {
175 match output {
176 Some(chio_kernel::ToolCallOutput::Value(value)) => value
177 .as_str()
178 .map(str::to_string)
179 .unwrap_or_else(|| serde_json::to_string(value).unwrap_or_else(|_| "{}".to_string())),
180 Some(chio_kernel::ToolCallOutput::Stream(stream)) => serde_json::to_string(
181 &stream
182 .chunks
183 .iter()
184 .map(|chunk| chunk.data.clone())
185 .collect::<Vec<_>>(),
186 )
187 .unwrap_or_else(|_| "[]".to_string()),
188 None => reason.unwrap_or("{}").to_string(),
189 }
190}