From b7c06db327de311509d04406877f7332b9eb28d1 Mon Sep 17 00:00:00 2001 From: weishu Date: Thu, 29 Jan 2026 15:41:19 +0800 Subject: [PATCH] refactor: extract agent flavor utility functions into shared module --- web/src/components/AssistantChat/HappyComposer.tsx | 5 +++-- web/src/components/ToolCard/PermissionFooter.tsx | 5 ++--- web/src/hooks/mutations/useSessionActions.ts | 4 ++-- web/src/lib/agentFlavorUtils.ts | 11 +++++++++++ 4 files changed, 18 insertions(+), 7 deletions(-) create mode 100644 web/src/lib/agentFlavorUtils.ts diff --git a/web/src/components/AssistantChat/HappyComposer.tsx b/web/src/components/AssistantChat/HappyComposer.tsx index 2c179a74..9f5b0761 100644 --- a/web/src/components/AssistantChat/HappyComposer.tsx +++ b/web/src/components/AssistantChat/HappyComposer.tsx @@ -20,6 +20,7 @@ import { useActiveSuggestions } from '@/hooks/useActiveSuggestions' import { applySuggestion } from '@/utils/applySuggestion' import { usePlatform } from '@/hooks/usePlatform' import { usePWAInstall } from '@/hooks/usePWAInstall' +import { isCodexFamilyFlavor } from '@/lib/agentFlavorUtils' import { markSkillUsed } from '@/lib/recent-skills' import { FloatingOverlay } from '@/components/ChatInput/FloatingOverlay' import { Autocomplete } from '@/components/ChatInput/Autocomplete' @@ -312,7 +313,7 @@ export function HappyComposer(props: { useEffect(() => { const handleGlobalKeyDown = (e: globalThis.KeyboardEvent) => { - if (e.key === 'm' && (e.metaKey || e.ctrlKey) && onModelModeChange && agentFlavor !== 'codex' && agentFlavor !== 'gemini' && agentFlavor !== 'opencode') { + if (e.key === 'm' && (e.metaKey || e.ctrlKey) && onModelModeChange && !isCodexFamilyFlavor(agentFlavor)) { e.preventDefault() const currentIndex = MODEL_MODES.indexOf(modelMode as typeof MODEL_MODES[number]) const nextIndex = (currentIndex + 1) % MODEL_MODES.length @@ -386,7 +387,7 @@ export function HappyComposer(props: { }, [onModelModeChange, controlsDisabled, haptic]) const showPermissionSettings = Boolean(onPermissionModeChange && permissionModeOptions.length > 0) - const showModelSettings = Boolean(onModelModeChange && agentFlavor !== 'codex' && agentFlavor !== 'gemini' && agentFlavor !== 'opencode') + const showModelSettings = Boolean(onModelModeChange && !isCodexFamilyFlavor(agentFlavor)) const showSettingsButton = Boolean(showPermissionSettings || showModelSettings) const showAbortButton = true const voiceEnabled = Boolean(onVoiceToggle) diff --git a/web/src/components/ToolCard/PermissionFooter.tsx b/web/src/components/ToolCard/PermissionFooter.tsx index 81b76ad0..3046663f 100644 --- a/web/src/components/ToolCard/PermissionFooter.tsx +++ b/web/src/components/ToolCard/PermissionFooter.tsx @@ -4,6 +4,7 @@ import type { SessionMetadataSummary } from '@/types/api' import type { ChatToolCall, ToolPermission } from '@/chat/types' import { usePlatform } from '@/hooks/usePlatform' import { Spinner } from '@/components/Spinner' +import { isCodexFamilyFlavor } from '@/lib/agentFlavorUtils' import { getInputStringAny } from '@/lib/toolInputUtils' import { useTranslation } from '@/lib/use-translation' @@ -22,9 +23,7 @@ function isToolAllowedForSession(toolName: string, toolInput: unknown, allowedTo } function isCodexSession(metadata: SessionMetadataSummary | null, toolName: string): boolean { - return metadata?.flavor === 'codex' - || metadata?.flavor === 'gemini' - || metadata?.flavor === 'opencode' + return isCodexFamilyFlavor(metadata?.flavor) || toolName.startsWith('Codex') || toolName.startsWith('Gemini') || toolName.startsWith('OpenCode') diff --git a/web/src/hooks/mutations/useSessionActions.ts b/web/src/hooks/mutations/useSessionActions.ts index e2dd299e..366d1cd3 100644 --- a/web/src/hooks/mutations/useSessionActions.ts +++ b/web/src/hooks/mutations/useSessionActions.ts @@ -4,6 +4,7 @@ import type { ApiClient } from '@/api/client' import type { ModelMode, PermissionMode } from '@/types/api' import { queryKeys } from '@/lib/query-keys' import { clearMessageWindow } from '@/lib/message-window-store' +import { isKnownFlavor } from '@/lib/agentFlavorUtils' export function useSessionActions( api: ApiClient | null, @@ -62,8 +63,7 @@ export function useSessionActions( if (!api || !sessionId) { throw new Error('Session unavailable') } - const isKnownFlavor = agentFlavor === 'claude' || agentFlavor === 'codex' || agentFlavor === 'gemini' || agentFlavor === 'opencode' - if (isKnownFlavor && !isPermissionModeAllowedForFlavor(mode, agentFlavor)) { + if (isKnownFlavor(agentFlavor) && !isPermissionModeAllowedForFlavor(mode, agentFlavor)) { throw new Error('Invalid permission mode for session flavor') } await api.setPermissionMode(sessionId, mode) diff --git a/web/src/lib/agentFlavorUtils.ts b/web/src/lib/agentFlavorUtils.ts new file mode 100644 index 00000000..d190e38c --- /dev/null +++ b/web/src/lib/agentFlavorUtils.ts @@ -0,0 +1,11 @@ +export function isCodexFamilyFlavor(flavor?: string | null): boolean { + return flavor === 'codex' || flavor === 'gemini' || flavor === 'opencode' +} + +export function isClaudeFlavor(flavor?: string | null): boolean { + return flavor === 'claude' +} + +export function isKnownFlavor(flavor?: string | null): boolean { + return isClaudeFlavor(flavor) || isCodexFamilyFlavor(flavor) +}