fix: 修复 ACP 模式下 messageSelector require 失败导致 submitMessage 崩溃

ACP 模式不加载完整的 React/Ink UI 组件,导致 require('src/components/MessageSelector.js')
返回 undefined。添加 try-catch 和 optional chaining fallback。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
claude-code-best
2026-04-24 09:59:23 +08:00
parent b217836f5a
commit d6374f02d6

View File

@@ -86,9 +86,13 @@ import {
// Lazy: MessageSelector.tsx pulls React/ink; only needed for message filtering at query time // Lazy: MessageSelector.tsx pulls React/ink; only needed for message filtering at query time
/* eslint-disable @typescript-eslint/no-require-imports */ /* eslint-disable @typescript-eslint/no-require-imports */
const messageSelector = const messageSelector = (): typeof import('src/components/MessageSelector.js') | null => {
(): typeof import('src/components/MessageSelector.js') => try {
require('src/components/MessageSelector.js') return require('src/components/MessageSelector.js')
} catch {
return null
}
}
import { import {
localCommandOutputToSDKAssistantMessage, localCommandOutputToSDKAssistantMessage,
@@ -466,12 +470,13 @@ export class QueryEngine {
} }
// Filter messages that should be acknowledged after transcript // Filter messages that should be acknowledged after transcript
const _selector = messageSelector()
const replayableMessages = messagesFromUserInput.filter( const replayableMessages = messagesFromUserInput.filter(
msg => msg =>
(msg.type === 'user' && (msg.type === 'user' &&
!msg.isMeta && // Skip synthetic caveat messages !msg.isMeta && // Skip synthetic caveat messages
!msg.toolUseResult && // Skip tool results (they'll be acked from query) !msg.toolUseResult && // Skip tool results (they'll be acked from query)
messageSelector().selectableUserMessagesFilter(msg)) || // Skip non-user-authored messages (task notifications, etc.) (_selector?.selectableUserMessagesFilter(msg) ?? true)) || // Skip non-user-authored messages (task notifications, etc.)
(msg.type === 'system' && msg.subtype === 'compact_boundary'), // Always ack compact boundaries (msg.type === 'system' && msg.subtype === 'compact_boundary'), // Always ack compact boundaries
) )
const messagesToAck = replayUserMessages ? replayableMessages : [] const messagesToAck = replayUserMessages ? replayableMessages : []
@@ -643,8 +648,10 @@ export class QueryEngine {
} }
if (fileHistoryEnabled() && persistSession) { if (fileHistoryEnabled() && persistSession) {
const _sel = messageSelector()
const _filter = _sel?.selectableUserMessagesFilter ?? ((_msg: unknown) => true)
messagesFromUserInput messagesFromUserInput
.filter(messageSelector().selectableUserMessagesFilter) .filter(_filter)
.forEach(message => { .forEach(message => {
void fileHistoryMakeSnapshot( void fileHistoryMakeSnapshot(
(updater: (prev: FileHistoryState) => FileHistoryState) => { (updater: (prev: FileHistoryState) => FileHistoryState) => {