-- name: DeleteChatByID :exec DELETE FROM chats WHERE id = @id::uuid; -- name: DeleteChatMessagesByChatID :exec DELETE FROM chat_messages WHERE chat_id = @chat_id::uuid; -- name: DeleteChatMessagesAfterID :exec DELETE FROM chat_messages WHERE chat_id = @chat_id::uuid AND id > @after_id::bigint; -- name: GetChatByID :one SELECT * FROM chats WHERE id = @id::uuid; -- name: GetChatMessageByID :one SELECT * FROM chat_messages WHERE id = @id::bigint; -- name: GetChatMessagesByChatID :many SELECT * FROM chat_messages WHERE chat_id = @chat_id::uuid AND visibility IN ('user', 'both') ORDER BY created_at ASC; -- name: GetChatMessagesForPromptByChatID :many WITH latest_compressed_summary AS ( SELECT id FROM chat_messages WHERE chat_id = @chat_id::uuid AND role = 'system' AND visibility IN ('model', 'both') AND compressed = TRUE ORDER BY created_at DESC, id DESC LIMIT 1 ) SELECT * FROM chat_messages WHERE chat_id = @chat_id::uuid AND visibility IN ('model', 'both') AND ( ( role = 'system' AND compressed = FALSE ) OR ( compressed = FALSE AND ( NOT EXISTS ( SELECT 1 FROM latest_compressed_summary ) OR id > ( SELECT id FROM latest_compressed_summary ) ) ) OR id = ( SELECT id FROM latest_compressed_summary ) ) ORDER BY created_at ASC, id ASC; -- name: GetChatsByOwnerID :many SELECT * FROM chats WHERE owner_id = @owner_id::uuid ORDER BY updated_at DESC; -- name: ListChildChatsByParentID :many SELECT * FROM chats WHERE parent_chat_id = @parent_chat_id::uuid ORDER BY created_at ASC; -- name: ListChatsByRootID :many SELECT * FROM chats WHERE root_chat_id = @root_chat_id::uuid ORDER BY created_at ASC; -- name: InsertChat :one INSERT INTO chats ( owner_id, workspace_id, workspace_agent_id, parent_chat_id, root_chat_id, last_model_config_id, title ) VALUES ( @owner_id::uuid, sqlc.narg('workspace_id')::uuid, sqlc.narg('workspace_agent_id')::uuid, sqlc.narg('parent_chat_id')::uuid, sqlc.narg('root_chat_id')::uuid, @last_model_config_id::uuid, @title::text ) RETURNING *; -- name: InsertChatMessage :one WITH updated_chat AS ( UPDATE chats SET last_model_config_id = sqlc.narg('model_config_id')::uuid WHERE id = @chat_id::uuid AND sqlc.narg('model_config_id')::uuid IS NOT NULL ) INSERT INTO chat_messages ( chat_id, model_config_id, role, content, visibility, input_tokens, output_tokens, total_tokens, reasoning_tokens, cache_creation_tokens, cache_read_tokens, context_limit, compressed ) VALUES ( @chat_id::uuid, sqlc.narg('model_config_id')::uuid, @role::text, sqlc.narg('content')::jsonb, @visibility::chat_message_visibility, sqlc.narg('input_tokens')::bigint, sqlc.narg('output_tokens')::bigint, sqlc.narg('total_tokens')::bigint, sqlc.narg('reasoning_tokens')::bigint, sqlc.narg('cache_creation_tokens')::bigint, sqlc.narg('cache_read_tokens')::bigint, sqlc.narg('context_limit')::bigint, COALESCE(sqlc.narg('compressed')::boolean, FALSE) ) RETURNING *; -- name: UpdateChatMessageByID :one UPDATE chat_messages SET model_config_id = COALESCE(sqlc.narg('model_config_id')::uuid, model_config_id), content = sqlc.narg('content')::jsonb WHERE id = @id::bigint RETURNING *; -- name: UpdateChatByID :one UPDATE chats SET title = @title::text, updated_at = NOW() WHERE id = @id::uuid RETURNING *; -- name: UpdateChatWorkspace :one UPDATE chats SET workspace_id = sqlc.narg('workspace_id')::uuid, workspace_agent_id = sqlc.narg('workspace_agent_id')::uuid, updated_at = NOW() WHERE id = @id::uuid RETURNING *; -- name: AcquireChat :one -- Acquires a pending chat for processing. Uses SKIP LOCKED to prevent -- multiple replicas from acquiring the same chat. UPDATE chats SET status = 'running'::chat_status, started_at = @started_at::timestamptz, heartbeat_at = @started_at::timestamptz, updated_at = @started_at::timestamptz, worker_id = @worker_id::uuid WHERE id = ( SELECT id FROM chats WHERE status = 'pending'::chat_status ORDER BY updated_at ASC FOR UPDATE SKIP LOCKED LIMIT 1 ) RETURNING *; -- name: UpdateChatStatus :one UPDATE chats SET status = @status::chat_status, worker_id = sqlc.narg('worker_id')::uuid, started_at = sqlc.narg('started_at')::timestamptz, heartbeat_at = sqlc.narg('heartbeat_at')::timestamptz, updated_at = NOW() WHERE id = @id::uuid RETURNING *; -- name: GetStaleChats :many -- Find chats that appear stuck (running but heartbeat has expired). -- Used for recovery after coderd crashes or long hangs. SELECT * FROM chats WHERE status = 'running'::chat_status AND heartbeat_at < @stale_threshold::timestamptz; -- name: UpdateChatHeartbeat :execrows -- Bumps the heartbeat timestamp for a running chat so that other -- replicas know the worker is still alive. UPDATE chats SET heartbeat_at = NOW() WHERE id = @id::uuid AND worker_id = @worker_id::uuid AND status = 'running'::chat_status; -- name: GetChatDiffStatusByChatID :one SELECT * FROM chat_diff_statuses WHERE chat_id = @chat_id::uuid; -- name: GetChatDiffStatusesByChatIDs :many SELECT * FROM chat_diff_statuses WHERE chat_id = ANY(@chat_ids::uuid[]); -- name: UpsertChatDiffStatusReference :one INSERT INTO chat_diff_statuses ( chat_id, url, git_branch, git_remote_origin, stale_at ) VALUES ( @chat_id::uuid, sqlc.narg('url')::text, @git_branch::text, @git_remote_origin::text, @stale_at::timestamptz ) ON CONFLICT (chat_id) DO UPDATE SET url = CASE WHEN EXCLUDED.url IS NOT NULL THEN EXCLUDED.url ELSE chat_diff_statuses.url END, git_branch = CASE WHEN EXCLUDED.git_branch != '' THEN EXCLUDED.git_branch ELSE chat_diff_statuses.git_branch END, git_remote_origin = CASE WHEN EXCLUDED.git_remote_origin != '' THEN EXCLUDED.git_remote_origin ELSE chat_diff_statuses.git_remote_origin END, stale_at = EXCLUDED.stale_at, updated_at = NOW() RETURNING *; -- name: UpsertChatDiffStatus :one INSERT INTO chat_diff_statuses ( chat_id, url, pull_request_state, changes_requested, additions, deletions, changed_files, refreshed_at, stale_at ) VALUES ( @chat_id::uuid, sqlc.narg('url')::text, sqlc.narg('pull_request_state')::text, @changes_requested::boolean, @additions::integer, @deletions::integer, @changed_files::integer, @refreshed_at::timestamptz, @stale_at::timestamptz ) ON CONFLICT (chat_id) DO UPDATE SET url = EXCLUDED.url, pull_request_state = EXCLUDED.pull_request_state, changes_requested = EXCLUDED.changes_requested, additions = EXCLUDED.additions, deletions = EXCLUDED.deletions, changed_files = EXCLUDED.changed_files, refreshed_at = EXCLUDED.refreshed_at, stale_at = EXCLUDED.stale_at, updated_at = NOW() RETURNING *; -- name: InsertChatQueuedMessage :one INSERT INTO chat_queued_messages (chat_id, content) VALUES (@chat_id, @content) RETURNING *; -- name: GetChatQueuedMessages :many SELECT * FROM chat_queued_messages WHERE chat_id = @chat_id ORDER BY id ASC; -- name: DeleteChatQueuedMessage :exec DELETE FROM chat_queued_messages WHERE id = @id AND chat_id = @chat_id; -- name: DeleteAllChatQueuedMessages :exec DELETE FROM chat_queued_messages WHERE chat_id = @chat_id; -- name: PopNextQueuedMessage :one DELETE FROM chat_queued_messages WHERE id = ( SELECT cqm.id FROM chat_queued_messages cqm WHERE cqm.chat_id = @chat_id ORDER BY cqm.id ASC LIMIT 1 ) RETURNING *; -- name: GetChatByIDForUpdate :one SELECT * FROM chats WHERE id = @id::uuid FOR UPDATE;