Files
coder/coderd/database/migrations/000449_aibridge_session_indexes.up.sql
Danny Kopping 43a1af3cd6 feat: session list API (#23202)
<!--

If you have used AI to produce some or all of this PR, please ensure you have read our [AI Contribution guidelines](https://coder.com/docs/about/contributing/AI_CONTRIBUTING) before submitting.

-->

_Disclaimer:_ _initially_ _produced_ _by_ _Claude_ _Opus_ _4\.6,_ _heavily_ _modified_ _and_ _reviewed_ _by_ _me._

Closes https://github.com/coder/internal/issues/1360

Adds a new `/api/v2/aibridge/sessions` API which returns "sessions".

Sessions, as defined in the [RFC](https://www.notion.so/coderhq/AI-Bridge-Sessions-Threads-2ccd579be59280f28021d3baf7472fbe?source=copy_link), are a set of interceptions logically grouped by a session key issued by the client.  
The API design for this endpoint was done in [this doc](https://github.com/coder/internal/issues/1360).

If the client has not provided a session ID, we will revert to the thread root ID, and if that's not present we use the interception's own ID (i.e. a session of a single interception - which is effectively what we show currently in our `/api/v2/aibridge/interceptions` API).

The SQL query looks gnarly but it's relatively simple, and seems to perform well (~200ms) even when I import dogfood's `aibridge_*` tables into my workspace. If we need to improve performance on this later we can investigate materialized views, perhaps, but for now I don't think it's warranted.

---

_The PR looks large but it's got a lot of generated code; the actual changes aren't huge._
2026-03-24 08:58:47 +02:00

41 lines
1.8 KiB
SQL

-- A "session" groups related interceptions together. See the COMMENT ON
-- COLUMN below for the full business-logic description.
ALTER TABLE aibridge_interceptions
ADD COLUMN session_id TEXT NOT NULL
GENERATED ALWAYS AS (
COALESCE(
client_session_id,
thread_root_id::text,
id::text
)
) STORED;
-- Searching and grouping on the resolved session ID will be common.
CREATE INDEX idx_aibridge_interceptions_session_id
ON aibridge_interceptions (session_id)
WHERE ended_at IS NOT NULL;
COMMENT ON COLUMN aibridge_interceptions.session_id IS
'Groups related interceptions into a logical session. '
'Determined by a priority chain: '
'(1) client_session_id — an explicit session identifier supplied by the '
'calling client (e.g. Claude Code); '
'(2) thread_root_id — the root of an agentic thread detected by Bridge '
'through tool-call correlation, used when the client does not supply its '
'own session ID; '
'(3) id — the interception''s own ID, used as a last resort so every '
'interception belongs to exactly one session even if it is standalone. '
'This is a generated column stored on disk so it can be indexed and '
'joined without recomputing the COALESCE on every query.';
-- Composite index for the most common filter path used by
-- ListAIBridgeSessions: initiator_id equality + started_at range,
-- with ended_at IS NOT NULL as a partial filter.
CREATE INDEX idx_aibridge_interceptions_sessions_filter
ON aibridge_interceptions (initiator_id, started_at DESC, id DESC)
WHERE ended_at IS NOT NULL;
-- Supports lateral prompt lookup by interception + recency.
CREATE INDEX idx_aibridge_user_prompts_interception_created
ON aibridge_user_prompts (interception_id, created_at DESC, id DESC);