pub struct ChatSessionState {
pub id: ChatSessionId,
pub title: String,
pub status: ChatSessionStatus,
pub messages: Vec<ChatMessage>,
pub active_request: Option<ChatRequestId>,
pub last_error: Option<String>,
}Expand description
Serializable, ordered state of one chat session.
The public fields allow adapters to restore provider snapshots directly.
Self::apply_event provides the canonical incremental update semantics.
§Examples
use ailloli_ui_core::{
ChatEvent, ChatItemId, ChatSessionId, ChatSessionState,
};
let mut session = ChatSessionState::new(ChatSessionId::from_index(1), "Demo");
assert!(session.apply_event(ChatEvent::MessageAdded(
ailloli_ui_core::ChatMessage::user(ChatItemId::from_index(1), "Hi"),
)));
assert_eq!(session.summary().message_count, 1);Fields§
§id: ChatSessionIdStable session identity.
title: StringConsumer-facing title; an empty title is allowed.
status: ChatSessionStatusAggregate lifecycle of the session.
messages: Vec<ChatMessage>Items in insertion order; replacing an existing ID preserves its index.
active_request: Option<ChatRequestId>In-flight provider request, or None when no request is tracked.
last_error: Option<String>Latest session-level failure text, or None when absent or cleared.
Implementations§
Source§impl ChatSessionState
impl ChatSessionState
Sourcepub fn new(id: ChatSessionId, title: impl Into<String>) -> Self
pub fn new(id: ChatSessionId, title: impl Into<String>) -> Self
Creates an empty session in ChatSessionStatus::Ready.
§Examples
use ailloli_ui_core::{ChatSessionId, ChatSessionState, ChatSessionStatus};
let session = ChatSessionState::new(ChatSessionId::new("session-1"), "Demo");
assert_eq!(session.status, ChatSessionStatus::Ready);Sourcepub fn summary(&self) -> ChatSessionSummary
pub fn summary(&self) -> ChatSessionSummary
Builds a compact owned summary of the current snapshot.
The preview is None when there are no messages. Otherwise it contains
at most 72 Unicode scalar values from the final message followed by
... when truncated; an empty final message yields Some("").
§Performance
Clones the ID and title and counts the final message text to determine whether truncation is required.
§Examples
use ailloli_ui_core::{ChatSessionId, ChatSessionState};
let summary = ChatSessionState::new(ChatSessionId::new("session-1"), "Demo").summary();
assert_eq!(summary.message_count, 0);Sourcepub fn with_event(&self, event: ChatEvent) -> Self
pub fn with_event(&self, event: ChatEvent) -> Self
Returns an updated clone, leaving this snapshot unchanged.
This has the same event semantics as Self::apply_event.
§Performance
Clones the complete session before applying the event.
§Examples
use ailloli_ui_core::{ChatEvent, ChatSessionId, ChatSessionState, ChatSessionStatus};
let session = ChatSessionState::new(ChatSessionId::new("session-1"), "Demo");
let failed = session.with_event(ChatEvent::Failed { message: "offline".into() });
assert_eq!(failed.status, ChatSessionStatus::Failed);
assert_eq!(session.status, ChatSessionStatus::Ready);Sourcepub fn apply_event(&mut self, event: ChatEvent) -> bool
pub fn apply_event(&mut self, event: ChatEvent) -> bool
Applies one reducer event and reports whether the snapshot changed.
Message IDs are upserted: an existing item is replaced at its current
index and a new item is appended. A delta for an unknown item creates a
streaming assistant text item without a request ID. Finishing an
assistant item marks the session completed and clears the active request
even when that item is unknown. Finishing a request clears
active_request only when IDs match, but always marks the session
completed. ChatEvent::RequestStarted is the event that clears
last_error; ordinary message events preserve it.
§Performance
Clones the complete pre-event state to compute the boolean result and performs a linear search through messages for each upsert or lookup.
§Examples
use ailloli_ui_core::{
ChatEvent, ChatItemId, ChatMessageKind, ChatRequestId,
ChatSessionId, ChatSessionState,
};
let mut chat = ChatSessionState::new(ChatSessionId::from_index(1), "Demo");
let item = ChatItemId::from_index(1);
chat.apply_event(ChatEvent::AssistantMessageStarted {
item_id: item.clone(),
request_id: ChatRequestId::from_index(1),
kind: ChatMessageKind::Text,
});
chat.apply_event(ChatEvent::AssistantMessageDelta {
item_id: item.clone(),
delta: "Hello".into(),
});
assert_eq!(chat.message(&item).unwrap().text, "Hello");Sourcepub fn message(&self, item_id: &ChatItemId) -> Option<&ChatMessage>
pub fn message(&self, item_id: &ChatItemId) -> Option<&ChatMessage>
Finds a message by ID without changing insertion order.
Returns None if the ID has not been observed. Lookup is linear in the
number of messages.
§Examples
use ailloli_ui_core::{ChatEvent, ChatItemId, ChatMessage, ChatSessionId, ChatSessionState};
let id = ChatItemId::new("item-1");
let mut session = ChatSessionState::new(ChatSessionId::new("session-1"), "Demo");
session.apply_event(ChatEvent::MessageAdded(ChatMessage::user(id.clone(), "Hello")));
assert_eq!(session.message(&id).unwrap().text, "Hello");Trait Implementations§
Source§impl Clone for ChatSessionState
impl Clone for ChatSessionState
Source§fn clone(&self) -> ChatSessionState
fn clone(&self) -> ChatSessionState
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more