From 555061b179b8ec034cb70f9a2dd6c823ced0f637 Mon Sep 17 00:00:00 2001 From: soryu Date: Tue, 23 Dec 2025 14:43:23 +0000 Subject: Add file body and initial tool call system --- makima/src/db/models.rs | 43 +++++++++++++++++++++++++++++++++++++++++++ makima/src/db/repository.rs | 21 ++++++++++++++------- 2 files changed, 57 insertions(+), 7 deletions(-) (limited to 'makima/src/db') diff --git a/makima/src/db/models.rs b/makima/src/db/models.rs index 45b0e53..135ae75 100644 --- a/makima/src/db/models.rs +++ b/makima/src/db/models.rs @@ -18,6 +18,40 @@ pub struct TranscriptEntry { pub is_final: bool, } +/// Chart type for visualization elements +#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)] +#[serde(rename_all = "lowercase")] +pub enum ChartType { + Line, + Bar, + Pie, + Area, +} + +/// Body element types for structured file content +#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)] +#[serde(tag = "type", rename_all = "camelCase")] +pub enum BodyElement { + /// Heading element (h1-h6) + Heading { level: u8, text: String }, + /// Paragraph text + Paragraph { text: String }, + /// Chart visualization + Chart { + #[serde(rename = "chartType")] + chart_type: ChartType, + title: Option, + data: serde_json::Value, + config: Option, + }, + /// Image element (deferred for MVP) + Image { + src: String, + alt: Option, + caption: Option, + }, +} + /// File record from the database. #[derive(Debug, Clone, FromRow, Serialize, ToSchema)] #[serde(rename_all = "camelCase")] @@ -29,6 +63,11 @@ pub struct File { #[sqlx(json)] pub transcript: Vec, pub location: Option, + /// AI-generated summary of the transcript + pub summary: Option, + /// Structured body content (headings, paragraphs, charts) + #[sqlx(json)] + pub body: Vec, pub created_at: DateTime, pub updated_at: DateTime, } @@ -57,6 +96,10 @@ pub struct UpdateFileRequest { pub description: Option, /// New transcript (optional) pub transcript: Option>, + /// AI-generated summary (optional) + pub summary: Option, + /// Structured body content (optional) + pub body: Option>, } /// Response for file list endpoint. diff --git a/makima/src/db/repository.rs b/makima/src/db/repository.rs index 90cb1b9..f8b90b3 100644 --- a/makima/src/db/repository.rs +++ b/makima/src/db/repository.rs @@ -19,12 +19,13 @@ fn generate_default_name() -> String { pub async fn create_file(pool: &PgPool, req: CreateFileRequest) -> Result { let name = req.name.unwrap_or_else(generate_default_name); let transcript_json = serde_json::to_value(&req.transcript).unwrap_or_default(); + let body_json = serde_json::to_value::>(vec![]).unwrap(); sqlx::query_as::<_, File>( r#" - INSERT INTO files (owner_id, name, description, transcript, location) - VALUES ($1, $2, $3, $4, $5) - RETURNING id, owner_id, name, description, transcript, location, created_at, updated_at + INSERT INTO files (owner_id, name, description, transcript, location, summary, body) + VALUES ($1, $2, $3, $4, $5, NULL, $6) + RETURNING id, owner_id, name, description, transcript, location, summary, body, created_at, updated_at "#, ) .bind(ANONYMOUS_OWNER_ID) @@ -32,6 +33,7 @@ pub async fn create_file(pool: &PgPool, req: CreateFileRequest) -> Result Result Result, sqlx::Error> { sqlx::query_as::<_, File>( r#" - SELECT id, owner_id, name, description, transcript, location, created_at, updated_at + SELECT id, owner_id, name, description, transcript, location, summary, body, created_at, updated_at FROM files WHERE id = $1 AND owner_id = $2 "#, @@ -55,7 +57,7 @@ pub async fn get_file(pool: &PgPool, id: Uuid) -> Result, sqlx::Err pub async fn list_files(pool: &PgPool) -> Result, sqlx::Error> { sqlx::query_as::<_, File>( r#" - SELECT id, owner_id, name, description, transcript, location, created_at, updated_at + SELECT id, owner_id, name, description, transcript, location, summary, body, created_at, updated_at FROM files WHERE owner_id = $1 ORDER BY created_at DESC @@ -83,13 +85,16 @@ pub async fn update_file( let description = req.description.or(existing.description); let transcript = req.transcript.unwrap_or(existing.transcript); let transcript_json = serde_json::to_value(&transcript).unwrap_or_default(); + let summary = req.summary.or(existing.summary); + let body = req.body.unwrap_or(existing.body); + let body_json = serde_json::to_value(&body).unwrap_or_default(); sqlx::query_as::<_, File>( r#" UPDATE files - SET name = $3, description = $4, transcript = $5 + SET name = $3, description = $4, transcript = $5, summary = $6, body = $7, updated_at = NOW() WHERE id = $1 AND owner_id = $2 - RETURNING id, owner_id, name, description, transcript, location, created_at, updated_at + RETURNING id, owner_id, name, description, transcript, location, summary, body, created_at, updated_at "#, ) .bind(id) @@ -97,6 +102,8 @@ pub async fn update_file( .bind(&name) .bind(&description) .bind(&transcript_json) + .bind(&summary) + .bind(&body_json) .fetch_optional(pool) .await } -- cgit v1.2.3