streamFunctionSummarizer function

SummarizeFn streamFunctionSummarizer(
  1. StreamFunction streamFunction,
  2. Model model, {
  3. CompactionPrompts prompts = defaultCompactionPrompts,
  4. void onDelta(
    1. String delta
    )?,
})

Adapts a provider StreamFunction into a SummarizeFn.

Sends the CompactionPrompts.system prompt (the built-in summarizationSystemPrompt unless overridden) plus the request prompt as a single user message and joins the response's text blocks. Error and aborted stop reasons map to failure results (errors-as-events contract); a throwing StreamFunction is defensive-converted into a failure.

Summaries are standalone requests, so every call runs with cacheRetention: 'none' and a fresh routing session id (uuidv7) via StreamCacheRouting: summarization never writes to nor routes through the session's prompt cache (pi's compaction callCompleteSimple).

Implementation

SummarizeFn streamFunctionSummarizer(
  StreamFunction streamFunction,
  Model model, {
  CompactionPrompts prompts = defaultCompactionPrompts,
  void Function(String delta)? onDelta,
}) {
  return (SummarizationRequest request) async {
    try {
      final stream = StreamCacheRouting.runWith(
        () => streamFunction(
          model,
          Context(
            systemPrompt: prompts.system,
            messages: [UserMessage.text(request.prompt)],
          ),
          cancelToken: request.cancelToken,
        ),
        sessionId: uuidv7(),
        cacheRetention: 'none',
      );
      // Surface streaming deltas (text + thinking) to the host UI while the
      // result future resolves: EventStream buffers until listened, and
      // `result` resolves independently of subscription, so this drain is
      // safe for the single-subscription stream.
      if (onDelta != null) {
        stream.listen((event) {
          final delta = switch (event) {
            TextDeltaEvent(:final delta) => delta,
            ThinkingDeltaEvent(:final delta) => delta,
            _ => null,
          };
          if (delta != null && delta.isNotEmpty) onDelta(delta);
        });
      }
      final response = await stream.result;
      return switch (response.stopReason) {
        StopReason.aborted => SummarizationResult.failure(
          response.errorMessage ?? 'Summarization aborted',
          aborted: true,
        ),
        StopReason.error => SummarizationResult.failure(
          'Summarization failed: ${response.errorMessage ?? 'Unknown error'}',
        ),
        _ => SummarizationResult.success(
          response.content
              .whereType<TextContent>()
              .map((block) => block.text)
              .join('\n'),
        ),
      };
    } catch (error) {
      return SummarizationResult.failure('Summarization failed: $error');
    }
  };
}