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.
89 lines
3.4 KiB
TypeScript
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'>>>
|