use crate::value::{VmError, VmValue};
use super::agent_tools;
type HookDispatchResult<T> = (Result<T, VmError>, Vec<serde_json::Value>);
#[inline(never)]
pub(super) fn pin_pre_tool_interception<'a>(
ctx: &'a crate::vm::AsyncBuiltinCtx,
tool_id: String,
tool_name: &'a str,
tool_args: &'a mut serde_json::Value,
) -> std::pin::Pin<Box<impl std::future::Future<Output = HookDispatchResult<Option<String>>> + 'a>>
{
Box::pin(async move {
let (action, mut reports) = crate::orchestration::scope_hook_reminder_reports(
crate::agent_sessions::scope_current_tool_call(tool_id.clone(), async {
crate::orchestration::run_pre_tool_hooks_with_ctx(Some(ctx), tool_name, tool_args)
.await
}),
)
.await;
let action = match action {
Ok(action) => action,
Err(error) => return (Err(error), reports),
};
let (result, applied_reports) = crate::orchestration::scope_hook_reminder_reports(
crate::agent_sessions::scope_current_tool_call(tool_id, async {
crate::orchestration::apply_pre_tool_action(action, tool_args)
}),
)
.await;
reports.extend(applied_reports);
(result, reports)
})
}
#[inline(never)]
pub(super) fn pin_post_tool_interception<'a>(
ctx: &'a crate::vm::AsyncBuiltinCtx,
tool_id: String,
tool_name: &'a str,
tool_args: &'a serde_json::Value,
rendered: &'a str,
) -> std::pin::Pin<
Box<
impl std::future::Future<
Output = HookDispatchResult<crate::orchestration::PostToolHookResult>,
> + 'a,
>,
> {
Box::pin(crate::orchestration::scope_hook_reminder_reports(
crate::agent_sessions::scope_current_tool_call(tool_id, async move {
crate::orchestration::run_post_tool_hooks_with_ctx(
Some(ctx),
tool_name,
tool_args,
rendered,
)
.await
}),
))
}
pub(super) struct ToolDispatchRequest<'a> {
pub(super) ctx: &'a crate::vm::AsyncBuiltinCtx,
pub(super) tool_name: &'a str,
pub(super) tool_args: &'a serde_json::Value,
pub(super) tools: Option<&'a VmValue>,
pub(super) mcp_clients:
Option<&'a std::collections::BTreeMap<String, crate::mcp::VmMcpClientHandle>>,
pub(super) bridge: Option<&'a std::sync::Arc<crate::bridge::HostBridge>>,
pub(super) tool_retries: usize,
pub(super) tool_backoff_ms: u64,
pub(super) prepared_invocation:
Option<std::sync::Arc<super::agent_tool_preparation::PreparedInvocation>>,
}
#[inline(never)]
pub(super) fn pin_scoped_tool_dispatch<'a>(
session_id: String,
tool_id: String,
request: ToolDispatchRequest<'a>,
) -> std::pin::Pin<Box<impl std::future::Future<Output = agent_tools::ToolDispatchOutcome> + 'a>> {
Box::pin(crate::orchestration::scope_agent_session(
session_id,
crate::agent_sessions::scope_current_tool_call(tool_id, async move {
super::agent_tool_preparation::scope(
request.prepared_invocation,
agent_tools::dispatch_tool_execution_with_mcp(
Some(request.ctx),
request.tool_name,
request.tool_args,
request.tools,
request.mcp_clients,
request.bridge,
request.tool_retries,
request.tool_backoff_ms,
),
)
.await
}),
))
}