feat: persist permission auto-accept on server (#2158)
Move per-session permission auto-accept policy ownership from the UI to the OpenChamber server so enabled sessions continue running when clients disconnect or the server restarts. - persist explicit per-session policies in OpenChamber settings - inherit the nearest explicit policy across subagent session hierarchies - allow child sessions to opt out of an inherited parent policy - immediately accept matching global and directory-scoped pending requests - process future requests without requiring a connected UI client - reconcile pending permissions after startup and event-stream reconnects - deduplicate concurrent requests and retry transient reply failures - synchronize policy updates across connected clients - migrate existing browser-persisted policies to server storage - suppress auto-accepted permission cards before they enter UI state - show deduplicated permission toasts for inactive sessions - preserve foreground-only permission handling in VS Code - integrate directory-aware notification routing from main - add coverage for persistence, inheritance, retries, reconciliation, pending requests, client hydration, and inactive-session toasts
This commit is contained in:
committed by
GitHub
parent
3d90eddcaf
commit
d738d41574
@@ -15,6 +15,10 @@ export const createNotificationTriggerRuntime = (deps) => {
|
||||
buildOpenCodeUrl,
|
||||
getOpenCodeAuthHeaders,
|
||||
} = deps;
|
||||
let getIsSessionAutoAccepting = deps.getIsSessionAutoAccepting;
|
||||
const setGetIsSessionAutoAccepting = (resolver) => {
|
||||
getIsSessionAutoAccepting = typeof resolver === 'function' ? resolver : undefined;
|
||||
};
|
||||
|
||||
// App-icon badge for native push: the set of DISTINCT collapse-ids (the push
|
||||
// `tag`, e.g. `ready-<sessionId>` / `permission-<requestKey>`) we've sent since
|
||||
@@ -609,7 +613,8 @@ export const createNotificationTriggerRuntime = (deps) => {
|
||||
// Client may be in Permission Auto-Accept for this session (or any
|
||||
// ancestor). Skip the whole notification path — the client responds
|
||||
// directly and the user has opted out of approval prompts.
|
||||
if (await isSessionAutoAccepting(sessionId, notificationDirectory)) {
|
||||
if (await (getIsSessionAutoAccepting?.(sessionId, notificationDirectory)
|
||||
?? isSessionAutoAccepting(sessionId, notificationDirectory))) {
|
||||
if (requestKey) notifiedPermissionRequests.add(requestKey);
|
||||
return;
|
||||
}
|
||||
@@ -622,7 +627,8 @@ export const createNotificationTriggerRuntime = (deps) => {
|
||||
const timer = setTimeout(async () => {
|
||||
pushPermissionDebounceTimers.delete(sessionId);
|
||||
|
||||
if (await isSessionAutoAccepting(sessionId, notificationDirectory)) {
|
||||
if (await (getIsSessionAutoAccepting?.(sessionId, notificationDirectory)
|
||||
?? isSessionAutoAccepting(sessionId, notificationDirectory))) {
|
||||
if (requestKey) notifiedPermissionRequests.add(requestKey);
|
||||
return;
|
||||
}
|
||||
@@ -742,6 +748,7 @@ export const createNotificationTriggerRuntime = (deps) => {
|
||||
maybeSendPushForTrigger,
|
||||
setAutoAcceptSession,
|
||||
setGetIsWindowFocused,
|
||||
setGetIsSessionAutoAccepting,
|
||||
clearPendingPushBadge,
|
||||
sendGoalSettlePush,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user