mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-15 21:05:51 +00:00
- P0: REPL.tsx 用 useMemo 包裹 deferred messages slice,避免每次渲染创建新数组引用导致不必要的后台重渲染 - P1: 预测性 compact 阈值改用 effectiveContextWindow - growth,消除与 autocompact buffer 的双重预留;TOOL_RESULT_GROWTH_ESTIMATE 从 20K 降至 15K - P2: 增量 lookups 增加 lastAssistantMsgId 一致性检查和 orphaned server_tool_use/mcp_tool_use 扫描,防止 UI 永久 loading - P3: reactiveCompact 类型断言改为直接使用 'compact' 字面量 - docs: CLAUDE.md 统一使用 precheck 替代分散的 typecheck/lint/test 命令 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
98 lines
2.8 KiB
TypeScript
98 lines
2.8 KiB
TypeScript
import { isEnvTruthy } from '../../utils/envUtils.js'
|
|
import {
|
|
isMediaSizeErrorMessage,
|
|
isPromptTooLongMessage,
|
|
} from '../api/errors.js'
|
|
import type { AssistantMessage, Message } from '../../types/message.js'
|
|
import { type CompactionResult, compactConversation } from './compact.js'
|
|
import { logError } from '../../utils/log.js'
|
|
import { logForDebugging } from '../../utils/debug.js'
|
|
import type { CacheSafeParams } from '../../utils/forkedAgent.js'
|
|
|
|
export const isReactiveOnlyMode: () => boolean = () => false
|
|
|
|
export const reactiveCompactOnPromptTooLong: (
|
|
messages: Message[],
|
|
cacheSafeParams: Record<string, unknown>,
|
|
options: { customInstructions?: string; trigger?: string },
|
|
) => Promise<{ ok: boolean; reason?: string; result?: CompactionResult }> =
|
|
async (messages, cacheSafeParams, options) => {
|
|
const params = cacheSafeParams as unknown as CacheSafeParams
|
|
try {
|
|
const result = await compactConversation(
|
|
messages,
|
|
params.toolUseContext,
|
|
params,
|
|
true,
|
|
options.customInstructions,
|
|
true,
|
|
{
|
|
isRecompactionInChain: false,
|
|
turnsSincePreviousCompact: 0,
|
|
autoCompactThreshold: 0,
|
|
querySource: 'compact',
|
|
},
|
|
)
|
|
return { ok: true, result }
|
|
} catch (error) {
|
|
logError(error)
|
|
return { ok: false, reason: String(error) }
|
|
}
|
|
}
|
|
|
|
export const isReactiveCompactEnabled: () => boolean = () => {
|
|
if (isEnvTruthy(process.env.DISABLE_COMPACT)) return false
|
|
return true
|
|
}
|
|
|
|
export const isWithheldPromptTooLong: (message: Message) => boolean =
|
|
message => {
|
|
if (message.type !== 'assistant' || !message.isApiErrorMessage) return false
|
|
return isPromptTooLongMessage(message as AssistantMessage)
|
|
}
|
|
|
|
export const isWithheldMediaSizeError: (message: Message) => boolean =
|
|
message => {
|
|
if (message.type !== 'assistant' || !message.isApiErrorMessage) return false
|
|
return isMediaSizeErrorMessage(message as AssistantMessage)
|
|
}
|
|
|
|
export const tryReactiveCompact: (params: {
|
|
hasAttempted: boolean
|
|
querySource: string
|
|
aborted: boolean
|
|
messages: Message[]
|
|
cacheSafeParams: Record<string, unknown>
|
|
}) => Promise<CompactionResult | null> = async ({
|
|
hasAttempted,
|
|
aborted,
|
|
messages,
|
|
cacheSafeParams,
|
|
}) => {
|
|
if (hasAttempted || aborted) return null
|
|
const params = cacheSafeParams as unknown as CacheSafeParams
|
|
try {
|
|
const result = await compactConversation(
|
|
messages,
|
|
params.toolUseContext,
|
|
params,
|
|
true,
|
|
undefined,
|
|
true,
|
|
{
|
|
isRecompactionInChain: false,
|
|
turnsSincePreviousCompact: 0,
|
|
autoCompactThreshold: 0,
|
|
},
|
|
)
|
|
return result
|
|
} catch (error) {
|
|
logForDebugging(
|
|
`reactiveCompact: emergency compaction failed — ${String(error)}`,
|
|
{ level: 'warn' },
|
|
)
|
|
logError(error)
|
|
return null
|
|
}
|
|
}
|