mirror of
https://github.com/deepseek-ai/deepseek-harness.git
synced 2026-08-29 04:26:38 +00:00
fix(ui-settings-plugins): align Subagent configuration card
This commit is contained in:
@@ -25,8 +25,8 @@
|
||||
- tabpanel "插件配置":
|
||||
- list:
|
||||
- listitem:
|
||||
- 'button "展开设置: Subagent 自选模型"':
|
||||
- text: Subagent 自选模型 选择新会话允许为 subagent 自选的模型。运行中的会话不会改变。
|
||||
- 'button "展开设置: Subagent"':
|
||||
- text: Subagent 控制 Agent 为 Subagent 选择模型的权限。
|
||||
- img
|
||||
- listitem:
|
||||
- 'button "展开设置: 终端"':
|
||||
|
||||
@@ -77,8 +77,8 @@ describe('web e2e: plugin configuration section', () => {
|
||||
|
||||
// Every card the shipped web composition exposes: subagent selection, the
|
||||
// shell executor, the agent loop, and the DeepSeek search provider.
|
||||
await dialog.getByText('Subagent 自选模型', { exact: true }).waitFor({ timeout: 10_000 })
|
||||
expect(await dialog.getByRole('button', { name: '展开设置: Subagent 自选模型' }).count()).toBe(1)
|
||||
await dialog.getByText('Subagent', { exact: true }).waitFor({ timeout: 10_000 })
|
||||
expect(await dialog.getByRole('button', { name: '展开设置: Subagent' }).count()).toBe(1)
|
||||
await dialog.getByText('终端', { exact: true }).waitFor({ timeout: 10_000 })
|
||||
expect(await dialog.getByText('Agent 循环', { exact: true }).count()).toBe(1)
|
||||
expect(await dialog.getByText('网页搜索', { exact: true }).count()).toBe(1)
|
||||
@@ -93,11 +93,11 @@ describe('web e2e: plugin configuration section', () => {
|
||||
it('persists selected adapter routes as the subagent model allowlist', async () => {
|
||||
onTestFailed(() => saveFailureShot(page, 'web-e2e-plugin-config-subagent-model-selection'))
|
||||
const dialog = await openPlugins()
|
||||
await dialog.getByText('Subagent 自选模型', { exact: true }).click()
|
||||
const toggle = dialog.getByRole('switch', { name: '允许 subagent 自选模型' })
|
||||
await dialog.getByText('Subagent', { exact: true }).click()
|
||||
const toggle = dialog.getByRole('switch', { name: '允许 Agent 为 Subagent 选择模型' })
|
||||
|
||||
await toggle.click()
|
||||
const models = dialog.getByRole('group', { name: '允许的模型' })
|
||||
const models = dialog.getByRole('group', { name: 'Agent 可选择的模型' })
|
||||
await models.waitFor({ timeout: 10_000 })
|
||||
const firstModel = models.getByRole('checkbox').first()
|
||||
await firstModel.check()
|
||||
@@ -110,7 +110,8 @@ describe('web e2e: plugin configuration section', () => {
|
||||
expect(await settingsDocument()).toContain('allowedModels:')
|
||||
expect(await settingsDocument()).toContain('provider:')
|
||||
expect(await settingsDocument()).toContain('model:')
|
||||
expect(await dialog.getByRole('status').textContent()).toBe('已保存,新会话将使用此设置。')
|
||||
await expect.poll(() => dialog.getByRole('button', { name: '保存', exact: true }).isDisabled()).toBe(true)
|
||||
expect(await dialog.getByText('未保存', { exact: true }).count()).toBe(0)
|
||||
|
||||
await toggle.click()
|
||||
await dialog.getByRole('button', { name: '保存', exact: true }).click()
|
||||
|
||||
+19
-6
@@ -54,8 +54,7 @@
|
||||
|
||||
.hint,
|
||||
.notice,
|
||||
.invalid,
|
||||
.status {
|
||||
.invalid {
|
||||
margin: 0;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
@@ -70,10 +69,6 @@
|
||||
color: var(--dsw-alias-label-error);
|
||||
}
|
||||
|
||||
.status {
|
||||
color: var(--dsw-alias-state-success-primary);
|
||||
}
|
||||
|
||||
.catalogError {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -109,6 +104,24 @@
|
||||
color: var(--dsw-alias-label-secondary);
|
||||
}
|
||||
|
||||
.modelGroup {
|
||||
display: grid;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.modelGroup + .modelGroup {
|
||||
margin-top: 4px;
|
||||
padding-top: 10px;
|
||||
border-top: 1px solid var(--dsw-alias-border-l3);
|
||||
}
|
||||
|
||||
.providerName {
|
||||
padding: 0 6px;
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
color: var(--dsw-alias-label-tertiary);
|
||||
}
|
||||
|
||||
.model {
|
||||
display: grid;
|
||||
grid-template-columns: auto minmax(0, 1fr) auto;
|
||||
|
||||
@@ -2,7 +2,10 @@
|
||||
|
||||
import clsx from 'clsx'
|
||||
import type { InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots'
|
||||
import type { SubagentModelSelectionCardFace } from './subagent-model-selection-card-controller.ts'
|
||||
import type {
|
||||
SubagentModelCandidate,
|
||||
SubagentModelSelectionCardFace,
|
||||
} from './subagent-model-selection-card-controller.ts'
|
||||
import type {} from './slot-contract.ts'
|
||||
import { PluginCard } from './PluginCard.tsx'
|
||||
import css from './SubagentModelSelectionCard.module.css'
|
||||
@@ -21,6 +24,43 @@ export type SubagentModelSelectionCardProps =
|
||||
export function SubagentModelSelectionCard(props: SubagentModelSelectionCardProps) {
|
||||
const { t } = props
|
||||
const state = props.useSubagentModelSelectionCard(snapshot => snapshot)
|
||||
const availableGroups = new Map<string, {
|
||||
providerName: string
|
||||
candidates: SubagentModelCandidate[]
|
||||
}>()
|
||||
const unavailable: SubagentModelCandidate[] = []
|
||||
for (const candidate of state.candidates) {
|
||||
if (!candidate.available) {
|
||||
unavailable.push(candidate)
|
||||
continue
|
||||
}
|
||||
const group = availableGroups.get(candidate.provider)
|
||||
if (group === undefined) {
|
||||
availableGroups.set(candidate.provider, {
|
||||
providerName: candidate.providerName,
|
||||
candidates: [candidate],
|
||||
})
|
||||
} else {
|
||||
group.candidates.push(candidate)
|
||||
}
|
||||
}
|
||||
const renderCandidate = (candidate: SubagentModelCandidate) => (
|
||||
<label key={candidate.key} className={css.model}>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={candidate.selected}
|
||||
disabled={!state.writable || state.saving}
|
||||
onChange={() => { props.toggleModel(candidate.key) }}
|
||||
/>
|
||||
<span>
|
||||
<span className={css.modelName}>{candidate.modelName}</span>
|
||||
<span className={css.route}>{`${candidate.providerName} · ${candidate.provider}/${candidate.model}`}</span>
|
||||
</span>
|
||||
{!candidate.available
|
||||
? <span className={css.unavailable}>{t('subagentModelSelectionUnavailable')}</span>
|
||||
: null}
|
||||
</label>
|
||||
)
|
||||
return (
|
||||
<PluginCard
|
||||
t={t}
|
||||
@@ -61,30 +101,27 @@ export function SubagentModelSelectionCard(props: SubagentModelSelectionCardProp
|
||||
</div>
|
||||
)
|
||||
: null}
|
||||
{state.catalogFailures.length > 0
|
||||
{state.catalogPartial
|
||||
? <p className={css.notice}>{t('subagentModelSelectionPartial')}</p>
|
||||
: null}
|
||||
{state.candidates.length > 0
|
||||
? (
|
||||
<fieldset className={css.models}>
|
||||
<legend>{t('subagentModelSelectionAllowed')}</legend>
|
||||
{state.candidates.map(candidate => (
|
||||
<label key={candidate.key} className={css.model}>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={candidate.selected}
|
||||
disabled={!state.writable || state.saving}
|
||||
onChange={() => { props.toggleModel(candidate.key) }}
|
||||
/>
|
||||
<span>
|
||||
<span className={css.modelName}>{candidate.modelName}</span>
|
||||
<span className={css.route}>{`${candidate.providerName} · ${candidate.provider}/${candidate.model}`}</span>
|
||||
</span>
|
||||
{!candidate.available
|
||||
? <span className={css.unavailable}>{t('subagentModelSelectionUnavailable')}</span>
|
||||
: null}
|
||||
</label>
|
||||
{[...availableGroups].map(([provider, group]) => (
|
||||
<div key={provider} className={css.modelGroup}>
|
||||
<div className={css.providerName}>{group.providerName}</div>
|
||||
{group.candidates.map(renderCandidate)}
|
||||
</div>
|
||||
))}
|
||||
{unavailable.length > 0
|
||||
? (
|
||||
<div className={css.modelGroup}>
|
||||
<div className={css.providerName}>{t('subagentModelSelectionUnavailableGroup')}</div>
|
||||
{unavailable.map(renderCandidate)}
|
||||
</div>
|
||||
)
|
||||
: null}
|
||||
</fieldset>
|
||||
)
|
||||
: state.catalogStatus === 'ready'
|
||||
@@ -94,7 +131,6 @@ export function SubagentModelSelectionCard(props: SubagentModelSelectionCardProp
|
||||
</div>
|
||||
)
|
||||
: <p className={css.hint}>{t('subagentModelSelectionOff')}</p>}
|
||||
{state.saved ? <p className={css.status} role="status">{t('subagentModelSelectionSaved')}</p> : null}
|
||||
</PluginCard>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -14,8 +14,9 @@ export type PluginsSettingsLocaleKey =
|
||||
| 'subagentModelSelectionTitle' | 'subagentModelSelectionDescription'
|
||||
| 'subagentModelSelectionToggle' | 'subagentModelSelectionChoose' | 'subagentModelSelectionAllowed'
|
||||
| 'subagentModelSelectionLoading' | 'subagentModelSelectionLoadFailed' | 'subagentModelSelectionRetry'
|
||||
| 'subagentModelSelectionPartial' | 'subagentModelSelectionUnavailable' | 'subagentModelSelectionEmpty'
|
||||
| 'subagentModelSelectionRequired' | 'subagentModelSelectionOff' | 'subagentModelSelectionSaved'
|
||||
| 'subagentModelSelectionPartial' | 'subagentModelSelectionUnavailable'
|
||||
| 'subagentModelSelectionUnavailableGroup' | 'subagentModelSelectionEmpty'
|
||||
| 'subagentModelSelectionRequired' | 'subagentModelSelectionOff'
|
||||
|
||||
/** English copy. */
|
||||
export const en: Record<PluginsSettingsLocaleKey, string> = {
|
||||
@@ -56,20 +57,20 @@ export const en: Record<PluginsSettingsLocaleKey, string> = {
|
||||
webSearchBaseUrlHint: 'Leave blank to use the provider default.',
|
||||
webSearchMaxUses: 'Max searches per request',
|
||||
webSearchMaxUsesHint: 'How many times one request may search before it must answer.',
|
||||
subagentModelSelectionTitle: 'Subagent model selection',
|
||||
subagentModelSelectionDescription: 'Choose which child models new sessions may select. Running sessions do not change.',
|
||||
subagentModelSelectionToggle: 'Allow subagents to choose models',
|
||||
subagentModelSelectionChoose: 'Select at least one model. Only these adapter routes appear in subagent discovery.',
|
||||
subagentModelSelectionAllowed: 'Allowed models',
|
||||
subagentModelSelectionLoading: 'Loading adapter models…',
|
||||
subagentModelSelectionLoadFailed: 'Adapter models could not be loaded.',
|
||||
subagentModelSelectionTitle: 'Subagent',
|
||||
subagentModelSelectionDescription: 'Control which models agents may choose for subagents.',
|
||||
subagentModelSelectionToggle: 'Allow agents to choose models for subagents',
|
||||
subagentModelSelectionChoose: 'When enabled, agents can choose a provider, model, and reasoning effort for each subagent from the authorized models below. Applies only to new sessions.',
|
||||
subagentModelSelectionAllowed: 'Models agents may choose',
|
||||
subagentModelSelectionLoading: 'Loading models…',
|
||||
subagentModelSelectionLoadFailed: 'Models could not be loaded.',
|
||||
subagentModelSelectionRetry: 'Retry',
|
||||
subagentModelSelectionPartial: 'Some providers could not list their models; stored choices remain removable.',
|
||||
subagentModelSelectionUnavailable: 'Unavailable',
|
||||
subagentModelSelectionEmpty: 'No adapter currently advertises a model.',
|
||||
subagentModelSelectionPartial: 'Some model providers could not be loaded; saved choices remain removable.',
|
||||
subagentModelSelectionUnavailable: 'Currently unavailable',
|
||||
subagentModelSelectionUnavailableGroup: 'Saved but currently unavailable',
|
||||
subagentModelSelectionEmpty: 'No model provider currently advertises a model.',
|
||||
subagentModelSelectionRequired: 'Select at least one model before saving.',
|
||||
subagentModelSelectionOff: 'New sessions inherit the configured or parent model without choosing another route.',
|
||||
subagentModelSelectionSaved: 'Saved. New sessions use this setting.',
|
||||
subagentModelSelectionOff: 'Subagents use configured defaults or inherit the parent agent\'s model. Saved model choices are retained.',
|
||||
}
|
||||
|
||||
/** Simplified Chinese copy. */
|
||||
@@ -111,18 +112,18 @@ export const zh: Record<PluginsSettingsLocaleKey, string> = {
|
||||
webSearchBaseUrlHint: '留空则使用提供方默认地址。',
|
||||
webSearchMaxUses: '单次请求最多搜索次数',
|
||||
webSearchMaxUsesHint: '一次请求在必须作答前最多可以搜索多少次。',
|
||||
subagentModelSelectionTitle: 'Subagent 自选模型',
|
||||
subagentModelSelectionDescription: '选择新会话允许为 subagent 自选的模型。运行中的会话不会改变。',
|
||||
subagentModelSelectionToggle: '允许 subagent 自选模型',
|
||||
subagentModelSelectionChoose: '请至少选择一个模型。Subagent 发现工具只会列出这些 adapter 路由。',
|
||||
subagentModelSelectionAllowed: '允许的模型',
|
||||
subagentModelSelectionLoading: '正在加载 adapter 模型…',
|
||||
subagentModelSelectionLoadFailed: '无法加载 adapter 模型。',
|
||||
subagentModelSelectionTitle: 'Subagent',
|
||||
subagentModelSelectionDescription: '控制 Agent 为 Subagent 选择模型的权限。',
|
||||
subagentModelSelectionToggle: '允许 Agent 为 Subagent 选择模型',
|
||||
subagentModelSelectionChoose: '开启后,Agent 可以从下方授权模型中,为每个 Subagent 选择提供方、模型和推理强度。仅影响新会话。',
|
||||
subagentModelSelectionAllowed: 'Agent 可选择的模型',
|
||||
subagentModelSelectionLoading: '正在加载模型…',
|
||||
subagentModelSelectionLoadFailed: '无法加载模型。',
|
||||
subagentModelSelectionRetry: '重试',
|
||||
subagentModelSelectionPartial: '部分提供方无法列出模型;仍可移除已保存的选项。',
|
||||
subagentModelSelectionUnavailable: '不可用',
|
||||
subagentModelSelectionEmpty: '当前没有 adapter 公布模型。',
|
||||
subagentModelSelectionPartial: '部分模型提供方暂时无法加载;已保存的选择仍可移除。',
|
||||
subagentModelSelectionUnavailable: '当前不可用',
|
||||
subagentModelSelectionUnavailableGroup: '已保存但当前不可用',
|
||||
subagentModelSelectionEmpty: '当前没有模型提供方公布模型。',
|
||||
subagentModelSelectionRequired: '保存前请至少选择一个模型。',
|
||||
subagentModelSelectionOff: '新会话会使用配置值或继承父 Agent 模型,不会自主选择其他路由。',
|
||||
subagentModelSelectionSaved: '已保存,新会话将使用此设置。',
|
||||
subagentModelSelectionOff: '关闭后,Subagent 使用配置的默认模型或继承父 Agent 的模型;已选模型会保留。',
|
||||
}
|
||||
|
||||
+7
-19
@@ -2,7 +2,6 @@
|
||||
|
||||
import type {
|
||||
IApiClient,
|
||||
ModelCatalogFailure,
|
||||
ModelProviderGroup,
|
||||
} from '@deepseek-ai/dsh-api-remotes/client'
|
||||
import { createSnapshotStore, type SnapshotStore } from '@deepseek-ai/dsh-client-store'
|
||||
@@ -48,10 +47,8 @@ export interface SubagentModelSelectionCardState extends CardShell {
|
||||
candidates: readonly SubagentModelCandidate[]
|
||||
/** Adapter-directory request state. */
|
||||
catalogStatus: 'idle' | 'loading' | 'ready' | 'error'
|
||||
/** Provider-local failures that did not block other candidates. */
|
||||
catalogFailures: readonly ModelCatalogFailure[]
|
||||
/** Whether the latest save landed. */
|
||||
saved: boolean
|
||||
/** Whether any provider-local catalog request failed. */
|
||||
catalogPartial: boolean
|
||||
}
|
||||
|
||||
/** Registration-side face for the subagent model-selection card. */
|
||||
@@ -130,13 +127,12 @@ function sameRoutes(left: readonly AllowedSubagentModel[], right: readonly Allow
|
||||
/** Bridges one settings scope and the live adapter directory onto a staged card. */
|
||||
export class SubagentModelSelectionCardController {
|
||||
private catalogGroups: readonly ModelProviderGroup[] = []
|
||||
private catalogFailures: readonly ModelCatalogFailure[] = []
|
||||
private catalogPartial = false
|
||||
private catalogStatus: SubagentModelSelectionCardState['catalogStatus'] = 'idle'
|
||||
private draftEnabled: boolean | undefined
|
||||
private draftSelected: Set<string> | undefined
|
||||
private draftRevision: number | undefined
|
||||
private saving = false
|
||||
private saved = false
|
||||
private failed = false
|
||||
private disposed = false
|
||||
private saveGeneration = 0
|
||||
@@ -156,7 +152,6 @@ export class SubagentModelSelectionCardController {
|
||||
this.unsubscribe = scope.subscribe(() => {
|
||||
if (!this.saving && this.draftSelected !== undefined
|
||||
&& this.scope.getSnapshot().revision !== this.draftRevision) {
|
||||
this.saved = false
|
||||
this.failed = true
|
||||
}
|
||||
if (this.enabled() && this.catalogStatus === 'idle') void this.loadCatalog()
|
||||
@@ -219,7 +214,6 @@ export class SubagentModelSelectionCardController {
|
||||
if (this.disposed || snapshot.status !== 'ready' || !snapshot.writable || this.saving) return
|
||||
this.beginDraft()
|
||||
this.draftEnabled = !this.draftEnabled
|
||||
this.saved = false
|
||||
this.failed = false
|
||||
if (this.draftEnabled && this.catalogStatus === 'idle') void this.loadCatalog()
|
||||
this.publish()
|
||||
@@ -231,7 +225,6 @@ export class SubagentModelSelectionCardController {
|
||||
const selected = this.beginDraft()
|
||||
if (selected.has(key)) selected.delete(key)
|
||||
else selected.add(key)
|
||||
this.saved = false
|
||||
this.failed = false
|
||||
this.publish()
|
||||
}
|
||||
@@ -241,7 +234,6 @@ export class SubagentModelSelectionCardController {
|
||||
this.draftEnabled = undefined
|
||||
this.draftSelected = undefined
|
||||
this.draftRevision = undefined
|
||||
this.saved = false
|
||||
this.failed = false
|
||||
this.publish()
|
||||
}
|
||||
@@ -264,14 +256,12 @@ export class SubagentModelSelectionCardController {
|
||||
|| (this.currentEnabled() === desiredEnabled && sameRoutes(this.currentRoutes(), desired))
|
||||
|| (desiredEnabled && desired.length === 0)) return
|
||||
if (this.draftSelected !== undefined && snapshot.revision !== this.draftRevision) {
|
||||
this.saved = false
|
||||
this.failed = true
|
||||
this.publish()
|
||||
return
|
||||
}
|
||||
const generation = this.saveGeneration
|
||||
this.saving = true
|
||||
this.saved = false
|
||||
this.failed = false
|
||||
this.publish()
|
||||
await this.scope.mutate([
|
||||
@@ -281,7 +271,6 @@ export class SubagentModelSelectionCardController {
|
||||
if (generation !== this.saveGeneration) return
|
||||
const landed = this.currentEnabled() === desiredEnabled && sameRoutes(this.currentRoutes(), desired)
|
||||
this.saving = false
|
||||
this.saved = landed
|
||||
this.failed = !landed
|
||||
if (landed) {
|
||||
this.draftEnabled = undefined
|
||||
@@ -296,7 +285,7 @@ export class SubagentModelSelectionCardController {
|
||||
if (this.disposed) return
|
||||
this.catalogGeneration += 1
|
||||
this.catalogStatus = 'idle'
|
||||
this.catalogFailures = []
|
||||
this.catalogPartial = false
|
||||
if (this.enabled()) void this.loadCatalog()
|
||||
else this.publish()
|
||||
}
|
||||
@@ -313,14 +302,14 @@ export class SubagentModelSelectionCardController {
|
||||
const generation = this.catalogGeneration
|
||||
this.catalogStatus = 'loading'
|
||||
this.catalogGroups = []
|
||||
this.catalogFailures = []
|
||||
this.catalogPartial = false
|
||||
this.publish()
|
||||
try {
|
||||
const response = await this.api.llm.models({})
|
||||
if (generation !== this.catalogGeneration) return
|
||||
if (!response.result.ok) throw new Error(response.result.error.message)
|
||||
this.catalogGroups = response.result.value.groups
|
||||
this.catalogFailures = response.result.value.failures
|
||||
this.catalogPartial = response.result.value.failures.length > 0
|
||||
this.catalogStatus = 'ready'
|
||||
} catch {
|
||||
if (generation !== this.catalogGeneration) return
|
||||
@@ -344,8 +333,7 @@ export class SubagentModelSelectionCardController {
|
||||
enabled,
|
||||
candidates: this.candidates(),
|
||||
catalogStatus: this.catalogStatus,
|
||||
catalogFailures: this.catalogFailures,
|
||||
saved: this.saved,
|
||||
catalogPartial: this.catalogPartial,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -88,8 +88,7 @@ function renderSubagentModelSelection(state: Partial<SubagentModelSelectionCardS
|
||||
enabled: false,
|
||||
candidates: [],
|
||||
catalogStatus: 'idle',
|
||||
catalogFailures: [],
|
||||
saved: false,
|
||||
catalogPartial: false,
|
||||
...state,
|
||||
})
|
||||
const actions = {
|
||||
@@ -335,10 +334,9 @@ describe('SubagentModelSelectionCard', () => {
|
||||
expect(actions.toggleEnabled).toHaveBeenCalledOnce()
|
||||
})
|
||||
|
||||
it('renders adapter candidates and reports a successful save', () => {
|
||||
it('groups available adapter candidates by provider', () => {
|
||||
const actions = renderSubagentModelSelection({
|
||||
enabled: true,
|
||||
saved: true,
|
||||
candidates: [{
|
||||
key: 'alpha\0fast',
|
||||
provider: 'alpha',
|
||||
@@ -353,7 +351,7 @@ describe('SubagentModelSelectionCard', () => {
|
||||
fireEvent.click(screen.getByText(en.subagentModelSelectionTitle))
|
||||
|
||||
expect(screen.getByRole('switch').getAttribute('aria-checked')).toBe('true')
|
||||
expect(screen.getByRole('status').textContent).toBe(en.subagentModelSelectionSaved)
|
||||
expect(screen.getByText('Alpha API', { exact: true })).toBeTruthy()
|
||||
fireEvent.click(screen.getByRole('checkbox', { name: /Fast/ }))
|
||||
expect(actions.toggleModel).toHaveBeenCalledWith('alpha\0fast')
|
||||
})
|
||||
@@ -374,7 +372,7 @@ describe('SubagentModelSelectionCard', () => {
|
||||
renderSubagentModelSelection({
|
||||
enabled: true,
|
||||
catalogStatus: 'ready',
|
||||
catalogFailures: [{ id: 'beta', name: 'Beta', message: 'offline' }],
|
||||
catalogPartial: true,
|
||||
candidates: [{
|
||||
key: 'legacy\0old',
|
||||
provider: 'legacy',
|
||||
@@ -388,6 +386,7 @@ describe('SubagentModelSelectionCard', () => {
|
||||
fireEvent.click(screen.getByText(en.subagentModelSelectionTitle))
|
||||
expect(screen.getByText(en.subagentModelSelectionPartial)).toBeTruthy()
|
||||
expect(screen.getByText(en.subagentModelSelectionUnavailable)).toBeTruthy()
|
||||
expect(screen.getByText(en.subagentModelSelectionUnavailableGroup)).toBeTruthy()
|
||||
|
||||
cleanup()
|
||||
renderSubagentModelSelection({ enabled: true, catalogStatus: 'ready' })
|
||||
|
||||
@@ -480,7 +480,6 @@ describe('SubagentModelSelectionCardController', () => {
|
||||
enabled: true,
|
||||
dirty: false,
|
||||
saving: false,
|
||||
saved: true,
|
||||
failed: false,
|
||||
})
|
||||
})
|
||||
@@ -521,7 +520,6 @@ describe('SubagentModelSelectionCardController', () => {
|
||||
enabled: true,
|
||||
dirty: true,
|
||||
saving: false,
|
||||
saved: false,
|
||||
})
|
||||
})
|
||||
|
||||
@@ -539,6 +537,7 @@ describe('SubagentModelSelectionCardController', () => {
|
||||
const face = controller.inject()
|
||||
const state = () => face.hooks.subagentModelSelectionCard.getSnapshot()
|
||||
await vi.waitFor(() => { expect(state().catalogStatus).toBe('ready') })
|
||||
expect(state().catalogPartial).toBe(true)
|
||||
|
||||
face.toggleModel('missing')
|
||||
expect(state().dirty).toBe(false)
|
||||
@@ -576,7 +575,7 @@ describe('SubagentModelSelectionCardController', () => {
|
||||
], 5)
|
||||
})
|
||||
expect(face.hooks.subagentModelSelectionCard.getSnapshot()).toMatchObject({
|
||||
enabled: false, dirty: false, saved: true,
|
||||
enabled: false, dirty: false,
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user