feat: auto-allow all tools toggle + fix team color fallback

- Add autoAllowAll setting: overrides all individual auto-allow rules,
  instantly approves every tool call without user interaction
- Settings panel: "Auto-allow all tools" checkbox at top, individual
  checkboxes greyed out when all-allow is active
- Fix team color badge: use getTeamColorSet(teamName) as fallback
  instead of getMemberColorByName which uses a different palette
  and produced wrong colors (yellow instead of pink)
This commit is contained in:
iliya 2026-03-21 12:25:06 +02:00
parent 0ebfd85b47
commit 73661c80a4
6 changed files with 42 additions and 9 deletions

View file

@ -2767,6 +2767,9 @@ async function handleToolApprovalSettings(
return { success: false, error: 'Settings must be an object' }; return { success: false, error: 'Settings must be an object' };
} }
const s = settings as Record<string, unknown>; const s = settings as Record<string, unknown>;
if (typeof s.autoAllowAll !== 'boolean') {
return { success: false, error: 'autoAllowAll must be a boolean' };
}
if (typeof s.autoAllowFileEdits !== 'boolean') { if (typeof s.autoAllowFileEdits !== 'boolean') {
return { success: false, error: 'autoAllowFileEdits must be a boolean' }; return { success: false, error: 'autoAllowFileEdits must be a boolean' };
} }

View file

