pull/6319/head
Dax Raad 2025-12-31 18:11:52 -05:00
parent c5d1a51b1f
commit a7f920d83b
5 changed files with 48 additions and 23 deletions

View File

@ -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

View File

@ -130,24 +130,24 @@ export function PermissionPrompt(props: { request: PermissionRequest }) {
<Match when={true}>
<box paddingLeft={1} gap={1}>
<text fg={theme.textMuted}>This will allow the following patterns until OpenCode is restarted</text>
<For each={props.request.always}>
{(pattern) => (
<text fg={theme.text}>
{"- "}
{pattern}
</text>
)}
</For>
<box>
<For each={props.request.always}>
{(pattern) => (
<text fg={theme.text}>
{"- "}
{pattern}
</text>
)}
</For>
</box>
</box>
</Match>
</Switch>
}
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,

View File

@ -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<string, Config.PermissionAction> = {}
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"

View File

@ -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:

View File

@ -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
}
},