fix: describe saved fixed project models accurately
Projects with a saved fixed Runtime model could incorrectly claim to follow the global Runtime configuration. Restore the fixed-model description while keeping the simplified menu and the ability to return to inherited settings. Model resolution, permissions, and remote Agent behavior are unchanged. Validation: 3911 tests passed, 66 skipped; typecheck, lint, and release-note validation passed. Added bilingual regressions for all three Agent Runtimes. Release note: 项目已固定 Runtime 模型时,现在明确显示所用固定模型,不再误报为跟随全局设置。
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
import { cleanup, fireEvent, render, screen } from '@testing-library/react'
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
import { defaultRuntimeSettings, type RuntimeSettings } from '../../shared/contracts'
|
||||
import { ProjectRuntimeSelector } from './ProjectRuntimeSelector'
|
||||
import i18n from './i18n'
|
||||
|
||||
afterEach(cleanup)
|
||||
|
||||
describe('ProjectRuntimeSelector saved model references', () => {
|
||||
it.each(['zh-CN', 'en-US'])('describes fixed selections accurately in %s without restoring duplicate menus', async (language) => {
|
||||
await i18n.changeLanguage(language)
|
||||
const profileId = '00000000-0000-4000-8000-000000000011'
|
||||
const settings = {
|
||||
...defaultRuntimeSettings,
|
||||
defaultModelProfileId: profileId,
|
||||
modelProfiles: [{
|
||||
id: profileId, name: 'Model A', modelName: 'model-a',
|
||||
baseUrl: 'https://example.com/v1', protocol: 'openai-chat-completions',
|
||||
authentication: 'api-key', apiKeyConfigured: true
|
||||
}]
|
||||
} as RuntimeSettings
|
||||
const onChange = vi.fn()
|
||||
for (const provider of ['opencode', 'continue', 'deepseek-harness'] as const) {
|
||||
const runtime = provider === 'opencode' ? 'OpenCode'
|
||||
: provider === 'continue' ? 'Continue' : 'DeepSeek Harness'
|
||||
const props = {
|
||||
ariaLabel: 'Project Runtime', label: 'Runtime', onChange,
|
||||
runtimeSettings: settings
|
||||
}
|
||||
const view = render(<ProjectRuntimeSelector {...props} selection={{ provider, profileId }} />)
|
||||
const select = screen.getByRole('combobox')
|
||||
expect(select).toHaveValue(`${provider}:${profileId}`)
|
||||
expect(screen.getByText(language === 'zh-CN'
|
||||
? `通过 ${runtime} 运行,固定使用 Model A。`
|
||||
: `Run through ${runtime} with the fixed model Model A.`)).toBeInTheDocument()
|
||||
expect(screen.getAllByRole('option').filter((option) =>
|
||||
(option as HTMLOptionElement).value.endsWith(`:${profileId}`))).toHaveLength(2)
|
||||
|
||||
fireEvent.change(select, { target: { value: `${provider}:default` } })
|
||||
expect(onChange).toHaveBeenLastCalledWith({ provider })
|
||||
view.rerender(<ProjectRuntimeSelector {...props} selection={{ provider }} />)
|
||||
expect(select).toHaveValue(`${provider}:default`)
|
||||
expect(screen.queryByText(language === 'zh-CN'
|
||||
? `通过 ${runtime} 运行,固定使用 Model A。`
|
||||
: `Run through ${runtime} with the fixed model Model A.`)).not.toBeInTheDocument()
|
||||
expect(screen.getAllByRole('option').filter((option) =>
|
||||
(option as HTMLOptionElement).value.endsWith(`:${profileId}`))).toHaveLength(1)
|
||||
view.unmount()
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -54,6 +54,15 @@ function runtimeSelectionDescription(
|
||||
: selection.provider === 'continue'
|
||||
? 'Continue'
|
||||
: 'DeepSeek Harness'
|
||||
if (selection.profileId) {
|
||||
const profile = settings.modelProfiles.find(
|
||||
(candidate) => candidate.id === selection.profileId
|
||||
)
|
||||
return t('channels.project.fixedRuntimeDescription', {
|
||||
runtime: runtimeLabel,
|
||||
name: profile?.name ?? t('channels.project.missingProfile')
|
||||
})
|
||||
}
|
||||
return t('channels.project.runtimeDescription', {
|
||||
runtime: runtimeLabel
|
||||
})
|
||||
|
||||
@@ -46,6 +46,7 @@ export const integrations = {
|
||||
directDescription:
|
||||
'Process messages directly with {{name}} ({{modelName}}).',
|
||||
defaultDirect: 'Direct · Follow the global default model',
|
||||
fixedRuntimeDescription: 'Run through {{runtime}} with the fixed model {{name}}.',
|
||||
automaticDescription:
|
||||
'Follow the global default Runtime setting.',
|
||||
runtimeDescription:
|
||||
|
||||
@@ -40,6 +40,7 @@ export const integrations = {
|
||||
'直接使用 {{name}}({{modelName}})处理消息。',
|
||||
automaticDescription: '跟随全局 Runtime 默认设置',
|
||||
defaultDirect: '直连 · 跟随全局默认模型',
|
||||
fixedRuntimeDescription: '通过 {{runtime}} 运行,固定使用 {{name}}。',
|
||||
runtimeDescription:
|
||||
'通过 {{runtime}} Agent Runtime 运行,并跟随“Agent Runtime”设置中的全局 {{runtime}} 配置。',
|
||||
defaultMode: '默认模式',
|
||||
|
||||
Reference in New Issue
Block a user