Files
deepseek-harness/packages/host/apiproxy/src/api/agent-presets.schema.ts
T
Yichen Jiang c56f23ae1f fix(agent-presets,web): broken presets are roster rows, not gaps
A hand-damaged preset was silent until the worst moment. An unparsable
composition listed as an ordinary selectable row and failed only at the
next session start — set as default, every new session failed. A
directory whose composition file was deleted vanished from the roster
while still occupying its id: copy answered "delete the existing preset
first" while remove answered "not found", a dead end.

Discovery now owns health: every id-shaped directory is a roster slot,
broken when its composition is missing or unloadable, checked with the
loader's own entryListSchema dialect (!!js included) so health never
rejects what the loader accepts. `broken` rides AgentPreset, the
agentPreset.list entry, and the UI row; mount/recompose/standingKeyFor
refuse broken up front with the discovery-reported reason, while
resolve/read/remove still answer. The section renders marked red cards —
unselectable, uncopyable, deletable, location kept on custom rows — and
both pickers drop broken rows entirely.

The cordis preset's persona now forbids editing the shipped install
(corrupting cordis would disable the mode itself) and points authoring
at $DSH_HOME/.agent-presets; its skill teaches preset.yml metadata, the
copy-first workflow, the one-escalation sandbox reality, and honest
verification. Exercised live: asked to edit the shipped composition the
composed agent refuses citing both rules; asked for real presets (simple
and complex) it lands them under the user root with one approved
escalation each and self-checks with the loader dialect.
2026-08-09 02:17:56 +08:00

89 lines
3.4 KiB
TypeScript

/**
* agent-presets domain zod schemas (names derived from map keys:
* agentPresetListRequestSchema / agentPresetListValueSchema).
*/
import { z } from 'zod'
import type { RequestPayload, ResponseValue } from './rpc-map.ts'
import type { Wire } from './rpc.schema.ts'
import { sessionIdSchema } from './sessions.schema.ts'
import type { AgentPresetEntry } from './agent-presets.ts'
/** AgentPresetEntry row of agentPreset.list. */
export const agentPresetEntrySchema = z.object({
id: z.string().min(1),
trust: z.union([z.literal('system'), z.literal('user')]),
isDefault: z.boolean(),
name: z.string().optional(),
description: z.string().optional(),
broken: z.string().min(1).optional(),
}) satisfies z.ZodType<Wire<AgentPresetEntry>>
/** agentPreset.list request payload. */
export const agentPresetListRequestSchema = z.object({
}) satisfies z.ZodType<Wire<RequestPayload<'agentPreset.list'>>>
/** agentPreset.list response value. */
export const agentPresetListValueSchema = z.object({
presets: z.array(agentPresetEntrySchema),
authorable: z.boolean(),
hasDocument: z.boolean(),
}) satisfies z.ZodType<Wire<ResponseValue<'agentPreset.list'>>>
/** agentPreset.select request payload. */
export const agentPresetSelectRequestSchema = z.object({
sessionId: sessionIdSchema,
agentPreset: z.string().min(1),
}) satisfies z.ZodType<Wire<RequestPayload<'agentPreset.select'>>>
/** agentPreset.select response value. */
export const agentPresetSelectValueSchema = z.object({
agentPreset: z.string(),
}) satisfies z.ZodType<Wire<ResponseValue<'agentPreset.select'>>>
/** agentPreset.read request payload. */
export const agentPresetReadRequestSchema = z.object({
agentPreset: z.string().min(1),
}) satisfies z.ZodType<Wire<RequestPayload<'agentPreset.read'>>>
/** agentPreset.read response value. */
export const agentPresetReadValueSchema = z.object({
agentPreset: z.string(),
trust: z.union([z.literal('system'), z.literal('user')]),
content: z.string(),
name: z.string().optional(),
description: z.string().optional(),
}) satisfies z.ZodType<Wire<ResponseValue<'agentPreset.read'>>>
/** agentPreset.copy request payload. */
export const agentPresetCopyRequestSchema = z.object({
from: z.string().min(1),
agentPreset: z.string().min(1),
name: z.string().optional(),
}) satisfies z.ZodType<Wire<RequestPayload<'agentPreset.copy'>>>
/** agentPreset.copy response value. */
export const agentPresetCopyValueSchema = z.object({
agentPreset: z.string(),
}) satisfies z.ZodType<Wire<ResponseValue<'agentPreset.copy'>>>
/** agentPreset.openDocument request payload. */
export const agentPresetOpenDocumentRequestSchema = z.object({
agentPreset: z.string().min(1),
}) satisfies z.ZodType<Wire<RequestPayload<'agentPreset.openDocument'>>>
/** agentPreset.openDocument response value. */
export const agentPresetOpenDocumentValueSchema = z.union([
z.object({ opened: z.literal(true) }),
z.object({ opened: z.literal(false), path: z.string() }),
]) satisfies z.ZodType<Wire<ResponseValue<'agentPreset.openDocument'>>>
/** agentPreset.remove request payload. */
export const agentPresetRemoveRequestSchema = z.object({
agentPreset: z.string().min(1),
}) satisfies z.ZodType<Wire<RequestPayload<'agentPreset.remove'>>>
/** agentPreset.remove response value. */
export const agentPresetRemoveValueSchema = z.object({
}) satisfies z.ZodType<Wire<ResponseValue<'agentPreset.remove'>>>