/** * Agent profiles — named personas for dispatch. * * A profile is a markdown file: YAML-ish frontmatter on top, a persona system * prompt below. It bundles a skill basket, a tool allowlist, and an optional * model so `dispatch` (and the `&` prefix) can launch a child as a named * specialist instead of hand-assembling tools/skills/prompt per task: * * --- * name: reviewer * description: Code review — correctness, tests, simplicity * skills: pr, review-checklist * tools: read, grep, find, ls * model: anthropic/claude-sonnet-4-5 * --- * Review the change against the task. Prefer the smallest correct fix. * * Discovery (first-wins by name, highest precedence first): * 1. `/.pi/agents/*.md` — project profiles * 2. `/agents/*.md` — user profiles * 3. host-provided extra dirs — e.g. a distribution's bundled defaults * * The frontmatter parser is deliberately small, not a YAML implementation: * `key: value` scalars, `key:` followed by `- item` block lists, and * comma-separated scalars for list fields. Unknown keys are ignored so files * shared with other agent-file consumers (Claude Code, pi-subagents) load. * * Skills resolve at dispatch time against the parent session's registered * skill catalog (bare names) or relative to the profile file (path entries). * Missing skills warn; they never fail the dispatch. */ export interface AgentProfile { name: string; description: string; /** Skill names (resolved via the session skill registry) or `.md` paths relative to the profile file. */ skills: string[]; /** Tool allowlist. Omitted = dispatch's read-only default. */ tools?: string[] | undefined; model?: string | undefined; /** Default the task to worktree isolation (the natural home for builder personas). */ worktree?: boolean | undefined; /** Replace pi's system prompt with the persona prompt instead of appending. */ replace?: boolean | undefined; /** Persona system prompt (frontmatter body). Empty string when absent. */ prompt: string; /** Source file, for diagnostics and relative skill resolution. */ path: string; scope: 'project' | 'user' | 'extra'; } /** The task fields a profile can default. Structural so index.ts's TaskSpec satisfies it. */ export interface ProfileTaskFields { agent?: string | undefined; model?: string | undefined; tools?: string[] | undefined; systemPrompt?: string | undefined; allowTreeMutation?: boolean | undefined; worktree?: boolean | undefined; skillPaths?: string[] | undefined; replaceSystemPrompt?: boolean | undefined; } export type ParseResult = { ok: true; profile: AgentProfile; } | { ok: false; error: string; }; /** * Parse one profile file. Returns a typed error (never throws) so discovery * can collect diagnostics and a strict `profile:` lookup can explain itself. */ export declare function parseAgentProfile(content: string, filePath: string, scope: AgentProfile['scope']): ParseResult; export interface ProfileDir { dir: string; scope: AgentProfile['scope']; } /** Ordered search dirs, highest precedence first. Missing dirs are fine. */ export declare function profileSearchDirs(cwd: string, agentDir: string, extraDirs: string[]): ProfileDir[]; export interface DiscoveredProfiles { /** name -> profile, first-wins across dirs in the given order. */ profiles: Map; /** Parse failures, for strict-lookup diagnostics. */ errors: string[]; } export declare function discoverProfiles(dirs: ProfileDir[]): DiscoveredProfiles; export interface ResolvedSkills { skillPaths: string[]; missing: string[]; } /** * Resolve a profile's skill entries to SKILL.md paths. Bare names look up in * `skillRegistry` (skill name -> SKILL.md path, from the parent session's * catalog); entries containing a path separator or ending in `.md` resolve * relative to the profile file. Missing entries are reported, not fatal. */ export declare function resolveProfileSkills(profile: AgentProfile, skillRegistry: Map): ResolvedSkills; /** * Merge a profile into a task spec. Explicit spec fields win — call beats * persona, persona beats defaults. `replace` applies only when the persona's * own prompt is used (an explicit systemPrompt keeps append semantics). */ export declare function applyProfile(spec: T, profile: AgentProfile, skillPaths: string[]): T;