3b9d985025
- 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.
22 lines
968 B
SQL
22 lines
968 B
SQL
-- Open chat with persona — file-anchored insight chat is keyed by
|
|
-- (library_id, file_path). The open chat is keyed by (user_id, persona_id)
|
|
-- with a single rolling transcript per pair. No tree branching in v1
|
|
-- (matches the locked-in "single rolling conversation per persona" scope);
|
|
-- a flat JSON blob is enough and avoids forcing a tree shape onto a
|
|
-- surface that's intentionally linear.
|
|
--
|
|
-- `messages_json` is the same `Vec<ChatMessage>` shape the file-anchored
|
|
-- chat persists, so the SSE replay / UI rendering on the mobile client
|
|
-- can reuse the same parser without a second schema.
|
|
|
|
CREATE TABLE persona_chat_conversations (
|
|
user_id INTEGER NOT NULL,
|
|
persona_id TEXT NOT NULL,
|
|
messages_json TEXT NOT NULL DEFAULT '[]',
|
|
turn_count INTEGER NOT NULL DEFAULT 0,
|
|
updated_at BIGINT NOT NULL,
|
|
PRIMARY KEY (user_id, persona_id)
|
|
);
|
|
|
|
CREATE INDEX idx_persona_chat_updated
|
|
ON persona_chat_conversations (user_id, updated_at DESC); |