refactor(ui-agent-preset): one home for turning a roster into options

The chip and the settings row both spread the same three fields, and
`exactOptionalPropertyTypes` makes the absent-vs-undefined dance verbose
enough that the duplication gate flagged it.
This commit is contained in:
Yichen Jiang
2026-08-07 15:46:46 +08:00
parent 1fa9a1cf1d
commit 0f27a505c4
2 changed files with 24 additions and 13 deletions

View File

@@ -14,7 +14,7 @@ import type { IApiClient } from '@deepseek-ai/dsh-client-connection/client'
import {
createSnapshotStore, type SessionId, type SnapshotStore,
} from '@deepseek-ai/dsh-client-runtime/client'
import { messageOf } from './settings-store.ts'
import { messageOf, presetOptions } from './settings-store.ts'
import type { AgentPresetOption } from './settings-store.ts'
/** Hero-chip snapshot. */
@@ -80,12 +80,7 @@ export class AgentPresetSeatController {
const { presets } = response.result.value
this.fallback = presets.find(preset => preset.isDefault)?.id ?? presets[0]?.id ?? ''
this.set({
options: presets.map(preset => ({
id: preset.id,
trust: preset.trust,
...preset.name === undefined ? {} : { name: preset.name },
...preset.description === undefined ? {} : { description: preset.description },
})),
options: presetOptions(presets),
current: this.staged ?? this.fallback,
error: null,
})

View File

@@ -61,6 +61,27 @@ export interface AgentPresetOption {
description?: string
}
/**
* The roster entries as every surface renders them.
*
* The chip, the row, and the management section all show the same three
* facts, and `exactOptionalPropertyTypes` makes "absent" and "present as
* undefined" different shapes — so the spread dance belongs in one place
* rather than once per store.
* @param presets - the roster the host answered with.
* @returns one option per preset, in roster order.
*/
export function presetOptions(
presets: readonly { id: string, trust: 'system' | 'user', name?: string, description?: string }[],
): AgentPresetOption[] {
return presets.map(preset => ({
id: preset.id,
trust: preset.trust,
...preset.name === undefined ? {} : { name: preset.name },
...preset.description === undefined ? {} : { description: preset.description },
}))
}
/** Agent-preset settings-row snapshot. */
export interface AgentPresetSettingsState {
status: 'idle' | 'loading' | 'ready' | 'saving' | 'unavailable' | 'error'
@@ -127,12 +148,7 @@ export class AgentPresetSettingsController {
status: 'ready',
error: null,
writable: described.result.ok && described.result.value.writable,
options: presets.map(preset => ({
id: preset.id,
trust: preset.trust,
...preset.name === undefined ? {} : { name: preset.name },
...preset.description === undefined ? {} : { description: preset.description },
})),
options: presetOptions(presets),
// A roster can mark nothing default: settings can name a preset that
// was since deleted, and the picker still has to show something.
currentValue: presets.find(preset => preset.isDefault)?.id ?? first.id,