From b8213b9c5247ade3a534ad04510313a1f8dd9268 Mon Sep 17 00:00:00 2001 From: Leeroy Brun Date: Tue, 30 Dec 2025 15:23:26 +0100 Subject: [PATCH] fix: correct `/new` permission-mode selection and harden per-session persistence - Use `agentType` as fallback when `metadata.flavor` is missing in `AgentInput` (fixes `/new`). - Make `storage.applySessions()` prefer persisted/non-default permission modes over `'default'`. - Persist permission modes incrementally per `sessionId` under `session-permission-modes`. --- sources/components/AgentInput.tsx | 9 +++++--- sources/sync/storage.ts | 34 +++++++++++++++---------------- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/sources/components/AgentInput.tsx b/sources/components/AgentInput.tsx index 016a53874..b33f091c9 100644 --- a/sources/components/AgentInput.tsx +++ b/sources/components/AgentInput.tsx @@ -290,9 +290,12 @@ export const AgentInput = React.memo(React.forwardRef 0; - // Check if this is a Codex or Gemini session - const isCodex = props.metadata?.flavor === 'codex'; - const isGemini = props.metadata?.flavor === 'gemini'; + // Determine agent flavor for UI decisions (permission modes, labels, etc). + // In a live session we can use `metadata.flavor`, but in `/new` we don't have session metadata yet, + // so we fall back to the explicitly selected `agentType`. + const flavor = props.metadata?.flavor ?? props.agentType ?? null; + const isCodex = flavor === 'codex'; + const isGemini = flavor === 'gemini'; // Calculate context warning const contextWarning = props.usageData?.contextSize diff --git a/sources/sync/storage.ts b/sources/sync/storage.ts index f1fe413f6..bba1cbbd1 100644 --- a/sources/sync/storage.ts +++ b/sources/sync/storage.ts @@ -302,7 +302,6 @@ export const storage = create()((set, get) => { applySessions: (sessions: (Omit & { presence?: "online" | number })[]) => set((state) => { // Load drafts and permission modes if sessions are empty (initial load) const savedDrafts = Object.keys(state.sessions).length === 0 ? sessionDrafts : {}; - const savedPermissionModes = Object.keys(state.sessions).length === 0 ? sessionPermissionModes : {}; // Merge new sessions with existing ones const mergedSessions: Record = { ...state.sessions }; @@ -316,12 +315,15 @@ export const storage = create()((set, get) => { const existingDraft = state.sessions[session.id]?.draft; const savedDraft = savedDrafts[session.id]; const existingPermissionMode = state.sessions[session.id]?.permissionMode; - const savedPermissionMode = savedPermissionModes[session.id]; + const savedPermissionMode = sessionPermissionModes[session.id]; + const resolvedPermissionMode = existingPermissionMode && existingPermissionMode !== 'default' + ? existingPermissionMode + : (savedPermissionMode || session.permissionMode || existingPermissionMode || 'default'); mergedSessions[session.id] = { ...session, presence, draft: existingDraft || savedDraft || session.draft || null, - permissionMode: existingPermissionMode || savedPermissionMode || session.permissionMode || 'default' + permissionMode: resolvedPermissionMode }; }); @@ -780,6 +782,16 @@ export const storage = create()((set, get) => { }), updateSessionPermissionMode: (sessionId: string, mode: 'default' | 'acceptEdits' | 'bypassPermissions' | 'plan' | 'read-only' | 'safe-yolo' | 'yolo') => set((state) => { const session = state.sessions[sessionId]; + // Persist permission modes even if the session isn't loaded yet. + // This is important for newly created sessions where we want the first render + // to show the intended permission mode, even if applySessions runs later. + if (mode !== 'default') { + sessionPermissionModes[sessionId] = mode; + } else { + delete sessionPermissionModes[sessionId]; + } + saveSessionPermissionModes(sessionPermissionModes); + if (!session) return state; // Update the session with the new permission mode @@ -791,17 +803,6 @@ export const storage = create()((set, get) => { } }; - // Collect all permission modes for persistence - const allModes: Record = {}; - Object.entries(updatedSessions).forEach(([id, sess]) => { - if (sess.permissionMode && sess.permissionMode !== 'default') { - allModes[id] = sess.permissionMode; - } - }); - - // Persist permission modes (only non-default values to save space) - saveSessionPermissionModes(allModes); - // No need to rebuild sessionListViewData since permission mode doesn't affect the list display return { ...state, @@ -928,9 +929,8 @@ export const storage = create()((set, get) => { delete drafts[sessionId]; saveSessionDrafts(drafts); - const modes = loadSessionPermissionModes(); - delete modes[sessionId]; - saveSessionPermissionModes(modes); + delete sessionPermissionModes[sessionId]; + saveSessionPermissionModes(sessionPermissionModes); // Rebuild sessionListViewData without the deleted session const sessionListViewData = buildSessionListViewData(remainingSessions);