agents 0.2.23 → 0.2.25
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 +5 -3
- package/dist/ai-chat-agent.d.ts +86 -13
- package/dist/ai-chat-agent.js +340 -74
- package/dist/ai-chat-agent.js.map +1 -1
- package/dist/{ai-chat-v5-migration-DBHGW4Hv.js → ai-chat-v5-migration-BSiGZmYU.js} +1 -1
- package/dist/{ai-chat-v5-migration-DBHGW4Hv.js.map → ai-chat-v5-migration-BSiGZmYU.js.map} +1 -1
- package/dist/ai-chat-v5-migration.js +1 -1
- package/dist/ai-react.d.ts +14 -9
- package/dist/ai-react.js +179 -29
- package/dist/ai-react.js.map +1 -1
- package/dist/{ai-types-D5YoPrBZ.d.ts → ai-types-81H_-Uxh.d.ts} +15 -7
- package/dist/{ai-types-B3aQaFv3.js → ai-types-CrMqkwc_.js} +5 -1
- package/dist/ai-types-CrMqkwc_.js.map +1 -0
- package/dist/ai-types.d.ts +1 -1
- package/dist/ai-types.js +1 -1
- package/dist/{client-BfiZ3HQd.js → client-B3SR12TQ.js} +2 -2
- package/dist/{client-BfiZ3HQd.js.map → client-B3SR12TQ.js.map} +1 -1
- package/dist/{client-CbWe9FBd.d.ts → client-BAQA84dr.d.ts} +2 -2
- package/dist/client-BZq9qau2.js +1093 -0
- package/dist/client-BZq9qau2.js.map +1 -0
- package/dist/client-CsaP9Irq.d.ts +1528 -0
- package/dist/client.d.ts +2 -2
- package/dist/client.js +2 -2
- package/dist/codemode/ai.js +5 -5
- package/dist/{do-oauth-client-provider-DGc5pP0l.d.ts → do-oauth-client-provider-C2CHH5x-.d.ts} +1 -1
- package/dist/{do-oauth-client-provider-CswoD5Lu.js → do-oauth-client-provider-CwqK5SXm.js} +2 -1
- package/dist/do-oauth-client-provider-CwqK5SXm.js.map +1 -0
- package/dist/{index-DhJCaDWd.d.ts → index-BUle9RiP.d.ts} +2 -2
- package/dist/{index-DEZFuVoU.d.ts → index-Bx5KK3VJ.d.ts} +44 -23
- package/dist/index.d.ts +6 -6
- package/dist/index.js +5 -5
- package/dist/mcp/client.d.ts +4 -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 +11 -11
- package/dist/mcp/index.js +21 -14
- 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-BwPscEiF.d.ts} +1 -1
- package/dist/observability/index.d.ts +2 -2
- package/dist/observability/index.js +5 -5
- package/dist/{react-CrV9uP64.d.ts → react-CbwD4fBf.d.ts} +4 -4
- package/dist/react.d.ts +9 -9
- package/dist/react.js +2 -2
- package/dist/react.js.map +1 -1
- package/dist/{serializable-CymX8ovI.d.ts → serializable-faDkMCai.d.ts} +1 -1
- package/dist/serializable.d.ts +1 -1
- package/dist/{src-C8K3lu37.js → src-D_KKH_4c.js} +99 -146
- package/dist/src-D_KKH_4c.js.map +1 -0
- package/package.json +7 -7
- package/dist/ai-types-B3aQaFv3.js.map +0 -1
- package/dist/client-DZhjV_XA.js +0 -719
- package/dist/client-DZhjV_XA.js.map +0 -1
- package/dist/client-GfgZTqrS.d.ts +0 -5283
- package/dist/do-oauth-client-provider-CswoD5Lu.js.map +0 -1
- package/dist/src-C8K3lu37.js.map +0 -1
package/dist/ai-react.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as MessageType } from "./ai-types-
|
|
1
|
+
import { t as MessageType } from "./ai-types-CrMqkwc_.js";
|
|
2
2
|
import { nanoid } from "nanoid";
|
|
3
3
|
import { useChat } from "@ai-sdk/react";
|
|
4
4
|
import { DefaultChatTransport, getToolName, isToolUIPart } from "ai";
|
|
@@ -22,7 +22,7 @@ function detectToolsRequiringConfirmation(tools) {
|
|
|
22
22
|
return Object.entries(tools).filter(([_name, tool$1]) => !tool$1.execute).map(([name]) => name);
|
|
23
23
|
}
|
|
24
24
|
function useAgentChat(options) {
|
|
25
|
-
const { agent, getInitialMessages, messages: optionsInitialMessages, experimental_automaticToolResolution, tools, toolsRequiringConfirmation: manualToolsRequiringConfirmation, autoSendAfterAllConfirmationsResolved = true
|
|
25
|
+
const { agent, getInitialMessages, messages: optionsInitialMessages, experimental_automaticToolResolution, tools, toolsRequiringConfirmation: manualToolsRequiringConfirmation, autoSendAfterAllConfirmationsResolved = true, resume = true, ...rest } = options;
|
|
26
26
|
const toolsRequiringConfirmation = manualToolsRequiringConfirmation ?? detectToolsRequiringConfirmation(tools);
|
|
27
27
|
const agentUrl = new URL(`${(agent._url || agent._pkurl)?.replace("ws://", "http://").replace("wss://", "https://")}`);
|
|
28
28
|
agentUrl.searchParams.delete("_pk");
|
|
@@ -78,13 +78,17 @@ function useAgentChat(options) {
|
|
|
78
78
|
const abortController = new AbortController();
|
|
79
79
|
let controller;
|
|
80
80
|
const currentAgent = agentRef.current;
|
|
81
|
+
localRequestIdsRef.current.add(id);
|
|
81
82
|
signal?.addEventListener("abort", () => {
|
|
82
83
|
currentAgent.send(JSON.stringify({
|
|
83
84
|
id,
|
|
84
85
|
type: MessageType.CF_AGENT_CHAT_REQUEST_CANCEL
|
|
85
86
|
}));
|
|
86
87
|
abortController.abort();
|
|
87
|
-
|
|
88
|
+
try {
|
|
89
|
+
controller.close();
|
|
90
|
+
} catch {}
|
|
91
|
+
localRequestIdsRef.current.delete(id);
|
|
88
92
|
});
|
|
89
93
|
currentAgent.addEventListener("message", (event) => {
|
|
90
94
|
let data;
|
|
@@ -97,18 +101,27 @@ function useAgentChat(options) {
|
|
|
97
101
|
if (data.id === id) if (data.error) {
|
|
98
102
|
controller.error(new Error(data.body));
|
|
99
103
|
abortController.abort();
|
|
104
|
+
localRequestIdsRef.current.delete(id);
|
|
100
105
|
} else {
|
|
101
106
|
if (data.body?.trim()) controller.enqueue(new TextEncoder().encode(`data: ${data.body}\n\n`));
|
|
102
107
|
if (data.done) {
|
|
103
|
-
|
|
108
|
+
try {
|
|
109
|
+
controller.close();
|
|
110
|
+
} catch {}
|
|
104
111
|
abortController.abort();
|
|
112
|
+
localRequestIdsRef.current.delete(id);
|
|
105
113
|
}
|
|
106
114
|
}
|
|
107
115
|
}
|
|
108
116
|
}, { signal: abortController.signal });
|
|
109
|
-
const stream = new ReadableStream({
|
|
110
|
-
|
|
111
|
-
|
|
117
|
+
const stream = new ReadableStream({
|
|
118
|
+
start(c) {
|
|
119
|
+
controller = c;
|
|
120
|
+
},
|
|
121
|
+
cancel(reason) {
|
|
122
|
+
console.warn("[agents/ai-react] cancelling stream", id, reason || "no reason");
|
|
123
|
+
}
|
|
124
|
+
});
|
|
112
125
|
currentAgent.send(JSON.stringify({
|
|
113
126
|
id,
|
|
114
127
|
init: {
|
|
@@ -136,12 +149,7 @@ function useAgentChat(options) {
|
|
|
136
149
|
fetch: aiFetch
|
|
137
150
|
}).sendMessages(options$1);
|
|
138
151
|
},
|
|
139
|
-
reconnectToStream: async (
|
|
140
|
-
return new DefaultChatTransport({
|
|
141
|
-
api: agentUrlString,
|
|
142
|
-
fetch: aiFetch
|
|
143
|
-
}).reconnectToStream(options$1);
|
|
144
|
-
}
|
|
152
|
+
reconnectToStream: async () => null
|
|
145
153
|
}), [agentUrlString, aiFetch]);
|
|
146
154
|
const useChatHelpers = useChat({
|
|
147
155
|
...rest,
|
|
@@ -199,8 +207,22 @@ function useAgentChat(options) {
|
|
|
199
207
|
useChatHelpers.sendMessage,
|
|
200
208
|
toolsRequiringConfirmation
|
|
201
209
|
]);
|
|
210
|
+
/**
|
|
211
|
+
* Contains the request ID, accumulated message parts, and a unique message ID.
|
|
212
|
+
* Used for both resumed streams and real-time broadcasts from other tabs.
|
|
213
|
+
*/
|
|
214
|
+
const activeStreamRef = useRef(null);
|
|
215
|
+
/**
|
|
216
|
+
* Tracks request IDs initiated by this tab via aiFetch.
|
|
217
|
+
* Used to distinguish local requests from broadcasts.
|
|
218
|
+
*/
|
|
219
|
+
const localRequestIdsRef = useRef(/* @__PURE__ */ new Set());
|
|
202
220
|
useEffect(() => {
|
|
203
|
-
|
|
221
|
+
/**
|
|
222
|
+
* Unified message handler that parses JSON once and dispatches based on type.
|
|
223
|
+
* Avoids duplicate parsing overhead from separate listeners.
|
|
224
|
+
*/
|
|
225
|
+
function onAgentMessage(event) {
|
|
204
226
|
if (typeof event.data !== "string") return;
|
|
205
227
|
let data;
|
|
206
228
|
try {
|
|
@@ -208,25 +230,153 @@ function useAgentChat(options) {
|
|
|
208
230
|
} catch (_error) {
|
|
209
231
|
return;
|
|
210
232
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
233
|
+
switch (data.type) {
|
|
234
|
+
case MessageType.CF_AGENT_CHAT_CLEAR:
|
|
235
|
+
useChatHelpers.setMessages([]);
|
|
236
|
+
break;
|
|
237
|
+
case MessageType.CF_AGENT_CHAT_MESSAGES:
|
|
238
|
+
useChatHelpers.setMessages(data.messages);
|
|
239
|
+
break;
|
|
240
|
+
case MessageType.CF_AGENT_STREAM_RESUMING:
|
|
241
|
+
if (!resume) return;
|
|
242
|
+
activeStreamRef.current = null;
|
|
243
|
+
activeStreamRef.current = {
|
|
244
|
+
id: data.id,
|
|
245
|
+
messageId: nanoid(),
|
|
246
|
+
parts: []
|
|
247
|
+
};
|
|
248
|
+
agentRef.current.send(JSON.stringify({
|
|
249
|
+
type: MessageType.CF_AGENT_STREAM_RESUME_ACK,
|
|
250
|
+
id: data.id
|
|
251
|
+
}));
|
|
252
|
+
break;
|
|
253
|
+
case MessageType.CF_AGENT_USE_CHAT_RESPONSE: {
|
|
254
|
+
if (localRequestIdsRef.current.has(data.id)) return;
|
|
255
|
+
if (!activeStreamRef.current || activeStreamRef.current.id !== data.id) activeStreamRef.current = {
|
|
256
|
+
id: data.id,
|
|
257
|
+
messageId: nanoid(),
|
|
258
|
+
parts: []
|
|
259
|
+
};
|
|
260
|
+
const activeMsg = activeStreamRef.current;
|
|
261
|
+
if (data.body?.trim()) try {
|
|
262
|
+
const chunkData = JSON.parse(data.body);
|
|
263
|
+
switch (chunkData.type) {
|
|
264
|
+
case "text-start":
|
|
265
|
+
activeMsg.parts.push({
|
|
266
|
+
type: "text",
|
|
267
|
+
text: "",
|
|
268
|
+
state: "streaming"
|
|
269
|
+
});
|
|
270
|
+
break;
|
|
271
|
+
case "text-delta": {
|
|
272
|
+
const lastTextPart = [...activeMsg.parts].reverse().find((p) => p.type === "text");
|
|
273
|
+
if (lastTextPart && lastTextPart.type === "text") lastTextPart.text += chunkData.delta;
|
|
274
|
+
else activeMsg.parts.push({
|
|
275
|
+
type: "text",
|
|
276
|
+
text: chunkData.delta
|
|
277
|
+
});
|
|
278
|
+
break;
|
|
279
|
+
}
|
|
280
|
+
case "text-end": {
|
|
281
|
+
const lastTextPart = [...activeMsg.parts].reverse().find((p) => p.type === "text");
|
|
282
|
+
if (lastTextPart && "state" in lastTextPart) lastTextPart.state = "done";
|
|
283
|
+
break;
|
|
284
|
+
}
|
|
285
|
+
case "reasoning-start":
|
|
286
|
+
activeMsg.parts.push({
|
|
287
|
+
type: "reasoning",
|
|
288
|
+
text: "",
|
|
289
|
+
state: "streaming"
|
|
290
|
+
});
|
|
291
|
+
break;
|
|
292
|
+
case "reasoning-delta": {
|
|
293
|
+
const lastReasoningPart = [...activeMsg.parts].reverse().find((p) => p.type === "reasoning");
|
|
294
|
+
if (lastReasoningPart && lastReasoningPart.type === "reasoning") lastReasoningPart.text += chunkData.delta;
|
|
295
|
+
break;
|
|
296
|
+
}
|
|
297
|
+
case "reasoning-end": {
|
|
298
|
+
const lastReasoningPart = [...activeMsg.parts].reverse().find((p) => p.type === "reasoning");
|
|
299
|
+
if (lastReasoningPart && "state" in lastReasoningPart) lastReasoningPart.state = "done";
|
|
300
|
+
break;
|
|
301
|
+
}
|
|
302
|
+
case "file":
|
|
303
|
+
activeMsg.parts.push({
|
|
304
|
+
type: "file",
|
|
305
|
+
mediaType: chunkData.mediaType,
|
|
306
|
+
url: chunkData.url
|
|
307
|
+
});
|
|
308
|
+
break;
|
|
309
|
+
case "source-url":
|
|
310
|
+
activeMsg.parts.push({
|
|
311
|
+
type: "source-url",
|
|
312
|
+
sourceId: chunkData.sourceId,
|
|
313
|
+
url: chunkData.url,
|
|
314
|
+
title: chunkData.title
|
|
315
|
+
});
|
|
316
|
+
break;
|
|
317
|
+
case "source-document":
|
|
318
|
+
activeMsg.parts.push({
|
|
319
|
+
type: "source-document",
|
|
320
|
+
sourceId: chunkData.sourceId,
|
|
321
|
+
mediaType: chunkData.mediaType,
|
|
322
|
+
title: chunkData.title,
|
|
323
|
+
filename: chunkData.filename
|
|
324
|
+
});
|
|
325
|
+
break;
|
|
326
|
+
case "tool-input-available":
|
|
327
|
+
activeMsg.parts.push({
|
|
328
|
+
type: `tool-${chunkData.toolName}`,
|
|
329
|
+
toolCallId: chunkData.toolCallId,
|
|
330
|
+
toolName: chunkData.toolName,
|
|
331
|
+
state: "input-available",
|
|
332
|
+
input: chunkData.input
|
|
333
|
+
});
|
|
334
|
+
break;
|
|
335
|
+
case "tool-output-available": {
|
|
336
|
+
const toolPart = activeMsg.parts.find((p) => "toolCallId" in p && p.toolCallId === chunkData.toolCallId);
|
|
337
|
+
if (toolPart && "state" in toolPart) {
|
|
338
|
+
toolPart.state = "output-available";
|
|
339
|
+
toolPart.output = chunkData.output;
|
|
340
|
+
}
|
|
341
|
+
break;
|
|
342
|
+
}
|
|
343
|
+
case "step-start":
|
|
344
|
+
activeMsg.parts.push({ type: "step-start" });
|
|
345
|
+
break;
|
|
346
|
+
}
|
|
347
|
+
useChatHelpers.setMessages((prevMessages) => {
|
|
348
|
+
if (!activeMsg) return prevMessages;
|
|
349
|
+
const existingIdx = prevMessages.findIndex((m) => m.id === activeMsg.messageId);
|
|
350
|
+
const partialMessage = {
|
|
351
|
+
id: activeMsg.messageId,
|
|
352
|
+
role: "assistant",
|
|
353
|
+
parts: [...activeMsg.parts]
|
|
354
|
+
};
|
|
355
|
+
if (existingIdx >= 0) {
|
|
356
|
+
const updated = [...prevMessages];
|
|
357
|
+
updated[existingIdx] = partialMessage;
|
|
358
|
+
return updated;
|
|
359
|
+
}
|
|
360
|
+
return [...prevMessages, partialMessage];
|
|
361
|
+
});
|
|
362
|
+
} catch (parseError) {
|
|
363
|
+
console.warn("[useAgentChat] Failed to parse stream chunk:", parseError instanceof Error ? parseError.message : parseError, "body:", data.body?.slice(0, 100));
|
|
364
|
+
}
|
|
365
|
+
if (data.done || data.error) activeStreamRef.current = null;
|
|
366
|
+
break;
|
|
367
|
+
}
|
|
220
368
|
}
|
|
221
|
-
if (data.type === MessageType.CF_AGENT_CHAT_MESSAGES) useChatHelpers.setMessages(data.messages);
|
|
222
369
|
}
|
|
223
|
-
agent.addEventListener("message",
|
|
224
|
-
agent.addEventListener("message", onMessages);
|
|
370
|
+
agent.addEventListener("message", onAgentMessage);
|
|
225
371
|
return () => {
|
|
226
|
-
agent.removeEventListener("message",
|
|
227
|
-
|
|
372
|
+
agent.removeEventListener("message", onAgentMessage);
|
|
373
|
+
activeStreamRef.current = null;
|
|
228
374
|
};
|
|
229
|
-
}, [
|
|
375
|
+
}, [
|
|
376
|
+
agent,
|
|
377
|
+
useChatHelpers.setMessages,
|
|
378
|
+
resume
|
|
379
|
+
]);
|
|
230
380
|
const addToolResultAndSendMessage = async (args) => {
|
|
231
381
|
const { toolCallId } = args;
|
|
232
382
|
await useChatHelpers.addToolResult(args);
|
package/dist/ai-react.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-react.js","names":["tool","options","controller: ReadableStreamDefaultController","data: OutgoingMessage<ChatMessage>","customTransport: ChatTransport<ChatMessage>","lastMessage","data: OutgoingMessage","addToolResultAndSendMessage: typeof useChatHelpers.addToolResult"],"sources":["../src/ai-react.tsx"],"sourcesContent":["import { useChat, type UseChatOptions } from \"@ai-sdk/react\";\nimport { getToolName, isToolUIPart } from \"ai\";\nimport type {\n ChatInit,\n ChatTransport,\n UIMessage as Message,\n UIMessage\n} from \"ai\";\nimport { DefaultChatTransport } from \"ai\";\nimport { nanoid } from \"nanoid\";\nimport { use, useCallback, useEffect, useMemo, useRef } from \"react\";\nimport type { OutgoingMessage } from \"./ai-types\";\nimport { MessageType } from \"./ai-types\";\nimport type { useAgent } from \"./react\";\n\nexport type AITool<Input = unknown, Output = unknown> = {\n description?: string;\n inputSchema?: unknown;\n execute?: (input: Input) => Output | Promise<Output>;\n};\n\ntype GetInitialMessagesOptions = {\n agent: string;\n name: string;\n url: string;\n};\n\n// v5 useChat parameters\ntype UseChatParams<M extends UIMessage = UIMessage> = ChatInit<M> &\n UseChatOptions<M>;\n\n/**\n * Options for the useAgentChat hook\n */\ntype UseAgentChatOptions<\n State,\n ChatMessage extends UIMessage = UIMessage\n> = Omit<UseChatParams<ChatMessage>, \"fetch\"> & {\n /** Agent connection from useAgent */\n agent: ReturnType<typeof useAgent<State>>;\n getInitialMessages?:\n | undefined\n | null\n | ((options: GetInitialMessagesOptions) => Promise<ChatMessage[]>);\n /** Request credentials */\n credentials?: RequestCredentials;\n /** Request headers */\n headers?: HeadersInit;\n /**\n * @description Whether to automatically resolve tool calls that do not require human interaction.\n * @experimental\n */\n experimental_automaticToolResolution?: boolean;\n /**\n * @description Tools object for automatic detection of confirmation requirements.\n * Tools without execute function will require confirmation.\n */\n tools?: Record<string, AITool<unknown, unknown>>;\n /**\n * @description Manual override for tools requiring confirmation.\n * If not provided, will auto-detect from tools object.\n */\n toolsRequiringConfirmation?: string[];\n /**\n * When true (default), automatically sends the next message only after\n * all pending confirmation-required tool calls have been resolved.\n * @default true\n */\n autoSendAfterAllConfirmationsResolved?: boolean;\n};\n\nconst requestCache = new Map<string, Promise<Message[]>>();\n\n/**\n * React hook for building AI chat interfaces using an Agent\n * @param options Chat options including the agent connection\n * @returns Chat interface controls and state with added clearHistory method\n */\n/**\n * Automatically detects which tools require confirmation based on their configuration.\n * Tools require confirmation if they have no execute function AND are not server-executed.\n * @param tools - Record of tool name to tool definition\n * @returns Array of tool names that require confirmation\n */\nexport function detectToolsRequiringConfirmation(\n tools?: Record<string, AITool<unknown, unknown>>\n): string[] {\n if (!tools) return [];\n\n return Object.entries(tools)\n .filter(([_name, tool]) => !tool.execute)\n .map(([name]) => name);\n}\n\nexport function useAgentChat<\n State = unknown,\n ChatMessage extends UIMessage = UIMessage\n>(\n options: UseAgentChatOptions<State, ChatMessage>\n): ReturnType<typeof useChat<ChatMessage>> & {\n clearHistory: () => void;\n} {\n const {\n agent,\n getInitialMessages,\n messages: optionsInitialMessages,\n experimental_automaticToolResolution,\n tools,\n toolsRequiringConfirmation: manualToolsRequiringConfirmation,\n autoSendAfterAllConfirmationsResolved = true,\n ...rest\n } = options;\n\n // Auto-detect tools requiring confirmation, or use manual override\n const toolsRequiringConfirmation =\n manualToolsRequiringConfirmation ?? detectToolsRequiringConfirmation(tools);\n\n const agentUrl = new URL(\n `${// @ts-expect-error we're using a protected _url property that includes query params\n ((agent._url as string | null) || agent._pkurl)\n ?.replace(\"ws://\", \"http://\")\n .replace(\"wss://\", \"https://\")}`\n );\n\n agentUrl.searchParams.delete(\"_pk\");\n const agentUrlString = agentUrl.toString();\n\n // we need to include agent.name in cache key to prevent collisions during agent switching.\n // The URL may be stale between updateProperties() and reconnect(), but agent.name\n // is updated synchronously, so each thread gets its own cache entry\n const initialMessagesCacheKey = `${agentUrlString}|${agent.agent ?? \"\"}|${agent.name ?? \"\"}`;\n\n // Keep a ref to always point to the latest agent instance\n const agentRef = useRef(agent);\n useEffect(() => {\n agentRef.current = agent;\n }, [agent]);\n\n async function defaultGetInitialMessagesFetch({\n url\n }: GetInitialMessagesOptions) {\n const getMessagesUrl = new URL(url);\n getMessagesUrl.pathname += \"/get-messages\";\n const response = await fetch(getMessagesUrl.toString(), {\n credentials: options.credentials,\n headers: options.headers\n });\n\n if (!response.ok) {\n console.warn(\n `Failed to fetch initial messages: ${response.status} ${response.statusText}`\n );\n return [];\n }\n\n const text = await response.text();\n if (!text.trim()) {\n return [];\n }\n\n try {\n return JSON.parse(text) as ChatMessage[];\n } catch (error) {\n console.warn(\"Failed to parse initial messages JSON:\", error);\n return [];\n }\n }\n\n const getInitialMessagesFetch =\n getInitialMessages || defaultGetInitialMessagesFetch;\n\n function doGetInitialMessages(\n getInitialMessagesOptions: GetInitialMessagesOptions,\n cacheKey: string\n ) {\n if (requestCache.has(cacheKey)) {\n return requestCache.get(cacheKey)! as Promise<ChatMessage[]>;\n }\n const promise = getInitialMessagesFetch(getInitialMessagesOptions);\n requestCache.set(cacheKey, promise);\n return promise;\n }\n\n const initialMessagesPromise =\n getInitialMessages === null\n ? null\n : doGetInitialMessages(\n {\n agent: agent.agent,\n name: agent.name,\n url: agentUrlString\n },\n initialMessagesCacheKey\n );\n const initialMessages = initialMessagesPromise\n ? use(initialMessagesPromise)\n : (optionsInitialMessages ?? []);\n\n useEffect(() => {\n if (!initialMessagesPromise) {\n return;\n }\n requestCache.set(initialMessagesCacheKey, initialMessagesPromise!);\n return () => {\n if (\n requestCache.get(initialMessagesCacheKey) === initialMessagesPromise\n ) {\n requestCache.delete(initialMessagesCacheKey);\n }\n };\n }, [initialMessagesCacheKey, initialMessagesPromise]);\n\n const aiFetch = useCallback(\n async (request: RequestInfo | URL, options: RequestInit = {}) => {\n const {\n method,\n keepalive,\n headers,\n body,\n redirect,\n integrity,\n signal,\n credentials,\n mode,\n referrer,\n referrerPolicy,\n window\n } = options;\n const id = nanoid(8);\n const abortController = new AbortController();\n let controller: ReadableStreamDefaultController;\n const currentAgent = agentRef.current;\n\n signal?.addEventListener(\"abort\", () => {\n currentAgent.send(\n JSON.stringify({\n id,\n type: MessageType.CF_AGENT_CHAT_REQUEST_CANCEL\n })\n );\n\n // NOTE - If we wanted to, we could preserve the \"interrupted\" message here, with the code below\n // However, I think it might be the responsibility of the library user to implement that behavior manually?\n // Reasoning: This code could be subject to collisions, as it \"force saves\" the messages we have locally\n //\n // agent.send(JSON.stringify({\n // type: MessageType.CF_AGENT_CHAT_MESSAGES,\n // messages: ... /* some way of getting current messages ref? */\n // }))\n\n abortController.abort();\n // Make sure to also close the stream (cf. https://github.com/cloudflare/agents-starter/issues/69)\n controller.close();\n });\n\n currentAgent.addEventListener(\n \"message\",\n (event) => {\n let data: OutgoingMessage<ChatMessage>;\n try {\n data = JSON.parse(event.data) as OutgoingMessage<ChatMessage>;\n } catch (_error) {\n // silently ignore invalid messages for now\n // TODO: log errors with log levels\n return;\n }\n if (data.type === MessageType.CF_AGENT_USE_CHAT_RESPONSE) {\n if (data.id === id) {\n if (data.error) {\n controller.error(new Error(data.body));\n abortController.abort();\n } else {\n // Only enqueue non-empty data to prevent JSON parsing errors\n if (data.body?.trim()) {\n controller.enqueue(\n new TextEncoder().encode(`data: ${data.body}\\n\\n`)\n );\n }\n if (data.done) {\n controller.close();\n abortController.abort();\n }\n }\n }\n }\n },\n { signal: abortController.signal }\n );\n\n const stream = new ReadableStream({\n start(c) {\n controller = c;\n }\n });\n\n currentAgent.send(\n JSON.stringify({\n id,\n init: {\n body,\n credentials,\n headers,\n integrity,\n keepalive,\n method,\n mode,\n redirect,\n referrer,\n referrerPolicy,\n window\n },\n type: MessageType.CF_AGENT_USE_CHAT_REQUEST,\n url: request.toString()\n })\n );\n\n return new Response(stream);\n },\n []\n );\n\n const customTransport: ChatTransport<ChatMessage> = useMemo(\n () => ({\n sendMessages: async (\n options: Parameters<\n typeof DefaultChatTransport.prototype.sendMessages\n >[0]\n ) => {\n const transport = new DefaultChatTransport<ChatMessage>({\n api: agentUrlString,\n fetch: aiFetch\n });\n return transport.sendMessages(options);\n },\n reconnectToStream: async (\n options: Parameters<\n typeof DefaultChatTransport.prototype.reconnectToStream\n >[0]\n ) => {\n const transport = new DefaultChatTransport<ChatMessage>({\n api: agentUrlString,\n fetch: aiFetch\n });\n return transport.reconnectToStream(options);\n }\n }),\n [agentUrlString, aiFetch]\n );\n\n const useChatHelpers = useChat<ChatMessage>({\n ...rest,\n messages: initialMessages,\n transport: customTransport,\n id: agent._pk\n });\n\n const processedToolCalls = useRef(new Set<string>());\n\n // Calculate pending confirmations for the latest assistant message\n const lastMessage =\n useChatHelpers.messages[useChatHelpers.messages.length - 1];\n\n const pendingConfirmations = (() => {\n if (!lastMessage || lastMessage.role !== \"assistant\") {\n return { messageId: undefined, toolCallIds: new Set<string>() };\n }\n\n const pendingIds = new Set<string>();\n for (const part of lastMessage.parts ?? []) {\n if (\n isToolUIPart(part) &&\n part.state === \"input-available\" &&\n toolsRequiringConfirmation.includes(getToolName(part))\n ) {\n pendingIds.add(part.toolCallId);\n }\n }\n return { messageId: lastMessage.id, toolCallIds: pendingIds };\n })();\n\n const pendingConfirmationsRef = useRef(pendingConfirmations);\n pendingConfirmationsRef.current = pendingConfirmations;\n\n // tools can be a different object everytime it's called,\n // which might lead to this effect being called multiple times with different tools objects.\n // we need to fix this, but that's a bigger refactor.\n // biome-ignore lint/correctness/useExhaustiveDependencies: we need to fix this\n useEffect(() => {\n if (!experimental_automaticToolResolution) {\n return;\n }\n\n const lastMessage =\n useChatHelpers.messages[useChatHelpers.messages.length - 1];\n if (!lastMessage || lastMessage.role !== \"assistant\") {\n return;\n }\n\n const toolCalls = lastMessage.parts.filter(\n (part) =>\n isToolUIPart(part) &&\n part.state === \"input-available\" &&\n !processedToolCalls.current.has(part.toolCallId)\n );\n\n if (toolCalls.length > 0) {\n (async () => {\n const toolCallsToResolve = toolCalls.filter(\n (part) =>\n isToolUIPart(part) &&\n !toolsRequiringConfirmation.includes(getToolName(part)) &&\n tools?.[getToolName(part)]?.execute // Only execute if client has execute function\n );\n\n if (toolCallsToResolve.length > 0) {\n for (const part of toolCallsToResolve) {\n if (isToolUIPart(part)) {\n processedToolCalls.current.add(part.toolCallId);\n let toolOutput = null;\n const toolName = getToolName(part);\n const tool = tools?.[toolName];\n\n if (tool?.execute && part.input) {\n try {\n toolOutput = await tool.execute(part.input);\n } catch (error) {\n toolOutput = `Error executing tool: ${error instanceof Error ? error.message : String(error)}`;\n }\n }\n\n await useChatHelpers.addToolResult({\n toolCallId: part.toolCallId,\n tool: toolName,\n output: toolOutput\n });\n }\n }\n // If there are NO pending confirmations for the latest assistant message,\n // we can continue the conversation. Otherwise, wait for the UI to resolve\n // those confirmations; the addToolResult wrapper will send when the last\n // pending confirmation is resolved.\n if (pendingConfirmationsRef.current.toolCallIds.size === 0) {\n useChatHelpers.sendMessage();\n }\n }\n })();\n }\n }, [\n useChatHelpers.messages,\n experimental_automaticToolResolution,\n useChatHelpers.addToolResult,\n useChatHelpers.sendMessage,\n toolsRequiringConfirmation\n ]);\n\n useEffect(() => {\n function onClearHistory(event: MessageEvent) {\n if (typeof event.data !== \"string\") return;\n let data: OutgoingMessage;\n try {\n data = JSON.parse(event.data) as OutgoingMessage;\n } catch (_error) {\n return;\n }\n if (data.type === MessageType.CF_AGENT_CHAT_CLEAR) {\n useChatHelpers.setMessages([]);\n }\n }\n\n function onMessages(event: MessageEvent) {\n if (typeof event.data !== \"string\") return;\n let data: OutgoingMessage<ChatMessage>;\n try {\n data = JSON.parse(event.data) as OutgoingMessage<ChatMessage>;\n } catch (_error) {\n return;\n }\n if (data.type === MessageType.CF_AGENT_CHAT_MESSAGES) {\n useChatHelpers.setMessages(data.messages);\n }\n }\n\n agent.addEventListener(\"message\", onClearHistory);\n agent.addEventListener(\"message\", onMessages);\n\n return () => {\n agent.removeEventListener(\"message\", onClearHistory);\n agent.removeEventListener(\"message\", onMessages);\n };\n }, [agent, useChatHelpers.setMessages]);\n\n // Wrapper that sends only when the last pending confirmation is resolved\n const addToolResultAndSendMessage: typeof useChatHelpers.addToolResult =\n async (args) => {\n const { toolCallId } = args;\n\n await useChatHelpers.addToolResult(args);\n\n if (!autoSendAfterAllConfirmationsResolved) {\n // always send immediately\n useChatHelpers.sendMessage();\n return;\n }\n\n // wait for all confirmations\n const pending = pendingConfirmationsRef.current?.toolCallIds;\n if (!pending) {\n useChatHelpers.sendMessage();\n return;\n }\n\n const wasLast = pending.size === 1 && pending.has(toolCallId);\n if (pending.has(toolCallId)) {\n pending.delete(toolCallId);\n }\n\n if (wasLast || pending.size === 0) {\n useChatHelpers.sendMessage();\n }\n };\n\n return {\n ...useChatHelpers,\n addToolResult: addToolResultAndSendMessage,\n clearHistory: () => {\n useChatHelpers.setMessages([]);\n agent.send(\n JSON.stringify({\n type: MessageType.CF_AGENT_CHAT_CLEAR\n })\n );\n },\n setMessages: (\n messages: Parameters<typeof useChatHelpers.setMessages>[0]\n ) => {\n useChatHelpers.setMessages(messages);\n agent.send(\n JSON.stringify({\n messages: Array.isArray(messages) ? messages : [],\n type: MessageType.CF_AGENT_CHAT_MESSAGES\n })\n );\n }\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ai-react.js","names":["tool","options","controller: ReadableStreamDefaultController","data: OutgoingMessage<ChatMessage>","customTransport: ChatTransport<ChatMessage>","lastMessage","addToolResultAndSendMessage: typeof useChatHelpers.addToolResult"],"sources":["../src/ai-react.tsx"],"sourcesContent":["import { useChat, type UseChatOptions } from \"@ai-sdk/react\";\nimport { getToolName, isToolUIPart } from \"ai\";\nimport type {\n ChatInit,\n ChatTransport,\n UIMessage as Message,\n UIMessage\n} from \"ai\";\nimport { DefaultChatTransport } from \"ai\";\nimport { nanoid } from \"nanoid\";\nimport { use, useCallback, useEffect, useMemo, useRef } from \"react\";\nimport type { OutgoingMessage } from \"./ai-types\";\nimport { MessageType } from \"./ai-types\";\nimport type { useAgent } from \"./react\";\n\nexport type AITool<Input = unknown, Output = unknown> = {\n description?: string;\n inputSchema?: unknown;\n execute?: (input: Input) => Output | Promise<Output>;\n};\n\ntype GetInitialMessagesOptions = {\n agent: string;\n name: string;\n url: string;\n};\n\n// v5 useChat parameters\ntype UseChatParams<M extends UIMessage = UIMessage> = ChatInit<M> &\n UseChatOptions<M>;\n\n/**\n * Options for the useAgentChat hook\n */\ntype UseAgentChatOptions<\n State,\n ChatMessage extends UIMessage = UIMessage\n> = Omit<UseChatParams<ChatMessage>, \"fetch\"> & {\n /** Agent connection from useAgent */\n agent: ReturnType<typeof useAgent<State>>;\n getInitialMessages?:\n | undefined\n | null\n | ((options: GetInitialMessagesOptions) => Promise<ChatMessage[]>);\n /** Request credentials */\n credentials?: RequestCredentials;\n /** Request headers */\n headers?: HeadersInit;\n /**\n * @description Whether to automatically resolve tool calls that do not require human interaction.\n * @experimental\n */\n experimental_automaticToolResolution?: boolean;\n /**\n * @description Tools object for automatic detection of confirmation requirements.\n * Tools without execute function will require confirmation.\n */\n tools?: Record<string, AITool<unknown, unknown>>;\n /**\n * @description Manual override for tools requiring confirmation.\n * If not provided, will auto-detect from tools object.\n */\n toolsRequiringConfirmation?: string[];\n /**\n * When true (default), automatically sends the next message only after\n * all pending confirmation-required tool calls have been resolved.\n * @default true\n */\n autoSendAfterAllConfirmationsResolved?: boolean;\n /**\n * Set to false to disable automatic stream resumption.\n * @default true\n */\n resume?: boolean;\n};\n\nconst requestCache = new Map<string, Promise<Message[]>>();\n\n/**\n * React hook for building AI chat interfaces using an Agent\n * @param options Chat options including the agent connection\n * @returns Chat interface controls and state with added clearHistory method\n */\n/**\n * Automatically detects which tools require confirmation based on their configuration.\n * Tools require confirmation if they have no execute function AND are not server-executed.\n * @param tools - Record of tool name to tool definition\n * @returns Array of tool names that require confirmation\n */\nexport function detectToolsRequiringConfirmation(\n tools?: Record<string, AITool<unknown, unknown>>\n): string[] {\n if (!tools) return [];\n\n return Object.entries(tools)\n .filter(([_name, tool]) => !tool.execute)\n .map(([name]) => name);\n}\n\nexport function useAgentChat<\n State = unknown,\n ChatMessage extends UIMessage = UIMessage\n>(\n options: UseAgentChatOptions<State, ChatMessage>\n): ReturnType<typeof useChat<ChatMessage>> & {\n clearHistory: () => void;\n} {\n const {\n agent,\n getInitialMessages,\n messages: optionsInitialMessages,\n experimental_automaticToolResolution,\n tools,\n toolsRequiringConfirmation: manualToolsRequiringConfirmation,\n autoSendAfterAllConfirmationsResolved = true,\n resume = true, // Enable stream resumption by default\n ...rest\n } = options;\n\n // Auto-detect tools requiring confirmation, or use manual override\n const toolsRequiringConfirmation =\n manualToolsRequiringConfirmation ?? detectToolsRequiringConfirmation(tools);\n\n const agentUrl = new URL(\n `${// @ts-expect-error we're using a protected _url property that includes query params\n ((agent._url as string | null) || agent._pkurl)\n ?.replace(\"ws://\", \"http://\")\n .replace(\"wss://\", \"https://\")}`\n );\n\n agentUrl.searchParams.delete(\"_pk\");\n const agentUrlString = agentUrl.toString();\n\n // we need to include agent.name in cache key to prevent collisions during agent switching.\n // The URL may be stale between updateProperties() and reconnect(), but agent.name\n // is updated synchronously, so each thread gets its own cache entry\n const initialMessagesCacheKey = `${agentUrlString}|${agent.agent ?? \"\"}|${agent.name ?? \"\"}`;\n\n // Keep a ref to always point to the latest agent instance\n const agentRef = useRef(agent);\n useEffect(() => {\n agentRef.current = agent;\n }, [agent]);\n\n async function defaultGetInitialMessagesFetch({\n url\n }: GetInitialMessagesOptions) {\n const getMessagesUrl = new URL(url);\n getMessagesUrl.pathname += \"/get-messages\";\n const response = await fetch(getMessagesUrl.toString(), {\n credentials: options.credentials,\n headers: options.headers\n });\n\n if (!response.ok) {\n console.warn(\n `Failed to fetch initial messages: ${response.status} ${response.statusText}`\n );\n return [];\n }\n\n const text = await response.text();\n if (!text.trim()) {\n return [];\n }\n\n try {\n return JSON.parse(text) as ChatMessage[];\n } catch (error) {\n console.warn(\"Failed to parse initial messages JSON:\", error);\n return [];\n }\n }\n\n const getInitialMessagesFetch =\n getInitialMessages || defaultGetInitialMessagesFetch;\n\n function doGetInitialMessages(\n getInitialMessagesOptions: GetInitialMessagesOptions,\n cacheKey: string\n ) {\n if (requestCache.has(cacheKey)) {\n return requestCache.get(cacheKey)! as Promise<ChatMessage[]>;\n }\n const promise = getInitialMessagesFetch(getInitialMessagesOptions);\n requestCache.set(cacheKey, promise);\n return promise;\n }\n\n const initialMessagesPromise =\n getInitialMessages === null\n ? null\n : doGetInitialMessages(\n {\n agent: agent.agent,\n name: agent.name,\n url: agentUrlString\n },\n initialMessagesCacheKey\n );\n const initialMessages = initialMessagesPromise\n ? use(initialMessagesPromise)\n : (optionsInitialMessages ?? []);\n\n useEffect(() => {\n if (!initialMessagesPromise) {\n return;\n }\n requestCache.set(initialMessagesCacheKey, initialMessagesPromise!);\n return () => {\n if (\n requestCache.get(initialMessagesCacheKey) === initialMessagesPromise\n ) {\n requestCache.delete(initialMessagesCacheKey);\n }\n };\n }, [initialMessagesCacheKey, initialMessagesPromise]);\n\n const aiFetch = useCallback(\n async (request: RequestInfo | URL, options: RequestInit = {}) => {\n const {\n method,\n keepalive,\n headers,\n body,\n redirect,\n integrity,\n signal,\n credentials,\n mode,\n referrer,\n referrerPolicy,\n window\n } = options;\n const id = nanoid(8);\n const abortController = new AbortController();\n let controller: ReadableStreamDefaultController;\n const currentAgent = agentRef.current;\n\n // Track this request ID so the onAgentMessage handler knows to skip it\n // (this tab's aiFetch listener handles its own stream)\n localRequestIdsRef.current.add(id);\n\n signal?.addEventListener(\"abort\", () => {\n currentAgent.send(\n JSON.stringify({\n id,\n type: MessageType.CF_AGENT_CHAT_REQUEST_CANCEL\n })\n );\n\n // NOTE - If we wanted to, we could preserve the \"interrupted\" message here, with the code below\n // However, I think it might be the responsibility of the library user to implement that behavior manually?\n // Reasoning: This code could be subject to collisions, as it \"force saves\" the messages we have locally\n //\n // agent.send(JSON.stringify({\n // type: MessageType.CF_AGENT_CHAT_MESSAGES,\n // messages: ... /* some way of getting current messages ref? */\n // }))\n abortController.abort();\n // Make sure to also close the stream (cf. https://github.com/cloudflare/agents-starter/issues/69)\n try {\n controller.close();\n } catch {\n // Stream may already be errored or closed\n }\n // Clean up the request ID tracking\n localRequestIdsRef.current.delete(id);\n });\n\n currentAgent.addEventListener(\n \"message\",\n (event) => {\n let data: OutgoingMessage<ChatMessage>;\n try {\n data = JSON.parse(event.data) as OutgoingMessage<ChatMessage>;\n } catch (_error) {\n // silently ignore invalid messages for now\n // TODO: log errors with log levels\n return;\n }\n if (data.type === MessageType.CF_AGENT_USE_CHAT_RESPONSE) {\n if (data.id === id) {\n if (data.error) {\n controller.error(new Error(data.body));\n abortController.abort();\n // Clean up the request ID tracking\n localRequestIdsRef.current.delete(id);\n } else {\n // Only enqueue non-empty data to prevent JSON parsing errors\n if (data.body?.trim()) {\n controller.enqueue(\n new TextEncoder().encode(`data: ${data.body}\\n\\n`)\n );\n }\n if (data.done) {\n try {\n controller.close();\n } catch {\n // Stream may already be errored or closed\n }\n abortController.abort();\n // Clean up the request ID tracking\n localRequestIdsRef.current.delete(id);\n }\n }\n }\n }\n },\n { signal: abortController.signal }\n );\n\n const stream = new ReadableStream({\n start(c) {\n controller = c;\n },\n cancel(reason?: unknown) {\n console.warn(\n \"[agents/ai-react] cancelling stream\",\n id,\n reason || \"no reason\"\n );\n }\n });\n\n currentAgent.send(\n JSON.stringify({\n id,\n init: {\n body,\n credentials,\n headers,\n integrity,\n keepalive,\n method,\n mode,\n redirect,\n referrer,\n referrerPolicy,\n window\n },\n type: MessageType.CF_AGENT_USE_CHAT_REQUEST,\n url: request.toString()\n })\n );\n\n return new Response(stream);\n },\n []\n );\n\n const customTransport: ChatTransport<ChatMessage> = useMemo(\n () => ({\n sendMessages: async (\n options: Parameters<\n typeof DefaultChatTransport.prototype.sendMessages\n >[0]\n ) => {\n const transport = new DefaultChatTransport<ChatMessage>({\n api: agentUrlString,\n fetch: aiFetch\n });\n return transport.sendMessages(options);\n },\n reconnectToStream: async () => null\n }),\n [agentUrlString, aiFetch]\n );\n\n const useChatHelpers = useChat<ChatMessage>({\n ...rest,\n messages: initialMessages,\n transport: customTransport,\n id: agent._pk\n // Note: We handle stream resumption via WebSocket instead of HTTP,\n // so we don't pass 'resume' to useChat. The onStreamResuming handler\n // automatically resumes active streams when the WebSocket reconnects.\n });\n\n const processedToolCalls = useRef(new Set<string>());\n\n // Calculate pending confirmations for the latest assistant message\n const lastMessage =\n useChatHelpers.messages[useChatHelpers.messages.length - 1];\n\n const pendingConfirmations = (() => {\n if (!lastMessage || lastMessage.role !== \"assistant\") {\n return { messageId: undefined, toolCallIds: new Set<string>() };\n }\n\n const pendingIds = new Set<string>();\n for (const part of lastMessage.parts ?? []) {\n if (\n isToolUIPart(part) &&\n part.state === \"input-available\" &&\n toolsRequiringConfirmation.includes(getToolName(part))\n ) {\n pendingIds.add(part.toolCallId);\n }\n }\n return { messageId: lastMessage.id, toolCallIds: pendingIds };\n })();\n\n const pendingConfirmationsRef = useRef(pendingConfirmations);\n pendingConfirmationsRef.current = pendingConfirmations;\n\n // tools can be a different object everytime it's called,\n // which might lead to this effect being called multiple times with different tools objects.\n // we need to fix this, but that's a bigger refactor.\n // biome-ignore lint/correctness/useExhaustiveDependencies: we need to fix this\n useEffect(() => {\n if (!experimental_automaticToolResolution) {\n return;\n }\n\n const lastMessage =\n useChatHelpers.messages[useChatHelpers.messages.length - 1];\n if (!lastMessage || lastMessage.role !== \"assistant\") {\n return;\n }\n\n const toolCalls = lastMessage.parts.filter(\n (part) =>\n isToolUIPart(part) &&\n part.state === \"input-available\" &&\n !processedToolCalls.current.has(part.toolCallId)\n );\n\n if (toolCalls.length > 0) {\n (async () => {\n const toolCallsToResolve = toolCalls.filter(\n (part) =>\n isToolUIPart(part) &&\n !toolsRequiringConfirmation.includes(getToolName(part)) &&\n tools?.[getToolName(part)]?.execute // Only execute if client has execute function\n );\n\n if (toolCallsToResolve.length > 0) {\n for (const part of toolCallsToResolve) {\n if (isToolUIPart(part)) {\n processedToolCalls.current.add(part.toolCallId);\n let toolOutput = null;\n const toolName = getToolName(part);\n const tool = tools?.[toolName];\n\n if (tool?.execute && part.input) {\n try {\n toolOutput = await tool.execute(part.input);\n } catch (error) {\n toolOutput = `Error executing tool: ${error instanceof Error ? error.message : String(error)}`;\n }\n }\n\n await useChatHelpers.addToolResult({\n toolCallId: part.toolCallId,\n tool: toolName,\n output: toolOutput\n });\n }\n }\n // If there are NO pending confirmations for the latest assistant message,\n // we can continue the conversation. Otherwise, wait for the UI to resolve\n // those confirmations; the addToolResult wrapper will send when the last\n // pending confirmation is resolved.\n if (pendingConfirmationsRef.current.toolCallIds.size === 0) {\n useChatHelpers.sendMessage();\n }\n }\n })();\n }\n }, [\n useChatHelpers.messages,\n experimental_automaticToolResolution,\n useChatHelpers.addToolResult,\n useChatHelpers.sendMessage,\n toolsRequiringConfirmation\n ]);\n\n /**\n * Contains the request ID, accumulated message parts, and a unique message ID.\n * Used for both resumed streams and real-time broadcasts from other tabs.\n */\n const activeStreamRef = useRef<{\n id: string;\n messageId: string;\n parts: ChatMessage[\"parts\"];\n } | null>(null);\n\n /**\n * Tracks request IDs initiated by this tab via aiFetch.\n * Used to distinguish local requests from broadcasts.\n */\n const localRequestIdsRef = useRef<Set<string>>(new Set());\n\n useEffect(() => {\n /**\n * Unified message handler that parses JSON once and dispatches based on type.\n * Avoids duplicate parsing overhead from separate listeners.\n */\n function onAgentMessage(event: MessageEvent) {\n if (typeof event.data !== \"string\") return;\n\n let data: OutgoingMessage<ChatMessage>;\n try {\n data = JSON.parse(event.data) as OutgoingMessage<ChatMessage>;\n } catch (_error) {\n return;\n }\n\n switch (data.type) {\n case MessageType.CF_AGENT_CHAT_CLEAR:\n useChatHelpers.setMessages([]);\n break;\n\n case MessageType.CF_AGENT_CHAT_MESSAGES:\n useChatHelpers.setMessages(data.messages);\n break;\n\n case MessageType.CF_AGENT_STREAM_RESUMING:\n if (!resume) return;\n // Clear any previous incomplete active stream to prevent memory leak\n activeStreamRef.current = null;\n // Initialize active stream state with unique ID\n activeStreamRef.current = {\n id: data.id,\n messageId: nanoid(),\n parts: []\n };\n // Send ACK to server - we're ready to receive chunks\n agentRef.current.send(\n JSON.stringify({\n type: MessageType.CF_AGENT_STREAM_RESUME_ACK,\n id: data.id\n })\n );\n break;\n\n case MessageType.CF_AGENT_USE_CHAT_RESPONSE: {\n // Skip if this is a response to a request this tab initiated\n // (handled by the aiFetch listener instead)\n if (localRequestIdsRef.current.has(data.id)) return;\n\n // Initialize stream state for broadcasts from other tabs\n if (\n !activeStreamRef.current ||\n activeStreamRef.current.id !== data.id\n ) {\n activeStreamRef.current = {\n id: data.id,\n messageId: nanoid(),\n parts: []\n };\n }\n\n const activeMsg = activeStreamRef.current;\n\n if (data.body?.trim()) {\n try {\n const chunkData = JSON.parse(data.body);\n\n // Handle all chunk types for complete message reconstruction\n switch (chunkData.type) {\n case \"text-start\": {\n activeMsg.parts.push({\n type: \"text\",\n text: \"\",\n state: \"streaming\"\n });\n break;\n }\n case \"text-delta\": {\n const lastTextPart = [...activeMsg.parts]\n .reverse()\n .find((p) => p.type === \"text\");\n if (lastTextPart && lastTextPart.type === \"text\") {\n lastTextPart.text += chunkData.delta;\n } else {\n // Handle plain text responses (no text-start)\n activeMsg.parts.push({\n type: \"text\",\n text: chunkData.delta\n });\n }\n break;\n }\n case \"text-end\": {\n const lastTextPart = [...activeMsg.parts]\n .reverse()\n .find((p) => p.type === \"text\");\n if (lastTextPart && \"state\" in lastTextPart) {\n lastTextPart.state = \"done\";\n }\n break;\n }\n case \"reasoning-start\": {\n activeMsg.parts.push({\n type: \"reasoning\",\n text: \"\",\n state: \"streaming\"\n });\n break;\n }\n case \"reasoning-delta\": {\n const lastReasoningPart = [...activeMsg.parts]\n .reverse()\n .find((p) => p.type === \"reasoning\");\n if (\n lastReasoningPart &&\n lastReasoningPart.type === \"reasoning\"\n ) {\n lastReasoningPart.text += chunkData.delta;\n }\n break;\n }\n case \"reasoning-end\": {\n const lastReasoningPart = [...activeMsg.parts]\n .reverse()\n .find((p) => p.type === \"reasoning\");\n if (lastReasoningPart && \"state\" in lastReasoningPart) {\n lastReasoningPart.state = \"done\";\n }\n break;\n }\n case \"file\": {\n activeMsg.parts.push({\n type: \"file\",\n mediaType: chunkData.mediaType,\n url: chunkData.url\n });\n break;\n }\n case \"source-url\": {\n activeMsg.parts.push({\n type: \"source-url\",\n sourceId: chunkData.sourceId,\n url: chunkData.url,\n title: chunkData.title\n });\n break;\n }\n case \"source-document\": {\n activeMsg.parts.push({\n type: \"source-document\",\n sourceId: chunkData.sourceId,\n mediaType: chunkData.mediaType,\n title: chunkData.title,\n filename: chunkData.filename\n });\n break;\n }\n case \"tool-input-available\": {\n // Add tool call part when input is available\n activeMsg.parts.push({\n type: `tool-${chunkData.toolName}`,\n toolCallId: chunkData.toolCallId,\n toolName: chunkData.toolName,\n state: \"input-available\",\n input: chunkData.input\n } as ChatMessage[\"parts\"][number]);\n break;\n }\n case \"tool-output-available\": {\n // Update existing tool part with output\n const toolPart = activeMsg.parts.find(\n (p) =>\n \"toolCallId\" in p && p.toolCallId === chunkData.toolCallId\n );\n if (toolPart && \"state\" in toolPart) {\n (toolPart as Record<string, unknown>).state =\n \"output-available\";\n (toolPart as Record<string, unknown>).output =\n chunkData.output;\n }\n break;\n }\n case \"step-start\": {\n activeMsg.parts.push({ type: \"step-start\" });\n break;\n }\n // Other chunk types (tool-input-start, tool-input-delta, etc.)\n // are intermediate states - the final state will be captured above\n }\n\n // Update messages with the partial response\n useChatHelpers.setMessages((prevMessages: ChatMessage[]) => {\n if (!activeMsg) return prevMessages;\n\n const existingIdx = prevMessages.findIndex(\n (m) => m.id === activeMsg.messageId\n );\n\n const partialMessage = {\n id: activeMsg.messageId,\n role: \"assistant\" as const,\n parts: [...activeMsg.parts]\n } as unknown as ChatMessage;\n\n if (existingIdx >= 0) {\n const updated = [...prevMessages];\n updated[existingIdx] = partialMessage;\n return updated;\n }\n return [...prevMessages, partialMessage];\n });\n } catch (parseError) {\n // Log corrupted chunk for debugging - could indicate data loss\n console.warn(\n \"[useAgentChat] Failed to parse stream chunk:\",\n parseError instanceof Error ? parseError.message : parseError,\n \"body:\",\n data.body?.slice(0, 100) // Truncate for logging\n );\n }\n }\n\n // Clear on completion or error\n if (data.done || data.error) {\n activeStreamRef.current = null;\n }\n break;\n }\n }\n }\n\n agent.addEventListener(\"message\", onAgentMessage);\n return () => {\n agent.removeEventListener(\"message\", onAgentMessage);\n // Clear active stream state on cleanup to prevent memory leak\n activeStreamRef.current = null;\n };\n }, [agent, useChatHelpers.setMessages, resume]);\n\n // Wrapper that sends only when the last pending confirmation is resolved\n const addToolResultAndSendMessage: typeof useChatHelpers.addToolResult =\n async (args) => {\n const { toolCallId } = args;\n\n await useChatHelpers.addToolResult(args);\n\n if (!autoSendAfterAllConfirmationsResolved) {\n // always send immediately\n useChatHelpers.sendMessage();\n return;\n }\n\n // wait for all confirmations\n const pending = pendingConfirmationsRef.current?.toolCallIds;\n if (!pending) {\n useChatHelpers.sendMessage();\n return;\n }\n\n const wasLast = pending.size === 1 && pending.has(toolCallId);\n if (pending.has(toolCallId)) {\n pending.delete(toolCallId);\n }\n\n if (wasLast || pending.size === 0) {\n useChatHelpers.sendMessage();\n }\n };\n\n return {\n ...useChatHelpers,\n addToolResult: addToolResultAndSendMessage,\n clearHistory: () => {\n useChatHelpers.setMessages([]);\n agent.send(\n JSON.stringify({\n type: MessageType.CF_AGENT_CHAT_CLEAR\n })\n );\n },\n setMessages: (\n messages: Parameters<typeof useChatHelpers.setMessages>[0]\n ) => {\n useChatHelpers.setMessages(messages);\n agent.send(\n JSON.stringify({\n messages: Array.isArray(messages) ? messages : [],\n type: MessageType.CF_AGENT_CHAT_MESSAGES\n })\n );\n }\n };\n}\n"],"mappings":"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"}
|
|
@@ -11,6 +11,10 @@ declare enum MessageType {
|
|
|
11
11
|
CF_AGENT_USE_CHAT_RESPONSE = "cf_agent_use_chat_response",
|
|
12
12
|
CF_AGENT_CHAT_CLEAR = "cf_agent_chat_clear",
|
|
13
13
|
CF_AGENT_CHAT_REQUEST_CANCEL = "cf_agent_chat_request_cancel",
|
|
14
|
+
/** Sent by server when client connects and there's an active stream to resume */
|
|
15
|
+
CF_AGENT_STREAM_RESUMING = "cf_agent_stream_resuming",
|
|
16
|
+
/** Sent by client to acknowledge stream resuming notification and request chunks */
|
|
17
|
+
CF_AGENT_STREAM_RESUME_ACK = "cf_agent_stream_resume_ack",
|
|
14
18
|
CF_AGENT_MCP_SERVERS = "cf_agent_mcp_servers",
|
|
15
19
|
CF_MCP_AGENT_EVENT = "cf_mcp_agent_event",
|
|
16
20
|
CF_AGENT_STATE = "cf_agent_state",
|
|
@@ -43,8 +47,10 @@ type OutgoingMessage<ChatMessage extends UIMessage = UIMessage> =
|
|
|
43
47
|
error?: boolean;
|
|
44
48
|
}
|
|
45
49
|
| {
|
|
46
|
-
/** Indicates
|
|
47
|
-
type: MessageType.
|
|
50
|
+
/** Indicates the server is resuming an active stream */
|
|
51
|
+
type: MessageType.CF_AGENT_STREAM_RESUMING;
|
|
52
|
+
/** The request ID of the stream being resumed */
|
|
53
|
+
id: string;
|
|
48
54
|
};
|
|
49
55
|
/**
|
|
50
56
|
* Types of messages sent from clients to the Agent
|
|
@@ -75,10 +81,6 @@ type IncomingMessage<ChatMessage extends UIMessage = UIMessage> =
|
|
|
75
81
|
| "window"
|
|
76
82
|
>;
|
|
77
83
|
}
|
|
78
|
-
| {
|
|
79
|
-
/** Indicates this message is a command to clear chat history */
|
|
80
|
-
type: MessageType.CF_AGENT_CHAT_CLEAR;
|
|
81
|
-
}
|
|
82
84
|
| {
|
|
83
85
|
/** Indicates this message contains updated chat messages */
|
|
84
86
|
type: MessageType.CF_AGENT_CHAT_MESSAGES;
|
|
@@ -89,7 +91,13 @@ type IncomingMessage<ChatMessage extends UIMessage = UIMessage> =
|
|
|
89
91
|
/** Indicates the user wants to stop generation of this message */
|
|
90
92
|
type: MessageType.CF_AGENT_CHAT_REQUEST_CANCEL;
|
|
91
93
|
id: string;
|
|
94
|
+
}
|
|
95
|
+
| {
|
|
96
|
+
/** Client acknowledges stream resuming notification and is ready to receive chunks */
|
|
97
|
+
type: MessageType.CF_AGENT_STREAM_RESUME_ACK;
|
|
98
|
+
/** The request ID of the stream being resumed */
|
|
99
|
+
id: string;
|
|
92
100
|
};
|
|
93
101
|
//#endregion
|
|
94
102
|
export { MessageType as n, OutgoingMessage as r, IncomingMessage as t };
|
|
95
|
-
//# sourceMappingURL=ai-types-
|
|
103
|
+
//# sourceMappingURL=ai-types-81H_-Uxh.d.ts.map
|
|
@@ -8,6 +8,10 @@ let MessageType = /* @__PURE__ */ function(MessageType$1) {
|
|
|
8
8
|
MessageType$1["CF_AGENT_USE_CHAT_RESPONSE"] = "cf_agent_use_chat_response";
|
|
9
9
|
MessageType$1["CF_AGENT_CHAT_CLEAR"] = "cf_agent_chat_clear";
|
|
10
10
|
MessageType$1["CF_AGENT_CHAT_REQUEST_CANCEL"] = "cf_agent_chat_request_cancel";
|
|
11
|
+
/** Sent by server when client connects and there's an active stream to resume */
|
|
12
|
+
MessageType$1["CF_AGENT_STREAM_RESUMING"] = "cf_agent_stream_resuming";
|
|
13
|
+
/** Sent by client to acknowledge stream resuming notification and request chunks */
|
|
14
|
+
MessageType$1["CF_AGENT_STREAM_RESUME_ACK"] = "cf_agent_stream_resume_ack";
|
|
11
15
|
MessageType$1["CF_AGENT_MCP_SERVERS"] = "cf_agent_mcp_servers";
|
|
12
16
|
MessageType$1["CF_MCP_AGENT_EVENT"] = "cf_mcp_agent_event";
|
|
13
17
|
MessageType$1["CF_AGENT_STATE"] = "cf_agent_state";
|
|
@@ -17,4 +21,4 @@ let MessageType = /* @__PURE__ */ function(MessageType$1) {
|
|
|
17
21
|
|
|
18
22
|
//#endregion
|
|
19
23
|
export { MessageType as t };
|
|
20
|
-
//# sourceMappingURL=ai-types-
|
|
24
|
+
//# sourceMappingURL=ai-types-CrMqkwc_.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-types-CrMqkwc_.js","names":[],"sources":["../src/ai-types.ts"],"sourcesContent":["import type { UIMessage } from \"ai\";\n\n/**\n * Enum for message types to improve type safety and maintainability\n */\nexport enum MessageType {\n CF_AGENT_CHAT_MESSAGES = \"cf_agent_chat_messages\",\n CF_AGENT_USE_CHAT_REQUEST = \"cf_agent_use_chat_request\",\n CF_AGENT_USE_CHAT_RESPONSE = \"cf_agent_use_chat_response\",\n CF_AGENT_CHAT_CLEAR = \"cf_agent_chat_clear\",\n CF_AGENT_CHAT_REQUEST_CANCEL = \"cf_agent_chat_request_cancel\",\n\n /** Sent by server when client connects and there's an active stream to resume */\n CF_AGENT_STREAM_RESUMING = \"cf_agent_stream_resuming\",\n /** Sent by client to acknowledge stream resuming notification and request chunks */\n CF_AGENT_STREAM_RESUME_ACK = \"cf_agent_stream_resume_ack\",\n\n CF_AGENT_MCP_SERVERS = \"cf_agent_mcp_servers\",\n CF_MCP_AGENT_EVENT = \"cf_mcp_agent_event\",\n CF_AGENT_STATE = \"cf_agent_state\",\n RPC = \"rpc\"\n}\n\n/**\n * Types of messages sent from the Agent to clients\n */\nexport type OutgoingMessage<ChatMessage extends UIMessage = UIMessage> =\n | {\n /** Indicates this message is a command to clear chat history */\n type: MessageType.CF_AGENT_CHAT_CLEAR;\n }\n | {\n /** Indicates this message contains updated chat messages */\n type: MessageType.CF_AGENT_CHAT_MESSAGES;\n /** Array of chat messages */\n messages: ChatMessage[];\n }\n | {\n /** Indicates this message is a response to a chat request */\n type: MessageType.CF_AGENT_USE_CHAT_RESPONSE;\n /** Unique ID of the request this response corresponds to */\n id: string;\n /** Content body of the response */\n body: string;\n /** Whether this is the final chunk of the response */\n done: boolean;\n /** Whether this response contains an error */\n error?: boolean;\n }\n | {\n /** Indicates the server is resuming an active stream */\n type: MessageType.CF_AGENT_STREAM_RESUMING;\n /** The request ID of the stream being resumed */\n id: string;\n };\n\n/**\n * Types of messages sent from clients to the Agent\n */\nexport type IncomingMessage<ChatMessage extends UIMessage = UIMessage> =\n | {\n /** Indicates this message is a command to clear chat history */\n type: MessageType.CF_AGENT_CHAT_CLEAR;\n }\n | {\n /** Indicates this message is a request to the chat API */\n type: MessageType.CF_AGENT_USE_CHAT_REQUEST;\n /** Unique ID for this request */\n id: string;\n /** Request initialization options */\n init: Pick<\n RequestInit,\n | \"method\"\n | \"keepalive\"\n | \"headers\"\n | \"body\"\n | \"redirect\"\n | \"integrity\"\n | \"credentials\"\n | \"mode\"\n | \"referrer\"\n | \"referrerPolicy\"\n | \"window\"\n >;\n }\n | {\n /** Indicates this message contains updated chat messages */\n type: MessageType.CF_AGENT_CHAT_MESSAGES;\n /** Array of chat messages */\n messages: ChatMessage[];\n }\n | {\n /** Indicates the user wants to stop generation of this message */\n type: MessageType.CF_AGENT_CHAT_REQUEST_CANCEL;\n id: string;\n }\n | {\n /** Client acknowledges stream resuming notification and is ready to receive chunks */\n type: MessageType.CF_AGENT_STREAM_RESUME_ACK;\n /** The request ID of the stream being resumed */\n id: string;\n };\n"],"mappings":";;;;AAKA,IAAY,sDAAL;AACL;AACA;AACA;AACA;AACA;;AAGA;;AAEA;AAEA;AACA;AACA;AACA"}
|
package/dist/ai-types.d.ts
CHANGED
package/dist/ai-types.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as MessageType } from "./ai-types-
|
|
1
|
+
import { t as MessageType } from "./ai-types-CrMqkwc_.js";
|
|
2
2
|
import { PartySocket } from "partysocket";
|
|
3
3
|
|
|
4
4
|
//#region src/client.ts
|
|
@@ -114,4 +114,4 @@ function agentFetch(opts, init) {
|
|
|
114
114
|
|
|
115
115
|
//#endregion
|
|
116
116
|
export { agentFetch as n, camelCaseToKebabCase as r, AgentClient as t };
|
|
117
|
-
//# sourceMappingURL=client-
|
|
117
|
+
//# sourceMappingURL=client-B3SR12TQ.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client-
|
|
1
|
+
{"version":3,"file":"client-B3SR12TQ.js","names":["parsedMessage: Record<string, unknown>","request: RPCRequest"],"sources":["../src/client.ts"],"sourcesContent":["import {\n type PartyFetchOptions,\n PartySocket,\n type PartySocketOptions\n} from \"partysocket\";\nimport type { RPCRequest, RPCResponse } from \"./\";\nimport type {\n SerializableReturnValue,\n SerializableValue\n} from \"./serializable\";\nimport { MessageType } from \"./ai-types\";\n\n/**\n * Options for creating an AgentClient\n */\nexport type AgentClientOptions<State = unknown> = Omit<\n PartySocketOptions,\n \"party\" | \"room\"\n> & {\n /** Name of the agent to connect to */\n agent: string;\n /** Name of the specific Agent instance */\n name?: string;\n /** Called when the Agent's state is updated */\n onStateUpdate?: (state: State, source: \"server\" | \"client\") => void;\n};\n\n/**\n * Options for streaming RPC calls\n */\nexport type StreamOptions = {\n /** Called when a chunk of data is received */\n onChunk?: (chunk: unknown) => void;\n /** Called when the stream ends */\n onDone?: (finalChunk: unknown) => void;\n /** Called when an error occurs */\n onError?: (error: string) => void;\n};\n\n/**\n * Options for the agentFetch function\n */\nexport type AgentClientFetchOptions = Omit<\n PartyFetchOptions,\n \"party\" | \"room\"\n> & {\n /** Name of the agent to connect to */\n agent: string;\n /** Name of the specific Agent instance */\n name?: string;\n};\n\n/**\n * Convert a camelCase string to a kebab-case string\n * @param str The string to convert\n * @returns The kebab-case string\n */\nexport function camelCaseToKebabCase(str: string): string {\n // If string is all uppercase, convert to lowercase\n if (str === str.toUpperCase() && str !== str.toLowerCase()) {\n return str.toLowerCase().replace(/_/g, \"-\");\n }\n\n // Otherwise handle camelCase to kebab-case\n let kebabified = str.replace(\n /[A-Z]/g,\n (letter) => `-${letter.toLowerCase()}`\n );\n kebabified = kebabified.startsWith(\"-\") ? kebabified.slice(1) : kebabified;\n // Convert any remaining underscores to hyphens and remove trailing -'s\n return kebabified.replace(/_/g, \"-\").replace(/-$/, \"\");\n}\n\n/**\n * WebSocket client for connecting to an Agent\n */\nexport class AgentClient<State = unknown> extends PartySocket {\n /**\n * @deprecated Use agentFetch instead\n */\n static fetch(_opts: PartyFetchOptions): Promise<Response> {\n throw new Error(\n \"AgentClient.fetch is not implemented, use agentFetch instead\"\n );\n }\n agent: string;\n name: string;\n private options: AgentClientOptions<State>;\n private _pendingCalls = new Map<\n string,\n {\n resolve: (value: unknown) => void;\n reject: (error: Error) => void;\n stream?: StreamOptions;\n type?: unknown;\n }\n >();\n\n constructor(options: AgentClientOptions<State>) {\n const agentNamespace = camelCaseToKebabCase(options.agent);\n super({\n party: agentNamespace,\n prefix: \"agents\",\n room: options.name || \"default\",\n ...options\n });\n this.agent = agentNamespace;\n this.name = options.name || \"default\";\n this.options = options;\n\n this.addEventListener(\"message\", (event) => {\n if (typeof event.data === \"string\") {\n let parsedMessage: Record<string, unknown>;\n try {\n parsedMessage = JSON.parse(event.data);\n } catch (_error) {\n // silently ignore invalid messages for now\n // TODO: log errors with log levels\n return;\n }\n if (parsedMessage.type === MessageType.CF_AGENT_STATE) {\n this.options.onStateUpdate?.(parsedMessage.state as State, \"server\");\n return;\n }\n if (parsedMessage.type === MessageType.RPC) {\n const response = parsedMessage as RPCResponse;\n const pending = this._pendingCalls.get(response.id);\n if (!pending) return;\n\n if (!response.success) {\n pending.reject(new Error(response.error));\n this._pendingCalls.delete(response.id);\n pending.stream?.onError?.(response.error);\n return;\n }\n\n // Handle streaming responses\n if (\"done\" in response) {\n if (response.done) {\n pending.resolve(response.result);\n this._pendingCalls.delete(response.id);\n pending.stream?.onDone?.(response.result);\n } else {\n pending.stream?.onChunk?.(response.result);\n }\n } else {\n // Non-streaming response\n pending.resolve(response.result);\n this._pendingCalls.delete(response.id);\n }\n }\n }\n });\n }\n\n setState(state: State) {\n this.send(JSON.stringify({ state, type: MessageType.CF_AGENT_STATE }));\n this.options.onStateUpdate?.(state, \"client\");\n }\n\n /**\n * Call a method on the Agent\n * @param method Name of the method to call\n * @param args Arguments to pass to the method\n * @param streamOptions Options for handling streaming responses\n * @returns Promise that resolves with the method's return value\n */\n call<T extends SerializableReturnValue>(\n method: string,\n args?: SerializableValue[],\n streamOptions?: StreamOptions\n ): Promise<T>;\n call<T = unknown>(\n method: string,\n args?: unknown[],\n streamOptions?: StreamOptions\n ): Promise<T>;\n async call<T>(\n method: string,\n args: unknown[] = [],\n streamOptions?: StreamOptions\n ): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const id = Math.random().toString(36).slice(2);\n this._pendingCalls.set(id, {\n reject,\n resolve: (value: unknown) => resolve(value as T),\n stream: streamOptions,\n type: null as T\n });\n\n const request: RPCRequest = {\n args,\n id,\n method,\n type: MessageType.RPC\n };\n\n this.send(JSON.stringify(request));\n });\n }\n}\n\n/**\n * Make an HTTP request to an Agent\n * @param opts Connection options\n * @param init Request initialization options\n * @returns Promise resolving to a Response\n */\nexport function agentFetch(opts: AgentClientFetchOptions, init?: RequestInit) {\n const agentNamespace = camelCaseToKebabCase(opts.agent);\n\n return PartySocket.fetch(\n {\n party: agentNamespace,\n prefix: \"agents\",\n room: opts.name || \"default\",\n ...opts\n },\n init\n );\n}\n"],"mappings":";;;;;;;;;AAyDA,SAAgB,qBAAqB,KAAqB;AAExD,KAAI,QAAQ,IAAI,aAAa,IAAI,QAAQ,IAAI,aAAa,CACxD,QAAO,IAAI,aAAa,CAAC,QAAQ,MAAM,IAAI;CAI7C,IAAI,aAAa,IAAI,QACnB,WACC,WAAW,IAAI,OAAO,aAAa,GACrC;AACD,cAAa,WAAW,WAAW,IAAI,GAAG,WAAW,MAAM,EAAE,GAAG;AAEhE,QAAO,WAAW,QAAQ,MAAM,IAAI,CAAC,QAAQ,MAAM,GAAG;;;;;AAMxD,IAAa,cAAb,cAAkD,YAAY;;;;CAI5D,OAAO,MAAM,OAA6C;AACxD,QAAM,IAAI,MACR,+DACD;;CAeH,YAAY,SAAoC;EAC9C,MAAM,iBAAiB,qBAAqB,QAAQ,MAAM;AAC1D,QAAM;GACJ,OAAO;GACP,QAAQ;GACR,MAAM,QAAQ,QAAQ;GACtB,GAAG;GACJ,CAAC;uCAjBoB,IAAI,KAQzB;AAUD,OAAK,QAAQ;AACb,OAAK,OAAO,QAAQ,QAAQ;AAC5B,OAAK,UAAU;AAEf,OAAK,iBAAiB,YAAY,UAAU;AAC1C,OAAI,OAAO,MAAM,SAAS,UAAU;IAClC,IAAIA;AACJ,QAAI;AACF,qBAAgB,KAAK,MAAM,MAAM,KAAK;aAC/B,QAAQ;AAGf;;AAEF,QAAI,cAAc,SAAS,YAAY,gBAAgB;AACrD,UAAK,QAAQ,gBAAgB,cAAc,OAAgB,SAAS;AACpE;;AAEF,QAAI,cAAc,SAAS,YAAY,KAAK;KAC1C,MAAM,WAAW;KACjB,MAAM,UAAU,KAAK,cAAc,IAAI,SAAS,GAAG;AACnD,SAAI,CAAC,QAAS;AAEd,SAAI,CAAC,SAAS,SAAS;AACrB,cAAQ,OAAO,IAAI,MAAM,SAAS,MAAM,CAAC;AACzC,WAAK,cAAc,OAAO,SAAS,GAAG;AACtC,cAAQ,QAAQ,UAAU,SAAS,MAAM;AACzC;;AAIF,SAAI,UAAU,SACZ,KAAI,SAAS,MAAM;AACjB,cAAQ,QAAQ,SAAS,OAAO;AAChC,WAAK,cAAc,OAAO,SAAS,GAAG;AACtC,cAAQ,QAAQ,SAAS,SAAS,OAAO;WAEzC,SAAQ,QAAQ,UAAU,SAAS,OAAO;UAEvC;AAEL,cAAQ,QAAQ,SAAS,OAAO;AAChC,WAAK,cAAc,OAAO,SAAS,GAAG;;;;IAI5C;;CAGJ,SAAS,OAAc;AACrB,OAAK,KAAK,KAAK,UAAU;GAAE;GAAO,MAAM,YAAY;GAAgB,CAAC,CAAC;AACtE,OAAK,QAAQ,gBAAgB,OAAO,SAAS;;CAoB/C,MAAM,KACJ,QACA,OAAkB,EAAE,EACpB,eACY;AACZ,SAAO,IAAI,SAAY,SAAS,WAAW;GACzC,MAAM,KAAK,KAAK,QAAQ,CAAC,SAAS,GAAG,CAAC,MAAM,EAAE;AAC9C,QAAK,cAAc,IAAI,IAAI;IACzB;IACA,UAAU,UAAmB,QAAQ,MAAW;IAChD,QAAQ;IACR,MAAM;IACP,CAAC;GAEF,MAAMC,UAAsB;IAC1B;IACA;IACA;IACA,MAAM,YAAY;IACnB;AAED,QAAK,KAAK,KAAK,UAAU,QAAQ,CAAC;IAClC;;;;;;;;;AAUN,SAAgB,WAAW,MAA+B,MAAoB;CAC5E,MAAM,iBAAiB,qBAAqB,KAAK,MAAM;AAEvD,QAAO,YAAY,MACjB;EACE,OAAO;EACP,QAAQ;EACR,MAAM,KAAK,QAAQ;EACnB,GAAG;EACJ,EACD,KACD"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
i as SerializableValue,
|
|
3
3
|
r as SerializableReturnValue
|
|
4
|
-
} from "./serializable-
|
|
4
|
+
} from "./serializable-faDkMCai.js";
|
|
5
5
|
import {
|
|
6
6
|
PartyFetchOptions,
|
|
7
7
|
PartySocket,
|
|
@@ -101,4 +101,4 @@ export {
|
|
|
101
101
|
AgentClientOptions as r,
|
|
102
102
|
AgentClient as t
|
|
103
103
|
};
|
|
104
|
-
//# sourceMappingURL=client-
|
|
104
|
+
//# sourceMappingURL=client-BAQA84dr.d.ts.map
|