fix(subagent): remove permission.question=deny override that caused zombie sessions

Child session creation was injecting permission: { question: 'deny' } which
conflicted with OpenCode's child session permission handling, causing subagent
sessions to hang with 0 messages after creation (zombie state).

Remove the permission override from all session creators (BackgroundManager,
sync-session-creator, call-omo-agent) and rely on prompt-level tool restrictions
(tools.question=false) to maintain the intended policy.

Closes #1711
This commit is contained in:
YeonGyu-Kim
2026-02-11 11:55:56 +09:00
parent 73c0fc9bb5
commit cd0e2e5190
12 changed files with 106 additions and 33 deletions
@@ -0,0 +1,50 @@
import { describe, expect, test } from "bun:test"
import { createOrGetSession } from "./session-creator"
import { _resetForTesting, subagentSessions } from "../../features/claude-code-session-state"
describe("call-omo-agent createOrGetSession", () => {
test("creates child session without overriding permission and tracks it as subagent session", async () => {
// given
_resetForTesting()
const createCalls: Array<unknown> = []
const ctx = {
directory: "/project",
client: {
session: {
get: async () => ({ data: { directory: "/parent" } }),
create: async (args: unknown) => {
createCalls.push(args)
return { data: { id: "ses_child" } }
},
},
},
}
const toolContext = {
sessionID: "ses_parent",
messageID: "msg_parent",
agent: "sisyphus",
abort: new AbortController().signal,
}
const args = {
description: "test",
prompt: "hello",
subagent_type: "explore",
run_in_background: true,
}
// when
const result = await createOrGetSession(args as any, toolContext as any, ctx as any)
// then
expect(result).toEqual({ sessionID: "ses_child", isNew: true })
expect(createCalls).toHaveLength(1)
const createBody = (createCalls[0] as any)?.body
expect(createBody?.parentID).toBe("ses_parent")
expect(createBody?.permission).toBeUndefined()
expect(subagentSessions.has("ses_child")).toBe(true)
})
})
+2 -3
View File
@@ -1,5 +1,6 @@
import type { CallOmoAgentArgs } from "./types"
import type { PluginInput } from "@opencode-ai/plugin"
import { subagentSessions } from "../../features/claude-code-session-state"
import { log } from "../../shared"
export async function createOrGetSession(
@@ -38,9 +39,6 @@ export async function createOrGetSession(
body: {
parentID: toolContext.sessionID,
title: `${args.description} (@${args.subagent_type} subagent)`,
permission: [
{ permission: "question", action: "deny" as const, pattern: "*" },
],
} as any,
query: {
directory: parentDirectory,
@@ -65,6 +63,7 @@ Original error: ${createResult.error}`)
const sessionID = createResult.data.id
log(`[call_omo_agent] Created session: ${sessionID}`)
subagentSessions.add(sessionID)
return { sessionID, isNew: true }
}
}
@@ -0,0 +1,47 @@
import { describe, expect, test } from "bun:test"
import { resolveOrCreateSessionId } from "./subagent-session-creator"
import { _resetForTesting, subagentSessions } from "../../features/claude-code-session-state"
describe("call-omo-agent resolveOrCreateSessionId", () => {
test("tracks newly created child session as subagent session", async () => {
// given
_resetForTesting()
const createCalls: Array<unknown> = []
const ctx = {
directory: "/project",
client: {
session: {
get: async () => ({ data: { directory: "/parent" } }),
create: async (args: unknown) => {
createCalls.push(args)
return { data: { id: "ses_child_sync" } }
},
},
},
}
const args = {
description: "sync test",
prompt: "hello",
subagent_type: "explore",
run_in_background: false,
}
const toolContext = {
sessionID: "ses_parent",
messageID: "msg_parent",
agent: "sisyphus",
abort: new AbortController().signal,
}
// when
const result = await resolveOrCreateSessionId(ctx as any, args as any, toolContext as any)
// then
expect(result).toEqual({ ok: true, sessionID: "ses_child_sync" })
expect(createCalls).toHaveLength(1)
expect(subagentSessions.has("ses_child_sync")).toBe(true)
})
})
@@ -1,5 +1,6 @@
import type { PluginInput } from "@opencode-ai/plugin"
import { log } from "../../shared"
import { subagentSessions } from "../../features/claude-code-session-state"
import type { CallOmoAgentArgs } from "./types"
import type { ToolContextWithMetadata } from "./tool-context-with-metadata"
@@ -63,5 +64,6 @@ Original error: ${createResult.error}`,
const sessionID = createResult.data.id
log(`[call_omo_agent] Created session: ${sessionID}`)
subagentSessions.add(sessionID)
return { ok: true, sessionID }
}
@@ -13,6 +13,7 @@ export async function promptSubagentSession(
tools: {
...getAgentToolRestrictions(options.agent),
task: false,
question: false,
},
parts: [{ type: "text", text: options.prompt }],
},
@@ -13,9 +13,6 @@ export async function createSyncSession(
body: {
parentID: input.parentSessionID,
title: `${input.description} (@${input.agentToUse} subagent)`,
permission: [
{ permission: "question", action: "deny" as const, pattern: "*" },
],
} as any,
query: {
directory: parentDirectory,