llm 1.3.8

A Rust library unifying multiple LLM backends.
Documentation
use crate::conversation::{
    ConversationMessage, MessageKind, MessageRole, MessageState, ToolInvocation,
};
use crate::runtime::AppStatus;

use super::super::AppController;

impl AppController {
    pub(super) fn append_stream_text(
        &mut self,
        message_id: crate::conversation::MessageId,
        delta: &str,
    ) {
        if let Some(conv) = self.state.active_conversation_mut() {
            if let Some(msg) = conv.messages.iter_mut().find(|m| m.id == message_id) {
                msg.update_text(delta);
                msg.state = MessageState::Streaming;
            }
        }
    }

    pub(super) fn add_tool_call(
        &mut self,
        conv_id: crate::conversation::ConversationId,
        id: String,
        name: String,
    ) {
        if let Some(conv) = self.state.active_conversation_mut() {
            if conv.id != conv_id {
                return;
            }
            let invocation = ToolInvocation {
                id,
                name,
                arguments: String::new(),
                partial: true,
            };
            let mut msg =
                ConversationMessage::new(MessageRole::Tool, MessageKind::ToolCall(invocation));
            msg.state = MessageState::Streaming;
            conv.push_message(msg);
        }
    }

    pub(super) fn update_tool_call(
        &mut self,
        conv_id: crate::conversation::ConversationId,
        id: &str,
        delta: &str,
    ) {
        if let Some(conv) = self.state.active_conversation_mut() {
            if conv.id != conv_id {
                return;
            }
            if let Some(msg) = conv
                .messages
                .iter_mut()
                .find(|m| matches!(&m.kind, MessageKind::ToolCall(inv) if inv.id == id))
            {
                if let MessageKind::ToolCall(inv) = &mut msg.kind {
                    inv.arguments.push_str(delta);
                    msg.bump_version();
                }
            }
        }
    }

    pub(super) async fn complete_tool_call(
        &mut self,
        conv_id: crate::conversation::ConversationId,
        invocation: ToolInvocation,
    ) {
        if let Some(conv) = self.state.active_conversation_mut() {
            if conv.id != conv_id {
                return;
            }
            if let Some(msg) = conv
                .messages
                .iter_mut()
                .find(|m| matches!(&m.kind, MessageKind::ToolCall(inv) if inv.id == invocation.id))
            {
                msg.replace_kind(MessageKind::ToolCall(invocation.clone()));
                msg.state = MessageState::Complete;
            } else {
                let mut msg = ConversationMessage::new(
                    MessageRole::Tool,
                    MessageKind::ToolCall(invocation.clone()),
                );
                msg.state = MessageState::Complete;
                conv.push_message(msg);
            }
        }
        self.schedule_tool_execution(invocation).await;
    }

    pub(super) fn increment_pending_tool(&mut self, conv_id: crate::conversation::ConversationId) {
        let entry = self.pending_tool_calls.entry(conv_id).or_insert(0);
        *entry = entry.saturating_add(1);
    }

    pub(super) fn update_usage(
        &mut self,
        message_id: crate::conversation::MessageId,
        usage: llm::chat::Usage,
    ) {
        let completion_tokens = usage.completion_tokens;
        if let Some(conv) = self.state.active_conversation_mut() {
            if let Some(msg) = conv.messages.iter_mut().find(|m| m.id == message_id) {
                msg.metadata.tokens = Some(usage);
                msg.bump_version();
            }
        }
        self.update_status_tokens(completion_tokens);
    }

    pub(super) fn finish_stream(&mut self) {
        if let Some(conv) = self.state.active_conversation_mut() {
            if let Some(msg) = conv
                .messages
                .iter_mut()
                .rev()
                .find(|m| m.role == MessageRole::Assistant)
            {
                msg.state = MessageState::Complete;
            }
        }
        self.record_snapshot();
    }

    pub(super) fn mark_stream_error(
        &mut self,
        message_id: crate::conversation::MessageId,
        error: String,
    ) {
        if let Some(conv) = self.state.active_conversation_mut() {
            if let Some(msg) = conv.messages.iter_mut().find(|m| m.id == message_id) {
                msg.replace_kind(MessageKind::Error(error));
                msg.state = MessageState::Error;
            }
        }
        self.set_status(AppStatus::Error("stream error".to_string()));
        self.record_snapshot();
    }
}