mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: session detail API (#23203)
This commit is contained in:
@@ -1092,6 +1092,45 @@ func (q *sqlQuerier) ListAIBridgeInterceptionsTelemetrySummaries(ctx context.Con
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const listAIBridgeModelThoughtsByInterceptionIDs = `-- name: ListAIBridgeModelThoughtsByInterceptionIDs :many
|
||||
SELECT
|
||||
interception_id, content, metadata, created_at
|
||||
FROM
|
||||
aibridge_model_thoughts
|
||||
WHERE
|
||||
interception_id = ANY($1::uuid[])
|
||||
ORDER BY
|
||||
created_at ASC
|
||||
`
|
||||
|
||||
func (q *sqlQuerier) ListAIBridgeModelThoughtsByInterceptionIDs(ctx context.Context, interceptionIds []uuid.UUID) ([]AIBridgeModelThought, error) {
|
||||
rows, err := q.db.QueryContext(ctx, listAIBridgeModelThoughtsByInterceptionIDs, pq.Array(interceptionIds))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []AIBridgeModelThought
|
||||
for rows.Next() {
|
||||
var i AIBridgeModelThought
|
||||
if err := rows.Scan(
|
||||
&i.InterceptionID,
|
||||
&i.Content,
|
||||
&i.Metadata,
|
||||
&i.CreatedAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const listAIBridgeModels = `-- name: ListAIBridgeModels :many
|
||||
SELECT
|
||||
model
|
||||
@@ -1146,6 +1185,115 @@ func (q *sqlQuerier) ListAIBridgeModels(ctx context.Context, arg ListAIBridgeMod
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const listAIBridgeSessionThreads = `-- name: ListAIBridgeSessionThreads :many
|
||||
WITH paginated_threads AS (
|
||||
SELECT
|
||||
-- Find thread root interceptions (thread_root_id IS NULL), apply cursor
|
||||
-- pagination, and return the page.
|
||||
aibridge_interceptions.id AS thread_id,
|
||||
aibridge_interceptions.started_at
|
||||
FROM
|
||||
aibridge_interceptions
|
||||
WHERE
|
||||
aibridge_interceptions.session_id = $1::text
|
||||
AND aibridge_interceptions.ended_at IS NOT NULL
|
||||
AND aibridge_interceptions.thread_root_id IS NULL
|
||||
-- Pagination cursor.
|
||||
AND ($2::uuid = '00000000-0000-0000-0000-000000000000'::uuid OR
|
||||
(aibridge_interceptions.started_at, aibridge_interceptions.id) > (
|
||||
(SELECT started_at FROM aibridge_interceptions ai2 WHERE ai2.id = $2),
|
||||
$2::uuid
|
||||
)
|
||||
)
|
||||
AND ($3::uuid = '00000000-0000-0000-0000-000000000000'::uuid OR
|
||||
(aibridge_interceptions.started_at, aibridge_interceptions.id) < (
|
||||
(SELECT started_at FROM aibridge_interceptions ai2 WHERE ai2.id = $3),
|
||||
$3::uuid
|
||||
)
|
||||
)
|
||||
-- @authorize_filter
|
||||
ORDER BY
|
||||
aibridge_interceptions.started_at ASC,
|
||||
aibridge_interceptions.id ASC
|
||||
LIMIT COALESCE(NULLIF($4::integer, 0), 50)
|
||||
)
|
||||
SELECT
|
||||
COALESCE(aibridge_interceptions.thread_root_id, aibridge_interceptions.id) AS thread_id,
|
||||
aibridge_interceptions.id, aibridge_interceptions.initiator_id, aibridge_interceptions.provider, aibridge_interceptions.model, aibridge_interceptions.started_at, aibridge_interceptions.metadata, aibridge_interceptions.ended_at, aibridge_interceptions.api_key_id, aibridge_interceptions.client, aibridge_interceptions.thread_parent_id, aibridge_interceptions.thread_root_id, aibridge_interceptions.client_session_id, aibridge_interceptions.session_id
|
||||
FROM
|
||||
aibridge_interceptions
|
||||
JOIN
|
||||
paginated_threads pt
|
||||
ON pt.thread_id = COALESCE(aibridge_interceptions.thread_root_id, aibridge_interceptions.id)
|
||||
WHERE
|
||||
aibridge_interceptions.session_id = $1::text
|
||||
AND aibridge_interceptions.ended_at IS NOT NULL
|
||||
-- @authorize_filter
|
||||
ORDER BY
|
||||
-- Ensure threads and their associated interceptions (agentic loops) are sorted chronologically.
|
||||
pt.started_at ASC,
|
||||
pt.thread_id ASC,
|
||||
aibridge_interceptions.started_at ASC,
|
||||
aibridge_interceptions.id ASC
|
||||
`
|
||||
|
||||
type ListAIBridgeSessionThreadsParams struct {
|
||||
SessionID string `db:"session_id" json:"session_id"`
|
||||
AfterID uuid.UUID `db:"after_id" json:"after_id"`
|
||||
BeforeID uuid.UUID `db:"before_id" json:"before_id"`
|
||||
Limit int32 `db:"limit_" json:"limit_"`
|
||||
}
|
||||
|
||||
type ListAIBridgeSessionThreadsRow struct {
|
||||
ThreadID uuid.UUID `db:"thread_id" json:"thread_id"`
|
||||
AIBridgeInterception AIBridgeInterception `db:"aibridge_interception" json:"aibridge_interception"`
|
||||
}
|
||||
|
||||
// Returns all interceptions belonging to paginated threads within a session.
|
||||
// Threads are paginated by (started_at, thread_id) cursor.
|
||||
func (q *sqlQuerier) ListAIBridgeSessionThreads(ctx context.Context, arg ListAIBridgeSessionThreadsParams) ([]ListAIBridgeSessionThreadsRow, error) {
|
||||
rows, err := q.db.QueryContext(ctx, listAIBridgeSessionThreads,
|
||||
arg.SessionID,
|
||||
arg.AfterID,
|
||||
arg.BeforeID,
|
||||
arg.Limit,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []ListAIBridgeSessionThreadsRow
|
||||
for rows.Next() {
|
||||
var i ListAIBridgeSessionThreadsRow
|
||||
if err := rows.Scan(
|
||||
&i.ThreadID,
|
||||
&i.AIBridgeInterception.ID,
|
||||
&i.AIBridgeInterception.InitiatorID,
|
||||
&i.AIBridgeInterception.Provider,
|
||||
&i.AIBridgeInterception.Model,
|
||||
&i.AIBridgeInterception.StartedAt,
|
||||
&i.AIBridgeInterception.Metadata,
|
||||
&i.AIBridgeInterception.EndedAt,
|
||||
&i.AIBridgeInterception.APIKeyID,
|
||||
&i.AIBridgeInterception.Client,
|
||||
&i.AIBridgeInterception.ThreadParentID,
|
||||
&i.AIBridgeInterception.ThreadRootID,
|
||||
&i.AIBridgeInterception.ClientSessionID,
|
||||
&i.AIBridgeInterception.SessionID,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const listAIBridgeSessions = `-- name: ListAIBridgeSessions :many
|
||||
WITH filtered_interceptions AS (
|
||||
SELECT
|
||||
|
||||
Reference in New Issue
Block a user