fix(app): auto-accept permissions
This commit is contained in:
@@ -1310,43 +1310,45 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Show when={store.mode === "normal" && permission.permissionsEnabled() && params.id}>
|
<div class="pointer-events-none absolute bottom-2 left-2">
|
||||||
<div class="pointer-events-none absolute bottom-2 left-2">
|
<div class="pointer-events-auto">
|
||||||
<div class="pointer-events-auto">
|
<TooltipKeybind
|
||||||
<TooltipKeybind
|
placement="top"
|
||||||
placement="top"
|
gutter={8}
|
||||||
gutter={8}
|
title={language.t(
|
||||||
title={language.t(
|
accepting() ? "command.permissions.autoaccept.disable" : "command.permissions.autoaccept.enable",
|
||||||
accepting() ? "command.permissions.autoaccept.disable" : "command.permissions.autoaccept.enable",
|
)}
|
||||||
)}
|
keybind={command.keybind("permissions.autoaccept")}
|
||||||
keybind={command.keybind("permissions.autoaccept")}
|
>
|
||||||
|
<Button
|
||||||
|
data-action="prompt-permissions"
|
||||||
|
variant="ghost"
|
||||||
|
disabled={!params.id}
|
||||||
|
onClick={() => {
|
||||||
|
if (!params.id) return
|
||||||
|
permission.toggleAutoAccept(params.id, sdk.directory)
|
||||||
|
}}
|
||||||
|
classList={{
|
||||||
|
"size-6 flex items-center justify-center": true,
|
||||||
|
"text-text-base": !accepting(),
|
||||||
|
"hover:bg-surface-success-base": accepting(),
|
||||||
|
}}
|
||||||
|
aria-label={
|
||||||
|
accepting()
|
||||||
|
? language.t("command.permissions.autoaccept.disable")
|
||||||
|
: language.t("command.permissions.autoaccept.enable")
|
||||||
|
}
|
||||||
|
aria-pressed={accepting()}
|
||||||
>
|
>
|
||||||
<Button
|
<Icon
|
||||||
data-action="prompt-permissions"
|
name="chevron-double-right"
|
||||||
variant="ghost"
|
size="small"
|
||||||
onClick={() => permission.toggleAutoAccept(params.id!, sdk.directory)}
|
classList={{ "text-icon-success-base": accepting() }}
|
||||||
classList={{
|
/>
|
||||||
"_hidden group-hover/prompt-input:flex size-6 items-center justify-center": true,
|
</Button>
|
||||||
"text-text-base": !accepting(),
|
</TooltipKeybind>
|
||||||
"hover:bg-surface-success-base": accepting(),
|
|
||||||
}}
|
|
||||||
aria-label={
|
|
||||||
accepting()
|
|
||||||
? language.t("command.permissions.autoaccept.disable")
|
|
||||||
: language.t("command.permissions.autoaccept.enable")
|
|
||||||
}
|
|
||||||
aria-pressed={accepting()}
|
|
||||||
>
|
|
||||||
<Icon
|
|
||||||
name="chevron-double-right"
|
|
||||||
size="small"
|
|
||||||
classList={{ "text-icon-success-base": accepting() }}
|
|
||||||
/>
|
|
||||||
</Button>
|
|
||||||
</TooltipKeybind>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</DockShellForm>
|
</DockShellForm>
|
||||||
<Show when={store.mode === "normal" || store.mode === "shell"}>
|
<Show when={store.mode === "normal" || store.mode === "shell"}>
|
||||||
|
|||||||
@@ -31,12 +31,33 @@ describe("autoRespondsPermission", () => {
|
|||||||
expect(autoRespondsPermission({ root: true }, sessions, permission("child"), "/tmp/project")).toBe(true)
|
expect(autoRespondsPermission({ root: true }, sessions, permission("child"), "/tmp/project")).toBe(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
test("ignores auto-accept from unrelated sessions", () => {
|
test("defaults to auto-accept when no lineage override exists", () => {
|
||||||
const sessions = [session({ id: "root" }), session({ id: "child", parentID: "root" }), session({ id: "other" })]
|
const sessions = [session({ id: "root" }), session({ id: "child", parentID: "root" }), session({ id: "other" })]
|
||||||
const autoAccept = {
|
const autoAccept = {
|
||||||
other: true,
|
other: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(autoRespondsPermission(autoAccept, sessions, permission("child"), "/tmp/project")).toBe(false)
|
expect(autoRespondsPermission(autoAccept, sessions, permission("child"), "/tmp/project")).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("inherits a parent session's false override", () => {
|
||||||
|
const directory = "/tmp/project"
|
||||||
|
const sessions = [session({ id: "root" }), session({ id: "child", parentID: "root" })]
|
||||||
|
const autoAccept = {
|
||||||
|
[`${base64Encode(directory)}/root`]: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(autoRespondsPermission(autoAccept, sessions, permission("child"), directory)).toBe(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("prefers a child override over parent override", () => {
|
||||||
|
const directory = "/tmp/project"
|
||||||
|
const sessions = [session({ id: "root" }), session({ id: "child", parentID: "root" })]
|
||||||
|
const autoAccept = {
|
||||||
|
[`${base64Encode(directory)}/root`]: false,
|
||||||
|
[`${base64Encode(directory)}/child`]: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(autoRespondsPermission(autoAccept, sessions, permission("child"), directory)).toBe(true)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -5,6 +5,11 @@ export function acceptKey(sessionID: string, directory?: string) {
|
|||||||
return `${base64Encode(directory)}/${sessionID}`
|
return `${base64Encode(directory)}/${sessionID}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function accepted(autoAccept: Record<string, boolean>, sessionID: string, directory?: string) {
|
||||||
|
const key = acceptKey(sessionID, directory)
|
||||||
|
return autoAccept[key] ?? autoAccept[sessionID]
|
||||||
|
}
|
||||||
|
|
||||||
function sessionLineage(session: { id: string; parentID?: string }[], sessionID: string) {
|
function sessionLineage(session: { id: string; parentID?: string }[], sessionID: string) {
|
||||||
const parent = session.reduce((acc, item) => {
|
const parent = session.reduce((acc, item) => {
|
||||||
if (item.parentID) acc.set(item.id, item.parentID)
|
if (item.parentID) acc.set(item.id, item.parentID)
|
||||||
@@ -29,8 +34,8 @@ export function autoRespondsPermission(
|
|||||||
permission: { sessionID: string },
|
permission: { sessionID: string },
|
||||||
directory?: string,
|
directory?: string,
|
||||||
) {
|
) {
|
||||||
return sessionLineage(session, permission.sessionID).some((id) => {
|
const value = sessionLineage(session, permission.sessionID)
|
||||||
const key = acceptKey(id, directory)
|
.map((id) => accepted(autoAccept, id, directory))
|
||||||
return autoAccept[key] ?? autoAccept[id] ?? false
|
.find((item): item is boolean => item !== undefined)
|
||||||
})
|
return value ?? true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,8 +115,8 @@ export const { use: usePermission, provider: PermissionProvider } = createSimple
|
|||||||
}
|
}
|
||||||
|
|
||||||
function isAutoAccepting(sessionID: string, directory?: string) {
|
function isAutoAccepting(sessionID: string, directory?: string) {
|
||||||
const key = acceptKey(sessionID, directory)
|
const session = directory ? globalSync.child(directory, { bootstrap: false })[0].session : []
|
||||||
return store.autoAccept[key] ?? store.autoAccept[sessionID] ?? false
|
return autoRespondsPermission(store.autoAccept, session, { sessionID }, directory)
|
||||||
}
|
}
|
||||||
|
|
||||||
function shouldAutoRespond(permission: PermissionRequest, directory?: string) {
|
function shouldAutoRespond(permission: PermissionRequest, directory?: string) {
|
||||||
@@ -168,10 +168,11 @@ export const { use: usePermission, provider: PermissionProvider } = createSimple
|
|||||||
|
|
||||||
function disable(sessionID: string, directory?: string) {
|
function disable(sessionID: string, directory?: string) {
|
||||||
bumpEnableVersion(sessionID, directory)
|
bumpEnableVersion(sessionID, directory)
|
||||||
const key = directory ? acceptKey(sessionID, directory) : undefined
|
const key = directory ? acceptKey(sessionID, directory) : sessionID
|
||||||
setStore(
|
setStore(
|
||||||
produce((draft) => {
|
produce((draft) => {
|
||||||
if (key) delete draft.autoAccept[key]
|
draft.autoAccept[key] = false
|
||||||
|
if (!directory) return
|
||||||
delete draft.autoAccept[sessionID]
|
delete draft.autoAccept[sessionID]
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user