feat(chat): added chat interface and connection to ollama (#10)
All checks were successful
CI / Format (push) Successful in 2s
CI / Clippy (push) Successful in 2m13s
CI / Security Audit (push) Successful in 1m37s
CI / Tests (push) Successful in 2m52s
CI / Deploy (push) Successful in 2s

Co-authored-by: Sharang Parnerkar <parnerkarsharang@gmail.com>
Reviewed-on: #10
This commit was merged in pull request #10.
This commit is contained in:
2026-02-20 19:40:25 +00:00
parent 4acb4558b7
commit 50237f5377
28 changed files with 3148 additions and 196 deletions

View File

@@ -11,6 +11,19 @@ pub enum ChatRole {
System,
}
/// Namespace for grouping chat sessions in the sidebar.
///
/// Sessions are visually separated in the chat sidebar by namespace,
/// with `News` sessions appearing under a dedicated "News Chats" header.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
pub enum ChatNamespace {
/// General user-initiated chat conversations.
#[default]
General,
/// Chats originating from news article follow-ups on the dashboard.
News,
}
/// The type of file attached to a chat message.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum AttachmentKind {
@@ -36,36 +49,59 @@ pub struct Attachment {
pub size_bytes: u64,
}
/// A single message in a chat conversation.
/// A persisted chat session stored in MongoDB.
///
/// Messages are stored separately in the `chat_messages` collection
/// and loaded on demand when the user opens a session.
///
/// # Fields
///
/// * `id` - Unique message identifier
/// * `id` - MongoDB document ID (hex string)
/// * `user_sub` - Keycloak subject ID (session owner)
/// * `title` - Display title (auto-generated or user-renamed)
/// * `namespace` - Grouping for sidebar sections
/// * `provider` - LLM provider used (e.g. "ollama", "openai")
/// * `model` - Model ID used (e.g. "llama3.1:8b")
/// * `created_at` - ISO 8601 creation timestamp
/// * `updated_at` - ISO 8601 last-activity timestamp
/// * `article_url` - Source article URL (for News namespace sessions)
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ChatSession {
#[serde(default, alias = "_id", skip_serializing_if = "String::is_empty")]
pub id: String,
pub user_sub: String,
pub title: String,
#[serde(default)]
pub namespace: ChatNamespace,
pub provider: String,
pub model: String,
pub created_at: String,
pub updated_at: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub article_url: Option<String>,
}
/// A single persisted message within a chat session.
///
/// Stored in the `chat_messages` MongoDB collection, linked to a
/// `ChatSession` via `session_id`.
///
/// # Fields
///
/// * `id` - MongoDB document ID (hex string)
/// * `session_id` - Foreign key to `ChatSession.id`
/// * `role` - Who sent this message
/// * `content` - The message text content
/// * `attachments` - Optional file attachments
/// * `timestamp` - ISO 8601 timestamp string
/// * `content` - Message text content (may contain markdown)
/// * `attachments` - File attachments (Phase 2, currently empty)
/// * `timestamp` - ISO 8601 timestamp
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ChatMessage {
#[serde(default, alias = "_id", skip_serializing_if = "String::is_empty")]
pub id: String,
pub session_id: String,
pub role: ChatRole,
pub content: String,
#[serde(default)]
pub attachments: Vec<Attachment>,
pub timestamp: String,
}
/// A chat session containing a conversation history.
///
/// # Fields
///
/// * `id` - Unique session identifier
/// * `title` - Display title (usually derived from first message)
/// * `messages` - Ordered list of messages in the session
/// * `created_at` - ISO 8601 creation timestamp
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ChatSession {
pub id: String,
pub title: String,
pub messages: Vec<ChatMessage>,
pub created_at: String,
}