Task 07 — Wire non-streaming chat completions
Depends on: 03, 04, 06
Unblocks: 11
Goal
The simplest end-to-end recorder integration: a non-streaming OpenAI
chat-completions request results in exactly one usage_events row with
populated token counts and price snapshots.
Scope
In src/services/copilot/create-chat-completions.ts and
src/routes/chat-completions/handler.ts:
- Capture
tStart = Date.now() at the beginning of the handler.
- After a successful non-streaming response, call
recordUsage with:
usage = normalizeOpenAIFinal(response.usage)
endpoint = 'chat.completions'
upstreamFormat = 'openai'
isStreaming = false
status = 'ok'
durationMs = Date.now() - tStart
requestId = response.id
isInternal = c.req.header('x-internal-pricing-sync') === '1'
- On thrown error before
recordUsage: best-effort write a status = 'error'
event with zero usage. Skip on missing model.
Streaming branch: untouched in this task (task 08 owns it).
Definition of Done
Task 07 — Wire non-streaming chat completions
Depends on: 03, 04, 06
Unblocks: 11
Goal
The simplest end-to-end recorder integration: a non-streaming OpenAI
chat-completions request results in exactly one
usage_eventsrow withpopulated token counts and price snapshots.
Scope
In
src/services/copilot/create-chat-completions.tsandsrc/routes/chat-completions/handler.ts:tStart = Date.now()at the beginning of the handler.recordUsagewith:usage = normalizeOpenAIFinal(response.usage)endpoint = 'chat.completions'upstreamFormat = 'openai'isStreaming = falsestatus = 'ok'durationMs = Date.now() - tStartrequestId = response.idisInternal = c.req.header('x-internal-pricing-sync') === '1'recordUsage: best-effort write astatus = 'error'event with zero usage. Skip on missing model.
Streaming branch: untouched in this task (task 08 owns it).
Definition of Done
usage_eventsand 1 / +1 inusage_daily.account_namereflects the chosenaccount.
isInternalrequest (header set) does not produce a row.docs/tasks/07-wire-nonstreaming-chat.mddocs/design/