agents 0.0.0-19a3a25 → 0.0.0-1a3d226
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 +126 -3
- package/dist/ai-chat-agent.d.ts +229 -22
- package/dist/ai-chat-agent.js +692 -106
- 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 +141 -16
- package/dist/ai-react.js +381 -68
- package/dist/ai-react.js.map +1 -1
- package/dist/{ai-types-D5YoPrBZ.d.ts → ai-types-0OnT3FHg.d.ts} +40 -8
- package/dist/{ai-types-B3aQaFv3.js → ai-types-DEtF_8Km.js} +9 -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/cli/index.d.ts +1 -0
- package/dist/{cli.js → cli/index.js} +7 -6
- package/dist/cli/index.js.map +1 -0
- package/dist/client-BINtT7y-.d.ts +834 -0
- package/dist/{client-CbWe9FBd.d.ts → client-CdM5I962.d.ts} +2 -2
- package/dist/{client-BfiZ3HQd.js → client-DjTPRM8-.js} +2 -2
- package/dist/{client-BfiZ3HQd.js.map → client-DjTPRM8-.js.map} +1 -1
- package/dist/client-QZa2Rq0l.js +1105 -0
- package/dist/client-QZa2Rq0l.js.map +1 -0
- package/dist/client.d.ts +1 -2
- package/dist/client.js +1 -2
- package/dist/codemode/ai.js +6 -6
- package/dist/codemode/ai.js.map +1 -1
- package/dist/context-BkKbAa1R.js +8 -0
- package/dist/context-BkKbAa1R.js.map +1 -0
- package/dist/context-DcbQ8o7k.d.ts +24 -0
- package/dist/context.d.ts +6 -0
- package/dist/context.js +3 -0
- package/dist/{do-oauth-client-provider-DGc5pP0l.d.ts → do-oauth-client-provider--To1Tsjj.d.ts} +20 -5
- package/dist/{do-oauth-client-provider-CswoD5Lu.js → do-oauth-client-provider-B1fVIshX.js} +70 -8
- package/dist/do-oauth-client-provider-B1fVIshX.js.map +1 -0
- package/dist/{index-CuqiHyhT.d.ts → index-CfZ2mfMI.d.ts} +80 -64
- package/dist/{index-DhJCaDWd.d.ts → index-DLuxm_9W.d.ts} +2 -2
- package/dist/index.d.ts +31 -34
- package/dist/index.js +5 -5
- package/dist/mcp/client.d.ts +2 -4
- package/dist/mcp/client.js +2 -1
- package/dist/mcp/do-oauth-client-provider.d.ts +1 -1
- package/dist/mcp/do-oauth-client-provider.js +1 -1
- package/dist/mcp/index.d.ts +23 -16
- package/dist/mcp/index.js +71 -69
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/x402.js +10 -6
- package/dist/mcp/x402.js.map +1 -1
- package/dist/{mcp-Dw5vDrY8.d.ts → mcp-CPSfGUgd.d.ts} +1 -1
- package/dist/observability/index.d.ts +1 -2
- package/dist/observability/index.js +5 -5
- package/dist/react.d.ts +134 -10
- package/dist/react.js +57 -57
- package/dist/react.js.map +1 -1
- package/dist/schedule.d.ts +18 -72
- package/dist/{serializable-CymX8ovI.d.ts → serializable-Crsj26mx.d.ts} +1 -1
- package/dist/serializable.d.ts +1 -1
- package/dist/{src-CwIW7tU2.js → src-BZDh910Z.js} +104 -139
- package/dist/src-BZDh910Z.js.map +1 -0
- package/package.json +31 -16
- package/dist/ai-chat-v5-migration-DBHGW4Hv.js +0 -155
- package/dist/ai-chat-v5-migration-DBHGW4Hv.js.map +0 -1
- package/dist/ai-types-B3aQaFv3.js.map +0 -1
- package/dist/cli.d.ts +0 -8
- package/dist/cli.js.map +0 -1
- package/dist/client-BnO9jNtu.d.ts +0 -5283
- package/dist/client-DZhjV_XA.js +0 -719
- package/dist/client-DZhjV_XA.js.map +0 -1
- package/dist/do-oauth-client-provider-CswoD5Lu.js.map +0 -1
- package/dist/react-Cx9uE2Jd.d.ts +0 -113
- package/dist/src-CwIW7tU2.js.map +0 -1
package/dist/ai-react.js
CHANGED
|
@@ -1,10 +1,28 @@
|
|
|
1
|
-
import { t as MessageType } from "./ai-types-
|
|
1
|
+
import { t as MessageType } from "./ai-types-DEtF_8Km.js";
|
|
2
|
+
import { DefaultChatTransport, getToolName, isToolUIPart } from "ai";
|
|
2
3
|
import { nanoid } from "nanoid";
|
|
3
4
|
import { useChat } from "@ai-sdk/react";
|
|
4
|
-
import {
|
|
5
|
-
import { use, useCallback, useEffect, useMemo, useRef } from "react";
|
|
5
|
+
import { use, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
6
6
|
|
|
7
7
|
//#region src/ai-react.tsx
|
|
8
|
+
/**
|
|
9
|
+
* Extracts tool schemas from tools that have client-side execute functions.
|
|
10
|
+
* These schemas are automatically sent to the server with each request.
|
|
11
|
+
* @param tools - Record of tool name to tool definition
|
|
12
|
+
* @returns Array of tool schemas to send to server, or undefined if none
|
|
13
|
+
*/
|
|
14
|
+
function extractClientToolSchemas(tools) {
|
|
15
|
+
if (!tools) return void 0;
|
|
16
|
+
const schemas = Object.entries(tools).filter(([_, tool$1]) => tool$1.execute).map(([name, tool$1]) => {
|
|
17
|
+
if (tool$1.inputSchema && !tool$1.parameters) console.warn(`[useAgentChat] Tool "${name}" uses deprecated 'inputSchema'. Please migrate to 'parameters'.`);
|
|
18
|
+
return {
|
|
19
|
+
name,
|
|
20
|
+
description: tool$1.description,
|
|
21
|
+
parameters: tool$1.parameters ?? tool$1.inputSchema
|
|
22
|
+
};
|
|
23
|
+
});
|
|
24
|
+
return schemas.length > 0 ? schemas : void 0;
|
|
25
|
+
}
|
|
8
26
|
const requestCache = /* @__PURE__ */ new Map();
|
|
9
27
|
/**
|
|
10
28
|
* React hook for building AI chat interfaces using an Agent
|
|
@@ -22,7 +40,7 @@ function detectToolsRequiringConfirmation(tools) {
|
|
|
22
40
|
return Object.entries(tools).filter(([_name, tool$1]) => !tool$1.execute).map(([name]) => name);
|
|
23
41
|
}
|
|
24
42
|
function useAgentChat(options) {
|
|
25
|
-
const { agent, getInitialMessages, messages: optionsInitialMessages, experimental_automaticToolResolution, tools, toolsRequiringConfirmation: manualToolsRequiringConfirmation, autoSendAfterAllConfirmationsResolved = true
|
|
43
|
+
const { agent, getInitialMessages, messages: optionsInitialMessages, experimental_automaticToolResolution, tools, toolsRequiringConfirmation: manualToolsRequiringConfirmation, autoContinueAfterToolResult = false, autoSendAfterAllConfirmationsResolved = true, resume = true, prepareSendMessagesRequest, ...rest } = options;
|
|
26
44
|
const toolsRequiringConfirmation = manualToolsRequiringConfirmation ?? detectToolsRequiringConfirmation(tools);
|
|
27
45
|
const agentUrl = new URL(`${(agent._url || agent._pkurl)?.replace("ws://", "http://").replace("wss://", "https://")}`);
|
|
28
46
|
agentUrl.searchParams.delete("_pk");
|
|
@@ -78,13 +96,17 @@ function useAgentChat(options) {
|
|
|
78
96
|
const abortController = new AbortController();
|
|
79
97
|
let controller;
|
|
80
98
|
const currentAgent = agentRef.current;
|
|
99
|
+
localRequestIdsRef.current.add(id);
|
|
81
100
|
signal?.addEventListener("abort", () => {
|
|
82
101
|
currentAgent.send(JSON.stringify({
|
|
83
102
|
id,
|
|
84
103
|
type: MessageType.CF_AGENT_CHAT_REQUEST_CANCEL
|
|
85
104
|
}));
|
|
86
105
|
abortController.abort();
|
|
87
|
-
|
|
106
|
+
try {
|
|
107
|
+
controller.close();
|
|
108
|
+
} catch {}
|
|
109
|
+
localRequestIdsRef.current.delete(id);
|
|
88
110
|
});
|
|
89
111
|
currentAgent.addEventListener("message", (event) => {
|
|
90
112
|
let data;
|
|
@@ -97,18 +119,27 @@ function useAgentChat(options) {
|
|
|
97
119
|
if (data.id === id) if (data.error) {
|
|
98
120
|
controller.error(new Error(data.body));
|
|
99
121
|
abortController.abort();
|
|
122
|
+
localRequestIdsRef.current.delete(id);
|
|
100
123
|
} else {
|
|
101
124
|
if (data.body?.trim()) controller.enqueue(new TextEncoder().encode(`data: ${data.body}\n\n`));
|
|
102
125
|
if (data.done) {
|
|
103
|
-
|
|
126
|
+
try {
|
|
127
|
+
controller.close();
|
|
128
|
+
} catch {}
|
|
104
129
|
abortController.abort();
|
|
130
|
+
localRequestIdsRef.current.delete(id);
|
|
105
131
|
}
|
|
106
132
|
}
|
|
107
133
|
}
|
|
108
134
|
}, { signal: abortController.signal });
|
|
109
|
-
const stream = new ReadableStream({
|
|
110
|
-
|
|
111
|
-
|
|
135
|
+
const stream = new ReadableStream({
|
|
136
|
+
start(c) {
|
|
137
|
+
controller = c;
|
|
138
|
+
},
|
|
139
|
+
cancel(reason) {
|
|
140
|
+
console.warn("[agents/ai-react] cancelling stream", id, reason || "no reason");
|
|
141
|
+
}
|
|
142
|
+
});
|
|
112
143
|
currentAgent.send(JSON.stringify({
|
|
113
144
|
id,
|
|
114
145
|
init: {
|
|
@@ -129,19 +160,47 @@ function useAgentChat(options) {
|
|
|
129
160
|
}));
|
|
130
161
|
return new Response(stream);
|
|
131
162
|
}, []);
|
|
163
|
+
const toolsRef = useRef(tools);
|
|
164
|
+
toolsRef.current = tools;
|
|
165
|
+
const prepareSendMessagesRequestRef = useRef(prepareSendMessagesRequest);
|
|
166
|
+
prepareSendMessagesRequestRef.current = prepareSendMessagesRequest;
|
|
132
167
|
const customTransport = useMemo(() => ({
|
|
133
|
-
sendMessages: async (
|
|
168
|
+
sendMessages: async (sendMessageOptions) => {
|
|
169
|
+
const clientToolSchemas = extractClientToolSchemas(toolsRef.current);
|
|
134
170
|
return new DefaultChatTransport({
|
|
135
171
|
api: agentUrlString,
|
|
136
|
-
fetch: aiFetch
|
|
137
|
-
|
|
172
|
+
fetch: aiFetch,
|
|
173
|
+
prepareSendMessagesRequest: clientToolSchemas || prepareSendMessagesRequestRef.current ? async (prepareOptions) => {
|
|
174
|
+
let body = {};
|
|
175
|
+
let headers;
|
|
176
|
+
let credentials;
|
|
177
|
+
let api;
|
|
178
|
+
if (clientToolSchemas) body = {
|
|
179
|
+
id: prepareOptions.id,
|
|
180
|
+
messages: prepareOptions.messages,
|
|
181
|
+
trigger: prepareOptions.trigger,
|
|
182
|
+
clientTools: clientToolSchemas
|
|
183
|
+
};
|
|
184
|
+
if (prepareSendMessagesRequestRef.current) {
|
|
185
|
+
const userResult = await prepareSendMessagesRequestRef.current(prepareOptions);
|
|
186
|
+
headers = userResult.headers;
|
|
187
|
+
credentials = userResult.credentials;
|
|
188
|
+
api = userResult.api;
|
|
189
|
+
body = {
|
|
190
|
+
...body,
|
|
191
|
+
...userResult.body ?? {}
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
return {
|
|
195
|
+
body,
|
|
196
|
+
headers,
|
|
197
|
+
credentials,
|
|
198
|
+
api
|
|
199
|
+
};
|
|
200
|
+
} : void 0
|
|
201
|
+
}).sendMessages(sendMessageOptions);
|
|
138
202
|
},
|
|
139
|
-
reconnectToStream: async (
|
|
140
|
-
return new DefaultChatTransport({
|
|
141
|
-
api: agentUrlString,
|
|
142
|
-
fetch: aiFetch
|
|
143
|
-
}).reconnectToStream(options$1);
|
|
144
|
-
}
|
|
203
|
+
reconnectToStream: async () => null
|
|
145
204
|
}), [agentUrlString, aiFetch]);
|
|
146
205
|
const useChatHelpers = useChat({
|
|
147
206
|
...rest,
|
|
@@ -150,6 +209,10 @@ function useAgentChat(options) {
|
|
|
150
209
|
id: agent._pk
|
|
151
210
|
});
|
|
152
211
|
const processedToolCalls = useRef(/* @__PURE__ */ new Set());
|
|
212
|
+
const isResolvingToolsRef = useRef(false);
|
|
213
|
+
const [clientToolResults, setClientToolResults] = useState(/* @__PURE__ */ new Map());
|
|
214
|
+
const messagesRef = useRef(useChatHelpers.messages);
|
|
215
|
+
messagesRef.current = useChatHelpers.messages;
|
|
153
216
|
const lastMessage = useChatHelpers.messages[useChatHelpers.messages.length - 1];
|
|
154
217
|
const pendingConfirmations = (() => {
|
|
155
218
|
if (!lastMessage || lastMessage.role !== "assistant") return {
|
|
@@ -167,40 +230,82 @@ function useAgentChat(options) {
|
|
|
167
230
|
pendingConfirmationsRef.current = pendingConfirmations;
|
|
168
231
|
useEffect(() => {
|
|
169
232
|
if (!experimental_automaticToolResolution) return;
|
|
233
|
+
if (isResolvingToolsRef.current) return;
|
|
170
234
|
const lastMessage$1 = useChatHelpers.messages[useChatHelpers.messages.length - 1];
|
|
171
235
|
if (!lastMessage$1 || lastMessage$1.role !== "assistant") return;
|
|
172
236
|
const toolCalls = lastMessage$1.parts.filter((part) => isToolUIPart(part) && part.state === "input-available" && !processedToolCalls.current.has(part.toolCallId));
|
|
173
|
-
if (toolCalls.length > 0)
|
|
174
|
-
const
|
|
237
|
+
if (toolCalls.length > 0) {
|
|
238
|
+
const currentTools = toolsRef.current;
|
|
239
|
+
const toolCallsToResolve = toolCalls.filter((part) => isToolUIPart(part) && !toolsRequiringConfirmation.includes(getToolName(part)) && currentTools?.[getToolName(part)]?.execute);
|
|
175
240
|
if (toolCallsToResolve.length > 0) {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
241
|
+
isResolvingToolsRef.current = true;
|
|
242
|
+
(async () => {
|
|
243
|
+
try {
|
|
244
|
+
const toolResults = [];
|
|
245
|
+
for (const part of toolCallsToResolve) if (isToolUIPart(part)) {
|
|
246
|
+
let toolOutput = null;
|
|
247
|
+
const toolName = getToolName(part);
|
|
248
|
+
const tool$1 = currentTools?.[toolName];
|
|
249
|
+
if (tool$1?.execute && part.input !== void 0) try {
|
|
250
|
+
toolOutput = await tool$1.execute(part.input);
|
|
251
|
+
} catch (error) {
|
|
252
|
+
toolOutput = `Error executing tool: ${error instanceof Error ? error.message : String(error)}`;
|
|
253
|
+
}
|
|
254
|
+
processedToolCalls.current.add(part.toolCallId);
|
|
255
|
+
toolResults.push({
|
|
256
|
+
toolCallId: part.toolCallId,
|
|
257
|
+
toolName,
|
|
258
|
+
output: toolOutput
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
if (toolResults.length > 0) {
|
|
262
|
+
for (const result of toolResults) agentRef.current.send(JSON.stringify({
|
|
263
|
+
type: MessageType.CF_AGENT_TOOL_RESULT,
|
|
264
|
+
toolCallId: result.toolCallId,
|
|
265
|
+
toolName: result.toolName,
|
|
266
|
+
output: result.output,
|
|
267
|
+
autoContinue: autoContinueAfterToolResult
|
|
268
|
+
}));
|
|
269
|
+
await Promise.all(toolResults.map((result) => useChatHelpers.addToolResult({
|
|
270
|
+
tool: result.toolName,
|
|
271
|
+
toolCallId: result.toolCallId,
|
|
272
|
+
output: result.output
|
|
273
|
+
})));
|
|
274
|
+
setClientToolResults((prev) => {
|
|
275
|
+
const newMap = new Map(prev);
|
|
276
|
+
for (const result of toolResults) newMap.set(result.toolCallId, result.output);
|
|
277
|
+
return newMap;
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
} finally {
|
|
281
|
+
isResolvingToolsRef.current = false;
|
|
185
282
|
}
|
|
186
|
-
|
|
187
|
-
toolCallId: part.toolCallId,
|
|
188
|
-
tool: toolName,
|
|
189
|
-
output: toolOutput
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
|
-
if (pendingConfirmationsRef.current.toolCallIds.size === 0) useChatHelpers.sendMessage();
|
|
283
|
+
})();
|
|
193
284
|
}
|
|
194
|
-
}
|
|
285
|
+
}
|
|
195
286
|
}, [
|
|
196
287
|
useChatHelpers.messages,
|
|
197
288
|
experimental_automaticToolResolution,
|
|
198
289
|
useChatHelpers.addToolResult,
|
|
199
|
-
|
|
200
|
-
|
|
290
|
+
toolsRequiringConfirmation,
|
|
291
|
+
autoContinueAfterToolResult
|
|
201
292
|
]);
|
|
293
|
+
/**
|
|
294
|
+
* Contains the request ID, accumulated message parts, and a unique message ID.
|
|
295
|
+
* Used for both resumed streams and real-time broadcasts from other tabs.
|
|
296
|
+
*/
|
|
297
|
+
const activeStreamRef = useRef(null);
|
|
298
|
+
/**
|
|
299
|
+
* Tracks request IDs initiated by this tab via aiFetch.
|
|
300
|
+
* Used to distinguish local requests from broadcasts.
|
|
301
|
+
*/
|
|
302
|
+
const localRequestIdsRef = useRef(/* @__PURE__ */ new Set());
|
|
202
303
|
useEffect(() => {
|
|
203
|
-
|
|
304
|
+
/**
|
|
305
|
+
* Unified message handler that parses JSON once and dispatches based on type.
|
|
306
|
+
* Avoids duplicate parsing overhead from separate listeners.
|
|
307
|
+
*/
|
|
308
|
+
function onAgentMessage(event) {
|
|
204
309
|
if (typeof event.data !== "string") return;
|
|
205
310
|
let data;
|
|
206
311
|
try {
|
|
@@ -208,46 +313,254 @@ function useAgentChat(options) {
|
|
|
208
313
|
} catch (_error) {
|
|
209
314
|
return;
|
|
210
315
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
316
|
+
switch (data.type) {
|
|
317
|
+
case MessageType.CF_AGENT_CHAT_CLEAR:
|
|
318
|
+
useChatHelpers.setMessages([]);
|
|
319
|
+
break;
|
|
320
|
+
case MessageType.CF_AGENT_CHAT_MESSAGES:
|
|
321
|
+
useChatHelpers.setMessages(data.messages);
|
|
322
|
+
break;
|
|
323
|
+
case MessageType.CF_AGENT_MESSAGE_UPDATED:
|
|
324
|
+
useChatHelpers.setMessages((prevMessages) => {
|
|
325
|
+
const updatedMessage = data.message;
|
|
326
|
+
let idx = prevMessages.findIndex((m) => m.id === updatedMessage.id);
|
|
327
|
+
if (idx < 0) {
|
|
328
|
+
const updatedToolCallIds = new Set(updatedMessage.parts.filter((p) => "toolCallId" in p && p.toolCallId).map((p) => p.toolCallId));
|
|
329
|
+
if (updatedToolCallIds.size > 0) idx = prevMessages.findIndex((m) => m.parts.some((p) => "toolCallId" in p && updatedToolCallIds.has(p.toolCallId)));
|
|
330
|
+
}
|
|
331
|
+
if (idx >= 0) {
|
|
332
|
+
const updated = [...prevMessages];
|
|
333
|
+
updated[idx] = {
|
|
334
|
+
...updatedMessage,
|
|
335
|
+
id: prevMessages[idx].id
|
|
336
|
+
};
|
|
337
|
+
return updated;
|
|
338
|
+
}
|
|
339
|
+
return [...prevMessages, updatedMessage];
|
|
340
|
+
});
|
|
341
|
+
break;
|
|
342
|
+
case MessageType.CF_AGENT_STREAM_RESUMING:
|
|
343
|
+
if (!resume) return;
|
|
344
|
+
activeStreamRef.current = null;
|
|
345
|
+
activeStreamRef.current = {
|
|
346
|
+
id: data.id,
|
|
347
|
+
messageId: nanoid(),
|
|
348
|
+
parts: []
|
|
349
|
+
};
|
|
350
|
+
agentRef.current.send(JSON.stringify({
|
|
351
|
+
type: MessageType.CF_AGENT_STREAM_RESUME_ACK,
|
|
352
|
+
id: data.id
|
|
353
|
+
}));
|
|
354
|
+
break;
|
|
355
|
+
case MessageType.CF_AGENT_USE_CHAT_RESPONSE: {
|
|
356
|
+
if (localRequestIdsRef.current.has(data.id)) return;
|
|
357
|
+
const isContinuation = data.continuation === true;
|
|
358
|
+
if (!activeStreamRef.current || activeStreamRef.current.id !== data.id) {
|
|
359
|
+
let messageId = nanoid();
|
|
360
|
+
let existingParts = [];
|
|
361
|
+
if (isContinuation) {
|
|
362
|
+
const currentMessages = messagesRef.current;
|
|
363
|
+
for (let i = currentMessages.length - 1; i >= 0; i--) if (currentMessages[i].role === "assistant") {
|
|
364
|
+
messageId = currentMessages[i].id;
|
|
365
|
+
existingParts = [...currentMessages[i].parts];
|
|
366
|
+
break;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
activeStreamRef.current = {
|
|
370
|
+
id: data.id,
|
|
371
|
+
messageId,
|
|
372
|
+
parts: existingParts
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
const activeMsg = activeStreamRef.current;
|
|
376
|
+
if (data.body?.trim()) try {
|
|
377
|
+
const chunkData = JSON.parse(data.body);
|
|
378
|
+
switch (chunkData.type) {
|
|
379
|
+
case "text-start":
|
|
380
|
+
activeMsg.parts.push({
|
|
381
|
+
type: "text",
|
|
382
|
+
text: "",
|
|
383
|
+
state: "streaming"
|
|
384
|
+
});
|
|
385
|
+
break;
|
|
386
|
+
case "text-delta": {
|
|
387
|
+
const lastTextPart = [...activeMsg.parts].reverse().find((p) => p.type === "text");
|
|
388
|
+
if (lastTextPart && lastTextPart.type === "text") lastTextPart.text += chunkData.delta;
|
|
389
|
+
else activeMsg.parts.push({
|
|
390
|
+
type: "text",
|
|
391
|
+
text: chunkData.delta
|
|
392
|
+
});
|
|
393
|
+
break;
|
|
394
|
+
}
|
|
395
|
+
case "text-end": {
|
|
396
|
+
const lastTextPart = [...activeMsg.parts].reverse().find((p) => p.type === "text");
|
|
397
|
+
if (lastTextPart && "state" in lastTextPart) lastTextPart.state = "done";
|
|
398
|
+
break;
|
|
399
|
+
}
|
|
400
|
+
case "reasoning-start":
|
|
401
|
+
activeMsg.parts.push({
|
|
402
|
+
type: "reasoning",
|
|
403
|
+
text: "",
|
|
404
|
+
state: "streaming"
|
|
405
|
+
});
|
|
406
|
+
break;
|
|
407
|
+
case "reasoning-delta": {
|
|
408
|
+
const lastReasoningPart = [...activeMsg.parts].reverse().find((p) => p.type === "reasoning");
|
|
409
|
+
if (lastReasoningPart && lastReasoningPart.type === "reasoning") lastReasoningPart.text += chunkData.delta;
|
|
410
|
+
break;
|
|
411
|
+
}
|
|
412
|
+
case "reasoning-end": {
|
|
413
|
+
const lastReasoningPart = [...activeMsg.parts].reverse().find((p) => p.type === "reasoning");
|
|
414
|
+
if (lastReasoningPart && "state" in lastReasoningPart) lastReasoningPart.state = "done";
|
|
415
|
+
break;
|
|
416
|
+
}
|
|
417
|
+
case "file":
|
|
418
|
+
activeMsg.parts.push({
|
|
419
|
+
type: "file",
|
|
420
|
+
mediaType: chunkData.mediaType,
|
|
421
|
+
url: chunkData.url
|
|
422
|
+
});
|
|
423
|
+
break;
|
|
424
|
+
case "source-url":
|
|
425
|
+
activeMsg.parts.push({
|
|
426
|
+
type: "source-url",
|
|
427
|
+
sourceId: chunkData.sourceId,
|
|
428
|
+
url: chunkData.url,
|
|
429
|
+
title: chunkData.title
|
|
430
|
+
});
|
|
431
|
+
break;
|
|
432
|
+
case "source-document":
|
|
433
|
+
activeMsg.parts.push({
|
|
434
|
+
type: "source-document",
|
|
435
|
+
sourceId: chunkData.sourceId,
|
|
436
|
+
mediaType: chunkData.mediaType,
|
|
437
|
+
title: chunkData.title,
|
|
438
|
+
filename: chunkData.filename
|
|
439
|
+
});
|
|
440
|
+
break;
|
|
441
|
+
case "tool-input-available":
|
|
442
|
+
activeMsg.parts.push({
|
|
443
|
+
type: `tool-${chunkData.toolName}`,
|
|
444
|
+
toolCallId: chunkData.toolCallId,
|
|
445
|
+
toolName: chunkData.toolName,
|
|
446
|
+
state: "input-available",
|
|
447
|
+
input: chunkData.input
|
|
448
|
+
});
|
|
449
|
+
break;
|
|
450
|
+
case "tool-output-available":
|
|
451
|
+
activeMsg.parts = activeMsg.parts.map((p) => {
|
|
452
|
+
if ("toolCallId" in p && p.toolCallId === chunkData.toolCallId && "state" in p) return {
|
|
453
|
+
...p,
|
|
454
|
+
state: "output-available",
|
|
455
|
+
output: chunkData.output
|
|
456
|
+
};
|
|
457
|
+
return p;
|
|
458
|
+
});
|
|
459
|
+
break;
|
|
460
|
+
case "step-start":
|
|
461
|
+
activeMsg.parts.push({ type: "step-start" });
|
|
462
|
+
break;
|
|
463
|
+
}
|
|
464
|
+
useChatHelpers.setMessages((prevMessages) => {
|
|
465
|
+
if (!activeMsg) return prevMessages;
|
|
466
|
+
const existingIdx = prevMessages.findIndex((m) => m.id === activeMsg.messageId);
|
|
467
|
+
const partialMessage = {
|
|
468
|
+
id: activeMsg.messageId,
|
|
469
|
+
role: "assistant",
|
|
470
|
+
parts: [...activeMsg.parts]
|
|
471
|
+
};
|
|
472
|
+
if (existingIdx >= 0) {
|
|
473
|
+
const updated = [...prevMessages];
|
|
474
|
+
updated[existingIdx] = partialMessage;
|
|
475
|
+
return updated;
|
|
476
|
+
}
|
|
477
|
+
return [...prevMessages, partialMessage];
|
|
478
|
+
});
|
|
479
|
+
} catch (parseError) {
|
|
480
|
+
console.warn("[useAgentChat] Failed to parse stream chunk:", parseError instanceof Error ? parseError.message : parseError, "body:", data.body?.slice(0, 100));
|
|
481
|
+
}
|
|
482
|
+
if (data.done || data.error) activeStreamRef.current = null;
|
|
483
|
+
break;
|
|
484
|
+
}
|
|
220
485
|
}
|
|
221
|
-
if (data.type === MessageType.CF_AGENT_CHAT_MESSAGES) useChatHelpers.setMessages(data.messages);
|
|
222
486
|
}
|
|
223
|
-
agent.addEventListener("message",
|
|
224
|
-
agent.addEventListener("message", onMessages);
|
|
487
|
+
agent.addEventListener("message", onAgentMessage);
|
|
225
488
|
return () => {
|
|
226
|
-
agent.removeEventListener("message",
|
|
227
|
-
|
|
489
|
+
agent.removeEventListener("message", onAgentMessage);
|
|
490
|
+
activeStreamRef.current = null;
|
|
228
491
|
};
|
|
229
|
-
}, [
|
|
492
|
+
}, [
|
|
493
|
+
agent,
|
|
494
|
+
useChatHelpers.setMessages,
|
|
495
|
+
resume
|
|
496
|
+
]);
|
|
230
497
|
const addToolResultAndSendMessage = async (args) => {
|
|
231
498
|
const { toolCallId } = args;
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
499
|
+
const toolName = "tool" in args ? args.tool : "";
|
|
500
|
+
const output = "output" in args ? args.output : void 0;
|
|
501
|
+
agentRef.current.send(JSON.stringify({
|
|
502
|
+
type: MessageType.CF_AGENT_TOOL_RESULT,
|
|
503
|
+
toolCallId,
|
|
504
|
+
toolName,
|
|
505
|
+
output,
|
|
506
|
+
autoContinue: autoContinueAfterToolResult
|
|
507
|
+
}));
|
|
508
|
+
setClientToolResults((prev) => new Map(prev).set(toolCallId, output));
|
|
509
|
+
useChatHelpers.addToolResult(args);
|
|
510
|
+
if (!autoContinueAfterToolResult) {
|
|
511
|
+
if (!autoSendAfterAllConfirmationsResolved) {
|
|
512
|
+
useChatHelpers.sendMessage();
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
const pending = pendingConfirmationsRef.current?.toolCallIds;
|
|
516
|
+
if (!pending) {
|
|
517
|
+
useChatHelpers.sendMessage();
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
520
|
+
const wasLast = pending.size === 1 && pending.has(toolCallId);
|
|
521
|
+
if (pending.has(toolCallId)) pending.delete(toolCallId);
|
|
522
|
+
if (wasLast || pending.size === 0) useChatHelpers.sendMessage();
|
|
241
523
|
}
|
|
242
|
-
const wasLast = pending.size === 1 && pending.has(toolCallId);
|
|
243
|
-
if (pending.has(toolCallId)) pending.delete(toolCallId);
|
|
244
|
-
if (wasLast || pending.size === 0) useChatHelpers.sendMessage();
|
|
245
524
|
};
|
|
525
|
+
const messagesWithToolResults = useMemo(() => {
|
|
526
|
+
if (clientToolResults.size === 0) return useChatHelpers.messages;
|
|
527
|
+
return useChatHelpers.messages.map((msg) => ({
|
|
528
|
+
...msg,
|
|
529
|
+
parts: msg.parts.map((p) => {
|
|
530
|
+
if (!("toolCallId" in p) || !("state" in p) || p.state !== "input-available" || !clientToolResults.has(p.toolCallId)) return p;
|
|
531
|
+
return {
|
|
532
|
+
...p,
|
|
533
|
+
state: "output-available",
|
|
534
|
+
output: clientToolResults.get(p.toolCallId)
|
|
535
|
+
};
|
|
536
|
+
})
|
|
537
|
+
}));
|
|
538
|
+
}, [useChatHelpers.messages, clientToolResults]);
|
|
539
|
+
useEffect(() => {
|
|
540
|
+
const currentToolCallIds = /* @__PURE__ */ new Set();
|
|
541
|
+
for (const msg of useChatHelpers.messages) for (const part of msg.parts) if ("toolCallId" in part && part.toolCallId) currentToolCallIds.add(part.toolCallId);
|
|
542
|
+
setClientToolResults((prev) => {
|
|
543
|
+
if (prev.size === 0) return prev;
|
|
544
|
+
let hasStaleEntries = false;
|
|
545
|
+
for (const toolCallId of prev.keys()) if (!currentToolCallIds.has(toolCallId)) {
|
|
546
|
+
hasStaleEntries = true;
|
|
547
|
+
break;
|
|
548
|
+
}
|
|
549
|
+
if (!hasStaleEntries) return prev;
|
|
550
|
+
const newMap = /* @__PURE__ */ new Map();
|
|
551
|
+
for (const [id, output] of prev) if (currentToolCallIds.has(id)) newMap.set(id, output);
|
|
552
|
+
return newMap;
|
|
553
|
+
});
|
|
554
|
+
for (const toolCallId of processedToolCalls.current) if (!currentToolCallIds.has(toolCallId)) processedToolCalls.current.delete(toolCallId);
|
|
555
|
+
}, [useChatHelpers.messages]);
|
|
246
556
|
return {
|
|
247
557
|
...useChatHelpers,
|
|
558
|
+
messages: messagesWithToolResults,
|
|
248
559
|
addToolResult: addToolResultAndSendMessage,
|
|
249
560
|
clearHistory: () => {
|
|
250
561
|
useChatHelpers.setMessages([]);
|
|
562
|
+
setClientToolResults(/* @__PURE__ */ new Map());
|
|
563
|
+
processedToolCalls.current.clear();
|
|
251
564
|
agent.send(JSON.stringify({ type: MessageType.CF_AGENT_CHAT_CLEAR }));
|
|
252
565
|
},
|
|
253
566
|
setMessages: (messages) => {
|
|
@@ -261,5 +574,5 @@ function useAgentChat(options) {
|
|
|
261
574
|
}
|
|
262
575
|
|
|
263
576
|
//#endregion
|
|
264
|
-
export { detectToolsRequiringConfirmation, useAgentChat };
|
|
577
|
+
export { detectToolsRequiringConfirmation, extractClientToolSchemas, useAgentChat };
|
|
265
578
|
//# sourceMappingURL=ai-react.js.map
|