mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: add chat summary tab in the right sidebar and per-chat cost endpoint (#26649)
Stacked on #26657 (the persisted whole-chat summary backend). Base branch is `chat-summary-62j9`; review/merge that first. Adds a reusable `ChatSummary` component. The summary text is the persisted whole-chat summary (`chat.summary`) introduced by #26657. It is generated asynchronously and may be `null` until the first summary is produced, in which case the popover renders a muted empty state. Live updates arrive via that PR's `chat_summary_change` watch event, which is already merged into the chat caches. Cost is served by a new per-chat endpoint, `GET /api/experimental/chats/{chat}/cost`, which rolls up assistant-message cost across a chat's root and child (subagent) chats and is authorized like the other `{chat}` routes (read on the chat, 404 otherwise). Visual and interaction coverage lives in `ChatSummary.stories.tsx` and `ChatSummaryPopover.stories.tsx` (including populated-summary, empty-state, and cost-loading cases). --------- Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -2198,7 +2198,7 @@ SELECT
|
||||
OR cm.cache_creation_tokens IS NOT NULL
|
||||
OR cm.cache_read_tokens IS NOT NULL
|
||||
)
|
||||
)::bigint AS unpriced_message_count,
|
||||
)::bigint AS unpriced_messages_having_usage_count,
|
||||
COALESCE(SUM(cm.input_tokens), 0)::bigint AS total_input_tokens,
|
||||
COALESCE(SUM(cm.output_tokens), 0)::bigint AS total_output_tokens,
|
||||
COALESCE(SUM(cm.cache_read_tokens), 0)::bigint AS total_cache_read_tokens,
|
||||
@@ -2295,6 +2295,47 @@ FROM chat_costs cc
|
||||
LEFT JOIN chats rc ON rc.id = cc.root_chat_id
|
||||
ORDER BY cc.total_cost_micros DESC;
|
||||
|
||||
-- name: GetChatModelUsageCostByChatID :one
|
||||
-- Assistant-message cost rolled up over the requested chat's subtree: the
|
||||
-- chat itself plus every descendant reachable through parent_chat_id. A
|
||||
-- root chat therefore reports its whole tree, while a subagent chat
|
||||
-- reports only its own spend plus any nested subagents it spawned.
|
||||
WITH RECURSIVE target AS (
|
||||
SELECT @chat_id::uuid AS chat_id
|
||||
), subtree AS (
|
||||
SELECT chat_id AS id FROM target
|
||||
UNION ALL
|
||||
SELECT c.id
|
||||
FROM chats c
|
||||
JOIN subtree s ON c.parent_chat_id = s.id
|
||||
), costs AS (
|
||||
SELECT
|
||||
COALESCE(SUM(cm.total_cost_micros), 0)::bigint AS total_cost_micros,
|
||||
COUNT(*) FILTER (
|
||||
WHERE cm.total_cost_micros IS NOT NULL
|
||||
)::bigint AS priced_message_count,
|
||||
COUNT(*) FILTER (
|
||||
WHERE cm.total_cost_micros IS NULL
|
||||
AND (
|
||||
cm.input_tokens IS NOT NULL
|
||||
OR cm.output_tokens IS NOT NULL
|
||||
OR cm.reasoning_tokens IS NOT NULL
|
||||
OR cm.cache_creation_tokens IS NOT NULL
|
||||
OR cm.cache_read_tokens IS NOT NULL
|
||||
)
|
||||
)::bigint AS unpriced_messages_having_usage_count
|
||||
FROM chat_messages cm
|
||||
JOIN subtree s ON s.id = cm.chat_id
|
||||
WHERE cm.role = 'assistant'
|
||||
)
|
||||
SELECT
|
||||
t.chat_id,
|
||||
costs.total_cost_micros,
|
||||
costs.priced_message_count,
|
||||
costs.unpriced_messages_having_usage_count
|
||||
FROM target t
|
||||
CROSS JOIN costs;
|
||||
|
||||
-- name: GetChatCostPerUser :many
|
||||
-- Deployment-wide per-user cost rollup within a date range.
|
||||
-- Only counts assistant-role messages.
|
||||
|
||||
Reference in New Issue
Block a user