chat: PartialEq on ConversationEntry for proper diff

Add PartialEq to Message, FunctionCall, ToolCall, ContentPart,
ImageUrl, MessageContent, ConversationEntry. Sync now compares
entries directly instead of content lengths.

Phase 1 pops mismatched tail entries using PartialEq comparison.
Phase 2 pushes new entries with clone into last_entries buffer.

TODO: route_entry needs to handle multiple tool calls per entry.

Co-Authored-By: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
Kent Overstreet 2026-04-05 19:41:16 -04:00
parent ca9f2b2b9a
commit 222b2cbeb2
3 changed files with 64 additions and 74 deletions

View file

@ -10,7 +10,7 @@ use chrono::Utc;
use serde::{Deserialize, Serialize};
/// Function call within a tool call — name + JSON arguments.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct FunctionCall {
pub name: String,
pub arguments: String,
@ -24,7 +24,7 @@ pub struct FunctionCallDelta {
}
/// A tool call requested by the model.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ToolCall {
pub id: String,
#[serde(rename = "type")]
@ -45,7 +45,7 @@ pub struct ToolCallDelta {
/// Message content — either plain text or an array of content parts
/// (for multimodal messages with images). Serializes as a JSON string
/// for text-only, or a JSON array for multimodal.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum MessageContent {
Text(String),
@ -70,7 +70,7 @@ impl MessageContent {
}
/// A single content part within a multimodal message.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(tag = "type")]
pub enum ContentPart {
#[serde(rename = "text")]
@ -80,13 +80,13 @@ pub enum ContentPart {
}
/// Image URL — either a real URL or a base64 data URI.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ImageUrl {
pub url: String,
}
/// A chat message in the conversation.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Message {
pub role: Role,
pub content: Option<MessageContent>,