fix(desktop): gate prompts on provider setup

Show the desktop provider onboarding flow before prompt submission when no inference provider is configured, preventing fresh installs from falling through to backend credential errors.
This commit is contained in:
Brooklyn Nicholson
2026-05-07 22:41:10 -04:00
parent 89d5ee4b10
commit 8d95e006b8
4 changed files with 76 additions and 52 deletions
@@ -25,6 +25,7 @@ import {
type ComposerAttachment
} from '@/store/composer'
import { clearNotifications, notify, notifyError } from '@/store/notifications'
import { requestDesktopOnboarding } from '@/store/onboarding'
import { $busy, $messages, setAwaitingResponse, setBusy, setMessages } from '@/store/session'
import type { ClientSessionState, ImageAttachResponse, SlashExecResponse } from '../../types'
@@ -45,6 +46,16 @@ function blobToDataUrl(blob: Blob): Promise<string> {
})
}
interface SetupStatus {
provider_configured?: boolean
}
function isProviderSetupError(error: unknown) {
const message = error instanceof Error ? error.message : String(error)
return /No inference provider configured|OPENROUTER_API_KEY|OPENAI_API_KEY|ANTHROPIC_API_KEY/i.test(message)
}
interface PromptActionsOptions {
activeSessionId: string | null
activeSessionIdRef: MutableRefObject<string | null>
@@ -216,6 +227,15 @@ export function usePromptActions({
setAwaitingResponse(true)
clearNotifications()
const setup = await requestGateway<SetupStatus>('setup.status').catch(() => null)
if (setup?.provider_configured === false) {
releaseBusy()
requestDesktopOnboarding('Add a provider credential before sending your first message.')
return
}
let sessionId = activeSessionId
if (!sessionId) {
@@ -257,6 +277,13 @@ export function usePromptActions({
} catch (err) {
releaseBusy()
updateSessionState(sessionId, state => ({ ...state, busy: false, awaitingResponse: false }))
if (isProviderSetupError(err)) {
requestDesktopOnboarding('Add a provider credential before sending your first message.')
return
}
notifyError(err, 'Prompt failed')
}
},