build static method

AssembledContext build({
  1. required List<ChunkSearchResult> searchResults,
  2. int tokenBudget = 2000,
  3. ContextStrategy strategy = ContextStrategy.relevanceFirst,
  4. String separator = '\n\n---\n\n',
  5. bool singleSourceMode = false,
})

Assemble context from search results within a token budget.

searchResults - Chunks ranked by relevance (highest first). tokenBudget - Maximum tokens to use. strategy - How to select and order chunks. separator - Text between chunks. singleSourceMode - If true, only include chunks from the most relevant source.

Implementation

static AssembledContext build({
  required List<ChunkSearchResult> searchResults,
  int tokenBudget = 2000,
  ContextStrategy strategy = ContextStrategy.relevanceFirst,
  String separator = '\n\n---\n\n',
  bool singleSourceMode = false,
}) {
  if (searchResults.isEmpty) {
    return const AssembledContext(
      text: '',
      includedChunks: [],
      estimatedTokens: 0,
      remainingBudget: 0,
    );
  }

  // Filter to single source if requested
  var filteredResults = searchResults;
  if (singleSourceMode) {
    filteredResults = _filterToMostRelevantSource(searchResults);
  }

  // Apply strategy
  final orderedResults = switch (strategy) {
    ContextStrategy.relevanceFirst => filteredResults,
    ContextStrategy.diverseSources => _diversifySources(filteredResults),
    ContextStrategy.chronological => _orderChronologically(filteredResults),
  };

  final skipHeaders = singleSourceMode;
  final state = _RenderedSelectionState(
    separator: separator,
    skipHeaders: skipHeaders,
    tokenCounter: _countTokens,
  );

  for (final chunk in orderedResults) {
    state.tryAddChunk(chunk, tokenBudget);
  }

  final text = state.renderedText;
  final measuredTokens = text.isEmpty ? 0 : state.measuredTokens;

  return AssembledContext(
    text: text,
    includedChunks: state.selectedChunks,
    estimatedTokens: measuredTokens,
    remainingBudget: tokenBudget - measuredTokens,
  );
}