1use std::{
4 collections::HashMap,
5 sync::{Arc, Mutex},
6};
7
8use cookie_agent_protocol::{
9 AgentRevision, AgentSnapshot, CatalogRevision, DelegateRequestPayload, DelegationReservation,
10 EventPayload, FrozenCacheStrategy, FrozenModelBinding, InvocationId, ModelRevision,
11 ModelSnapshotRevision, ProviderStateRevision, RecipeRegistryRevision, RunId, RuntimeRevision,
12 SessionId, SessionStatus, Sha256Digest, ToolCallId,
13};
14use sha2::{Digest as _, Sha256};
15use thiserror::Error;
16
17use crate::session::{SessionError, SessionStore};
18
19pub(crate) fn delegation_request_fingerprint(
20 child_agent: &AgentSnapshot,
21 selected_suffix: &[FrozenModelBinding],
22 cache_strategies: &[Option<FrozenCacheStrategy>],
23 request: &DelegateRequestPayload,
24) -> Result<Sha256Digest, ()> {
25 let payload = if cache_strategies.is_empty() {
26 serde_json::to_vec(&(
27 &child_agent.agent,
28 &request.description,
29 &request.prompt,
30 &request.title,
31 &request.resume_session_id,
32 request.inherit_context,
33 request.background,
34 &request.seeded_context,
35 child_agent,
36 selected_suffix,
37 &request.staged_skill,
38 ))
39 } else {
40 serde_json::to_vec(&(
41 &child_agent.agent,
42 &request.description,
43 &request.prompt,
44 &request.title,
45 &request.resume_session_id,
46 request.inherit_context,
47 request.background,
48 &request.seeded_context,
49 child_agent,
50 selected_suffix,
51 cache_strategies,
52 &request.staged_skill,
53 ))
54 }
55 .map_err(|_| ())?;
56 Sha256Digest::new(format!("{:x}", Sha256::digest(payload))).map_err(|_| ())
57}
58
59#[derive(Clone, Debug, Eq, PartialEq)]
60pub struct DelegationRuntimeRevisions {
61 pub manifest_revision: ModelSnapshotRevision,
62 pub runtime_revision: RuntimeRevision,
63 pub catalog_revision: CatalogRevision,
64 pub provider_state_revision: ProviderStateRevision,
65 pub model_revision: ModelRevision,
66 pub agent_revision: AgentRevision,
67 pub recipe_registry_revision: RecipeRegistryRevision,
68}
69
70#[derive(Clone, Debug, PartialEq)]
71pub struct DelegationEntry {
72 pub reservation: DelegationReservation,
73 pub child_agent: AgentSnapshot,
74 pub revisions: DelegationRuntimeRevisions,
75 pub selected_suffix: Vec<FrozenModelBinding>,
76 pub cache_strategies: Vec<Option<FrozenCacheStrategy>>,
77 pub request_fingerprint: Sha256Digest,
78 pub request: DelegateRequestPayload,
79 pub started: bool,
80 pub child_run_id: Option<RunId>,
81 pub run_attached: bool,
82 pub terminal_status: Option<SessionStatus>,
83 pub terminal_reason: Option<cookie_agent_protocol::SafeErrorMessage>,
84}
85
86#[derive(Debug, Error)]
87pub enum DelegationEventError {
88 #[error(transparent)]
89 Session(#[from] SessionError),
90 #[error("delegation event corruption for invocation {0}")]
91 Corrupt(InvocationId),
92}
93
94#[derive(Debug, Default)]
95struct DelegationState {
96 entries: HashMap<InvocationId, DelegationEntry>,
97 order: Vec<InvocationId>,
98}
99
100#[derive(Debug)]
101pub struct DelegationEventStore {
102 sessions: Arc<SessionStore>,
103 state: Mutex<DelegationState>,
104}
105
106impl DelegationEventStore {
107 pub fn open(sessions: Arc<SessionStore>) -> Result<Arc<Self>, DelegationEventError> {
111 let mut state = DelegationState::default();
112 let mut parents = sessions.root_snapshots();
113 parents.sort_by_key(|session| session.meta.session_id);
114 for parent in parents {
115 for envelope in parent.log.event_snapshot().iter() {
116 if parent.log.delegation_event_tainted(envelope) {
117 continue;
118 }
119 apply_event(
120 &mut state,
121 parent.meta.session_id,
122 envelope.run_id,
123 envelope.payload.clone(),
124 )?;
125 }
126 }
127 Ok(Arc::new(Self {
128 sessions,
129 state: Mutex::new(state),
130 }))
131 }
132
133 pub fn extend_from_payloads(
136 &self,
137 payloads: &[(
138 SessionId,
139 Option<RunId>,
140 cookie_agent_protocol::EventPayload,
141 )],
142 ) -> Result<Vec<DelegationEntry>, DelegationEventError> {
143 if payloads.is_empty() {
144 return Ok(Vec::new());
145 }
146 let mut state = self
147 .state
148 .lock()
149 .unwrap_or_else(|poisoned| poisoned.into_inner());
150 let mut touched = Vec::new();
151 for (parent_session_id, run_id, payload) in payloads {
152 let Some(invocation_id) = delegation_invocation_of(payload) else {
153 continue;
154 };
155 let before = state.entries.get(&invocation_id).cloned();
156 apply_event(&mut state, *parent_session_id, *run_id, payload.clone())?;
157 match state.entries.get(&invocation_id).cloned() {
158 Some(updated) if Some(&updated) != before.as_ref() => touched.push(updated),
159 _ => {}
160 }
161 }
162 Ok(touched)
163 }
164
165 #[allow(clippy::too_many_arguments)]
166 pub fn reserve(
167 &self,
168 invocation_id: InvocationId,
169 parent_session_id: SessionId,
170 parent_run_id: RunId,
171 parent_tool_call_id: ToolCallId,
172 child_agent: AgentSnapshot,
173 revisions: DelegationRuntimeRevisions,
174 selected_suffix: Vec<FrozenModelBinding>,
175 cache_strategies: Vec<Option<FrozenCacheStrategy>>,
176 request_fingerprint: Sha256Digest,
177 request: DelegateRequestPayload,
178 ) -> Result<DelegationEntry, DelegationEventError> {
179 let mut state = self
180 .state
181 .lock()
182 .unwrap_or_else(|poisoned| poisoned.into_inner());
183 if let Some(entry) = state.entries.get(&invocation_id) {
184 let same_request = entry.reservation.parent_session_id == parent_session_id
185 && entry.reservation.parent_run_id == parent_run_id
186 && entry.reservation.parent_tool_call_id == parent_tool_call_id
187 && entry.request_fingerprint == request_fingerprint
188 && entry.child_agent == child_agent
189 && entry.revisions == revisions
190 && entry.selected_suffix == selected_suffix
191 && entry.cache_strategies == cache_strategies
192 && entry.request == request;
193 return if same_request {
194 Ok(entry.clone())
195 } else {
196 Err(DelegationEventError::Corrupt(invocation_id))
197 };
198 }
199 if !valid_request(&request)
200 || selected_suffix.is_empty()
201 || !cache_strategies_match_bindings(&selected_suffix, &cache_strategies)
202 || selected_suffix
203 .iter()
204 .any(|binding| binding.manifest_revision != revisions.manifest_revision)
205 || child_agent
206 .validate_selected_suffix(
207 &cookie_agent_protocol::RunSelection {
208 agent: child_agent.agent.clone(),
209 model: selected_suffix[0].selection.clone(),
210 preset: None,
211 },
212 &selected_suffix,
213 )
214 .is_err()
215 {
216 return Err(DelegationEventError::Corrupt(invocation_id));
217 }
218 let child_session_id = request.resume_session_id.unwrap_or_else(SessionId::new_v7);
219 let reservation = DelegationReservation {
220 invocation_id,
221 parent_session_id,
222 parent_run_id,
223 parent_tool_call_id,
224 child_session_id,
225 };
226 let entry = DelegationEntry {
227 reservation: reservation.clone(),
228 child_agent: child_agent.clone(),
229 revisions: revisions.clone(),
230 selected_suffix: selected_suffix.clone(),
231 cache_strategies: cache_strategies.clone(),
232 request_fingerprint: request_fingerprint.clone(),
233 request: request.clone(),
234 started: false,
235 child_run_id: None,
236 run_attached: false,
237 terminal_status: None,
238 terminal_reason: None,
239 };
240 self.sessions.append(
241 parent_session_id,
242 Some(parent_run_id),
243 cookie_agent_protocol::EventOrigin::new("engine:delegation")
244 .expect("static event origin is valid"),
245 EventPayload::DelegationReserved {
246 reservation,
247 child_agent: Box::new(child_agent),
248 manifest_revision: revisions.manifest_revision,
249 runtime_revision: revisions.runtime_revision,
250 catalog_revision: revisions.catalog_revision,
251 provider_state_revision: revisions.provider_state_revision,
252 model_revision: revisions.model_revision,
253 agent_revision: revisions.agent_revision,
254 recipe_registry_revision: revisions.recipe_registry_revision,
255 selected_suffix,
256 cache_strategies,
257 request_fingerprint,
258 request,
259 },
260 )?;
261 state.entries.insert(invocation_id, entry.clone());
262 state.order.push(invocation_id);
263 Ok(entry)
264 }
265
266 pub fn mark_started(&self, invocation_id: InvocationId) -> Result<(), DelegationEventError> {
267 let mut state = self
268 .state
269 .lock()
270 .unwrap_or_else(|poisoned| poisoned.into_inner());
271 let Some(entry) = state.entries.get(&invocation_id) else {
272 return Err(DelegationEventError::Corrupt(invocation_id));
273 };
274 if entry.started {
275 return Ok(());
276 }
277 let reservation = entry.reservation.clone();
278 self.sessions.append(
279 reservation.parent_session_id,
280 Some(reservation.parent_run_id),
281 cookie_agent_protocol::EventOrigin::new("engine:delegation")
282 .expect("static event origin is valid"),
283 EventPayload::DelegationStarted {
284 invocation_id,
285 child_session_id: reservation.child_session_id,
286 },
287 )?;
288 state
289 .entries
290 .get_mut(&invocation_id)
291 .expect("checked entry")
292 .started = true;
293 Ok(())
294 }
295
296 pub fn mark_run_started(
297 &self,
298 invocation_id: InvocationId,
299 child_run_id: RunId,
300 ) -> Result<(), DelegationEventError> {
301 self.mark_run(invocation_id, child_run_id, false)
302 }
303
304 pub fn mark_run_attached(
305 &self,
306 invocation_id: InvocationId,
307 child_run_id: RunId,
308 ) -> Result<(), DelegationEventError> {
309 self.mark_run(invocation_id, child_run_id, true)
310 }
311
312 fn mark_run(
313 &self,
314 invocation_id: InvocationId,
315 child_run_id: RunId,
316 attached: bool,
317 ) -> Result<(), DelegationEventError> {
318 let mut state = self
319 .state
320 .lock()
321 .unwrap_or_else(|poisoned| poisoned.into_inner());
322 let Some(entry) = state.entries.get(&invocation_id) else {
323 return Err(DelegationEventError::Corrupt(invocation_id));
324 };
325 if entry.terminal_status.is_some()
326 || (attached && entry.request.resume_session_id.is_none())
327 {
328 return Err(DelegationEventError::Corrupt(invocation_id));
329 }
330 if entry.child_run_id == Some(child_run_id) && entry.run_attached == attached {
331 return Ok(());
332 }
333 if entry.child_run_id.is_some() {
334 return Err(DelegationEventError::Corrupt(invocation_id));
335 }
336 let reservation = entry.reservation.clone();
337 let payload = if attached {
338 EventPayload::DelegationRunAttached {
339 invocation_id,
340 child_run_id,
341 }
342 } else {
343 EventPayload::DelegationRunStarted {
344 invocation_id,
345 child_run_id,
346 }
347 };
348 self.sessions.append(
349 reservation.parent_session_id,
350 Some(reservation.parent_run_id),
351 cookie_agent_protocol::EventOrigin::new("engine:delegation")
352 .expect("static event origin is valid"),
353 payload,
354 )?;
355 let entry = state
356 .entries
357 .get_mut(&invocation_id)
358 .expect("checked entry");
359 entry.child_run_id = Some(child_run_id);
360 entry.run_attached = attached;
361 Ok(())
362 }
363
364 pub fn mark_finished(
365 &self,
366 invocation_id: InvocationId,
367 status: SessionStatus,
368 ) -> Result<(), DelegationEventError> {
369 self.mark_finished_with_reason(invocation_id, status, None)
370 }
371
372 pub fn mark_finished_with_reason(
373 &self,
374 invocation_id: InvocationId,
375 status: SessionStatus,
376 reason: Option<cookie_agent_protocol::SafeErrorMessage>,
377 ) -> Result<(), DelegationEventError> {
378 if !matches!(
379 status,
380 SessionStatus::Completed
381 | SessionStatus::Failed
382 | SessionStatus::Cancelled
383 | SessionStatus::Interrupted
384 ) {
385 return Err(DelegationEventError::Corrupt(invocation_id));
386 }
387 let mut state = self
388 .state
389 .lock()
390 .unwrap_or_else(|poisoned| poisoned.into_inner());
391 let Some(entry) = state.entries.get(&invocation_id) else {
392 return Err(DelegationEventError::Corrupt(invocation_id));
393 };
394 if entry.terminal_status == Some(status) {
395 return if entry.terminal_reason == reason {
396 Ok(())
397 } else {
398 Err(DelegationEventError::Corrupt(invocation_id))
399 };
400 }
401 if entry.terminal_status.is_some() {
402 return Err(DelegationEventError::Corrupt(invocation_id));
403 }
404 let reservation = entry.reservation.clone();
405 let child_run_id = entry.child_run_id;
406 self.sessions.append(
407 reservation.parent_session_id,
408 Some(reservation.parent_run_id),
409 cookie_agent_protocol::EventOrigin::new("engine:delegation")
410 .expect("static event origin is valid"),
411 EventPayload::DelegationFinished {
412 invocation_id,
413 child_session_id: reservation.child_session_id,
414 child_run_id,
415 status,
416 reason: reason.clone(),
417 },
418 )?;
419 let entry = state
420 .entries
421 .get_mut(&invocation_id)
422 .expect("checked entry");
423 entry.terminal_status = Some(status);
424 entry.terminal_reason = reason;
425 Ok(())
426 }
427
428 #[must_use]
429 pub fn get(&self, invocation_id: InvocationId) -> Option<DelegationEntry> {
430 self.state
431 .lock()
432 .unwrap_or_else(|poisoned| poisoned.into_inner())
433 .entries
434 .get(&invocation_id)
435 .cloned()
436 }
437
438 #[must_use]
439 pub fn entries(&self) -> Vec<DelegationEntry> {
440 let state = self
441 .state
442 .lock()
443 .unwrap_or_else(|poisoned| poisoned.into_inner());
444 state
445 .order
446 .iter()
447 .filter_map(|invocation_id| state.entries.get(invocation_id).cloned())
448 .collect()
449 }
450
451 pub fn reconcile_parent(
452 &self,
453 parent_session_id: SessionId,
454 ) -> Result<(), DelegationEventError> {
455 let parent = self.sessions.get(parent_session_id)?;
456 let mut rebuilt = DelegationState::default();
457 for envelope in parent.log.event_snapshot().iter() {
458 if parent.log.delegation_event_tainted(envelope) {
459 continue;
460 }
461 apply_event(
462 &mut rebuilt,
463 parent_session_id,
464 envelope.run_id,
465 envelope.payload.clone(),
466 )?;
467 }
468
469 let mut state = self
470 .state
471 .lock()
472 .unwrap_or_else(|poisoned| poisoned.into_inner());
473 state
474 .entries
475 .retain(|_, entry| entry.reservation.parent_session_id != parent_session_id);
476 let retained = state
477 .entries
478 .keys()
479 .copied()
480 .collect::<std::collections::HashSet<_>>();
481 state
482 .order
483 .retain(|invocation_id| retained.contains(invocation_id));
484 for invocation_id in rebuilt.order {
485 if let Some(entry) = rebuilt.entries.remove(&invocation_id) {
486 state.entries.insert(invocation_id, entry);
487 state.order.push(invocation_id);
488 }
489 }
490 Ok(())
491 }
492}
493
494fn delegation_invocation_of(payload: &EventPayload) -> Option<cookie_agent_protocol::InvocationId> {
496 match payload {
497 EventPayload::DelegationReserved { reservation, .. } => Some(reservation.invocation_id),
498 EventPayload::DelegationStarted { invocation_id, .. }
499 | EventPayload::DelegationRunStarted { invocation_id, .. }
500 | EventPayload::DelegationRunAttached { invocation_id, .. }
501 | EventPayload::DelegationFinished { invocation_id, .. } => Some(*invocation_id),
502 _ => None,
503 }
504}
505
506pub(crate) fn is_delegation_payload(payload: &EventPayload) -> bool {
512 matches!(
513 payload,
514 EventPayload::DelegationReserved { .. }
515 | EventPayload::DelegationStarted { .. }
516 | EventPayload::DelegationRunStarted { .. }
517 | EventPayload::DelegationRunAttached { .. }
518 | EventPayload::DelegationFinished { .. }
519 )
520}
521
522fn apply_event(
523 state: &mut DelegationState,
524 parent_session_id: SessionId,
525 run_id: Option<RunId>,
526 payload: EventPayload,
527) -> Result<(), DelegationEventError> {
528 match payload {
529 EventPayload::DelegationReserved {
530 reservation,
531 child_agent,
532 manifest_revision,
533 runtime_revision,
534 catalog_revision,
535 provider_state_revision,
536 model_revision,
537 agent_revision,
538 recipe_registry_revision,
539 selected_suffix,
540 cache_strategies,
541 request_fingerprint,
542 request,
543 } => {
544 let invocation_id = reservation.invocation_id;
545 let revisions = DelegationRuntimeRevisions {
546 manifest_revision,
547 runtime_revision,
548 catalog_revision,
549 provider_state_revision,
550 model_revision,
551 agent_revision,
552 recipe_registry_revision,
553 };
554 let fingerprint_valid = delegation_request_fingerprint(
555 &child_agent,
556 &selected_suffix,
557 &cache_strategies,
558 &request,
559 )
560 .is_ok_and(|computed| computed == request_fingerprint);
561 if parent_session_id != reservation.parent_session_id
562 || run_id != Some(reservation.parent_run_id)
563 || state.entries.contains_key(&invocation_id)
564 || request
565 .resume_session_id
566 .is_some_and(|id| id != reservation.child_session_id)
567 || !valid_request(&request)
568 || !fingerprint_valid
569 || selected_suffix.is_empty()
570 || (!cache_strategies.is_empty()
571 && !cache_strategies_match_bindings(&selected_suffix, &cache_strategies))
572 || selected_suffix
573 .iter()
574 .any(|binding| binding.manifest_revision != revisions.manifest_revision)
575 || child_agent
576 .validate_selected_suffix(
577 &cookie_agent_protocol::RunSelection {
578 agent: child_agent.agent.clone(),
579 model: selected_suffix[0].selection.clone(),
580 preset: None,
581 },
582 &selected_suffix,
583 )
584 .is_err()
585 {
586 return Err(DelegationEventError::Corrupt(invocation_id));
587 }
588 state.entries.insert(
589 invocation_id,
590 DelegationEntry {
591 reservation,
592 child_agent: *child_agent,
593 revisions,
594 selected_suffix,
595 cache_strategies,
596 request_fingerprint,
597 request,
598 started: false,
599 child_run_id: None,
600 run_attached: false,
601 terminal_status: None,
602 terminal_reason: None,
603 },
604 );
605 state.order.push(invocation_id);
606 }
607 EventPayload::DelegationStarted {
608 invocation_id,
609 child_session_id,
610 } => {
611 let Some(entry) = state.entries.get_mut(&invocation_id) else {
612 return Ok(());
613 };
614 if parent_session_id != entry.reservation.parent_session_id
615 || run_id != Some(entry.reservation.parent_run_id)
616 || child_session_id != entry.reservation.child_session_id
617 || entry.started
618 {
619 return Err(DelegationEventError::Corrupt(invocation_id));
620 }
621 entry.started = true;
622 }
623 payload @ (EventPayload::DelegationRunStarted { .. }
624 | EventPayload::DelegationRunAttached { .. }) => {
625 let (invocation_id, child_run_id, attached) = match payload {
626 EventPayload::DelegationRunStarted {
627 invocation_id,
628 child_run_id,
629 } => (invocation_id, child_run_id, false),
630 EventPayload::DelegationRunAttached {
631 invocation_id,
632 child_run_id,
633 } => (invocation_id, child_run_id, true),
634 _ => unreachable!(),
635 };
636 let Some(entry) = state.entries.get_mut(&invocation_id) else {
637 return Ok(());
638 };
639 if parent_session_id != entry.reservation.parent_session_id
640 || run_id != Some(entry.reservation.parent_run_id)
641 || entry.child_run_id.is_some()
642 || entry.terminal_status.is_some()
643 || (attached && entry.request.resume_session_id.is_none())
644 {
645 return Err(DelegationEventError::Corrupt(invocation_id));
646 }
647 entry.child_run_id = Some(child_run_id);
648 entry.run_attached = attached;
649 }
650 EventPayload::DelegationFinished {
651 invocation_id,
652 child_session_id,
653 child_run_id,
654 status,
655 reason,
656 } => {
657 let Some(entry) = state.entries.get_mut(&invocation_id) else {
658 return Ok(());
659 };
660 if parent_session_id != entry.reservation.parent_session_id
661 || run_id != Some(entry.reservation.parent_run_id)
662 || child_session_id != entry.reservation.child_session_id
663 || child_run_id != entry.child_run_id
664 || entry.terminal_status.is_some()
665 || !matches!(
666 status,
667 SessionStatus::Completed
668 | SessionStatus::Failed
669 | SessionStatus::Cancelled
670 | SessionStatus::Interrupted
671 )
672 {
673 return Err(DelegationEventError::Corrupt(invocation_id));
674 }
675 entry.terminal_status = Some(status);
676 entry.terminal_reason = reason;
677 }
678 _ => {}
679 }
680 Ok(())
681}
682
683fn valid_request(request: &DelegateRequestPayload) -> bool {
684 if request.description.is_empty() || request.prompt.is_empty() {
685 return false;
686 }
687 if request.resume_session_id.is_some() && request.inherit_context {
688 return false;
689 }
690 if !request.inherit_context && !request.seeded_context.is_empty() {
691 return false;
692 }
693 if request.seeded_context.len() > 65_536 {
694 return false;
695 }
696 if request.staged_skill.as_ref().is_some_and(|skill| {
697 skill.provenance != cookie_agent_protocol::StagedSkillProvenance::SkillFork
698 || skill.name.is_empty()
699 || skill.rendered_body.is_empty()
700 || skill.source_path.is_empty()
701 || skill.base_dir.is_empty()
702 || skill.supporting_files.len() > 10
703 || skill.grants.len() > 256
704 || request.resume_session_id.is_some()
705 }) {
706 return false;
707 }
708 if request
709 .seeded_context
710 .iter()
711 .any(|turn| turn.text.is_empty())
712 {
713 return false;
714 }
715 request
716 .seeded_context
717 .iter()
718 .map(|turn| turn.text.len())
719 .sum::<usize>()
720 <= 65_536
721}
722
723fn cache_strategies_match_bindings(
724 bindings: &[FrozenModelBinding],
725 strategies: &[Option<FrozenCacheStrategy>],
726) -> bool {
727 bindings.len() == strategies.len()
728 && bindings.iter().zip(strategies).all(|(binding, strategy)| {
729 let Some(strategy) = strategy else {
730 return true;
731 };
732 let Some(family) = cookie_agent_models::adapters::wire_adapter_for_protocol(
733 binding.descriptor.adapter_id.as_str(),
734 ) else {
735 return false;
736 };
737 matches!(
738 (family, strategy),
739 (
740 cookie_agent_models::adapters::OvenAdapterFamily::Anthropic
741 | cookie_agent_models::adapters::OvenAdapterFamily::AnthropicCompatible,
742 FrozenCacheStrategy::Anthropic { .. }
743 ) | (
744 cookie_agent_models::adapters::OvenAdapterFamily::AwsBedrockConverse,
745 FrozenCacheStrategy::Bedrock { .. }
746 ) | (
747 cookie_agent_models::adapters::OvenAdapterFamily::GoogleGemini
748 | cookie_agent_models::adapters::OvenAdapterFamily::GoogleVertexGemini,
749 FrozenCacheStrategy::Google { .. }
750 ) | (
751 cookie_agent_models::adapters::OvenAdapterFamily::OpenaiChat
752 | cookie_agent_models::adapters::OvenAdapterFamily::OpenaiResponses
753 | cookie_agent_models::adapters::OvenAdapterFamily::OpenaiCompatible
754 | cookie_agent_models::adapters::OvenAdapterFamily::AzureOpenaiChat
755 | cookie_agent_models::adapters::OvenAdapterFamily::AzureOpenaiResponses,
756 FrozenCacheStrategy::OpenAi { .. }
757 )
758 )
759 })
760}