From de9494c0a3c10693b38c621f1afd5b3bc6000777 Mon Sep 17 00:00:00 2001 From: claude-code-best Date: Sun, 26 Apr 2026 15:01:31 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=20RSS=20=E5=86=85?= =?UTF-8?q?=E5=AD=98=E6=8C=87=E7=A4=BA=E5=99=A8=E5=B9=B6=E8=A7=A3=E7=BB=91?= =?UTF-8?q?=20auto=20=E6=9D=83=E9=99=90=E6=A8=A1=E5=BC=8F=E4=B8=8E=20TRANS?= =?UTF-8?q?CRIPT=5FCLASSIFIER?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 REPL 底栏添加 RSS 内存使用显示,512MB 以下 dimColor,512MB-1GB warning 色,1GB 以上 error 色 - auto 权限模式不再依赖 TRANSCRIPT_CLASSIFIER feature flag,classifier 不可用时 fallback 到 prompting - Config 面板 defaultPermissionMode 使用类型安全的 permissionModeFromString,显示改用 shortTitle - bypassPermissions title 缩短为 Bypass 与 shortTitle 一致 Co-Authored-By: Claude Opus 4.7 --- .../PromptInput/PromptInputFooterLeftSide.tsx | 35 ++++++++++++++++++- src/components/Settings/Config.tsx | 8 +++-- src/types/permissions.ts | 4 ++- src/utils/permissions/PermissionMode.ts | 20 +++++------ src/utils/settings/types.ts | 6 +--- 5 files changed, 52 insertions(+), 21 deletions(-) diff --git a/src/components/PromptInput/PromptInputFooterLeftSide.tsx b/src/components/PromptInput/PromptInputFooterLeftSide.tsx index 8130c8ef1..ab3814786 100644 --- a/src/components/PromptInput/PromptInputFooterLeftSide.tsx +++ b/src/components/PromptInput/PromptInputFooterLeftSide.tsx @@ -42,7 +42,7 @@ import { usePrStatus } from '../../hooks/usePrStatus.js' import { Byline, KeyboardShortcutHint } from '@anthropic/ink' import { useTerminalSize } from '../../hooks/useTerminalSize.js' import { useTasksV2 } from '../../hooks/useTasksV2.js' -import { formatDuration } from '../../utils/format.js' +import { formatDuration, formatFileSize } from '../../utils/format.js' import { VoiceWarmupHint } from './VoiceIndicator.js' import { useVoiceEnabled } from '../../hooks/useVoiceEnabled.js' import { useVoiceState } from '../../context/voice.js' @@ -63,6 +63,26 @@ const NO_OP_SUBSCRIBE = (_cb: () => void) => () => {} const NULL = () => null const MAX_VOICE_HINT_SHOWS = 3 +const RSS_UPDATE_INTERVAL_MS = 5_000 + +type RssState = { text: string; level: 'normal' | 'warning' | 'error' } + +function useRssDisplay(): RssState | null { + const [state, setState] = useState(null) + useEffect(() => { + function update(): void { + const mb = process.memoryUsage().rss / (1024 * 1024) + const level = mb >= 1024 ? 'error' : mb >= 512 ? 'warning' : 'normal' + const text = formatFileSize(mb * 1024 * 1024) + setState(prev => (prev?.text === text ? prev : { text, level })) + } + update() + const timer = setInterval(update, RSS_UPDATE_INTERVAL_MS) + return () => clearInterval(timer) + }, []) + return state +} + type Props = { exitMessage: { show: boolean @@ -315,6 +335,7 @@ function ModeIndicator({ const isKillAgentsConfirmShowing = useAppState( s => s.notifications.current?.key === 'kill-agents-confirm', ) + const rssState = useRssDisplay() // Derive team info from teamContext (no filesystem I/O needed) // Match the same logic as TeamStatus to avoid trailing separator @@ -428,6 +449,18 @@ function ModeIndicator({ />, ] : []), + // RSS memory indicator — always visible + ...(rssState + ? [ + + {rssState.text} + , + ] + : []), ] // Check if any in-process teammates exist (for hint text cycling) diff --git a/src/components/Settings/Config.tsx b/src/components/Settings/Config.tsx index 0a03317d2..7f8207d0f 100644 --- a/src/components/Settings/Config.tsx +++ b/src/components/Settings/Config.tsx @@ -16,6 +16,7 @@ import { import chalk from 'chalk'; import { permissionModeTitle, + permissionModeShortTitle, permissionModeFromString, toExternalPermissionMode, isExternalPermissionMode, @@ -167,6 +168,9 @@ export function Config({ const thinkingEnabled = useAppState(s => s.thinkingEnabled); const isFastMode = useAppState(s => (isFastModeEnabled() ? s.fastMode : false)); const promptSuggestionEnabled = useAppState(s => s.promptSuggestionEnabled); + const currentDefaultPermissionMode = permissionModeFromString( + settingsData?.permissions?.defaultMode ?? 'default', + ); // Show auto in the default-mode dropdown when the user has opted in OR the // config is fully 'enabled' — even if currently circuit-broken ('disabled'), // an opted-in user should still see it in settings (it's a temporary state). @@ -558,7 +562,7 @@ export function Config({ { id: 'defaultPermissionMode', label: 'Default permission mode', - value: settingsData?.permissions?.defaultMode || 'default', + value: currentDefaultPermissionMode, options: (() => { const priorityOrder: PermissionMode[] = ['default', 'plan']; return [...priorityOrder, ...PERMISSION_MODES.filter(m => !priorityOrder.includes(m))]; @@ -1961,7 +1965,7 @@ export function Config({ ) : setting.id === 'defaultPermissionMode' ? ( - {permissionModeTitle(setting.value as PermissionMode)} + {permissionModeShortTitle(setting.value as PermissionMode)} ) : setting.id === 'autoUpdatesChannel' && autoUpdaterDisabledReason ? ( diff --git a/src/types/permissions.ts b/src/types/permissions.ts index 32ef776b2..b0bfe917c 100644 --- a/src/types/permissions.ts +++ b/src/types/permissions.ts @@ -30,9 +30,11 @@ export type PermissionMode = InternalPermissionMode // Runtime validation set: modes that are user-addressable (settings.json // defaultMode, --permission-mode CLI flag, conversation recovery). +// 'auto' is always available — when TRANSCRIPT_CLASSIFIER is off, the +// classifier is unavailable and auto mode falls back to prompting. export const INTERNAL_PERMISSION_MODES = [ ...EXTERNAL_PERMISSION_MODES, - ...(feature('TRANSCRIPT_CLASSIFIER') ? (['auto'] as const) : ([] as const)), + 'auto' as const, ] as const satisfies readonly PermissionMode[] export const PERMISSION_MODES = INTERNAL_PERMISSION_MODES diff --git a/src/utils/permissions/PermissionMode.ts b/src/utils/permissions/PermissionMode.ts index 0dbd93639..ac02d9bbf 100644 --- a/src/utils/permissions/PermissionMode.ts +++ b/src/utils/permissions/PermissionMode.ts @@ -64,7 +64,7 @@ const PERMISSION_MODE_CONFIG: Partial< external: 'acceptEdits', }, bypassPermissions: { - title: 'Bypass Permissions', + title: 'Bypass', shortTitle: 'Bypass', symbol: '⏵⏵', color: 'error', @@ -77,17 +77,13 @@ const PERMISSION_MODE_CONFIG: Partial< color: 'error', external: 'dontAsk', }, - ...(feature('TRANSCRIPT_CLASSIFIER') - ? { - auto: { - title: 'Auto mode', - shortTitle: 'Auto', - symbol: '⏵⏵', - color: 'warning' as ModeColorKey, - external: 'default' as ExternalPermissionMode, - }, - } - : {}), + auto: { + title: 'Auto', + shortTitle: 'Auto', + symbol: '⏵⏵', + color: 'warning' as ModeColorKey, + external: 'default' as ExternalPermissionMode, + }, } /** diff --git a/src/utils/settings/types.ts b/src/utils/settings/types.ts index f715c568d..e7b0bbfb5 100644 --- a/src/utils/settings/types.ts +++ b/src/utils/settings/types.ts @@ -57,11 +57,7 @@ export const PermissionsSchema = lazySchema(() => 'List of permission rules that should always prompt for confirmation', ), defaultMode: z - .enum( - feature('TRANSCRIPT_CLASSIFIER') - ? PERMISSION_MODES - : EXTERNAL_PERMISSION_MODES, - ) + .enum(PERMISSION_MODES) .optional() .describe('Default permission mode when Claude Code needs access'), disableBypassPermissionsMode: z