@aparte/engine — API reference
Generated reference for @aparte/engine — runStreamAgent and its stream events.
On this page
Interfaces
Section titled “Interfaces”StreamUsage
Section titled “StreamUsage”Defined in: packages/engine/src/agent/stream-events.ts:34
Token usage. Structurally a superset-compatible mirror of AparteUsage: the
five common fields plus an index signature that carries the provider-specific
rest (ttft/decode/phases/…) opaquely — the loop transports usage, never reads
past these five.
Properties
Section titled “Properties”inputTokens
Section titled “inputTokens”inputTokens: number;Defined in: packages/engine/src/agent/stream-events.ts:35
outputTokens
Section titled “outputTokens”outputTokens: number;Defined in: packages/engine/src/agent/stream-events.ts:36
totalTokens?
Section titled “totalTokens?”optional totalTokens?: number;Defined in: packages/engine/src/agent/stream-events.ts:37
cacheReadTokens?
Section titled “cacheReadTokens?”optional cacheReadTokens?: number;Defined in: packages/engine/src/agent/stream-events.ts:38
durationMs?
Section titled “durationMs?”optional durationMs?: number;Defined in: packages/engine/src/agent/stream-events.ts:39
StreamToolCall
Section titled “StreamToolCall”Defined in: packages/engine/src/agent/stream-events.ts:57
One tool call as surfaced by the provider stream (mirrors AparteToolCall).
Properties
Section titled “Properties”id: string;Defined in: packages/engine/src/agent/stream-events.ts:58
name: string;Defined in: packages/engine/src/agent/stream-events.ts:59
input: Record<string, unknown>;Defined in: packages/engine/src/agent/stream-events.ts:68
Record<string, unknown>, mirroring core exactly, not unknown.
unknown looked safer — the loop does not read tool input, it forwards it —
but the seam needs assignability in BOTH directions (transportCall is
contravariant), and unknown is not assignable to Record<string, unknown>.
Core’s composition compiles against it.
StreamTool
Section titled “StreamTool”Defined in: packages/engine/src/agent/stream-events.ts:90
A tool declaration, structurally mirroring core’s AparteTool.
The loop forwards the inventory to the transport and reads maxTurns and
needsApproval from its own lookup — it never interprets the schema. Mirrored
exactly all the same, because the seam needs assignability in both directions;
core’s composition compiles against it.
Properties
Section titled “Properties”name: string;Defined in: packages/engine/src/agent/stream-events.ts:91
description
Section titled “description”description: string;Defined in: packages/engine/src/agent/stream-events.ts:92
inputSchema
Section titled “inputSchema”inputSchema: Record<string, unknown>;Defined in: packages/engine/src/agent/stream-events.ts:93
systemPrompt?
Section titled “systemPrompt?”optional systemPrompt?: string;Defined in: packages/engine/src/agent/stream-events.ts:94
maxTurns?
Section titled “maxTurns?”optional maxTurns?: number;Defined in: packages/engine/src/agent/stream-events.ts:95
needsApproval?
Section titled “needsApproval?”optional needsApproval?: boolean;Defined in: packages/engine/src/agent/stream-events.ts:96
StreamTextPart
Section titled “StreamTextPart”Defined in: packages/engine/src/agent/stream-events.ts:113
Multimodal content parts — a structural mirror of core’s AparteContentPart.
Mirrored rather than imported for the same reason as everything else in this
file: engine stays zero-import at runtime. Mirrored EXACTLY rather than
loosened to unknown[], which was the first attempt: transportCall is
contravariant, so the message type has to be assignable to core’s AND core’s to
it, and unknown[] fails the second direction. Core compiles
streamRunner: runStreamAgent, so a part added on one side and not the other is
a typecheck error there rather than a silent divergence.
The loop never looks inside content — it carries messages to the transport and appends results. This exists to make the seam type-check, not to be read.
Properties
Section titled “Properties”type: "text";Defined in: packages/engine/src/agent/stream-events.ts:113
text: string;Defined in: packages/engine/src/agent/stream-events.ts:113
StreamImagePart
Section titled “StreamImagePart”Defined in: packages/engine/src/agent/stream-events.ts:114
Properties
Section titled “Properties”type: "image";Defined in: packages/engine/src/agent/stream-events.ts:114
image: string;Defined in: packages/engine/src/agent/stream-events.ts:114
mimeType?
Section titled “mimeType?”optional mimeType?: string;Defined in: packages/engine/src/agent/stream-events.ts:114
StreamAgentMessage
Section titled “StreamAgentMessage”Defined in: packages/engine/src/agent/stream-events.ts:131
A conversation message (mirrors AparteChatMessage).
role used to be a bare string, justified by a comment saying the loop needed
to push the envelope roles of a tool turn “without importing core’s union”. But
core’s union already contained them — so the reason had not been true for some
time, and the looseness cost something real: transportCall
is contravariant, so this message type must ALSO be assignable to core’s, and a
string role is not assignable to a closed union. That was the last link in the
chain that stopped streamRunner: runStreamAgent from compiling.
Mirrored structurally rather than imported, to keep this package zero-import at runtime; core, which depends on this package, compiles the two against each other.
Properties
Section titled “Properties”role: "user" | "assistant" | "system" | "tool";Defined in: packages/engine/src/agent/stream-events.ts:132
content
Section titled “content”content: string | StreamContentPart[];Defined in: packages/engine/src/agent/stream-events.ts:142
Message content — carried, never inspected by this loop.
Was plain string, because core’s AparteChatMessage.content became
string | AparteContentPart[] for multimodal messages and this mirror never
followed. The consequence was not subtle: new AparteClient({ streamRunner: runStreamAgent }) — the one composition the two packages exist to make, and
the headline of five docs pages — did not typecheck.
toolCalls?
Section titled “toolCalls?”optional toolCalls?: StreamToolCall[];Defined in: packages/engine/src/agent/stream-events.ts:147
Present on an 'assistant' message — the whole turn’s calls, grouped. What it
said before them is that message’s own content, '' when it said nothing.
toolCallId?
Section titled “toolCallId?”optional toolCallId?: string;Defined in: packages/engine/src/agent/stream-events.ts:149
Present on a 'tool' message — which call it answers.
toolName?
Section titled “toolName?”optional toolName?: string;Defined in: packages/engine/src/agent/stream-events.ts:151
Present on a 'tool' message — the name of the tool that ran.
StreamChatRequest
Section titled “StreamChatRequest”Defined in: packages/engine/src/agent/stream-events.ts:180
The request handed to the transport each turn (mirrors AparteChatRequest).
The two fields the loop actually reads are DECLARED rather than reached through
an index signature. They used to be dynamic ([key: string]: unknown), which
read like “extra fields pass through” but is a requirement on the target of an
assignment, not a permission — it is what made core’s AparteChatRequest
un-assignable here and broke streamRunner: runStreamAgent. Declaring them is
both the fix and the more honest description: these are the fields the loop
branches on. Anything else a host attaches still passes through untouched,
because TypeScript only excess-property-checks object literals.
Types kept structural (not imported from core) so this package stays zero-import at runtime; core’s composition compiles the two against each other.
Properties
Section titled “Properties”messages
Section titled “messages”messages: StreamAgentMessage[];Defined in: packages/engine/src/agent/stream-events.ts:181
modelId
Section titled “modelId”modelId: string;Defined in: packages/engine/src/agent/stream-events.ts:188
Required, because transportCall is contravariant: the runner hands this
request to a transport typed against core’s AparteChatRequest, where
modelId is required. A mirror that omitted it made the whole runner
un-assignable — from the opposite direction to the messages mismatch.
_meta?
Section titled “_meta?”optional _meta?: Record<string, unknown>;Defined in: packages/engine/src/agent/stream-events.ts:190
Per-turn hints carried through for the host (prefixSegments, and whatever the consumer puts there); the loop reads none.
toolChoice?
Section titled “toolChoice?”optional toolChoice?:
| {
name: string;
input?: Record<string, unknown>;
}
| "auto"
| "none";Defined in: packages/engine/src/agent/stream-events.ts:197
'none' makes the loop drop the tool inventory for that turn. An object forces
a tool, and forcing is a turn-1 instruction: the loop sends it on the first
transport call of the run and lifts it (to 'auto') for every turn after, so
the model can answer once the tool has.
tools?
Section titled “tools?”optional tools?: StreamTool[];Defined in: packages/engine/src/agent/stream-events.ts:199
The inventory the loop sends, and clears when toolChoice is 'none'.
StreamToolConfig
Section titled “StreamToolConfig”Defined in: packages/engine/src/agent/stream-events.ts:214
Per-tool loop configuration (mirrors the AparteTool subset the loop reads).
Properties
Section titled “Properties”maxTurns?
Section titled “maxTurns?”optional maxTurns?: number;Defined in: packages/engine/src/agent/stream-events.ts:215
needsApproval?
Section titled “needsApproval?”optional needsApproval?: boolean | ((call) => boolean | "ask" | "deny");Defined in: packages/engine/src/agent/stream-events.ts:229
Whether a call of this tool pauses for a decision. A boolean is the tool’s own
declaration; a predicate decides PER CALL, from the arguments — the shape an
approval policy needs (“a write to this path asks, a read does not”), and one a
boolean could only approximate by gating every call and auto-approving most,
which paints awaiting-approval on rows nobody was ever going to be asked about.
The predicate has three answers, because a policy has three: false runs the
call, 'ask' (or true) puts it to someone — the loop announces the pause with
tool-awaiting-approval — and 'deny' means the decision is already made: the
resolver is still consulted (it is the one channel that carries the refusal
sentence back), but nothing is announced, since nobody is being asked.
external?
Section titled “external?”optional external?: boolean;Defined in: packages/engine/src/agent/stream-events.ts:236
Known to the model, executed elsewhere — a browser tool behind a server loop.
The loop never looks up a handler for it: with deferral the call waits for its
result in deferral.outcomes; without it, the call is aborted like a missing
handler.
StreamDeferredCall
Section titled “StreamDeferredCall”Defined in: packages/engine/src/agent/stream-events.ts:247
A call a suspended run left without an answer.
Properties
Section titled “Properties”toolCallId
Section titled “toolCallId”toolCallId: string;Defined in: packages/engine/src/agent/stream-events.ts:248
name: string;Defined in: packages/engine/src/agent/stream-events.ts:249
input: unknown;Defined in: packages/engine/src/agent/stream-events.ts:250
reason
Section titled “reason”reason: StreamDeferredReason;Defined in: packages/engine/src/agent/stream-events.ts:251
StreamDeferral
Section titled “StreamDeferral”Defined in: packages/engine/src/agent/stream-events.ts:277
Defer instead of block — see StreamRunOptions.deferral. Data only, so a run it
answers can be days old and on another machine.
Properties
Section titled “Properties”outcomes?
Section titled “outcomes?”optional outcomes?: Record<string, StreamDeferredOutcome>;Defined in: packages/engine/src/agent/stream-events.ts:283
Answers for calls a previous run left pending, by tool call id. They answer those calls only: a call the model makes after the resume goes through its gate afresh, even when it carries the same id.
token?
Section titled “token?”optional token?: string;Defined in: packages/engine/src/agent/stream-events.ts:285
Opaque to the loop, which never reads it: a remote runner carries its continuation ticket here.
StreamRunOptions
Section titled “StreamRunOptions”Defined in: packages/engine/src/agent/stream-run.ts:45
Properties
Section titled “Properties”messageId
Section titled “messageId”messageId: string;Defined in: packages/engine/src/agent/stream-run.ts:47
Id of the assistant message being streamed (opaque; carried in events).
baseRequest
Section titled “baseRequest”baseRequest: StreamChatRequest;Defined in: packages/engine/src/agent/stream-run.ts:49
Turn-1 request; the loop clones its messages and enriches them per turn.
transportCall
Section titled “transportCall”transportCall: (request) => Promise<
| string
| AsyncIterable<StreamChatEvent, any, any>>;Defined in: packages/engine/src/agent/stream-run.ts:56
Calls the transport with the (possibly enriched) request. Returns the
structured stream, or a plain string for a non-streaming provider. Mirrors
getTransport().chat(provider, request, auth, ctx) with provider/auth/ctx
closed over by the adapter.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
request | StreamChatRequest |
Returns
Section titled “Returns”Promise<
| string
| AsyncIterable<StreamChatEvent, any, any>>
toolLookup
Section titled “toolLookup”toolLookup: (name) => StreamToolHandler | undefined;Defined in: packages/engine/src/agent/stream-run.ts:58
Resolves a tool’s handler by name (mirrors aparteGlobalConfig.getToolHandler).
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
name | string |
Returns
Section titled “Returns”StreamToolHandler | undefined
toolConfigLookup?
Section titled “toolConfigLookup?”optional toolConfigLookup?: (name) => StreamToolConfig | undefined;Defined in: packages/engine/src/agent/stream-run.ts:60
Resolves a tool’s loop config by name (maxTurns / needsApproval).
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
name | string |
Returns
Section titled “Returns”StreamToolConfig | undefined
approvalResolver?
Section titled “approvalResolver?”optional approvalResolver?: StreamApprovalResolver;Defined in: packages/engine/src/agent/stream-run.ts:62
HITL approval resolver for needsApproval tools (default: never called).
emitter
Section titled “emitter”emitter: StreamRunEmitter;Defined in: packages/engine/src/agent/stream-run.ts:64
Synchronous, ordered event sink consumed by the adapter.
signal
Section titled “signal”signal: AbortSignal;Defined in: packages/engine/src/agent/stream-run.ts:66
Single abort signal composing _isAborted + the stream controller.
maxTurns?
Section titled “maxTurns?”optional maxTurns?: number;Defined in: packages/engine/src/agent/stream-run.ts:68
Global turn cap.
Default
Section titled “Default”10toolTimeoutMs?
Section titled “toolTimeoutMs?”optional toolTimeoutMs?: number;Defined in: packages/engine/src/agent/stream-run.ts:70
Per-tool-call handler timeout in ms.
Default
Section titled “Default”300000onHistoryAppend?
Section titled “onHistoryAppend?”optional onHistoryAppend?: (message) => void;Defined in: packages/engine/src/agent/stream-run.ts:104
Called for every turn the loop appends to the history — the assistant message
carrying the turn’s calls, each tool message answering one (resolved or
rejected), and a pipeline phase’s reply — in order, and always before the
transport call that would carry it. Never called for the messages you passed
in baseRequest.
For hosts that own their own transcript. The loop re-sends its messages
array every turn, which suits stateless message APIs but not a prefix
cache (llama.cpp slots, vLLM), where turn N+1 must EXTEND turn N byte for
byte. Such a host builds its own request in transportCall — ignoring
request.messages — and mirrors these notifications into its append-only
log, instead of reimplementing the loop’s tool bookkeeping. Synchronous and
ordered, like emitter.
One rule about the envelope: a turn’s assistant message is reported ONCE, when
its first call completes, and the calls that complete later in the same turn are
already in that same object’s toolCalls — the array is shared by reference, not
copied. Hold the reference, not a snapshot, and every result you receive after it
is declared by it.
Two of its fields are finalised after you are notified, then: toolCalls gains
the turn’s later calls, and content is re-read at the turn’s end (a provider
that emits [tool, text] streams the rest of the sentence after the envelope is
opened — see syncEnvelopeText). A host that must write BYTES at receipt — an
append-only log, which cannot hold a reference — should therefore treat the
envelope as provisional and write it only once the turn’s last tool message
has arrived, or re-read the object it holds before serialising.
content is the field that moved here, and the failure is louder than it was:
a snapshot no longer loses a trailing clause, it loses the whole sentence the
assistant said before it called anything.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
message | StreamAgentMessage |
Returns
Section titled “Returns”void
idGen?
Section titled “idGen?”optional idGen?: (prefix) => string;Defined in: packages/engine/src/agent/stream-run.ts:111
Generates the ids the loop mints itself — today only the synthetic call of a
forced toolChoice (prefix is 'synthetic-tool'). The default is a
deterministic per-run counter; core’s client injects a crypto-based one. Tool
ids otherwise flow from the stream.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
prefix | string |
Returns
Section titled “Returns”string
deferral?
Section titled “deferral?”optional deferral?: StreamDeferral;Defined in: packages/engine/src/agent/stream-run.ts:125
Defer instead of block. With this set, a call the gate sends to a person is not
awaited on approvalResolver, and an external tool is not treated as missing:
each takes its answer from outcomes, and without one the call is DEFERRED —
declared on the turn’s envelope with no tool answer. The rest of the model’s
reply is still read to its end (its later calls pending too, nothing run after the
pause point), and the run ends on run-suspended instead of run-done.
A run whose baseRequest.messages ends on an assistant envelope with unanswered
calls RESUMES: those calls go through the same processCall as a streamed one,
in order, before the first transport call. A call the gate denies is never
deferred — it is refused, through approvalResolver, as without this option.
providerId?
Section titled “providerId?”optional providerId?: string;Defined in: packages/engine/src/agent/stream-run.ts:130
The caller’s provider id. Opaque to the loop, like messageId: a runner that
forwards the run elsewhere (a server) needs it.
Type Aliases
Section titled “Type Aliases”StreamChatEvent
Section titled “StreamChatEvent”type StreamChatEvent =
| {
type: "text";
delta: string;
}
| {
type: "thinking";
delta: string;
}
| {
type: "tool_use";
} & StreamToolCall
| {
type: "error";
message: string;
}
| {
type: "done";
usage?: StreamUsage;
};Defined in: packages/engine/src/agent/stream-events.ts:75
A structured stream event from the transport (mirrors AparteStreamEvent). The
tool_use variant spreads StreamToolCall exactly like core’s does.
StreamContentPart
Section titled “StreamContentPart”type StreamContentPart =
| StreamTextPart
| StreamImagePart;Defined in: packages/engine/src/agent/stream-events.ts:115
StreamToolHandler
Section titled “StreamToolHandler”type StreamToolHandler = (call, signal) => Promise<{
content: string;
structuredContent?: unknown;
}>;Defined in: packages/engine/src/agent/stream-events.ts:203
A tool handler (mirrors the resolved AparteToolHandler).
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
call | StreamToolCall |
signal | AbortSignal |
Returns
Section titled “Returns”Promise<{
content: string;
structuredContent?: unknown;
}>
StreamDeferredReason
Section titled “StreamDeferredReason”type StreamDeferredReason = "approval" | "external" | "queued";Defined in: packages/engine/src/agent/stream-events.ts:244
Why a deferred call waits. approval: a person must decide. external: the tool
runs elsewhere and its result must come back. queued: nothing — it came after the
pause point in the same reply, and runs when the run resumes.
StreamRefusalOrigin
Section titled “StreamRefusalOrigin”type StreamRefusalOrigin = "person" | "policy" | "earlier-refusal";Defined in: packages/engine/src/agent/stream-events.ts:259
Who refused a call, for the row: the model reads one sentence whoever it was from, the
person reading the transcript needs to know. 'earlier-refusal' is a call the loop did
not run because another call of the same step had been refused.
StreamAbortCause
Section titled “StreamAbortCause”type StreamAbortCause = "stopped" | "timeout" | "no-handler" | "no-resolver";Defined in: packages/engine/src/agent/stream-events.ts:265
Why a call was aborted: a Stop, its handler’s timeout, no handler for it here, or a gate with nobody to ask.
StreamDeferredOutcome
Section titled “StreamDeferredOutcome”type StreamDeferredOutcome =
| {
kind: "decision";
approved: boolean;
reason?: string;
instruction?: string;
by?: StreamRefusalOrigin;
payload?: unknown;
}
| {
kind: "result";
content: string;
structuredContent?: unknown;
}
| {
kind: "failed";
error: string;
};Defined in: packages/engine/src/agent/stream-events.ts:268
The answer to a deferred call, handed to the run that resumes it.
StreamApprovalResolver
Section titled “StreamApprovalResolver”type StreamApprovalResolver = (call, signal) => Promise<{
approved: boolean;
payload?: unknown;
instruction?: string;
reason?: string;
by?: StreamRefusalOrigin;
}>;Defined in: packages/engine/src/agent/stream-events.ts:292
Resolves a human-in-the-loop approval (mirrors core’s
AparteToolApprovalResolver). Injected so the loop stays headless.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
call | { id: string; name: string; input: Record<string, unknown>; } |
call.id | string |
call.name | string |
call.input | Record<string, unknown> |
signal | AbortSignal |
Returns
Section titled “Returns”Promise<{
approved: boolean;
payload?: unknown;
instruction?: string;
reason?: string;
by?: StreamRefusalOrigin;
}>
StreamRunEvent
Section titled “StreamRunEvent”type StreamRunEvent =
| {
type: "run-start";
}
| {
type: "turn-start";
}
| {
type: "text-delta";
delta: string;
}
| {
type: "text-flush";
}
| {
type: "thinking-delta";
delta: string;
}
| {
type: "tool-start";
toolCallId: string;
name: string;
input: unknown;
}
| {
type: "tool-awaiting-approval";
toolCallId: string;
name: string;
input: unknown;
}
| {
type: "tool-approved";
toolCallId: string;
}
| {
type: "tool-rejected";
toolCallId: string;
reason: string;
by?: StreamRefusalOrigin;
instruction?: string;
}
| {
type: "tool-failed";
toolCallId: string;
error: string;
}
| {
type: "tool-resolved";
toolCallId: string;
result: string;
structuredResult?: unknown;
}
| {
type: "tool-aborted";
toolCallId: string;
cause?: StreamAbortCause;
}
| {
type: "turn-limit-exceeded";
scope: "global" | "tool";
limit: number;
toolCallId?: string;
}
| {
type: "run-aborted";
}
| {
type: "run-done";
usage?: StreamUsage;
}
| {
type: "run-suspended";
pending: StreamDeferredCall[];
usage?: StreamUsage;
};Defined in: packages/engine/src/agent/stream-events.ts:340
High-level, DOM-free events isomorphic to the inline loop’s targetElement.*
call sequence. Emitted synchronously and in order (see StreamRunEmitter)
so the adapter reproduces the exact streaming update order.
Mapping to the inline loop it replaced, for the adapter:
run-start→ updateMessage(status:‘streaming’) once at loop entry (the leading write before turn 1)turn-start→ reset the per-turn parser / thinking / streaming-segment state (no DOM); one per turntext-delta→ parser-driven addSegment/updateSegment, else typeName/updateLastMessagetext-flush→ textParser.finalize() then addSegment/updateSegment the finalized segments; one per turn, after the inner SSE loop ends (surfaced by the spike — a turn-boundary flush)thinking-delta→ addSegment(‘thinking’) then updateSegment(content); firsttext-deltaafter thinking collapses it (updateSegment collapsed:true)tool-start→ renderer lookup + per-tool-name CSS inject into document.head + addSegmenttool-awaiting-approval→ updateSegment(‘awaiting-approval’) + dispatchaparte-tool-approval-requesttool-approved→ updateSegment(‘pending’)tool-rejected→ updateSegment(‘rejected’, result)tool-failed→ updateSegment(‘failed’, error) — the handler threw; the run then ends on that errortool-resolved→ updateSegment(‘resolved’, result)tool-aborted→ updateSegment(‘aborted’) (no-handler path, timeout/abort path, or per-tool maxTurns path)turn-limit-exceededscope:‘global’ → addSegment(error ‘MAX_TURNS_EXCEEDED’); scope:‘tool’ → updateSegment(‘aborted’)run-aborted→ dispatchaparte-message-aborted(from the inner-loop abort check or the outer turn-boundary abort check)run-done→ updateMessage(status:‘completed’) always + setUsage if usagerun-suspended→ (withdeferral) the run ends with calls left pending; the adapter marks them and completes the message — the TURN goes on through the run that resumes them
Union Members
Section titled “Union Members”Type Literal
Section titled “Type Literal”{
type: "run-start";
}Type Literal
Section titled “Type Literal”{
type: "turn-start";
}Type Literal
Section titled “Type Literal”{
type: "text-delta";
delta: string;
}Type Literal
Section titled “Type Literal”{
type: "text-flush";
}Type Literal
Section titled “Type Literal”{
type: "thinking-delta";
delta: string;
}Type Literal
Section titled “Type Literal”{
type: "tool-start";
toolCallId: string;
name: string;
input: unknown;
}Type Literal
Section titled “Type Literal”{
type: "tool-awaiting-approval";
toolCallId: string;
name: string;
input: unknown;
}Type Literal
Section titled “Type Literal”{
type: "tool-approved";
toolCallId: string;
}Type Literal
Section titled “Type Literal”{
type: "tool-rejected";
toolCallId: string;
reason: string;
by?: StreamRefusalOrigin;
instruction?: string;
}reason is the sentence the model reads; by and instruction are for the row, which
speaks to a person in their own language (optional for a runner that emits its own).
Type Literal
Section titled “Type Literal”{
type: "tool-failed";
toolCallId: string;
error: string;
}The handler threw (not an abort): the row hears of the crash before the run ends on it.
Type Literal
Section titled “Type Literal”{
type: "tool-resolved";
toolCallId: string;
result: string;
structuredResult?: unknown;
}Type Literal
Section titled “Type Literal”{
type: "tool-aborted";
toolCallId: string;
cause?: StreamAbortCause;
}The call did not run to an answer. cause says why, for the row: 'no-handler' and
'no-resolver' are the page’s setup, not anything the person did. Absent on the calls
a run ended before reaching.
Type Literal
Section titled “Type Literal”{
type: "turn-limit-exceeded";
scope: "global" | "tool";
limit: number;
toolCallId?: string;
}Type Literal
Section titled “Type Literal”{
type: "run-aborted";
}Type Literal
Section titled “Type Literal”{
type: "run-done";
usage?: StreamUsage;
}Type Literal
Section titled “Type Literal”{
type: "run-suspended";
pending: StreamDeferredCall[];
usage?: StreamUsage;
}Ends a run in place of run-done when calls are left for someone else to answer.
StreamRunEmitter
Section titled “StreamRunEmitter”type StreamRunEmitter = (event) => void;Defined in: packages/engine/src/agent/stream-events.ts:374
Synchronous event sink. Synchronous by contract: the loop must never yield between emitting an event and its ordered successor, or the adapter’s streaming updates would interleave out of order.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
event | StreamRunEvent |
Returns
Section titled “Returns”void
Functions
Section titled “Functions”runStreamAgent()
Section titled “runStreamAgent()”function runStreamAgent(opts): Promise<StreamUsage | undefined>;Defined in: packages/engine/src/agent/stream-run.ts:161
Run the structured-stream agent loop. Resolves the last turn’s usage (the
done{usage} last-write-wins, mirroring _streamLoop’s return), or
undefined. Throws on a stream error event or a non-abort tool failure —
the caller (adapter) routes that to its lifecycle-error handler, exactly as
_handleSend/_handleRetry/_handleEdit catch _streamLoop.
This block has to stay ADJACENT to the function. It used to sit above
warnUnknownStreamEvent, six lines and a docblock away from what it describes, and a
docblock separated from its declaration is attached to nothing: TypeDoc took the
helper’s comment as the neighbouring one and @aparte/engine’s reference page carried
the package’s headline export with no description at all — the very export its own
frontmatter names. Same trap the custom-elements analyser has with a class docblock
pushed above an import.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
opts | StreamRunOptions |
Returns
Section titled “Returns”Promise<StreamUsage | undefined>
unansweredTail()
Section titled “unansweredTail()”function unansweredTail(messages): StreamToolCall[];Defined in: packages/engine/src/agent/stream-run.ts:589
The calls a history leaves unanswered: those of its LAST assistant envelope that no
following tool message answers, in declaration order. A resumed run answers them
first; a server checks them against the ticket it signed when the run paused.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
messages | readonly StreamAgentMessage[] |
Returns
Section titled “Returns”toolRefusal()
Section titled “toolRefusal()”function toolRefusal(decision): {
reason: string;
by: StreamRefusalOrigin;
instruction?: string;
};Defined in: packages/engine/src/agent/stream-run.ts:638
What a refusal says, and to whom. reason is the sentence the model reads: the refuser’s
own when it gave one, else the person’s words quoted, else the fixed sentence. by and
instruction are for the row, which tells a person who refused in their own language —
a reason with no origin is a policy’s, as StreamApprovalResolver defines it.
Exported so a runner that answers an agent elsewhere writes the same sentence.
Parameters
Section titled “Parameters”| Parameter | Type |
|---|---|
decision | { reason?: string; instruction?: string; by?: StreamRefusalOrigin; } |
decision.reason? | string |
decision.instruction? | string |
decision.by? | StreamRefusalOrigin |
Returns
Section titled “Returns”{
reason: string;
by: StreamRefusalOrigin;
instruction?: string;
}reason
Section titled “reason”reason: string;by: StreamRefusalOrigin;instruction?
Section titled “instruction?”optional instruction?: string;