fix(web): persist the default agent preset, and give its page an identity

Three fixes to the settings surface.

The default never reached settings.yaml. The api-proxy keeps an explicit
allowlist of settings namespaces it exposes to configuration clients, and
`agent-presets` was never added — so both pickers moved and then silently
forgot, which is worse than refusing the control. The host seam was fine all
along; only the wire boundary refused. The regression test fails with the
namespace removed.

The nav row showed the fallback gear and read `Agent preset` in Chinese,
matching neither sibling (通用设置 / 模型). It is now 智能体 with the think
glyph, the only unused icon in the set whose semantics point at the agent
rather than at tuning sliders (Personalization is already the workspace
browser's filter control).
This commit is contained in:
Yichen Jiang
2026-08-04 13:34:22 +08:00
parent bf0828e469
commit 9edfdb589d
9 changed files with 41 additions and 10 deletions

View File

@@ -26,7 +26,8 @@ import {
// Type-only: brings the `ctx.tools` Context merge into this program (viewFor reads presenters).
import {
InvalidCompositionError, InvalidPresetIdError, PresetMountError,
PresetNotWritableError, resolveSessionPreset, UnknownPresetError,
PresetNotWritableError, resolveSessionPreset,
SETTINGS_NAMESPACE as AGENT_PRESET_SETTINGS_NAMESPACE, UnknownPresetError,
} from '@deepseek-ai/dsh-agent-presets'
import type {} from '@deepseek-ai/dsh-tools'
import type {
@@ -89,8 +90,15 @@ const COLD_SUMMARY_BATCH_SIZE = 16
/** Conversation message event types (the pagination counting unit). */
const MESSAGE_TYPES = new Set(['user/message', 'assistant/message'])
/** Product settings intentionally exposed beside model-provider namespaces. */
const PRODUCT_SETTINGS_NAMESPACES = new Set(['ui-onboarding'])
/**
* Product settings intentionally exposed beside model-provider namespaces.
*
* The agent-preset namespace carries one field — which preset a session with
* no explicit choice is composed from — and both browser surfaces that offer
* that choice write it through `settings.update`, so it has to cross the
* configuration boundary or the pickers silently fail to persist.
*/
const PRODUCT_SETTINGS_NAMESPACES = new Set(['ui-onboarding', AGENT_PRESET_SETTINGS_NAMESPACE])
/** Read live abort state across awaits without treating it as synchronously immutable. */
function isAborted(signal: AbortSignal): boolean {