feat: track chat file associations with chat_file_links on chats (#23537)

Needed by #23833

Adds a `chat_file_links` association table to track which files are
associated with each chat.

- `AppendChatFileIDs` query links a file to a chat with deduplication
- `GetChatFileMetadataByIDs` query returns lightweight file metadata by
IDs
- Tool-created files (e.g. `propose_plan`) are linked to the chat after
insert
- User-uploaded files are linked to the chat when the referencing
message is sent
- Single-chat GET endpoint hydrates `files: ChatFileMetadata[]` on the
response

> 🤖 Created by Coder Agents and massaged into shape by a human.
This commit is contained in:
Cian Johnston
2026-04-07 12:05:29 +01:00
committed by GitHub
parent beb99c17de
commit d5a1792f07
26 changed files with 1175 additions and 60 deletions
@@ -0,0 +1,9 @@
ALTER TABLE chats ADD COLUMN file_ids uuid[] DEFAULT '{}'::uuid[] NOT NULL;
UPDATE chats SET file_ids = (
SELECT COALESCE(array_agg(cfl.file_id), '{}')
FROM chat_file_links cfl
WHERE cfl.chat_id = chats.id
);
DROP TABLE chat_file_links;
@@ -0,0 +1,17 @@
CREATE TABLE chat_file_links (
chat_id uuid NOT NULL,
file_id uuid NOT NULL,
UNIQUE (chat_id, file_id)
);
CREATE INDEX idx_chat_file_links_chat_id ON chat_file_links (chat_id);
ALTER TABLE chat_file_links
ADD CONSTRAINT chat_file_links_chat_id_fkey
FOREIGN KEY (chat_id) REFERENCES chats(id) ON DELETE CASCADE;
ALTER TABLE chat_file_links
ADD CONSTRAINT chat_file_links_file_id_fkey
FOREIGN KEY (file_id) REFERENCES chat_files(id) ON DELETE CASCADE;
ALTER TABLE chats DROP COLUMN IF EXISTS file_ids;
@@ -0,0 +1,5 @@
INSERT INTO chat_file_links (chat_id, file_id)
VALUES (
'72c0438a-18eb-4688-ab80-e4c6a126ef96',
'00000000-0000-0000-0000-000000000099'
);