* fix(shellcheck): declare and assign separately in router.sh (SC2155) * feat(plugin): enhance context management and skill invocation - Update .context-manifest.json to include profile and detailed source information. - Revise context-scout.md to clarify context root discovery and navigation. - Modify commands to replace deprecated skills with updated ones (brainstorming → approach, systematic-debugging → debugger). - Streamline install-context.md for clarity and remove interactive profile selection. - Improve oac-status.md to provide a more comprehensive status report. - Add OAC system paths to session-start.sh for better context management. - Remove obsolete skills and improve documentation for existing commands.
4.1 KiB
4.1 KiB
Example: Zod Schema Migration Pattern
Purpose: Migrate TypeScript definitions to runtime-validated Zod schemas
Last Updated: 2026-02-04
Why Zod?
Benefits: Runtime validation + single source of truth + better error messages
Basic Pattern
// BEFORE: .d.ts interface
interface AgentFrontmatter {
name: string
mode: 'primary' | 'subagent' | 'all'
temperature?: number
}
// AFTER: Zod schema
import { z } from 'zod'
export const AgentFrontmatterSchema = z.object({
name: z.string(),
mode: z.enum(['primary', 'subagent', 'all']),
temperature: z.number().min(0).max(2).optional()
})
export type AgentFrontmatter = z.infer<typeof AgentFrontmatterSchema>
Complex Schema
// Granular permissions
export const GranularPermissionSchema = z.object({
allow: z.array(z.string()).optional(),
deny: z.array(z.string()).optional(),
ask: z.array(z.string()).optional()
})
export const PermissionRuleSchema = z.union([
z.literal('allow'),
z.literal('deny'),
z.boolean(),
GranularPermissionSchema
])
export const ToolAccessSchema = z.object({
read: PermissionRuleSchema.optional(),
write: PermissionRuleSchema.optional(),
bash: PermissionRuleSchema.optional()
})
export type ToolAccess = z.infer<typeof ToolAccessSchema>
Validation Usage
// Strict parsing (throws on invalid)
const frontmatter = AgentFrontmatterSchema.parse(data)
// Safe parsing (returns result object)
const result = AgentFrontmatterSchema.safeParse(data)
if (result.success) {
console.log(result.data) // Typed correctly
} else {
console.error(result.error.errors) // Detailed errors
}
Common Patterns
Enums
export const ModeSchema = z.enum(['primary', 'subagent']).default('primary')
Arrays
export const SkillSchema = z.union([
z.string(), // "skill-name"
z.object({ name: z.string() }) // { name, config }
])
export const SkillsSchema = z.array(SkillSchema).optional()
Records
export const MetadataSchema = z.record(z.unknown()) // { [key: string]: any }
Optionals
z.string().optional() // string | undefined
z.number().default(0.7) // number with default
Full Example: OpenAgent
export const OpenAgentSchema = z.object({
frontmatter: AgentFrontmatterSchema,
metadata: AgentMetadataSchema.optional(),
systemPrompt: z.string(),
contexts: z.array(ContextReferenceSchema).optional()
})
export type OpenAgent = z.infer<typeof OpenAgentSchema>
Migration Checklist
interface→z.object()type X = Y | Z→z.union([...])?optional →.optional()- Add constraints (
.min(),.max()) - Export schema AND type
- Test with valid/invalid data
Testing
describe('AgentFrontmatterSchema', () => {
it('validates correct data', () => {
expect(() => AgentFrontmatterSchema.parse({
name: 'TestAgent',
mode: 'primary'
})).not.toThrow()
})
it('rejects invalid mode', () => {
expect(() => AgentFrontmatterSchema.parse({
name: 'Test',
mode: 'invalid'
})).toThrow()
})
it('rejects out-of-range temperature', () => {
expect(() => AgentFrontmatterSchema.parse({
name: 'Test',
temperature: 5.0 // Max 2.0
})).toThrow()
})
})
Key Schemas (Compatibility Layer)
20+ schemas migrated:
OpenAgentSchema- Complete agentAgentFrontmatterSchema- YAML frontmatterToolAccessSchema- Tool permissionsPermissionRuleSchema- Permission typesSkillReferenceSchema- Skill definitionsHookDefinitionSchema- Hook configs
Reference
- Implementation:
packages/compatibility-layer/src/types.ts(315 lines) - Original:
packages/compatibility-layer/dist/src/types.d.ts(679 lines) - Zod Docs: https://zod.dev
- Related:
- examples/baseadapter-pattern.md
- concepts/compatibility-layer.md