mirror of
https://github.com/multica-ai/multica.git
synced 2026-07-27 04:56:20 +02:00
* feat(chat): task-owned direct-chat input batches + explicit no_response outcome (MUL-4351) Direct (web/mobile) chat no longer uses the last-assistant-row as an implicit input cursor. Each direct send now owns an immutable input batch: - agent_task_queue.chat_input_task_id makes a task the owner of the user messages it must consume; the send path creates the task + user message + attachment bindings + session touch in one transaction, and the daemon is notified only after commit. A claim reads exactly that batch, so a message that arrives mid-run belongs to the next task and is never absorbed. - Auto-retry inherits the root input owner and is queued at a bumped priority, created inside FailTask's transaction so no newer chat task can jump ahead. - CompleteTask writes exactly one assistant outcome inside the completion transaction: a normal message, or a visible no_response outcome (with a non-empty English fallback) when the final output is empty. The write failing rolls the completion back and the handler returns 5xx so the daemon retries; the status CAS keeps it idempotent. chat:done carries message_kind. - Web/desktop/mobile render no_response as a localized 'no text reply' state (keeping the tool timeline), suppress Copy, keep it unread, and keep the session-list preview non-blank. - Legacy/channel tasks (chat_input_task_id NULL) keep the trailing-message selector, so a rolling deploy never replays Slack/Lark history. Co-authored-by: multica-agent <github@multica.ai> * fix(chat): scope no_response to direct tasks; don't cancel task on input read error (MUL-4351) Addresses PR review (Niko): - writeChatCompletionOutcome only writes a no_response row for task-owned direct tasks (chat_input_task_id set). Legacy/channel (Slack/Lark) tasks keep the prior behavior: empty output writes no assistant row, so chat:done carries empty content and the channel outbound silently drops it — the no_response fallback body never reaches an external channel. - The daemon claim distinguishes a genuine zero-input batch from a failed input read: on ListChatInputMessages / ListChatMessages error it returns 5xx and preserves the dispatched task for redelivery instead of cancelling a valid task on a transient DB error. Co-authored-by: multica-agent <github@multica.ai> --------- Co-authored-by: J <j@multica.ai> Co-authored-by: multica-agent <github@multica.ai>
17 lines
889 B
SQL
17 lines
889 B
SQL
-- Index the task-owned input-batch lookup added in MUL-4351.
|
|
--
|
|
-- The direct-chat claim path loads its input with
|
|
-- SELECT * FROM chat_message WHERE task_id = $1 AND role = 'user' ORDER BY created_at
|
|
-- (ListChatInputMessages), keyed on the task's chat_input_task_id. Before this
|
|
-- there was no index on chat_message.task_id at all (only the
|
|
-- chat_session_id/created_at index from migration 033), so the lookup would seq
|
|
-- scan. This partial index covers exactly the user-message batch reads and the
|
|
-- existing task_id-keyed writes (LinkChatMessageToTask,
|
|
-- DeleteUserChatMessageByTask) without indexing assistant rows.
|
|
--
|
|
-- Single-statement migration: CREATE INDEX CONCURRENTLY cannot run inside a
|
|
-- transaction or a multi-command string.
|
|
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_chat_message_input_owner
|
|
ON chat_message (task_id, created_at)
|
|
WHERE role = 'user';
|