mirror of
https://github.com/NanmiCoder/cc-haha
synced 2026-07-17 13:13:35 +08:00
fix(desktop): default new sessions to provider main model (#818)
Tested: bun run check:desktop Confidence: high Scope-risk: narrow
This commit is contained in:
parent
0a7db60394
commit
65e662450c
@ -97,11 +97,12 @@ describe('ModelSelector', () => {
|
||||
|
||||
render(<ModelSelector runtimeKey="session-oauth-on-open" />)
|
||||
|
||||
await clickByRole(/alpha/i)
|
||||
await clickByRole(/provider-main/i)
|
||||
await act(async () => {
|
||||
fireEvent.keyDown(document, { key: 'Escape' })
|
||||
await Promise.resolve()
|
||||
})
|
||||
await clickByRole(/alpha/i)
|
||||
await clickByRole(/provider-main/i)
|
||||
|
||||
expect(fetchClaudeStatus).toHaveBeenCalledTimes(1)
|
||||
expect(fetchOpenAIStatus).toHaveBeenCalledTimes(1)
|
||||
@ -192,7 +193,7 @@ describe('ModelSelector', () => {
|
||||
|
||||
render(<ModelSelector runtimeKey="session-1" />)
|
||||
|
||||
await clickByRole(/alpha/i)
|
||||
await clickByRole(/provider-main/i)
|
||||
await act(async () => {
|
||||
fireEvent.click(screen.getByRole('button', { name: /provider-fast/ }))
|
||||
await Promise.resolve()
|
||||
@ -210,6 +211,51 @@ describe('ModelSelector', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('defaults blank provider-scoped runtime selections to the active provider main model', async () => {
|
||||
useSettingsStore.setState({
|
||||
locale: 'en',
|
||||
availableModels: [
|
||||
{ id: 'deepseek-v4-flash', name: 'deepseek-v4-flash', description: 'Main Model · Haiku Model', context: '' },
|
||||
{ id: 'deepseek-v4-pro', name: 'deepseek-v4-pro', description: 'Sonnet Model · Opus Model', context: '' },
|
||||
],
|
||||
currentModel: { id: 'deepseek-v4-pro', name: 'deepseek-v4-pro', description: 'Sonnet Model · Opus Model', context: '' },
|
||||
activeProviderName: 'Custom-DeepSeek-OpenAI',
|
||||
})
|
||||
useProviderStore.setState({
|
||||
providers: [{
|
||||
id: 'deepseek-provider',
|
||||
presetId: 'custom',
|
||||
name: 'Custom-DeepSeek-OpenAI',
|
||||
apiKey: '***',
|
||||
baseUrl: 'https://api.deepseek.com',
|
||||
apiFormat: 'openai_chat',
|
||||
models: {
|
||||
main: 'deepseek-v4-flash',
|
||||
haiku: 'deepseek-v4-flash',
|
||||
sonnet: 'deepseek-v4-pro',
|
||||
opus: 'deepseek-v4-pro',
|
||||
},
|
||||
}],
|
||||
activeId: 'deepseek-provider',
|
||||
hasLoadedProviders: true,
|
||||
isLoading: true,
|
||||
})
|
||||
|
||||
render(<ModelSelector runtimeKey="blank-session" />)
|
||||
|
||||
const trigger = screen.getByRole('button', { name: /deepseek-v4-flash/i })
|
||||
await act(async () => {
|
||||
fireEvent.click(trigger)
|
||||
await Promise.resolve()
|
||||
})
|
||||
|
||||
const flashOption = screen
|
||||
.getAllByRole('button', { name: /deepseek-v4-flash/i })
|
||||
.find((button) => button.textContent?.includes('Main Model'))
|
||||
expect(flashOption).toBeDefined()
|
||||
expect(flashOption?.className).toContain('border-[var(--color-model-option-selected-border)]')
|
||||
})
|
||||
|
||||
it('keeps runtime effort scoped to the selected session', async () => {
|
||||
const setSessionRuntime = vi.fn()
|
||||
useSettingsStore.setState({
|
||||
@ -249,12 +295,12 @@ describe('ModelSelector', () => {
|
||||
|
||||
render(<ModelSelector runtimeKey="session-1" />)
|
||||
|
||||
await clickByRole(/alpha/i)
|
||||
await clickByRole(/provider-main/i)
|
||||
await clickByRole(/^High$/)
|
||||
|
||||
expect(useSessionRuntimeStore.getState().selections['session-1']).toEqual({
|
||||
providerId: 'provider-a',
|
||||
modelId: 'alpha',
|
||||
modelId: 'provider-main',
|
||||
effortLevel: 'high',
|
||||
})
|
||||
expect(useSessionRuntimeStore.getState().selections['session-2']).toEqual({
|
||||
@ -264,7 +310,7 @@ describe('ModelSelector', () => {
|
||||
})
|
||||
expect(setSessionRuntime).toHaveBeenCalledWith('session-1', {
|
||||
providerId: 'provider-a',
|
||||
modelId: 'alpha',
|
||||
modelId: 'provider-main',
|
||||
effortLevel: 'high',
|
||||
})
|
||||
expect(useSettingsStore.getState().effortLevel).toBe('max')
|
||||
@ -357,7 +403,7 @@ describe('ModelSelector', () => {
|
||||
|
||||
render(<ModelSelector runtimeKey="session-hide" />)
|
||||
|
||||
await clickByRole(/alpha/i)
|
||||
await clickByRole(/provider-main/i)
|
||||
|
||||
const dropdown = screen.getByTestId('model-selector-dropdown')
|
||||
expect(dropdown.textContent).not.toContain('Claude Official')
|
||||
|
||||
@ -146,15 +146,17 @@ function resolveDefaultRuntimeSelection(
|
||||
providers: SavedProvider[],
|
||||
currentModelId: string | undefined,
|
||||
): RuntimeSelection {
|
||||
const inferredProviderId = activeId ?? (
|
||||
activeProviderName
|
||||
? providers.find((provider) => provider.name === activeProviderName)?.id ?? null
|
||||
: null
|
||||
)
|
||||
const activeProvider = activeId
|
||||
? providers.find((provider) => provider.id === activeId)
|
||||
: activeProviderName
|
||||
? providers.find((provider) => provider.name === activeProviderName)
|
||||
: undefined
|
||||
const inferredProviderId = activeId ?? activeProvider?.id ?? null
|
||||
const providerMainModelId = activeProvider?.models.main.trim()
|
||||
|
||||
return {
|
||||
providerId: inferredProviderId,
|
||||
modelId: currentModelId ?? (
|
||||
modelId: providerMainModelId || currentModelId || (
|
||||
inferredProviderId === OPENAI_OFFICIAL_PROVIDER_ID
|
||||
? OPENAI_OFFICIAL_DEFAULT_MODEL_ID
|
||||
: OFFICIAL_DEFAULT_MODEL_ID
|
||||
|
||||
@ -115,6 +115,7 @@ describe('providerStore runtime refresh', () => {
|
||||
providerId: provider.id,
|
||||
modelId: 'model-main',
|
||||
})
|
||||
expect(settingsSetModelMock).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('keeps an explicit provider model selection when the model still exists', async () => {
|
||||
@ -181,6 +182,21 @@ describe('providerStore runtime refresh', () => {
|
||||
expect(settingsSetModelMock).toHaveBeenCalledWith('model-main')
|
||||
expect(settingsFetchAllMock).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('sets the provider main model when updating the active saved provider', async () => {
|
||||
const provider = makeProvider({ models: { main: 'model-flash', haiku: 'model-flash', sonnet: 'model-pro', opus: 'model-pro' } })
|
||||
providersApiMock.update.mockResolvedValue({ provider })
|
||||
providersApiMock.list.mockResolvedValue({
|
||||
providers: [provider],
|
||||
activeId: provider.id,
|
||||
})
|
||||
|
||||
const { useProviderStore } = await import('./providerStore')
|
||||
await useProviderStore.getState().updateProvider(provider.id, { models: provider.models })
|
||||
|
||||
expect(settingsSetModelMock).toHaveBeenCalledWith('model-flash')
|
||||
expect(settingsFetchAllMock).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
describe('providerStore reorderProviders', () => {
|
||||
|
||||
@ -203,7 +203,16 @@ export const useProviderStore = create<ProviderStore>((set, get) => ({
|
||||
updateProvider: async (id, input) => {
|
||||
const { provider } = await providersApi.update(id, input)
|
||||
await get().fetchProviders()
|
||||
refreshConnectedSessionsForProvider(provider, get().activeId)
|
||||
const activeId = get().activeId
|
||||
if (activeId === provider.id && input.models !== undefined) {
|
||||
const mainModelId = provider.models.main.trim()
|
||||
if (mainModelId) {
|
||||
const settings = useSettingsStore.getState()
|
||||
await settings.setModel(mainModelId)
|
||||
await settings.fetchAll()
|
||||
}
|
||||
}
|
||||
refreshConnectedSessionsForProvider(provider, activeId)
|
||||
return provider
|
||||
},
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user