diff --git a/src/tools/delegate-task/tools-browser-provider.test.ts b/src/tools/delegate-task/tools-browser-provider.test.ts
new file mode 100644
index 000000000..27b920c08
--- /dev/null
+++ b/src/tools/delegate-task/tools-browser-provider.test.ts
@@ -0,0 +1,163 @@
+///
+
+import { mkdirSync, rmSync, writeFileSync } from "node:fs"
+import { tmpdir } from "node:os"
+import { join } from "node:path"
+import { clearSkillCache } from "../../features/opencode-skill-loader/skill-content"
+
+declare const require: NodeJS.Require
+
+const { afterEach, beforeEach, describe, expect, test } = require("bun:test")
+
+const SYSTEM_DEFAULT_MODEL = "anthropic/claude-sonnet-4-6"
+const TOOL_CONTEXT = {
+ sessionID: "parent-session",
+ messageID: "parent-message",
+ agent: "sisyphus",
+ abort: new AbortController().signal,
+}
+
+type EnvSnapshot = Record<"CLAUDE_CONFIG_DIR" | "OPENCODE_CONFIG_DIR", string | undefined>
+type PromptBody = { system?: string }
+type PromptInput = { body?: PromptBody }
+
+let envSnapshot: EnvSnapshot
+let testConfigDir: string | undefined
+
+function restoreEnvValue(key: keyof EnvSnapshot): void {
+ const value = envSnapshot[key]
+ if (value === undefined) {
+ delete process.env[key]
+ return
+ }
+
+ process.env[key] = value
+}
+
+function createAgentBrowserSkillFixture(content: string): void {
+ const unique = `delegate-agent-browser-${Date.now()}-${Math.random().toString(16).slice(2)}`
+ testConfigDir = join(tmpdir(), unique)
+ const skillDir = join(testConfigDir, "skills", "compound-engineering", "agent-browser")
+ mkdirSync(skillDir, { recursive: true })
+ writeFileSync(
+ join(skillDir, "SKILL.md"),
+ `---\nname: agent-browser\ndescription: Test-owned browser automation skill\n---\n${content}`,
+ )
+ process.env.CLAUDE_CONFIG_DIR = testConfigDir
+ process.env.OPENCODE_CONFIG_DIR = testConfigDir
+ clearSkillCache()
+}
+
+describe("delegate task browserProvider propagation", () => {
+ beforeEach(() => {
+ envSnapshot = {
+ CLAUDE_CONFIG_DIR: process.env.CLAUDE_CONFIG_DIR,
+ OPENCODE_CONFIG_DIR: process.env.OPENCODE_CONFIG_DIR,
+ }
+ testConfigDir = undefined
+ clearSkillCache()
+ })
+
+ afterEach(() => {
+ restoreEnvValue("CLAUDE_CONFIG_DIR")
+ restoreEnvValue("OPENCODE_CONFIG_DIR")
+ clearSkillCache()
+ if (testConfigDir !== undefined) {
+ rmSync(testConfigDir, { recursive: true, force: true })
+ }
+ })
+
+ test("resolves agent-browser builtin skill when browserProvider is passed", async () => {
+ // given
+ const { createDelegateTask } = require("./tools")
+ let promptBody: PromptBody | undefined
+ const promptMock = async (input: PromptInput) => {
+ promptBody = input.body
+ return { data: {} }
+ }
+ const mockClient = {
+ app: { agents: async () => ({ data: [] }) },
+ config: { get: async () => ({ data: { model: SYSTEM_DEFAULT_MODEL } }) },
+ session: {
+ get: async () => ({ data: { directory: "/project" } }),
+ create: async () => ({ data: { id: "ses_browser_provider" } }),
+ prompt: promptMock,
+ promptAsync: promptMock,
+ messages: async () => ({
+ data: [{ info: { role: "assistant" }, parts: [{ type: "text", text: "Done" }] }],
+ }),
+ status: async () => ({ data: {} }),
+ },
+ }
+ const tool = createDelegateTask({
+ manager: { launch: async () => ({}) },
+ client: mockClient,
+ browserProvider: "agent-browser",
+ })
+
+ // when
+ await tool.execute(
+ {
+ description: "Test browserProvider propagation",
+ prompt: "Do something",
+ category: "ultrabrain",
+ run_in_background: false,
+ load_skills: ["agent-browser"],
+ },
+ TOOL_CONTEXT,
+ )
+
+ // then
+ const system = promptBody?.system ?? ""
+ expect(system).toContain("agent-browser")
+ expect(system).toContain("")
+ expect(system.startsWith("")).toBe(false)
+ }, { timeout: 20000 })
+
+ test("resolves discovered agent-browser skill by short name without browserProvider", async () => {
+ // given
+ const fixtureContent = "Test-owned agent-browser fixture content"
+ createAgentBrowserSkillFixture(fixtureContent)
+ const { createDelegateTask } = require("./tools")
+ let promptBody: PromptBody | undefined
+ const promptMock = async (input: PromptInput) => {
+ promptBody = input.body
+ return { data: {} }
+ }
+ const mockClient = {
+ app: { agents: async () => ({ data: [] }) },
+ config: { get: async () => ({ data: { model: SYSTEM_DEFAULT_MODEL } }) },
+ session: {
+ get: async () => ({ data: { directory: "/project" } }),
+ create: async () => ({ data: { id: "ses_no_browser_provider" } }),
+ prompt: promptMock,
+ promptAsync: promptMock,
+ messages: async () => ({
+ data: [{ info: { role: "assistant" }, parts: [{ type: "text", text: "Done" }] }],
+ }),
+ status: async () => ({ data: {} }),
+ },
+ }
+ const tool = createDelegateTask({
+ manager: { launch: async () => ({}) },
+ client: mockClient,
+ })
+
+ // when
+ const result = await tool.execute(
+ {
+ description: "Test missing browserProvider",
+ prompt: "Do something",
+ category: "ultrabrain",
+ run_in_background: false,
+ load_skills: ["agent-browser"],
+ },
+ TOOL_CONTEXT,
+ )
+
+ // then
+ expect(result).toContain("Task completed")
+ expect(result).toContain("ses_no_browser_provider")
+ expect(promptBody?.system).toContain(fixtureContent)
+ })
+})
diff --git a/src/tools/delegate-task/tools.test.ts b/src/tools/delegate-task/tools.test.ts
index 0df9e1d24..ee61f4699 100644
--- a/src/tools/delegate-task/tools.test.ts
+++ b/src/tools/delegate-task/tools.test.ts
@@ -696,7 +696,7 @@ describe("sisyphus-task", () => {
//#given - manager.launch returns before sessionID is available
const { createDelegateTask } = require("./tools")
- const tasks = new Map()
+ const tasks = new Map()
const mockManager = {
getTask: (id: string) => tasks.get(id),
launch: async () => {
@@ -3222,119 +3222,6 @@ describe("sisyphus-task", () => {
})
})
- describe("browserProvider propagation", () => {
- test("should resolve agent-browser skill when browserProvider is passed", async () => {
- // given - task configured with browserProvider: "agent-browser"
- const { createDelegateTask } = require("./tools")
- let promptBody: any
-
- const mockManager = { launch: async () => ({}) }
-
- const promptMock = async (input: any) => {
- promptBody = input.body
- return { data: {} }
- }
-
- const mockClient = {
- app: { agents: async () => ({ data: [] }) },
- config: { get: async () => ({ data: { model: SYSTEM_DEFAULT_MODEL } }) },
- session: {
- get: async () => ({ data: { directory: "/project" } }),
- create: async () => ({ data: { id: "ses_browser_provider" } }),
- prompt: promptMock,
- promptAsync: promptMock,
- messages: async () => ({
- data: [{ info: { role: "assistant" }, parts: [{ type: "text", text: "Done" }] }]
- }),
- status: async () => ({ data: {} }),
- },
- }
-
- // Pass browserProvider to createDelegateTask
- const tool = createDelegateTask({
- manager: mockManager,
- client: mockClient,
- browserProvider: "agent-browser",
- })
-
- const toolContext = {
- sessionID: "parent-session",
- messageID: "parent-message",
- agent: "sisyphus",
- abort: new AbortController().signal,
- }
-
- // when - request agent-browser skill
- await tool.execute(
- {
- description: "Test browserProvider propagation",
- prompt: "Do something",
- category: "ultrabrain",
- run_in_background: false,
- load_skills: ["agent-browser"],
- },
- toolContext
- )
-
- // then - agent-browser skill should be resolved
- expect(promptBody).toBeDefined()
- expect(promptBody.system).toBeDefined()
- expect(promptBody.system).toContain("")
- expect(String(promptBody.system).startsWith("")).toBe(false)
- }, { timeout: 20000 })
-
- test("should resolve agent-browser skill even when browserProvider is not set", async () => {
- // given - delegate_task without browserProvider
- const { createDelegateTask } = require("./tools")
- const mockManager = { launch: async () => ({}) }
- const mockClient = {
- app: { agents: async () => ({ data: [] }) },
- config: { get: async () => ({ data: { model: SYSTEM_DEFAULT_MODEL } }) },
- session: {
- get: async () => ({ data: { directory: "/project" } }),
- create: async () => ({ data: { id: "ses_no_browser_provider" } }),
- prompt: async () => {
- return { data: {} }
- },
- promptAsync: async () => ({ data: {} }),
- messages: async () => ({
- data: [{ info: { role: "assistant" }, parts: [{ type: "text", text: "Done" }] }]
- }),
- status: async () => ({ data: {} }),
- },
- }
-
- // No browserProvider passed
- const tool = createDelegateTask({
- manager: mockManager,
- client: mockClient,
- })
-
- const toolContext = {
- sessionID: "parent-session",
- messageID: "parent-message",
- agent: "sisyphus",
- abort: new AbortController().signal,
- }
-
- // when - request agent-browser skill without browserProvider
- const result = await tool.execute(
- {
- description: "Test missing browserProvider",
- prompt: "Do something",
- category: "ultrabrain",
- run_in_background: false,
- load_skills: ["agent-browser"],
- },
- toolContext
- )
-
- // then - the external compound-engineering/agent-browser skill can resolve by unique short name
- expect(result).toContain("Task completed")
- expect(result).toContain("ses_no_browser_provider")
- })
- })
-
describe("delegate task with short skill name", () => {
let envCleanup: Record