Rename agent parameter to subagent_type for consistency with delegate-task tool changes. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
137 lines
3.9 KiB
TypeScript
137 lines
3.9 KiB
TypeScript
import type { PluginInput } from "@opencode-ai/plugin"
|
|
|
|
export interface DelegateTaskErrorPattern {
|
|
pattern: string
|
|
errorType: string
|
|
fixHint: string
|
|
}
|
|
|
|
export const DELEGATE_TASK_ERROR_PATTERNS: DelegateTaskErrorPattern[] = [
|
|
{
|
|
pattern: "run_in_background",
|
|
errorType: "missing_run_in_background",
|
|
fixHint: "Add run_in_background=false (for delegation) or run_in_background=true (for parallel exploration)",
|
|
},
|
|
{
|
|
pattern: "load_skills",
|
|
errorType: "missing_load_skills",
|
|
fixHint: "Add load_skills=[] parameter (empty array if no skills needed). Note: Calling Skill tool does NOT populate this.",
|
|
},
|
|
{
|
|
pattern: "category OR subagent_type",
|
|
errorType: "mutual_exclusion",
|
|
fixHint: "Provide ONLY one of: category (e.g., 'general', 'quick') OR subagent_type (e.g., 'oracle', 'explore')",
|
|
},
|
|
{
|
|
pattern: "Must provide either category or subagent_type",
|
|
errorType: "missing_category_or_agent",
|
|
fixHint: "Add either category='general' OR subagent_type='explore'",
|
|
},
|
|
{
|
|
pattern: "Unknown category",
|
|
errorType: "unknown_category",
|
|
fixHint: "Use a valid category from the Available list in the error message",
|
|
},
|
|
{
|
|
pattern: "Agent name cannot be empty",
|
|
errorType: "empty_agent",
|
|
fixHint: "Provide a non-empty subagent_type value",
|
|
},
|
|
{
|
|
pattern: "Unknown agent",
|
|
errorType: "unknown_agent",
|
|
fixHint: "Use a valid agent from the Available agents list in the error message",
|
|
},
|
|
{
|
|
pattern: "Cannot call primary agent",
|
|
errorType: "primary_agent",
|
|
fixHint: "Primary agents cannot be called via delegate_task. Use a subagent like 'explore', 'oracle', or 'librarian'",
|
|
},
|
|
{
|
|
pattern: "Skills not found",
|
|
errorType: "unknown_skills",
|
|
fixHint: "Use valid skill names from the Available list in the error message",
|
|
},
|
|
]
|
|
|
|
export interface DetectedError {
|
|
errorType: string
|
|
originalOutput: string
|
|
}
|
|
|
|
export function detectDelegateTaskError(output: string): DetectedError | null {
|
|
if (!output.includes("[ERROR]") && !output.includes("Invalid arguments")) return null
|
|
|
|
for (const errorPattern of DELEGATE_TASK_ERROR_PATTERNS) {
|
|
if (output.includes(errorPattern.pattern)) {
|
|
return {
|
|
errorType: errorPattern.errorType,
|
|
originalOutput: output,
|
|
}
|
|
}
|
|
}
|
|
|
|
return null
|
|
}
|
|
|
|
function extractAvailableList(output: string): string | null {
|
|
const availableMatch = output.match(/Available[^:]*:\s*(.+)$/m)
|
|
return availableMatch ? availableMatch[1].trim() : null
|
|
}
|
|
|
|
export function buildRetryGuidance(errorInfo: DetectedError): string {
|
|
const pattern = DELEGATE_TASK_ERROR_PATTERNS.find(
|
|
(p) => p.errorType === errorInfo.errorType
|
|
)
|
|
|
|
if (!pattern) {
|
|
return `[delegate_task ERROR] Fix the error and retry with correct parameters.`
|
|
}
|
|
|
|
let guidance = `
|
|
[delegate_task CALL FAILED - IMMEDIATE RETRY REQUIRED]
|
|
|
|
**Error Type**: ${errorInfo.errorType}
|
|
**Fix**: ${pattern.fixHint}
|
|
`
|
|
|
|
const availableList = extractAvailableList(errorInfo.originalOutput)
|
|
if (availableList) {
|
|
guidance += `\n**Available Options**: ${availableList}\n`
|
|
}
|
|
|
|
guidance += `
|
|
**Action**: Retry delegate_task NOW with corrected parameters.
|
|
|
|
Example of CORRECT call:
|
|
\`\`\`
|
|
delegate_task(
|
|
description="Task description",
|
|
prompt="Detailed prompt...",
|
|
category="unspecified-low", // OR subagent_type="explore"
|
|
run_in_background=false,
|
|
load_skills=[]
|
|
)
|
|
\`\`\`
|
|
`
|
|
|
|
return guidance
|
|
}
|
|
|
|
export function createDelegateTaskRetryHook(_ctx: PluginInput) {
|
|
return {
|
|
"tool.execute.after": async (
|
|
input: { tool: string; sessionID: string; callID: string },
|
|
output: { title: string; output: string; metadata: unknown }
|
|
) => {
|
|
if (input.tool.toLowerCase() !== "delegate_task") return
|
|
|
|
const errorInfo = detectDelegateTaskError(output.output)
|
|
if (errorInfo) {
|
|
const guidance = buildRetryGuidance(errorInfo)
|
|
output.output += `\n${guidance}`
|
|
}
|
|
},
|
|
}
|
|
}
|