agents 0.0.0-295f4dd → 0.0.0-29938d4

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.
Files changed (51) hide show
  1. package/README.md +121 -0
  2. package/dist/ai-chat-agent.d.ts +142 -17
  3. package/dist/ai-chat-agent.js +346 -40
  4. package/dist/ai-chat-agent.js.map +1 -1
  5. package/dist/ai-chat-v5-migration.js +154 -2
  6. package/dist/ai-chat-v5-migration.js.map +1 -0
  7. package/dist/ai-react.d.ts +136 -17
  8. package/dist/ai-react.js +216 -53
  9. package/dist/ai-react.js.map +1 -1
  10. package/dist/{ai-types-D_hTbf25.d.ts → ai-types-0OnT3FHg.d.ts} +26 -2
  11. package/dist/{ai-types-CwgHzwUb.js → ai-types-DEtF_8Km.js} +5 -1
  12. package/dist/ai-types-DEtF_8Km.js.map +1 -0
  13. package/dist/ai-types.d.ts +1 -1
  14. package/dist/ai-types.js +1 -1
  15. package/dist/{client-ClORm6f0.d.ts → client-CdM5I962.d.ts} +2 -2
  16. package/dist/{client-C_M5uPrn.d.ts → client-DFotUKH_.d.ts} +9 -9
  17. package/dist/{client-CcyhkGfN.js → client-DjTPRM8-.js} +2 -2
  18. package/dist/{client-CcyhkGfN.js.map → client-DjTPRM8-.js.map} +1 -1
  19. package/dist/client.d.ts +1 -2
  20. package/dist/client.js +1 -2
  21. package/dist/codemode/ai.js +3 -4
  22. package/dist/codemode/ai.js.map +1 -1
  23. package/dist/{context-_sPQqJWv.d.ts → context-DcbQ8o7k.d.ts} +1 -1
  24. package/dist/context.d.ts +1 -1
  25. package/dist/{do-oauth-client-provider-B-ryFIPr.d.ts → do-oauth-client-provider--To1Tsjj.d.ts} +1 -1
  26. package/dist/{index-DUnsVDnf.d.ts → index-CT2tCrLr.d.ts} +14 -14
  27. package/dist/{index-CyDpAVHZ.d.ts → index-DLuxm_9W.d.ts} +2 -2
  28. package/dist/index.d.ts +4 -7
  29. package/dist/index.js +2 -3
  30. package/dist/mcp/client.d.ts +1 -3
  31. package/dist/mcp/do-oauth-client-provider.d.ts +1 -1
  32. package/dist/mcp/index.d.ts +18 -12
  33. package/dist/mcp/index.js +21 -49
  34. package/dist/mcp/index.js.map +1 -1
  35. package/dist/{mcp-CzbSsLfc.d.ts → mcp-CPSfGUgd.d.ts} +1 -1
  36. package/dist/observability/index.d.ts +1 -2
  37. package/dist/observability/index.js +2 -3
  38. package/dist/react.d.ts +133 -14
  39. package/dist/react.js +50 -57
  40. package/dist/react.js.map +1 -1
  41. package/dist/schedule.d.ts +18 -72
  42. package/dist/{serializable-C4GLimgv.d.ts → serializable-Crsj26mx.d.ts} +1 -1
  43. package/dist/serializable.d.ts +1 -1
  44. package/dist/{src-BmbDclOA.js → src-BZDh910Z.js} +3 -3
  45. package/dist/src-BZDh910Z.js.map +1 -0
  46. package/package.json +28 -13
  47. package/dist/ai-chat-v5-migration-DguhuLKF.js +0 -155
  48. package/dist/ai-chat-v5-migration-DguhuLKF.js.map +0 -1
  49. package/dist/ai-types-CwgHzwUb.js.map +0 -1
  50. package/dist/react-DIGWa87z.d.ts +0 -137
  51. package/dist/src-BmbDclOA.js.map +0 -1
