fix(keyword-detector): implement agent-aware ultrawork message generation
Restructure ultrawork message generation to support agent-specific instructions. - Extract ultrawork message components into modular constants - Add getUltraworkMessage(agentName) function that adapts instructions based on agent type - Support planner-specific vs default agent execution patterns - Pass agentName parameter through detector.ts for message resolution 🤖 GENERATED WITH ASSISTANCE OF [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode)
This commit is contained in:
@@ -1,12 +1,7 @@
|
|||||||
export const CODE_BLOCK_PATTERN = /```[\s\S]*?```/g
|
export const CODE_BLOCK_PATTERN = /```[\s\S]*?```/g
|
||||||
export const INLINE_CODE_PATTERN = /`[^`]+`/g
|
export const INLINE_CODE_PATTERN = /`[^`]+`/g
|
||||||
|
|
||||||
export const KEYWORD_DETECTORS: Array<{ pattern: RegExp; message: string }> = [
|
const ULTRAWORK_TODO_SECTION = `## TODO IS YOUR LIFELINE (NON-NEGOTIABLE)
|
||||||
{
|
|
||||||
pattern: /(ultrawork|ulw)/i,
|
|
||||||
message: `<ultrawork-mode>
|
|
||||||
|
|
||||||
## TODO IS YOUR LIFELINE (NON-NEGOTIABLE)
|
|
||||||
|
|
||||||
**USE TodoWrite OBSESSIVELY. This is the #1 most important tool.**
|
**USE TodoWrite OBSESSIVELY. This is the #1 most important tool.**
|
||||||
|
|
||||||
@@ -29,9 +24,122 @@ GOOD:
|
|||||||
- "Add auth tests - login failure case"
|
- "Add auth tests - login failure case"
|
||||||
- "Verify LSP diagnostics clean"
|
- "Verify LSP diagnostics clean"
|
||||||
|
|
||||||
**YOUR WORK IS INVISIBLE WITHOUT TODOs. USE THEM.**
|
**YOUR WORK IS INVISIBLE WITHOUT TODOs. USE THEM.**`
|
||||||
|
|
||||||
## TDD WORKFLOW (MANDATORY when tests exist)
|
const ULTRAWORK_AGENT_UTILIZATION_DEFAULT = `## AGENT UTILIZATION PRINCIPLES (by capability, not by name)
|
||||||
|
- **Codebase Exploration**: Spawn exploration agents using BACKGROUND TASKS for file patterns, internal implementations, project structure
|
||||||
|
- **Documentation & References**: Use librarian-type agents via BACKGROUND TASKS for API references, examples, external library docs
|
||||||
|
- **Planning & Strategy**: NEVER plan yourself - use \`plan\` agent for work breakdown
|
||||||
|
- **CRITICAL**: Use the regular \`plan\` agent (subagent_type="plan"), NOT Prometheus, NOT Metis, NOT any other planner
|
||||||
|
- The \`plan\` agent is specifically designed for ultrawork workflows
|
||||||
|
- **High-IQ Reasoning**: Leverage specialized agents for architecture decisions, code review, strategic planning
|
||||||
|
- **Frontend/UI Tasks**: Delegate to UI-specialized agents for design and implementation`
|
||||||
|
|
||||||
|
const ULTRAWORK_AGENT_UTILIZATION_PLANNER = `## CRITICAL: YOU ARE A PLANNER, NOT AN IMPLEMENTER
|
||||||
|
|
||||||
|
**IDENTITY CONSTRAINT (NON-NEGOTIABLE):**
|
||||||
|
You ARE the planner. You ARE NOT an implementer. You DO NOT write code. You DO NOT execute tasks.
|
||||||
|
|
||||||
|
**TOOL RESTRICTIONS (SYSTEM-ENFORCED):**
|
||||||
|
| Tool | Allowed | Blocked |
|
||||||
|
|------|---------|---------|
|
||||||
|
| Write/Edit | \`.sisyphus/**/*.md\` ONLY | Everything else |
|
||||||
|
| Read | All files | - |
|
||||||
|
| Bash | Research commands only | Implementation commands |
|
||||||
|
| sisyphus_task | explore, librarian | - |
|
||||||
|
|
||||||
|
**IF YOU TRY TO WRITE/EDIT OUTSIDE \`.sisyphus/\`:**
|
||||||
|
- System will BLOCK your action
|
||||||
|
- You will receive an error
|
||||||
|
- DO NOT retry - you are not supposed to implement
|
||||||
|
|
||||||
|
**YOUR ONLY WRITABLE PATHS:**
|
||||||
|
- \`.sisyphus/plans/*.md\` - Final work plans
|
||||||
|
- \`.sisyphus/drafts/*.md\` - Working drafts during interview
|
||||||
|
|
||||||
|
**WHEN USER ASKS YOU TO IMPLEMENT:**
|
||||||
|
REFUSE. Say: "I'm a planner. I create work plans, not implementations. Run \`/start-work\` after I finish planning."
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## CONTEXT GATHERING (MANDATORY BEFORE PLANNING)
|
||||||
|
|
||||||
|
You ARE the planner. Your job: create bulletproof work plans.
|
||||||
|
**Before drafting ANY plan, gather context via explore/librarian agents.**
|
||||||
|
|
||||||
|
### Research Protocol
|
||||||
|
1. **Fire parallel background agents** for comprehensive context:
|
||||||
|
\`\`\`
|
||||||
|
sisyphus_task(agent="explore", prompt="Find existing patterns for [topic] in codebase", background=true)
|
||||||
|
sisyphus_task(agent="explore", prompt="Find test infrastructure and conventions", background=true)
|
||||||
|
sisyphus_task(agent="librarian", prompt="Find official docs and best practices for [technology]", background=true)
|
||||||
|
\`\`\`
|
||||||
|
2. **Wait for results** before planning - rushed plans fail
|
||||||
|
3. **Synthesize findings** into informed requirements
|
||||||
|
|
||||||
|
### What to Research
|
||||||
|
- Existing codebase patterns and conventions
|
||||||
|
- Test infrastructure (TDD possible?)
|
||||||
|
- External library APIs and constraints
|
||||||
|
- Similar implementations in OSS (via librarian)
|
||||||
|
|
||||||
|
**NEVER plan blind. Context first, plan second.**`
|
||||||
|
|
||||||
|
const ULTRAWORK_EXECUTION_DEFAULT = `## EXECUTION RULES
|
||||||
|
- **TODO**: Track EVERY step. Mark complete IMMEDIATELY after each.
|
||||||
|
- **PARALLEL**: Fire independent agent calls simultaneously via sisyphus_task - NEVER wait sequentially.
|
||||||
|
- **BACKGROUND FIRST**: Use sisyphus_task for exploration/research agents (10+ concurrent if needed).
|
||||||
|
- **VERIFY**: Re-read request after completion. Check ALL requirements met before reporting done.
|
||||||
|
- **DELEGATE**: Don't do everything yourself - orchestrate specialized agents for their strengths.
|
||||||
|
|
||||||
|
## MANDATORY INITIAL TODOS (CREATE IMMEDIATELY)
|
||||||
|
|
||||||
|
Upon detecting ultrawork, you MUST create these todos FIRST before any other action:
|
||||||
|
|
||||||
|
\`\`\`
|
||||||
|
TodoWrite([
|
||||||
|
{"id": "pre-0", "content": "Check if test infrastructure exists (bun test, npm test, pytest, etc.)", "status": "pending", "priority": "high"},
|
||||||
|
{"id": "pre-1", "content": "Decide TDD vs regular flow based on test infrastructure", "status": "pending", "priority": "high"},
|
||||||
|
{"id": "pre-2", "content": "Use plan agent (NOT Prometheus!) via task(subagent_type='plan') to create work breakdown", "status": "pending", "priority": "high"}
|
||||||
|
])
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## WORKFLOW
|
||||||
|
1. **Create mandatory todos above FIRST**
|
||||||
|
2. Check test infrastructure: run \`bun test --help\` or check package.json scripts
|
||||||
|
3. If tests exist → TDD flow. If not → regular flow.
|
||||||
|
4. **Use \`plan\` agent (NOT Prometheus!) to create detailed work breakdown**
|
||||||
|
- Call: \`task(subagent_type="plan", prompt="...")\`
|
||||||
|
- DO NOT call Prometheus, Metis, or any other planner variant
|
||||||
|
5. Execute with continuous verification against original requirements`
|
||||||
|
|
||||||
|
const ULTRAWORK_EXECUTION_PLANNER = `## EXECUTION RULES
|
||||||
|
- **TODO**: Track EVERY research/planning step. Mark complete IMMEDIATELY after each.
|
||||||
|
- **PARALLEL**: Fire explore/librarian agents simultaneously - NEVER wait sequentially.
|
||||||
|
- **BACKGROUND FIRST**: Use sisyphus_task for all context gathering (10+ concurrent if needed).
|
||||||
|
- **VERIFY**: Re-read user request after planning. Check plan addresses ALL requirements.
|
||||||
|
|
||||||
|
## MANDATORY INITIAL TODOS (CREATE IMMEDIATELY)
|
||||||
|
|
||||||
|
Upon detecting ultrawork, you MUST create these todos FIRST:
|
||||||
|
|
||||||
|
\`\`\`
|
||||||
|
TodoWrite([
|
||||||
|
{"id": "pre-0", "content": "Fire explore agents for codebase patterns and structure", "status": "pending", "priority": "high"},
|
||||||
|
{"id": "pre-1", "content": "Fire librarian agents for external docs and OSS examples", "status": "pending", "priority": "high"},
|
||||||
|
{"id": "pre-2", "content": "Collect and synthesize research results", "status": "pending", "priority": "high"},
|
||||||
|
{"id": "pre-3", "content": "Draft comprehensive work plan based on findings", "status": "pending", "priority": "high"}
|
||||||
|
])
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## WORKFLOW
|
||||||
|
1. **Create todos above FIRST**
|
||||||
|
2. Launch parallel explore/librarian agents for context
|
||||||
|
3. Collect results - understand codebase state, patterns, constraints
|
||||||
|
4. Draft plan incorporating research findings
|
||||||
|
5. Verify plan addresses ALL user requirements`
|
||||||
|
|
||||||
|
const ULTRAWORK_COMMON_TAIL = `## TDD FLOW (when test infrastructure exists)
|
||||||
|
|
||||||
Check for test infrastructure FIRST. If exists, follow strictly:
|
Check for test infrastructure FIRST. If exists, follow strictly:
|
||||||
|
|
||||||
@@ -84,13 +192,55 @@ If you realize you've taken shortcuts:
|
|||||||
|
|
||||||
**THE USER ASKED FOR X. DELIVER EXACTLY X. COMPLETELY. HONESTLY. NO MATTER THE SIZE.**
|
**THE USER ASKED FOR X. DELIVER EXACTLY X. COMPLETELY. HONESTLY. NO MATTER THE SIZE.**
|
||||||
|
|
||||||
## SUCCESS = All TODOs Done + All Requirements Met + Evidence Provided
|
## SUCCESS = All TODOs Done + All Requirements Met + Evidence Provided`
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if the agent is a planner-type agent.
|
||||||
|
* Planner agents should NOT be told to call plan agent (they ARE the planner).
|
||||||
|
*/
|
||||||
|
function isPlannerAgent(agentName?: string): boolean {
|
||||||
|
if (!agentName) return false
|
||||||
|
const lowerName = agentName.toLowerCase()
|
||||||
|
return lowerName.includes("prometheus") || lowerName.includes("planner") || lowerName === "plan"
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the ultrawork message based on agent context.
|
||||||
|
* Planner agents get context-gathering focused instructions.
|
||||||
|
* Other agents get plan-delegation instructions.
|
||||||
|
*/
|
||||||
|
export function getUltraworkMessage(agentName?: string): string {
|
||||||
|
const isPlanner = isPlannerAgent(agentName)
|
||||||
|
|
||||||
|
const agentSection = isPlanner
|
||||||
|
? ULTRAWORK_AGENT_UTILIZATION_PLANNER
|
||||||
|
: ULTRAWORK_AGENT_UTILIZATION_DEFAULT
|
||||||
|
|
||||||
|
const executionSection = isPlanner
|
||||||
|
? ULTRAWORK_EXECUTION_PLANNER
|
||||||
|
: ULTRAWORK_EXECUTION_DEFAULT
|
||||||
|
|
||||||
|
return `<ultrawork-mode>
|
||||||
|
|
||||||
|
${ULTRAWORK_TODO_SECTION}
|
||||||
|
|
||||||
|
${agentSection}
|
||||||
|
|
||||||
|
${executionSection}
|
||||||
|
|
||||||
|
${ULTRAWORK_COMMON_TAIL}
|
||||||
|
|
||||||
</ultrawork-mode>
|
</ultrawork-mode>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
`,
|
`
|
||||||
|
}
|
||||||
|
|
||||||
|
export const KEYWORD_DETECTORS: Array<{ pattern: RegExp; message: string | ((agentName?: string) => string) }> = [
|
||||||
|
{
|
||||||
|
pattern: /(ultrawork|ulw)/i,
|
||||||
|
message: getUltraworkMessage,
|
||||||
},
|
},
|
||||||
// SEARCH: EN/KO/JP/CN/VN
|
// SEARCH: EN/KO/JP/CN/VN
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -13,20 +13,30 @@ export function removeCodeBlocks(text: string): string {
|
|||||||
return text.replace(CODE_BLOCK_PATTERN, "").replace(INLINE_CODE_PATTERN, "")
|
return text.replace(CODE_BLOCK_PATTERN, "").replace(INLINE_CODE_PATTERN, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
export function detectKeywords(text: string): string[] {
|
/**
|
||||||
|
* Resolves message to string, handling both static strings and dynamic functions.
|
||||||
|
*/
|
||||||
|
function resolveMessage(
|
||||||
|
message: string | ((agentName?: string) => string),
|
||||||
|
agentName?: string
|
||||||
|
): string {
|
||||||
|
return typeof message === "function" ? message(agentName) : message
|
||||||
|
}
|
||||||
|
|
||||||
|
export function detectKeywords(text: string, agentName?: string): string[] {
|
||||||
const textWithoutCode = removeCodeBlocks(text)
|
const textWithoutCode = removeCodeBlocks(text)
|
||||||
return KEYWORD_DETECTORS.filter(({ pattern }) =>
|
return KEYWORD_DETECTORS.filter(({ pattern }) =>
|
||||||
pattern.test(textWithoutCode)
|
pattern.test(textWithoutCode)
|
||||||
).map(({ message }) => message)
|
).map(({ message }) => resolveMessage(message, agentName))
|
||||||
}
|
}
|
||||||
|
|
||||||
export function detectKeywordsWithType(text: string): DetectedKeyword[] {
|
export function detectKeywordsWithType(text: string, agentName?: string): DetectedKeyword[] {
|
||||||
const textWithoutCode = removeCodeBlocks(text)
|
const textWithoutCode = removeCodeBlocks(text)
|
||||||
const types: Array<"ultrawork" | "search" | "analyze"> = ["ultrawork", "search", "analyze"]
|
const types: Array<"ultrawork" | "search" | "analyze"> = ["ultrawork", "search", "analyze"]
|
||||||
return KEYWORD_DETECTORS.map(({ pattern, message }, index) => ({
|
return KEYWORD_DETECTORS.map(({ pattern, message }, index) => ({
|
||||||
matches: pattern.test(textWithoutCode),
|
matches: pattern.test(textWithoutCode),
|
||||||
type: types[index],
|
type: types[index],
|
||||||
message,
|
message: resolveMessage(message, agentName),
|
||||||
}))
|
}))
|
||||||
.filter((result) => result.matches)
|
.filter((result) => result.matches)
|
||||||
.map(({ type, message }) => ({ type, message }))
|
.map(({ type, message }) => ({ type, message }))
|
||||||
|
|||||||
Reference in New Issue
Block a user