generated from nhcarrigan/template
fix: handle multiple tabs requesting permission
This commit is contained in:
@@ -47,6 +47,8 @@ export const claudeStore = {
|
|||||||
getConversationHistory: conversationsStore.getConversationHistory,
|
getConversationHistory: conversationsStore.getConversationHistory,
|
||||||
requestPermission: conversationsStore.requestPermission,
|
requestPermission: conversationsStore.requestPermission,
|
||||||
clearPermission: conversationsStore.clearPermission,
|
clearPermission: conversationsStore.clearPermission,
|
||||||
|
requestPermissionForConversation: conversationsStore.requestPermissionForConversation,
|
||||||
|
clearPermissionForConversation: conversationsStore.clearPermissionForConversation,
|
||||||
grantTool: conversationsStore.grantTool,
|
grantTool: conversationsStore.grantTool,
|
||||||
revokeAllTools: conversationsStore.revokeAllTools,
|
revokeAllTools: conversationsStore.revokeAllTools,
|
||||||
isToolGranted: conversationsStore.isToolGranted,
|
isToolGranted: conversationsStore.isToolGranted,
|
||||||
@@ -83,8 +85,8 @@ export const claudeStore = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const hasPermissionPending = derived(
|
export const hasPermissionPending = derived(
|
||||||
claudeStore.pendingPermission,
|
claudeStore.activeConversation,
|
||||||
($permission) => $permission !== null
|
($conversation) => $conversation?.pendingPermission !== null
|
||||||
);
|
);
|
||||||
|
|
||||||
// Derived store to check if Claude is currently processing (can be interrupted)
|
// Derived store to check if Claude is currently processing (can be interrupted)
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ export interface Conversation {
|
|||||||
characterState: CharacterState;
|
characterState: CharacterState;
|
||||||
isProcessing: boolean;
|
isProcessing: boolean;
|
||||||
grantedTools: Set<string>;
|
grantedTools: Set<string>;
|
||||||
|
pendingPermission: PermissionRequest | null;
|
||||||
createdAt: Date;
|
createdAt: Date;
|
||||||
lastActivityAt: Date;
|
lastActivityAt: Date;
|
||||||
}
|
}
|
||||||
@@ -21,7 +22,6 @@ export interface Conversation {
|
|||||||
function createConversationsStore() {
|
function createConversationsStore() {
|
||||||
const conversations = writable<Map<string, Conversation>>(new Map());
|
const conversations = writable<Map<string, Conversation>>(new Map());
|
||||||
const activeConversationId = writable<string | null>(null);
|
const activeConversationId = writable<string | null>(null);
|
||||||
const pendingPermission = writable<PermissionRequest | null>(null);
|
|
||||||
const pendingRetryMessage = writable<string | null>(null);
|
const pendingRetryMessage = writable<string | null>(null);
|
||||||
|
|
||||||
let conversationCounter = 0;
|
let conversationCounter = 0;
|
||||||
@@ -47,6 +47,7 @@ function createConversationsStore() {
|
|||||||
characterState: "idle",
|
characterState: "idle",
|
||||||
isProcessing: false,
|
isProcessing: false,
|
||||||
grantedTools: new Set(),
|
grantedTools: new Set(),
|
||||||
|
pendingPermission: null,
|
||||||
createdAt: new Date(),
|
createdAt: new Date(),
|
||||||
lastActivityAt: new Date(),
|
lastActivityAt: new Date(),
|
||||||
};
|
};
|
||||||
@@ -93,6 +94,10 @@ function createConversationsStore() {
|
|||||||
activeConversation,
|
activeConversation,
|
||||||
($conv) => $conv?.grantedTools || new Set<string>()
|
($conv) => $conv?.grantedTools || new Set<string>()
|
||||||
);
|
);
|
||||||
|
const pendingPermission = derived(
|
||||||
|
activeConversation,
|
||||||
|
($conv) => $conv?.pendingPermission || null
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
// Expose derived stores for compatibility
|
// Expose derived stores for compatibility
|
||||||
@@ -148,8 +153,52 @@ function createConversationsStore() {
|
|||||||
return convs;
|
return convs;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
requestPermission: (request: PermissionRequest) => pendingPermission.set(request),
|
requestPermission: (request: PermissionRequest) => {
|
||||||
clearPermission: () => pendingPermission.set(null),
|
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),
|
setPendingRetryMessage: (message: string | null) => pendingRetryMessage.set(message),
|
||||||
|
|
||||||
// Conversation management
|
// Conversation management
|
||||||
|
|||||||
+15
-13
@@ -292,25 +292,27 @@ export async function initializeTauriListeners() {
|
|||||||
const permissionUnlisten = await listen<PermissionPromptEvent>("claude:permission", (event) => {
|
const permissionUnlisten = await listen<PermissionPromptEvent>("claude:permission", (event) => {
|
||||||
const { id, tool_name, tool_input, description, conversation_id } = event.payload;
|
const { id, tool_name, tool_input, description, conversation_id } = event.payload;
|
||||||
|
|
||||||
// Only process permission requests for the active conversation
|
// Store permission request for the specific conversation
|
||||||
const activeConversationId = get(claudeStore.activeConversationId);
|
if (conversation_id) {
|
||||||
if (conversation_id === activeConversationId) {
|
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({
|
claudeStore.requestPermission({
|
||||||
id,
|
id,
|
||||||
tool: tool_name,
|
tool: tool_name,
|
||||||
description,
|
description,
|
||||||
input: tool_input,
|
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}`);
|
claudeStore.addLine("system", `Permission requested for: ${tool_name}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user