1use crate::connection_services::{ProviderCredentialStore, UserConnectionResolver};
4use crate::delegation_services::{
5 SessionCreationAuthority, SubagentNestingPolicy, SubagentSpawnStore,
6};
7use crate::event_emitter::EventEmitter;
8use crate::events::EventRequest;
9use crate::execution_loading::{AgentStore, SessionStore};
10use crate::image_services::ImageArtifactStore;
11use crate::session_files::SessionFileSystem;
12use crate::session_services::{
13 LeasedResourceStore, SessionResourceRegistry, SessionScheduleStore, SessionStorageStore,
14};
15use crate::tool_execution::{BudgetChecker, PaymentAuthority};
16use crate::typed_id::{SessionId, WorkspaceId};
17use std::any::{Any, TypeId};
18use std::collections::{HashMap, HashSet};
19use std::sync::Arc;
20
21#[derive(Clone, Default)]
32pub struct ReasoningEffortHandle {
33 inner: Arc<std::sync::RwLock<Option<everruns_provider::model::ReasoningEffort>>>,
34}
35
36impl ReasoningEffortHandle {
37 pub fn new() -> Self {
39 Self::default()
40 }
41
42 pub fn with_effort(effort: everruns_provider::model::ReasoningEffort) -> Self {
44 Self {
45 inner: Arc::new(std::sync::RwLock::new(Some(effort))),
46 }
47 }
48
49 pub fn set(&self, effort: Option<everruns_provider::model::ReasoningEffort>) {
53 let mut guard = self.inner.write().unwrap_or_else(|e| e.into_inner());
57 *guard = effort;
58 }
59
60 pub fn get(&self) -> Option<everruns_provider::model::ReasoningEffort> {
62 let guard = self.inner.read().unwrap_or_else(|e| e.into_inner());
65 *guard
66 }
67}
68
69impl std::fmt::Debug for ReasoningEffortHandle {
70 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
71 f.debug_struct("ReasoningEffortHandle")
72 .field("effort", &self.get())
73 .finish()
74 }
75}
76
77#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
83pub enum ToolContextService {
84 SessionFileSystem,
85 SessionStorageStore,
86 ImageArtifactStore,
87 ProviderCredentialStore,
88 UtilityLlmService,
89 McpInvoker,
90 EgressService,
91 MessageRetriever,
92 SessionStore,
93 AgentStore,
94 ConnectionResolver,
95 ScheduleStore,
96 SubagentSessionDelegate,
97 LeasedResourceStore,
98 SessionResourceRegistry,
99 SessionTaskRegistry,
100 EventEmitter,
101 CapabilityRegistry,
102 ToolRegistry,
103 OrgId,
104 BudgetChecker,
105 PaymentAuthority,
106 SessionCreationAuthority,
107 SubagentSpawnStore,
108 ReasoningEffortHandle,
109}
110
111impl ToolContextService {
112 pub const fn name(self) -> &'static str {
113 match self {
114 Self::SessionFileSystem => "SessionFileSystem",
115 Self::SessionStorageStore => "SessionStorageStore",
116 Self::ImageArtifactStore => "ImageArtifactStore",
117 Self::ProviderCredentialStore => "ProviderCredentialStore",
118 Self::UtilityLlmService => "UtilityLlmService",
119 Self::McpInvoker => "McpInvoker",
120 Self::EgressService => "EgressService",
121 Self::MessageRetriever => "MessageRetriever",
122 Self::SessionStore => "SessionStore",
123 Self::AgentStore => "AgentStore",
124 Self::ConnectionResolver => "ConnectionResolver",
125 Self::ScheduleStore => "SessionScheduleStore",
126 Self::SubagentSessionDelegate => "SubagentSessionDelegate",
127 Self::LeasedResourceStore => "LeasedResourceStore",
128 Self::SessionResourceRegistry => "SessionResourceRegistry",
129 Self::SessionTaskRegistry => "SessionTaskRegistry",
130 Self::EventEmitter => "EventEmitter",
131 Self::CapabilityRegistry => "CapabilityRegistry",
132 Self::ToolRegistry => "ToolRegistry",
133 Self::OrgId => "OrgId",
134 Self::BudgetChecker => "BudgetChecker",
135 Self::PaymentAuthority => "PaymentAuthority",
136 Self::SessionCreationAuthority => "SessionCreationAuthority",
137 Self::SubagentSpawnStore => "SubagentSpawnStore",
138 Self::ReasoningEffortHandle => "ReasoningEffortHandle",
139 }
140 }
141}
142
143#[derive(Clone, Default)]
148pub struct ToolContextServices {
149 pub file_store: Option<Arc<dyn SessionFileSystem>>,
150 pub storage_store: Option<Arc<dyn SessionStorageStore>>,
151 pub image_store: Option<Arc<dyn ImageArtifactStore>>,
152 pub provider_credential_store: Option<Arc<dyn ProviderCredentialStore>>,
153 pub utility_llm_service: Option<Arc<dyn crate::UtilityLlmService>>,
154 pub mcp_invoker: Option<Arc<dyn crate::McpToolInvoker>>,
155 pub egress_service: Option<Arc<dyn crate::EgressService>>,
156 pub message_retriever: Option<Arc<dyn crate::message_retriever::MessageRetriever>>,
157 pub session_store: Option<Arc<dyn SessionStore>>,
158 pub agent_store: Option<Arc<dyn AgentStore>>,
159 pub connection_resolver: Option<Arc<dyn UserConnectionResolver>>,
160 pub schedule_store: Option<Arc<dyn SessionScheduleStore>>,
161 pub subagent_delegate: Option<Arc<dyn crate::subagent_delegation::SubagentSessionDelegate>>,
162 pub extensions: ToolContextExtensions,
163 pub leased_resource_store: Option<Arc<dyn LeasedResourceStore>>,
164 pub session_resource_registry: Option<Arc<dyn SessionResourceRegistry>>,
165 pub session_task_registry: Option<Arc<dyn crate::session_task::SessionTaskRegistry>>,
166 pub event_emitter: Option<Arc<dyn EventEmitter>>,
167 pub capability_registry: Option<crate::capabilities::CapabilityRegistry>,
168 pub tool_registry: Option<Arc<crate::tools::ToolRegistry>>,
169 pub org_id: Option<crate::typed_id::OrgId>,
170 pub network_access: Option<crate::network_access::NetworkAccessList>,
171 pub budget_checker: Option<Arc<dyn BudgetChecker>>,
172 pub payment_authority: Option<Arc<dyn PaymentAuthority>>,
173 pub session_creation_authority: Option<Arc<dyn SessionCreationAuthority>>,
174 pub subagent_spawn_store: Option<Arc<dyn SubagentSpawnStore>>,
175 pub subagent_nesting_policy: SubagentNestingPolicy,
176 pub reasoning_effort_handle: Option<ReasoningEffortHandle>,
177}
178
179impl ToolContextServices {
180 pub fn provides(&self, service: ToolContextService) -> bool {
181 match service {
182 ToolContextService::SessionFileSystem => self.file_store.is_some(),
183 ToolContextService::SessionStorageStore => self.storage_store.is_some(),
184 ToolContextService::ImageArtifactStore => self.image_store.is_some(),
185 ToolContextService::ProviderCredentialStore => self.provider_credential_store.is_some(),
186 ToolContextService::UtilityLlmService => self.utility_llm_service.is_some(),
187 ToolContextService::McpInvoker => self.mcp_invoker.is_some(),
188 ToolContextService::EgressService => self.egress_service.is_some(),
189 ToolContextService::MessageRetriever => self.message_retriever.is_some(),
190 ToolContextService::SessionStore => self.session_store.is_some(),
191 ToolContextService::AgentStore => self.agent_store.is_some(),
192 ToolContextService::ConnectionResolver => self.connection_resolver.is_some(),
193 ToolContextService::ScheduleStore => self.schedule_store.is_some(),
194 ToolContextService::SubagentSessionDelegate => self.subagent_delegate.is_some(),
195 ToolContextService::LeasedResourceStore => self.leased_resource_store.is_some(),
196 ToolContextService::SessionResourceRegistry => self.session_resource_registry.is_some(),
197 ToolContextService::SessionTaskRegistry => self.session_task_registry.is_some(),
198 ToolContextService::EventEmitter => self.event_emitter.is_some(),
199 ToolContextService::CapabilityRegistry => self.capability_registry.is_some(),
200 ToolContextService::ToolRegistry => self.tool_registry.is_some(),
201 ToolContextService::OrgId => self.org_id.is_some(),
202 ToolContextService::BudgetChecker => self.budget_checker.is_some(),
203 ToolContextService::PaymentAuthority => self.payment_authority.is_some(),
204 ToolContextService::SessionCreationAuthority => {
205 self.session_creation_authority.is_some()
206 }
207 ToolContextService::SubagentSpawnStore => self.subagent_spawn_store.is_some(),
208 ToolContextService::ReasoningEffortHandle => self.reasoning_effort_handle.is_some(),
209 }
210 }
211}
212
213#[derive(Clone, Default)]
218pub struct ToolContextExtensions {
219 values: Arc<HashMap<TypeId, Arc<dyn Any + Send + Sync>>>,
220}
221
222impl ToolContextExtensions {
223 pub fn insert<T: Any + Send + Sync>(&mut self, value: Arc<T>) {
225 Arc::make_mut(&mut self.values).insert(TypeId::of::<T>(), value);
226 }
227
228 pub fn get<T: Any + Send + Sync>(&self) -> Option<Arc<T>> {
230 self.values
231 .get(&TypeId::of::<T>())
232 .and_then(|value| value.clone().downcast::<T>().ok())
233 }
234
235 pub fn is_empty(&self) -> bool {
236 self.values.is_empty()
237 }
238}
239
240impl std::fmt::Debug for ToolContextExtensions {
241 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
242 f.debug_struct("ToolContextExtensions")
243 .field("len", &self.values.len())
244 .finish()
245 }
246}
247
248#[derive(Clone)]
257pub struct ToolContext {
258 pub session_id: SessionId,
260 pub workspace_id: WorkspaceId,
267
268 pub file_store: Option<Arc<dyn SessionFileSystem>>,
270
271 pub storage_store: Option<Arc<dyn SessionStorageStore>>,
273
274 pub image_store: Option<Arc<dyn ImageArtifactStore>>,
276
277 pub provider_credential_store: Option<Arc<dyn ProviderCredentialStore>>,
279
280 pub utility_llm_service: Option<Arc<dyn crate::UtilityLlmService>>,
282
283 pub mcp_invoker: Option<Arc<dyn crate::McpToolInvoker>>,
289
290 pub egress_service: Option<Arc<dyn crate::EgressService>>,
292
293 pub message_retriever: Option<Arc<dyn crate::message_retriever::MessageRetriever>>,
295
296 pub session_store: Option<Arc<dyn SessionStore>>,
298
299 pub agent_store: Option<Arc<dyn AgentStore>>,
301
302 pub connection_resolver: Option<Arc<dyn UserConnectionResolver>>,
304
305 pub schedule_store: Option<Arc<dyn SessionScheduleStore>>,
307
308 pub subagent_delegate: Option<Arc<dyn crate::subagent_delegation::SubagentSessionDelegate>>,
312 pub extensions: ToolContextExtensions,
316 pub leased_resource_store: Option<Arc<dyn LeasedResourceStore>>,
318
319 pub session_resource_registry: Option<Arc<dyn SessionResourceRegistry>>,
321
322 pub session_task_registry: Option<Arc<dyn crate::session_task::SessionTaskRegistry>>,
325
326 pub event_emitter: Option<Arc<dyn EventEmitter>>,
329
330 pub event_context: Option<crate::events::EventContext>,
333
334 pub tool_call_id: Option<String>,
337 pub capability_registry: Option<crate::capabilities::CapabilityRegistry>,
339
340 pub tool_registry: Option<Arc<crate::tools::ToolRegistry>>,
343
344 pub visible_tool_names: Option<Arc<HashSet<String>>>,
348
349 pub org_id: Option<crate::typed_id::OrgId>,
351
352 pub network_access: Option<crate::network_access::NetworkAccessList>,
355
356 pub locale: Option<String>,
360
361 pub budget_checker: Option<Arc<dyn BudgetChecker>>,
363
364 pub payment_authority: Option<Arc<dyn PaymentAuthority>>,
366
367 pub session_creation_authority: Option<Arc<dyn SessionCreationAuthority>>,
369
370 pub subagent_spawn_store: Option<Arc<dyn SubagentSpawnStore>>,
374
375 pub subagent_nesting_policy: SubagentNestingPolicy,
377
378 pub reasoning_effort_handle: Option<ReasoningEffortHandle>,
382
383 pub cancellation: Option<tokio_util::sync::CancellationToken>,
393}
394
395impl ToolContext {
396 pub fn workspace_fs_key(&self) -> SessionId {
401 SessionId::from_uuid(self.workspace_id.uuid())
402 }
403
404 pub fn with_workspace_id(mut self, workspace_id: WorkspaceId) -> Self {
406 self.workspace_id = workspace_id;
407 self
408 }
409
410 pub fn new(session_id: SessionId) -> Self {
412 Self {
413 session_id,
414 workspace_id: WorkspaceId::from_uuid(session_id.uuid()),
415 file_store: None,
416 storage_store: None,
417 image_store: None,
418 provider_credential_store: None,
419 utility_llm_service: None,
420 mcp_invoker: None,
421 egress_service: None,
422 message_retriever: None,
423 session_store: None,
424 agent_store: None,
425 connection_resolver: None,
426 schedule_store: None,
427 subagent_delegate: None,
428 extensions: ToolContextExtensions::default(),
429 leased_resource_store: None,
430 session_resource_registry: None,
431 session_task_registry: None,
432 event_emitter: None,
433 event_context: None,
434 tool_call_id: None,
435 capability_registry: None,
436 tool_registry: None,
437 visible_tool_names: None,
438 org_id: None,
439 network_access: None,
440 locale: None,
441 budget_checker: None,
442 payment_authority: None,
443 session_creation_authority: None,
444 subagent_spawn_store: None,
445 subagent_nesting_policy: SubagentNestingPolicy::default(),
446 reasoning_effort_handle: None,
447 cancellation: None,
448 }
449 }
450
451 pub fn from_services(session_id: SessionId, services: &ToolContextServices) -> Self {
453 Self {
454 session_id,
455 workspace_id: WorkspaceId::from_uuid(session_id.uuid()),
456 file_store: services.file_store.clone(),
457 storage_store: services.storage_store.clone(),
458 image_store: services.image_store.clone(),
459 provider_credential_store: services.provider_credential_store.clone(),
460 utility_llm_service: services.utility_llm_service.clone(),
461 mcp_invoker: services.mcp_invoker.clone(),
462 egress_service: services.egress_service.clone(),
463 message_retriever: services.message_retriever.clone(),
464 session_store: services.session_store.clone(),
465 agent_store: services.agent_store.clone(),
466 connection_resolver: services.connection_resolver.clone(),
467 schedule_store: services.schedule_store.clone(),
468 subagent_delegate: services.subagent_delegate.clone(),
469 extensions: services.extensions.clone(),
470 leased_resource_store: services.leased_resource_store.clone(),
471 session_resource_registry: services.session_resource_registry.clone(),
472 session_task_registry: services.session_task_registry.clone(),
473 event_emitter: services.event_emitter.clone(),
474 event_context: None,
475 tool_call_id: None,
476 capability_registry: services.capability_registry.clone(),
477 tool_registry: services.tool_registry.clone(),
478 visible_tool_names: None,
479 org_id: services.org_id,
480 network_access: services.network_access.clone(),
481 locale: None,
482 budget_checker: services.budget_checker.clone(),
483 payment_authority: services.payment_authority.clone(),
484 session_creation_authority: services.session_creation_authority.clone(),
485 subagent_spawn_store: services.subagent_spawn_store.clone(),
486 subagent_nesting_policy: services.subagent_nesting_policy,
487 reasoning_effort_handle: services.reasoning_effort_handle.clone(),
488 cancellation: None,
489 }
490 }
491
492 pub fn with_file_store(session_id: SessionId, file_store: Arc<dyn SessionFileSystem>) -> Self {
494 Self {
495 session_id,
496 workspace_id: WorkspaceId::from_uuid(session_id.uuid()),
497 file_store: Some(file_store),
498 storage_store: None,
499 image_store: None,
500 provider_credential_store: None,
501 utility_llm_service: None,
502 mcp_invoker: None,
503 egress_service: None,
504 message_retriever: None,
505 session_store: None,
506 agent_store: None,
507 connection_resolver: None,
508 schedule_store: None,
509 subagent_delegate: None,
510 extensions: ToolContextExtensions::default(),
511 leased_resource_store: None,
512 session_resource_registry: None,
513 session_task_registry: None,
514 event_emitter: None,
515 event_context: None,
516 tool_call_id: None,
517 capability_registry: None,
518 tool_registry: None,
519 visible_tool_names: None,
520 org_id: None,
521 network_access: None,
522 locale: None,
523 budget_checker: None,
524 payment_authority: None,
525 session_creation_authority: None,
526 subagent_spawn_store: None,
527 subagent_nesting_policy: SubagentNestingPolicy::default(),
528 reasoning_effort_handle: None,
529 cancellation: None,
530 }
531 }
532
533 pub fn with_storage_store(
535 session_id: SessionId,
536 storage_store: Arc<dyn SessionStorageStore>,
537 ) -> Self {
538 Self {
539 session_id,
540 workspace_id: WorkspaceId::from_uuid(session_id.uuid()),
541 file_store: None,
542 storage_store: Some(storage_store),
543 image_store: None,
544 provider_credential_store: None,
545 utility_llm_service: None,
546 mcp_invoker: None,
547 egress_service: None,
548 message_retriever: None,
549 session_store: None,
550 agent_store: None,
551 connection_resolver: None,
552 schedule_store: None,
553 subagent_delegate: None,
554 extensions: ToolContextExtensions::default(),
555 leased_resource_store: None,
556 session_resource_registry: None,
557 session_task_registry: None,
558 event_emitter: None,
559 event_context: None,
560 tool_call_id: None,
561 capability_registry: None,
562 tool_registry: None,
563 visible_tool_names: None,
564 org_id: None,
565 network_access: None,
566 locale: None,
567 budget_checker: None,
568 payment_authority: None,
569 session_creation_authority: None,
570 subagent_spawn_store: None,
571 subagent_nesting_policy: SubagentNestingPolicy::default(),
572 reasoning_effort_handle: None,
573 cancellation: None,
574 }
575 }
576
577 pub fn with_stores(
579 session_id: SessionId,
580 file_store: Arc<dyn SessionFileSystem>,
581 storage_store: Arc<dyn SessionStorageStore>,
582 ) -> Self {
583 Self {
584 session_id,
585 workspace_id: WorkspaceId::from_uuid(session_id.uuid()),
586 file_store: Some(file_store),
587 storage_store: Some(storage_store),
588 image_store: None,
589 provider_credential_store: None,
590 utility_llm_service: None,
591 mcp_invoker: None,
592 egress_service: None,
593 message_retriever: None,
594 session_store: None,
595 agent_store: None,
596 connection_resolver: None,
597 schedule_store: None,
598 subagent_delegate: None,
599 extensions: ToolContextExtensions::default(),
600 leased_resource_store: None,
601 session_resource_registry: None,
602 session_task_registry: None,
603 event_emitter: None,
604 event_context: None,
605 tool_call_id: None,
606 capability_registry: None,
607 tool_registry: None,
608 visible_tool_names: None,
609 org_id: None,
610 network_access: None,
611 locale: None,
612 budget_checker: None,
613 payment_authority: None,
614 session_creation_authority: None,
615 subagent_spawn_store: None,
616 subagent_nesting_policy: SubagentNestingPolicy::default(),
617 reasoning_effort_handle: None,
618 cancellation: None,
619 }
620 }
621
622 pub fn with_message_retriever(
624 mut self,
625 retriever: Arc<dyn crate::message_retriever::MessageRetriever>,
626 ) -> Self {
627 self.message_retriever = Some(retriever);
628 self
629 }
630
631 pub fn with_session_store(mut self, store: Arc<dyn SessionStore>) -> Self {
633 self.session_store = Some(store);
634 self
635 }
636
637 pub fn with_cancellation(mut self, token: tokio_util::sync::CancellationToken) -> Self {
643 self.cancellation = Some(token);
644 self
645 }
646
647 pub fn is_cancelled(&self) -> bool {
650 self.cancellation
651 .as_ref()
652 .is_some_and(|token| token.is_cancelled())
653 }
654
655 pub fn with_reasoning_effort_handle(mut self, handle: ReasoningEffortHandle) -> Self {
656 self.reasoning_effort_handle = Some(handle);
657 self
658 }
659
660 pub fn with_agent_store(mut self, store: Arc<dyn AgentStore>) -> Self {
662 self.agent_store = Some(store);
663 self
664 }
665
666 pub fn with_connection_resolver(mut self, resolver: Arc<dyn UserConnectionResolver>) -> Self {
668 self.connection_resolver = Some(resolver);
669 self
670 }
671
672 pub fn with_image_store(
674 session_id: SessionId,
675 image_store: Arc<dyn ImageArtifactStore>,
676 ) -> Self {
677 Self {
678 session_id,
679 workspace_id: WorkspaceId::from_uuid(session_id.uuid()),
680 file_store: None,
681 storage_store: None,
682 image_store: Some(image_store),
683 provider_credential_store: None,
684 utility_llm_service: None,
685 mcp_invoker: None,
686 egress_service: None,
687 message_retriever: None,
688 session_store: None,
689 agent_store: None,
690 connection_resolver: None,
691 schedule_store: None,
692 subagent_delegate: None,
693 extensions: ToolContextExtensions::default(),
694 leased_resource_store: None,
695 session_resource_registry: None,
696 session_task_registry: None,
697 event_emitter: None,
698 event_context: None,
699 tool_call_id: None,
700 capability_registry: None,
701 tool_registry: None,
702 visible_tool_names: None,
703 org_id: None,
704 network_access: None,
705 locale: None,
706 budget_checker: None,
707 payment_authority: None,
708 session_creation_authority: None,
709 subagent_spawn_store: None,
710 subagent_nesting_policy: SubagentNestingPolicy::default(),
711 reasoning_effort_handle: None,
712 cancellation: None,
713 }
714 }
715
716 pub fn with_provider_credential_store(
718 mut self,
719 store: Arc<dyn ProviderCredentialStore>,
720 ) -> Self {
721 self.provider_credential_store = Some(store);
722 self
723 }
724
725 pub fn with_utility_llm_service(mut self, service: Arc<dyn crate::UtilityLlmService>) -> Self {
727 self.utility_llm_service = Some(service);
728 self
729 }
730
731 pub fn with_mcp_invoker(mut self, invoker: Arc<dyn crate::McpToolInvoker>) -> Self {
733 self.mcp_invoker = Some(invoker);
734 self
735 }
736
737 pub fn with_egress_service(mut self, service: Arc<dyn crate::EgressService>) -> Self {
739 self.egress_service = Some(service);
740 self
741 }
742
743 pub fn with_egress_service_opt(
746 mut self,
747 service: Option<Arc<dyn crate::EgressService>>,
748 ) -> Self {
749 if let Some(service) = service {
750 self.egress_service = Some(service);
751 }
752 self
753 }
754
755 pub fn with_storage_store_arc(mut self, store: Arc<dyn SessionStorageStore>) -> Self {
757 self.storage_store = Some(store);
758 self
759 }
760
761 pub fn with_schedule_store(mut self, store: Arc<dyn SessionScheduleStore>) -> Self {
763 self.schedule_store = Some(store);
764 self
765 }
766
767 pub fn with_subagent_delegate(
769 mut self,
770 delegate: Arc<dyn crate::subagent_delegation::SubagentSessionDelegate>,
771 ) -> Self {
772 self.subagent_delegate = Some(delegate);
773 self
774 }
775
776 pub fn with_extension<T: std::any::Any + Send + Sync>(mut self, value: Arc<T>) -> Self {
779 self.extensions.insert(value);
780 self
781 }
782
783 pub fn extension<T: std::any::Any + Send + Sync>(&self) -> Option<Arc<T>> {
786 self.extensions.get::<T>()
787 }
788
789 pub fn with_leased_resource_store(mut self, store: Arc<dyn LeasedResourceStore>) -> Self {
791 self.leased_resource_store = Some(store);
792 self
793 }
794
795 pub fn with_session_resource_registry(
797 mut self,
798 registry: Arc<dyn SessionResourceRegistry>,
799 ) -> Self {
800 self.session_resource_registry = Some(registry);
801 self
802 }
803
804 pub fn with_session_task_registry(
806 mut self,
807 registry: Arc<dyn crate::session_task::SessionTaskRegistry>,
808 ) -> Self {
809 self.session_task_registry = Some(registry);
810 self
811 }
812
813 pub fn with_org_id(mut self, org_id: crate::typed_id::OrgId) -> Self {
815 self.org_id = Some(org_id);
816 self
817 }
818
819 pub fn with_tool_registry(mut self, registry: Arc<crate::tools::ToolRegistry>) -> Self {
821 self.tool_registry = Some(registry);
822 self
823 }
824
825 pub fn with_visible_tool_names(mut self, names: Arc<HashSet<String>>) -> Self {
827 self.visible_tool_names = Some(names);
828 self
829 }
830
831 pub fn with_network_access(
833 mut self,
834 network_access: Option<crate::network_access::NetworkAccessList>,
835 ) -> Self {
836 self.network_access = network_access;
837 self
838 }
839
840 pub fn with_payment_authority(mut self, authority: Arc<dyn PaymentAuthority>) -> Self {
842 self.payment_authority = Some(authority);
843 self
844 }
845
846 pub fn with_subagent_spawn_store(mut self, store: Arc<dyn SubagentSpawnStore>) -> Self {
848 self.subagent_spawn_store = Some(store);
849 self
850 }
851
852 pub fn with_subagent_nesting_policy(mut self, policy: SubagentNestingPolicy) -> Self {
854 self.subagent_nesting_policy = policy;
855 self
856 }
857
858 pub async fn emit_progress(&self, tool_name: &str, message: &str) {
863 let (Some(emitter), Some(ctx), Some(call_id)) =
864 (&self.event_emitter, &self.event_context, &self.tool_call_id)
865 else {
866 return;
867 };
868 if let Err(e) = emitter
869 .emit(EventRequest::new(
870 self.session_id,
871 ctx.clone(),
872 crate::events::ToolProgressData {
873 tool_call_id: call_id.clone(),
874 tool_name: tool_name.to_string(),
875 message: message.to_string(),
876 display_name: None,
877 },
878 ))
879 .await
880 {
881 tracing::debug!(
882 tool_call_id = call_id,
883 tool_name,
884 error = %e,
885 "Failed to emit tool.progress event"
886 );
887 }
888 }
889
890 pub async fn emit_tool_output(&self, tool_name: &str, delta: &str, stream: &str) {
895 let (Some(emitter), Some(ctx), Some(call_id)) =
896 (&self.event_emitter, &self.event_context, &self.tool_call_id)
897 else {
898 return;
899 };
900 if let Err(e) = emitter
901 .emit(EventRequest::new(
902 self.session_id,
903 ctx.clone(),
904 crate::events::ToolOutputDeltaData {
905 tool_call_id: call_id.clone(),
906 tool_name: tool_name.to_string(),
907 delta: delta.to_string(),
908 stream: stream.to_string(),
909 },
910 ))
911 .await
912 {
913 tracing::debug!(
914 tool_call_id = call_id,
915 tool_name,
916 error = %e,
917 "Failed to emit tool.output.delta event"
918 );
919 }
920 }
921}
922
923impl std::fmt::Debug for ToolContext {
924 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
925 f.debug_struct("ToolContext")
926 .field("session_id", &self.session_id)
927 .field("file_store", &self.file_store.is_some())
928 .field("storage_store", &self.storage_store.is_some())
929 .field("image_store", &self.image_store.is_some())
930 .field(
931 "provider_credential_store",
932 &self.provider_credential_store.is_some(),
933 )
934 .field("utility_llm_service", &self.utility_llm_service.is_some())
935 .field("egress_service", &self.egress_service.is_some())
936 .field("message_retriever", &self.message_retriever.is_some())
937 .field("session_store", &self.session_store.is_some())
938 .field("agent_store", &self.agent_store.is_some())
939 .field("connection_resolver", &self.connection_resolver.is_some())
940 .field("schedule_store", &self.schedule_store.is_some())
941 .field("subagent_delegate", &self.subagent_delegate.is_some())
942 .field(
943 "leased_resource_store",
944 &self.leased_resource_store.is_some(),
945 )
946 .field("event_emitter", &self.event_emitter.is_some())
947 .field("tool_registry", &self.tool_registry.is_some())
948 .field("payment_authority", &self.payment_authority.is_some())
949 .field("subagent_spawn_store", &self.subagent_spawn_store.is_some())
950 .field("subagent_nesting_policy", &self.subagent_nesting_policy)
951 .field("org_id", &self.org_id)
952 .finish()
953 }
954}