Skip to content

Commit 08d4e74

Browse files
feat: auto-accept toggle in composer, fix generating state on session_ready, remove approve-and-remember
1 parent 4708e5d commit 08d4e74

3 files changed

Lines changed: 55 additions & 43 deletions

File tree

crates/tauri-app/frontend/src/components/chat/ChatArea.tsx

Lines changed: 10 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -267,26 +267,15 @@ export function ChatArea() {
267267
{(approval) => {
268268
const toolName = () => approval.description.split(":")[0]?.trim() || "tool";
269269

270-
function handleApproveAndRemember() {
271-
// Store an allow rule for this tool
272-
const rule = `${toolName()}`;
273-
ipc.getSetting("allowed_tools").then((current) => {
274-
const rules = current ? current.split(",") : [];
275-
if (!rules.includes(rule)) {
276-
rules.push(rule);
277-
ipc.setSetting("allowed_tools", rules.join(","));
278-
}
279-
}).catch(() => {});
280-
approveRequest(approval);
281-
}
282-
283-
function handleBypassSession() {
284-
// Approve this request and set session to bypass
270+
function handleAutoAccept() {
271+
// Set permission mode to bypass and approve ALL pending
285272
ipc.setSetting("permission_mode", "bypassPermissions").catch(() => {});
273+
appStore.setStore("autoAcceptEnabled", true);
286274
// Approve all pending approvals for this thread
287-
store.pendingApprovals
288-
.filter((a) => a.threadId === approval.threadId)
289-
.forEach((a) => approveRequest(a));
275+
const pending = [...store.pendingApprovals.filter((a) => a.threadId === approval.threadId)];
276+
for (const a of pending) {
277+
approveRequest(a);
278+
}
290279
}
291280

292281
return (
@@ -303,11 +292,8 @@ export function ChatArea() {
303292
<div class="approval-actions">
304293
<button class="deny-btn" onClick={() => denyRequest(approval)}>Deny</button>
305294
<button class="approve-btn" onClick={() => approveRequest(approval)}>Approve</button>
306-
<button class="approve-remember-btn" onClick={handleApproveAndRemember} title={`Always allow ${toolName()}`}>
307-
Approve &amp; Remember
308-
</button>
309-
<button class="bypass-btn" onClick={handleBypassSession} title="Auto-approve everything for this session">
310-
Bypass All
295+
<button class="bypass-btn" onClick={handleAutoAccept} title="Auto-approve everything from now on">
296+
Auto Accept
311297
</button>
312298
</div>
313299
</div>
@@ -910,7 +896,7 @@ if (!document.getElementById("chat-styles")) {
910896
border-radius: var(--radius-pill);
911897
}
912898
.approval-actions { display: flex; gap: 6px; justify-content: flex-end; flex-wrap: wrap; }
913-
.approve-btn, .deny-btn, .approve-remember-btn, .bypass-btn {
899+
.approve-btn, .deny-btn, .bypass-btn {
914900
padding: 6px 12px;
915901
border-radius: var(--radius-sm);
916902
font-size: 11px;
@@ -922,15 +908,6 @@ if (!document.getElementById("chat-styles")) {
922908
color: #fff;
923909
}
924910
.approve-btn:hover { filter: brightness(1.1); transform: translateY(-1px); }
925-
.approve-remember-btn {
926-
background: rgba(76, 214, 148, 0.12);
927-
border: 1px solid rgba(76, 214, 148, 0.25);
928-
color: var(--green);
929-
}
930-
.approve-remember-btn:hover {
931-
background: rgba(76, 214, 148, 0.2);
932-
border-color: rgba(76, 214, 148, 0.4);
933-
}
934911
.bypass-btn {
935912
background: rgba(240, 184, 64, 0.1);
936913
border: 1px solid rgba(240, 184, 64, 0.2);

crates/tauri-app/frontend/src/components/composer/Composer.tsx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,21 @@ export function Composer() {
352352
<svg class="chevron" width="8" height="8" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><polyline points="6 9 12 15 18 9" /></svg>
353353
</button>
354354
<ModelSelector />
355+
<button
356+
class="meta-pill"
357+
classList={{ "meta-pill--active": store.autoAcceptEnabled }}
358+
onClick={() => {
359+
const next = !store.autoAcceptEnabled;
360+
appStore.setStore("autoAcceptEnabled", next);
361+
ipc.setSetting("permission_mode", next ? "bypassPermissions" : "default").catch(() => {});
362+
}}
363+
title={store.autoAcceptEnabled ? "Auto-accepting all tools (click to require approval)" : "Requiring approval (click to auto-accept)"}
364+
>
365+
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
366+
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" />
367+
</svg>
368+
{store.autoAcceptEnabled ? "Auto" : "Ask"}
369+
</button>
355370
<button class="meta-pill subtle" onClick={pickFolder}>
356371
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
357372
<path d="M22 19a2 2 0 01-2 2H4a2 2 0 01-2-2V5a2 2 0 012-2h5l2 3h9a2 2 0 012 2z" />
@@ -571,6 +586,15 @@ if (!document.getElementById("composer-styles")) {
571586
gap: 5px;
572587
}
573588
.meta-pill:hover { background: var(--bg-accent); border-color: var(--border-strong); }
589+
.meta-pill--active {
590+
background: rgba(76, 214, 148, 0.1);
591+
border-color: rgba(76, 214, 148, 0.2);
592+
color: var(--green);
593+
}
594+
.meta-pill--active:hover {
595+
background: rgba(76, 214, 148, 0.15);
596+
border-color: rgba(76, 214, 148, 0.3);
597+
}
574598
.meta-pill .chevron {
575599
color: var(--text-tertiary);
576600
transition: color 0.15s;

crates/tauri-app/frontend/src/stores/app-store.ts

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ export interface AppStore {
4242
attachments: Attachment[];
4343
threadTokenUsage: Record<string, ThreadTokenUsage>;
4444
notificationsEnabled: boolean;
45+
autoAcceptEnabled: boolean;
4546
threadMessagesLoading: Record<string, boolean>;
4647
projectGitStatus: Record<string, "none" | "git" | "github">;
4748
projectPrMap: Record<string, Record<string, number>>;
@@ -80,6 +81,7 @@ function createAppStore() {
8081
attachments: [],
8182
threadTokenUsage: {},
8283
notificationsEnabled: true,
84+
autoAcceptEnabled: false,
8385
threadMessagesLoading: {},
8486
projectGitStatus: {},
8587
projectPrMap: {},
@@ -557,7 +559,11 @@ function createAppStore() {
557559
break;
558560
}
559561
case "session_ready":
560-
setStore("sessionStatuses", thread_id, "ready");
562+
// Don't reset to "ready" if we're mid-generation —
563+
// session_ready fires when the sidecar initializes but before the response
564+
if (store.sessionStatuses[thread_id] !== "generating") {
565+
setStore("sessionStatuses", thread_id, "ready");
566+
}
561567
break;
562568
case "session_error": {
563569
setStore("sessionStatuses", thread_id, "error");
@@ -572,15 +578,20 @@ function createAppStore() {
572578
}
573579
case "approval_required":
574580
if (payload.request_id && payload.description) {
575-
setStore("pendingApprovals", (a) => [
576-
...a,
577-
{
578-
sessionId: payload.session_id,
579-
requestId: payload.request_id!,
580-
description: payload.description!,
581-
threadId: thread_id,
582-
},
583-
]);
581+
// Auto-accept if enabled
582+
if (store.autoAcceptEnabled) {
583+
ipc.respondToApproval(payload.session_id, payload.request_id!, true).catch(() => {});
584+
} else {
585+
setStore("pendingApprovals", (a) => [
586+
...a,
587+
{
588+
sessionId: payload.session_id,
589+
requestId: payload.request_id!,
590+
description: payload.description!,
591+
threadId: thread_id,
592+
},
593+
]);
594+
}
584595
}
585596
break;
586597
}

0 commit comments

Comments
 (0)