MCPcopy Index your code
hub / github.com/CodebuffAI/codebuff / SessionEndedBanner

Function SessionEndedBanner

cli/src/components/session-ended-banner.tsx:31–190  ·  view source on GitHub ↗
({
  isStreaming,
})

Source from the content-addressed store, hash-verified

29 * once no in-flight work needs the global stream-interrupt handler.
30 */
31export const SessionEndedBanner: React.FC<SessionEndedBannerProps> = ({
32 isStreaming,
33}) => {
34 const theme = useTheme()
35 const [pendingAction, setPendingAction] = useState<
36 'waiting-room' | 'same-chat' | null
37 >(null)
38
39 // All premium models share one daily pool; the server replicates the same
40 // snapshot under each premium model id, so the first entry has the right
41 // count.
42 const premiumQuota = useFreebuffSessionStore(
43 (s) => Object.values(getRateLimitsByModel(s.session) ?? {})[0] ?? null,
44 )
45 const isQuotaExhausted = premiumQuota
46 ? premiumQuota.recentCount >= premiumQuota.limit
47 : false
48 const accessTier = useFreebuffSessionStore((s) =>
49 s.session && 'accessTier' in s.session ? s.session.accessTier : 'full',
50 )
51 const quotaLabel =
52 accessTier === 'limited' ? 'sessions' : 'premium sessions'
53 const bannerTitle = premiumQuota
54 ? `Session ended · ${formatSessionUnits(premiumQuota.recentCount)} of ${premiumQuota.limit} ${quotaLabel} used today`
55 : 'Session ended'
56 const landingButtonLabel =
57 accessTier === 'limited' ? 'Back to start' : 'Change model'
58 const landingPendingLabel =
59 accessTier === 'limited'
60 ? 'Opening start screen…'
61 : 'Opening model selection…'
62
63 // While a request is still streaming, restart is disabled: it would
64 // unmount <Chat> and abort the in-flight agent run. The promise is "we
65 // let the agent finish" — honoring that means Enter does nothing until
66 // the stream ends or the user hits Esc.
67 const canRestart = !isStreaming && pendingAction === null
68 const pickNewModel = useCallback(() => {
69 if (!canRestart) return
70 setPendingAction('waiting-room')
71 // Drop back to the landing picker (status: 'none') so the user picks a
72 // model and hits Enter again to commit, instead of being silently
73 // re-queued. app.tsx swaps us into <WaitingRoomScreen> on the
74 // transition, unmounting this banner — no need to clear the pending state on
75 // success.
76 returnToFreebuffLanding({ resetChat: true }).catch(() =>
77 setPendingAction(null),
78 )
79 }, [canRestart])
80
81 const startSameChatSession = useCallback(() => {
82 if (!canRestart) return
83 setPendingAction('same-chat')
84 // Re-POST with the currently selected model and keep the chat/run state
85 // intact so the next prompt continues the same conversation.
86 refreshFreebuffSession().catch(() => setPendingAction(null))
87 }, [canRestart])
88

Callers

nothing calls this directly

Calls 6

useThemeFunction · 0.90
getRateLimitsByModelFunction · 0.90
formatSessionUnitsFunction · 0.90
returnToFreebuffLandingFunction · 0.90
refreshFreebuffSessionFunction · 0.90
isPlainEnterKeyFunction · 0.90

Tested by

no test coverage detected