fix(background-task): gracefully handle agent not found errors

When an invalid or unregistered agent is passed to background_task or
call_omo_agent, OpenCode crashes with "TypeError: undefined is not an
object (evaluating 'agent.name')". This fix:

- Validates agent parameter is not empty before launching
- Catches prompt errors and returns friendly error message
- Notifies parent session when background task fails
- Improves error message to guide user on resolution

Fixes #37

🤖 GENERATED WITH ASSISTANCE OF [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode)
This commit is contained in:
YeonGyu-Kim
2025-12-14 01:22:28 +09:00
parent 53d8cf12f2
commit b00b8238f4
3 changed files with 38 additions and 14 deletions

View File

@@ -39,6 +39,10 @@ export class BackgroundManager {
} }
async launch(input: LaunchInput): Promise<BackgroundTask> { async launch(input: LaunchInput): Promise<BackgroundTask> {
if (!input.agent || input.agent.trim() === "") {
throw new Error("Agent parameter is required")
}
const createResult = await this.client.session.create({ const createResult = await this.client.session.create({
body: { body: {
parentID: input.parentSessionID, parentID: input.parentSessionID,
@@ -71,7 +75,7 @@ export class BackgroundManager {
this.tasks.set(task.id, task) this.tasks.set(task.id, task)
this.startPolling() this.startPolling()
log("[background-agent] Launching task:", { taskId: task.id, sessionID }) log("[background-agent] Launching task:", { taskId: task.id, sessionID, agent: input.agent })
this.client.session.promptAsync({ this.client.session.promptAsync({
path: { id: sessionID }, path: { id: sessionID },
@@ -90,8 +94,15 @@ export class BackgroundManager {
const existingTask = this.findBySession(sessionID) const existingTask = this.findBySession(sessionID)
if (existingTask) { if (existingTask) {
existingTask.status = "error" existingTask.status = "error"
existingTask.error = String(error) const errorMessage = error instanceof Error ? error.message : String(error)
if (errorMessage.includes("agent.name") || errorMessage.includes("undefined")) {
existingTask.error = `Agent "${input.agent}" not found. Make sure the agent is registered in your opencode.json or provided by a plugin.`
} else {
existingTask.error = errorMessage
}
existingTask.completedAt = new Date() existingTask.completedAt = new Date()
this.markForNotification(existingTask)
this.notifyParentSession(existingTask)
} }
}) })

View File

@@ -26,14 +26,18 @@ export function createBackgroundTask(manager: BackgroundManager) {
args: { args: {
description: tool.schema.string().describe("Short task description (shown in status)"), description: tool.schema.string().describe("Short task description (shown in status)"),
prompt: tool.schema.string().describe("Full detailed prompt for the agent"), prompt: tool.schema.string().describe("Full detailed prompt for the agent"),
agent: tool.schema.string().describe("Agent type to use (any agent allowed)"), agent: tool.schema.string().describe("Agent type to use (any registered agent)"),
}, },
async execute(args: BackgroundTaskArgs, toolContext) { async execute(args: BackgroundTaskArgs, toolContext) {
if (!args.agent || args.agent.trim() === "") {
return `❌ Agent parameter is required. Please specify which agent to use (e.g., "explore", "librarian", "build", etc.)`
}
try { try {
const task = await manager.launch({ const task = await manager.launch({
description: args.description, description: args.description,
prompt: args.prompt, prompt: args.prompt,
agent: args.agent, agent: args.agent.trim(),
parentSessionID: toolContext.sessionID, parentSessionID: toolContext.sessionID,
parentMessageID: toolContext.messageID, parentMessageID: toolContext.messageID,
}) })

View File

@@ -114,17 +114,26 @@ async function executeSync(
log(`[call_omo_agent] Sending prompt to session ${sessionID}`) log(`[call_omo_agent] Sending prompt to session ${sessionID}`)
log(`[call_omo_agent] Prompt text:`, args.prompt.substring(0, 100)) log(`[call_omo_agent] Prompt text:`, args.prompt.substring(0, 100))
await ctx.client.session.prompt({ try {
path: { id: sessionID }, await ctx.client.session.prompt({
body: { path: { id: sessionID },
agent: args.subagent_type, body: {
tools: { agent: args.subagent_type,
task: false, tools: {
call_omo_agent: false, task: false,
call_omo_agent: false,
},
parts: [{ type: "text", text: args.prompt }],
}, },
parts: [{ type: "text", text: args.prompt }], })
}, } catch (error) {
}) const errorMessage = error instanceof Error ? error.message : String(error)
log(`[call_omo_agent] Prompt error:`, errorMessage)
if (errorMessage.includes("agent.name") || errorMessage.includes("undefined")) {
return `Error: Agent "${args.subagent_type}" not found. Make sure the agent is registered in your opencode.json or provided by a plugin.\n\n<task_metadata>\nsession_id: ${sessionID}\n</task_metadata>`
}
return `Error: Failed to send prompt: ${errorMessage}\n\n<task_metadata>\nsession_id: ${sessionID}\n</task_metadata>`
}
log(`[call_omo_agent] Prompt sent, fetching messages...`) log(`[call_omo_agent] Prompt sent, fetching messages...`)