diff --git a/.fork-features/manifest.json b/.fork-features/manifest.json index 4a0679718e5..f0c55b0aac6 100644 --- a/.fork-features/manifest.json +++ b/.fork-features/manifest.json @@ -26,7 +26,8 @@ "cleanupSessionMaps", "formatCompletedTasksForInjection", "TaskTool", - "CheckTaskTool" + "CheckTaskTool", + "Agent.get(task.agent)" ], "tests": ["packages/opencode/test/tool/check_task.test.ts"], "upstreamTracking": { diff --git a/packages/opencode/src/session/prompt.ts b/packages/opencode/src/session/prompt.ts index b562a3e7711..fd35af14e1d 100644 --- a/packages/opencode/src/session/prompt.ts +++ b/packages/opencode/src/session/prompt.ts @@ -326,7 +326,8 @@ export namespace SessionPrompt { // pending subtask // TODO: centralize "invoke tool" logic if (task?.type === "subtask") { - const taskTool = await TaskTool.init() + const agentInfo = await Agent.get(task.agent) + const taskTool = await TaskTool.init({ agent: agentInfo }) const taskModel = task.model ? await Provider.getModel(task.model.providerID, task.model.modelID) : model const assistantMessage = (await Session.updateMessage({ id: Identifier.ascending("message"), diff --git a/packages/opencode/test/agent/agent.test.ts b/packages/opencode/test/agent/agent.test.ts index 024e2edac10..944f0b0529c 100644 --- a/packages/opencode/test/agent/agent.test.ts +++ b/packages/opencode/test/agent/agent.test.ts @@ -552,8 +552,10 @@ description: Permission skill. }, }) } finally { - process.env.OPENCODE_TEST_HOME = home - process.env.OPENCODE_DISABLE_GLOBAL_SKILLS = originalDisableGlobalSkills + if (home === undefined) delete process.env.OPENCODE_TEST_HOME + else process.env.OPENCODE_TEST_HOME = home + if (originalDisableGlobalSkills === undefined) delete process.env.OPENCODE_DISABLE_GLOBAL_SKILLS + else process.env.OPENCODE_DISABLE_GLOBAL_SKILLS = originalDisableGlobalSkills } }) diff --git a/packages/opencode/test/preload.ts b/packages/opencode/test/preload.ts index 474aae6cfdf..60926c3a765 100644 --- a/packages/opencode/test/preload.ts +++ b/packages/opencode/test/preload.ts @@ -31,11 +31,13 @@ mock.module("../src/bun/index", () => ({ }, })) -// Mock builtin plugins to prevent import errors -const mockPlugin = () => ({}) +// Mock builtin plugins to prevent import errors during module resolution. +// Mocks match real package export shapes for forward-compatibility. +// copilot-auth is skipped at runtime (plugin/index.ts line 56) but mocked defensively. +const mockPlugin = async () => ({}) mock.module("opencode-copilot-auth", () => ({ default: mockPlugin })) mock.module("opencode-anthropic-auth", () => ({ default: mockPlugin })) -mock.module("@gitlab/opencode-gitlab-auth", () => ({ default: mockPlugin })) +mock.module("@gitlab/opencode-gitlab-auth", () => ({ default: mockPlugin, gitlabAuthPlugin: mockPlugin })) // Mock optional SDK dependencies that aren't installed but are dynamically imported mock.module("@aws-sdk/credential-providers", () => ({ diff --git a/packages/opencode/test/skill/skill.test.ts b/packages/opencode/test/skill/skill.test.ts index 13cb466294f..10a8972dabb 100644 --- a/packages/opencode/test/skill/skill.test.ts +++ b/packages/opencode/test/skill/skill.test.ts @@ -58,7 +58,8 @@ Instructions here. }, }) } finally { - process.env.OPENCODE_DISABLE_CLAUDE_CODE_SKILLS = originalDisableClaudeSkills + if (originalDisableClaudeSkills === undefined) delete process.env.OPENCODE_DISABLE_CLAUDE_CODE_SKILLS + else process.env.OPENCODE_DISABLE_CLAUDE_CODE_SKILLS = originalDisableClaudeSkills } }) @@ -99,8 +100,10 @@ description: Skill for dirs test. }, }) } finally { - process.env.OPENCODE_TEST_HOME = home - process.env.OPENCODE_DISABLE_GLOBAL_SKILLS = originalDisableGlobalSkills + if (home === undefined) delete process.env.OPENCODE_TEST_HOME + else process.env.OPENCODE_TEST_HOME = home + if (originalDisableGlobalSkills === undefined) delete process.env.OPENCODE_DISABLE_GLOBAL_SKILLS + else process.env.OPENCODE_DISABLE_GLOBAL_SKILLS = originalDisableGlobalSkills } }) @@ -147,7 +150,8 @@ description: Second test skill. }, }) } finally { - process.env.OPENCODE_DISABLE_CLAUDE_CODE_SKILLS = originalDisableClaudeSkills + if (originalDisableClaudeSkills === undefined) delete process.env.OPENCODE_DISABLE_CLAUDE_CODE_SKILLS + else process.env.OPENCODE_DISABLE_CLAUDE_CODE_SKILLS = originalDisableClaudeSkills } }) @@ -178,7 +182,8 @@ Just some content without YAML frontmatter. }, }) } finally { - process.env.OPENCODE_DISABLE_CLAUDE_CODE_SKILLS = originalDisableClaudeSkills + if (originalDisableClaudeSkills === undefined) delete process.env.OPENCODE_DISABLE_CLAUDE_CODE_SKILLS + else process.env.OPENCODE_DISABLE_CLAUDE_CODE_SKILLS = originalDisableClaudeSkills } }) @@ -217,8 +222,10 @@ description: A skill in the .claude/skills directory. }, }) } finally { - process.env.OPENCODE_DISABLE_CLAUDE_CODE = originalDisableClaudeCode - process.env.OPENCODE_DISABLE_CLAUDE_CODE_SKILLS = originalDisableClaudeSkills + if (originalDisableClaudeCode === undefined) delete process.env.OPENCODE_DISABLE_CLAUDE_CODE + else process.env.OPENCODE_DISABLE_CLAUDE_CODE = originalDisableClaudeCode + if (originalDisableClaudeSkills === undefined) delete process.env.OPENCODE_DISABLE_CLAUDE_CODE_SKILLS + else process.env.OPENCODE_DISABLE_CLAUDE_CODE_SKILLS = originalDisableClaudeSkills } }) @@ -248,9 +255,12 @@ test("discovers global skills from ~/.claude/skills/ directory", async () => { }, }) } finally { - process.env.OPENCODE_TEST_HOME = originalHome - process.env.OPENCODE_DISABLE_CLAUDE_CODE = originalDisableClaudeCode - process.env.OPENCODE_DISABLE_CLAUDE_CODE_SKILLS = originalDisableClaudeSkills + if (originalHome === undefined) delete process.env.OPENCODE_TEST_HOME + else process.env.OPENCODE_TEST_HOME = originalHome + if (originalDisableClaudeCode === undefined) delete process.env.OPENCODE_DISABLE_CLAUDE_CODE + else process.env.OPENCODE_DISABLE_CLAUDE_CODE = originalDisableClaudeCode + if (originalDisableClaudeSkills === undefined) delete process.env.OPENCODE_DISABLE_CLAUDE_CODE_SKILLS + else process.env.OPENCODE_DISABLE_CLAUDE_CODE_SKILLS = originalDisableClaudeSkills } }) @@ -269,7 +279,8 @@ test("returns empty array when no skills exist", async () => { }, }) } finally { - process.env.OPENCODE_DISABLE_CLAUDE_CODE_SKILLS = originalDisableClaudeSkills + if (originalDisableClaudeSkills === undefined) delete process.env.OPENCODE_DISABLE_CLAUDE_CODE_SKILLS + else process.env.OPENCODE_DISABLE_CLAUDE_CODE_SKILLS = originalDisableClaudeSkills } }) @@ -306,7 +317,8 @@ description: A skill in the .agents/skills directory. }, }) } finally { - process.env.OPENCODE_DISABLE_CLAUDE_CODE_SKILLS = originalDisableClaudeSkills + if (originalDisableClaudeSkills === undefined) delete process.env.OPENCODE_DISABLE_CLAUDE_CODE_SKILLS + else process.env.OPENCODE_DISABLE_CLAUDE_CODE_SKILLS = originalDisableClaudeSkills } }) @@ -348,8 +360,10 @@ This skill is loaded from the global home directory. }, }) } finally { - process.env.OPENCODE_TEST_HOME = originalHome - process.env.OPENCODE_DISABLE_CLAUDE_CODE_SKILLS = originalDisableClaudeSkills + if (originalHome === undefined) delete process.env.OPENCODE_TEST_HOME + else process.env.OPENCODE_TEST_HOME = originalHome + if (originalDisableClaudeSkills === undefined) delete process.env.OPENCODE_DISABLE_CLAUDE_CODE_SKILLS + else process.env.OPENCODE_DISABLE_CLAUDE_CODE_SKILLS = originalDisableClaudeSkills } }) @@ -396,7 +410,8 @@ description: A skill in the .agents/skills directory. }, }) } finally { - process.env.OPENCODE_DISABLE_CLAUDE_CODE_SKILLS = originalDisableClaudeSkills + if (originalDisableClaudeSkills === undefined) delete process.env.OPENCODE_DISABLE_CLAUDE_CODE_SKILLS + else process.env.OPENCODE_DISABLE_CLAUDE_CODE_SKILLS = originalDisableClaudeSkills } }) @@ -463,6 +478,7 @@ description: A skill in the .opencode/skills directory. }, }) } finally { - process.env.OPENCODE_DISABLE_CLAUDE_CODE_SKILLS = originalDisableClaudeSkills + if (originalDisableClaudeSkills === undefined) delete process.env.OPENCODE_DISABLE_CLAUDE_CODE_SKILLS + else process.env.OPENCODE_DISABLE_CLAUDE_CODE_SKILLS = originalDisableClaudeSkills } }) diff --git a/packages/opencode/test/tool/skill.test.ts b/packages/opencode/test/tool/skill.test.ts index c0bf59dc556..287847c1583 100644 --- a/packages/opencode/test/tool/skill.test.ts +++ b/packages/opencode/test/tool/skill.test.ts @@ -1,5 +1,6 @@ import { describe, expect, test } from "bun:test" import path from "path" +import fs from "fs/promises" import { pathToFileURL } from "url" import type { PermissionNext } from "../../src/permission/next" import type { Tool } from "../../src/tool/tool" @@ -42,7 +43,6 @@ description: Skill for tool tests. process.env.OPENCODE_DISABLE_GLOBAL_SKILLS = "0" // Create the config directory so Bun.Glob.scan() doesn't ENOENT with null byte - const fs = await import("fs/promises") await fs.mkdir(path.join(tmp.path, ".config", "opencode"), { recursive: true }) try { @@ -55,8 +55,10 @@ description: Skill for tool tests. }, }) } finally { - process.env.OPENCODE_TEST_HOME = home - process.env.OPENCODE_DISABLE_GLOBAL_SKILLS = originalDisableGlobalSkills + if (home === undefined) delete process.env.OPENCODE_TEST_HOME + else process.env.OPENCODE_TEST_HOME = home + if (originalDisableGlobalSkills === undefined) delete process.env.OPENCODE_DISABLE_GLOBAL_SKILLS + else process.env.OPENCODE_DISABLE_GLOBAL_SKILLS = originalDisableGlobalSkills } }) @@ -87,7 +89,6 @@ Use this skill. process.env.OPENCODE_DISABLE_GLOBAL_SKILLS = "0" // Create the config directory so Bun.Glob.scan() doesn't ENOENT with null byte - const fs = await import("fs/promises") await fs.mkdir(path.join(tmp.path, ".config", "opencode"), { recursive: true }) try { @@ -119,8 +120,10 @@ Use this skill. }, }) } finally { - process.env.OPENCODE_TEST_HOME = home - process.env.OPENCODE_DISABLE_GLOBAL_SKILLS = originalDisableGlobalSkills + if (home === undefined) delete process.env.OPENCODE_TEST_HOME + else process.env.OPENCODE_TEST_HOME = home + if (originalDisableGlobalSkills === undefined) delete process.env.OPENCODE_DISABLE_GLOBAL_SKILLS + else process.env.OPENCODE_DISABLE_GLOBAL_SKILLS = originalDisableGlobalSkills } }) })