promptToolStreamFunction function
Wraps inner with prompt-based tool calling.
When context.tools is non-empty (or
PromptToolOptions.injectWhenNoTools is set), the returned
StreamFunction appends the tool instructions to the system prompt,
re-serializes tool calls/results in the message history as fenced text,
and parses tool_call fenced blocks out of the inner stream's text into
the harness tool-call event contract. Otherwise the inner stream is
returned untouched (byte-identical passthrough).
The wrapper preserves the provider contract: it never throws and terminates with exactly one DoneEvent or ErrorEvent.
Implementation
StreamFunction promptToolStreamFunction(
StreamFunction inner, {
PromptToolOptions? options,
}) {
final opts = options ?? const PromptToolOptions();
return (Model model, Context context, {CancelToken? cancelToken}) {
final tools = context.tools ?? const <Tool>[];
if (tools.isEmpty && !opts.injectWhenNoTools) {
return inner(model, context, cancelToken: cancelToken);
}
final out = AssistantMessageEventStream();
final parser = _PromptToolStreamParser(out, opts, model);
final AssistantMessageEventStream innerStream;
try {
innerStream = inner(
model,
_transformContext(context, tools, opts.slim),
cancelToken: cancelToken,
);
} catch (error) {
// Defensive: the StreamFunction contract is never-throw.
parser.fail(error);
out.end();
return out;
}
unawaited(() async {
try {
await for (final event in innerStream) {
parser.handle(event);
}
parser.streamClosed();
} catch (error) {
// Defensive: inner streams report failures as ErrorEvents.
parser.fail(error);
} finally {
out.end();
}
}());
return out;
};
}