Skip to content

Commit 45c892f

Browse files
revert: 恢复 HISTORY_SNIP
1 parent 5b333e2 commit 45c892f

4 files changed

Lines changed: 2 additions & 124 deletions

File tree

scripts/defines.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ export const DEFAULT_BUILD_FEATURES = [
5959
'DAEMON', // 守护进程模式,长驻 supervisor 管理后台 worker(非 GB 级主因)
6060
'ACP', // ACP 代理协议,支持外部 agent 接入
6161
'WORKFLOW_SCRIPTS', // 工作流脚本(.claude/workflows/ 中的 YAML/MD)
62-
// 'HISTORY_SNIP', // 历史消息裁剪,压缩上下文窗口
62+
'HISTORY_SNIP', // 历史消息裁剪,压缩上下文窗口
6363
// 'CONTEXT_COLLAPSE', // 已禁用:实现是空壳 stub,启用后会抑制 auto compact 导致上下文管理完全失效
6464
'MONITOR_TOOL', // Monitor 工具,流式监控后台进程输出
6565
// 'FORK_SUBAGENT', // 已禁用:显式 `fork: true` 参数触发 fork 路径(继承父级上下文和模型),不影响 forceAsync 和探索任务模型选择

src/QueryEngine.ts

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,15 +1003,6 @@ export class QueryEngine {
10031003
uuid: msg.uuid,
10041004
}
10051005
}
1006-
// Proactive truncation: prevent unbounded growth when API doesn't
1007-
// return compact_boundary (e.g. third-party compat layers).
1008-
if (feature('HISTORY_SNIP') && snipModule) {
1009-
const truncated = snipModule.proactiveTruncate(this.mutableMessages)
1010-
if (truncated !== this.mutableMessages) {
1011-
this.mutableMessages.length = 0
1012-
this.mutableMessages.push(...truncated)
1013-
}
1014-
}
10151006
// Don't yield other system messages in headless mode
10161007
break
10171008
}

src/services/compact/snipCompact.ts

Lines changed: 0 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -163,77 +163,3 @@ export function isSnipRuntimeEnabled(): boolean {
163163
export function shouldNudgeForSnips(messages: Message[]): boolean {
164164
return messages.length >= SNIP_NUDGE_THRESHOLD
165165
}
166-
167-
/**
168-
* Maximum total character length of message content before proactive
169-
* truncation kicks in. ~150 MB of string data corresponds to roughly
170-
* 1.5x the default 200k-token context window at 4 chars/token — well
171-
* beyond what any model can actually use in a single request.
172-
*/
173-
const PROACTIVE_TRUNCATE_CHARS = 150_000_000
174-
175-
/**
176-
* Minimum number of messages to keep when falling back to tail-only
177-
* retention (i.e. when no compact_boundary exists in the array).
178-
*/
179-
const PROACTIVE_TRUNCATE_MIN_TAIL = 50
180-
181-
/**
182-
* Proactively truncate old messages when the in-memory store grows too
183-
* large. Unlike `snipCompactIfNeeded` (which waits for a snip_boundary
184-
* from the API), this runs client-side after every push — ensuring
185-
* unbounded growth cannot happen even when the API never returns a
186-
* compact_boundary (e.g. third-party compat layers).
187-
*
188-
* Strategy:
189-
* 1. If a `compact_boundary` exists, keep it and everything after it.
190-
* 2. Otherwise, keep only the last `PROACTIVE_TRUNCATE_MIN_TAIL` messages.
191-
*
192-
* Returns the same array reference when no truncation is needed.
193-
*/
194-
export function proactiveTruncate(messages: Message[]): Message[] {
195-
if (messages.length < PROACTIVE_TRUNCATE_MIN_TAIL) return messages
196-
197-
let totalChars = 0
198-
for (const msg of messages) {
199-
const content = msg.message?.content
200-
if (typeof content === 'string') {
201-
totalChars += content.length
202-
} else if (Array.isArray(content)) {
203-
for (const block of content) {
204-
if (typeof block === 'string') {
205-
totalChars += (block as string).length
206-
} else if (block && typeof block === 'object') {
207-
const obj = block as unknown as Record<string, unknown>
208-
const text = obj.text ?? obj.content
209-
if (typeof text === 'string') {
210-
totalChars += text.length
211-
}
212-
}
213-
}
214-
}
215-
}
216-
217-
if (totalChars < PROACTIVE_TRUNCATE_CHARS) return messages
218-
219-
// Find last compact_boundary — the standard anchor point
220-
let boundaryIdx = -1
221-
for (let i = messages.length - 1; i >= 0; i--) {
222-
const msg = messages[i]!
223-
if (
224-
msg.type === 'system' &&
225-
(msg as Record<string, unknown>).subtype === 'compact_boundary'
226-
) {
227-
boundaryIdx = i
228-
break
229-
}
230-
}
231-
232-
const keepFrom =
233-
boundaryIdx >= 0
234-
? boundaryIdx
235-
: Math.max(0, messages.length - PROACTIVE_TRUNCATE_MIN_TAIL)
236-
if (keepFrom === 0) return messages
237-
238-
return messages.slice(keepFrom)
239-
}

src/utils/telemetry/instrumentation.ts

Lines changed: 1 addition & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -206,49 +206,10 @@ async function getOtlpReaders() {
206206

207207
return exporters.map(exporter => {
208208
if ('export' in exporter) {
209-
const reader = new PeriodicExportingMetricReader({
209+
return new PeriodicExportingMetricReader({
210210
exporter,
211211
exportIntervalMillis: exportInterval,
212212
})
213-
// Wrap the export callback to auto-shutdown the reader on auth
214-
// failures (401/403). Without this the PeriodicExportingMetricReader's
215-
// internal setInterval keeps retrying forever, leaking handles.
216-
const originalExport = (
217-
exporter as unknown as {
218-
export: (
219-
metrics: unknown,
220-
callback: (result: { error?: Error }) => void,
221-
) => unknown
222-
}
223-
).export.bind(exporter)
224-
;(
225-
exporter as unknown as {
226-
export: (
227-
metrics: unknown,
228-
callback: (result: { error?: Error }) => void,
229-
) => unknown
230-
}
231-
).export = (metrics, callback) => {
232-
return originalExport(metrics, result => {
233-
if (result.error) {
234-
const msg = result.error.message || ''
235-
if (
236-
msg.includes('401') ||
237-
msg.includes('403') ||
238-
msg.includes('Unauthorized') ||
239-
msg.includes('authentication')
240-
) {
241-
logForDebugging(
242-
`[3P telemetry] Auth error detected, shutting down metric reader`,
243-
{ level: 'error' },
244-
)
245-
void reader.shutdown()
246-
}
247-
}
248-
callback(result)
249-
})
250-
}
251-
return reader
252213
}
253214
return exporter
254215
})

0 commit comments

Comments
 (0)