174 lines
6.2 KiB
TypeScript
174 lines
6.2 KiB
TypeScript
import type {
|
|
AvailableAgent,
|
|
AvailableCategory,
|
|
AvailableSkill,
|
|
} from "./dynamic-agent-prompt-types"
|
|
|
|
export function buildHardBlocksSection(): string {
|
|
const blocks = [
|
|
"- Type error suppression (`as any`, `@ts-ignore`) - **Never**",
|
|
"- Commit without explicit request - **Never**",
|
|
"- Speculate about unread code - **Never**",
|
|
"- Leave code in broken state after failures - **Never**",
|
|
"- `background_cancel(all=true)` - **Never.** Always cancel individually by taskId.",
|
|
"- Delivering final answer before collecting Oracle result - **Never.**",
|
|
]
|
|
|
|
return `## Hard Blocks (NEVER violate)
|
|
|
|
${blocks.join("\n")}`
|
|
}
|
|
|
|
export function buildAntiPatternsSection(): string {
|
|
const patterns = [
|
|
"- **Type Safety**: `as any`, `@ts-ignore`, `@ts-expect-error`",
|
|
"- **Error Handling**: Empty catch blocks `catch(e) {}`",
|
|
'- **Testing**: Deleting failing tests to "pass"',
|
|
"- **Search**: Firing agents for single-line typos or obvious syntax errors",
|
|
"- **Debugging**: Shotgun debugging, random changes",
|
|
"- **Background Tasks**: Polling `background_output` on running tasks - end response and wait for notification",
|
|
"- **Delegation Duplication**: Delegating exploration to explore/librarian and then manually doing the same search yourself",
|
|
"- **Oracle**: Delivering answer without collecting Oracle results",
|
|
]
|
|
|
|
return `## Anti-Patterns (BLOCKING violations)
|
|
|
|
${patterns.join("\n")}`
|
|
}
|
|
|
|
export function buildToolCallFormatSection(): string {
|
|
return `## Tool Call Format (CRITICAL)
|
|
|
|
**ALWAYS use the native tool calling mechanism. NEVER output tool calls as text.**
|
|
|
|
When you need to call a tool:
|
|
1. Use the tool call interface provided by the system
|
|
2. Do NOT write tool calls as plain text like \`assistant to=functions.XXX\`
|
|
3. Do NOT output JSON directly in your text response
|
|
4. The system handles tool call formatting automatically
|
|
|
|
**CORRECT**: Invoke the tool through the tool call interface
|
|
**WRONG**: Writing \`assistant to=functions.todowrite\` or \`json\n{...}\` as text
|
|
|
|
Your tool calls are processed automatically. Just invoke the tool - do not format the call yourself.`
|
|
}
|
|
|
|
export function buildUltraworkSection(
|
|
agents: AvailableAgent[],
|
|
categories: AvailableCategory[],
|
|
skills: AvailableSkill[],
|
|
): string {
|
|
const lines: string[] = []
|
|
|
|
if (categories.length > 0) {
|
|
lines.push("**Categories** (for implementation tasks):")
|
|
for (const category of categories) {
|
|
const shortDescription = category.description || category.name
|
|
lines.push(`- \`${category.name}\`: ${shortDescription}`)
|
|
}
|
|
lines.push("")
|
|
}
|
|
|
|
if (skills.length > 0) {
|
|
const builtinSkills = skills.filter((skill) => skill.location === "plugin")
|
|
const customSkills = skills.filter((skill) => skill.location !== "plugin")
|
|
|
|
if (builtinSkills.length > 0) {
|
|
lines.push("**Built-in Skills** (combine with categories):")
|
|
for (const skill of builtinSkills) {
|
|
const shortDescription = skill.description.split(".")[0] || skill.description
|
|
lines.push(`- \`${skill.name}\`: ${shortDescription}`)
|
|
}
|
|
lines.push("")
|
|
}
|
|
|
|
if (customSkills.length > 0) {
|
|
lines.push("**User-Installed Skills** (HIGH PRIORITY - user installed these for their workflow):")
|
|
for (const skill of customSkills) {
|
|
const shortDescription = skill.description.split(".")[0] || skill.description
|
|
lines.push(`- \`${skill.name}\`: ${shortDescription}`)
|
|
}
|
|
lines.push("")
|
|
}
|
|
}
|
|
|
|
if (agents.length > 0) {
|
|
const ultraworkAgentPriority = ["explore", "librarian", "plan", "oracle"]
|
|
const sortedAgents = [...agents].sort((left, right) => {
|
|
const leftIndex = ultraworkAgentPriority.indexOf(left.name)
|
|
const rightIndex = ultraworkAgentPriority.indexOf(right.name)
|
|
if (leftIndex === -1 && rightIndex === -1) {
|
|
return 0
|
|
}
|
|
if (leftIndex === -1) {
|
|
return 1
|
|
}
|
|
if (rightIndex === -1) {
|
|
return -1
|
|
}
|
|
return leftIndex - rightIndex
|
|
})
|
|
|
|
lines.push("**Agents** (for specialized consultation/exploration):")
|
|
for (const agent of sortedAgents) {
|
|
const shortDescription =
|
|
agent.description.length > 120
|
|
? `${agent.description.slice(0, 120)}...`
|
|
: agent.description
|
|
const suffix =
|
|
agent.name === "explore" || agent.name === "librarian" ? " (multiple)" : ""
|
|
lines.push(`- \`${agent.name}${suffix}\`: ${shortDescription}`)
|
|
}
|
|
}
|
|
|
|
return lines.join("\n")
|
|
}
|
|
|
|
export function buildAntiDuplicationSection(): string {
|
|
return `<Anti_Duplication>
|
|
## Anti-Duplication Rule (CRITICAL)
|
|
|
|
Once you delegate exploration to explore/librarian agents, **DO NOT perform the same search yourself**.
|
|
|
|
### What this means:
|
|
|
|
**FORBIDDEN:**
|
|
- After firing explore/librarian, manually grep/search for the same information
|
|
- Re-doing the research the agents were just tasked with
|
|
- "Just quickly checking" the same files the background agents are checking
|
|
|
|
**ALLOWED:**
|
|
- Continue with **non-overlapping work** - work that doesn't depend on the delegated research
|
|
- Work on unrelated parts of the codebase
|
|
- Preparation work (e.g., setting up files, configs) that can proceed independently
|
|
|
|
### Wait for Results Properly:
|
|
|
|
When you need the delegated results but they're not ready:
|
|
|
|
1. **End your response** - do NOT continue with work that depends on those results
|
|
2. **Wait for the completion notification** - the system will trigger your next turn
|
|
3. **Then** collect results via \`background_output(task_id="bg_...")\`
|
|
4. **Do NOT** impatiently re-search the same topics while waiting
|
|
|
|
### Why This Matters:
|
|
|
|
- **Wasted tokens**: Duplicate exploration wastes your context budget
|
|
- **Confusion**: You might contradict the agent's findings
|
|
- **Efficiency**: The whole point of delegation is parallel throughput
|
|
|
|
### Example:
|
|
|
|
\`\`\`typescript
|
|
// WRONG: After delegating, re-doing the search
|
|
task(subagent_type="explore", run_in_background=true, ...)
|
|
// Then immediately grep for the same thing yourself - FORBIDDEN
|
|
|
|
// CORRECT: Continue non-overlapping work
|
|
task(subagent_type="explore", run_in_background=true, ...)
|
|
// Work on a different, unrelated file while they search
|
|
// End your response and wait for the notification
|
|
\`\`\`
|
|
</Anti_Duplication>`
|
|
}
|