capTrajectoryRequestDetail function

TrajectoryRequestDetail capTrajectoryRequestDetail(
  1. TrajectoryRequestDetail detail
)

Bounds the per-message summaries of detail (gh-1073): newest messages keep their full summaries while both caps allow, older ones become size-only stubs. messageCount, sizes, tool names and hashes pass through untouched — the record keeps describing the WHOLE request, it just stops embedding every message's text. Returns detail itself when everything already fits.

Implementation

TrajectoryRequestDetail capTrajectoryRequestDetail(
  TrajectoryRequestDetail detail,
) {
  final messages = detail.messages;
  var fullChars = 0;
  var fullCount = 0;
  // Walk from the NEWEST end; the first [requestSummaryMaxMessages]
  // messages (or until the char budget runs out) stay full.
  for (var i = messages.length - 1; i >= 0; i--) {
    final message = messages[i];
    final weight =
        message.preview.length +
        [for (final b in message.blocks) b.text.length].fold<int>(
          0,
          (a, b) => a + b,
        );
    if (fullCount >= requestSummaryMaxMessages ||
        fullChars + weight > requestSummaryCharsBudget) {
      break;
    }
    fullChars += weight;
    fullCount++;
  }
  if (fullCount >= messages.length) return detail;
  final fullFrom = messages.length - fullCount;
  return TrajectoryRequestDetail(
    messageCount: detail.messageCount,
    systemPromptChars: detail.systemPromptChars,
    toolCount: detail.toolCount,
    toolNames: detail.toolNames,
    systemPromptHash: detail.systemPromptHash,
    toolManifestHash: detail.toolManifestHash,
    wireDumpHash: detail.wireDumpHash,
    messages: [
      for (var i = 0; i < messages.length; i++)
        i < fullFrom
            ? TrajectoryRequestMessageSummary(
                role: messages[i].role,
                chars: messages[i].chars,
                preview: '',
              )
            : messages[i],
    ],
  );
}