fix(agent): restore streamFn extension compatibility

Keep streamFn required for typed callers while preserving the legacy runtime fallback for extensions that omit it.\n\nfixes #6915
This commit is contained in:
Mario Zechner
2026-07-21 18:34:56 +02:00
parent b142504125
commit b9e5c5d941
26 changed files with 210 additions and 88 deletions
+9 -8
View File
@@ -10,6 +10,7 @@ import {
type ToolResultMessage,
validateToolArguments,
} from "@earendil-works/pi-ai";
import { getDefaultStreamFn } from "./stream-fn.ts";
import type {
AgentContext,
AgentEvent,
@@ -32,7 +33,7 @@ export function agentLoop(
context: AgentContext,
config: AgentLoopConfig,
signal: AbortSignal | undefined,
streamFunction: StreamFn,
streamFn: StreamFn,
): EventStream<AgentEvent, AgentMessage[]> {
const stream = createAgentStream();
@@ -44,7 +45,7 @@ export function agentLoop(
stream.push(event);
},
signal,
streamFunction,
streamFn,
).then((messages) => {
stream.end(messages);
});
@@ -64,7 +65,7 @@ export function agentLoopContinue(
context: AgentContext,
config: AgentLoopConfig,
signal: AbortSignal | undefined,
streamFunction: StreamFn,
streamFn: StreamFn,
): EventStream<AgentEvent, AgentMessage[]> {
if (context.messages.length === 0) {
throw new Error("Cannot continue: no messages in context");
@@ -83,7 +84,7 @@ export function agentLoopContinue(
stream.push(event);
},
signal,
streamFunction,
streamFn,
).then((messages) => {
stream.end(messages);
});
@@ -97,7 +98,7 @@ export async function runAgentLoop(
config: AgentLoopConfig,
emit: AgentEventSink,
signal: AbortSignal | undefined,
streamFunction: StreamFn,
streamFn: StreamFn,
): Promise<AgentMessage[]> {
const newMessages: AgentMessage[] = [...prompts];
const currentContext: AgentContext = {
@@ -112,7 +113,7 @@ export async function runAgentLoop(
await emit({ type: "message_end", message: prompt });
}
await runLoop(currentContext, newMessages, config, signal, emit, streamFunction);
await runLoop(currentContext, newMessages, config, signal, emit, streamFn ?? getDefaultStreamFn());
return newMessages;
}
@@ -121,7 +122,7 @@ export async function runAgentLoopContinue(
config: AgentLoopConfig,
emit: AgentEventSink,
signal: AbortSignal | undefined,
streamFunction: StreamFn,
streamFn: StreamFn,
): Promise<AgentMessage[]> {
if (context.messages.length === 0) {
throw new Error("Cannot continue: no messages in context");
@@ -137,7 +138,7 @@ export async function runAgentLoopContinue(
await emit({ type: "agent_start" });
await emit({ type: "turn_start" });
await runLoop(currentContext, newMessages, config, signal, emit, streamFunction);
await runLoop(currentContext, newMessages, config, signal, emit, streamFn ?? getDefaultStreamFn());
return newMessages;
}