Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/plugin/tool-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export function createToolRegistry(args: {
const { ctx, pluginConfig, managers, skillContext, availableCategories } = args

const backgroundTools = createBackgroundTools(managers.backgroundManager, ctx.client)
const callOmoAgent = createCallOmoAgent(ctx, managers.backgroundManager)
const callOmoAgent = createCallOmoAgent(ctx, managers.backgroundManager, pluginConfig.disabled_agents ?? [])

const isMultimodalLookerEnabled = !(pluginConfig.disabled_agents ?? []).some(
(agent) => agent.toLowerCase() === "multimodal-looker",
Expand Down
102 changes: 102 additions & 0 deletions src/tools/call-omo-agent/tools.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import { describe, test, expect, mock } from "bun:test"
import type { PluginInput } from "@opencode-ai/plugin"
import type { BackgroundManager } from "../../features/background-agent"
import { createCallOmoAgent } from "./tools"

describe("createCallOmoAgent", () => {
const mockCtx = {
client: {},
directory: "/test",
} as unknown as PluginInput

const mockBackgroundManager = {
launch: mock(() => Promise.resolve({
id: "test-task-id",
sessionID: null,
description: "Test task",
agent: "test-agent",
status: "pending",
})),
} as unknown as BackgroundManager

test("should reject agent in disabled_agents list", async () => {
//#given
const toolDef = createCallOmoAgent(mockCtx, mockBackgroundManager, ["explore"])
const executeFunc = toolDef.execute as Function

//#when
const result = await executeFunc(
{
description: "Test",
prompt: "Test prompt",
subagent_type: "explore",
run_in_background: true,
},
{ sessionID: "test", messageID: "msg", agent: "test", abort: new AbortController().signal }
)

//#then
expect(result).toContain("disabled via disabled_agents")
})

test("should reject agent in disabled_agents list with case-insensitive matching", async () => {
//#given
const toolDef = createCallOmoAgent(mockCtx, mockBackgroundManager, ["Explore"])
const executeFunc = toolDef.execute as Function

//#when
const result = await executeFunc(
{
description: "Test",
prompt: "Test prompt",
subagent_type: "explore",
run_in_background: true,
},
{ sessionID: "test", messageID: "msg", agent: "test", abort: new AbortController().signal }
)

//#then
expect(result).toContain("disabled via disabled_agents")
})

test("should allow agent not in disabled_agents list", async () => {
//#given
const toolDef = createCallOmoAgent(mockCtx, mockBackgroundManager, ["librarian"])
const executeFunc = toolDef.execute as Function

//#when
const result = await executeFunc(
{
description: "Test",
prompt: "Test prompt",
subagent_type: "explore",
run_in_background: true,
},
{ sessionID: "test", messageID: "msg", agent: "test", abort: new AbortController().signal }
)

//#then
// Should not contain disabled error - may fail for other reasons but disabled check should pass
expect(result).not.toContain("disabled via disabled_agents")
})

test("should allow all agents when disabled_agents is empty", async () => {
//#given
const toolDef = createCallOmoAgent(mockCtx, mockBackgroundManager, [])
const executeFunc = toolDef.execute as Function

//#when
const result = await executeFunc(
{
description: "Test",
prompt: "Test prompt",
subagent_type: "explore",
run_in_background: true,
},
{ sessionID: "test", messageID: "msg", agent: "test", abort: new AbortController().signal }
)

//#then
expect(result).not.toContain("disabled via disabled_agents")
})
})
8 changes: 7 additions & 1 deletion src/tools/call-omo-agent/tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import { executeSync } from "./sync-executor"

export function createCallOmoAgent(
ctx: PluginInput,
backgroundManager: BackgroundManager
backgroundManager: BackgroundManager,
disabledAgents: string[] = []
): ToolDefinition {
const agentDescriptions = ALLOWED_AGENTS.map(
(name) => `- ${name}: Specialized agent for ${name} tasks`
Expand Down Expand Up @@ -44,6 +45,11 @@ export function createCallOmoAgent(
const normalizedAgent = args.subagent_type.toLowerCase() as AllowedAgentType
args = { ...args, subagent_type: normalizedAgent }

// Check if agent is disabled
if (disabledAgents.some((disabled) => disabled.toLowerCase() === normalizedAgent)) {
return `Error: Agent "${normalizedAgent}" is disabled via disabled_agents configuration. Remove it from disabled_agents in your oh-my-opencode.json to use it.`
}

if (args.run_in_background) {
if (args.session_id) {
return `Error: session_id is not supported in background mode. Use run_in_background=false to continue an existing session.`
Expand Down