mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-17 13:55:50 +00:00
perf: 优化内存与遥测管理,启用 Vite minify
- 禁用 HISTORY_SNIP feature flag 并新增 proactiveTruncate 防止无 compact_boundary 时内存无限增长 - 跳过未启用 telemetry 时的 OTel 初始化,防止长会话 PerformanceMeasure 堆积 - OTel 导出遇 401/403 自动关闭 reader,防止 handle 泄漏 - Vite 构建启用 minify Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -163,3 +163,77 @@ export function isSnipRuntimeEnabled(): boolean {
|
||||
export function shouldNudgeForSnips(messages: Message[]): boolean {
|
||||
return messages.length >= SNIP_NUDGE_THRESHOLD
|
||||
}
|
||||
|
||||
/**
|
||||
* Maximum total character length of message content before proactive
|
||||
* truncation kicks in. ~150 MB of string data corresponds to roughly
|
||||
* 1.5x the default 200k-token context window at 4 chars/token — well
|
||||
* beyond what any model can actually use in a single request.
|
||||
*/
|
||||
const PROACTIVE_TRUNCATE_CHARS = 150_000_000
|
||||
|
||||
/**
|
||||
* Minimum number of messages to keep when falling back to tail-only
|
||||
* retention (i.e. when no compact_boundary exists in the array).
|
||||
*/
|
||||
const PROACTIVE_TRUNCATE_MIN_TAIL = 50
|
||||
|
||||
/**
|
||||
* Proactively truncate old messages when the in-memory store grows too
|
||||
* large. Unlike `snipCompactIfNeeded` (which waits for a snip_boundary
|
||||
* from the API), this runs client-side after every push — ensuring
|
||||
* unbounded growth cannot happen even when the API never returns a
|
||||
* compact_boundary (e.g. third-party compat layers).
|
||||
*
|
||||
* Strategy:
|
||||
* 1. If a `compact_boundary` exists, keep it and everything after it.
|
||||
* 2. Otherwise, keep only the last `PROACTIVE_TRUNCATE_MIN_TAIL` messages.
|
||||
*
|
||||
* Returns the same array reference when no truncation is needed.
|
||||
*/
|
||||
export function proactiveTruncate(messages: Message[]): Message[] {
|
||||
if (messages.length < PROACTIVE_TRUNCATE_MIN_TAIL) return messages
|
||||
|
||||
let totalChars = 0
|
||||
for (const msg of messages) {
|
||||
const content = msg.message?.content
|
||||
if (typeof content === 'string') {
|
||||
totalChars += content.length
|
||||
} else if (Array.isArray(content)) {
|
||||
for (const block of content) {
|
||||
if (typeof block === 'string') {
|
||||
totalChars += (block as string).length
|
||||
} else if (block && typeof block === 'object') {
|
||||
const obj = block as unknown as Record<string, unknown>
|
||||
const text = obj.text ?? obj.content
|
||||
if (typeof text === 'string') {
|
||||
totalChars += text.length
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (totalChars < PROACTIVE_TRUNCATE_CHARS) return messages
|
||||
|
||||
// Find last compact_boundary — the standard anchor point
|
||||
let boundaryIdx = -1
|
||||
for (let i = messages.length - 1; i >= 0; i--) {
|
||||
const msg = messages[i]!
|
||||
if (
|
||||
msg.type === 'system' &&
|
||||
(msg as Record<string, unknown>).subtype === 'compact_boundary'
|
||||
) {
|
||||
boundaryIdx = i
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
const keepFrom =
|
||||
boundaryIdx >= 0
|
||||
? boundaryIdx
|
||||
: Math.max(0, messages.length - PROACTIVE_TRUNCATE_MIN_TAIL)
|
||||
if (keepFrom === 0) return messages
|
||||
|
||||
return messages.slice(keepFrom)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user