@@ -420,6 +420,39 @@ describe('/api/v1/chat/completions POST endpoint', () => {
420420 expect ( body . message ) . toContain ( expectedResetCountdown )
421421 expect ( body . message ) . not . toContain ( nextQuotaReset )
422422 } )
423+
424+ it ( 'skips credit check when in FREE mode even with 0 credits' , async ( ) => {
425+ const req = new NextRequest (
426+ 'http://localhost:3000/api/v1/chat/completions' ,
427+ {
428+ method : 'POST' ,
429+ headers : { Authorization : 'Bearer test-api-key-no-credits' } ,
430+ body : JSON . stringify ( {
431+ model : 'test/test-model' ,
432+ stream : false ,
433+ codebuff_metadata : {
434+ run_id : 'run-123' ,
435+ client_id : 'test-client-id-123' ,
436+ cost_mode : 'free' ,
437+ } ,
438+ } ) ,
439+ } ,
440+ )
441+
442+ const response = await postChatCompletions ( {
443+ req,
444+ getUserInfoFromApiKey : mockGetUserInfoFromApiKey ,
445+ logger : mockLogger ,
446+ trackEvent : mockTrackEvent ,
447+ getUserUsageData : mockGetUserUsageData ,
448+ getAgentRunFromId : mockGetAgentRunFromId ,
449+ fetch : mockFetch ,
450+ insertMessageBigquery : mockInsertMessageBigquery ,
451+ loggerWithContext : mockLoggerWithContext ,
452+ } )
453+
454+ expect ( response . status ) . toBe ( 200 )
455+ } )
423456 } )
424457
425458 describe ( 'Successful responses' , ( ) => {
@@ -549,6 +582,52 @@ describe('/api/v1/chat/completions POST endpoint', () => {
549582 expect ( body . message ) . toContain ( 'Enable "Continue with credits"' )
550583 } )
551584
585+ it ( 'skips subscription limit check when in FREE mode even with fallback disabled' , async ( ) => {
586+ const weeklyLimitError : BlockGrantResult = {
587+ error : 'weekly_limit_reached' ,
588+ used : 3500 ,
589+ limit : 3500 ,
590+ resetsAt : new Date ( Date . now ( ) + 3 * 24 * 60 * 60 * 1000 ) ,
591+ }
592+ const mockEnsureSubscriberBlockGrant = mock ( async ( ) => weeklyLimitError )
593+ const mockGetUserPreferences : GetUserPreferencesFn = mock ( async ( ) => ( {
594+ fallbackToALaCarte : false ,
595+ } ) )
596+
597+ const freeModeRequest = new NextRequest (
598+ 'http://localhost:3000/api/v1/chat/completions' ,
599+ {
600+ method : 'POST' ,
601+ headers : { Authorization : 'Bearer test-api-key-123' } ,
602+ body : JSON . stringify ( {
603+ model : 'test/test-model' ,
604+ stream : false ,
605+ codebuff_metadata : {
606+ run_id : 'run-123' ,
607+ client_id : 'test-client-id-123' ,
608+ cost_mode : 'free' ,
609+ } ,
610+ } ) ,
611+ } ,
612+ )
613+
614+ const response = await postChatCompletions ( {
615+ req : freeModeRequest ,
616+ getUserInfoFromApiKey : mockGetUserInfoFromApiKey ,
617+ logger : mockLogger ,
618+ trackEvent : mockTrackEvent ,
619+ getUserUsageData : mockGetUserUsageData ,
620+ getAgentRunFromId : mockGetAgentRunFromId ,
621+ fetch : mockFetch ,
622+ insertMessageBigquery : mockInsertMessageBigquery ,
623+ loggerWithContext : mockLoggerWithContext ,
624+ ensureSubscriberBlockGrant : mockEnsureSubscriberBlockGrant ,
625+ getUserPreferences : mockGetUserPreferences ,
626+ } )
627+
628+ expect ( response . status ) . toBe ( 200 )
629+ } )
630+
552631 it ( 'returns 429 when block exhausted and fallback disabled' , async ( ) => {
553632 const blockExhaustedError : BlockGrantResult = {
554633 error : 'block_exhausted' ,
0 commit comments