MCPcopy Create free account
hub / github.com/AI45Lab/Code / call_llm

Method call_llm

core/src/agent/llm_turn.rs:348–430  ·  view source on GitHub ↗

Call the LLM, handling streaming vs non-streaming internally. Streaming events (`TextDelta`, `ToolStart`) are forwarded to `event_tx` as they arrive. Non-streaming mode simply awaits the complete response. Tool definitions are selected per turn by the centralized tool selector. Returns `Err` on any LLM API failure. The circuit breaker in `execute_loop` wraps this call with retry logic for non-s

(
        &self,
        messages: &[Message],
        system: Option<&str>,
        event_tx: &Option<mpsc::Sender<AgentEvent>>,
        cancel_token: &tokio_util::sync::CancellationToken,
    )

Source from the content-addressed store, hash-verified

346 /// Returns `Err` on any LLM API failure. The circuit breaker in
347 /// `execute_loop` wraps this call with retry logic for non-streaming mode.
348 async fn call_llm(
349 &self,
350 messages: &[Message],
351 system: Option<&str>,
352 event_tx: &Option<mpsc::Sender<AgentEvent>>,
353 cancel_token: &tokio_util::sync::CancellationToken,
354 ) -> anyhow::Result<LlmResponse> {
355 let tools = crate::tools::select_tools_for_messages(&self.config.tools, messages);
356
357 if event_tx.is_some() {
358 let mut stream_rx = match self
359 .llm_client
360 .complete_streaming(messages, system, &tools, cancel_token.clone())
361 .await
362 {
363 Ok(rx) => rx,
364 Err(stream_error) => {
365 // Do not fall back to non-streaming if cancelled — propagate cancellation
366 if cancel_token.is_cancelled() {
367 anyhow::bail!("Operation cancelled by user");
368 }
369 tracing::warn!(
370 error = %stream_error,
371 "LLM streaming setup failed; falling back to non-streaming completion"
372 );
373 return self
374 .llm_client
375 .complete(messages, system, &tools)
376 .await
377 .with_context(|| {
378 format!(
379 "LLM streaming call failed ({stream_error}); non-streaming fallback also failed"
380 )
381 });
382 }
383 };
384
385 let mut final_response: Option<LlmResponse> = None;
386 loop {
387 tokio::select! {
388 _ = cancel_token.cancelled() => {
389 tracing::info!("🛑 LLM streaming cancelled by CancellationToken");
390 anyhow::bail!("Operation cancelled by user");
391 }
392 event = stream_rx.recv() => {
393 match event {
394 Some(crate::llm::StreamEvent::TextDelta(text)) => {
395 if let Some(tx) = event_tx {
396 tx.send(AgentEvent::TextDelta { text }).await.ok();
397 }
398 }
399 Some(crate::llm::StreamEvent::ReasoningDelta(text)) => {
400 if let Some(tx) = event_tx {
401 tx.send(AgentEvent::ReasoningDelta { text }).await.ok();
402 }
403 }
404 Some(crate::llm::StreamEvent::ToolUseStart { id, name }) => {
405 if let Some(tx) = event_tx {

Callers 1

Calls 6

with_contextMethod · 0.80
contextMethod · 0.80
complete_streamingMethod · 0.45
cloneMethod · 0.45
completeMethod · 0.45

Tested by

no test coverage detected