agents 0.8.7 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,454 @@
1
+ import { JSONSchema7, Tool, ToolSet, UIMessage } from "ai";
2
+ import { Connection } from "agents";
3
+
4
+ //#region src/chat/message-builder.d.ts
5
+ /** The parts array type from UIMessage */
6
+ type MessageParts = UIMessage["parts"];
7
+ /** A single part from the UIMessage parts array */
8
+ type MessagePart = MessageParts[number];
9
+ /**
10
+ * Parsed chunk data from an AI SDK stream event.
11
+ * This is the JSON-parsed body of a CF_AGENT_USE_CHAT_RESPONSE message,
12
+ * or the `data:` payload of an SSE line.
13
+ */
14
+ type StreamChunkData = {
15
+ type: string;
16
+ id?: string;
17
+ delta?: string;
18
+ text?: string;
19
+ mediaType?: string;
20
+ url?: string;
21
+ sourceId?: string;
22
+ title?: string;
23
+ filename?: string;
24
+ toolCallId?: string;
25
+ toolName?: string;
26
+ input?: unknown;
27
+ inputTextDelta?: string;
28
+ output?: unknown;
29
+ state?: string;
30
+ errorText?: string; /** When true, the output is preliminary (may be updated by a later chunk) */
31
+ preliminary?: boolean; /** Approval ID for tools with needsApproval */
32
+ approvalId?: string;
33
+ providerMetadata?: Record<string, unknown>; /** Whether the tool was executed by the provider (e.g. Gemini code execution) */
34
+ providerExecuted?: boolean; /** Payload for data-* parts (developer-defined typed JSON) */
35
+ data?: unknown; /** When true, data parts are ephemeral and not persisted to message.parts */
36
+ transient?: boolean; /** Message ID assigned by the server at stream start */
37
+ messageId?: string; /** Per-message metadata attached by start/finish/message-metadata chunks */
38
+ messageMetadata?: unknown;
39
+ [key: string]: unknown;
40
+ };
41
+ /**
42
+ * Applies a stream chunk to a mutable parts array, building up the message
43
+ * incrementally. Returns true if the chunk was handled, false if it was
44
+ * an unrecognized type (caller may handle it with additional logic).
45
+ *
46
+ * Handles all common chunk types that both server and client need:
47
+ * - text-start / text-delta / text-end
48
+ * - reasoning-start / reasoning-delta / reasoning-end
49
+ * - file
50
+ * - source-url / source-document
51
+ * - tool-input-start / tool-input-delta / tool-input-available / tool-input-error
52
+ * - tool-output-available / tool-output-error
53
+ * - step-start (aliased from start-step)
54
+ * - data-* (developer-defined typed JSON blobs)
55
+ *
56
+ * @param parts - The mutable parts array to update
57
+ * @param chunk - The parsed stream chunk data
58
+ * @returns true if handled, false if the chunk type is not recognized
59
+ */
60
+ declare function applyChunkToParts(parts: MessagePart[], chunk: StreamChunkData): boolean;
61
+ //#endregion
62
+ //#region src/chat/sanitize.d.ts
63
+ /** Maximum serialized message size before compaction (bytes). 1.8MB with headroom below SQLite's 2MB limit. */
64
+ declare const ROW_MAX_BYTES = 1800000;
65
+ /** Measure UTF-8 byte length of a string. */
66
+ declare function byteLength(s: string): number;
67
+ /**
68
+ * Sanitize a message for persistence by removing ephemeral provider-specific
69
+ * data that should not be stored or sent back in subsequent requests.
70
+ *
71
+ * 1. Strips OpenAI ephemeral fields (itemId, reasoningEncryptedContent)
72
+ * 2. Filters truly empty reasoning parts (no text, no remaining providerMetadata)
73
+ */
74
+ declare function sanitizeMessage(message: UIMessage): UIMessage;
75
+ /**
76
+ * Enforce SQLite row size limits by compacting tool outputs and text parts
77
+ * when a serialized message exceeds the safety threshold (1.8MB).
78
+ *
79
+ * Compaction strategy:
80
+ * 1. Compact tool outputs over 1KB (replace with summary)
81
+ * 2. If still too big, truncate text parts from oldest to newest
82
+ */
83
+ declare function enforceRowSizeLimit(message: UIMessage): UIMessage;
84
+ //#endregion
85
+ //#region src/chat/stream-accumulator.d.ts
86
+ interface StreamAccumulatorOptions {
87
+ messageId: string;
88
+ continuation?: boolean;
89
+ existingParts?: UIMessage["parts"];
90
+ existingMetadata?: Record<string, unknown>;
91
+ }
92
+ type ChunkAction = {
93
+ type: "start";
94
+ messageId?: string;
95
+ metadata?: Record<string, unknown>;
96
+ } | {
97
+ type: "finish";
98
+ finishReason?: string;
99
+ metadata?: Record<string, unknown>;
100
+ } | {
101
+ type: "message-metadata";
102
+ metadata: Record<string, unknown>;
103
+ } | {
104
+ type: "tool-approval-request";
105
+ toolCallId: string;
106
+ } | {
107
+ type: "cross-message-tool-update";
108
+ updateType: "output-available" | "output-error";
109
+ toolCallId: string;
110
+ output?: unknown;
111
+ errorText?: string;
112
+ preliminary?: boolean;
113
+ } | {
114
+ type: "error";
115
+ error: string;
116
+ };
117
+ interface ChunkResult {
118
+ handled: boolean;
119
+ action?: ChunkAction;
120
+ }
121
+ declare class StreamAccumulator {
122
+ messageId: string;
123
+ readonly parts: UIMessage["parts"];
124
+ metadata?: Record<string, unknown>;
125
+ private _isContinuation;
126
+ constructor(options: StreamAccumulatorOptions);
127
+ applyChunk(chunk: StreamChunkData): ChunkResult;
128
+ /** Snapshot the current state as a UIMessage. */
129
+ toMessage(): UIMessage;
130
+ /**
131
+ * Merge this accumulator's message into an existing message array.
132
+ * Handles continuation (walk backward for last assistant), replacement
133
+ * (update existing by messageId), or append (new message).
134
+ */
135
+ mergeInto(messages: UIMessage[]): UIMessage[];
136
+ }
137
+ //#endregion
138
+ //#region src/chat/turn-queue.d.ts
139
+ /**
140
+ * TurnQueue — serial async queue with generation-based invalidation.
141
+ *
142
+ * Serializes async work via a promise chain, tracks which request is
143
+ * currently active, and lets callers invalidate all queued work by
144
+ * advancing a generation counter.
145
+ *
146
+ * Used by @cloudflare/ai-chat (full concurrency policy spectrum) and
147
+ * @cloudflare/think (simple serial queue) to prevent overlapping
148
+ * chat turns.
149
+ */
150
+ type TurnResult<T> = {
151
+ status: "completed";
152
+ value: T;
153
+ } | {
154
+ status: "stale";
155
+ };
156
+ interface EnqueueOptions {
157
+ /**
158
+ * Generation to bind this turn to. Defaults to the current generation
159
+ * at the time of the `enqueue` call. If the queue's generation has
160
+ * advanced past this value by the time the turn reaches the front,
161
+ * `fn` is not called and `{ status: "stale" }` is returned.
162
+ */
163
+ generation?: number;
164
+ }
165
+ declare class TurnQueue {
166
+ private _queue;
167
+ private _generation;
168
+ private _activeRequestId;
169
+ private _countsByGeneration;
170
+ get generation(): number;
171
+ get activeRequestId(): string | null;
172
+ get isActive(): boolean;
173
+ enqueue<T>(requestId: string, fn: () => Promise<T>, options?: EnqueueOptions): Promise<TurnResult<T>>;
174
+ /**
175
+ * Advance the generation counter. All turns enqueued under older
176
+ * generations will be skipped when they reach the front of the queue.
177
+ */
178
+ reset(): void;
179
+ /**
180
+ * Wait until the queue is fully drained (no pending or active turns).
181
+ */
182
+ waitForIdle(): Promise<void>;
183
+ /**
184
+ * Number of active + queued turns for a given generation.
185
+ * Defaults to the current generation.
186
+ */
187
+ queuedCount(generation?: number): number;
188
+ private _decrementCount;
189
+ }
190
+ //#endregion
191
+ //#region src/chat/broadcast-state.d.ts
192
+ type BroadcastStreamState = {
193
+ status: "idle";
194
+ } | {
195
+ status: "observing";
196
+ streamId: string;
197
+ accumulator: StreamAccumulator;
198
+ };
199
+ type BroadcastStreamEvent = {
200
+ type: "response";
201
+ streamId: string; /** Fallback message ID for a new accumulator (ignored if one exists for this stream). */
202
+ messageId: string;
203
+ chunkData?: unknown;
204
+ done?: boolean;
205
+ error?: boolean;
206
+ replay?: boolean;
207
+ replayComplete?: boolean;
208
+ continuation?: boolean; /** Required when continuation=true so the accumulator can pick up existing parts. */
209
+ currentMessages?: UIMessage[];
210
+ } | {
211
+ type: "resume-fallback";
212
+ streamId: string;
213
+ messageId: string;
214
+ } | {
215
+ type: "clear";
216
+ };
217
+ interface TransitionResult {
218
+ state: BroadcastStreamState;
219
+ messagesUpdate?: (prev: UIMessage[]) => UIMessage[];
220
+ isStreaming: boolean;
221
+ }
222
+ declare function transition(state: BroadcastStreamState, event: BroadcastStreamEvent): TransitionResult;
223
+ //#endregion
224
+ //#region src/chat/resumable-stream.d.ts
225
+ /**
226
+ * Minimal SQL interface matching Agent's this.sql tagged template.
227
+ * Allows ResumableStream to work with the Agent's SQLite without
228
+ * depending on the full Agent class.
229
+ */
230
+ type SqlTaggedTemplate = {
231
+ <T = Record<string, unknown>>(strings: TemplateStringsArray, ...values: (string | number | boolean | null)[]): T[];
232
+ };
233
+ declare class ResumableStream {
234
+ private sql;
235
+ private _activeStreamId;
236
+ private _activeRequestId;
237
+ private _streamChunkIndex;
238
+ /**
239
+ * Whether the active stream was started in this instance (true) or
240
+ * restored from SQLite after hibernation/restart (false). An orphaned
241
+ * stream has no live LLM reader — the ReadableStream was lost when the
242
+ * DO was evicted.
243
+ */
244
+ private _isLive;
245
+ private _chunkBuffer;
246
+ private _isFlushingChunks;
247
+ private _lastCleanupTime;
248
+ constructor(sql: SqlTaggedTemplate);
249
+ get activeStreamId(): string | null;
250
+ get activeRequestId(): string | null;
251
+ hasActiveStream(): boolean;
252
+ /**
253
+ * Whether the active stream has a live LLM reader (started in this
254
+ * instance) vs being restored from SQLite after hibernation (orphaned).
255
+ */
256
+ get isLive(): boolean;
257
+ /**
258
+ * Start tracking a new stream for resumable streaming.
259
+ * Creates metadata entry in SQLite and sets up tracking state.
260
+ * @param requestId - The unique ID of the chat request
261
+ * @returns The generated stream ID
262
+ */
263
+ start(requestId: string): string;
264
+ /**
265
+ * Mark a stream as completed and flush any pending chunks.
266
+ * @param streamId - The stream to mark as completed
267
+ */
268
+ complete(streamId: string): void;
269
+ /**
270
+ * Mark a stream as errored and clean up state.
271
+ * @param streamId - The stream to mark as errored
272
+ */
273
+ markError(streamId: string): void;
274
+ /** Maximum chunk body size before skipping storage (bytes). Prevents SQLite row limit crash. */
275
+ private static CHUNK_MAX_BYTES;
276
+ /**
277
+ * Buffer a stream chunk for batch write to SQLite.
278
+ * Chunks exceeding the row size limit are skipped to prevent crashes.
279
+ * The chunk is still broadcast to live clients (caller handles that),
280
+ * but will be missing from replay on reconnection.
281
+ * @param streamId - The stream this chunk belongs to
282
+ * @param body - The serialized chunk body
283
+ */
284
+ storeChunk(streamId: string, body: string): void;
285
+ /**
286
+ * Flush buffered chunks to SQLite in a single batch.
287
+ * Uses a lock to prevent concurrent flush operations.
288
+ */
289
+ flushBuffer(): void;
290
+ /**
291
+ * Send stored stream chunks to a connection for replay.
292
+ * Chunks are marked with replay: true so the client can batch-apply them.
293
+ *
294
+ * Three outcomes:
295
+ * - **Live stream**: sends chunks + `replayComplete` — client flushes and
296
+ * continues receiving live chunks from the LLM reader.
297
+ * - **Orphaned stream** (restored from SQLite after hibernation, no reader):
298
+ * sends chunks + `done` and completes the stream. The caller should
299
+ * reconstruct and persist the partial message from the stored chunks.
300
+ * - **Completed during replay** (defensive): sends chunks + `done`.
301
+ *
302
+ * @param connection - The WebSocket connection
303
+ * @param requestId - The original request ID
304
+ * @returns The stream ID if the stream was orphaned and finalized, null otherwise.
305
+ * When non-null the caller should reconstruct the message from chunks.
306
+ */
307
+ replayChunks(connection: Connection, requestId: string): string | null;
308
+ /**
309
+ * Restore active stream state if the agent was restarted during streaming.
310
+ * Validates stream freshness to avoid sending stale resume notifications.
311
+ */
312
+ restore(): void;
313
+ /**
314
+ * Clear all stream data (called on chat history clear).
315
+ */
316
+ clearAll(): void;
317
+ /**
318
+ * Drop all stream tables (called on destroy).
319
+ */
320
+ destroy(): void;
321
+ private _maybeCleanupOldStreams;
322
+ /** @internal For testing only */
323
+ getStreamChunks(streamId: string): Array<{
324
+ body: string;
325
+ chunk_index: number;
326
+ }>;
327
+ /** @internal For testing only */
328
+ getStreamMetadata(streamId: string): {
329
+ status: string;
330
+ request_id: string;
331
+ } | null;
332
+ /** @internal For testing only */
333
+ getAllStreamMetadata(): Array<{
334
+ id: string;
335
+ status: string;
336
+ request_id: string;
337
+ created_at: number;
338
+ }>;
339
+ /** @internal For testing only */
340
+ insertStaleStream(streamId: string, requestId: string, ageMs: number): void;
341
+ }
342
+ //#endregion
343
+ //#region src/chat/client-tools.d.ts
344
+ /**
345
+ * Wire-format tool schema sent from the client.
346
+ * Uses `parameters` (JSONSchema7) rather than AI SDK's `inputSchema`
347
+ * because Zod schemas cannot be serialized over the wire.
348
+ */
349
+ type ClientToolSchema = {
350
+ /** Unique name for the tool */name: string; /** Human-readable description of what the tool does */
351
+ description?: Tool["description"]; /** JSON Schema defining the tool's input parameters */
352
+ parameters?: JSONSchema7;
353
+ };
354
+ /**
355
+ * Converts client tool schemas to AI SDK tool format.
356
+ *
357
+ * These tools have no `execute` function — when the AI model calls them,
358
+ * the tool call is sent back to the client for execution.
359
+ *
360
+ * @param clientTools - Array of tool schemas from the client
361
+ * @returns Record of AI SDK tools that can be spread into your tools object
362
+ */
363
+ declare function createToolsFromClientSchemas(clientTools?: ClientToolSchema[]): ToolSet;
364
+ //#endregion
365
+ //#region src/chat/protocol.d.ts
366
+ /**
367
+ * Wire protocol message type constants for the cf_agent_chat_* protocol.
368
+ *
369
+ * These are the string values used on the wire between agent servers and
370
+ * clients. Both @cloudflare/ai-chat (via its MessageType enum) and
371
+ * @cloudflare/think use these values.
372
+ */
373
+ declare const CHAT_MESSAGE_TYPES: {
374
+ readonly CHAT_MESSAGES: "cf_agent_chat_messages";
375
+ readonly USE_CHAT_REQUEST: "cf_agent_use_chat_request";
376
+ readonly USE_CHAT_RESPONSE: "cf_agent_use_chat_response";
377
+ readonly CHAT_CLEAR: "cf_agent_chat_clear";
378
+ readonly CHAT_REQUEST_CANCEL: "cf_agent_chat_request_cancel";
379
+ readonly STREAM_RESUMING: "cf_agent_stream_resuming";
380
+ readonly STREAM_RESUME_ACK: "cf_agent_stream_resume_ack";
381
+ readonly STREAM_RESUME_REQUEST: "cf_agent_stream_resume_request";
382
+ readonly STREAM_RESUME_NONE: "cf_agent_stream_resume_none";
383
+ readonly TOOL_RESULT: "cf_agent_tool_result";
384
+ readonly TOOL_APPROVAL: "cf_agent_tool_approval";
385
+ readonly MESSAGE_UPDATED: "cf_agent_message_updated";
386
+ };
387
+ //#endregion
388
+ //#region src/chat/continuation-state.d.ts
389
+ /**
390
+ * Minimal connection interface for sending WebSocket messages.
391
+ * Matches the Connection type from agents without importing it.
392
+ * Uses a permissive send signature so Connection (which extends
393
+ * WebSocket with its own send overload) is structurally assignable.
394
+ */
395
+ interface ContinuationConnection {
396
+ readonly id: string;
397
+ send(message: string): void;
398
+ }
399
+ interface ContinuationPending {
400
+ connection: ContinuationConnection;
401
+ connectionId: string;
402
+ requestId: string;
403
+ clientTools?: ClientToolSchema[];
404
+ body?: Record<string, unknown>;
405
+ errorPrefix: string | null;
406
+ prerequisite: Promise<boolean> | null;
407
+ pastCoalesce: boolean;
408
+ }
409
+ interface ContinuationDeferred {
410
+ connection: ContinuationConnection;
411
+ connectionId: string;
412
+ clientTools?: ClientToolSchema[];
413
+ body?: Record<string, unknown>;
414
+ errorPrefix: string;
415
+ prerequisite: Promise<boolean> | null;
416
+ }
417
+ declare class ContinuationState {
418
+ pending: ContinuationPending | null;
419
+ deferred: ContinuationDeferred | null;
420
+ activeRequestId: string | null;
421
+ activeConnectionId: string | null;
422
+ awaitingConnections: Map<string, ContinuationConnection>;
423
+ /** Clear pending state and awaiting connections (without sending RESUME_NONE). */
424
+ clearPending(): void;
425
+ clearDeferred(): void;
426
+ clearAll(): void;
427
+ /**
428
+ * Send STREAM_RESUME_NONE to all connections waiting for a
429
+ * continuation stream to start, then clear the map.
430
+ */
431
+ sendResumeNone(): void;
432
+ /**
433
+ * Flush awaiting connections by notifying each one via the provided
434
+ * callback (typically sends STREAM_RESUMING), then clear.
435
+ */
436
+ flushAwaitingConnections(notify: (conn: ContinuationConnection) => void): void;
437
+ /**
438
+ * Transition pending → active. Called when the continuation stream
439
+ * actually starts. Moves request/connection IDs to active slots,
440
+ * clears pending fields.
441
+ */
442
+ activatePending(): void;
443
+ /**
444
+ * Transition deferred → pending. Called when a continuation turn
445
+ * completes and there's a deferred follow-up waiting.
446
+ *
447
+ * Returns the new pending state (so the host can enqueue the turn),
448
+ * or null if there was nothing deferred.
449
+ */
450
+ activateDeferred(generateRequestId: () => string): ContinuationPending | null;
451
+ }
452
+ //#endregion
453
+ export { type BroadcastStreamEvent, type BroadcastStreamState, type TransitionResult as BroadcastTransitionResult, CHAT_MESSAGE_TYPES, type ChunkAction, type ChunkResult, type ClientToolSchema, type ContinuationConnection, type ContinuationDeferred, type ContinuationPending, ContinuationState, type EnqueueOptions, type MessagePart, type MessageParts, ROW_MAX_BYTES, ResumableStream, type SqlTaggedTemplate, StreamAccumulator, type StreamAccumulatorOptions, type StreamChunkData, TurnQueue, type TurnResult, applyChunkToParts, transition as broadcastTransition, byteLength, createToolsFromClientSchemas, enforceRowSizeLimit, sanitizeMessage };
454
+ //# sourceMappingURL=index.d.ts.map