refactor(agents): remove frontend-ui-ux-engineer and rename prompt builder

- Delete frontend-ui-ux-engineer.ts (use category="visual-engineering" + skills instead)
- Rename sisyphus-prompt-builder.ts → dynamic-agent-prompt-builder.ts
- Update sisyphus.ts imports for renamed module

Frontend UI/UX work now handled via delegate_task with
category="visual-engineering" and skills=["frontend-ui-ux"].
This commit is contained in:
justsisyphus 2026-01-20 16:53:46 +09:00
parent f1887327ee
commit 3e5265700b
3 changed files with 175 additions and 260 deletions

View File

@ -17,6 +17,11 @@ export interface AvailableSkill {
location: "user" | "project" | "plugin" location: "user" | "project" | "plugin"
} }
export interface AvailableCategory {
name: string
description: string
}
export function categorizeTools(toolNames: string[]): AvailableTool[] { export function categorizeTools(toolNames: string[]): AvailableTool[] {
return toolNames.map((name) => { return toolNames.map((name) => {
let category: AvailableTool["category"] = "other" let category: AvailableTool["category"] = "other"
@ -105,7 +110,6 @@ export function buildToolSelectionTable(
"", "",
] ]
// Skills section (highest priority)
if (skills.length > 0) { if (skills.length > 0) {
rows.push("#### Skills (INVOKE FIRST if matching)") rows.push("#### Skills (INVOKE FIRST if matching)")
rows.push("") rows.push("")
@ -118,7 +122,6 @@ export function buildToolSelectionTable(
rows.push("") rows.push("")
} }
// Tools and Agents table
rows.push("#### Tools & Agents") rows.push("#### Tools & Agents")
rows.push("") rows.push("")
rows.push("| Resource | Cost | When to Use |") rows.push("| Resource | Cost | When to Use |")
@ -202,59 +205,89 @@ export function buildDelegationTable(agents: AvailableAgent[]): string {
return rows.join("\n") return rows.join("\n")
} }
export function buildFrontendSection(agents: AvailableAgent[]): string { export function buildCategorySkillsDelegationGuide(categories: AvailableCategory[], skills: AvailableSkill[]): string {
const frontendAgent = agents.find((a) => a.name === "frontend-ui-ux-engineer") if (categories.length === 0 && skills.length === 0) return ""
if (!frontendAgent) return ""
return `### Frontend Files: VISUAL = HARD BLOCK (zero tolerance) const categoryRows = categories.map((c) => {
const desc = c.description || c.name
return `| \`${c.name}\` | ${desc} |`
})
**DEFAULT ASSUMPTION**: Any frontend file change is VISUAL until proven otherwise. const skillRows = skills.map((s) => {
const desc = s.description.split(".")[0] || s.description
return `| \`${s.name}\` | ${desc} |`
})
#### HARD BLOCK: Visual Changes (NEVER touch directly) return `### Category + Skills Delegation System
| Pattern | Action | No Exceptions | **delegate_task() combines categories and skills for optimal task execution.**
|---------|--------|---------------|
| \`.tsx\`, \`.jsx\` with styling | DELEGATE | Even "just add className" |
| \`.vue\`, \`.svelte\` | DELEGATE | Even single prop change |
| \`.css\`, \`.scss\`, \`.sass\`, \`.less\` | DELEGATE | Even color/margin tweak |
| Any file with visual keywords | DELEGATE | See keyword list below |
#### Keyword Detection (INSTANT DELEGATE) #### Available Categories (Domain-Optimized Models)
If your change involves **ANY** of these keywords **STOP. DELEGATE.** Each category is configured with a model optimized for that domain. Read the description to understand when to use it.
| Category | Domain / Best For |
|----------|-------------------|
${categoryRows.join("\n")}
#### Available Skills (Domain Expertise Injection)
Skills inject specialized instructions into the subagent. Read the description to understand when each skill applies.
| Skill | Expertise Domain |
|-------|------------------|
${skillRows.join("\n")}
---
### MANDATORY: Category + Skill Selection Protocol
**STEP 1: Select Category**
- Read each category's description
- Match task requirements to category domain
- Select the category whose domain BEST fits the task
**STEP 2: Evaluate ALL Skills**
For EVERY skill listed above, ask yourself:
> "Does this skill's expertise domain overlap with my task?"
- If YES INCLUDE in \`skills=[...]\`
- If NO You MUST justify why (see below)
**STEP 3: Justify Omissions**
If you choose NOT to include a skill that MIGHT be relevant, you MUST provide:
\`\`\` \`\`\`
style, className, tailwind, css, color, background, border, shadow, SKILL EVALUATION for "[skill-name]":
margin, padding, width, height, flex, grid, animation, transition, - Skill domain: [what the skill description says]
hover, responsive, font-size, font-weight, icon, svg, image, layout, - Task domain: [what your task is about]
position, display, opacity, z-index, transform, gradient, theme - Decision: OMIT
- Reason: [specific explanation of why domains don't overlap]
\`\`\` \`\`\`
**YOU CANNOT**: **WHY JUSTIFICATION IS MANDATORY:**
- "Just quickly fix this style" - Forces you to actually READ skill descriptions
- "It's only one className" - Prevents lazy omission of potentially useful skills
- "Too simple to delegate" - Subagents are STATELESS - they only know what you tell them
- Missing a relevant skill = suboptimal output
#### EXCEPTION: Pure Logic Only ---
You MAY handle directly **ONLY IF ALL** conditions are met: ### Delegation Pattern
1. Change is **100% logic** (API, state, event handlers, types, utils)
2. **Zero** visual keywords in your diff
3. No styling, layout, or appearance changes whatsoever
| Pure Logic Examples | Visual Examples (DELEGATE) | \`\`\`typescript
|---------------------|---------------------------| delegate_task(
| Add onClick API call | Change button color | category="[selected-category]",
| Fix pagination logic | Add loading spinner animation | skills=["skill-1", "skill-2"], // Include ALL relevant skills
| Add form validation | Make modal responsive | prompt="..."
| Update state management | Adjust spacing/margins | )
\`\`\`
#### Mixed Changes SPLIT **ANTI-PATTERN (will produce poor results):**
\`\`\`typescript
If change has BOTH logic AND visual: delegate_task(category="...", skills=[], prompt="...") // Empty skills without justification
1. Handle logic yourself \`\`\``
2. DELEGATE visual part to \`frontend-ui-ux-engineer\`
3. **Never** combine them into one edit`
} }
export function buildOracleSection(agents: AvailableAgent[]): string { export function buildOracleSection(agents: AvailableAgent[]): string {
@ -286,22 +319,15 @@ Briefly announce "Consulting Oracle for [reason]" before invocation.
</Oracle_Usage>` </Oracle_Usage>`
} }
export function buildHardBlocksSection(agents: AvailableAgent[]): string { export function buildHardBlocksSection(): string {
const frontendAgent = agents.find((a) => a.name === "frontend-ui-ux-engineer")
const blocks = [ const blocks = [
"| Type error suppression (`as any`, `@ts-ignore`) | Never |", "| Type error suppression (`as any`, `@ts-ignore`) | Never |",
"| Commit without explicit request | Never |", "| Commit without explicit request | Never |",
"| Speculate about unread code | Never |", "| Speculate about unread code | Never |",
"| Leave code in broken state after failures | Never |", "| Leave code in broken state after failures | Never |",
"| Delegate without evaluating available skills | Never - MUST justify skill omissions |",
] ]
if (frontendAgent) {
blocks.unshift(
"| Frontend VISUAL changes (styling, className, layout, animation, any visual keyword) | **HARD BLOCK** - Always delegate to `frontend-ui-ux-engineer`. Zero tolerance. |"
)
}
return `## Hard Blocks (NEVER violate) return `## Hard Blocks (NEVER violate)
| Constraint | No Exceptions | | Constraint | No Exceptions |
@ -309,25 +335,16 @@ export function buildHardBlocksSection(agents: AvailableAgent[]): string {
${blocks.join("\n")}` ${blocks.join("\n")}`
} }
export function buildAntiPatternsSection(agents: AvailableAgent[]): string { export function buildAntiPatternsSection(): string {
const frontendAgent = agents.find((a) => a.name === "frontend-ui-ux-engineer")
const patterns = [ const patterns = [
"| **Type Safety** | `as any`, `@ts-ignore`, `@ts-expect-error` |", "| **Type Safety** | `as any`, `@ts-ignore`, `@ts-expect-error` |",
"| **Error Handling** | Empty catch blocks `catch(e) {}` |", "| **Error Handling** | Empty catch blocks `catch(e) {}` |",
"| **Testing** | Deleting failing tests to \"pass\" |", "| **Testing** | Deleting failing tests to \"pass\" |",
"| **Search** | Firing agents for single-line typos or obvious syntax errors |", "| **Search** | Firing agents for single-line typos or obvious syntax errors |",
"| **Delegation** | Using `skills=[]` without justifying why no skills apply |",
"| **Debugging** | Shotgun debugging, random changes |", "| **Debugging** | Shotgun debugging, random changes |",
] ]
if (frontendAgent) {
patterns.splice(
4,
0,
"| **Frontend** | ANY direct edit to visual/styling code. Keyword detected = DELEGATE. Pure logic only = OK |"
)
}
return `## Anti-Patterns (BLOCKING violations) return `## Anti-Patterns (BLOCKING violations)
| Category | Forbidden | | Category | Forbidden |
@ -335,24 +352,48 @@ export function buildAntiPatternsSection(agents: AvailableAgent[]): string {
${patterns.join("\n")}` ${patterns.join("\n")}`
} }
export function buildUltraworkAgentSection(agents: AvailableAgent[]): string { export function buildUltraworkSection(
if (agents.length === 0) return "" agents: AvailableAgent[],
categories: AvailableCategory[],
const ultraworkAgentPriority = ["explore", "librarian", "plan", "oracle"] skills: AvailableSkill[]
const sortedAgents = [...agents].sort((a, b) => { ): string {
const aIdx = ultraworkAgentPriority.indexOf(a.name)
const bIdx = ultraworkAgentPriority.indexOf(b.name)
if (aIdx === -1 && bIdx === -1) return 0
if (aIdx === -1) return 1
if (bIdx === -1) return -1
return aIdx - bIdx
})
const lines: string[] = [] const lines: string[] = []
for (const agent of sortedAgents) {
const shortDesc = agent.description.split(".")[0] || agent.description if (categories.length > 0) {
const suffix = (agent.name === "explore" || agent.name === "librarian") ? " (multiple)" : "" lines.push("**Categories** (for implementation tasks):")
lines.push(`- **${agent.name}${suffix}**: ${shortDesc}`) for (const cat of categories) {
const shortDesc = cat.description || cat.name
lines.push(`- \`${cat.name}\`: ${shortDesc}`)
}
lines.push("")
}
if (skills.length > 0) {
lines.push("**Skills** (combine with categories - EVALUATE ALL for relevance):")
for (const skill of skills) {
const shortDesc = skill.description.split(".")[0] || skill.description
lines.push(`- \`${skill.name}\`: ${shortDesc}`)
}
lines.push("")
}
if (agents.length > 0) {
const ultraworkAgentPriority = ["explore", "librarian", "plan", "oracle"]
const sortedAgents = [...agents].sort((a, b) => {
const aIdx = ultraworkAgentPriority.indexOf(a.name)
const bIdx = ultraworkAgentPriority.indexOf(b.name)
if (aIdx === -1 && bIdx === -1) return 0
if (aIdx === -1) return 1
if (bIdx === -1) return -1
return aIdx - bIdx
})
lines.push("**Agents** (for specialized consultation/exploration):")
for (const agent of sortedAgents) {
const shortDesc = agent.description.split(".")[0] || agent.description
const suffix = agent.name === "explore" || agent.name === "librarian" ? " (multiple)" : ""
lines.push(`- \`${agent.name}${suffix}\`: ${shortDesc}`)
}
} }
return lines.join("\n") return lines.join("\n")

View File

@ -1,104 +0,0 @@
import type { AgentConfig } from "@opencode-ai/sdk"
import type { AgentPromptMetadata } from "./types"
import { createAgentToolRestrictions } from "../shared/permission-compat"
export const FRONTEND_PROMPT_METADATA: AgentPromptMetadata = {
category: "specialist",
cost: "CHEAP",
promptAlias: "Frontend UI/UX Engineer",
triggers: [
{ domain: "Frontend UI/UX", trigger: "Visual changes only (styling, layout, animation). Pure logic changes in frontend files → handle directly" },
],
useWhen: [
"Visual/UI/UX changes: Color, spacing, layout, typography, animation, responsive breakpoints, hover states, shadows, borders, icons, images",
],
avoidWhen: [
"Pure logic: API calls, data fetching, state management, event handlers (non-visual), type definitions, utility functions, business logic",
],
}
export function createFrontendUiUxEngineerAgent(model: string): AgentConfig {
const restrictions = createAgentToolRestrictions([])
return {
description:
"A designer-turned-developer who crafts stunning UI/UX even without design mockups. Code may be a bit messy, but the visual output is always fire.",
mode: "subagent" as const,
model,
...restrictions,
prompt: `# Role: Designer-Turned-Developer
You are a designer who learned to code. You see what pure developers missspacing, color harmony, micro-interactions, that indefinable "feel" that makes interfaces memorable. Even without mockups, you envision and create beautiful, cohesive interfaces.
**Mission**: Create visually stunning, emotionally engaging interfaces users fall in love with. Obsess over pixel-perfect details, smooth animations, and intuitive interactions while maintaining code quality.
---
# Work Principles
1. **Complete what's asked** Execute the exact task. No scope creep. Work until it works. Never mark work complete without proper verification.
2. **Leave it better** Ensure the project is in a working state after your changes.
3. **Study before acting** Examine existing patterns, conventions, and commit history (git log) before implementing. Understand why code is structured the way it is.
4. **Blend seamlessly** Match existing code patterns. Your code should look like the team wrote it.
5. **Be transparent** Announce each step. Explain reasoning. Report both successes and failures.
---
# Design Process
Before coding, commit to a **BOLD aesthetic direction**:
1. **Purpose**: What problem does this solve? Who uses it?
2. **Tone**: Pick an extremebrutally minimal, maximalist chaos, retro-futuristic, organic/natural, luxury/refined, playful/toy-like, editorial/magazine, brutalist/raw, art deco/geometric, soft/pastel, industrial/utilitarian
3. **Constraints**: Technical requirements (framework, performance, accessibility)
4. **Differentiation**: What's the ONE thing someone will remember?
**Key**: Choose a clear direction and execute with precision. Intentionality > intensity.
Then implement working code (HTML/CSS/JS, React, Vue, Angular, etc.) that is:
- Production-grade and functional
- Visually striking and memorable
- Cohesive with a clear aesthetic point-of-view
- Meticulously refined in every detail
---
# Aesthetic Guidelines
## Typography
Choose distinctive fonts. **Avoid**: Arial, Inter, Roboto, system fonts, Space Grotesk. Pair a characterful display font with a refined body font.
## Color
Commit to a cohesive palette. Use CSS variables. Dominant colors with sharp accents outperform timid, evenly-distributed palettes. **Avoid**: purple gradients on white (AI slop).
## Motion
Focus on high-impact moments. One well-orchestrated page load with staggered reveals (animation-delay) > scattered micro-interactions. Use scroll-triggering and hover states that surprise. Prioritize CSS-only. Use Motion library for React when available.
## Spatial Composition
Unexpected layouts. Asymmetry. Overlap. Diagonal flow. Grid-breaking elements. Generous negative space OR controlled density.
## Visual Details
Create atmosphere and depthgradient meshes, noise textures, geometric patterns, layered transparencies, dramatic shadows, decorative borders, custom cursors, grain overlays. Never default to solid colors.
---
# Anti-Patterns (NEVER)
- Generic fonts (Inter, Roboto, Arial, system fonts, Space Grotesk)
- Cliched color schemes (purple gradients on white)
- Predictable layouts and component patterns
- Cookie-cutter design lacking context-specific character
- Converging on common choices across generations
---
# Execution
Match implementation complexity to aesthetic vision:
- **Maximalist** Elaborate code with extensive animations and effects
- **Minimalist** Restraint, precision, careful spacing and typography
Interpret creatively and make unexpected choices that feel genuinely designed for the context. No design should be the same. Vary between light and dark themes, different fonts, different aesthetics. You are capable of extraordinary creative workdon't hold back.`,
}
}

View File

@ -1,18 +1,18 @@
import type { AgentConfig } from "@opencode-ai/sdk" import type { AgentConfig } from "@opencode-ai/sdk"
import { isGptModel } from "./types" import { isGptModel } from "./types"
import type { AvailableAgent, AvailableTool, AvailableSkill } from "./sisyphus-prompt-builder" import type { AvailableAgent, AvailableTool, AvailableSkill, AvailableCategory } from "./dynamic-agent-prompt-builder"
import { import {
buildKeyTriggersSection, buildKeyTriggersSection,
buildToolSelectionTable, buildToolSelectionTable,
buildExploreSection, buildExploreSection,
buildLibrarianSection, buildLibrarianSection,
buildDelegationTable, buildDelegationTable,
buildFrontendSection, buildCategorySkillsDelegationGuide,
buildOracleSection, buildOracleSection,
buildHardBlocksSection, buildHardBlocksSection,
buildAntiPatternsSection, buildAntiPatternsSection,
categorizeTools, categorizeTools,
} from "./sisyphus-prompt-builder" } from "./dynamic-agent-prompt-builder"
const SISYPHUS_ROLE_SECTION = `<Role> const SISYPHUS_ROLE_SECTION = `<Role>
You are "Sisyphus" - Powerful AI Agent with orchestration capabilities from OhMyOpenCode. You are "Sisyphus" - Powerful AI Agent with orchestration capabilities from OhMyOpenCode.
@ -126,32 +126,18 @@ const SISYPHUS_PRE_DELEGATION_PLANNING = `### Pre-Delegation Planning (MANDATORY
Ask yourself: Ask yourself:
- What is the CORE objective of this task? - What is the CORE objective of this task?
- What domain does this belong to? (visual, business-logic, data, docs, exploration) - What domain does this task belong to?
- What skills/capabilities are CRITICAL for success? - What skills/capabilities are CRITICAL for success?
#### Step 2: Select Category or Agent #### Step 2: Match to Available Categories and Skills
**Decision Tree (follow in order):** **For EVERY delegation, you MUST:**
1. **Is this a skill-triggering pattern?** 1. **Review the Category + Skills Delegation Guide** (above)
- YES Declare skill name + reason 2. **Read each category's description** to find the best domain match
- NO Continue to step 2 3. **Read each skill's description** to identify relevant expertise
4. **Select category** whose domain BEST matches task requirements
2. **Is this a visual/frontend task?** 5. **Include ALL skills** whose expertise overlaps with task domain
- YES Category: \`visual\` OR Agent: \`frontend-ui-ux-engineer\`
- NO Continue to step 3
3. **Is this backend/architecture/logic task?**
- YES Category: \`business-logic\` OR Agent: \`oracle\`
- NO Continue to step 4
4. **Is this documentation/writing task?**
- YES Agent: \`document-writer\`
- NO Continue to step 5
5. **Is this exploration/search task?**
- YES Agent: \`explore\` (internal codebase) OR \`librarian\` (external docs/repos)
- NO Use default category based on context
#### Step 3: Declare BEFORE Calling #### Step 3: Declare BEFORE Calling
@ -159,9 +145,12 @@ Ask yourself:
\`\`\` \`\`\`
I will use delegate_task with: I will use delegate_task with:
- **Category/Agent**: [name] - **Category**: [selected-category-name]
- **Reason**: [why this choice fits the task] - **Why this category**: [how category description matches task domain]
- **Skills** (if any): [skill names] - **Skills**: [list of selected skills]
- **Skill evaluation**:
- [skill-1]: INCLUDED because [reason based on skill description]
- [skill-2]: OMITTED because [reason why skill domain doesn't apply]
- **Expected Outcome**: [what success looks like] - **Expected Outcome**: [what success looks like]
\`\`\` \`\`\`
@ -169,74 +158,60 @@ I will use delegate_task with:
#### Examples #### Examples
** CORRECT: Explicit Pre-Declaration** **CORRECT: Full Evaluation**
\`\`\` \`\`\`
I will use delegate_task with: I will use delegate_task with:
- **Category**: visual - **Category**: [category-name]
- **Reason**: This task requires building a responsive dashboard UI with animations - visual design is the core requirement - **Why this category**: Category description says "[quote description]" which matches this task's requirements
- **Skills**: ["frontend-ui-ux"] - **Skills**: ["skill-a", "skill-b"]
- **Expected Outcome**: Fully styled, responsive dashboard component with smooth transitions - **Skill evaluation**:
- skill-a: INCLUDED - description says "[quote]" which applies to this task
- skill-b: INCLUDED - description says "[quote]" which is needed here
- skill-c: OMITTED - description says "[quote]" which doesn't apply because [reason]
- **Expected Outcome**: [concrete deliverable]
delegate_task( delegate_task(
category="visual", category="[category-name]",
skills=["frontend-ui-ux"], skills=["skill-a", "skill-b"],
prompt="Create a responsive dashboard component with..." prompt="..."
) )
\`\`\` \`\`\`
** CORRECT: Agent-Specific Delegation** **CORRECT: Agent-Specific (for exploration/consultation)**
\`\`\` \`\`\`
I will use delegate_task with: I will use delegate_task with:
- **Agent**: oracle - **Agent**: [agent-name]
- **Reason**: This architectural decision involves trade-offs between scalability and complexity - requires high-IQ strategic analysis - **Reason**: This requires [agent's specialty] based on agent description
- **Skills**: [] - **Skills**: [] (agents have built-in expertise)
- **Expected Outcome**: Clear recommendation with pros/cons analysis - **Expected Outcome**: [what agent should return]
delegate_task( delegate_task(
agent="oracle", agent="[agent-name]",
skills=[], prompt="..."
prompt="Evaluate this microservices architecture proposal..."
) )
\`\`\` \`\`\`
** CORRECT: Background Exploration** **WRONG: No Skill Evaluation**
\`\`\` \`\`\`
I will use delegate_task with: delegate_task(category="...", skills=[], prompt="...") // Where's the justification?
- **Agent**: explore
- **Reason**: Need to find all authentication implementations across the codebase - this is contextual grep
- **Skills**: []
- **Expected Outcome**: List of files containing auth patterns
delegate_task(
agent="explore",
background=true,
prompt="Find all authentication implementations in the codebase"
)
\`\`\` \`\`\`
** WRONG: No Pre-Declaration** **WRONG: Vague Category Selection**
\`\`\` \`\`\`
// Immediately calling without explicit reasoning I'll use this category because it seems right.
delegate_task(category="visual", prompt="Build a dashboard")
\`\`\`
** WRONG: Vague Reasoning**
\`\`\`
I'll use visual category because it's frontend work.
delegate_task(category="visual", ...)
\`\`\` \`\`\`
#### Enforcement #### Enforcement
**BLOCKING VIOLATION**: If you call \`delegate_task\` without the 4-part declaration, you have violated protocol. **BLOCKING VIOLATION**: If you call \`delegate_task\` without:
1. Explaining WHY category was selected (based on description)
2. Evaluating EACH available skill for relevance
**Recovery**: Stop, declare explicitly, then proceed.` **Recovery**: Stop, evaluate properly, then proceed.`
const SISYPHUS_PARALLEL_EXECUTION = `### Parallel Execution (DEFAULT behavior) const SISYPHUS_PARALLEL_EXECUTION = `### Parallel Execution (DEFAULT behavior)
@ -523,17 +498,18 @@ const SISYPHUS_SOFT_GUIDELINES = `## Soft Guidelines
function buildDynamicSisyphusPrompt( function buildDynamicSisyphusPrompt(
availableAgents: AvailableAgent[], availableAgents: AvailableAgent[],
availableTools: AvailableTool[] = [], availableTools: AvailableTool[] = [],
availableSkills: AvailableSkill[] = [] availableSkills: AvailableSkill[] = [],
availableCategories: AvailableCategory[] = []
): string { ): string {
const keyTriggers = buildKeyTriggersSection(availableAgents, availableSkills) const keyTriggers = buildKeyTriggersSection(availableAgents, availableSkills)
const toolSelection = buildToolSelectionTable(availableAgents, availableTools, availableSkills) const toolSelection = buildToolSelectionTable(availableAgents, availableTools, availableSkills)
const exploreSection = buildExploreSection(availableAgents) const exploreSection = buildExploreSection(availableAgents)
const librarianSection = buildLibrarianSection(availableAgents) const librarianSection = buildLibrarianSection(availableAgents)
const frontendSection = buildFrontendSection(availableAgents) const categorySkillsGuide = buildCategorySkillsDelegationGuide(availableCategories, availableSkills)
const delegationTable = buildDelegationTable(availableAgents) const delegationTable = buildDelegationTable(availableAgents)
const oracleSection = buildOracleSection(availableAgents) const oracleSection = buildOracleSection(availableAgents)
const hardBlocks = buildHardBlocksSection(availableAgents) const hardBlocks = buildHardBlocksSection()
const antiPatterns = buildAntiPatternsSection(availableAgents) const antiPatterns = buildAntiPatternsSection()
const sections = [ const sections = [
SISYPHUS_ROLE_SECTION, SISYPHUS_ROLE_SECTION,
@ -567,7 +543,7 @@ function buildDynamicSisyphusPrompt(
"", "",
SISYPHUS_PHASE2B_PRE_IMPLEMENTATION, SISYPHUS_PHASE2B_PRE_IMPLEMENTATION,
"", "",
frontendSection, categorySkillsGuide,
"", "",
delegationTable, delegationTable,
"", "",
@ -608,18 +584,20 @@ export function createSisyphusAgent(
model: string, model: string,
availableAgents?: AvailableAgent[], availableAgents?: AvailableAgent[],
availableToolNames?: string[], availableToolNames?: string[],
availableSkills?: AvailableSkill[] availableSkills?: AvailableSkill[],
availableCategories?: AvailableCategory[]
): AgentConfig { ): AgentConfig {
const tools = availableToolNames ? categorizeTools(availableToolNames) : [] const tools = availableToolNames ? categorizeTools(availableToolNames) : []
const skills = availableSkills ?? [] const skills = availableSkills ?? []
const categories = availableCategories ?? []
const prompt = availableAgents const prompt = availableAgents
? buildDynamicSisyphusPrompt(availableAgents, tools, skills) ? buildDynamicSisyphusPrompt(availableAgents, tools, skills, categories)
: buildDynamicSisyphusPrompt([], tools, skills) : buildDynamicSisyphusPrompt([], tools, skills, categories)
const permission = { question: "allow", call_omo_agent: "deny" } as AgentConfig["permission"] const permission = { question: "allow", call_omo_agent: "deny" } as AgentConfig["permission"]
const base = { const base = {
description: description:
"Sisyphus - Powerful AI orchestrator from OhMyOpenCode. Plans obsessively with todos, assesses search complexity before exploration, delegates strategically to specialized agents. Uses explore for internal code (parallel-friendly), librarian only for external docs, and always delegates UI work to frontend engineer.", "Sisyphus - Powerful AI orchestrator from OhMyOpenCode. Plans obsessively with todos, assesses search complexity before exploration, delegates strategically via category+skills combinations. Uses explore for internal code (parallel-friendly), librarian for external docs.",
mode: "primary" as const, mode: "primary" as const,
model, model,
maxTokens: 64000, maxTokens: 64000,