1- import { beforeAll , beforeEach , describe , expect , it , jest } from '@jest/globals'
1+ import {
2+ beforeAll ,
3+ beforeEach ,
4+ describe ,
5+ expect ,
6+ it ,
7+ jest ,
8+ } from '@jest/globals'
29
310jest . mock ( '@codebuff/bigquery' , ( ) => ( {
411 setupBigQuery : jest . fn ( ) ,
512} ) )
613
7- jest . mock ( '@codebuff/billing' , ( ) => ( {
8- consumeCreditsAndAddAgentStep : jest . fn ( ) ,
9- recordMessageWithoutBilling : jest . fn ( ) ,
10- } ) )
11-
1214import type { ChatCompletionTraceRow } from '@codebuff/common/types/contracts/bigquery'
1315import type { ChatCompletionRequestBody } from '../types'
1416import type {
1517 recordChatCompletionTrace as recordChatCompletionTraceType ,
1618 resetChatCompletionTraceCacheForTests as resetChatCompletionTraceCacheForTestsType ,
17- } from '../helpers '
19+ } from '../chat-completion-trace '
1820
1921const testLogger = {
2022 debug : ( ) => { } ,
@@ -26,48 +28,60 @@ const testLogger = {
2628const baseBody = (
2729 messages : ChatCompletionRequestBody [ 'messages' ] ,
2830) : ChatCompletionRequestBody => ( {
29- model : 'deepseek/deepseek-v4-pro' ,
30- stream : true ,
31- messages,
32- tools : [
33- {
34- type : 'function' ,
35- function : { name : 'read_files' , parameters : { } } ,
36- } ,
37- ] ,
38- codebuff_metadata : {
39- client_id : 'client-1' ,
40- run_id : 'run-1' ,
41- trace_session_id : 'session-1' ,
42- trace_request_id : 'trace-1' ,
43- cost_mode : 'free' ,
31+ model : 'deepseek/deepseek-v4-pro' ,
32+ stream : true ,
33+ messages,
34+ tools : [
35+ {
36+ type : 'function' ,
37+ function : { name : 'read_files' , parameters : { } } ,
4438 } ,
39+ ] ,
40+ codebuff_metadata : {
41+ client_id : 'client-1' ,
42+ run_id : 'run-1' ,
43+ trace_session_id : 'session-1' ,
44+ trace_request_id : 'trace-1' ,
45+ cost_mode : 'free' ,
46+ } ,
4547} )
4648
4749describe ( 'buildChatCompletionTraceRow' , ( ) => {
4850 let recordChatCompletionTrace : typeof recordChatCompletionTraceType
4951 let resetChatCompletionTraceCacheForTests : typeof resetChatCompletionTraceCacheForTestsType
5052 let rows : ChatCompletionTraceRow [ ]
53+ let traceWriteTasks : Promise < void > [ ]
5154
5255 beforeAll ( async ( ) => {
53- const helpers = await import ( '../helpers ' )
54- recordChatCompletionTrace = helpers . recordChatCompletionTrace
56+ const traceModule = await import ( '../chat-completion-trace ' )
57+ recordChatCompletionTrace = traceModule . recordChatCompletionTrace
5558 resetChatCompletionTraceCacheForTests =
56- helpers . resetChatCompletionTraceCacheForTests
59+ traceModule . resetChatCompletionTraceCacheForTests
5760 } )
5861
5962 beforeEach ( ( ) => {
6063 resetChatCompletionTraceCacheForTests ( )
6164 rows = [ ]
65+ traceWriteTasks = [ ]
6266 } )
6367
68+ const scheduleTraceWrite = ( task : ( ) => Promise < void > ) => {
69+ traceWriteTasks . push ( task ( ) )
70+ }
71+
72+ const flushTraceWrites = async ( ) => {
73+ const tasks = traceWriteTasks
74+ traceWriteTasks = [ ]
75+ await Promise . all ( tasks )
76+ }
77+
6478 const record = async ( params : {
6579 body : ChatCompletionRequestBody
6680 userId ?: string
6781 agentId ?: string
6882 ancestorRunIds ?: string [ ]
6983 } ) => {
70- await recordChatCompletionTrace ( {
84+ recordChatCompletionTrace ( {
7185 body : params . body ,
7286 userId : params . userId ?? 'user-1' ,
7387 agentId : params . agentId ?? 'base2-free-deepseek' ,
@@ -77,7 +91,9 @@ describe('buildChatCompletionTraceRow', () => {
7791 rows . push ( row )
7892 return true
7993 } ,
94+ scheduleTraceWrite,
8095 } )
96+ await flushTraceWrites ( )
8197 return rows . at ( - 1 ) !
8298 }
8399
@@ -178,14 +194,16 @@ describe('buildChatCompletionTraceRow', () => {
178194 } )
179195
180196 it ( 'does not advance the prefix cache when BigQuery insert fails' , async ( ) => {
181- await recordChatCompletionTrace ( {
197+ recordChatCompletionTrace ( {
182198 body : baseBody ( [ { role : 'user' , content : 'hello' } ] ) ,
183199 userId : 'user-1' ,
184200 agentId : 'base2-free-deepseek' ,
185201 ancestorRunIds : [ ] ,
186202 logger : testLogger ,
187203 insertChatCompletionTraceBigquery : async ( ) => false ,
204+ scheduleTraceWrite,
188205 } )
206+ await flushTraceWrites ( )
189207
190208 const row = await record ( {
191209 body : baseBody ( [
@@ -210,7 +228,7 @@ describe('buildChatCompletionTraceRow', () => {
210228 cost_mode : 'free' ,
211229 }
212230
213- const traceRequestId = await recordChatCompletionTrace ( {
231+ const traceRequestId = recordChatCompletionTrace ( {
214232 body,
215233 userId : 'user-1' ,
216234 agentId : 'base2-free-deepseek' ,
@@ -220,10 +238,40 @@ describe('buildChatCompletionTraceRow', () => {
220238 rows . push ( row )
221239 return true
222240 } ,
241+ scheduleTraceWrite,
223242 } )
224243
225244 expect ( traceRequestId ) . toBeNull ( )
226245 expect ( rows ) . toHaveLength ( 0 )
227246 expect ( body . codebuff_metadata ?. trace_request_id ) . toBeUndefined ( )
228247 } )
248+
249+ it ( 'schedules BigQuery work off the caller stack' , async ( ) => {
250+ let scheduledTask : ( ( ) => Promise < void > ) | undefined
251+ const body = baseBody ( [ { role : 'user' , content : 'hello' } ] )
252+
253+ const traceRequestId = recordChatCompletionTrace ( {
254+ body,
255+ userId : 'user-1' ,
256+ agentId : 'base2-free-deepseek' ,
257+ ancestorRunIds : [ ] ,
258+ logger : testLogger ,
259+ insertChatCompletionTraceBigquery : async ( { row } ) => {
260+ rows . push ( row )
261+ return true
262+ } ,
263+ scheduleTraceWrite : ( task ) => {
264+ scheduledTask = task
265+ } ,
266+ } )
267+
268+ expect ( typeof traceRequestId ) . toBe ( 'string' )
269+ expect ( body . codebuff_metadata ?. trace_request_id ) . toBe ( traceRequestId )
270+ expect ( rows ) . toHaveLength ( 0 )
271+
272+ await scheduledTask ?.( )
273+
274+ expect ( rows ) . toHaveLength ( 1 )
275+ expect ( rows [ 0 ] ?. id ) . toBe ( traceRequestId )
276+ } )
229277} )
0 commit comments