a3s-code-core 3.0.0

A3S Code Core - Embeddable AI agent library with tool execution
Documentation
use super::execution_state::ExecutionLoopState;
use super::tool_result_runtime::{push_tool_result_message, NormalizedToolResult};
use super::{AgentEvent, AgentLoop};
use crate::llm::ToolCall;
use std::time::Instant;
use tokio::sync::mpsc;

pub(super) struct ToolCompletionInput<'a> {
    pub(super) tool_call: &'a ToolCall,
    pub(super) event_tx: &'a Option<mpsc::Sender<AgentEvent>>,
    pub(super) session_id: Option<&'a str>,
    pub(super) effective_prompt: &'a str,
    pub(super) tool_start: Instant,
    pub(super) normalized: NormalizedToolResult,
}

impl AgentLoop {
    pub(super) async fn complete_tool_call(
        &self,
        state: &mut ExecutionLoopState,
        input: ToolCompletionInput<'_>,
    ) {
        let ToolCompletionInput {
            tool_call,
            event_tx,
            session_id,
            effective_prompt,
            tool_start,
            normalized,
        } = input;
        let tool_duration = tool_start.elapsed();
        crate::telemetry::record_tool_result(normalized.exit_code, tool_duration);
        Self::collect_verification_report(&mut state.verification_reports, &normalized.metadata);

        let output = if let Some(ref sp) = self.config.security_provider {
            sp.sanitize_output(&normalized.output)
        } else {
            normalized.output.clone()
        };

        state.remember_tool_signature(&tool_call.name, &tool_call.args, normalized.is_error);

        self.fire_post_tool_use(
            session_id.unwrap_or(""),
            &tool_call.name,
            &tool_call.args,
            &output,
            normalized.exit_code == 0,
            tool_duration.as_millis() as u64,
        )
        .await;

        self.remember_tool_result(
            effective_prompt,
            &tool_call.name,
            &output,
            normalized.exit_code,
            event_tx,
        )
        .await;

        if let Some(tx) = event_tx {
            tx.send(AgentEvent::ToolEnd {
                id: tool_call.id.clone(),
                name: tool_call.name.clone(),
                output: output.clone(),
                exit_code: normalized.exit_code,
                metadata: normalized.metadata.clone(),
                error_kind: normalized.error_kind.clone(),
            })
            .await
            .ok();
        }

        push_tool_result_message(
            state,
            &tool_call.id,
            &output,
            normalized.is_error,
            normalized.images,
        );
    }
}