diff --git a/packages/opencode/src/agent/agent.ts b/packages/opencode/src/agent/agent.ts index c683727dfa3..f7c2391d930 100644 --- a/packages/opencode/src/agent/agent.ts +++ b/packages/opencode/src/agent/agent.ts @@ -8,6 +8,7 @@ import { Instance } from "../project/instance" import PROMPT_GENERATE from "./generate.txt" import PROMPT_COMPACTION from "./prompt/compaction.txt" import PROMPT_EXPLORE from "./prompt/explore.txt" +import PROMPT_REVIEW from "../command/template/review.txt" import PROMPT_SUMMARY from "./prompt/summary.txt" import PROMPT_TITLE from "./prompt/title.txt" import { PermissionNext } from "@/permission/next" @@ -120,6 +121,30 @@ export namespace Agent { mode: "subagent", native: true, }, + review: { + name: "review", + description: "Specialized agent for reviewing code changes", + permission: PermissionNext.merge( + defaults, + PermissionNext.fromConfig({ + todowrite: "allow", + todoread: "allow", + grep: "allow", + glob: "allow", + bash: "allow", + webfetch: "allow", + websearch: "allow", + codesearch: "allow", + read: "allow", + }), + user, + ), + prompt: PROMPT_REVIEW, + options: {}, + mode: "subagent", + native: true, + hidden: true, + }, compaction: { name: "compaction", mode: "primary", @@ -173,7 +198,7 @@ export namespace Agent { continue } let item = result[key] - if (!item) + if (item === undefined) { item = result[key] = { name: key, mode: "all", @@ -181,6 +206,7 @@ export namespace Agent { options: {}, native: false, } + } if (value.model) item.model = Provider.parseModel(value.model) item.prompt = value.prompt ?? item.prompt item.description = value.description ?? item.description diff --git a/packages/opencode/src/command/index.ts b/packages/opencode/src/command/index.ts index 976f1cd51e9..64df9f6231f 100644 --- a/packages/opencode/src/command/index.ts +++ b/packages/opencode/src/command/index.ts @@ -69,6 +69,7 @@ export namespace Command { }, [Default.REVIEW]: { name: Default.REVIEW, + agent: "review", description: "review changes [commit|branch|pr], defaults to uncommitted", get template() { return PROMPT_REVIEW.replace("${path}", Instance.worktree) diff --git a/packages/opencode/src/session/prompt.ts b/packages/opencode/src/session/prompt.ts index 87b53f526bb..116e47cc1d2 100644 --- a/packages/opencode/src/session/prompt.ts +++ b/packages/opencode/src/session/prompt.ts @@ -1530,6 +1530,7 @@ export namespace SessionPrompt { } const templateParts = await resolvePromptParts(template) + const agentInfo = await Agent.get(agentName) const parts = (agent.mode === "subagent" && command.subtask !== false) || command.subtask === true ? [ @@ -1538,8 +1539,8 @@ export namespace SessionPrompt { agent: agent.name, description: command.description ?? "", command: input.command, - // TODO: how can we make task tool accept a more complex input? - prompt: templateParts.find((y) => y.type === "text")?.text ?? "", + // If agent already has a prompt defined, don't duplicate it in the user message + prompt: agentInfo?.prompt ? "" : (templateParts.find((y) => y.type === "text")?.text ?? ""), }, ] : [...templateParts, ...(input.parts ?? [])]