diff --git a/package.json b/package.json index a30b55be73..aa7031bec7 100644 --- a/package.json +++ b/package.json @@ -78,8 +78,6 @@ "url": "https://github.com/sst/opencode" }, "license": "MIT", - "randomField": "hello from claude", - "anotherRandomField": "xkcd-927-compliance-level", "prettier": { "semi": false, "printWidth": 120 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 37f169b193..e3d519115b 100644 --- a/packages/opencode/src/cli/cmd/tui/routes/session/permission.tsx +++ b/packages/opencode/src/cli/cmd/tui/routes/session/permission.tsx @@ -130,24 +130,24 @@ export function PermissionPrompt(props: { request: PermissionRequest }) { This will allow the following patterns until OpenCode is restarted - - {(pattern) => ( - - {"- "} - {pattern} - - )} - + + + {(pattern) => ( + + {"- "} + {pattern} + + )} + + } options={{ confirm: "Confirm", cancel: "Cancel" }} onSelect={(option) => { - if (option === "cancel") { - setStore("always", false) - return - } + setStore("always", false) + if (option === "cancel") return sdk.client.permission.reply({ reply: "always", requestID: props.request.id, diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index 80d761b71d..f5d895dc8f 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -123,13 +123,22 @@ export namespace Config { result.permission = mergeDeep(result.permission ?? {}, JSON.parse(Flag.OPENCODE_PERMISSION)) } - if (!result.username) result.username = os.userInfo().username - - // Handle migration from autoshare to share field - if (result.autoshare === true && !result.share) { - result.share = "auto" + // Backwards compatibility: legacy top-level `tools` config + if (result.tools) { + const perms: Record = {} + for (const [tool, enabled] of Object.entries(result.tools)) { + const action: Config.PermissionAction = enabled ? "allow" : "deny" + if (tool === "write" || tool === "edit" || tool === "patch" || tool === "multiedit") { + perms.edit = action + continue + } + perms[tool] = action + } + result.permission = mergeDeep(perms, result.permission ?? {}) } + if (!result.username) result.username = os.userInfo().username + // Handle migration from autoshare to share field if (result.autoshare === true && !result.share) { result.share = "auto" diff --git a/packages/opencode/src/permission/arity.ts b/packages/opencode/src/permission/arity.ts index bbc6bb03db..948841c8e7 100644 --- a/packages/opencode/src/permission/arity.ts +++ b/packages/opencode/src/permission/arity.ts @@ -5,7 +5,8 @@ export namespace BashArity { const arity = ARITY[prefix] if (arity !== undefined) return tokens.slice(0, arity) } - return tokens + if (tokens.length === 0) return [] + return tokens.slice(0, 1) } /* Generated with following prompt: diff --git a/packages/opencode/src/permission/next.ts b/packages/opencode/src/permission/next.ts index b434b79643..5102a22fdc 100644 --- a/packages/opencode/src/permission/next.ts +++ b/packages/opencode/src/permission/next.ts @@ -181,7 +181,6 @@ export namespace PermissionNext { return } if (input.reply === "always") { - const projectID = Instance.project.id for (const pattern of existing.info.always) { s.approved.push({ permission: existing.info.permission, @@ -189,10 +188,28 @@ export namespace PermissionNext { action: "allow", }) } + + existing.resolve() + + const sessionID = existing.info.sessionID + for (const [id, pending] of Object.entries(s.pending)) { + if (pending.info.sessionID !== sessionID) continue + const ok = pending.info.patterns.every( + (pattern) => evaluate(pending.info.permission, pattern, s.approved) === "allow", + ) + if (!ok) continue + delete s.pending[id] + Bus.publish(Event.Replied, { + sessionID: pending.info.sessionID, + requestID: pending.info.id, + reply: "always", + }) + pending.resolve() + } + // TODO: we don't save the permission ruleset to disk yet until there's // UI to manage it - // await Storage.write(["permission", projectID], s.approved) - existing.resolve() + // await Storage.write(["permission", Instance.project.id], s.approved) return } },