11import type { CategoryConfig } from "../../config/schema"
2+ import type {
3+ AvailableCategory ,
4+ AvailableSkill ,
5+ } from "../../agents/dynamic-agent-prompt-builder"
26
37export const VISUAL_CATEGORY_PROMPT_APPEND = `<Category_Context>
48You are working on VISUAL/UI tasks.
@@ -231,7 +235,7 @@ export const CATEGORY_DESCRIPTIONS: Record<string, string> = {
231235 * then summarize user requirements and clarify uncertainties before proceeding.
232236 * Also MANDATES dependency graphs, parallel execution analysis, and category+skill recommendations.
233237 */
234- export const PLAN_AGENT_SYSTEM_PREPEND = `<system>
238+ export const PLAN_AGENT_SYSTEM_PREPEND_STATIC_BEFORE_SKILLS = `<system>
235239BEFORE you begin planning, you MUST first understand the user's request deeply.
236240
237241MANDATORY CONTEXT GATHERING PROTOCOL:
@@ -337,39 +341,9 @@ WHY THIS MATTERS:
337341FOR EVERY TASK, YOU MUST RECOMMEND:
3383421. Which CATEGORY to use for delegation
3393432. Which SKILLS to load for the delegated agent
344+ `
340345
341- ### AVAILABLE CATEGORIES
342-
343- | Category | Best For | Model |
344- |----------|----------|-------|
345- | \`visual-engineering\` | Frontend, UI/UX, design, styling, animation | google/gemini-3-pro |
346- | \`ultrabrain\` | Complex architecture, deep logical reasoning | openai/gpt-5.3-codex |
347- | \`artistry\` | Highly creative/artistic tasks, novel ideas | google/gemini-3-pro |
348- | \`quick\` | Trivial tasks - single file, typo fixes | anthropic/claude-haiku-4-5 |
349- | \`unspecified-low\` | Moderate effort, doesn't fit other categories | anthropic/claude-sonnet-4-5 |
350- | \`unspecified-high\` | High effort, doesn't fit other categories | anthropic/claude-opus-4-6 |
351- | \`writing\` | Documentation, prose, technical writing | google/gemini-3-flash |
352-
353- ### AVAILABLE SKILLS (ALWAYS EVALUATE ALL)
354-
355- Skills inject specialized expertise into the delegated agent.
356- YOU MUST evaluate EVERY skill and justify inclusions/omissions.
357-
358- | Skill | Domain |
359- |-------|--------|
360- | \`agent-browser\` | Browser automation, web testing |
361- | \`frontend-ui-ux\` | Stunning UI/UX design |
362- | \`git-master\` | Atomic commits, git operations |
363- | \`dev-browser\` | Persistent browser state automation |
364- | \`typescript-programmer\` | Production TypeScript code |
365- | \`python-programmer\` | Production Python code |
366- | \`svelte-programmer\` | Svelte components |
367- | \`golang-tui-programmer\` | Go TUI with Charmbracelet |
368- | \`python-debugger\` | Interactive Python debugging |
369- | \`data-scientist\` | DuckDB/Polars data processing |
370- | \`prompt-engineer\` | AI prompt optimization |
371-
372- ### REQUIRED OUTPUT FORMAT
346+ export const PLAN_AGENT_SYSTEM_PREPEND_STATIC_AFTER_SKILLS = `### REQUIRED OUTPUT FORMAT
373347
374348For EACH task, include a recommendation block:
375349
@@ -508,6 +482,58 @@ WHY THIS FORMAT IS MANDATORY:
508482
509483`
510484
485+ function renderPlanAgentCategoryRows ( categories : AvailableCategory [ ] ) : string [ ] {
486+ const sorted = [ ...categories ] . sort ( ( a , b ) => a . name . localeCompare ( b . name ) )
487+ return sorted . map ( ( category ) => {
488+ const bestFor = category . description || category . name
489+ const model = category . model || ""
490+ return `| \`${ category . name } \` | ${ bestFor } | ${ model } |`
491+ } )
492+ }
493+
494+ function renderPlanAgentSkillRows ( skills : AvailableSkill [ ] ) : string [ ] {
495+ const sorted = [ ...skills ] . sort ( ( a , b ) => a . name . localeCompare ( b . name ) )
496+ return sorted . map ( ( skill ) => {
497+ const firstSentence = skill . description . split ( "." ) [ 0 ] || skill . description
498+ const domain = firstSentence . trim ( ) || skill . name
499+ return `| \`${ skill . name } \` | ${ domain } |`
500+ } )
501+ }
502+
503+ export function buildPlanAgentSkillsSection (
504+ categories : AvailableCategory [ ] = [ ] ,
505+ skills : AvailableSkill [ ] = [ ]
506+ ) : string {
507+ const categoryRows = renderPlanAgentCategoryRows ( categories )
508+ const skillRows = renderPlanAgentSkillRows ( skills )
509+
510+ return `### AVAILABLE CATEGORIES
511+
512+ | Category | Best For | Model |
513+ |----------|----------|-------|
514+ ${ categoryRows . join ( "\n" ) }
515+
516+ ### AVAILABLE SKILLS (ALWAYS EVALUATE ALL)
517+
518+ Skills inject specialized expertise into the delegated agent.
519+ YOU MUST evaluate EVERY skill and justify inclusions/omissions.
520+
521+ | Skill | Domain |
522+ |-------|--------|
523+ ${ skillRows . join ( "\n" ) } `
524+ }
525+
526+ export function buildPlanAgentSystemPrepend (
527+ categories : AvailableCategory [ ] = [ ] ,
528+ skills : AvailableSkill [ ] = [ ]
529+ ) : string {
530+ return [
531+ PLAN_AGENT_SYSTEM_PREPEND_STATIC_BEFORE_SKILLS ,
532+ buildPlanAgentSkillsSection ( categories , skills ) ,
533+ PLAN_AGENT_SYSTEM_PREPEND_STATIC_AFTER_SKILLS ,
534+ ] . join ( "\n\n" )
535+ }
536+
511537/**
512538 * List of agent names that should be treated as plan agents.
513539 * Case-insensitive matching is used.
@@ -524,4 +550,3 @@ export function isPlanAgent(agentName: string | undefined): boolean {
524550 const lowerName = agentName . toLowerCase ( ) . trim ( )
525551 return PLAN_AGENT_NAMES . some ( name => lowerName === name || lowerName . includes ( name ) )
526552}
527-
0 commit comments