@@ -1,13 +1,35 @@
1
1
  import { t as agentContext } from "./context-BkKbAa1R.js";
2
- import { t as MessageType } from "./ai-types-CwgHzwUb.js";
3
- import "./client-CcyhkGfN.js";
2
+ import { t as MessageType } from "./ai-types-DEtF_8Km.js";
3
+ import "./client-DjTPRM8-.js";
4
4
  import "./client-QZa2Rq0l.js";
5
5
  import "./do-oauth-client-provider-B1fVIshX.js";
6
- import { t as Agent } from "./src-BmbDclOA.js";
7
- import { r as autoTransformMessages } from "./ai-chat-v5-migration-DguhuLKF.js";
6
+ import { t as Agent } from "./src-BZDh910Z.js";
7
+ import { autoTransformMessages } from "./ai-chat-v5-migration.js";
8
+ import { jsonSchema, tool } from "ai";
8
9
  import { nanoid } from "nanoid";
9
10
 
10
11
  //#region src/ai-chat-agent.ts
12
+ /**
13
+ * Converts client tool schemas to AI SDK tool format.
14
+ *
15
+ * These tools have no `execute` function - when the AI model calls them,
16
+ * the tool call is sent back to the client for execution.
17
+ *
18
+ * @param clientTools - Array of tool schemas from the client
19
+ * @returns Record of AI SDK tools that can be spread into your tools object
20
+ */
21
+ function createToolsFromClientSchemas(clientTools) {
22
+ if (!clientTools || clientTools.length === 0) return {};
23
+ const seenNames = /* @__PURE__ */ new Set();
24
+ for (const t of clientTools) {
25
+ if (seenNames.has(t.name)) console.warn(`[createToolsFromClientSchemas] Duplicate tool name "${t.name}" found. Later definitions will override earlier ones.`);
26
+ seenNames.add(t.name);
27
+ }
28
+ return Object.fromEntries(clientTools.map((t) => [t.name, tool({
29
+ description: t.description ?? "",
30
+ inputSchema: jsonSchema(t.parameters ?? { type: "object" })
31
+ })]));
32
+ }
11
33
  /** Number of chunks to buffer before flushing to SQLite */
12
34
  const CHUNK_BUFFER_SIZE = 10;
13
35
  /** Maximum buffer size to prevent memory issues on rapid reconnections */
