mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
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._
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
DROP INDEX IF EXISTS idx_aibridge_interceptions_session_id;
|
||||
DROP INDEX IF EXISTS idx_aibridge_user_prompts_interception_created;
|
||||
DROP INDEX IF EXISTS idx_aibridge_interceptions_sessions_filter;
|
||||
|
||||
ALTER TABLE aibridge_interceptions DROP COLUMN IF EXISTS session_id;
|
||||
@@ -0,0 +1,40 @@
|
||||
-- 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);
|
||||
Reference in New Issue
Block a user