## Summary - add a per-session Yolo mode toggle for permission prompts and persist its state - move the control into the Status tab with clearer copy, an info tooltip, and a visible header badge when it is enabled - auto-accept queued permissions for any yolo-enabled session in the instance, not only the currently focused session ## Why - keeps this risky mode explicit and easy to audit from the session status area - matches the expected multi-session desktop behavior when several sessions stay active in parallel ## Testing - npm run typecheck --workspace @codenomad/ui - npm run build --workspace @codenomad/ui Closes #18
82 lines
2.4 KiB
TypeScript
82 lines
2.4 KiB
TypeScript
import { createSignal } from "solid-js"
|
|
|
|
const STORAGE_KEY = "codenomad:permission-auto-accept:v1"
|
|
|
|
function makeKey(instanceId: string, sessionId: string) {
|
|
return `${instanceId}:${sessionId}`
|
|
}
|
|
|
|
function readInitialState() {
|
|
if (typeof window === "undefined" || !window.localStorage) {
|
|
return new Map<string, boolean>()
|
|
}
|
|
|
|
try {
|
|
const raw = window.localStorage.getItem(STORAGE_KEY)
|
|
if (!raw) return new Map<string, boolean>()
|
|
const parsed = JSON.parse(raw) as Record<string, boolean>
|
|
return new Map(Object.entries(parsed).filter((entry): entry is [string, boolean] => entry[1] === true))
|
|
} catch {
|
|
return new Map<string, boolean>()
|
|
}
|
|
}
|
|
|
|
function persist(next: Map<string, boolean>) {
|
|
if (typeof window === "undefined" || !window.localStorage) {
|
|
return
|
|
}
|
|
|
|
try {
|
|
window.localStorage.setItem(STORAGE_KEY, JSON.stringify(Object.fromEntries(next)))
|
|
} catch {
|
|
// ignore persistence failures
|
|
}
|
|
}
|
|
|
|
const [autoAcceptState, setAutoAcceptState] = createSignal(readInitialState())
|
|
const [inFlightVersion, setInFlightVersion] = createSignal(0)
|
|
|
|
const inFlight = new Set<string>()
|
|
|
|
export function isPermissionAutoAcceptEnabled(instanceId: string, sessionId: string) {
|
|
return autoAcceptState().get(makeKey(instanceId, sessionId)) ?? false
|
|
}
|
|
|
|
export function setPermissionAutoAcceptEnabled(instanceId: string, sessionId: string, enabled: boolean) {
|
|
const key = makeKey(instanceId, sessionId)
|
|
setAutoAcceptState((prev) => {
|
|
const next = new Map(prev)
|
|
if (enabled) {
|
|
next.set(key, true)
|
|
} else {
|
|
next.delete(key)
|
|
}
|
|
persist(next)
|
|
return next
|
|
})
|
|
}
|
|
|
|
export function togglePermissionAutoAccept(instanceId: string, sessionId: string) {
|
|
setPermissionAutoAcceptEnabled(instanceId, sessionId, !isPermissionAutoAcceptEnabled(instanceId, sessionId))
|
|
}
|
|
|
|
export function canAutoRespondPermission(instanceId: string, sessionId: string, requestId: string) {
|
|
const key = makeKey(instanceId, sessionId)
|
|
if (!autoAcceptState().get(key)) return false
|
|
const requestKey = `${key}:${requestId}`
|
|
if (inFlight.has(requestKey)) return false
|
|
inFlight.add(requestKey)
|
|
return true
|
|
}
|
|
|
|
export function getPermissionAutoAcceptInFlightVersion() {
|
|
return inFlightVersion()
|
|
}
|
|
|
|
export function finishAutoRespondPermission(instanceId: string, sessionId: string, requestId: string) {
|
|
if (!inFlight.delete(`${makeKey(instanceId, sessionId)}:${requestId}`)) {
|
|
return
|
|
}
|
|
setInFlightVersion((value) => value + 1)
|
|
}
|