refactor: wave 1 - extract leaf modules, rename catch-all files, split index.ts hooks

- Split 25+ index.ts files into hook.ts + extracted modules
- Rename all catch-all utils.ts/helpers.ts to domain-specific names
- Split src/tools/lsp/ into ~15 focused modules
- Split src/tools/delegate-task/ into ~18 focused modules
- Separate shared types from implementation
- 155 files changed, 60+ new files created
- All typecheck clean, 61 tests pass
This commit is contained in:
YeonGyu-Kim
2026-02-08 13:57:26 +09:00
parent 7a15c1f3f9
commit df03300211
156 changed files with 7280 additions and 6771 deletions
+45
View File
@@ -0,0 +1,45 @@
import { DELEGATE_TASK_ERROR_PATTERNS, type DetectedError } from "./patterns"
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 `[task ERROR] Fix the error and retry with correct parameters.`
}
let guidance = `
[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 task NOW with corrected parameters.
Example of CORRECT call:
\`\`\`
task(
description="Task description",
prompt="Detailed prompt...",
category="unspecified-low", // OR subagent_type="explore"
run_in_background=false,
load_skills=[]
)
\`\`\`
`
return guidance
}
+21
View File
@@ -0,0 +1,21 @@
import type { PluginInput } from "@opencode-ai/plugin"
import { buildRetryGuidance } from "./guidance"
import { detectDelegateTaskError } from "./patterns"
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() !== "task") return
const errorInfo = detectDelegateTaskError(output.output)
if (errorInfo) {
const guidance = buildRetryGuidance(errorInfo)
output.output += `\n${guidance}`
}
},
}
}
+4 -136
View File
@@ -1,136 +1,4 @@
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 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 `[task ERROR] Fix the error and retry with correct parameters.`
}
let guidance = `
[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 task NOW with corrected parameters.
Example of CORRECT call:
\`\`\`
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() !== "task") return
const errorInfo = detectDelegateTaskError(output.output)
if (errorInfo) {
const guidance = buildRetryGuidance(errorInfo)
output.output += `\n${guidance}`
}
},
}
}
export type { DelegateTaskErrorPattern, DetectedError } from "./patterns"
export { DELEGATE_TASK_ERROR_PATTERNS, detectDelegateTaskError } from "./patterns"
export { buildRetryGuidance } from "./guidance"
export { createDelegateTaskRetryHook } from "./hook"
+77
View File
@@ -0,0 +1,77 @@
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 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
}