mirror of
https://github.com/coder/coder.git
synced 2026-06-02 20:48:20 +00:00
43a1af3cd6
<!-- 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._
41 lines
1.8 KiB
SQL
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);
|