Skip to content

Commit eeba1c6

Browse files
committed
Tell people in wait room their country is blocked
1 parent 9c3ff45 commit eeba1c6

4 files changed

Lines changed: 45 additions & 0 deletions

File tree

cli/src/hooks/helpers/send-message.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
import { getErrorObject } from '@codebuff/common/util/error'
22

33
import {
4+
markFreebuffSessionCountryBlocked,
45
markFreebuffSessionEnded,
56
markFreebuffSessionSuperseded,
67
refreshFreebuffSession,
78
} from '../use-freebuff-session'
89
import { getProjectRoot } from '../../project-files'
910
import { useChatStore } from '../../state/chat-store'
11+
import { IS_FREEBUFF } from '../../utils/constants'
1012
import { processBashContext } from '../../utils/bash-context-processor'
1113
import { markRunningAgentsAsCancelled } from '../../utils/block-operations'
1214
import {
15+
getCountryCodeFromFreeModeError,
1316
getFreebuffGateErrorKind,
1417
isOutOfCreditsError,
1518
isFreeModeUnavailableError,
@@ -389,6 +392,11 @@ export const handleRunCompletion = (params: {
389392

390393
if (isFreeModeUnavailableError(output)) {
391394
updater.setError(FREE_MODE_UNAVAILABLE_MESSAGE)
395+
if (IS_FREEBUFF) {
396+
markFreebuffSessionCountryBlocked(
397+
getCountryCodeFromFreeModeError(output) ?? 'UNKNOWN',
398+
)
399+
}
392400
finalizeAfterError()
393401
return
394402
}
@@ -484,6 +492,11 @@ export const handleRunError = (params: {
484492

485493
if (isFreeModeUnavailableError(error)) {
486494
updater.setError(FREE_MODE_UNAVAILABLE_MESSAGE)
495+
if (IS_FREEBUFF) {
496+
markFreebuffSessionCountryBlocked(
497+
getCountryCodeFromFreeModeError(error) ?? 'UNKNOWN',
498+
)
499+
}
487500
return
488501
}
489502

cli/src/hooks/use-freebuff-session.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,21 @@ export function markFreebuffSessionSuperseded(): void {
280280
controller?.apply({ status: 'superseded' })
281281
}
282282

283+
/** Flip into the terminal `country_blocked` state from outside the poll loop.
284+
* Used when the chat-completions gate rejects on country even though the
285+
* session-level country check had failed open (null detection → admitted).
286+
* Transitioning the session state here unmounts the Chat surface in favor of
287+
* the waiting-room's country_blocked message, so the user can't keep typing
288+
* and sending doomed requests. */
289+
export function markFreebuffSessionCountryBlocked(countryCode: string): void {
290+
if (!IS_FREEBUFF) return
291+
controller?.abort()
292+
controller?.apply({ status: 'country_blocked', countryCode })
293+
// Best-effort DELETE so we don't hold a waiting-room seat on a session the
294+
// server is already refusing to serve at chat time.
295+
releaseFreebuffSlot().catch(() => {})
296+
}
297+
283298
/** Flip into the local `ended` state without an instanceId (server has lost
284299
* our row). The chat surface stays mounted with the rejoin banner. */
285300
export function markFreebuffSessionEnded(): void {

cli/src/utils/error-handling.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,22 @@ export const isFreeModeUnavailableError = (error: unknown): boolean => {
5757
return false
5858
}
5959

60+
/**
61+
* Extract the detected countryCode off a free_mode_unavailable error, if the
62+
* server included one. Used to populate the country_blocked screen after the
63+
* chat-completions gate rejects a user whose session-level country check had
64+
* previously failed open (null country detection → admitted → now blocked).
65+
*/
66+
export const getCountryCodeFromFreeModeError = (
67+
error: unknown,
68+
): string | null => {
69+
if (!isFreeModeUnavailableError(error)) return null
70+
const candidate = (error as { countryCode?: unknown }).countryCode
71+
return typeof candidate === 'string' && candidate.length > 0
72+
? candidate
73+
: null
74+
}
75+
6076
/**
6177
* Freebuff waiting-room gate errors returned by /api/v1/chat/completions.
6278
*

web/src/app/api/v1/chat/completions/_post.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,7 @@ export async function postChatCompletions(params: {
286286
{
287287
error: 'free_mode_unavailable',
288288
message: 'Free mode is not available in your country.',
289+
countryCode,
289290
},
290291
{ status: 403 },
291292
)

0 commit comments

Comments
 (0)