agents 0.0.0-293b546 → 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 +158 -24
- package/dist/ai-chat-agent.js +380 -60
- 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 -16
- package/dist/ai-react.js +252 -74
- package/dist/ai-react.js.map +1 -1
- package/dist/{ai-types-81H_-Uxh.d.ts → ai-types-0OnT3FHg.d.ts} +26 -2
- package/dist/{ai-types-CrMqkwc_.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/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-BAQA84dr.d.ts → client-CdM5I962.d.ts} +2 -2
- package/dist/client-DFotUKH_.d.ts +834 -0
- package/dist/{client-B3SR12TQ.js → client-DjTPRM8-.js} +2 -2
- package/dist/{client-B3SR12TQ.js.map → client-DjTPRM8-.js.map} +1 -1
- package/dist/{client-C8VrzljV.js → client-QZa2Rq0l.js} +371 -187
- 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-C2CHH5x-.d.ts → do-oauth-client-provider--To1Tsjj.d.ts} +20 -5
- package/dist/{do-oauth-client-provider-CwqK5SXm.js → do-oauth-client-provider-B1fVIshX.js} +69 -8
- package/dist/do-oauth-client-provider-B1fVIshX.js.map +1 -0
- package/dist/{index-7kI1zprE.d.ts → index-CT2tCrLr.d.ts} +59 -60
- package/dist/{index-BUle9RiP.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 -2
- 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 +19 -12
- package/dist/mcp/index.js +55 -60
- package/dist/mcp/index.js.map +1 -1
- package/dist/{mcp-BwPscEiF.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 +56 -56
- package/dist/react.js.map +1 -1
- package/dist/schedule.d.ts +18 -72
- package/dist/{serializable-faDkMCai.d.ts → serializable-Crsj26mx.d.ts} +1 -1
- package/dist/serializable.d.ts +1 -1
- package/dist/{src-xjQt2wBU.js → src-BZDh910Z.js} +26 -25
- package/dist/src-BZDh910Z.js.map +1 -0
- package/package.json +29 -14
- package/dist/ai-chat-v5-migration-BSiGZmYU.js +0 -155
- package/dist/ai-chat-v5-migration-BSiGZmYU.js.map +0 -1
- package/dist/ai-types-CrMqkwc_.js.map +0 -1
- package/dist/cli.d.ts +0 -8
- package/dist/cli.js.map +0 -1
- package/dist/client-BG2wUgN5.d.ts +0 -1462
- package/dist/client-C8VrzljV.js.map +0 -1
- package/dist/do-oauth-client-provider-CwqK5SXm.js.map +0 -1
- package/dist/react-9nVfoERh.d.ts +0 -113
- package/dist/src-xjQt2wBU.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, resume = true, ...rest } = options;
|
|
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,6 +96,7 @@ 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,
|
|
@@ -87,6 +106,7 @@ function useAgentChat(options) {
|
|
|
87
106
|
try {
|
|
88
107
|
controller.close();
|
|
89
108
|
} catch {}
|
|
109
|
+
localRequestIdsRef.current.delete(id);
|
|
90
110
|
});
|
|
91
111
|
currentAgent.addEventListener("message", (event) => {
|
|
92
112
|
let data;
|
|
@@ -99,6 +119,7 @@ function useAgentChat(options) {
|
|
|
99
119
|
if (data.id === id) if (data.error) {
|
|
100
120
|
controller.error(new Error(data.body));
|
|
101
121
|
abortController.abort();
|
|
122
|
+
localRequestIdsRef.current.delete(id);
|
|
102
123
|
} else {
|
|
103
124
|
if (data.body?.trim()) controller.enqueue(new TextEncoder().encode(`data: ${data.body}\n\n`));
|
|
104
125
|
if (data.done) {
|
|
@@ -106,6 +127,7 @@ function useAgentChat(options) {
|
|
|
106
127
|
controller.close();
|
|
107
128
|
} catch {}
|
|
108
129
|
abortController.abort();
|
|
130
|
+
localRequestIdsRef.current.delete(id);
|
|
109
131
|
}
|
|
110
132
|
}
|
|
111
133
|
}
|
|
@@ -138,12 +160,45 @@ function useAgentChat(options) {
|
|
|
138
160
|
}));
|
|
139
161
|
return new Response(stream);
|
|
140
162
|
}, []);
|
|
163
|
+
const toolsRef = useRef(tools);
|
|
164
|
+
toolsRef.current = tools;
|
|
165
|
+
const prepareSendMessagesRequestRef = useRef(prepareSendMessagesRequest);
|
|
166
|
+
prepareSendMessagesRequestRef.current = prepareSendMessagesRequest;
|
|
141
167
|
const customTransport = useMemo(() => ({
|
|
142
|
-
sendMessages: async (
|
|
168
|
+
sendMessages: async (sendMessageOptions) => {
|
|
169
|
+
const clientToolSchemas = extractClientToolSchemas(toolsRef.current);
|
|
143
170
|
return new DefaultChatTransport({
|
|
144
171
|
api: agentUrlString,
|
|
145
|
-
fetch: aiFetch
|
|
146
|
-
|
|
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);
|
|
147
202
|
},
|
|
148
203
|
reconnectToStream: async () => null
|
|
149
204
|
}), [agentUrlString, aiFetch]);
|
|
@@ -154,6 +209,10 @@ function useAgentChat(options) {
|
|
|
154
209
|
id: agent._pk
|
|
155
210
|
});
|
|
156
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;
|
|
157
216
|
const lastMessage = useChatHelpers.messages[useChatHelpers.messages.length - 1];
|
|
158
217
|
const pendingConfirmations = (() => {
|
|
159
218
|
if (!lastMessage || lastMessage.role !== "assistant") return {
|
|
@@ -171,42 +230,76 @@ function useAgentChat(options) {
|
|
|
171
230
|
pendingConfirmationsRef.current = pendingConfirmations;
|
|
172
231
|
useEffect(() => {
|
|
173
232
|
if (!experimental_automaticToolResolution) return;
|
|
233
|
+
if (isResolvingToolsRef.current) return;
|
|
174
234
|
const lastMessage$1 = useChatHelpers.messages[useChatHelpers.messages.length - 1];
|
|
175
235
|
if (!lastMessage$1 || lastMessage$1.role !== "assistant") return;
|
|
176
236
|
const toolCalls = lastMessage$1.parts.filter((part) => isToolUIPart(part) && part.state === "input-available" && !processedToolCalls.current.has(part.toolCallId));
|
|
177
|
-
if (toolCalls.length > 0)
|
|
178
|
-
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);
|
|
179
240
|
if (toolCallsToResolve.length > 0) {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
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;
|
|
189
282
|
}
|
|
190
|
-
|
|
191
|
-
toolCallId: part.toolCallId,
|
|
192
|
-
tool: toolName,
|
|
193
|
-
output: toolOutput
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
if (pendingConfirmationsRef.current.toolCallIds.size === 0) useChatHelpers.sendMessage();
|
|
283
|
+
})();
|
|
197
284
|
}
|
|
198
|
-
}
|
|
285
|
+
}
|
|
199
286
|
}, [
|
|
200
287
|
useChatHelpers.messages,
|
|
201
288
|
experimental_automaticToolResolution,
|
|
202
289
|
useChatHelpers.addToolResult,
|
|
203
|
-
|
|
204
|
-
|
|
290
|
+
toolsRequiringConfirmation,
|
|
291
|
+
autoContinueAfterToolResult
|
|
205
292
|
]);
|
|
206
293
|
/**
|
|
207
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.
|
|
208
296
|
*/
|
|
209
|
-
const
|
|
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());
|
|
210
303
|
useEffect(() => {
|
|
211
304
|
/**
|
|
212
305
|
* Unified message handler that parses JSON once and dispatches based on type.
|
|
@@ -227,10 +320,29 @@ function useAgentChat(options) {
|
|
|
227
320
|
case MessageType.CF_AGENT_CHAT_MESSAGES:
|
|
228
321
|
useChatHelpers.setMessages(data.messages);
|
|
229
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;
|
|
230
342
|
case MessageType.CF_AGENT_STREAM_RESUMING:
|
|
231
343
|
if (!resume) return;
|
|
232
|
-
|
|
233
|
-
|
|
344
|
+
activeStreamRef.current = null;
|
|
345
|
+
activeStreamRef.current = {
|
|
234
346
|
id: data.id,
|
|
235
347
|
messageId: nanoid(),
|
|
236
348
|
parts: []
|
|
@@ -240,60 +352,77 @@ function useAgentChat(options) {
|
|
|
240
352
|
id: data.id
|
|
241
353
|
}));
|
|
242
354
|
break;
|
|
243
|
-
case MessageType.CF_AGENT_USE_CHAT_RESPONSE:
|
|
244
|
-
if (
|
|
245
|
-
|
|
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;
|
|
246
376
|
if (data.body?.trim()) try {
|
|
247
377
|
const chunkData = JSON.parse(data.body);
|
|
248
|
-
const resumedMsg = resumedStreamRef.current;
|
|
249
378
|
switch (chunkData.type) {
|
|
250
379
|
case "text-start":
|
|
251
|
-
|
|
380
|
+
activeMsg.parts.push({
|
|
252
381
|
type: "text",
|
|
253
382
|
text: "",
|
|
254
383
|
state: "streaming"
|
|
255
384
|
});
|
|
256
385
|
break;
|
|
257
386
|
case "text-delta": {
|
|
258
|
-
const lastTextPart = [...
|
|
387
|
+
const lastTextPart = [...activeMsg.parts].reverse().find((p) => p.type === "text");
|
|
259
388
|
if (lastTextPart && lastTextPart.type === "text") lastTextPart.text += chunkData.delta;
|
|
260
|
-
else
|
|
389
|
+
else activeMsg.parts.push({
|
|
261
390
|
type: "text",
|
|
262
391
|
text: chunkData.delta
|
|
263
392
|
});
|
|
264
393
|
break;
|
|
265
394
|
}
|
|
266
395
|
case "text-end": {
|
|
267
|
-
const lastTextPart = [...
|
|
396
|
+
const lastTextPart = [...activeMsg.parts].reverse().find((p) => p.type === "text");
|
|
268
397
|
if (lastTextPart && "state" in lastTextPart) lastTextPart.state = "done";
|
|
269
398
|
break;
|
|
270
399
|
}
|
|
271
400
|
case "reasoning-start":
|
|
272
|
-
|
|
401
|
+
activeMsg.parts.push({
|
|
273
402
|
type: "reasoning",
|
|
274
403
|
text: "",
|
|
275
404
|
state: "streaming"
|
|
276
405
|
});
|
|
277
406
|
break;
|
|
278
407
|
case "reasoning-delta": {
|
|
279
|
-
const lastReasoningPart = [...
|
|
408
|
+
const lastReasoningPart = [...activeMsg.parts].reverse().find((p) => p.type === "reasoning");
|
|
280
409
|
if (lastReasoningPart && lastReasoningPart.type === "reasoning") lastReasoningPart.text += chunkData.delta;
|
|
281
410
|
break;
|
|
282
411
|
}
|
|
283
412
|
case "reasoning-end": {
|
|
284
|
-
const lastReasoningPart = [...
|
|
413
|
+
const lastReasoningPart = [...activeMsg.parts].reverse().find((p) => p.type === "reasoning");
|
|
285
414
|
if (lastReasoningPart && "state" in lastReasoningPart) lastReasoningPart.state = "done";
|
|
286
415
|
break;
|
|
287
416
|
}
|
|
288
417
|
case "file":
|
|
289
|
-
|
|
418
|
+
activeMsg.parts.push({
|
|
290
419
|
type: "file",
|
|
291
420
|
mediaType: chunkData.mediaType,
|
|
292
421
|
url: chunkData.url
|
|
293
422
|
});
|
|
294
423
|
break;
|
|
295
424
|
case "source-url":
|
|
296
|
-
|
|
425
|
+
activeMsg.parts.push({
|
|
297
426
|
type: "source-url",
|
|
298
427
|
sourceId: chunkData.sourceId,
|
|
299
428
|
url: chunkData.url,
|
|
@@ -301,7 +430,7 @@ function useAgentChat(options) {
|
|
|
301
430
|
});
|
|
302
431
|
break;
|
|
303
432
|
case "source-document":
|
|
304
|
-
|
|
433
|
+
activeMsg.parts.push({
|
|
305
434
|
type: "source-document",
|
|
306
435
|
sourceId: chunkData.sourceId,
|
|
307
436
|
mediaType: chunkData.mediaType,
|
|
@@ -310,7 +439,7 @@ function useAgentChat(options) {
|
|
|
310
439
|
});
|
|
311
440
|
break;
|
|
312
441
|
case "tool-input-available":
|
|
313
|
-
|
|
442
|
+
activeMsg.parts.push({
|
|
314
443
|
type: `tool-${chunkData.toolName}`,
|
|
315
444
|
toolCallId: chunkData.toolCallId,
|
|
316
445
|
toolName: chunkData.toolName,
|
|
@@ -318,25 +447,27 @@ function useAgentChat(options) {
|
|
|
318
447
|
input: chunkData.input
|
|
319
448
|
});
|
|
320
449
|
break;
|
|
321
|
-
case "tool-output-available":
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
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
|
+
});
|
|
327
459
|
break;
|
|
328
|
-
}
|
|
329
460
|
case "step-start":
|
|
330
|
-
|
|
461
|
+
activeMsg.parts.push({ type: "step-start" });
|
|
331
462
|
break;
|
|
332
463
|
}
|
|
333
464
|
useChatHelpers.setMessages((prevMessages) => {
|
|
334
|
-
if (!
|
|
335
|
-
const existingIdx = prevMessages.findIndex((m) => m.id ===
|
|
465
|
+
if (!activeMsg) return prevMessages;
|
|
466
|
+
const existingIdx = prevMessages.findIndex((m) => m.id === activeMsg.messageId);
|
|
336
467
|
const partialMessage = {
|
|
337
|
-
id:
|
|
468
|
+
id: activeMsg.messageId,
|
|
338
469
|
role: "assistant",
|
|
339
|
-
parts: [...
|
|
470
|
+
parts: [...activeMsg.parts]
|
|
340
471
|
};
|
|
341
472
|
if (existingIdx >= 0) {
|
|
342
473
|
const updated = [...prevMessages];
|
|
@@ -346,16 +477,17 @@ function useAgentChat(options) {
|
|
|
346
477
|
return [...prevMessages, partialMessage];
|
|
347
478
|
});
|
|
348
479
|
} catch (parseError) {
|
|
349
|
-
console.warn("[useAgentChat] Failed to parse
|
|
480
|
+
console.warn("[useAgentChat] Failed to parse stream chunk:", parseError instanceof Error ? parseError.message : parseError, "body:", data.body?.slice(0, 100));
|
|
350
481
|
}
|
|
351
|
-
if (data.done || data.error)
|
|
482
|
+
if (data.done || data.error) activeStreamRef.current = null;
|
|
352
483
|
break;
|
|
484
|
+
}
|
|
353
485
|
}
|
|
354
486
|
}
|
|
355
487
|
agent.addEventListener("message", onAgentMessage);
|
|
356
488
|
return () => {
|
|
357
489
|
agent.removeEventListener("message", onAgentMessage);
|
|
358
|
-
|
|
490
|
+
activeStreamRef.current = null;
|
|
359
491
|
};
|
|
360
492
|
}, [
|
|
361
493
|
agent,
|
|
@@ -364,25 +496,71 @@ function useAgentChat(options) {
|
|
|
364
496
|
]);
|
|
365
497
|
const addToolResultAndSendMessage = async (args) => {
|
|
366
498
|
const { toolCallId } = args;
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
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();
|
|
376
523
|
}
|
|
377
|
-
const wasLast = pending.size === 1 && pending.has(toolCallId);
|
|
378
|
-
if (pending.has(toolCallId)) pending.delete(toolCallId);
|
|
379
|
-
if (wasLast || pending.size === 0) useChatHelpers.sendMessage();
|
|
380
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]);
|
|
381
556
|
return {
|
|
382
557
|
...useChatHelpers,
|
|
558
|
+
messages: messagesWithToolResults,
|
|
383
559
|
addToolResult: addToolResultAndSendMessage,
|
|
384
560
|
clearHistory: () => {
|
|
385
561
|
useChatHelpers.setMessages([]);
|
|
562
|
+
setClientToolResults(/* @__PURE__ */ new Map());
|
|
563
|
+
processedToolCalls.current.clear();
|
|
386
564
|
agent.send(JSON.stringify({ type: MessageType.CF_AGENT_CHAT_CLEAR }));
|
|
387
565
|
},
|
|
388
566
|
setMessages: (messages) => {
|
|
@@ -396,5 +574,5 @@ function useAgentChat(options) {
|
|
|
396
574
|
}
|
|
397
575
|
|
|
398
576
|
//#endregion
|
|
399
|
-
export { detectToolsRequiringConfirmation, useAgentChat };
|
|
577
|
+
export { detectToolsRequiringConfirmation, extractClientToolSchemas, useAgentChat };
|
|
400
578
|
//# sourceMappingURL=ai-react.js.map
|