From b5893afd3b760105ef623d9605107b6cec73d0cf Mon Sep 17 00:00:00 2001 From: Naomi Carrigan Date: Wed, 21 Jan 2026 14:51:45 -0800 Subject: [PATCH] fix: handle multiple tabs requesting permission --- src/lib/stores/claude.ts | 6 ++-- src/lib/stores/conversations.ts | 55 +++++++++++++++++++++++++++++++-- src/lib/tauri.ts | 28 +++++++++-------- 3 files changed, 71 insertions(+), 18 deletions(-) diff --git a/src/lib/stores/claude.ts b/src/lib/stores/claude.ts index 1a822f3..f8a92bb 100644 --- a/src/lib/stores/claude.ts +++ b/src/lib/stores/claude.ts @@ -47,6 +47,8 @@ export const claudeStore = { getConversationHistory: conversationsStore.getConversationHistory, requestPermission: conversationsStore.requestPermission, clearPermission: conversationsStore.clearPermission, + requestPermissionForConversation: conversationsStore.requestPermissionForConversation, + clearPermissionForConversation: conversationsStore.clearPermissionForConversation, grantTool: conversationsStore.grantTool, revokeAllTools: conversationsStore.revokeAllTools, isToolGranted: conversationsStore.isToolGranted, @@ -83,8 +85,8 @@ export const claudeStore = { }; export const hasPermissionPending = derived( - claudeStore.pendingPermission, - ($permission) => $permission !== null + claudeStore.activeConversation, + ($conversation) => $conversation?.pendingPermission !== null ); // Derived store to check if Claude is currently processing (can be interrupted) diff --git a/src/lib/stores/conversations.ts b/src/lib/stores/conversations.ts index 539bcd9..e5a21cc 100644 --- a/src/lib/stores/conversations.ts +++ b/src/lib/stores/conversations.ts @@ -14,6 +14,7 @@ export interface Conversation { characterState: CharacterState; isProcessing: boolean; grantedTools: Set; + pendingPermission: PermissionRequest | null; createdAt: Date; lastActivityAt: Date; } @@ -21,7 +22,6 @@ export interface Conversation { function createConversationsStore() { const conversations = writable>(new Map()); const activeConversationId = writable(null); - const pendingPermission = writable(null); const pendingRetryMessage = writable(null); let conversationCounter = 0; @@ -47,6 +47,7 @@ function createConversationsStore() { characterState: "idle", isProcessing: false, grantedTools: new Set(), + pendingPermission: null, createdAt: new Date(), lastActivityAt: new Date(), }; @@ -93,6 +94,10 @@ function createConversationsStore() { activeConversation, ($conv) => $conv?.grantedTools || new Set() ); + const pendingPermission = derived( + activeConversation, + ($conv) => $conv?.pendingPermission || null + ); return { // Expose derived stores for compatibility @@ -148,8 +153,52 @@ function createConversationsStore() { return convs; }); }, - requestPermission: (request: PermissionRequest) => pendingPermission.set(request), - clearPermission: () => pendingPermission.set(null), + requestPermission: (request: PermissionRequest) => { + const activeId = get(activeConversationId); + if (!activeId) return; + + conversations.update((convs) => { + const conv = convs.get(activeId); + if (conv) { + conv.pendingPermission = request; + conv.lastActivityAt = new Date(); + } + return convs; + }); + }, + clearPermission: () => { + const activeId = get(activeConversationId); + if (!activeId) return; + + conversations.update((convs) => { + const conv = convs.get(activeId); + if (conv) { + conv.pendingPermission = null; + conv.lastActivityAt = new Date(); + } + return convs; + }); + }, + requestPermissionForConversation: (conversationId: string, request: PermissionRequest) => { + conversations.update((convs) => { + const conv = convs.get(conversationId); + if (conv) { + conv.pendingPermission = request; + conv.lastActivityAt = new Date(); + } + return convs; + }); + }, + clearPermissionForConversation: (conversationId: string) => { + conversations.update((convs) => { + const conv = convs.get(conversationId); + if (conv) { + conv.pendingPermission = null; + conv.lastActivityAt = new Date(); + } + return convs; + }); + }, setPendingRetryMessage: (message: string | null) => pendingRetryMessage.set(message), // Conversation management diff --git a/src/lib/tauri.ts b/src/lib/tauri.ts index a9310e7..30a0eaf 100644 --- a/src/lib/tauri.ts +++ b/src/lib/tauri.ts @@ -292,25 +292,27 @@ export async function initializeTauriListeners() { const permissionUnlisten = await listen("claude:permission", (event) => { const { id, tool_name, tool_input, description, conversation_id } = event.payload; - // Only process permission requests for the active conversation - const activeConversationId = get(claudeStore.activeConversationId); - if (conversation_id === activeConversationId) { + // Store permission request for the specific conversation + if (conversation_id) { + claudeStore.requestPermissionForConversation(conversation_id, { + id, + tool: tool_name, + description, + input: tool_input, + }); + claudeStore.addLineToConversation( + conversation_id, + "system", + `Permission requested for: ${tool_name}` + ); + } else { + // Fallback to active conversation if no conversation_id claudeStore.requestPermission({ id, tool: tool_name, description, input: tool_input, }); - } - - // Always store the permission message to the correct conversation - if (conversation_id) { - claudeStore.addLineToConversation( - conversation_id, - "system", - `Permission requested for: ${tool_name}` - ); - } else if (conversation_id === activeConversationId) { claudeStore.addLine("system", `Permission requested for: ${tool_name}`); } });