partialCompactConversation method
Future<CompactionResult>
partialCompactConversation({
- required List<
Message> allMessages, - required int pivotIndex,
- required String systemPrompt,
- String? userFeedback,
- PartialCompactDirection direction = PartialCompactDirection.from,
- OnCompactProgress? onProgress,
Partial compaction around a selected message index.
direction controls which side of the pivot is summarized:
- PartialCompactDirection.from: summarizes after the pivot, preserving earlier messages (preserves prompt cache).
- PartialCompactDirection.upTo: summarizes before the pivot, keeping later messages (invalidates prompt cache).
Implementation
Future<CompactionResult> partialCompactConversation({
required List<Message> allMessages,
required int pivotIndex,
required String systemPrompt,
String? userFeedback,
PartialCompactDirection direction = PartialCompactDirection.from,
OnCompactProgress? onProgress,
}) async {
final messagesToSummarize =
direction == PartialCompactDirection.upTo
? allMessages.sublist(0, pivotIndex)
: allMessages.sublist(pivotIndex);
final messagesToKeep =
direction == PartialCompactDirection.upTo
? allMessages.sublist(pivotIndex)
: allMessages.sublist(0, pivotIndex);
if (messagesToSummarize.isEmpty) {
final desc =
direction == PartialCompactDirection.upTo ? 'before' : 'after';
throw CompactionException(
'Nothing to summarize $desc the selected message.',
);
}
final preTokenCount = estimateTokenCount(allMessages);
onProgress?.call(
const CompactProgressEvent(
type: CompactProgressType.hooksStart,
hookType: CompactHookType.preCompact,
),
);
onProgress?.call(
const CompactProgressEvent(type: CompactProgressType.compactStart),
);
try {
final stripped = stripImagesFromMessages(messagesToSummarize);
final String? customInstructions =
userFeedback != null ? 'User context: $userFeedback' : null;
final summary = await _generateSummary(
messages: stripped,
systemPrompt: systemPrompt,
customInstructions: customInstructions,
);
if (summary.isEmpty) {
throw CompactionException(
'Failed to generate conversation summary — response did not '
'contain valid text content',
);
}
final summaryMsg = Message.user(
_formatCompactSummary(summary, false),
);
// Build the compacted messages in the correct order.
final List<Message> compactedMessages;
if (direction == PartialCompactDirection.upTo) {
compactedMessages = [summaryMsg, ...messagesToKeep];
} else {
compactedMessages = [...messagesToKeep, summaryMsg];
}
_consecutiveFailures = 0;
onProgress?.call(
const CompactProgressEvent(
type: CompactProgressType.hooksStart,
hookType: CompactHookType.postCompact,
),
);
return CompactionResult(
compactedMessages: compactedMessages,
summary: summary,
preCompactTokenCount: preTokenCount,
postCompactTokenCount: estimateTokenCount(compactedMessages),
strategy: CompactionStrategy.manual,
messagesToKeep: messagesToKeep,
);
} catch (e) {
_consecutiveFailures++;
rethrow;
} finally {
onProgress?.call(
const CompactProgressEvent(type: CompactProgressType.compactEnd),
);
}
}