use std::sync::Arc;
use async_trait::async_trait;
use crate::agent::agent_turn::execute::tool_dispatch::InternalToolDispatch;
use crate::agent::agent_turn::execute::tool_dispatch::ToolDispatch;
use crate::agent::agent_turn::execute::tool_execution_trait::{
ParallelPrefetchFailures, ParallelPrefetchParams, ToolExecutionHost,
};
use crate::cm_internal::tool_registry::{self, DispatchToolParams, HandlerId};
use crate::agent::per_coord::PerCoordinator;
use crate::agent::workflow_tool_dispatch;
use crate::request_chrome_trace::RequestTurnTrace;
async fn prefetch_parallel_approval_failures_impl(
params: ParallelPrefetchParams<'_>,
) -> ParallelPrefetchFailures {
let ParallelPrefetchParams {
tool_calls,
cfg,
web_tool_ctx,
handler_lookup,
} = params;
let mut prefetch_failures = ParallelPrefetchFailures::new();
if tool_calls.iter().any(|t| t.function.name == "http_fetch") {
prefetch_failures.extend(
tool_registry::prefetch_http_fetch_parallel_approvals(tool_calls, cfg, web_tool_ctx)
.await,
);
}
prefetch_failures.extend(
tool_registry::prefetch_parallel_syncdefault_approvals(
tool_calls,
web_tool_ctx,
handler_lookup,
)
.await,
);
prefetch_failures
}
pub struct CrabmateToolExecutionHost<'a> {
pub per_coord: &'a mut PerCoordinator,
pub request_chrome_trace: Option<Arc<RequestTurnTrace>>,
}
#[derive(Debug, Clone, Copy, Default)]
pub struct CrabmateParallelToolDispatch;
#[async_trait]
impl ToolExecutionHost for CrabmateToolExecutionHost<'_> {
async fn dispatch_tool_call(
&mut self,
name: &str,
p: DispatchToolParams<'_>,
) -> (String, Option<serde_json::Value>) {
if p.policy.handler_lookup.id_for(name) == HandlerId::Workflow {
workflow_tool_dispatch::dispatch_workflow_execute_tool(
p.runtime,
self.per_coord,
p.policy.cfg,
p.workspace.effective_working_dir,
p.workspace.workspace_is_set,
p.call.args,
self.request_chrome_trace.clone(),
)
.await
} else {
InternalToolDispatch.dispatch(p).await
}
}
async fn prefetch_parallel_approval_failures(
&self,
params: ParallelPrefetchParams<'_>,
) -> ParallelPrefetchFailures {
prefetch_parallel_approval_failures_impl(params).await
}
}
#[async_trait]
impl ToolExecutionHost for CrabmateParallelToolDispatch {
async fn dispatch_tool_call(
&mut self,
name: &str,
p: DispatchToolParams<'_>,
) -> (String, Option<serde_json::Value>) {
if p.policy.handler_lookup.id_for(name) == HandlerId::Workflow {
return (
"错误:并行只读批不支持 workflow_execute。".to_string(),
None,
);
}
InternalToolDispatch.dispatch(p).await
}
async fn prefetch_parallel_approval_failures(
&self,
params: ParallelPrefetchParams<'_>,
) -> ParallelPrefetchFailures {
prefetch_parallel_approval_failures_impl(params).await
}
}
pub struct ParallelHttpFetchParams<'a> {
pub cfg: &'a Arc<crate::config::AgentConfig>,
pub args: &'a str,
pub effective_working_dir: &'a std::path::Path,
pub read_file_turn_cache: Option<Arc<crate::read_file_turn_cache::ReadFileTurnCache>>,
pub workspace_changelist: Option<Arc<crate::workspace::changelist::WorkspaceChangelist>>,
pub long_term_memory: Option<Arc<crate::memory::long_term_memory::LongTermMemoryRuntime>>,
pub long_term_memory_scope_id: Option<String>,
}
impl CrabmateParallelToolDispatch {
pub async fn dispatch_parallel_http_fetch(params: ParallelHttpFetchParams<'_>) -> String {
let ParallelHttpFetchParams {
cfg,
args,
effective_working_dir,
read_file_turn_cache,
workspace_changelist,
long_term_memory,
long_term_memory_scope_id,
} = params;
let cfg = Arc::clone(cfg);
let args = args.to_string();
let wd = effective_working_dir.to_path_buf();
let rfc = read_file_turn_cache;
let wcl = workspace_changelist;
let ltm = long_term_memory;
let ltm_scope = long_term_memory_scope_id;
let span_http = tracing::Span::current();
tokio::task::spawn_blocking(move || {
let _g = span_http.enter();
let hosts = crate::memory_tool_hosts::DispatchMemoryHosts::from_dispatch_inputs(
cfg.as_ref(),
ltm,
ltm_scope.as_deref(),
);
let ctx = crate::tools::tool_context_for_with_read_cache_and_memory(
cfg.as_ref(),
cfg.command_exec.allowed_commands.as_ref(),
wd.as_path(),
rfc.as_ref().map(|a| a.as_ref()),
wcl.as_ref(),
Some(hosts.codebase_ref()),
hosts.long_term_ref(),
);
crate::tools::http_fetch::run_direct(&args, &ctx)
})
.await
.unwrap_or_else(|e| format!("工具执行 panic:{}", e))
}
}
pub use CrabmateParallelToolDispatch as CrabmateRegistryToolDispatch;