feat: add /persona_chat endpoints for open chat with persona
- PersonaChatSession dispatches turns through the shared agent loop, persisting transcripts keyed on (user_id, persona_id) in the new persona_chat table (migration included). - GET /persona_chat/history returns a rendered transcript (tool invocations folded, is_initial flag) matching the file-chat shape. - POST /persona_chat/turn returns 202 with a turn_id; SSE replay and cancel reuse turn_replay_impl/cancel_turn_impl, extracted from the actix-attributed handlers so both route families share the logic. - POST /persona_chat/reset clears the persona transcript. - Concurrent dispatches for the same (user, persona) are rejected with 409 via an in-flight gate (InFlightPersonaTurns) whose RAII guard drops with the spawned turn task, freeing the slot on completion, error, or abort.
This commit is contained in:
1 parent
649863a700
commit
3b9d985025
11 files changed
+1716
-179
No files matched your search
+24
-2
@@ -4,6 +4,7 @@ use crate::ai::face_client::FaceClient;
|
||||
use crate::ai::insight_chat::{ChatLockMap, InsightChatService};
|
||||
use crate::ai::llamacpp::LlamaCppClient;
|
||||
use crate::ai::openrouter::OpenRouterClient;
|
||||
use crate::ai::persona_chat::PersonaChatSession;
|
||||
use crate::ai::turn_registry::TurnRegistry;
|
||||
use crate::ai::{InsightGenerator, OllamaClient, SmsApiClient};
|
||||
use crate::database::{
|
||||
@@ -84,6 +85,9 @@ pub struct AppState {
|
||||
pub insight_generator: InsightGenerator,
|
||||
/// Chat continuation service. Hold an Arc so handlers can clone cheaply.
|
||||
pub insight_chat: Arc<InsightChatService>,
|
||||
/// Open chat with persona service. Same shape as insight_chat but
|
||||
/// anchored on (user_id, persona_id) instead of (library_id, file_path).
|
||||
pub persona_chat_session: Arc<PersonaChatSession>,
|
||||
pub turn_registry: Arc<TurnRegistry>,
|
||||
pub face_client: FaceClient,
|
||||
pub clip_client: ClipClient,
|
||||
@@ -133,6 +137,7 @@ impl AppState {
|
||||
sms_client: SmsApiClient,
|
||||
insight_generator: InsightGenerator,
|
||||
insight_chat: Arc<InsightChatService>,
|
||||
persona_chat_session: Arc<PersonaChatSession>,
|
||||
turn_registry: Arc<TurnRegistry>,
|
||||
preview_dao: Arc<Mutex<Box<dyn PreviewDao>>>,
|
||||
face_client: FaceClient,
|
||||
@@ -194,6 +199,7 @@ impl AppState {
|
||||
sms_client,
|
||||
insight_generator,
|
||||
insight_chat,
|
||||
persona_chat_session,
|
||||
turn_registry,
|
||||
face_client,
|
||||
clip_client,
|
||||
@@ -316,7 +322,7 @@ impl Default for AppState {
|
||||
tag_dao.clone(),
|
||||
face_dao.clone(),
|
||||
knowledge_dao,
|
||||
persona_dao,
|
||||
persona_dao.clone(),
|
||||
libraries_vec.clone(),
|
||||
);
|
||||
|
||||
@@ -330,6 +336,13 @@ impl Default for AppState {
|
||||
chat_locks,
|
||||
));
|
||||
|
||||
// Open chat with persona: reuses the generator + persona DAO.
|
||||
let persona_chat_session = Arc::new(PersonaChatSession::new(
|
||||
Arc::new(insight_generator.clone()),
|
||||
persona_dao.clone(),
|
||||
Arc::new(tokio::sync::Mutex::new(std::collections::HashMap::new())),
|
||||
));
|
||||
|
||||
// Turn registry for reconnectable chat turns. 5-minute timeout for
|
||||
// stale turns (background cleaner drops entries older than this).
|
||||
let timeout_secs: u64 = env::var("INSIGHT_CHAT_TURN_TIMEOUT_SECS")
|
||||
@@ -360,6 +373,7 @@ impl Default for AppState {
|
||||
sms_client,
|
||||
insight_generator,
|
||||
insight_chat,
|
||||
persona_chat_session,
|
||||
turn_registry,
|
||||
preview_dao,
|
||||
face_client,
|
||||
@@ -528,7 +542,7 @@ impl AppState {
|
||||
tag_dao.clone(),
|
||||
face_dao.clone(),
|
||||
knowledge_dao,
|
||||
persona_dao,
|
||||
persona_dao.clone(),
|
||||
vec![test_lib],
|
||||
);
|
||||
|
||||
@@ -540,6 +554,13 @@ impl AppState {
|
||||
chat_locks,
|
||||
));
|
||||
|
||||
// Open chat with persona (test).
|
||||
let persona_chat_session = Arc::new(PersonaChatSession::new(
|
||||
Arc::new(insight_generator.clone()),
|
||||
persona_dao.clone(),
|
||||
Arc::new(tokio::sync::Mutex::new(std::collections::HashMap::new())),
|
||||
));
|
||||
|
||||
// Turn registry for test state.
|
||||
let turn_registry = Arc::new(TurnRegistry::new(300));
|
||||
|
||||
@@ -571,6 +592,7 @@ impl AppState {
|
||||
sms_client,
|
||||
insight_generator,
|
||||
insight_chat,
|
||||
persona_chat_session,
|
||||
turn_registry,
|
||||
preview_dao,
|
||||
FaceClient::new(None), // disabled in test
|
||||
|
||||
Reference in new issue
Block a user