@@ -8,8 +8,9 @@ import { hasDirectUrlReference, prioritizePerplexity } from "@/lib/url-access"
88import { waitForDrain } from "@/lib/drain-registry"
99import {
1010 getApiKeyPromptMessage ,
11+ getBudgetExceededMessage ,
1112 getMissingApiKeyMessage ,
12- parseNoKeyProviderFromResponse ,
13+ parse402FromResponse ,
1314} from "@/lib/api-key-errors"
1415import { getClientKey , getAccessCode , isFirstRunKeyless } from "@/lib/client-api-keys"
1516import { authEnabled } from "@/lib/deploy-config"
@@ -403,7 +404,15 @@ export function useDebateEngine(config: {
403404 }
404405
405406 if ( res . status === 402 ) {
406- const missingProvider = ( await parseNoKeyProviderFromResponse ( res ) ) ?? provider
407+ const blocked = await parse402FromResponse ( res )
408+ if ( blocked ?. kind === "host_budget_exceeded" ) {
409+ // Daily host budget wall, not a key problem - the key toast would mislead.
410+ updatePlaceholder ( getBudgetExceededMessage ( ! isAnonymousRef . current , locale ) )
411+ stopRef . current = true
412+ clearTypingIfCurrentSession ( )
413+ return null
414+ }
415+ const missingProvider = blocked ?. provider ?? provider
407416 onApiKeyRequired ?.( missingProvider )
408417 // A keyless first-run visitor gets a generic welcome; the panel's
409418 // lead provider (perplexity) is arbitrary, so don't single it out.
@@ -549,8 +558,11 @@ export function useDebateEngine(config: {
549558 . then ( async ( res ) => {
550559 if ( sessionIdRef . current !== sessionId || stopRef . current ) return
551560 if ( res . status === 402 ) {
552- const missingProvider = await parseNoKeyProviderFromResponse ( res )
553- if ( missingProvider ) onApiKeyRequired ?.( missingProvider )
561+ // Budget wall stays silent here - the chat calls surface it.
562+ const blocked = await parse402FromResponse ( res )
563+ if ( blocked ?. kind === "no_key" && blocked . provider ) {
564+ onApiKeyRequired ?.( blocked . provider )
565+ }
554566 return
555567 }
556568 if ( ! res . ok ) return
@@ -693,14 +705,21 @@ export function useDebateEngine(config: {
693705 logDebate ( "verdict:skipped-stopped" , { } )
694706 } else if ( res . status === 402 ) {
695707 if ( sessionIdRef . current !== thisSession ) return
696- const missingProvider = await parseNoKeyProviderFromResponse ( res )
697- if ( missingProvider ) onApiKeyRequired ?.( missingProvider )
698- else onApiKeyRequired ?.( "gemini" )
699- dispatch ( {
700- type : "UPDATE_MESSAGE" ,
701- id : analyzingMsg . id ,
702- content : SYSTEM_MESSAGES . missingConsensusKey ( locale , ! isAnonymousRef . current ) ,
703- } )
708+ const blocked = await parse402FromResponse ( res )
709+ if ( blocked ?. kind === "host_budget_exceeded" ) {
710+ dispatch ( {
711+ type : "UPDATE_MESSAGE" ,
712+ id : analyzingMsg . id ,
713+ content : getBudgetExceededMessage ( ! isAnonymousRef . current , locale ) ,
714+ } )
715+ } else {
716+ onApiKeyRequired ?.( blocked ?. provider ?? "gemini" )
717+ dispatch ( {
718+ type : "UPDATE_MESSAGE" ,
719+ id : analyzingMsg . id ,
720+ content : SYSTEM_MESSAGES . missingConsensusKey ( locale , ! isAnonymousRef . current ) ,
721+ } )
722+ }
704723 } else if ( ! res . ok ) {
705724 const failMsg = await consensusFailureMessage ( res , locale )
706725 logDebate ( "verdict:failed" , { status : res . status , message : failMsg } )
@@ -822,9 +841,16 @@ export function useDebateEngine(config: {
822841 . then ( async ( res ) => {
823842 if ( res . status === 402 ) {
824843 if ( sessionIdRef . current !== stoppedSession ) return null
825- const missingProvider = await parseNoKeyProviderFromResponse ( res )
826- if ( missingProvider ) onApiKeyRequired ?.( missingProvider )
827- else onApiKeyRequired ?.( "gemini" )
844+ const blocked = await parse402FromResponse ( res )
845+ if ( blocked ?. kind === "host_budget_exceeded" ) {
846+ dispatch ( {
847+ type : "UPDATE_MESSAGE" ,
848+ id : analyzingMsg . id ,
849+ content : getBudgetExceededMessage ( ! isAnonymousRef . current , locale ) ,
850+ } )
851+ return null
852+ }
853+ onApiKeyRequired ?.( blocked ?. provider ?? "gemini" )
828854 dispatch ( {
829855 type : "UPDATE_MESSAGE" ,
830856 id : analyzingMsg . id ,
0 commit comments