From e483789d1b5feea7d237cbc396f8acc0c3ffda0a Mon Sep 17 00:00:00 2001 From: oabrivard Date: Tue, 24 Mar 2026 10:38:54 +0100 Subject: [PATCH] feat: add use_llm_for_source_links and use_llm_for_article_extraction settings Co-Authored-By: Claude Sonnet 4.6 --- CLAUDE.md | 2 +- ...260324000014_add_llm_scraping_settings.sql | 2 ++ backend/src/db/settings.rs | 22 ++++++++++++++----- backend/src/models/settings.rs | 12 ++++++++++ backend/src/services/prompts.rs | 2 ++ 5 files changed, 33 insertions(+), 7 deletions(-) create mode 100644 backend/migrations/20260324000014_add_llm_scraping_settings.sql diff --git a/CLAUDE.md b/CLAUDE.md index 07eea90..399cee5 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -117,7 +117,7 @@ cd frontend && npx tsc --noEmit - `GET /api/v1/admin/users` — user list - `PUT /api/v1/admin/users/:id/role` — role management -## Database (13 migrations) +## Database (14 migrations) Tables: `users`, `sessions`, `magic_link_tokens`, `user_settings`, `sources`, `syntheses`, `admin_providers`, `admin_rate_limits`, `user_api_keys`, `audit_log` ## Environment Variables diff --git a/backend/migrations/20260324000014_add_llm_scraping_settings.sql b/backend/migrations/20260324000014_add_llm_scraping_settings.sql new file mode 100644 index 0000000..ea4fa65 --- /dev/null +++ b/backend/migrations/20260324000014_add_llm_scraping_settings.sql @@ -0,0 +1,2 @@ +ALTER TABLE settings ADD COLUMN use_llm_for_source_links BOOLEAN NOT NULL DEFAULT false; +ALTER TABLE settings ADD COLUMN use_llm_for_article_extraction BOOLEAN NOT NULL DEFAULT false; diff --git a/backend/src/db/settings.rs b/backend/src/db/settings.rs index 496fa47..bbed2a4 100644 --- a/backend/src/db/settings.rs +++ b/backend/src/db/settings.rs @@ -19,6 +19,8 @@ struct SettingsRow { max_items_per_category: i32, max_articles_per_source: i32, source_diversity_window: i32, + use_llm_for_source_links: bool, + use_llm_for_article_extraction: bool, search_agent_behavior: String, ai_provider: String, ai_model: String, @@ -44,6 +46,8 @@ impl TryFrom for UserSettings { max_items_per_category: row.max_items_per_category, max_articles_per_source: row.max_articles_per_source, source_diversity_window: row.source_diversity_window, + use_llm_for_source_links: row.use_llm_for_source_links, + use_llm_for_article_extraction: row.use_llm_for_article_extraction, search_agent_behavior: row.search_agent_behavior, ai_provider: row.ai_provider, ai_model: row.ai_model, @@ -70,10 +74,10 @@ pub async fn get_or_create_default( let row = sqlx::query_as::<_, SettingsRow>( r#" - INSERT INTO settings (user_id, theme, max_age_days, categories, max_items_per_category, search_agent_behavior, ai_provider, ai_model, ai_model_writing, rate_limit_max_requests, rate_limit_time_window_seconds, max_articles_per_source, source_diversity_window) - VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13) + INSERT INTO settings (user_id, theme, max_age_days, categories, max_items_per_category, search_agent_behavior, ai_provider, ai_model, ai_model_writing, rate_limit_max_requests, rate_limit_time_window_seconds, max_articles_per_source, source_diversity_window, use_llm_for_source_links, use_llm_for_article_extraction) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15) ON CONFLICT (user_id) DO UPDATE SET user_id = settings.user_id - RETURNING user_id, theme, max_age_days, categories, max_items_per_category, search_agent_behavior, ai_provider, ai_model, ai_model_writing, rate_limit_max_requests, rate_limit_time_window_seconds, max_articles_per_source, source_diversity_window, updated_at + RETURNING user_id, theme, max_age_days, categories, max_items_per_category, search_agent_behavior, ai_provider, ai_model, ai_model_writing, rate_limit_max_requests, rate_limit_time_window_seconds, max_articles_per_source, source_diversity_window, use_llm_for_source_links, use_llm_for_article_extraction, updated_at "#, ) .bind(user_id) @@ -89,6 +93,8 @@ pub async fn get_or_create_default( .bind(defaults.rate_limit_time_window_seconds) .bind(defaults.max_articles_per_source) .bind(defaults.source_diversity_window) + .bind(defaults.use_llm_for_source_links) + .bind(defaults.use_llm_for_article_extraction) .fetch_one(pool) .await?; @@ -107,8 +113,8 @@ pub async fn upsert( let row = sqlx::query_as::<_, SettingsRow>( r#" - INSERT INTO settings (user_id, theme, max_age_days, categories, max_items_per_category, search_agent_behavior, ai_provider, ai_model, ai_model_writing, rate_limit_max_requests, rate_limit_time_window_seconds, max_articles_per_source, source_diversity_window) - VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13) + INSERT INTO settings (user_id, theme, max_age_days, categories, max_items_per_category, search_agent_behavior, ai_provider, ai_model, ai_model_writing, rate_limit_max_requests, rate_limit_time_window_seconds, max_articles_per_source, source_diversity_window, use_llm_for_source_links, use_llm_for_article_extraction) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15) ON CONFLICT (user_id) DO UPDATE SET theme = EXCLUDED.theme, max_age_days = EXCLUDED.max_age_days, @@ -122,8 +128,10 @@ pub async fn upsert( rate_limit_time_window_seconds = EXCLUDED.rate_limit_time_window_seconds, max_articles_per_source = EXCLUDED.max_articles_per_source, source_diversity_window = EXCLUDED.source_diversity_window, + use_llm_for_source_links = EXCLUDED.use_llm_for_source_links, + use_llm_for_article_extraction = EXCLUDED.use_llm_for_article_extraction, updated_at = now() - RETURNING user_id, theme, max_age_days, categories, max_items_per_category, search_agent_behavior, ai_provider, ai_model, ai_model_writing, rate_limit_max_requests, rate_limit_time_window_seconds, max_articles_per_source, source_diversity_window, updated_at + RETURNING user_id, theme, max_age_days, categories, max_items_per_category, search_agent_behavior, ai_provider, ai_model, ai_model_writing, rate_limit_max_requests, rate_limit_time_window_seconds, max_articles_per_source, source_diversity_window, use_llm_for_source_links, use_llm_for_article_extraction, updated_at "#, ) .bind(user_id) @@ -139,6 +147,8 @@ pub async fn upsert( .bind(req.rate_limit_time_window_seconds) .bind(req.max_articles_per_source) .bind(req.source_diversity_window) + .bind(req.use_llm_for_source_links) + .bind(req.use_llm_for_article_extraction) .fetch_one(pool) .await?; diff --git a/backend/src/models/settings.rs b/backend/src/models/settings.rs index e331d9a..2e5d7a0 100644 --- a/backend/src/models/settings.rs +++ b/backend/src/models/settings.rs @@ -14,6 +14,8 @@ pub struct UserSettings { pub max_items_per_category: i32, pub max_articles_per_source: i32, pub source_diversity_window: i32, + pub use_llm_for_source_links: bool, + pub use_llm_for_article_extraction: bool, pub search_agent_behavior: String, pub ai_provider: String, pub ai_model: String, @@ -32,6 +34,8 @@ pub struct SettingsResponse { pub max_items_per_category: i32, pub max_articles_per_source: i32, pub source_diversity_window: i32, + pub use_llm_for_source_links: bool, + pub use_llm_for_article_extraction: bool, pub search_agent_behavior: String, pub ai_provider: String, pub ai_model: String, @@ -49,6 +53,8 @@ impl From for SettingsResponse { max_items_per_category: s.max_items_per_category, max_articles_per_source: s.max_articles_per_source, source_diversity_window: s.source_diversity_window, + use_llm_for_source_links: s.use_llm_for_source_links, + use_llm_for_article_extraction: s.use_llm_for_article_extraction, search_agent_behavior: s.search_agent_behavior, ai_provider: s.ai_provider, ai_model: s.ai_model, @@ -68,6 +74,8 @@ pub struct UpdateSettingsRequest { pub max_items_per_category: i32, pub max_articles_per_source: i32, pub source_diversity_window: i32, + pub use_llm_for_source_links: bool, + pub use_llm_for_article_extraction: bool, pub search_agent_behavior: String, pub ai_provider: String, pub ai_model: String, @@ -160,6 +168,8 @@ impl Default for UserSettings { max_items_per_category: 4, max_articles_per_source: 3, source_diversity_window: 3, + use_llm_for_source_links: false, + use_llm_for_article_extraction: false, search_agent_behavior: String::new(), ai_provider: String::new(), ai_model: String::new(), @@ -184,6 +194,8 @@ mod tests { max_items_per_category: 4, max_articles_per_source: 3, source_diversity_window: 3, + use_llm_for_source_links: false, + use_llm_for_article_extraction: false, search_agent_behavior: String::new(), ai_provider: String::new(), ai_model: String::new(), diff --git a/backend/src/services/prompts.rs b/backend/src/services/prompts.rs index 39dd158..6d13d47 100644 --- a/backend/src/services/prompts.rs +++ b/backend/src/services/prompts.rs @@ -232,6 +232,8 @@ mod tests { max_items_per_category: 4, max_articles_per_source: 3, source_diversity_window: 3, + use_llm_for_source_links: false, + use_llm_for_article_extraction: false, search_agent_behavior: String::new(), ai_provider: String::new(), ai_model: String::new(),