From da10c45e763f253abfca0f82038901a8587c113a Mon Sep 17 00:00:00 2001 From: claude-code-best Date: Tue, 9 Jun 2026 23:00:06 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=B0=86=20pipeIpc=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=88=B0=20AppState=20=E7=B1=BB=E5=9E=8B=E5=A3=B0=E6=98=8E?= =?UTF-8?q?=EF=BC=8C=E6=B6=88=E9=99=A4=204=20=E4=B8=AA=20as=20any?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - AppStateStore: 添加 pipeIpc?: PipeIpcState 可选字段 - PromptInputFooter: 直接访问 s.pipeIpc - useBackgroundTaskNavigation: 直接访问 s.pipeIpc - usePipeRouter: 直接访问 store.getState().pipeIpc - REPL.tsx: 移除 getPipeIpc(s as any) 中的 as any precheck 通过 --- src/components/PromptInput/PromptInputFooter.tsx | 2 +- src/hooks/useBackgroundTaskNavigation.ts | 2 +- src/hooks/usePipeRouter.ts | 2 +- src/screens/REPL.tsx | 2 +- src/state/AppStateStore.ts | 3 +++ 5 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/components/PromptInput/PromptInputFooter.tsx b/src/components/PromptInput/PromptInputFooter.tsx index fef8c74f0..9c7970fef 100644 --- a/src/components/PromptInput/PromptInputFooter.tsx +++ b/src/components/PromptInput/PromptInputFooter.tsx @@ -256,7 +256,7 @@ function PipeStatusInline(): React.ReactNode { if (!feature('UDS_INBOX')) return null; // All hooks must be called before any conditional return to maintain // consistent hook count across renders (React rules of hooks). - const pipeIpc = useAppState(s => (s as any).pipeIpc); + const pipeIpc = useAppState(s => s.pipeIpc); const setAppState = useSetAppState(); const [cursorIndex, setCursorIndex] = useState(0); diff --git a/src/hooks/useBackgroundTaskNavigation.ts b/src/hooks/useBackgroundTaskNavigation.ts index 93ac7994c..9e0b678fd 100644 --- a/src/hooks/useBackgroundTaskNavigation.ts +++ b/src/hooks/useBackgroundTaskNavigation.ts @@ -72,7 +72,7 @@ export function useBackgroundTaskNavigation(options?: { const viewSelectionMode = useAppState(s => s.viewSelectionMode) const viewingAgentTaskId = useAppState(s => s.viewingAgentTaskId) const selectedIPAgentIndex = useAppState(s => s.selectedIPAgentIndex) - const pipeIpc = useAppState(s => (s as any).pipeIpc) + const pipeIpc = useAppState(s => s.pipeIpc) const setAppState = useSetAppState() // Filter to running teammates and sort alphabetically to match TeammateSpinnerTree display diff --git a/src/hooks/usePipeRouter.ts b/src/hooks/usePipeRouter.ts index f3e8dd4a5..6388c4e31 100644 --- a/src/hooks/usePipeRouter.ts +++ b/src/hooks/usePipeRouter.ts @@ -37,7 +37,7 @@ export function usePipeRouter({ store, setAppState, addNotification }: Deps): { if (!input.trim() || input.trim().startsWith('/')) return false /* eslint-disable @typescript-eslint/no-require-imports */ - const pipeState = (store.getState() as any).pipeIpc + const pipeState = store.getState().pipeIpc const selectedPipes: string[] = pipeState?.selectedPipes ?? [] const routeMode: 'selected' | 'local' = pipeState?.routeMode ?? 'selected' diff --git a/src/screens/REPL.tsx b/src/screens/REPL.tsx index cb4a7d975..b07655f63 100644 --- a/src/screens/REPL.tsx +++ b/src/screens/REPL.tsx @@ -4966,7 +4966,7 @@ export function REPL({ useMailboxBridge({ isLoading, onSubmitMessage: handleIncomingPrompt }); useMasterMonitor(); useSlaveNotifications(); - const _pipeIpcState = useAppState(s => getPipeIpc(s as any)); + const _pipeIpcState = useAppState(s => getPipeIpc(s)); usePipePermissionForward({ store, tools, setMessages, setToolUseConfirmQueue, getToolUseContext, mainLoopModel }); usePipeMuteSync({ setToolUseConfirmQueue }); diff --git a/src/state/AppStateStore.ts b/src/state/AppStateStore.ts index 92f6fb735..5adccaad2 100644 --- a/src/state/AppStateStore.ts +++ b/src/state/AppStateStore.ts @@ -36,6 +36,7 @@ import type { PermissionMode } from '../utils/permissions/PermissionMode.js' import { getInitialSettings } from '../utils/settings/settings.js' import type { SettingsJson } from '../utils/settings/types.js' import { shouldEnableThinkingByDefault } from '../utils/thinking.js' +import type { PipeIpcState } from '../utils/pipeTransport.js' import type { Store } from './store.js' export type CompletionBoundary = @@ -159,6 +160,8 @@ export type AppState = DeepImmutable<{ replBridgeInitialName: string | undefined // Always-on bridge: first-time remote dialog pending (set by /remote-control command) showRemoteCallout: boolean + // Pipe IPC state — added at runtime when feature('PIPE_IPC') is enabled. + pipeIpc?: PipeIpcState }> & { // Unified task state - excluded from DeepImmutable because TaskState contains function types tasks: { [taskId: string]: TaskState }