MCPcopy Index your code
hub / github.com/ChatLab/ChatLab / checkAndCompress

Function checkAndCompress

packages/node-runtime/src/ai/compression/compressor.ts:65–186  ·  view source on GitHub ↗
(
  aiChatId: string,
  config: CompressionConfig,
  systemPrompt: string,
  llmAdapter: CompressionLlmAdapter,
  convManager: AIChatManager,
  logger: CompressionLogger = defaultLogger
)

Source from the content-addressed store, hash-verified

63}
64
65export async function checkAndCompress(
66 aiChatId: string,
67 config: CompressionConfig,
68 systemPrompt: string,
69 llmAdapter: CompressionLlmAdapter,
70 convManager: AIChatManager,
71 logger: CompressionLogger = defaultLogger
72): Promise<CompressionResult> {
73 if (!config.enabled) {
74 return { compressed: false, reason: 'skipped_disabled' }
75 }
76
77 try {
78 const contextWindow = llmAdapter.contextWindow || DEFAULT_CONTEXT_WINDOW
79 const thresholdTokens = Math.floor(contextWindow * (config.tokenThresholdPercent / 100) * 0.95)
80
81 const summary = convManager.getLatestSummary(aiChatId)
82
83 let messages: Array<{ role: AIMessageRole; content: string; timestamp: number; contentBlocks?: ContentBlock[] }>
84 if (summary) {
85 const metaBlock = summary.contentBlocks?.find(
86 (b): b is Extract<ContentBlock, { type: 'summary_meta' }> => b.type === 'summary_meta'
87 )
88 const boundary = metaBlock?.bufferBoundaryTimestamp ?? summary.timestamp
89 messages = convManager.getMessagesAfterSummary(aiChatId, boundary - 1)
90 } else {
91 messages = convManager.getAllUserAssistantMessages(aiChatId)
92 }
93
94 const historyForTokenCount: Array<{ role: string; content: string }> = []
95 if (summary) {
96 historyForTokenCount.push({ role: 'assistant', content: summary.content })
97 }
98 for (const msg of messages) {
99 historyForTokenCount.push({ role: msg.role, content: msg.content })
100 // Persisted tool results are replayed as toolCall/toolResult pairs each
101 // turn (see agent/history.ts), so they occupy real context and must be counted.
102 for (const toolText of replayedToolResultTexts(msg.contentBlocks)) {
103 historyForTokenCount.push({ role: 'tool', content: toolText })
104 }
105 }
106
107 const currentTokens = countMessagesTokens(historyForTokenCount, systemPrompt)
108
109 logger.info('Compression', `Token check: ${currentTokens} / ${thresholdTokens} (${contextWindow} window)`, {
110 aiChatId,
111 messageCount: messages.length,
112 hasSummary: !!summary,
113 })
114
115 if (currentTokens < thresholdTokens) {
116 return { compressed: false, reason: 'skipped_below_threshold', tokensBefore: currentTokens }
117 }
118
119 const bufferTokenBudget = Math.floor(contextWindow * (config.bufferSizePercent / 100))
120 const { bufferMessages, messagesToCompress } = splitMessagesForCompression(messages, bufferTokenBudget)
121
122 const MIN_MESSAGES_TO_COMPRESS = 3

Callers 4

compressor.test.tsFile · 0.90
runServerAgentFunction · 0.90
manualCompressFunction · 0.85

Calls 13

countMessagesTokensFunction · 0.90
replayedToolResultTextsFunction · 0.85
buildCompressionInputFunction · 0.85
forceTruncateFunction · 0.85
getLatestSummaryMethod · 0.80
compressMethod · 0.80
addSummaryMessageMethod · 0.80
infoMethod · 0.65
warnMethod · 0.65

Tested by

no test coverage detected