MCPcopy Create free account
hub / github.com/QodeXcli/QodeX / compactMessages

Function compactMessages

src/utils/compaction.ts:134–193  ·  view source on GitHub ↗
(
  messages: Message[],
  options: {
    keepLastTurns?: number;
    summarize: (msgs: Message[]) => Promise<string>;
  },
)

Source from the content-addressed store, hash-verified

132 ];
133}
134
135/**
136 * Compact a message list by summarizing all but the most recent `keepLast` turns.
137 * A "turn" is a user message + everything until the next user message.
138 *
139 * The caller provides a `summarize` callback that runs an LLM call on the
140 * messages-to-summarize and returns the summary text.
141 */
142export async function compactMessages(
143 messages: Message[],
144 options: {
145 keepLastTurns?: number;
146 summarize: (msgs: Message[]) => Promise<string>;
147 },
148): Promise<CompactionResult> {
149 const keepLastTurns = options.keepLastTurns ?? 6;
150 const before = estimateTokens(messages);
151
152 const system = messages.filter(m => m.role === 'system');
153 const nonSystem = messages.filter(m => m.role !== 'system');
154
155 // Group into turn-groups: user msg starts each group
156 const groups: Message[][] = [];
157 let cur: Message[] = [];
158 for (const m of nonSystem) {
159 if (m.role === 'user' && cur.length > 0) {
160 groups.push(cur);
161 cur = [m];
162 } else {
163 cur.push(m);
164 }
165 }
166 if (cur.length > 0) groups.push(cur);
167
168 if (groups.length <= keepLastTurns) {
169 // Nothing to do
170 return { messages, before, after: before, turnsCompacted: 0 };
171 }
172
173 const toSummarize = groups.slice(0, groups.length - keepLastTurns).flat();
174 const toKeep = groups.slice(groups.length - keepLastTurns).flat();
175 const turnsCompacted = groups.length - keepLastTurns;
176
177 // Filter out existing summary messages from the to-summarize set
178 // and keep ALL system messages (including any prior summary) so the new
179 // summary CAN reference them.
180 const summarizationInput = buildCompactionRequest(toSummarize);
181 let summaryText: string;
182 try {
183 summaryText = await options.summarize(summarizationInput);
184 } catch (e: any) {
185 logger.warn('Compaction summarization failed; returning original messages', { err: e?.message });
186 return { messages, before, after: before, turnsCompacted: 0 };
187 }
188 // Refuse to trade real history for an empty summary.
189 //
190 // Compaction DELETES the summarized turns. A throw is handled above, but a summarizer can
191 // also succeed and return nothing useful: an aborted stream (the caller's loop does

Callers 1

runCompactionMethod · 0.85

Calls 6

buildCompactionRequestFunction · 0.85
summarizeMethod · 0.80
warnMethod · 0.80
infoMethod · 0.80
estimateTokensFunction · 0.70
pushMethod · 0.45

Tested by

no test coverage detected