agent_sdk_core/testing/
output_delivery.rs1use std::sync::{Arc, Mutex};
8
9use crate::{
10 domain::{AgentError, AgentErrorKind, RetryClassification},
11 output_delivery::{OutputDeliveryReceipt, OutputDeliveryRequest, OutputSinkRef},
12 output_delivery_port::{OutputSink, OutputSinkCapabilities},
13};
14
15#[derive(Clone)]
16pub struct ScriptedOutputSink {
19 sink_ref: OutputSinkRef,
20 capabilities: OutputSinkCapabilities,
21 calls: Arc<Mutex<Vec<OutputDeliveryRequest>>>,
22 next_receipts: Arc<Mutex<Vec<Result<OutputDeliveryReceipt, AgentError>>>>,
23}
24
25impl ScriptedOutputSink {
26 pub fn new(sink_ref: OutputSinkRef, capabilities: OutputSinkCapabilities) -> Self {
36 Self {
37 sink_ref,
38 capabilities,
39 calls: Arc::new(Mutex::new(Vec::new())),
40 next_receipts: Arc::new(Mutex::new(Vec::new())),
41 }
42 }
43
44 pub fn push_receipt(&self, receipt: Result<OutputDeliveryReceipt, AgentError>) {
48 self.next_receipts
49 .lock()
50 .expect("output sink receipt lock")
51 .push(receipt);
52 }
53
54 pub fn calls(&self) -> Vec<OutputDeliveryRequest> {
58 self.calls.lock().expect("output sink calls lock").clone()
59 }
60
61 fn next_receipt(
62 &self,
63 request: OutputDeliveryRequest,
64 ) -> Result<OutputDeliveryReceipt, AgentError> {
65 self.calls
66 .lock()
67 .expect("output sink calls lock")
68 .push(request.clone());
69 self.next_receipts
70 .lock()
71 .expect("output sink receipt lock")
72 .pop()
73 .unwrap_or_else(|| {
74 Ok(OutputDeliveryReceipt::completed(
75 request.delivery_id,
76 "ack.output_delivery.fake",
77 ))
78 })
79 }
80}
81
82impl OutputSink for ScriptedOutputSink {
83 fn sink_ref(&self) -> OutputSinkRef {
84 self.sink_ref.clone()
85 }
86
87 fn capabilities(&self) -> OutputSinkCapabilities {
88 self.capabilities.clone()
89 }
90
91 fn send_chunk(
92 &self,
93 request: OutputDeliveryRequest,
94 ) -> Result<OutputDeliveryReceipt, AgentError> {
95 if !self.capabilities.supports_chunks {
96 return Err(AgentError::new(
97 AgentErrorKind::HostConfigurationNeeded,
98 RetryClassification::HostConfigurationNeeded,
99 "output sink does not support chunks",
100 ));
101 }
102 self.next_receipt(request)
103 }
104
105 fn send_final(
106 &self,
107 request: OutputDeliveryRequest,
108 ) -> Result<OutputDeliveryReceipt, AgentError> {
109 self.next_receipt(request)
110 }
111
112 fn reconcile(
113 &self,
114 request: OutputDeliveryRequest,
115 ) -> Result<OutputDeliveryReceipt, AgentError> {
116 self.next_receipt(request)
117 }
118}