diff --git a/packages/opencode/src/permission/index.ts b/packages/opencode/src/permission/index.ts index 3a4a9901b71..32dbd5a0370 100644 --- a/packages/opencode/src/permission/index.ts +++ b/packages/opencode/src/permission/index.ts @@ -186,8 +186,13 @@ export namespace Permission { public readonly permissionID: string, public readonly toolCallID?: string, public readonly metadata?: Record, + public readonly reason?: string, ) { - super(`The user rejected permission to use this specific tool call. You may try again with different parameters.`) + super( + reason !== undefined + ? reason + : `The user rejected permission to use this specific tool call. You may try again with different parameters.`, + ) } } } diff --git a/packages/opencode/src/session/processor.ts b/packages/opencode/src/session/processor.ts index 5c2005587b2..2af8e888eb6 100644 --- a/packages/opencode/src/session/processor.ts +++ b/packages/opencode/src/session/processor.ts @@ -136,6 +136,7 @@ export namespace SessionProcessor { const parts = await MessageV2.parts(input.assistantMessage.id) const lastThree = parts.slice(-DOOM_LOOP_THRESHOLD) + if ( lastThree.length === DOOM_LOOP_THRESHOLD && lastThree.every( @@ -160,6 +161,17 @@ export namespace SessionProcessor { input: value.input, }, }) + } else if (permission.doom_loop === "deny") { + throw new Permission.RejectedError( + input.assistantMessage.sessionID, + "doom_loop", + value.toolCallId, + { + tool: value.toolName, + input: value.input, + }, + `You seem to be stuck in a doom loop, please stop repeating the same action`, + ) } } } diff --git a/packages/opencode/src/tool/edit.ts b/packages/opencode/src/tool/edit.ts index ca9859370bc..46627a3edf5 100644 --- a/packages/opencode/src/tool/edit.ts +++ b/packages/opencode/src/tool/edit.ts @@ -57,6 +57,17 @@ export const EditTool = Tool.define("edit", { parentDir, }, }) + } else if (agent.permission.external_directory === "deny") { + throw new Permission.RejectedError( + ctx.sessionID, + "external_directory", + ctx.callID, + { + filepath: filePath, + parentDir, + }, + `File ${filePath} is not in the current working directory`, + ) } } diff --git a/packages/opencode/src/tool/patch.ts b/packages/opencode/src/tool/patch.ts index 0571cd35318..b8934f7c939 100644 --- a/packages/opencode/src/tool/patch.ts +++ b/packages/opencode/src/tool/patch.ts @@ -68,6 +68,17 @@ export const PatchTool = Tool.define("patch", { parentDir, }, }) + } else if (agent.permission.external_directory === "deny") { + throw new Permission.RejectedError( + ctx.sessionID, + "external_directory", + ctx.callID, + { + filepath: filePath, + parentDir, + }, + `File ${filePath} is not in the current working directory`, + ) } } diff --git a/packages/opencode/src/tool/read.ts b/packages/opencode/src/tool/read.ts index ec97c8a6c23..7e523496c37 100644 --- a/packages/opencode/src/tool/read.ts +++ b/packages/opencode/src/tool/read.ts @@ -46,6 +46,17 @@ export const ReadTool = Tool.define("read", { parentDir, }, }) + } else if (agent.permission.external_directory === "deny") { + throw new Permission.RejectedError( + ctx.sessionID, + "external_directory", + ctx.callID, + { + filepath: filepath, + parentDir, + }, + `File ${filepath} is not in the current working directory`, + ) } } diff --git a/packages/opencode/src/tool/write.ts b/packages/opencode/src/tool/write.ts index 58a0c177eb9..42bbe4690a6 100644 --- a/packages/opencode/src/tool/write.ts +++ b/packages/opencode/src/tool/write.ts @@ -36,6 +36,17 @@ export const WriteTool = Tool.define("write", { parentDir, }, }) + } else if (agent.permission.external_directory === "deny") { + throw new Permission.RejectedError( + ctx.sessionID, + "external_directory", + ctx.callID, + { + filepath: filepath, + parentDir, + }, + `File ${filepath} is not in the current working directory`, + ) } }