Skip to content

Commit ff7c889

Browse files
charlesvienjonathanlab
authored andcommitted
Fix permission rejection bricking chat
1 parent 712cac3 commit ff7c889

File tree

1 file changed

+30
-27
lines changed

1 file changed

+30
-27
lines changed

apps/twig/src/renderer/features/sessions/stores/sessionStore.ts

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,6 +1248,21 @@ const useStore = create<SessionStore>()(
12481248
return;
12491249
}
12501250

1251+
// Always remove permission from UI state first - the user has taken action
1252+
// and we should clear the selector regardless of backend success
1253+
const currentState = get();
1254+
const sess = currentState.sessions[session.taskRunId];
1255+
if (sess) {
1256+
const newPermissions = new Map(sess.pendingPermissions);
1257+
newPermissions.delete(toolCallId);
1258+
set((draft) => {
1259+
if (draft.sessions[session.taskRunId]) {
1260+
draft.sessions[session.taskRunId].pendingPermissions =
1261+
newPermissions;
1262+
}
1263+
});
1264+
}
1265+
12511266
try {
12521267
await trpcVanilla.agent.respondToPermission.mutate({
12531268
sessionId: session.taskRunId,
@@ -1257,20 +1272,6 @@ const useStore = create<SessionStore>()(
12571272
customInput,
12581273
});
12591274

1260-
// Create new Map outside of Immer (Maps don't work well with Immer proxies)
1261-
const currentState = get();
1262-
const sess = currentState.sessions[session.taskRunId];
1263-
if (sess) {
1264-
const newPermissions = new Map(sess.pendingPermissions);
1265-
newPermissions.delete(toolCallId);
1266-
set((draft) => {
1267-
if (draft.sessions[session.taskRunId]) {
1268-
draft.sessions[session.taskRunId].pendingPermissions =
1269-
newPermissions;
1270-
}
1271-
});
1272-
}
1273-
12741275
log.info("Permission response sent", {
12751276
taskId,
12761277
toolCallId,
@@ -1329,25 +1330,27 @@ const useStore = create<SessionStore>()(
13291330
return;
13301331
}
13311332

1333+
// Always remove permission from UI state first - the user has taken action
1334+
// and we should clear the selector regardless of backend success
1335+
const currentState = get();
1336+
const sess = currentState.sessions[session.taskRunId];
1337+
if (sess) {
1338+
const newPermissions = new Map(sess.pendingPermissions);
1339+
newPermissions.delete(toolCallId);
1340+
set((draft) => {
1341+
if (draft.sessions[session.taskRunId]) {
1342+
draft.sessions[session.taskRunId].pendingPermissions =
1343+
newPermissions;
1344+
}
1345+
});
1346+
}
1347+
13321348
try {
13331349
await trpcVanilla.agent.cancelPermission.mutate({
13341350
sessionId: session.taskRunId,
13351351
toolCallId,
13361352
});
13371353

1338-
const currentState = get();
1339-
const sess = currentState.sessions[session.taskRunId];
1340-
if (sess) {
1341-
const newPermissions = new Map(sess.pendingPermissions);
1342-
newPermissions.delete(toolCallId);
1343-
set((draft) => {
1344-
if (draft.sessions[session.taskRunId]) {
1345-
draft.sessions[session.taskRunId].pendingPermissions =
1346-
newPermissions;
1347-
}
1348-
});
1349-
}
1350-
13511354
log.info("Permission cancelled", { taskId, toolCallId });
13521355

13531356
// Persist permission cancellation to logs for recovery tracking

0 commit comments

Comments
 (0)