use crate::kernel::ChioKernel;
use crate::{
ChioReceipt, ChioReceiptBody, KernelError, ToolCallRequest, ToolCallResponse,
ToolInvocationCost, ToolServerOutput, Verdict,
};
#[allow(async_fn_in_trait)]
pub trait ToolEvaluator: Send + Sync {
async fn evaluate(
&self,
kernel: &ChioKernel,
request: &ToolCallRequest,
) -> Result<ToolCallResponse, KernelError>;
async fn evaluate_with_metadata(
&self,
kernel: &ChioKernel,
request: &ToolCallRequest,
extra_metadata: Option<serde_json::Value>,
) -> Result<ToolCallResponse, KernelError> {
let _ = extra_metadata;
self.evaluate(kernel, request).await
}
async fn validate_capability(
&self,
kernel: &ChioKernel,
request: &ToolCallRequest,
) -> Result<Verdict, KernelError> {
let response = self.evaluate(kernel, request).await?;
Ok(response.verdict)
}
async fn run_guards(
&self,
kernel: &ChioKernel,
request: &ToolCallRequest,
) -> Result<Verdict, KernelError> {
let response = self.evaluate(kernel, request).await?;
Ok(response.verdict)
}
async fn dispatch(
&self,
kernel: &ChioKernel,
request: &ToolCallRequest,
has_monetary_grant: bool,
) -> Result<(ToolServerOutput, Option<ToolInvocationCost>), KernelError> {
let _ = (kernel, request, has_monetary_grant);
Err(KernelError::DirectDispatchUnavailable)
}
async fn sign_receipt(
&self,
kernel: &ChioKernel,
body: ChioReceiptBody,
canonical_content: Vec<u8>,
) -> Result<ChioReceipt, KernelError> {
kernel
.sign_receipt_via_channel(body, canonical_content)
.await
}
}
#[allow(dead_code)]
#[derive(Debug, Default, Clone, Copy)]
pub struct BlockingToolEvaluator;
impl ToolEvaluator for BlockingToolEvaluator {
async fn evaluate(
&self,
kernel: &ChioKernel,
request: &ToolCallRequest,
) -> Result<ToolCallResponse, KernelError> {
match tokio::runtime::Handle::try_current() {
Ok(handle) if handle.runtime_flavor() == tokio::runtime::RuntimeFlavor::MultiThread => {
tokio::task::block_in_place(|| kernel.evaluate_tool_call_sync(request))
}
_ => kernel.evaluate_tool_call_sync(request),
}
}
async fn evaluate_with_metadata(
&self,
kernel: &ChioKernel,
request: &ToolCallRequest,
extra_metadata: Option<serde_json::Value>,
) -> Result<ToolCallResponse, KernelError> {
match tokio::runtime::Handle::try_current() {
Ok(handle) if handle.runtime_flavor() == tokio::runtime::RuntimeFlavor::MultiThread => {
tokio::task::block_in_place(|| {
kernel.evaluate_tool_call_blocking_with_metadata(request, extra_metadata)
})
}
_ => kernel.evaluate_tool_call_blocking_with_metadata(request, extra_metadata),
}
}
}