@ -116,6 +116,11 @@ export function shouldAutoAllow(
toolName: string, toolName: string,
toolInput: Record<string, unknown> toolInput: Record<string, unknown>
): AutoAllowResult { ): AutoAllowResult {
// Auto-allow ALL tools (overrides everything)
if (settings.autoAllowAll) {
return { autoAllow: true, reason: 'auto_allow_all' };
}
// File edit auto-allow // File edit auto-allow
if (settings.autoAllowFileEdits && FILE_EDIT_TOOLS.has(toolName)) { if (settings.autoAllowFileEdits && FILE_EDIT_TOOLS.has(toolName)) {
return { autoAllow: true, reason: 'auto_allow_category' }; return { autoAllow: true, reason: 'auto_allow_category' };

View file

@ -4,7 +4,6 @@ import { getTeamColorSet, getThemedBadge } from '@renderer/constants/teamColors'
import { useTheme } from '@renderer/hooks/useTheme'; import { useTheme } from '@renderer/hooks/useTheme';
import { useStore } from '@renderer/store'; import { useStore } from '@renderer/store';
import { highlightLines } from '@renderer/utils/syntaxHighlighter'; import { highlightLines } from '@renderer/utils/syntaxHighlighter';
import { getMemberColorByName } from '@shared/constants/memberColors';
import { AlertTriangle, FileText, Search, Terminal } from 'lucide-react'; import { AlertTriangle, FileText, Search, Terminal } from 'lucide-react';
import { ToolApprovalDiffPreview } from './ToolApprovalDiffPreview'; import { ToolApprovalDiffPreview } from './ToolApprovalDiffPreview';
@ -170,10 +169,9 @@ export const ToolApprovalSheet: React.FC = () => {
if (!current) return null; if (!current) return null;
// Prefer color from the approval itself (always available, even during provisioning), // Prefer color from the approval itself (always available, even during provisioning),
// fall back to teams list, then deterministic color from team name. // fall back to teams list, then getTeamColorSet hashes unknown names into TEAMMATE_COLORS.
const teamSummary = teams.find((t) => t.teamName === current.teamName); const teamSummary = teams.find((t) => t.teamName === current.teamName);
const colorName = const colorName = current.teamColor ?? teamSummary?.color ?? current.teamName;
current.teamColor ?? teamSummary?.color ?? getMemberColorByName(current.teamName);
const teamColor = getTeamColorSet(colorName); const teamColor = getTeamColorSet(colorName);
const displayName = current.teamDisplayName ?? teamSummary?.displayName ?? current.teamName; const displayName = current.teamDisplayName ?? teamSummary?.displayName ?? current.teamName;

View file

@ -50,13 +50,32 @@ export const ToolApprovalSettingsPanel: React.FC = () => {
borderColor: 'var(--color-border)', borderColor: 'var(--color-border)',
}} }}
> >
{/* Auto-allow file edits */} {/* Auto-allow ALL */}
<label <label
className="flex items-center gap-2 text-xs" className="flex items-center gap-2 text-xs font-medium"
style={{ color: 'var(--color-text-secondary)' }} style={{ color: 'var(--color-text-secondary)' }}
> >
<Checkbox <Checkbox
checked={settings.autoAllowFileEdits} checked={settings.autoAllowAll}
onCheckedChange={(checked) => void updateSettings({ autoAllowAll: checked === true })}
/>
Auto-allow all tools
</label>
{/* Separator */}
<div className="border-t" style={{ borderColor: 'var(--color-border)' }} />
{/* Auto-allow file edits */}
<label
className="flex items-center gap-2 text-xs"
style={{
color: 'var(--color-text-secondary)',
opacity: settings.autoAllowAll ? 0.5 : 1,
}}
>
<Checkbox
checked={settings.autoAllowAll || settings.autoAllowFileEdits}
disabled={settings.autoAllowAll}
onCheckedChange={(checked) => onCheckedChange={(checked) =>
void updateSettings({ autoAllowFileEdits: checked === true }) void updateSettings({ autoAllowFileEdits: checked === true })
} }
@ -67,10 +86,14 @@ export const ToolApprovalSettingsPanel: React.FC = () => {
{/* Auto-allow safe bash */} {/* Auto-allow safe bash */}
<label <label
className="flex items-center gap-2 text-xs" className="flex items-center gap-2 text-xs"
style={{ color: 'var(--color-text-secondary)' }} style={{
color: 'var(--color-text-secondary)',
opacity: settings.autoAllowAll ? 0.5 : 1,
}}
> >
<Checkbox <Checkbox
checked={settings.autoAllowSafeBash} checked={settings.autoAllowAll || settings.autoAllowSafeBash}
disabled={settings.autoAllowAll}
onCheckedChange={(checked) => onCheckedChange={(checked) =>
void updateSettings({ autoAllowSafeBash: checked === true }) void updateSettings({ autoAllowSafeBash: checked === true })
} }

View file

@ -727,6 +727,7 @@ function loadToolApprovalSettings(): ToolApprovalSettings {
const parsed = JSON.parse(raw) as Record<string, unknown>; const parsed = JSON.parse(raw) as Record<string, unknown>;
const d = DEFAULT_TOOL_APPROVAL_SETTINGS; const d = DEFAULT_TOOL_APPROVAL_SETTINGS;
return { return {
autoAllowAll: typeof parsed.autoAllowAll === 'boolean' ? parsed.autoAllowAll : d.autoAllowAll,
autoAllowFileEdits: autoAllowFileEdits:
typeof parsed.autoAllowFileEdits === 'boolean' typeof parsed.autoAllowFileEdits === 'boolean'
? parsed.autoAllowFileEdits ? parsed.autoAllowFileEdits

View file

@ -828,6 +828,8 @@ export type ToolApprovalTimeoutAction = 'allow' | 'deny' | 'wait';
/** User-configurable auto-allow settings for tool approval. */ /** User-configurable auto-allow settings for tool approval. */
export interface ToolApprovalSettings { export interface ToolApprovalSettings {
/** Auto-allow ALL tools (overrides individual settings below). */
autoAllowAll: boolean;
/** Auto-allow file edit tools (Edit, Write, NotebookEdit). */ /** Auto-allow file edit tools (Edit, Write, NotebookEdit). */
autoAllowFileEdits: boolean; autoAllowFileEdits: boolean;
/** Auto-allow safe bash commands (git, pnpm, npm, ls, cat, echo, etc.). */ /** Auto-allow safe bash commands (git, pnpm, npm, ls, cat, echo, etc.). */
@ -839,6 +841,7 @@ export interface ToolApprovalSettings {
} }
export const DEFAULT_TOOL_APPROVAL_SETTINGS: ToolApprovalSettings = { export const DEFAULT_TOOL_APPROVAL_SETTINGS: ToolApprovalSettings = {
autoAllowAll: false,
autoAllowFileEdits: false, autoAllowFileEdits: false,
autoAllowSafeBash: false, autoAllowSafeBash: false,
timeoutAction: 'wait', timeoutAction: 'wait',