mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: Add full text search over chat messages (#27126)
Closes CODAGT-721 Closes CODAGT-722 Closes CODAGT-723 Closes CODAGT-724 Closes CODAGT-725 This PR adds the database and API pieces necessary to support full-text chat message search. - Adds required chat schema for full-text search - Adds dbpurge job to populate search_tsv in the background - Adds `search` parameter to GetChats query - Adds `search` filter to `searchquery.Chats` - Wires chat search filter into chats API > Implemented by Coder Agents, reviewed and tested by a human.
This commit is contained in:
Generated
+37
-3
@@ -783,6 +783,18 @@ BEGIN
|
||||
END;
|
||||
$$;
|
||||
|
||||
CREATE FUNCTION chat_message_search_text(content jsonb) RETURNS text
|
||||
LANGUAGE sql IMMUTABLE PARALLEL SAFE
|
||||
AS $$
|
||||
SELECT CASE WHEN jsonb_typeof(content) = 'array' THEN (
|
||||
SELECT string_agg(part->>'text', ' ' ORDER BY ordinality)
|
||||
FROM jsonb_array_elements(content) WITH ORDINALITY AS t(part, ordinality)
|
||||
WHERE part->>'type' = 'text'
|
||||
) END
|
||||
$$;
|
||||
|
||||
COMMENT ON FUNCTION chat_message_search_text(content jsonb) IS 'Extracts searchable content from chat_messages. Returns NULL for scalar JSON strings (content_version=0). Immutable as it is used in indexes.';
|
||||
|
||||
CREATE FUNCTION check_workspace_agent_name_unique() RETURNS trigger
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
@@ -1365,6 +1377,7 @@ CREATE FUNCTION set_chat_message_revision_before() RETURNS trigger
|
||||
AS $$
|
||||
DECLARE
|
||||
chat_snapshot_version bigint;
|
||||
cmp chat_messages;
|
||||
BEGIN
|
||||
IF TG_OP = 'INSERT' AND NEW.revision IS NOT NULL THEN
|
||||
RAISE EXCEPTION 'chat_messages.revision must be assigned by trigger';
|
||||
@@ -1379,7 +1392,9 @@ BEGIN
|
||||
RAISE EXCEPTION 'chat_messages.revision must be assigned by trigger';
|
||||
END IF;
|
||||
|
||||
IF OLD IS NOT DISTINCT FROM NEW THEN
|
||||
cmp := NEW;
|
||||
cmp.search_tsv := OLD.search_tsv;
|
||||
IF OLD IS NOT DISTINCT FROM cmp THEN
|
||||
RETURN NEW;
|
||||
END IF;
|
||||
END IF;
|
||||
@@ -1396,6 +1411,8 @@ BEGIN
|
||||
END;
|
||||
$$;
|
||||
|
||||
COMMENT ON FUNCTION set_chat_message_revision_before() IS 'Component of chatd. Updates chat_snapshot_version when any fields of chat_messages change. Excludes changes to search_tsv as it is not relevant to chatd''s processing loop.';
|
||||
|
||||
CREATE FUNCTION sync_chat_retry_state() RETURNS trigger
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
@@ -1446,7 +1463,7 @@ BEGIN
|
||||
SELECT DISTINCT n.chat_id
|
||||
FROM chat_message_history_new_rows n
|
||||
JOIN chat_message_history_old_rows o ON o.id = n.id
|
||||
WHERE o IS DISTINCT FROM n
|
||||
WHERE (to_jsonb(o) - 'search_tsv') IS DISTINCT FROM (to_jsonb(n) - 'search_tsv')
|
||||
) AS affected
|
||||
WHERE c.id = affected.chat_id
|
||||
AND (
|
||||
@@ -1457,6 +1474,8 @@ BEGIN
|
||||
END;
|
||||
$$;
|
||||
|
||||
COMMENT ON FUNCTION update_chat_history_after_message_update() IS 'Component of chatd. Updates history_version and generation_attempt on chats when chat_messages is updated. Excludes changes to search_tsv.';
|
||||
|
||||
CREATE TABLE ai_gateway_keys (
|
||||
id uuid NOT NULL,
|
||||
created_at timestamp with time zone NOT NULL,
|
||||
@@ -1946,11 +1965,14 @@ CREATE TABLE chat_messages (
|
||||
provider_response_id text,
|
||||
api_key_id text,
|
||||
revision bigint NOT NULL,
|
||||
reasoning_effort chat_reasoning_effort
|
||||
reasoning_effort chat_reasoning_effort,
|
||||
search_tsv tsvector
|
||||
);
|
||||
|
||||
COMMENT ON COLUMN chat_messages.reasoning_effort IS 'Stores the selected effort for the turn triggered by this message.';
|
||||
|
||||
COMMENT ON COLUMN chat_messages.search_tsv IS 'Used for full text search. NULL initially, populated async via background job.';
|
||||
|
||||
CREATE SEQUENCE chat_messages_id_seq
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
@@ -4717,6 +4739,8 @@ CREATE UNIQUE INDEX idx_chat_debug_steps_run_step ON chat_debug_steps USING btre
|
||||
|
||||
CREATE INDEX idx_chat_debug_steps_stale ON chat_debug_steps USING btree (updated_at) WHERE (finished_at IS NULL);
|
||||
|
||||
CREATE INDEX idx_chat_diff_statuses_pr_title_fts ON chat_diff_statuses USING gin (to_tsvector('simple'::regconfig, pull_request_title));
|
||||
|
||||
CREATE INDEX idx_chat_diff_statuses_stale_at ON chat_diff_statuses USING btree (stale_at);
|
||||
|
||||
CREATE INDEX idx_chat_diff_statuses_url_lower ON chat_diff_statuses USING btree (lower(url)) WHERE ((url IS NOT NULL) AND (url <> ''::text));
|
||||
@@ -4737,6 +4761,12 @@ CREATE INDEX idx_chat_messages_created_at ON chat_messages USING btree (created_
|
||||
|
||||
CREATE INDEX idx_chat_messages_owner_spend ON chat_messages USING btree (chat_id, created_at) WHERE (total_cost_micros IS NOT NULL);
|
||||
|
||||
CREATE INDEX idx_chat_messages_search_tsv ON chat_messages USING gin (search_tsv) WHERE ((search_tsv IS NOT NULL) AND (deleted = false) AND (visibility = ANY (ARRAY['user'::chat_message_visibility, 'both'::chat_message_visibility])) AND (role = ANY (ARRAY['user'::chat_message_role, 'assistant'::chat_message_role])));
|
||||
|
||||
COMMENT ON INDEX idx_chat_messages_search_tsv IS 'Partial index over chat_messages used for populating search_tsv in the background. Only defined over ''searchable'' rows of chat_messages where search_tsv is NULL.';
|
||||
|
||||
CREATE INDEX idx_chat_messages_search_tsv_pending ON chat_messages USING btree (id DESC) WHERE ((search_tsv IS NULL) AND (deleted = false) AND (visibility = ANY (ARRAY['user'::chat_message_visibility, 'both'::chat_message_visibility])) AND (role = ANY (ARRAY['user'::chat_message_role, 'assistant'::chat_message_role])));
|
||||
|
||||
CREATE INDEX idx_chat_messages_user_prompts ON chat_messages USING btree (chat_id, id DESC) WHERE ((deleted = false) AND (role = 'user'::chat_message_role) AND (visibility = ANY (ARRAY['user'::chat_message_visibility, 'both'::chat_message_visibility])));
|
||||
|
||||
CREATE INDEX idx_chat_model_configs_ai_provider_id ON chat_model_configs USING btree (ai_provider_id);
|
||||
@@ -4763,6 +4793,10 @@ CREATE INDEX idx_chats_parent_chat_id ON chats USING btree (parent_chat_id);
|
||||
|
||||
CREATE INDEX idx_chats_root_chat_id ON chats USING btree (root_chat_id);
|
||||
|
||||
CREATE INDEX idx_chats_title_fts ON chats USING gin (to_tsvector('simple'::regconfig, title));
|
||||
|
||||
COMMENT ON INDEX idx_chats_title_fts IS 'Used for full text search. Defined over all rows of the chats table.';
|
||||
|
||||
CREATE INDEX idx_chats_worker_acquisition_candidates ON chats USING btree (status, updated_at, id) WHERE (archived = false);
|
||||
|
||||
CREATE INDEX idx_chats_workspace ON chats USING btree (workspace_id);
|
||||
|
||||
Reference in New Issue
Block a user