a3s_code_core/agent_api/
governance_facade.rs1use super::*;
2
3impl AgentSession {
4 pub fn set_budget_guard(
14 &self,
15 guard: Option<Arc<dyn crate::budget::BudgetGuard>>,
16 ) -> crate::error::Result<()> {
17 self.close_handle.mutate_immediate(|| {
18 let mut slot = self
19 .runtime_budget_guard
20 .lock()
21 .unwrap_or_else(|p| p.into_inner());
22 *slot = guard;
23 drop(slot);
24 self.refresh_task_delegation_tools();
29 self.refresh_skill_tools();
30 })
31 }
32
33 pub fn budget_guard(&self) -> Option<Arc<dyn crate::budget::BudgetGuard>> {
36 self.runtime_budget_guard
37 .lock()
38 .unwrap_or_else(|p| p.into_inner())
39 .clone()
40 }
41
42 pub fn set_agent_style(
47 &self,
48 style: Option<crate::prompts::AgentStyle>,
49 ) -> crate::error::Result<()> {
50 self.close_handle.mutate_immediate(|| {
51 let mut slot = self
52 .runtime_agent_style
53 .lock()
54 .unwrap_or_else(|p| p.into_inner());
55 *slot = Some(style);
56 Ok(())
57 })?
58 }
59
60 pub fn set_output_language(
65 &self,
66 language: Option<impl Into<String>>,
67 ) -> crate::error::Result<()> {
68 let language = language.map(Into::into).and_then(|value| {
69 let trimmed = value.trim();
70 (!trimmed.is_empty()).then(|| trimmed.to_string())
71 });
72 self.close_handle.mutate_immediate(|| {
73 let mut slot = self
74 .runtime_output_language
75 .lock()
76 .unwrap_or_else(|p| p.into_inner());
77 *slot = Some(language);
78 Ok(())
79 })?
80 }
81
82 pub(crate) fn runtime_agent_style_override(
85 &self,
86 ) -> Option<Option<crate::prompts::AgentStyle>> {
87 *self
88 .runtime_agent_style
89 .lock()
90 .unwrap_or_else(|p| p.into_inner())
91 }
92
93 pub(crate) fn runtime_output_language_override(&self) -> Option<Option<String>> {
96 self.runtime_output_language
97 .lock()
98 .unwrap_or_else(|p| p.into_inner())
99 .clone()
100 }
101
102 pub fn set_session_checkpoint_export_sink(
108 &self,
109 sink: Option<Arc<dyn crate::session_checkpoint::SessionCheckpointExportSink>>,
110 ) -> crate::error::Result<()> {
111 self.close_handle.mutate_immediate(|| {
112 let mut slot = self
113 .runtime_session_checkpoint_export_sink
114 .lock()
115 .unwrap_or_else(|p| p.into_inner());
116 *slot = sink;
117 })
118 }
119
120 pub fn session_checkpoint_export_sink(
122 &self,
123 ) -> Option<Arc<dyn crate::session_checkpoint::SessionCheckpointExportSink>> {
124 self.runtime_session_checkpoint_export_sink
125 .lock()
126 .unwrap_or_else(|p| p.into_inner())
127 .clone()
128 }
129
130 pub async fn pending_confirmations(&self) -> Vec<PendingConfirmationInfo> {
132 HitlControl::from_session(self)
133 .pending_confirmations()
134 .await
135 }
136
137 pub async fn confirm_tool_use(
142 &self,
143 tool_id: &str,
144 approved: bool,
145 reason: Option<String>,
146 ) -> Result<bool> {
147 HitlControl::from_session(self)
148 .confirm_tool_use(tool_id, approved, reason)
149 .await
150 }
151
152 pub async fn cancel_confirmations(&self) -> usize {
154 HitlControl::from_session(self).cancel_confirmations().await
155 }
156
157 pub fn verification_reports(&self) -> Vec<crate::verification::VerificationReport> {
159 VerificationRuntime::from_session(self).reports()
160 }
161
162 pub fn verification_summary(&self) -> crate::verification::VerificationSummary {
164 VerificationRuntime::from_session(self).summary()
165 }
166
167 pub fn verification_summary_text(&self) -> String {
169 VerificationRuntime::from_session(self).summary_text()
170 }
171
172 pub fn record_verification_reports(
174 &self,
175 reports: impl IntoIterator<Item = crate::verification::VerificationReport>,
176 ) {
177 VerificationRuntime::from_session(self).record(reports);
178 }
179
180 pub fn register_hook(&self, hook: crate::hooks::Hook) -> crate::error::Result<()> {
182 self.close_handle.mutate_immediate(|| {
183 self.ensure_compatibility_name_available(
184 crate::capability::CapabilityKind::Hook,
185 &hook.id,
186 )?;
187 HookControl::from_session(self).register_hook(hook);
188 Ok(())
189 })?
190 }
191
192 pub fn unregister_hook(
194 &self,
195 hook_id: &str,
196 ) -> crate::error::Result<Option<crate::hooks::Hook>> {
197 self.close_handle.mutate_immediate(|| {
198 self.ensure_compatibility_name_available(
199 crate::capability::CapabilityKind::Hook,
200 hook_id,
201 )?;
202 Ok(HookControl::from_session(self).unregister_hook(hook_id))
203 })?
204 }
205
206 pub fn register_hook_handler(
208 &self,
209 hook_id: &str,
210 handler: Arc<dyn crate::hooks::HookHandler>,
211 ) -> crate::error::Result<()> {
212 let mut pending_handler = Some(handler);
213 let retired = self.close_handle.mutate_immediate(|| {
214 self.ensure_compatibility_name_available(
215 crate::capability::CapabilityKind::Hook,
216 hook_id,
217 )?;
218 let handler = pending_handler.take().ok_or_else(|| {
219 crate::error::CodeError::Capability(
220 crate::capability::CapabilityRuntimeError::RuntimeValueInvalid {
221 kind: crate::capability::CapabilityKind::Hook,
222 public_name: hook_id.to_owned(),
223 message: "Hook handler mutation was already consumed".to_owned(),
224 },
225 )
226 })?;
227 Ok::<_, crate::error::CodeError>(
228 HookControl::from_session(self).register_hook_handler(hook_id, handler),
229 )
230 })??;
231 drop(retired);
232 Ok(())
233 }
234
235 pub fn unregister_hook_handler(&self, hook_id: &str) -> crate::error::Result<()> {
237 let retired = self.close_handle.mutate_immediate(|| {
238 self.ensure_compatibility_name_available(
239 crate::capability::CapabilityKind::Hook,
240 hook_id,
241 )?;
242 Ok::<_, crate::error::CodeError>(
243 HookControl::from_session(self).unregister_hook_handler(hook_id),
244 )
245 })??;
246 drop(retired);
247 Ok(())
248 }
249
250 pub fn register_hook_registration(
256 &self,
257 hook: crate::hooks::Hook,
258 handler: Option<Arc<dyn crate::hooks::HookHandler>>,
259 ) -> crate::error::Result<()> {
260 let mut pending_handler = Some(handler);
261 let retired = self.close_handle.mutate_immediate(|| {
262 self.ensure_compatibility_name_available(
263 crate::capability::CapabilityKind::Hook,
264 &hook.id,
265 )?;
266 let handler = pending_handler.take().ok_or_else(|| {
267 crate::error::CodeError::Capability(
268 crate::capability::CapabilityRuntimeError::RuntimeValueInvalid {
269 kind: crate::capability::CapabilityKind::Hook,
270 public_name: hook.id.clone(),
271 message: "Hook registration was already consumed".to_owned(),
272 },
273 )
274 })?;
275 Ok::<_, crate::error::CodeError>(
276 HookControl::from_session(self).register_hook_registration(hook, handler),
277 )
278 })??;
279 drop(retired);
280 Ok(())
281 }
282
283 pub fn unregister_hook_registration(
285 &self,
286 hook_id: &str,
287 ) -> crate::error::Result<Option<crate::hooks::Hook>> {
288 let (retired_hook, retired_handler) = self.close_handle.mutate_immediate(|| {
289 self.ensure_compatibility_name_available(
290 crate::capability::CapabilityKind::Hook,
291 hook_id,
292 )?;
293 Ok::<_, crate::error::CodeError>(
294 HookControl::from_session(self).unregister_hook_registration(hook_id),
295 )
296 })??;
297 let removed = retired_hook.as_deref().cloned();
298 drop((retired_hook, retired_handler));
299 Ok(removed)
300 }
301
302 pub fn hook_count(&self) -> usize {
304 HookControl::from_session(self).hook_count()
305 }
306
307 pub async fn verify_commands(
309 &self,
310 subject: &str,
311 commands: &[crate::verification::VerificationCommand],
312 ) -> Result<crate::verification::VerificationReport> {
313 VerificationRuntime::from_session(self)
314 .verify_commands(subject, commands)
315 .await
316 }
317
318 pub fn verification_presets(&self) -> Vec<crate::verification::VerificationPreset> {
320 VerificationRuntime::from_session(self).presets()
321 }
322}