diff --git a/packages/client/ui-agent-preset/src/client/seat-store.ts b/packages/client/ui-agent-preset/src/client/seat-store.ts index b071d8efd4..335cd48e68 100644 --- a/packages/client/ui-agent-preset/src/client/seat-store.ts +++ b/packages/client/ui-agent-preset/src/client/seat-store.ts @@ -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, }) diff --git a/packages/client/ui-agent-preset/src/client/settings-store.ts b/packages/client/ui-agent-preset/src/client/settings-store.ts index e5f8125b7e..d14c8b89b3 100644 --- a/packages/client/ui-agent-preset/src/client/settings-store.ts +++ b/packages/client/ui-agent-preset/src/client/settings-store.ts @@ -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,