feat: nightly agentic pre-generation of memory reels
Implement end-to-end nightly pre-generation of memory reels with agentic
scripting that grounds narration in calendar, location, messages, and RAG.
Sections A-E from the plan:
A. Extract produce_reel pipeline core from run_reel_job with
ScripterMode::Fast/Agentic and progress callbacks.
B. Agentic scripter: factor run_readonly_tool_loop from the insight
generator, build read-only tool gate, prompt builder with GPS, and
generate_script_agentic with fallback to fast path.
C. Precomputed reels ledger (SQLite table + DAO), GET /reels/precomputed
handler with validity gate, GET /reels/by-key/{key}/video streaming,
and normalize_library_key helper.
D. Nightly scheduler: spawn_pregen_scheduler with configurable hour,
run_pregen_batch (day/week/month spans), pregen_one with dedup and
disk-check, secs_until_next_run_hour time math.
E. user_ai_prefs passive mirror table + DAO for param capture in
create_reel_handler and replay in the scheduler.
Also fixes resolve_library_param signature to take &[Library] and adds
resolve_library_param_state wrapper for AppState callers.
New files: migrations/2026-06-13-000000_add_precomputed_reels/,
migrations/2026-06-13-000010_add_user_ai_prefs/,
src/database/precomputed_reel_dao.rs,
src/database/user_ai_prefs_dao.rs
This commit is contained in:
1 parent
b30c8c16d0
commit
f707353807
26 files changed
+1825
-153
No files matched your search
+55
-1
@@ -1,6 +1,7 @@
|
||||
use crate::database::schema::{
|
||||
entities, entity_facts, entity_photo_links, favorites, image_exif, insight_generation_jobs,
|
||||
libraries, personas, photo_insights, users, video_preview_clips,
|
||||
libraries, personas, photo_insights, precomputed_reels, user_ai_prefs, users,
|
||||
video_preview_clips,
|
||||
};
|
||||
use serde::Serialize;
|
||||
|
||||
@@ -505,3 +506,56 @@ pub struct InsightGenerationJob {
|
||||
pub result_insight_id: Option<i32>,
|
||||
pub error_message: Option<String>,
|
||||
}
|
||||
|
||||
// --- Precomputed reels -------------------------------------------------------
|
||||
|
||||
#[derive(Insertable)]
|
||||
#[diesel(table_name = precomputed_reels)]
|
||||
pub struct InsertablePrecomputedReel {
|
||||
pub span: String,
|
||||
pub library_key: String,
|
||||
pub cache_key: String,
|
||||
pub output_path: String,
|
||||
pub title: String,
|
||||
pub media_count: i32,
|
||||
pub render_version: i32,
|
||||
pub tz_offset_minutes: i32,
|
||||
pub voice: Option<String>,
|
||||
pub generated_at: i64,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Queryable, Clone, Debug)]
|
||||
pub struct PrecomputedReel {
|
||||
pub id: i32,
|
||||
pub span: String,
|
||||
pub library_key: String,
|
||||
pub cache_key: String,
|
||||
pub output_path: String,
|
||||
pub title: String,
|
||||
pub media_count: i32,
|
||||
pub render_version: i32,
|
||||
pub tz_offset_minutes: i32,
|
||||
pub voice: Option<String>,
|
||||
pub generated_at: i64,
|
||||
}
|
||||
|
||||
// --- User AI preferences (Section E) ----------------------------------------
|
||||
|
||||
#[derive(Queryable, Insertable, Debug, Clone, serde::Deserialize, serde::Serialize)]
|
||||
#[diesel(table_name = user_ai_prefs)]
|
||||
pub struct UserAiPrefs {
|
||||
pub id: i32,
|
||||
pub voice: Option<String>,
|
||||
pub tz_offset_minutes: Option<i32>,
|
||||
pub library: Option<String>,
|
||||
pub updated_at: i64,
|
||||
}
|
||||
|
||||
#[derive(Insertable, Debug, Clone, serde::Deserialize, serde::Serialize)]
|
||||
#[diesel(table_name = user_ai_prefs)]
|
||||
pub struct UpsertUserAiPrefs {
|
||||
pub voice: Option<String>,
|
||||
pub tz_offset_minutes: Option<i32>,
|
||||
pub library: Option<String>,
|
||||
pub updated_at: i64,
|
||||
}
|
||||
Reference in new issue
Block a user