Files
oh-my-openagent/src/plugin-handlers/tool-config-handler.test.ts
Chocothin 65bc742881 fix(tool-config): respect question permission from OPENCODE_CONFIG_CONTENT
applyToolConfig() unconditionally set question permission based only on
OPENCODE_CLI_RUN_MODE, ignoring the question:deny already configured via
OPENCODE_CONFIG_CONTENT. This caused agents to hang in headless environments
(e.g. Maestro Auto Run) where the host sets question:deny but does not
know about the plugin-internal OPENCODE_CLI_RUN_MODE variable.

Read permission.question from OPENCODE_CONFIG_CONTENT and give it highest
priority: config deny > CLI run mode deny > default allow.
2026-03-01 22:49:47 +09:00

187 lines
5.9 KiB
TypeScript

import { describe, it, expect, beforeEach, afterEach } from "bun:test"
import { applyToolConfig } from "./tool-config-handler"
import type { OhMyOpenCodeConfig } from "../config"
function createParams(overrides: {
taskSystem?: boolean
agents?: string[]
}) {
const agentResult: Record<string, { permission?: Record<string, unknown> }> = {}
for (const agent of overrides.agents ?? []) {
agentResult[agent] = { permission: {} }
}
return {
config: { tools: {}, permission: {} } as Record<string, unknown>,
pluginConfig: {
experimental: { task_system: overrides.taskSystem ?? false },
} as OhMyOpenCodeConfig,
agentResult: agentResult as Record<string, unknown>,
}
}
describe("applyToolConfig", () => {
describe("#given task_system is enabled", () => {
describe("#when applying tool config", () => {
it("#then should deny todowrite and todoread globally", () => {
const params = createParams({ taskSystem: true })
applyToolConfig(params)
const tools = params.config.tools as Record<string, unknown>
expect(tools.todowrite).toBe(false)
expect(tools.todoread).toBe(false)
})
it.each([
"atlas",
"sisyphus",
"hephaestus",
"prometheus",
"sisyphus-junior",
])("#then should deny todo tools for %s agent", (agentName) => {
const params = createParams({
taskSystem: true,
agents: [agentName],
})
applyToolConfig(params)
const agent = params.agentResult[agentName] as {
permission: Record<string, unknown>
}
expect(agent.permission.todowrite).toBe("deny")
expect(agent.permission.todoread).toBe("deny")
})
})
})
describe("#given OPENCODE_CONFIG_CONTENT has question set to deny", () => {
let originalConfigContent: string | undefined
let originalCliRunMode: string | undefined
beforeEach(() => {
originalConfigContent = process.env.OPENCODE_CONFIG_CONTENT
originalCliRunMode = process.env.OPENCODE_CLI_RUN_MODE
})
afterEach(() => {
if (originalConfigContent === undefined) {
delete process.env.OPENCODE_CONFIG_CONTENT
} else {
process.env.OPENCODE_CONFIG_CONTENT = originalConfigContent
}
if (originalCliRunMode === undefined) {
delete process.env.OPENCODE_CLI_RUN_MODE
} else {
process.env.OPENCODE_CLI_RUN_MODE = originalCliRunMode
}
})
describe("#when config explicitly denies question permission", () => {
it.each(["sisyphus", "hephaestus", "prometheus"])(
"#then should deny question for %s even without CLI_RUN_MODE",
(agentName) => {
process.env.OPENCODE_CONFIG_CONTENT = JSON.stringify({
permission: { question: "deny" },
})
delete process.env.OPENCODE_CLI_RUN_MODE
const params = createParams({ agents: [agentName] })
applyToolConfig(params)
const agent = params.agentResult[agentName] as {
permission: Record<string, unknown>
}
expect(agent.permission.question).toBe("deny")
},
)
})
describe("#when config does not deny question permission", () => {
it.each(["sisyphus", "hephaestus", "prometheus"])(
"#then should allow question for %s in interactive mode",
(agentName) => {
process.env.OPENCODE_CONFIG_CONTENT = JSON.stringify({
permission: { question: "allow" },
})
delete process.env.OPENCODE_CLI_RUN_MODE
const params = createParams({ agents: [agentName] })
applyToolConfig(params)
const agent = params.agentResult[agentName] as {
permission: Record<string, unknown>
}
expect(agent.permission.question).toBe("allow")
},
)
})
describe("#when CLI_RUN_MODE is true and config does not deny", () => {
it.each(["sisyphus", "hephaestus", "prometheus"])(
"#then should deny question for %s via CLI_RUN_MODE",
(agentName) => {
process.env.OPENCODE_CONFIG_CONTENT = JSON.stringify({
permission: {},
})
process.env.OPENCODE_CLI_RUN_MODE = "true"
const params = createParams({ agents: [agentName] })
applyToolConfig(params)
const agent = params.agentResult[agentName] as {
permission: Record<string, unknown>
}
expect(agent.permission.question).toBe("deny")
},
)
})
describe("#when config deny overrides CLI_RUN_MODE allow", () => {
it.each(["sisyphus", "hephaestus", "prometheus"])(
"#then should deny question for %s when config says deny regardless of CLI_RUN_MODE",
(agentName) => {
process.env.OPENCODE_CONFIG_CONTENT = JSON.stringify({
permission: { question: "deny" },
})
process.env.OPENCODE_CLI_RUN_MODE = "false"
const params = createParams({ agents: [agentName] })
applyToolConfig(params)
const agent = params.agentResult[agentName] as {
permission: Record<string, unknown>
}
expect(agent.permission.question).toBe("deny")
},
)
})
})
describe("#given task_system is disabled", () => {
describe("#when applying tool config", () => {
it.each([
"atlas",
"sisyphus",
"hephaestus",
"prometheus",
"sisyphus-junior",
])("#then should NOT deny todo tools for %s agent", (agentName) => {
const params = createParams({
taskSystem: false,
agents: [agentName],
})
applyToolConfig(params)
const agent = params.agentResult[agentName] as {
permission: Record<string, unknown>
}
expect(agent.permission.todowrite).toBeUndefined()
expect(agent.permission.todoread).toBeUndefined()
})
})
})
})