fix(channels): archive group messages before the pending buffer drops them (#1514)

channel_pending_messages is a buffer, not an archive. Rows were deleted
outright on two paths: the bot being mentioned hands the buffer to the
agent and clears the key, and LLM compaction replaces old rows with a
summary. For group capture that buffer held the only copy of the raw
text, so a single mention or compaction pass destroyed days of messages
nothing had read yet.

Copy every row into channel_message_archive inside the same transaction
as the delete, tagged with the reason (consumed, compacted, stale).
Archived rows keep their original id, so a replayed delete is a no-op.
Add ListArchivedByKey so consumers that need full history read the
archive instead of the buffer.
This commit is contained in:
minhdang03 authored and GitHub committed 2026-08-15 23:48:15 +07:00
1 parent bb0291294b
commit 1d68a21f65
14 files changed
+778 -37

No files matched your search

+26
View File
@@ -1188,6 +1188,32 @@ CREATE INDEX IF NOT EXISTS idx_channel_pending_messages_lookup ON channel_pendin
CREATE INDEX IF NOT EXISTS idx_channel_pending_messages_parent ON channel_pending_messages(channel_name, parent_history_key) WHERE parent_history_key <> '';
CREATE INDEX IF NOT EXISTS idx_channel_pending_messages_tenant ON channel_pending_messages(tenant_id);
-- ============================================================
-- Table: channel_message_archive
-- ============================================================
-- Append-only copy of every pending message taken before it leaves the buffer.
-- Rows keep their original id so a replayed delete cannot duplicate them.
CREATE TABLE IF NOT EXISTS channel_message_archive (
id TEXT NOT NULL PRIMARY KEY,
channel_name VARCHAR(100) NOT NULL,
history_key VARCHAR(200) NOT NULL,
parent_history_key VARCHAR(200) NOT NULL DEFAULT '',
sender VARCHAR(255) NOT NULL,
sender_id VARCHAR(255) NOT NULL DEFAULT '',
body TEXT NOT NULL,
platform_msg_id VARCHAR(100) NOT NULL DEFAULT '',
is_summary BOOLEAN NOT NULL DEFAULT 0,
tenant_id TEXT NOT NULL REFERENCES tenants(id),
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL,
archived_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
archive_reason VARCHAR(20) NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_channel_message_archive_lookup ON channel_message_archive(tenant_id, channel_name, history_key, created_at);
CREATE INDEX IF NOT EXISTS idx_channel_message_archive_archived_at ON channel_message_archive(tenant_id, archived_at);
-- ============================================================
-- Table: channel_memory_extraction_runs
-- ============================================================