From 4aa25bfb72d25d3b0ba82eb9ce4975c40b54846e Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Fri, 13 Mar 2026 22:54:41 +0100 Subject: [PATCH] docs(agent,ai): clarify non-throwing stream and hook contracts --- packages/agent/src/types.ts | 4 ++++ packages/ai/src/types.ts | 17 ++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/packages/agent/src/types.ts b/packages/agent/src/types.ts index a38a9e76..e7bc89eb 100644 --- a/packages/agent/src/types.ts +++ b/packages/agent/src/types.ts @@ -98,6 +98,8 @@ export interface AgentLoopConfig extends SimpleStreamOptions { * these messages are added to the context before the next LLM call. * * Use this for "steering" the agent while it's working. + * + * Contract: must not throw or reject. Return [] when no steering messages are available. */ getSteeringMessages?: () => Promise; @@ -109,6 +111,8 @@ export interface AgentLoopConfig extends SimpleStreamOptions { * continues with another turn. * * Use this for follow-up messages that should wait until the agent finishes. + * + * Contract: must not throw or reject. Return [] when no follow-up messages are available. */ getFollowUpMessages?: () => Promise; } diff --git a/packages/ai/src/types.ts b/packages/ai/src/types.ts index cc4a4309..7b27beff 100644 --- a/packages/ai/src/types.ts +++ b/packages/ai/src/types.ts @@ -114,7 +114,14 @@ export interface SimpleStreamOptions extends StreamOptions { thinkingBudgets?: ThinkingBudgets; } -// Generic StreamFunction with typed options +// Generic StreamFunction with typed options. +// +// Contract: +// - Must return an AssistantMessageEventStream. +// - Once invoked, request/model/runtime failures should be encoded in the +// returned stream, not thrown. +// - Error termination must produce an AssistantMessage with stopReason +// "error" or "aborted" and errorMessage, emitted via the stream protocol. export type StreamFunction = ( model: Model, context: Context, @@ -218,6 +225,14 @@ export interface Context { tools?: Tool[]; } +/** + * Event protocol for AssistantMessageEventStream. + * + * Streams should emit `start` before partial updates, then terminate with either: + * - `done` carrying the final successful AssistantMessage, or + * - `error` carrying the final AssistantMessage with stopReason "error" or "aborted" + * and errorMessage. + */ export type AssistantMessageEvent = | { type: "start"; partial: AssistantMessage } | { type: "text_start"; contentIndex: number; partial: AssistantMessage }