Skip to content

Commit 4bee762

Browse files
felarof99claude
andauthored
fix: prevent undefined provider in chat requests on fresh install (#442)
* fix: fallback to default BrowserOS provider when provider is null When the extension first loads, provider config is loaded async from storage. If a chat request fires before loading completes (race condition), provider is null and the server receives provider: undefined, causing a Zod validation error. This adds a fallback to createDefaultBrowserOSProvider() in both chat paths (sidepanel and scheduled tasks) so provider.type is always defined. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: fallback to first provider when default provider ID is stale When defaultProviderId in storage doesn't match any loaded provider (e.g. after Kimi/Moonshot rollout), selectedProvider was null causing provider: undefined in chat requests. Now falls back to providers[0]. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: repair stale defaultProviderId in storage on load When the stored default provider ID doesn't match any loaded provider, write back the corrected ID (providers[0].id) to storage so it doesn't silently persist across sessions. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 5b1b4e2 commit 4bee762

3 files changed

Lines changed: 18 additions & 3 deletions

File tree

packages/browseros-agent/apps/agent/entrypoints/sidepanel/index/useChatSession.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
import { formatConversationHistory } from '@/lib/conversations/formatConversationHistory'
2424
import { declinedAppsStorage } from '@/lib/declined-apps/storage'
2525
import { useGraphqlQuery } from '@/lib/graphql/useGraphqlQuery'
26+
import { createDefaultBrowserOSProvider } from '@/lib/llm-providers/storage'
2627
import { useLlmProviders } from '@/lib/llm-providers/useLlmProviders'
2728
import { track } from '@/lib/metrics/track'
2829
import { searchActionsStorage } from '@/lib/search-actions/searchActionsStorage'
@@ -208,7 +209,7 @@ export const useChatSession = (options?: ChatSessionOptions) => {
208209
})
209210
const activeTab = activeTabsList?.[0] ?? undefined
210211
const message = getLastMessageText(messages)
211-
const provider = selectedLlmProviderRef.current
212+
const provider = selectedLlmProviderRef.current ?? createDefaultBrowserOSProvider()
212213
const currentMode = modeRef.current
213214
const enabledMcpServers = enabledMcpServersRef.current
214215
const customMcpServers = enabledCustomServersRef.current

packages/browseros-agent/apps/agent/lib/llm-providers/useLlmProviders.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,15 @@ export function useLlmProviders(): UseLlmProvidersReturn {
6060
await defaultProviderIdStorage.setValue(loadedDefaultId)
6161
}
6262

63+
// Repair stale default ID that doesn't match any provider
64+
const defaultExists = loadedProviders.some(
65+
(p) => p.id === loadedDefaultId,
66+
)
67+
if (!defaultExists && loadedProviders.length > 0) {
68+
loadedDefaultId = loadedProviders[0].id
69+
await defaultProviderIdStorage.setValue(loadedDefaultId)
70+
}
71+
6372
setProviders(loadedProviders)
6473
setDefaultProviderId(loadedDefaultId)
6574
} catch {
@@ -146,8 +155,12 @@ export function useLlmProviders(): UseLlmProvidersReturn {
146155
await providersStorage.setValue(updatedProviders)
147156
}
148157

158+
// Fall back to first provider if defaultProviderId is stale/invalid
149159
const selectedProvider = useMemo(
150-
() => providers.find((p) => p.id === defaultProviderId) ?? null,
160+
() =>
161+
providers.find((p) => p.id === defaultProviderId) ??
162+
providers[0] ??
163+
null,
151164
[providers, defaultProviderId],
152165
)
153166

packages/browseros-agent/apps/agent/lib/schedules/getChatServerResponse.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { createParser, type EventSourceMessage } from 'eventsource-parser'
22
import type { ChatMode } from '@/entrypoints/sidepanel/index/chatTypes'
33
import { getAgentServerUrl } from '@/lib/browseros/helpers'
44
import {
5+
createDefaultBrowserOSProvider,
56
defaultProviderIdStorage,
67
providersStorage,
78
} from '@/lib/llm-providers/storage'
@@ -78,7 +79,7 @@ export async function getChatServerResponse(
7879
request: ChatServerRequest,
7980
): Promise<ChatServerResponse> {
8081
const agentServerUrl = await getAgentServerUrl()
81-
const provider = await getDefaultProvider()
82+
const provider = (await getDefaultProvider()) ?? createDefaultBrowserOSProvider()
8283
const conversationId = request.conversationId ?? crypto.randomUUID()
8384
const personalization = await personalizationStorage.getValue()
8485

0 commit comments

Comments
 (0)