agents 0.0.0-c552d8b → 0.0.0-c5abd5e
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 +22 -22
- package/dist/ai-chat-agent.d.ts +32 -5
- package/dist/ai-chat-agent.js +149 -115
- package/dist/ai-chat-agent.js.map +1 -1
- package/dist/ai-react.d.ts +18 -5
- package/dist/ai-react.js +28 -29
- package/dist/ai-react.js.map +1 -1
- package/dist/chunk-KUH345EY.js +116 -0
- package/dist/chunk-KUH345EY.js.map +1 -0
- package/dist/chunk-MFNGQLFL.js +1260 -0
- package/dist/chunk-MFNGQLFL.js.map +1 -0
- package/dist/{chunk-Q5ZBHY4Z.js → chunk-MW5BQ2FW.js} +49 -36
- package/dist/chunk-MW5BQ2FW.js.map +1 -0
- package/dist/chunk-PVQZBKN7.js +106 -0
- package/dist/chunk-PVQZBKN7.js.map +1 -0
- package/dist/client.d.ts +16 -2
- package/dist/client.js +6 -126
- package/dist/client.js.map +1 -1
- package/dist/index-BIJvkfYt.d.ts +614 -0
- package/dist/index.d.ts +33 -308
- package/dist/index.js +10 -3
- package/dist/mcp/client.d.ts +301 -23
- package/dist/mcp/client.js +1 -2
- package/dist/mcp/do-oauth-client-provider.d.ts +3 -3
- package/dist/mcp/do-oauth-client-provider.js +3 -103
- package/dist/mcp/do-oauth-client-provider.js.map +1 -1
- package/dist/mcp/index.d.ts +23 -13
- package/dist/mcp/index.js +150 -175
- package/dist/mcp/index.js.map +1 -1
- package/dist/observability/index.d.ts +12 -0
- package/dist/observability/index.js +10 -0
- package/dist/react.d.ts +85 -5
- package/dist/react.js +20 -8
- package/dist/react.js.map +1 -1
- package/dist/schedule.d.ts +6 -6
- package/dist/schedule.js +4 -6
- package/dist/schedule.js.map +1 -1
- package/dist/serializable.d.ts +32 -0
- package/dist/serializable.js +1 -0
- package/dist/serializable.js.map +1 -0
- package/package.json +76 -68
- package/src/index.ts +1068 -136
- package/dist/chunk-HMLY7DHA.js +0 -16
- package/dist/chunk-Q5ZBHY4Z.js.map +0 -1
- package/dist/chunk-WNIGPPNB.js +0 -608
- package/dist/chunk-WNIGPPNB.js.map +0 -1
- /package/dist/{chunk-HMLY7DHA.js.map → observability/index.js.map} +0 -0
package/dist/ai-react.d.ts
CHANGED
|
@@ -4,7 +4,19 @@ import { useChat } from "@ai-sdk/react";
|
|
|
4
4
|
import { useAgent } from "./react.js";
|
|
5
5
|
import "partysocket";
|
|
6
6
|
import "partysocket/react";
|
|
7
|
+
import "./index-BIJvkfYt.js";
|
|
8
|
+
import "@modelcontextprotocol/sdk/client/index.js";
|
|
9
|
+
import "@modelcontextprotocol/sdk/types.js";
|
|
10
|
+
import "partyserver";
|
|
11
|
+
import "./mcp/client.js";
|
|
12
|
+
import "zod";
|
|
13
|
+
import "@modelcontextprotocol/sdk/client/sse.js";
|
|
14
|
+
import "@modelcontextprotocol/sdk/shared/protocol.js";
|
|
15
|
+
import "./mcp/do-oauth-client-provider.js";
|
|
16
|
+
import "@modelcontextprotocol/sdk/client/auth.js";
|
|
17
|
+
import "@modelcontextprotocol/sdk/shared/auth.js";
|
|
7
18
|
import "./client.js";
|
|
19
|
+
import "./serializable.js";
|
|
8
20
|
|
|
9
21
|
type GetInitialMessagesOptions = {
|
|
10
22
|
agent: string;
|
|
@@ -33,15 +45,15 @@ type UseAgentChatOptions<State> = Omit<
|
|
|
33
45
|
declare function useAgentChat<State = unknown>(
|
|
34
46
|
options: UseAgentChatOptions<State>
|
|
35
47
|
): {
|
|
48
|
+
/**
|
|
49
|
+
* Clear chat history on both client and Agent
|
|
50
|
+
*/
|
|
51
|
+
clearHistory: () => void;
|
|
36
52
|
/**
|
|
37
53
|
* Set the chat messages and synchronize with the Agent
|
|
38
54
|
* @param messages New messages to set
|
|
39
55
|
*/
|
|
40
56
|
setMessages: (messages: Message[]) => void;
|
|
41
|
-
/**
|
|
42
|
-
* Clear chat history on both client and Agent
|
|
43
|
-
*/
|
|
44
|
-
clearHistory: () => void;
|
|
45
57
|
messages: ai.UIMessage[];
|
|
46
58
|
error: undefined | Error;
|
|
47
59
|
append: (
|
|
@@ -52,6 +64,7 @@ declare function useAgentChat<State = unknown>(
|
|
|
52
64
|
chatRequestOptions?: ai.ChatRequestOptions
|
|
53
65
|
) => Promise<string | null | undefined>;
|
|
54
66
|
stop: () => void;
|
|
67
|
+
experimental_resume: () => void;
|
|
55
68
|
input: string;
|
|
56
69
|
setInput: React.Dispatch<React.SetStateAction<string>>;
|
|
57
70
|
handleInputChange: (
|
|
@@ -78,7 +91,7 @@ declare function useAgentChat<State = unknown>(
|
|
|
78
91
|
id: string;
|
|
79
92
|
addToolResult: ({
|
|
80
93
|
toolCallId,
|
|
81
|
-
result
|
|
94
|
+
result
|
|
82
95
|
}: {
|
|
83
96
|
toolCallId: string;
|
|
84
97
|
result: any;
|
package/dist/ai-react.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import "./chunk-HMLY7DHA.js";
|
|
2
|
-
|
|
3
1
|
// src/ai-react.tsx
|
|
4
2
|
import { useChat } from "@ai-sdk/react";
|
|
5
|
-
import { use, useEffect } from "react";
|
|
6
3
|
import { nanoid } from "nanoid";
|
|
4
|
+
import { use, useEffect } from "react";
|
|
7
5
|
var requestCache = /* @__PURE__ */ new Map();
|
|
8
6
|
function useAgentChat(options) {
|
|
9
7
|
const { agent, getInitialMessages, ...rest } = options;
|
|
@@ -19,8 +17,8 @@ function useAgentChat(options) {
|
|
|
19
17
|
const getMessagesUrl = new URL(url);
|
|
20
18
|
getMessagesUrl.pathname += "/get-messages";
|
|
21
19
|
const response = await fetch(getMessagesUrl.toString(), {
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
credentials: options.credentials,
|
|
21
|
+
headers: options.headers
|
|
24
22
|
});
|
|
25
23
|
return response.json();
|
|
26
24
|
}
|
|
@@ -71,11 +69,12 @@ function useAgentChat(options) {
|
|
|
71
69
|
signal?.addEventListener("abort", () => {
|
|
72
70
|
agent.send(
|
|
73
71
|
JSON.stringify({
|
|
74
|
-
|
|
75
|
-
|
|
72
|
+
id,
|
|
73
|
+
type: "cf_agent_chat_request_cancel"
|
|
76
74
|
})
|
|
77
75
|
);
|
|
78
76
|
abortController.abort();
|
|
77
|
+
controller.close();
|
|
79
78
|
});
|
|
80
79
|
agent.addEventListener(
|
|
81
80
|
"message",
|
|
@@ -83,7 +82,7 @@ function useAgentChat(options) {
|
|
|
83
82
|
let data;
|
|
84
83
|
try {
|
|
85
84
|
data = JSON.parse(event.data);
|
|
86
|
-
} catch (
|
|
85
|
+
} catch (_error) {
|
|
87
86
|
return;
|
|
88
87
|
}
|
|
89
88
|
if (data.type === "cf_agent_use_chat_response") {
|
|
@@ -106,32 +105,32 @@ function useAgentChat(options) {
|
|
|
106
105
|
});
|
|
107
106
|
agent.send(
|
|
108
107
|
JSON.stringify({
|
|
109
|
-
type: "cf_agent_use_chat_request",
|
|
110
108
|
id,
|
|
111
|
-
url: request.toString(),
|
|
112
109
|
init: {
|
|
113
|
-
method,
|
|
114
|
-
keepalive,
|
|
115
|
-
headers,
|
|
116
110
|
body,
|
|
117
|
-
redirect,
|
|
118
|
-
integrity,
|
|
119
111
|
credentials,
|
|
112
|
+
headers,
|
|
113
|
+
integrity,
|
|
114
|
+
keepalive,
|
|
115
|
+
method,
|
|
120
116
|
mode,
|
|
117
|
+
redirect,
|
|
121
118
|
referrer,
|
|
122
119
|
referrerPolicy,
|
|
123
120
|
window
|
|
124
121
|
// dispatcher,
|
|
125
122
|
// duplex
|
|
126
|
-
}
|
|
123
|
+
},
|
|
124
|
+
type: "cf_agent_use_chat_request",
|
|
125
|
+
url: request.toString()
|
|
127
126
|
})
|
|
128
127
|
);
|
|
129
128
|
return new Response(stream);
|
|
130
129
|
}
|
|
131
130
|
const useChatHelpers = useChat({
|
|
131
|
+
fetch: aiFetch,
|
|
132
132
|
initialMessages,
|
|
133
133
|
sendExtraMessageFields: true,
|
|
134
|
-
fetch: aiFetch,
|
|
135
134
|
...rest
|
|
136
135
|
});
|
|
137
136
|
useEffect(() => {
|
|
@@ -142,7 +141,7 @@ function useAgentChat(options) {
|
|
|
142
141
|
let data;
|
|
143
142
|
try {
|
|
144
143
|
data = JSON.parse(event.data);
|
|
145
|
-
} catch (
|
|
144
|
+
} catch (_error) {
|
|
146
145
|
return;
|
|
147
146
|
}
|
|
148
147
|
if (data.type === "cf_agent_chat_clear") {
|
|
@@ -156,7 +155,7 @@ function useAgentChat(options) {
|
|
|
156
155
|
let data;
|
|
157
156
|
try {
|
|
158
157
|
data = JSON.parse(event.data);
|
|
159
|
-
} catch (
|
|
158
|
+
} catch (_error) {
|
|
160
159
|
return;
|
|
161
160
|
}
|
|
162
161
|
if (data.type === "cf_agent_chat_messages") {
|
|
@@ -173,26 +172,26 @@ function useAgentChat(options) {
|
|
|
173
172
|
return {
|
|
174
173
|
...useChatHelpers,
|
|
175
174
|
/**
|
|
176
|
-
*
|
|
177
|
-
* @param messages New messages to set
|
|
175
|
+
* Clear chat history on both client and Agent
|
|
178
176
|
*/
|
|
179
|
-
|
|
180
|
-
useChatHelpers.setMessages(
|
|
177
|
+
clearHistory: () => {
|
|
178
|
+
useChatHelpers.setMessages([]);
|
|
181
179
|
agent.send(
|
|
182
180
|
JSON.stringify({
|
|
183
|
-
type: "
|
|
184
|
-
messages
|
|
181
|
+
type: "cf_agent_chat_clear"
|
|
185
182
|
})
|
|
186
183
|
);
|
|
187
184
|
},
|
|
188
185
|
/**
|
|
189
|
-
*
|
|
186
|
+
* Set the chat messages and synchronize with the Agent
|
|
187
|
+
* @param messages New messages to set
|
|
190
188
|
*/
|
|
191
|
-
|
|
192
|
-
useChatHelpers.setMessages(
|
|
189
|
+
setMessages: (messages) => {
|
|
190
|
+
useChatHelpers.setMessages(messages);
|
|
193
191
|
agent.send(
|
|
194
192
|
JSON.stringify({
|
|
195
|
-
|
|
193
|
+
messages,
|
|
194
|
+
type: "cf_agent_chat_messages"
|
|
196
195
|
})
|
|
197
196
|
);
|
|
198
197
|
}
|
package/dist/ai-react.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/ai-react.tsx"],"sourcesContent":["import { useChat } from \"@ai-sdk/react\";\nimport type { Message } from \"ai\";\nimport { use, useEffect } from \"react\";\nimport type { OutgoingMessage } from \"./ai-types\";\nimport type { useAgent } from \"./react\";\nimport { nanoid } from \"nanoid\";\n\ntype GetInitialMessagesOptions = {\n agent: string;\n name: string;\n url: string;\n};\n\n/**\n * Options for the useAgentChat hook\n */\ntype UseAgentChatOptions<State> = Omit<\n Parameters<typeof useChat>[0] & {\n /** Agent connection from useAgent */\n agent: ReturnType<typeof useAgent<State>>;\n getInitialMessages?:\n | undefined\n | null\n // | (() => Message[])\n | ((options: GetInitialMessagesOptions) => Promise<Message[]>);\n },\n \"fetch\"\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 */\nexport function useAgentChat<State = unknown>(\n options: UseAgentChatOptions<State>\n) {\n const { agent, getInitialMessages, ...rest } = options;\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 // delete the _pk query param\n agentUrl.searchParams.delete(\"_pk\");\n const agentUrlString = agentUrl.toString();\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 headers: options.headers,\n credentials: options.credentials,\n });\n return response.json<Message[]>();\n }\n\n const getInitialMessagesFetch =\n getInitialMessages || defaultGetInitialMessagesFetch;\n\n function doGetInitialMessages(\n getInitialMessagesOptions: GetInitialMessagesOptions\n ) {\n if (requestCache.has(agentUrlString)) {\n return requestCache.get(agentUrlString)!;\n }\n const promise = getInitialMessagesFetch(getInitialMessagesOptions);\n // immediately cache the promise so that we don't\n // create multiple requests for the same agent during multiple\n // concurrent renders\n requestCache.set(agentUrlString, promise);\n return promise;\n }\n\n const initialMessagesPromise =\n getInitialMessages === null\n ? null\n : doGetInitialMessages({\n agent: agent.agent,\n name: agent.name,\n url: agentUrlString,\n });\n const initialMessages = initialMessagesPromise\n ? use(initialMessagesPromise)\n : (rest.initialMessages ?? []);\n\n // manages adding and removing the promise from the cache\n useEffect(() => {\n if (!initialMessagesPromise) {\n return;\n }\n // this effect is responsible for removing the promise from the cache\n // when the component unmounts or the promise changes,\n // but that means it also must add the promise to the cache\n // so that multiple arbitrary effect runs produce the expected state\n // when resolved.\n requestCache.set(agentUrlString, initialMessagesPromise!);\n return () => {\n if (requestCache.get(agentUrlString) === initialMessagesPromise) {\n requestCache.delete(agentUrlString);\n }\n };\n }, [agentUrlString, initialMessagesPromise]);\n\n async function aiFetch(\n request: RequestInfo | URL,\n options: RequestInit = {}\n ) {\n // we're going to use a websocket to do the actual \"fetching\"\n // but still satisfy the type signature of the fetch function\n // so we'll return a promise that resolves to a response\n\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 // dispatcher, duplex\n } = options;\n const id = nanoid(8);\n const abortController = new AbortController();\n\n signal?.addEventListener(\"abort\", () => {\n // Propagate request cancellation to the Agent\n // We need to communciate cancellation as a websocket message, instead of a request signal\n agent.send(\n JSON.stringify({\n type: \"cf_agent_chat_request_cancel\",\n id,\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: \"cf_agent_chat_messages\",\n // messages: ... /* some way of getting current messages ref? */\n // }))\n\n abortController.abort();\n });\n\n agent.addEventListener(\n \"message\",\n (event) => {\n let data: OutgoingMessage;\n try {\n data = JSON.parse(event.data) as OutgoingMessage;\n } catch (error) {\n // silently ignore invalid messages for now\n // TODO: log errors with log levels\n return;\n }\n if (data.type === \"cf_agent_use_chat_response\") {\n if (data.id === id) {\n controller.enqueue(new TextEncoder().encode(data.body));\n if (data.done) {\n controller.close();\n abortController.abort();\n }\n }\n }\n },\n { signal: abortController.signal }\n );\n\n let controller: ReadableStreamDefaultController;\n\n const stream = new ReadableStream({\n start(c) {\n controller = c;\n },\n });\n\n agent.send(\n JSON.stringify({\n type: \"cf_agent_use_chat_request\",\n id,\n url: request.toString(),\n init: {\n method,\n keepalive,\n headers,\n body,\n redirect,\n integrity,\n credentials,\n mode,\n referrer,\n referrerPolicy,\n window,\n // dispatcher,\n // duplex\n },\n })\n );\n\n return new Response(stream);\n }\n const useChatHelpers = useChat({\n initialMessages,\n sendExtraMessageFields: true,\n fetch: aiFetch,\n ...rest,\n });\n\n useEffect(() => {\n function onClearHistory(event: MessageEvent) {\n if (typeof event.data !== \"string\") {\n return;\n }\n let data: OutgoingMessage;\n try {\n data = JSON.parse(event.data) as OutgoingMessage;\n } catch (error) {\n // silently ignore invalid messages for now\n // TODO: log errors with log levels\n return;\n }\n if (data.type === \"cf_agent_chat_clear\") {\n useChatHelpers.setMessages([]);\n }\n }\n\n function onMessages(event: MessageEvent) {\n if (typeof event.data !== \"string\") {\n return;\n }\n let data: OutgoingMessage;\n try {\n data = JSON.parse(event.data) as OutgoingMessage;\n } catch (error) {\n // silently ignore invalid messages for now\n // TODO: log errors with log levels\n return;\n }\n if (data.type === \"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 return {\n ...useChatHelpers,\n /**\n * Set the chat messages and synchronize with the Agent\n * @param messages New messages to set\n */\n setMessages: (messages: Message[]) => {\n useChatHelpers.setMessages(messages);\n agent.send(\n JSON.stringify({\n type: \"cf_agent_chat_messages\",\n messages,\n })\n );\n },\n /**\n * Clear chat history on both client and Agent\n */\n clearHistory: () => {\n useChatHelpers.setMessages([]);\n agent.send(\n JSON.stringify({\n type: \"cf_agent_chat_clear\",\n })\n );\n },\n };\n}\n"],"mappings":"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","names":["options"]}
|
|
1
|
+
{"version":3,"sources":["../src/ai-react.tsx"],"sourcesContent":["import { useChat } from \"@ai-sdk/react\";\nimport type { Message } from \"ai\";\nimport { nanoid } from \"nanoid\";\nimport { use, useEffect } from \"react\";\nimport type { OutgoingMessage } from \"./ai-types\";\nimport type { useAgent } from \"./react\";\n\ntype GetInitialMessagesOptions = {\n agent: string;\n name: string;\n url: string;\n};\n\n/**\n * Options for the useAgentChat hook\n */\ntype UseAgentChatOptions<State> = Omit<\n Parameters<typeof useChat>[0] & {\n /** Agent connection from useAgent */\n agent: ReturnType<typeof useAgent<State>>;\n getInitialMessages?:\n | undefined\n | null\n // | (() => Message[])\n | ((options: GetInitialMessagesOptions) => Promise<Message[]>);\n },\n \"fetch\"\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 */\nexport function useAgentChat<State = unknown>(\n options: UseAgentChatOptions<State>\n) {\n const { agent, getInitialMessages, ...rest } = options;\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 // delete the _pk query param\n agentUrl.searchParams.delete(\"_pk\");\n const agentUrlString = agentUrl.toString();\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 return response.json<Message[]>();\n }\n\n const getInitialMessagesFetch =\n getInitialMessages || defaultGetInitialMessagesFetch;\n\n function doGetInitialMessages(\n getInitialMessagesOptions: GetInitialMessagesOptions\n ) {\n if (requestCache.has(agentUrlString)) {\n return requestCache.get(agentUrlString)!;\n }\n const promise = getInitialMessagesFetch(getInitialMessagesOptions);\n // immediately cache the promise so that we don't\n // create multiple requests for the same agent during multiple\n // concurrent renders\n requestCache.set(agentUrlString, promise);\n return promise;\n }\n\n const initialMessagesPromise =\n getInitialMessages === null\n ? null\n : doGetInitialMessages({\n agent: agent.agent,\n name: agent.name,\n url: agentUrlString\n });\n const initialMessages = initialMessagesPromise\n ? use(initialMessagesPromise)\n : (rest.initialMessages ?? []);\n\n // manages adding and removing the promise from the cache\n useEffect(() => {\n if (!initialMessagesPromise) {\n return;\n }\n // this effect is responsible for removing the promise from the cache\n // when the component unmounts or the promise changes,\n // but that means it also must add the promise to the cache\n // so that multiple arbitrary effect runs produce the expected state\n // when resolved.\n requestCache.set(agentUrlString, initialMessagesPromise!);\n return () => {\n if (requestCache.get(agentUrlString) === initialMessagesPromise) {\n requestCache.delete(agentUrlString);\n }\n };\n }, [agentUrlString, initialMessagesPromise]);\n\n async function aiFetch(\n request: RequestInfo | URL,\n options: RequestInit = {}\n ) {\n // we're going to use a websocket to do the actual \"fetching\"\n // but still satisfy the type signature of the fetch function\n // so we'll return a promise that resolves to a response\n\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 // dispatcher, duplex\n } = options;\n const id = nanoid(8);\n const abortController = new AbortController();\n\n signal?.addEventListener(\"abort\", () => {\n // Propagate request cancellation to the Agent\n // We need to communciate cancellation as a websocket message, instead of a request signal\n agent.send(\n JSON.stringify({\n id,\n type: \"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: \"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 agent.addEventListener(\n \"message\",\n (event) => {\n let data: OutgoingMessage;\n try {\n data = JSON.parse(event.data) as OutgoingMessage;\n } catch (_error) {\n // silently ignore invalid messages for now\n // TODO: log errors with log levels\n return;\n }\n if (data.type === \"cf_agent_use_chat_response\") {\n if (data.id === id) {\n controller.enqueue(new TextEncoder().encode(data.body));\n if (data.done) {\n controller.close();\n abortController.abort();\n }\n }\n }\n },\n { signal: abortController.signal }\n );\n\n let controller: ReadableStreamDefaultController;\n\n const stream = new ReadableStream({\n start(c) {\n controller = c;\n }\n });\n\n agent.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 // dispatcher,\n // duplex\n },\n type: \"cf_agent_use_chat_request\",\n url: request.toString()\n })\n );\n\n return new Response(stream);\n }\n const useChatHelpers = useChat({\n fetch: aiFetch,\n initialMessages,\n sendExtraMessageFields: true,\n ...rest\n });\n\n useEffect(() => {\n function onClearHistory(event: MessageEvent) {\n if (typeof event.data !== \"string\") {\n return;\n }\n let data: OutgoingMessage;\n try {\n data = JSON.parse(event.data) as OutgoingMessage;\n } catch (_error) {\n // silently ignore invalid messages for now\n // TODO: log errors with log levels\n return;\n }\n if (data.type === \"cf_agent_chat_clear\") {\n useChatHelpers.setMessages([]);\n }\n }\n\n function onMessages(event: MessageEvent) {\n if (typeof event.data !== \"string\") {\n return;\n }\n let data: OutgoingMessage;\n try {\n data = JSON.parse(event.data) as OutgoingMessage;\n } catch (_error) {\n // silently ignore invalid messages for now\n // TODO: log errors with log levels\n return;\n }\n if (data.type === \"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 return {\n ...useChatHelpers,\n /**\n * Clear chat history on both client and Agent\n */\n clearHistory: () => {\n useChatHelpers.setMessages([]);\n agent.send(\n JSON.stringify({\n type: \"cf_agent_chat_clear\"\n })\n );\n },\n /**\n * Set the chat messages and synchronize with the Agent\n * @param messages New messages to set\n */\n setMessages: (messages: Message[]) => {\n useChatHelpers.setMessages(messages);\n agent.send(\n JSON.stringify({\n messages,\n type: \"cf_agent_chat_messages\"\n })\n );\n }\n };\n}\n"],"mappings":"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","names":["options"]}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
// src/client.ts
|
|
2
|
+
import {
|
|
3
|
+
PartySocket
|
|
4
|
+
} from "partysocket";
|
|
5
|
+
function camelCaseToKebabCase(str) {
|
|
6
|
+
if (str === str.toUpperCase() && str !== str.toLowerCase()) {
|
|
7
|
+
return str.toLowerCase().replace(/_/g, "-");
|
|
8
|
+
}
|
|
9
|
+
let kebabified = str.replace(
|
|
10
|
+
/[A-Z]/g,
|
|
11
|
+
(letter) => `-${letter.toLowerCase()}`
|
|
12
|
+
);
|
|
13
|
+
kebabified = kebabified.startsWith("-") ? kebabified.slice(1) : kebabified;
|
|
14
|
+
return kebabified.replace(/_/g, "-").replace(/-$/, "");
|
|
15
|
+
}
|
|
16
|
+
var AgentClient = class extends PartySocket {
|
|
17
|
+
constructor(options) {
|
|
18
|
+
const agentNamespace = camelCaseToKebabCase(options.agent);
|
|
19
|
+
super({
|
|
20
|
+
party: agentNamespace,
|
|
21
|
+
prefix: "agents",
|
|
22
|
+
room: options.name || "default",
|
|
23
|
+
...options
|
|
24
|
+
});
|
|
25
|
+
this._pendingCalls = /* @__PURE__ */ new Map();
|
|
26
|
+
this.agent = agentNamespace;
|
|
27
|
+
this.name = options.name || "default";
|
|
28
|
+
this.options = options;
|
|
29
|
+
this.addEventListener("message", (event) => {
|
|
30
|
+
if (typeof event.data === "string") {
|
|
31
|
+
let parsedMessage;
|
|
32
|
+
try {
|
|
33
|
+
parsedMessage = JSON.parse(event.data);
|
|
34
|
+
} catch (_error) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
if (parsedMessage.type === "cf_agent_state") {
|
|
38
|
+
this.options.onStateUpdate?.(parsedMessage.state, "server");
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (parsedMessage.type === "rpc") {
|
|
42
|
+
const response = parsedMessage;
|
|
43
|
+
const pending = this._pendingCalls.get(response.id);
|
|
44
|
+
if (!pending) return;
|
|
45
|
+
if (!response.success) {
|
|
46
|
+
pending.reject(new Error(response.error));
|
|
47
|
+
this._pendingCalls.delete(response.id);
|
|
48
|
+
pending.stream?.onError?.(response.error);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if ("done" in response) {
|
|
52
|
+
if (response.done) {
|
|
53
|
+
pending.resolve(response.result);
|
|
54
|
+
this._pendingCalls.delete(response.id);
|
|
55
|
+
pending.stream?.onDone?.(response.result);
|
|
56
|
+
} else {
|
|
57
|
+
pending.stream?.onChunk?.(response.result);
|
|
58
|
+
}
|
|
59
|
+
} else {
|
|
60
|
+
pending.resolve(response.result);
|
|
61
|
+
this._pendingCalls.delete(response.id);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* @deprecated Use agentFetch instead
|
|
69
|
+
*/
|
|
70
|
+
static fetch(_opts) {
|
|
71
|
+
throw new Error(
|
|
72
|
+
"AgentClient.fetch is not implemented, use agentFetch instead"
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
setState(state) {
|
|
76
|
+
this.send(JSON.stringify({ state, type: "cf_agent_state" }));
|
|
77
|
+
this.options.onStateUpdate?.(state, "client");
|
|
78
|
+
}
|
|
79
|
+
async call(method, args = [], streamOptions) {
|
|
80
|
+
return new Promise((resolve, reject) => {
|
|
81
|
+
const id = Math.random().toString(36).slice(2);
|
|
82
|
+
this._pendingCalls.set(id, {
|
|
83
|
+
reject,
|
|
84
|
+
resolve: (value) => resolve(value),
|
|
85
|
+
stream: streamOptions,
|
|
86
|
+
type: null
|
|
87
|
+
});
|
|
88
|
+
const request = {
|
|
89
|
+
args,
|
|
90
|
+
id,
|
|
91
|
+
method,
|
|
92
|
+
type: "rpc"
|
|
93
|
+
};
|
|
94
|
+
this.send(JSON.stringify(request));
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
function agentFetch(opts, init) {
|
|
99
|
+
const agentNamespace = camelCaseToKebabCase(opts.agent);
|
|
100
|
+
return PartySocket.fetch(
|
|
101
|
+
{
|
|
102
|
+
party: agentNamespace,
|
|
103
|
+
prefix: "agents",
|
|
104
|
+
room: opts.name || "default",
|
|
105
|
+
...opts
|
|
106
|
+
},
|
|
107
|
+
init
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export {
|
|
112
|
+
camelCaseToKebabCase,
|
|
113
|
+
AgentClient,
|
|
114
|
+
agentFetch
|
|
115
|
+
};
|
|
116
|
+
//# sourceMappingURL=chunk-KUH345EY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"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\";\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 === \"cf_agent_state\") {\n this.options.onStateUpdate?.(parsedMessage.state as State, \"server\");\n return;\n }\n if (parsedMessage.type === \"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: \"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: \"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":"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","names":[]}
|