diff --git a/packages/opencode/src/agent/agent.ts b/packages/opencode/src/agent/agent.ts index 46a43a6deb..065bc2398f 100644 --- a/packages/opencode/src/agent/agent.ts +++ b/packages/opencode/src/agent/agent.ts @@ -42,20 +42,19 @@ export namespace Agent { const state = Instance.state(async () => { const cfg = await Config.get() - const permission: PermissionNext.Ruleset = PermissionNext.merge( - PermissionNext.fromConfig({ - "*": "allow", - doom_loop: "ask", - external_directory: "ask", - }), - PermissionNext.fromConfig(cfg.permission ?? {}), - ) + + const defaults = PermissionNext.fromConfig({ + "*": "allow", + doom_loop: "ask", + external_directory: "ask", + }) + const user = PermissionNext.fromConfig(cfg.permission ?? {}) const result: Record = { build: { name: "build", options: {}, - permission, + permission: PermissionNext.merge(defaults, user), mode: "primary", native: true, }, @@ -63,13 +62,14 @@ export namespace Agent { name: "plan", options: {}, permission: PermissionNext.merge( - permission, + defaults, PermissionNext.fromConfig({ edit: { "*": "deny", ".opencode/plan/*.md": "allow", }, }), + user, ), mode: "primary", native: true, @@ -78,11 +78,12 @@ export namespace Agent { name: "general", description: `General-purpose agent for researching complex questions and executing multi-step tasks. Use this agent to execute multiple units of work in parallel.`, permission: PermissionNext.merge( - permission, + defaults, PermissionNext.fromConfig({ todoread: "deny", todowrite: "deny", }), + user, ), options: {}, mode: "subagent", @@ -92,7 +93,7 @@ export namespace Agent { explore: { name: "explore", permission: PermissionNext.merge( - permission, + defaults, PermissionNext.fromConfig({ "*": "deny", grep: "allow", @@ -104,6 +105,7 @@ export namespace Agent { codesearch: "allow", read: "allow", }), + user, ), description: `Fast agent specialized for exploring codebases. Use this when you need to quickly find files by patterns (eg. "src/components/**/*.tsx"), search code for keywords (eg. "API endpoints"), or answer questions about the codebase (eg. "how do API endpoints work?"). When calling this agent, specify the desired thoroughness level: "quick" for basic searches, "medium" for moderate exploration, or "very thorough" for comprehensive analysis across multiple locations and naming conventions.`, prompt: PROMPT_EXPLORE, @@ -117,9 +119,13 @@ export namespace Agent { native: true, hidden: true, prompt: PROMPT_COMPACTION, - permission: PermissionNext.fromConfig({ - "*": "deny", - }), + permission: PermissionNext.merge( + defaults, + PermissionNext.fromConfig({ + "*": "deny", + }), + user, + ), options: {}, }, title: { @@ -128,9 +134,13 @@ export namespace Agent { options: {}, native: true, hidden: true, - permission: PermissionNext.fromConfig({ - "*": "deny", - }), + permission: PermissionNext.merge( + defaults, + PermissionNext.fromConfig({ + "*": "deny", + }), + user, + ), prompt: PROMPT_TITLE, }, summary: { @@ -139,9 +149,13 @@ export namespace Agent { options: {}, native: true, hidden: true, - permission: PermissionNext.fromConfig({ - "*": "deny", - }), + permission: PermissionNext.merge( + defaults, + PermissionNext.fromConfig({ + "*": "deny", + }), + user, + ), prompt: PROMPT_SUMMARY, }, } @@ -156,7 +170,7 @@ export namespace Agent { item = result[key] = { name: key, mode: "all", - permission, + permission: PermissionNext.merge(defaults, user), options: {}, native: false, } diff --git a/packages/opencode/src/cli/cmd/tui/routes/session/permission.tsx b/packages/opencode/src/cli/cmd/tui/routes/session/permission.tsx index 34e7011144..06620ab66c 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/permission.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/permission.tsx @@ -161,10 +161,9 @@ export function PermissionPrompt(props: { request: PermissionRequest }) { diff --git a/packages/opencode/src/session/processor.ts b/packages/opencode/src/session/processor.ts index 0558839445..c8771345bf 100644 --- a/packages/opencode/src/session/processor.ts +++ b/packages/opencode/src/session/processor.ts @@ -153,7 +153,7 @@ export namespace SessionProcessor { JSON.stringify(p.state.input) === JSON.stringify(value.input), ) ) { - const agent = await Agent.get(input.assistantMessage.mode) + const agent = await Agent.get(input.assistantMessage.agent) await PermissionNext.ask({ permission: "doom_loop", patterns: [value.toolName], diff --git a/packages/opencode/src/session/prompt.ts b/packages/opencode/src/session/prompt.ts index 2d4575a679..aa681bdbe1 100644 --- a/packages/opencode/src/session/prompt.ts +++ b/packages/opencode/src/session/prompt.ts @@ -241,6 +241,7 @@ export namespace SessionPrompt { using _ = defer(() => cancel(sessionID)) let step = 0 + const session = await Session.get(sessionID) while (true) { SessionStatus.set(sessionID, { type: "busy" }) log.info("loop", { step, sessionID }) @@ -277,7 +278,7 @@ export namespace SessionPrompt { step++ if (step === 1) ensureTitle({ - session: await Session.get(sessionID), + session, modelID: lastUser.model.modelID, providerID: lastUser.model.providerID, message: msgs.find((m) => m.info.role === "user")!, @@ -519,7 +520,7 @@ export namespace SessionPrompt { }) const tools = await resolveTools({ agent, - sessionID, + session, model, tools: lastUser.tools, processor, @@ -589,7 +590,7 @@ export namespace SessionPrompt { async function resolveTools(input: { agent: Agent.Info model: Provider.Model - sessionID: string + session: Session.Info tools?: Record processor: SessionProcessor.Info }) { @@ -606,7 +607,7 @@ export namespace SessionPrompt { "tool.execute.before", { tool: item.id, - sessionID: input.sessionID, + sessionID: input.session.id, callID: options.toolCallId, }, { @@ -614,7 +615,7 @@ export namespace SessionPrompt { }, ) const ctx: Tool.Context = { - sessionID: input.sessionID, + sessionID: input.session.id, abort: options.abortSignal!, messageID: input.processor.message.id, callID: options.toolCallId, @@ -640,7 +641,7 @@ export namespace SessionPrompt { async ask(req) { await PermissionNext.ask({ ...req, - sessionID: input.sessionID, + sessionID: input.session.parentID ?? input.session.id, tool: { messageID: input.processor.message.id, callID: options.toolCallId }, ruleset: input.agent.permission, }) @@ -651,7 +652,7 @@ export namespace SessionPrompt { "tool.execute.after", { tool: item.id, - sessionID: input.sessionID, + sessionID: input.session.id, callID: options.toolCallId, }, result, @@ -676,7 +677,7 @@ export namespace SessionPrompt { "tool.execute.before", { tool: key, - sessionID: input.sessionID, + sessionID: input.session.id, callID: opts.toolCallId, }, { @@ -689,7 +690,7 @@ export namespace SessionPrompt { "tool.execute.after", { tool: key, - sessionID: input.sessionID, + sessionID: input.session.id, callID: opts.toolCallId, }, result, @@ -704,7 +705,7 @@ export namespace SessionPrompt { } else if (contentItem.type === "image") { attachments.push({ id: Identifier.ascending("part"), - sessionID: input.sessionID, + sessionID: input.session.id, messageID: input.processor.message.id, type: "file", mime: contentItem.mimeType,