@@ -28,6 +50,9 @@ var AIChatAgent = class extends Agent {
28
50
  super(ctx, env);
29
51
  this._activeStreamId = null;
30
52
  this._activeRequestId = null;
53
+ this._streamingMessage = null;
54
+ this._streamCompletionPromise = null;
55
+ this._streamCompletionResolve = null;
31
56
  this._streamChunkIndex = 0;
32
57
  this._chunkBuffer = [];
33
58
  this._isFlushingChunks = false;
@@ -72,7 +97,7 @@ var AIChatAgent = class extends Agent {
72
97
  }
73
98
  if (data.type === MessageType.CF_AGENT_USE_CHAT_REQUEST && data.init.method === "POST") {
74
99
  const { body } = data.init;
75
- const { messages } = JSON.parse(body);
100
+ const { messages, clientTools } = JSON.parse(body);
76
101
  const transformedMessages = autoTransformMessages(messages);
77
102
  this._broadcastChatMessage({
78
103
  messages: transformedMessages,
@@ -104,8 +129,11 @@ var AIChatAgent = class extends Agent {
104
129
  timestamp: Date.now(),
105
130
  type: "message:response"
106
131
  }, this.ctx);
107
- }, abortSignal ? { abortSignal } : void 0);
108
- if (response) await this._reply(data.id, response);
132
+ }, {
133
+ abortSignal,
134
+ clientTools
135
+ });
136
+ if (response) await this._reply(data.id, response, [connection.id]);
109
137
  else {
110
138
  console.warn(`[AIChatAgent] onChatMessage returned no response for chatMessageId: ${chatMessageId}`);
111
139
  this._broadcastChatMessage({
@@ -143,6 +171,42 @@ var AIChatAgent = class extends Agent {
143
171
  if (this._activeStreamId && this._activeRequestId && this._activeRequestId === data.id) this._sendStreamChunks(connection, this._activeStreamId, this._activeRequestId);
144
172
  return;
145
173
  }
174
+ if (data.type === MessageType.CF_AGENT_TOOL_RESULT) {
175
+ const { toolCallId, toolName, output, autoContinue } = data;
176
+ this._applyToolResult(toolCallId, toolName, output).then((applied) => {
177
+ if (applied && autoContinue) {
178
+ const waitForStream = async () => {
179
+ if (this._streamCompletionPromise) await this._streamCompletionPromise;
180
+ else await new Promise((resolve) => setTimeout(resolve, 500));
181
+ };
182
+ waitForStream().then(() => {
183
+ const continuationId = nanoid();
184
+ const abortSignal = this._getAbortSignal(continuationId);
185
+ this._tryCatchChat(async () => {
186
+ return agentContext.run({
187
+ agent: this,
188
+ connection,
189
+ request: void 0,
190
+ email: void 0
191
+ }, async () => {
192
+ const response = await this.onChatMessage(async (_finishResult) => {
193
+ this._removeAbortController(continuationId);
194
+ this.observability?.emit({
195
+ displayMessage: "Chat message response (tool continuation)",
196
+ id: continuationId,
197
+ payload: {},
198
+ timestamp: Date.now(),
199
+ type: "message:response"
200
+ }, this.ctx);
201
+ }, { abortSignal });
202
+ if (response) await this._reply(continuationId, response, [], { continuation: true });
203
+ });
204
+ });
205
+ });
206
+ }
207
+ });
208
+ return;
209
+ }
146
210
  }
147
211
  return _onMessage(connection, message);
148
212
  };
@@ -344,7 +408,7 @@ var AIChatAgent = class extends Agent {
344
408
  /**
345
409
  * Handle incoming chat messages and generate a response
346
410
  * @param onFinish Callback to be called when the response is finished
347
- * @param options.signal A signal to pass to any child requests which can be used to cancel them
411
+ * @param options Options including abort signal and client-defined tools
348
412
  * @returns Response to send to the client or undefined
349
413
  */
350
414
  async onChatMessage(onFinish, options) {
@@ -362,46 +426,262 @@ var AIChatAgent = class extends Agent {
362
426
  });
363
427
  }
364
428
  async persistMessages(messages, excludeBroadcastIds = []) {
365
- for (const message of messages) this.sql`
429
+ const mergedMessages = this._mergeIncomingWithServerState(messages);
430
+ for (const message of mergedMessages) {
431
+ const sanitizedMessage = this._sanitizeMessageForPersistence(message);
432
+ const messageToSave = this._resolveMessageForToolMerge(sanitizedMessage);
433
+ this.sql`
366
434
  insert into cf_ai_chat_agent_messages (id, message)
367
- values (${message.id}, ${JSON.stringify(message)})
435
+ values (${messageToSave.id}, ${JSON.stringify(messageToSave)})
368
436
  on conflict(id) do update set message = excluded.message
369
437
  `;
438
+ }
370
439
  this.messages = autoTransformMessages(this._loadMessagesFromDb());
371
440
  this._broadcastChatMessage({
372
- messages,
441
+ messages: mergedMessages,
373
442
  type: MessageType.CF_AGENT_CHAT_MESSAGES
374
443
  }, excludeBroadcastIds);
375
444
  }
376
- async _reply(id, response) {
445
+ /**
446
+ * Merges incoming messages with existing server state.
447
+ * This preserves tool outputs that the server has (via _applyToolResult)
448
+ * but the client doesn't have yet.
449
+ *
450
+ * @param incomingMessages - Messages from the client
451
+ * @returns Messages with server's tool outputs preserved
452
+ */
453
+ _mergeIncomingWithServerState(incomingMessages) {
454
+ const serverToolOutputs = /* @__PURE__ */ new Map();
455
+ for (const msg of this.messages) {
456
+ if (msg.role !== "assistant") continue;
457
+ for (const part of msg.parts) if ("toolCallId" in part && "state" in part && part.state === "output-available" && "output" in part) serverToolOutputs.set(part.toolCallId, part.output);
458
+ }
459
+ if (serverToolOutputs.size === 0) return incomingMessages;
460
+ return incomingMessages.map((msg) => {
461
+ if (msg.role !== "assistant") return msg;
462
+ let hasChanges = false;
463
+ const updatedParts = msg.parts.map((part) => {
464
+ if ("toolCallId" in part && "state" in part && part.state === "input-available" && serverToolOutputs.has(part.toolCallId)) {
465
+ hasChanges = true;
466
+ return {
467
+ ...part,
468
+ state: "output-available",
469
+ output: serverToolOutputs.get(part.toolCallId)
470
+ };
471
+ }
472
+ return part;
473
+ });
474
+ return hasChanges ? {
475
+ ...msg,
476
+ parts: updatedParts
477
+ } : msg;
478
+ });
479
+ }
480
+ /**
481
+ * Resolves a message for persistence, handling tool result merging.
482
+ * If the message contains tool parts with output-available state, checks if there's
483
+ * an existing message with the same toolCallId that should be updated instead of
484
+ * creating a duplicate. This prevents the "Duplicate item found" error from OpenAI
485
+ * when client-side tool results arrive in a new request.
486
+ *
487
+ * @param message - The message to potentially merge
488
+ * @returns The message with the correct ID (either original or merged)
489
+ */
490
+ _resolveMessageForToolMerge(message) {
491
+ if (message.role !== "assistant") return message;
492
+ for (const part of message.parts) if ("toolCallId" in part && "state" in part && part.state === "output-available") {
493
+ const toolCallId = part.toolCallId;
494
+ const existingMessage = this._findMessageByToolCallId(toolCallId);
495
+ if (existingMessage && existingMessage.id !== message.id) return {
496
+ ...message,
497
+ id: existingMessage.id
498
+ };
499
+ }
500
+ return message;
501
+ }
502
+ /**
503
+ * Finds an existing assistant message that contains a tool part with the given toolCallId.
504
+ * Used to detect when a tool result should update an existing message rather than
505
+ * creating a new one.
506
+ *
507
+ * @param toolCallId - The tool call ID to search for
508
+ * @returns The existing message if found, undefined otherwise
509
+ */
510
+ _findMessageByToolCallId(toolCallId) {
511
+ for (const msg of this.messages) {
512
+ if (msg.role !== "assistant") continue;
513
+ for (const part of msg.parts) if ("toolCallId" in part && part.toolCallId === toolCallId) return msg;
514
+ }
515
+ }
516
+ /**
517
+ * Sanitizes a message for persistence by removing ephemeral provider-specific
518
+ * data that should not be stored or sent back in subsequent requests.
519
+ *
520
+ * This handles two issues with the OpenAI Responses API:
521
+ *
522
+ * 1. **Duplicate item IDs**: The AI SDK's @ai-sdk/openai provider (v2.0.x+)
523
+ * defaults to using OpenAI's Responses API which assigns unique itemIds
524
+ * to each message part. When these IDs are persisted and sent back,
525
+ * OpenAI rejects them as duplicates.
526
+ *
527
+ * 2. **Empty reasoning parts**: OpenAI may return reasoning parts with empty
528
+ * text and encrypted content. These cause "Non-OpenAI reasoning parts are
529
+ * not supported" warnings when sent back via convertToModelMessages().
530
+ *
531
+ * @param message - The message to sanitize
532
+ * @returns A new message with ephemeral provider data removed
533
+ */
534
+ _sanitizeMessageForPersistence(message) {
535
+ const sanitizedParts = message.parts.filter((part) => {
536
+ if (part.type === "reasoning") {
537
+ const reasoningPart = part;
538
+ if (!reasoningPart.text || reasoningPart.text.trim() === "") return false;
539
+ }
540
+ return true;
541
+ }).map((part) => {
542
+ let sanitizedPart = part;
543
+ if ("providerMetadata" in sanitizedPart && sanitizedPart.providerMetadata && typeof sanitizedPart.providerMetadata === "object" && "openai" in sanitizedPart.providerMetadata) sanitizedPart = this._stripOpenAIMetadata(sanitizedPart, "providerMetadata");
544
+ if ("callProviderMetadata" in sanitizedPart && sanitizedPart.callProviderMetadata && typeof sanitizedPart.callProviderMetadata === "object" && "openai" in sanitizedPart.callProviderMetadata) sanitizedPart = this._stripOpenAIMetadata(sanitizedPart, "callProviderMetadata");
545
+ return sanitizedPart;
546
+ });
547
+ return {
548
+ ...message,
549
+ parts: sanitizedParts
550
+ };
551
+ }
552
+ /**
553
+ * Helper to strip OpenAI-specific ephemeral fields from a metadata object.
554
+ * Removes itemId and reasoningEncryptedContent while preserving other fields.
555
+ */
556
+ _stripOpenAIMetadata(part, metadataKey) {
557
+ const metadata = part[metadataKey];
558
+ if (!metadata?.openai) return part;
559
+ const { itemId: _itemId, reasoningEncryptedContent: _rec, ...restOpenai } = metadata.openai;
560
+ const hasOtherOpenaiFields = Object.keys(restOpenai).length > 0;
561
+ const { openai: _openai, ...restMetadata } = metadata;
562
+ let newMetadata;
563
+ if (hasOtherOpenaiFields) newMetadata = {
564
+ ...restMetadata,
565
+ openai: restOpenai
566
+ };
567
+ else if (Object.keys(restMetadata).length > 0) newMetadata = restMetadata;
568
+ const { [metadataKey]: _oldMeta, ...restPart } = part;
569
+ if (newMetadata) return {
570
+ ...restPart,
571
+ [metadataKey]: newMetadata
572
+ };
573
+ return restPart;
574
+ }
575
+ /**
576
+ * Applies a tool result to an existing assistant message.
577
+ * This is used when the client sends CF_AGENT_TOOL_RESULT for client-side tools.
578
+ * The server is the source of truth, so we update the message here and broadcast
579
+ * the update to all clients.
580
+ *
581
+ * @param toolCallId - The tool call ID this result is for
582
+ * @param toolName - The name of the tool
583
+ * @param output - The output from the tool execution
584
+ * @returns true if the result was applied, false if the message was not found
585
+ */
586
+ async _applyToolResult(toolCallId, _toolName, output) {
587
+ let message;
588
+ if (this._streamingMessage) {
589
+ for (const part of this._streamingMessage.parts) if ("toolCallId" in part && part.toolCallId === toolCallId) {
590
+ message = this._streamingMessage;
591
+ break;
592
+ }
593
+ }
594
+ if (!message) for (let attempt = 0; attempt < 10; attempt++) {
595
+ message = this._findMessageByToolCallId(toolCallId);
596
+ if (message) break;
597
+ await new Promise((resolve) => setTimeout(resolve, 100));
598
+ }
599
+ if (!message) {
600
+ console.warn(`[AIChatAgent] _applyToolResult: Could not find message with toolCallId ${toolCallId} after retries`);
601
+ return false;
602
+ }
603
+ const isStreamingMessage = message === this._streamingMessage;
604
+ let updated = false;
605
+ if (isStreamingMessage) {
606
+ for (const part of message.parts) if ("toolCallId" in part && part.toolCallId === toolCallId && "state" in part && part.state === "input-available") {
607
+ part.state = "output-available";
608
+ part.output = output;
609
+ updated = true;
610
+ break;
611
+ }
612
+ } else {
613
+ const updatedParts = message.parts.map((part) => {
614
+ if ("toolCallId" in part && part.toolCallId === toolCallId && "state" in part && part.state === "input-available") {
615
+ updated = true;
616
+ return {
617
+ ...part,
618
+ state: "output-available",
619
+ output
620
+ };
621
+ }
622
+ return part;
623
+ });
624
+ if (updated) {
625
+ const updatedMessage = this._sanitizeMessageForPersistence({
626
+ ...message,
627
+ parts: updatedParts
628
+ });
629
+ this.sql`
630
+ update cf_ai_chat_agent_messages
631
+ set message = ${JSON.stringify(updatedMessage)}
632
+ where id = ${message.id}
633
+ `;
634
+ this.messages = autoTransformMessages(this._loadMessagesFromDb());
635
+ }
636
+ }
637
+ if (!updated) {
638
+ console.warn(`[AIChatAgent] _applyToolResult: Tool part with toolCallId ${toolCallId} not in input-available state`);
639
+ return false;
640
+ }
641
+ if (!isStreamingMessage) {
642
+ const broadcastMessage = this._findMessageByToolCallId(toolCallId);
643
+ if (broadcastMessage) this._broadcastChatMessage({
644
+ type: MessageType.CF_AGENT_MESSAGE_UPDATED,
645
+ message: broadcastMessage
646
+ });
647
+ }
648
+ return true;
649
+ }
650
+ async _reply(id, response, excludeBroadcastIds = [], options = {}) {
651
+ const { continuation = false } = options;
377
652
  return this._tryCatchChat(async () => {
378
653
  if (!response.body) {
379
654
  this._broadcastChatMessage({
380
655
  body: "",
381
656
  done: true,
382
657
  id,
383
- type: MessageType.CF_AGENT_USE_CHAT_RESPONSE
658
+ type: MessageType.CF_AGENT_USE_CHAT_RESPONSE,
659
+ ...continuation && { continuation: true }
384
660
  });
385
661
  return;
386
662
  }
387
663
  const streamId = this._startStream(id);
388
- const { getToolName, isToolUIPart, parsePartialJson } = await import("ai");
664
+ const { getToolName: getToolName$1, isToolUIPart: isToolUIPart$1, parsePartialJson } = await import("ai");
389
665
  const reader = response.body.getReader();
390
666
  const message = {
391
667
  id: `assistant_${Date.now()}_${Math.random().toString(36).slice(2, 11)}`,
392
668
  role: "assistant",
393
669
  parts: []
394
670
  };
671
+ this._streamingMessage = message;
672
+ this._streamCompletionPromise = new Promise((resolve) => {
673
+ this._streamCompletionResolve = resolve;
674
+ });
395
675
  let activeTextParts = {};
396
676
  let activeReasoningParts = {};
397
677
  const partialToolCalls = {};
398
- function updateDynamicToolPart(options) {
399
- const part = message.parts.find((part$1) => part$1.type === "dynamic-tool" && part$1.toolCallId === options.toolCallId);
400
- const anyOptions = options;
678
+ function updateDynamicToolPart(options$1) {
679
+ const part = message.parts.find((part$1) => part$1.type === "dynamic-tool" && part$1.toolCallId === options$1.toolCallId);
680
+ const anyOptions = options$1;
401
681
  const anyPart = part;
402
682
  if (part != null) {
403
- part.state = options.state;
404
- anyPart.toolName = options.toolName;
683
+ part.state = options$1.state;
684
+ anyPart.toolName = options$1.toolName;
405
685
  anyPart.input = anyOptions.input;
406
686
  anyPart.output = anyOptions.output;
407
687
  anyPart.errorText = anyOptions.errorText;
@@ -410,9 +690,9 @@ var AIChatAgent = class extends Agent {
410
690
  if (anyOptions.providerMetadata != null && part.state === "input-available") part.callProviderMetadata = anyOptions.providerMetadata;
411
691
  } else message.parts.push({
412
692
  type: "dynamic-tool",
413
- toolName: options.toolName,
414
- toolCallId: options.toolCallId,
415
- state: options.state,
693
+ toolName: options$1.toolName,
694
+ toolCallId: options$1.toolCallId,
695
+ state: options$1.state,
416
696
  input: anyOptions.input,
417
697
  output: anyOptions.output,
418
698
  errorText: anyOptions.errorText,
@@ -420,12 +700,12 @@ var AIChatAgent = class extends Agent {
420
700
  ...anyOptions.providerMetadata != null ? { callProviderMetadata: anyOptions.providerMetadata } : {}
421
701
  });
422
702
  }
423
- function updateToolPart(options) {
424
- const part = message.parts.find((part$1) => isToolUIPart(part$1) && part$1.toolCallId === options.toolCallId);
425
- const anyOptions = options;
703
+ function updateToolPart(options$1) {
704
+ const part = message.parts.find((part$1) => isToolUIPart$1(part$1) && part$1.toolCallId === options$1.toolCallId);
705
+ const anyOptions = options$1;
426
706
  const anyPart = part;
427
707
  if (part != null) {
428
- part.state = options.state;
708
+ part.state = options$1.state;
429
709
  anyPart.input = anyOptions.input;
430
710
  anyPart.output = anyOptions.output;
431
711
  anyPart.errorText = anyOptions.errorText;
@@ -434,9 +714,9 @@ var AIChatAgent = class extends Agent {
434
714
  anyPart.providerExecuted = anyOptions.providerExecuted ?? part.providerExecuted;
435
715
  if (anyOptions.providerMetadata != null && part.state === "input-available") part.callProviderMetadata = anyOptions.providerMetadata;
436
716
  } else message.parts.push({
437
- type: `tool-${options.toolName}`,
438
- toolCallId: options.toolCallId,
439
- state: options.state,
717
+ type: `tool-${options$1.toolName}`,
718
+ toolCallId: options$1.toolCallId,
719
+ state: options$1.state,
440
720
  input: anyOptions.input,
441
721
  output: anyOptions.output,
442
722
  rawInput: anyOptions.rawInput,
@@ -463,7 +743,8 @@ var AIChatAgent = class extends Agent {
463
743
  body: "",
464
744
  done: true,
465
745
  id,
466
- type: MessageType.CF_AGENT_USE_CHAT_RESPONSE
746
+ type: MessageType.CF_AGENT_USE_CHAT_RESPONSE,
747
+ ...continuation && { continuation: true }
467
748
  });
468
749
  break;
469
750
  }
@@ -548,7 +829,7 @@ var AIChatAgent = class extends Agent {
548
829
  });
549
830
  break;
550
831
  case "tool-input-start": {
551
- const toolInvocations = message.parts.filter(isToolUIPart);
832
+ const toolInvocations = message.parts.filter(isToolUIPart$1);
552
833
  partialToolCalls[data.toolCallId] = {
553
834
  text: "",
554
835
  toolName: data.toolName,
@@ -637,11 +918,11 @@ var AIChatAgent = class extends Agent {
637
918
  preliminary: data.preliminary
638
919
  });
639
920
  } else {
640
- const toolInvocation = message.parts.filter(isToolUIPart).find((invocation) => invocation.toolCallId === data.toolCallId);
921
+ const toolInvocation = message.parts.filter(isToolUIPart$1).find((invocation) => invocation.toolCallId === data.toolCallId);
641
922
  if (!toolInvocation) throw new Error("Tool invocation not found");
642
923
  updateToolPart({
643
924
  toolCallId: data.toolCallId,
644
- toolName: getToolName(toolInvocation),
925
+ toolName: getToolName$1(toolInvocation),
645
926
  state: "output-available",
646
927
  input: toolInvocation.input,
647
928
  output: data.output,
@@ -662,11 +943,11 @@ var AIChatAgent = class extends Agent {
662
943
  errorText: data.errorText
663
944
  });
664
945
  } else {
665
- const toolInvocation = message.parts.filter(isToolUIPart).find((invocation) => invocation.toolCallId === data.toolCallId);
946
+ const toolInvocation = message.parts.filter(isToolUIPart$1).find((invocation) => invocation.toolCallId === data.toolCallId);
666
947
  if (!toolInvocation) throw new Error("Tool invocation not found");
667
948
  updateToolPart({
668
949
  toolCallId: data.toolCallId,
669
- toolName: getToolName(toolInvocation),
950
+ toolName: getToolName$1(toolInvocation),
670
951
  state: "output-error",
671
952
  input: toolInvocation.input,
672
953
  rawInput: "rawInput" in toolInvocation ? toolInvocation.rawInput : void 0,
@@ -716,7 +997,8 @@ var AIChatAgent = class extends Agent {
716
997
  body: chunkBody,
717
998
  done: false,
718
999
  id,
719
- type: MessageType.CF_AGENT_USE_CHAT_RESPONSE
1000
+ type: MessageType.CF_AGENT_USE_CHAT_RESPONSE,
1001
+ ...continuation && { continuation: true }
720
1002
  });
721
1003
  } catch (_error) {}
722
1004
  } else if (chunk.length > 0) {
@@ -733,7 +1015,8 @@ var AIChatAgent = class extends Agent {
733
1015
  body: chunkBody,
734
1016
  done: false,
735
1017
  id,
736
- type: MessageType.CF_AGENT_USE_CHAT_RESPONSE
1018
+ type: MessageType.CF_AGENT_USE_CHAT_RESPONSE,
1019
+ ...continuation && { continuation: true }
737
1020
  });
738
1021
  }
739
1022
  }
@@ -745,14 +1028,37 @@ var AIChatAgent = class extends Agent {
745
1028
  done: true,
746
1029
  error: true,
747
1030
  id,
748
- type: MessageType.CF_AGENT_USE_CHAT_RESPONSE
1031
+ type: MessageType.CF_AGENT_USE_CHAT_RESPONSE,
1032
+ ...continuation && { continuation: true }
749
1033
  });
750
1034
  }
751
1035
  throw error;
752
1036
  } finally {
753
1037
  reader.releaseLock();
754
1038
  }
755
- if (message.parts.length > 0) await this.persistMessages([...this.messages, message]);
1039
+ if (message.parts.length > 0) if (continuation) {
1040
+ let lastAssistantIdx = -1;
1041
+ for (let i = this.messages.length - 1; i >= 0; i--) if (this.messages[i].role === "assistant") {
1042
+ lastAssistantIdx = i;
1043
+ break;
1044
+ }
1045
+ if (lastAssistantIdx >= 0) {
1046
+ const lastAssistant = this.messages[lastAssistantIdx];
1047
+ const mergedMessage = {
1048
+ ...lastAssistant,
1049
+ parts: [...lastAssistant.parts, ...message.parts]
1050
+ };
1051
+ const updatedMessages = [...this.messages];
1052
+ updatedMessages[lastAssistantIdx] = mergedMessage;
1053
+ await this.persistMessages(updatedMessages, excludeBroadcastIds);
1054
+ } else await this.persistMessages([...this.messages, message], excludeBroadcastIds);
1055
+ } else await this.persistMessages([...this.messages, message], excludeBroadcastIds);
1056
+ this._streamingMessage = null;
1057
+ if (this._streamCompletionResolve) {
1058
+ this._streamCompletionResolve();
1059
+ this._streamCompletionResolve = null;
1060
+ this._streamCompletionPromise = null;
1061
+ }
756
1062
  });
757
1063
  }
758
1064
  /**
@@ -816,5 +1122,5 @@ var AIChatAgent = class extends Agent {
816
1122
  };
817
1123
 
818
1124
  //#endregion
819
- export { AIChatAgent };
1125
+ export { AIChatAgent, createToolsFromClientSchemas };
820
1126
  //# sourceMappingURL=ai-chat-agent.js.map