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.
- package/README.md +121 -0
- package/dist/ai-chat-agent.d.ts +142 -17
- package/dist/ai-chat-agent.js +346 -40
- package/dist/ai-chat-agent.js.map +1 -1
- package/dist/ai-chat-v5-migration.js +154 -2
- package/dist/ai-chat-v5-migration.js.map +1 -0
- package/dist/ai-react.d.ts +136 -17
- package/dist/ai-react.js +216 -53
- package/dist/ai-react.js.map +1 -1
- package/dist/{ai-types-D_hTbf25.d.ts → ai-types-0OnT3FHg.d.ts} +26 -2
- package/dist/{ai-types-CwgHzwUb.js → ai-types-DEtF_8Km.js} +5 -1
- package/dist/ai-types-DEtF_8Km.js.map +1 -0
- package/dist/ai-types.d.ts +1 -1
- package/dist/ai-types.js +1 -1
- package/dist/{client-ClORm6f0.d.ts → client-CdM5I962.d.ts} +2 -2
- package/dist/{client-C_M5uPrn.d.ts → client-DFotUKH_.d.ts} +9 -9
- package/dist/{client-CcyhkGfN.js → client-DjTPRM8-.js} +2 -2
- package/dist/{client-CcyhkGfN.js.map → client-DjTPRM8-.js.map} +1 -1
- package/dist/client.d.ts +1 -2
- package/dist/client.js +1 -2
- package/dist/codemode/ai.js +3 -4
- package/dist/codemode/ai.js.map +1 -1
- package/dist/{context-_sPQqJWv.d.ts → context-DcbQ8o7k.d.ts} +1 -1
- package/dist/context.d.ts +1 -1
- package/dist/{do-oauth-client-provider-B-ryFIPr.d.ts → do-oauth-client-provider--To1Tsjj.d.ts} +1 -1
- package/dist/{index-DUnsVDnf.d.ts → index-CT2tCrLr.d.ts} +14 -14
- package/dist/{index-CyDpAVHZ.d.ts → index-DLuxm_9W.d.ts} +2 -2
- package/dist/index.d.ts +4 -7
- package/dist/index.js +2 -3
- package/dist/mcp/client.d.ts +1 -3
- package/dist/mcp/do-oauth-client-provider.d.ts +1 -1
- package/dist/mcp/index.d.ts +18 -12
- package/dist/mcp/index.js +21 -49
- package/dist/mcp/index.js.map +1 -1
- package/dist/{mcp-CzbSsLfc.d.ts → mcp-CPSfGUgd.d.ts} +1 -1
- package/dist/observability/index.d.ts +1 -2
- package/dist/observability/index.js +2 -3
- package/dist/react.d.ts +133 -14
- package/dist/react.js +50 -57
- package/dist/react.js.map +1 -1
- package/dist/schedule.d.ts +18 -72
- package/dist/{serializable-C4GLimgv.d.ts → serializable-Crsj26mx.d.ts} +1 -1
- package/dist/serializable.d.ts +1 -1
- package/dist/{src-BmbDclOA.js → src-BZDh910Z.js} +3 -3
- package/dist/src-BZDh910Z.js.map +1 -0
- package/package.json +28 -13
- package/dist/ai-chat-v5-migration-DguhuLKF.js +0 -155
- package/dist/ai-chat-v5-migration-DguhuLKF.js.map +0 -1
- package/dist/ai-types-CwgHzwUb.js.map +0 -1
- package/dist/react-DIGWa87z.d.ts +0 -137
- package/dist/src-BmbDclOA.js.map +0 -1
package/dist/ai-chat-agent.js
CHANGED
|
@@ -1,13 +1,35 @@
|
|
|
1
1
|
import { t as agentContext } from "./context-BkKbAa1R.js";
|
|
2
|
-
import { t as MessageType } from "./ai-types-
|
|
3
|
-
import "./client-
|
|
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-
|
|
7
|
-
import {
|
|
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
|
-
},
|
|
108
|
-
|
|
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
|
|
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
|
-
|
|
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 (${
|
|
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
|
-
|
|
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)
|
|
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
|