(params: {
userId: string
accessTier?: FreebuffAccessTier
userEmail?: string | null | undefined
claimedInstanceId: string | null | undefined
/** Forces a real active session row check even when the waiting room is
* globally disabled or the user email normally bypasses it. Use for
* subagent/model combinations that must be bound to trusted session state. */
requireActiveSession?: boolean
/** Model the chat-completions request is for. When provided, the gate
* rejects requests whose model doesn't match the active session's model
* so a stale CLI tab can't slip a request through under the wrong model. */
requestedModel?: string | null | undefined
deps?: SessionDeps
})
| 671 | * for that detail. |
| 672 | */ |
| 673 | export async function checkSessionAdmissible(params: { |
| 674 | userId: string |
| 675 | accessTier?: FreebuffAccessTier |
| 676 | userEmail?: string | null | undefined |
| 677 | claimedInstanceId: string | null | undefined |
| 678 | /** Forces a real active session row check even when the waiting room is |
| 679 | * globally disabled or the user email normally bypasses it. Use for |
| 680 | * subagent/model combinations that must be bound to trusted session state. */ |
| 681 | requireActiveSession?: boolean |
| 682 | /** Model the chat-completions request is for. When provided, the gate |
| 683 | * rejects requests whose model doesn't match the active session's model |
| 684 | * so a stale CLI tab can't slip a request through under the wrong model. */ |
| 685 | requestedModel?: string | null | undefined |
| 686 | deps?: SessionDeps |
| 687 | }): Promise<SessionGateResult> { |
| 688 | const deps = params.deps ?? defaultDeps |
| 689 | const accessTier = params.accessTier ?? 'full' |
| 690 | if ( |
| 691 | !params.requireActiveSession && |
| 692 | (!deps.isWaitingRoomEnabled() || |
| 693 | isWaitingRoomBypassedForEmail(params.userEmail)) |
| 694 | ) { |
| 695 | return { ok: true, reason: 'disabled' } |
| 696 | } |
| 697 | |
| 698 | // Pre-waiting-room CLIs never send a freebuff_instance_id. Classify that up |
| 699 | // front so the caller gets a distinct code (→ 426 Upgrade Required) and the |
| 700 | // user sees a clear "please restart" message instead of a gate reject they |
| 701 | // can't interpret. |
| 702 | if (!params.claimedInstanceId) { |
| 703 | return { |
| 704 | ok: false, |
| 705 | code: 'freebuff_update_required', |
| 706 | message: |
| 707 | 'This version of freebuff is out of date. Please restart freebuff to upgrade and continue using free mode.', |
| 708 | } |
| 709 | } |
| 710 | |
| 711 | const row = await deps.getSessionRow(params.userId) |
| 712 | |
| 713 | if (!row) { |
| 714 | return { |
| 715 | ok: false, |
| 716 | code: 'waiting_room_required', |
| 717 | message: |
| 718 | 'No active free session. Call POST /api/v1/freebuff/session first.', |
| 719 | } |
| 720 | } |
| 721 | |
| 722 | if (row.status === 'queued') { |
| 723 | return { |
| 724 | ok: false, |
| 725 | code: 'waiting_room_queued', |
| 726 | message: |
| 727 | 'You are in the waiting room. Poll GET /api/v1/freebuff/session for your position.', |
| 728 | } |
| 729 | } |
| 730 |
no test coverage detected