agents 0.0.0-33ff003 → 0.0.0-352d62c

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.
Files changed (50) hide show
  1. package/README.md +131 -25
  2. package/dist/ai-chat-agent.d.ts +10 -5
  3. package/dist/ai-chat-agent.js +75 -42
  4. package/dist/ai-chat-agent.js.map +1 -1
  5. package/dist/ai-react.d.ts +14 -9
  6. package/dist/ai-react.js +31 -31
  7. package/dist/ai-react.js.map +1 -1
  8. package/dist/ai-types.d.ts +27 -9
  9. package/dist/ai-types.js +6 -0
  10. package/dist/chunk-EEKLJYON.js +17 -0
  11. package/dist/chunk-EEKLJYON.js.map +1 -0
  12. package/dist/{chunk-Y67CHZBI.js → chunk-EM3J4KV7.js} +168 -34
  13. package/dist/chunk-EM3J4KV7.js.map +1 -0
  14. package/dist/chunk-ID62XSAS.js +1290 -0
  15. package/dist/chunk-ID62XSAS.js.map +1 -0
  16. package/dist/{chunk-BZXOAZUX.js → chunk-PVQZBKN7.js} +5 -5
  17. package/dist/chunk-PVQZBKN7.js.map +1 -0
  18. package/dist/{chunk-QSGN3REV.js → chunk-QEVM4BVL.js} +10 -17
  19. package/dist/chunk-QEVM4BVL.js.map +1 -0
  20. package/dist/client-DgyzBU_8.d.ts +4601 -0
  21. package/dist/client.d.ts +8 -2
  22. package/dist/client.js +2 -2
  23. package/dist/index.d.ts +192 -19
  24. package/dist/index.js +11 -5
  25. package/dist/mcp/client.d.ts +9 -781
  26. package/dist/mcp/client.js +1 -2
  27. package/dist/mcp/do-oauth-client-provider.js +1 -2
  28. package/dist/mcp/index.d.ts +38 -10
  29. package/dist/mcp/index.js +238 -62
  30. package/dist/mcp/index.js.map +1 -1
  31. package/dist/observability/index.d.ts +46 -0
  32. package/dist/observability/index.js +11 -0
  33. package/dist/react.d.ts +81 -11
  34. package/dist/react.js +20 -10
  35. package/dist/react.js.map +1 -1
  36. package/dist/schedule.d.ts +6 -6
  37. package/dist/schedule.js +4 -6
  38. package/dist/schedule.js.map +1 -1
  39. package/dist/serializable.d.ts +32 -0
  40. package/dist/serializable.js +1 -0
  41. package/dist/serializable.js.map +1 -0
  42. package/package.json +79 -71
  43. package/src/index.ts +865 -187
  44. package/dist/chunk-BZXOAZUX.js.map +0 -1
  45. package/dist/chunk-NOUFNU2O.js +0 -12
  46. package/dist/chunk-NPGUKHFR.js +0 -773
  47. package/dist/chunk-NPGUKHFR.js.map +0 -1
  48. package/dist/chunk-QSGN3REV.js.map +0 -1
  49. package/dist/chunk-Y67CHZBI.js.map +0 -1
  50. /package/dist/{chunk-NOUFNU2O.js.map → observability/index.js.map} +0 -0
package/dist/ai-react.js CHANGED
@@ -1,9 +1,9 @@
1
- import "./chunk-NOUFNU2O.js";
1
+ import "./chunk-EEKLJYON.js";
2
2
 
3
3
  // src/ai-react.tsx
4
4
  import { useChat } from "@ai-sdk/react";
5
- import { use, useEffect } from "react";
6
5
  import { nanoid } from "nanoid";
6
+ import { use, useEffect } from "react";
7
7
  var requestCache = /* @__PURE__ */ new Map();
8
8
  function useAgentChat(options) {
9
9
  const { agent, getInitialMessages, ...rest } = options;
@@ -19,8 +19,8 @@ function useAgentChat(options) {
19
19
  const getMessagesUrl = new URL(url);
20
20
  getMessagesUrl.pathname += "/get-messages";
21
21
  const response = await fetch(getMessagesUrl.toString(), {
22
- headers: options.headers,
23
- credentials: options.credentials
22
+ credentials: options.credentials,
23
+ headers: options.headers
24
24
  });
25
25
  return response.json();
26
26
  }
@@ -71,8 +71,8 @@ function useAgentChat(options) {
71
71
  signal?.addEventListener("abort", () => {
72
72
  agent.send(
73
73
  JSON.stringify({
74
- type: "cf_agent_chat_request_cancel",
75
- id
74
+ id,
75
+ type: "cf_agent_chat_request_cancel" /* CF_AGENT_CHAT_REQUEST_CANCEL */
76
76
  })
77
77
  );
78
78
  abortController.abort();
@@ -84,10 +84,10 @@ function useAgentChat(options) {
84
84
  let data;
85
85
  try {
86
86
  data = JSON.parse(event.data);
87
- } catch (error) {
87
+ } catch (_error) {
88
88
  return;
89
89
  }
90
- if (data.type === "cf_agent_use_chat_response") {
90
+ if (data.type === "cf_agent_use_chat_response" /* CF_AGENT_USE_CHAT_RESPONSE */) {
91
91
  if (data.id === id) {
92
92
  controller.enqueue(new TextEncoder().encode(data.body));
93
93
  if (data.done) {
@@ -107,32 +107,32 @@ function useAgentChat(options) {
107
107
  });
108
108
  agent.send(
109
109
  JSON.stringify({
110
- type: "cf_agent_use_chat_request",
111
110
  id,
112
- url: request.toString(),
113
111
  init: {
114
- method,
115
- keepalive,
116
- headers,
117
112
  body,
118
- redirect,
119
- integrity,
120
113
  credentials,
114
+ headers,
115
+ integrity,
116
+ keepalive,
117
+ method,
121
118
  mode,
119
+ redirect,
122
120
  referrer,
123
121
  referrerPolicy,
124
122
  window
125
123
  // dispatcher,
126
124
  // duplex
127
- }
125
+ },
126
+ type: "cf_agent_use_chat_request" /* CF_AGENT_USE_CHAT_REQUEST */,
127
+ url: request.toString()
128
128
  })
129
129
  );
130
130
  return new Response(stream);
131
131
  }
132
132
  const useChatHelpers = useChat({
133
+ fetch: aiFetch,
133
134
  initialMessages,
134
135
  sendExtraMessageFields: true,
135
- fetch: aiFetch,
136
136
  ...rest
137
137
  });
138
138
  useEffect(() => {
@@ -143,10 +143,10 @@ function useAgentChat(options) {
143
143
  let data;
144
144
  try {
145
145
  data = JSON.parse(event.data);
146
- } catch (error) {
146
+ } catch (_error) {
147
147
  return;
148
148
  }
149
- if (data.type === "cf_agent_chat_clear") {
149
+ if (data.type === "cf_agent_chat_clear" /* CF_AGENT_CHAT_CLEAR */) {
150
150
  useChatHelpers.setMessages([]);
151
151
  }
152
152
  }
@@ -157,10 +157,10 @@ function useAgentChat(options) {
157
157
  let data;
158
158
  try {
159
159
  data = JSON.parse(event.data);
160
- } catch (error) {
160
+ } catch (_error) {
161
161
  return;
162
162
  }
163
- if (data.type === "cf_agent_chat_messages") {
163
+ if (data.type === "cf_agent_chat_messages" /* CF_AGENT_CHAT_MESSAGES */) {
164
164
  useChatHelpers.setMessages(data.messages);
165
165
  }
166
166
  }
@@ -174,26 +174,26 @@ function useAgentChat(options) {
174
174
  return {
175
175
  ...useChatHelpers,
176
176
  /**
177
- * Set the chat messages and synchronize with the Agent
178
- * @param messages New messages to set
177
+ * Clear chat history on both client and Agent
179
178
  */
180
- setMessages: (messages) => {
181
- useChatHelpers.setMessages(messages);
179
+ clearHistory: () => {
180
+ useChatHelpers.setMessages([]);
182
181
  agent.send(
183
182
  JSON.stringify({
184
- type: "cf_agent_chat_messages",
185
- messages
183
+ type: "cf_agent_chat_clear" /* CF_AGENT_CHAT_CLEAR */
186
184
  })
187
185
  );
188
186
  },
189
187
  /**
190
- * Clear chat history on both client and Agent
188
+ * Set the chat messages and synchronize with the Agent
189
+ * @param messages New messages to set
191
190
  */
192
- clearHistory: () => {
193
- useChatHelpers.setMessages([]);
191
+ setMessages: (messages) => {
192
+ useChatHelpers.setMessages(messages);
194
193
  agent.send(
195
194
  JSON.stringify({
196
- type: "cf_agent_chat_clear"
195
+ messages,
196
+ type: "cf_agent_chat_messages" /* CF_AGENT_CHAT_MESSAGES */
197
197
  })
198
198
  );
199
199
  }
@@ -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 // 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 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 { MessageType, 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: 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: \"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 === MessageType.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: MessageType.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 === MessageType.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 === 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 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: MessageType.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: MessageType.CF_AGENT_CHAT_MESSAGES\n })\n );\n }\n };\n}\n"],"mappings":"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","names":["options"]}
@@ -1,18 +1,36 @@
1
1
  import { Message } from "ai";
2
2
 
3
+ /**
4
+ * Enum for message types used in Agent communication
5
+ */
6
+ declare enum MessageType {
7
+ /** Indicates this message contains updated chat messages */
8
+ CF_AGENT_CHAT_MESSAGES = "cf_agent_chat_messages",
9
+ /** Indicates this message is a response to a chat request */
10
+ CF_AGENT_USE_CHAT_RESPONSE = "cf_agent_use_chat_response",
11
+ /** Indicates this message is a command to clear chat history */
12
+ CF_AGENT_CHAT_CLEAR = "cf_agent_chat_clear",
13
+ /** Indicates this message is a request to the chat API */
14
+ CF_AGENT_USE_CHAT_REQUEST = "cf_agent_use_chat_request",
15
+ /** Indicates the user wants to stop generation of this message */
16
+ CF_AGENT_CHAT_REQUEST_CANCEL = "cf_agent_chat_request_cancel",
17
+ CF_AGENT_MCP_SERVERS = "cf_agent_mcp_servers",
18
+ CF_AGENT_STATE = "cf_agent_state",
19
+ RPC = "rpc"
20
+ }
3
21
  /**
4
22
  * Types of messages sent from the Agent to clients
5
23
  */
6
24
  type OutgoingMessage =
7
25
  | {
8
26
  /** Indicates this message contains updated chat messages */
9
- type: "cf_agent_chat_messages";
27
+ type: MessageType.CF_AGENT_CHAT_MESSAGES;
10
28
  /** Array of chat messages */
11
29
  messages: Message[];
12
30
  }
13
31
  | {
14
32
  /** Indicates this message is a response to a chat request */
15
- type: "cf_agent_use_chat_response";
33
+ type: MessageType.CF_AGENT_USE_CHAT_RESPONSE;
16
34
  /** Unique ID of the request this response corresponds to */
17
35
  id: string;
18
36
  /** Content body of the response */
@@ -22,13 +40,13 @@ type OutgoingMessage =
22
40
  }
23
41
  | {
24
42
  /** Indicates this message contains updated chat messages */
25
- type: "cf_agent_chat_messages";
43
+ type: MessageType.CF_AGENT_CHAT_MESSAGES;
26
44
  /** Array of chat messages */
27
45
  messages: Message[];
28
46
  }
29
47
  | {
30
48
  /** Indicates this message is a command to clear chat history */
31
- type: "cf_agent_chat_clear";
49
+ type: MessageType.CF_AGENT_CHAT_CLEAR;
32
50
  };
33
51
  /**
34
52
  * Types of messages sent from clients to the Agent
@@ -36,7 +54,7 @@ type OutgoingMessage =
36
54
  type IncomingMessage =
37
55
  | {
38
56
  /** Indicates this message is a request to the chat API */
39
- type: "cf_agent_use_chat_request";
57
+ type: MessageType.CF_AGENT_USE_CHAT_REQUEST;
40
58
  /** Unique ID for this request */
41
59
  id: string;
42
60
  /** Request initialization options */
@@ -57,18 +75,18 @@ type IncomingMessage =
57
75
  }
58
76
  | {
59
77
  /** Indicates this message is a command to clear chat history */
60
- type: "cf_agent_chat_clear";
78
+ type: MessageType.CF_AGENT_CHAT_CLEAR;
61
79
  }
62
80
  | {
63
81
  /** Indicates this message contains updated chat messages */
64
- type: "cf_agent_chat_messages";
82
+ type: MessageType.CF_AGENT_CHAT_MESSAGES;
65
83
  /** Array of chat messages */
66
84
  messages: Message[];
67
85
  }
68
86
  | {
69
87
  /** Indicates the user wants to stop generation of this message */
70
- type: "cf_agent_chat_request_cancel";
88
+ type: MessageType.CF_AGENT_CHAT_REQUEST_CANCEL;
71
89
  id: string;
72
90
  };
73
91
 
74
- export type { IncomingMessage, OutgoingMessage };
92
+ export { type IncomingMessage, MessageType, type OutgoingMessage };
package/dist/ai-types.js CHANGED
@@ -1 +1,7 @@
1
+ import {
2
+ MessageType
3
+ } from "./chunk-EEKLJYON.js";
4
+ export {
5
+ MessageType
6
+ };
1
7
  //# sourceMappingURL=ai-types.js.map
@@ -0,0 +1,17 @@
1
+ // src/ai-types.ts
2
+ var MessageType = /* @__PURE__ */ ((MessageType2) => {
3
+ MessageType2["CF_AGENT_CHAT_MESSAGES"] = "cf_agent_chat_messages";
4
+ MessageType2["CF_AGENT_USE_CHAT_RESPONSE"] = "cf_agent_use_chat_response";
5
+ MessageType2["CF_AGENT_CHAT_CLEAR"] = "cf_agent_chat_clear";
6
+ MessageType2["CF_AGENT_USE_CHAT_REQUEST"] = "cf_agent_use_chat_request";
7
+ MessageType2["CF_AGENT_CHAT_REQUEST_CANCEL"] = "cf_agent_chat_request_cancel";
8
+ MessageType2["CF_AGENT_MCP_SERVERS"] = "cf_agent_mcp_servers";
9
+ MessageType2["CF_AGENT_STATE"] = "cf_agent_state";
10
+ MessageType2["RPC"] = "rpc";
11
+ return MessageType2;
12
+ })(MessageType || {});
13
+
14
+ export {
15
+ MessageType
16
+ };
17
+ //# sourceMappingURL=chunk-EEKLJYON.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/ai-types.ts"],"sourcesContent":["import type { Message as ChatMessage } from \"ai\";\n\n/**\n * Enum for message types used in Agent communication\n */\nexport enum MessageType {\n /** Indicates this message contains updated chat messages */\n CF_AGENT_CHAT_MESSAGES = \"cf_agent_chat_messages\",\n /** Indicates this message is a response to a chat request */\n CF_AGENT_USE_CHAT_RESPONSE = \"cf_agent_use_chat_response\",\n /** Indicates this message is a command to clear chat history */\n CF_AGENT_CHAT_CLEAR = \"cf_agent_chat_clear\",\n /** Indicates this message is a request to the chat API */\n CF_AGENT_USE_CHAT_REQUEST = \"cf_agent_use_chat_request\",\n /** Indicates the user wants to stop generation of this message */\n CF_AGENT_CHAT_REQUEST_CANCEL = \"cf_agent_chat_request_cancel\",\n\n CF_AGENT_MCP_SERVERS = \"cf_agent_mcp_servers\",\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 =\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 }\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 command to clear chat history */\n type: MessageType.CF_AGENT_CHAT_CLEAR;\n };\n\n/**\n * Types of messages sent from clients to the Agent\n */\nexport type IncomingMessage =\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 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 the user wants to stop generation of this message */\n type: MessageType.CF_AGENT_CHAT_REQUEST_CANCEL;\n id: string;\n };\n"],"mappings":";AAKO,IAAK,cAAL,kBAAKA,iBAAL;AAEL,EAAAA,aAAA,4BAAyB;AAEzB,EAAAA,aAAA,gCAA6B;AAE7B,EAAAA,aAAA,yBAAsB;AAEtB,EAAAA,aAAA,+BAA4B;AAE5B,EAAAA,aAAA,kCAA+B;AAE/B,EAAAA,aAAA,0BAAuB;AACvB,EAAAA,aAAA,oBAAiB;AACjB,EAAAA,aAAA,SAAM;AAdI,SAAAA;AAAA,GAAA;","names":["MessageType"]}
@@ -1,3 +1,16 @@
1
+ // src/mcp/client.ts
2
+ import { jsonSchema } from "ai";
3
+ import { nanoid } from "nanoid";
4
+
5
+ // src/mcp/client-connection.ts
6
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
7
+ import {
8
+ PromptListChangedNotificationSchema,
9
+ ResourceListChangedNotificationSchema,
10
+ ToolListChangedNotificationSchema,
11
+ ElicitRequestSchema
12
+ } from "@modelcontextprotocol/sdk/types.js";
13
+
1
14
  // src/mcp/sse-edge.ts
2
15
  import {
3
16
  SSEClientTransport
@@ -45,15 +58,59 @@ var SSEEdgeClientTransport = class extends SSEClientTransport {
45
58
  }
46
59
  };
47
60
 
48
- // src/mcp/client-connection.ts
61
+ // src/mcp/streamable-http-edge.ts
49
62
  import {
50
- ToolListChangedNotificationSchema,
51
- ResourceListChangedNotificationSchema,
52
- PromptListChangedNotificationSchema
53
- } from "@modelcontextprotocol/sdk/types.js";
54
- import { Client } from "@modelcontextprotocol/sdk/client/index.js";
63
+ StreamableHTTPClientTransport
64
+ } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
65
+ var StreamableHTTPEdgeClientTransport = class extends StreamableHTTPClientTransport {
66
+ /**
67
+ * Creates a new StreamableHTTPEdgeClientTransport, which overrides fetch to be compatible with the CF workers environment
68
+ */
69
+ constructor(url, options) {
70
+ const fetchOverride = async (fetchUrl, fetchInit = {}) => {
71
+ const headers = await this.authHeaders();
72
+ const workerOptions = {
73
+ ...fetchInit,
74
+ headers: {
75
+ ...options.requestInit?.headers,
76
+ ...fetchInit?.headers,
77
+ ...headers
78
+ }
79
+ };
80
+ delete workerOptions.mode;
81
+ return (
82
+ // @ts-expect-error Custom fetch function for Cloudflare Workers compatibility
83
+ options.requestInit?.fetch?.(
84
+ fetchUrl,
85
+ workerOptions
86
+ ) || fetch(fetchUrl, workerOptions)
87
+ );
88
+ };
89
+ super(url, {
90
+ ...options,
91
+ requestInit: {
92
+ ...options.requestInit,
93
+ // @ts-expect-error Custom fetch override for Cloudflare Workers
94
+ fetch: fetchOverride
95
+ }
96
+ });
97
+ this.authProvider = options.authProvider;
98
+ }
99
+ async authHeaders() {
100
+ if (this.authProvider) {
101
+ const tokens = await this.authProvider.tokens();
102
+ if (tokens) {
103
+ return {
104
+ Authorization: `Bearer ${tokens.access_token}`
105
+ };
106
+ }
107
+ }
108
+ }
109
+ };
110
+
111
+ // src/mcp/client-connection.ts
55
112
  var MCPClientConnection = class {
56
- constructor(url, info, options = { transport: {}, client: {} }) {
113
+ constructor(url, info, options = { client: {}, transport: {} }) {
57
114
  this.url = url;
58
115
  this.options = options;
59
116
  this.connectionState = "connecting";
@@ -61,7 +118,14 @@ var MCPClientConnection = class {
61
118
  this.prompts = [];
62
119
  this.resources = [];
63
120
  this.resourceTemplates = [];
64
- this.client = new Client(info, options.client);
121
+ const clientOptions = {
122
+ ...options.client,
123
+ capabilities: {
124
+ ...options.client?.capabilities,
125
+ elicitation: {}
126
+ }
127
+ };
128
+ this.client = new Client(info, clientOptions);
65
129
  }
66
130
  /**
67
131
  * Initialize a client connection
@@ -71,14 +135,8 @@ var MCPClientConnection = class {
71
135
  */
72
136
  async init(code) {
73
137
  try {
74
- const transport = new SSEEdgeClientTransport(
75
- this.url,
76
- this.options.transport
77
- );
78
- if (code) {
79
- await transport.finishAuth(code);
80
- }
81
- await this.client.connect(transport);
138
+ const transportType = this.options.transport.type || "streamable-http";
139
+ await this.tryConnect(transportType, code);
82
140
  } catch (e) {
83
141
  if (e.toString().includes("Unauthorized")) {
84
142
  this.connectionState = "authenticating";
@@ -92,18 +150,36 @@ var MCPClientConnection = class {
92
150
  if (!this.serverCapabilities) {
93
151
  throw new Error("The MCP Server failed to return server capabilities");
94
152
  }
95
- const [instructions, tools, resources, prompts, resourceTemplates] = await Promise.all([
153
+ const [
154
+ instructionsResult,
155
+ toolsResult,
156
+ resourcesResult,
157
+ promptsResult,
158
+ resourceTemplatesResult
159
+ ] = await Promise.allSettled([
96
160
  this.client.getInstructions(),
97
161
  this.registerTools(),
98
162
  this.registerResources(),
99
163
  this.registerPrompts(),
100
164
  this.registerResourceTemplates()
101
165
  ]);
102
- this.instructions = instructions;
103
- this.tools = tools;
104
- this.resources = resources;
105
- this.prompts = prompts;
106
- this.resourceTemplates = resourceTemplates;
166
+ const operations = [
167
+ { name: "instructions", result: instructionsResult },
168
+ { name: "tools", result: toolsResult },
169
+ { name: "resources", result: resourcesResult },
170
+ { name: "prompts", result: promptsResult },
171
+ { name: "resource templates", result: resourceTemplatesResult }
172
+ ];
173
+ for (const { name, result } of operations) {
174
+ if (result.status === "rejected") {
175
+ console.error(`Failed to initialize ${name}:`, result.reason);
176
+ }
177
+ }
178
+ this.instructions = instructionsResult.status === "fulfilled" ? instructionsResult.value : void 0;
179
+ this.tools = toolsResult.status === "fulfilled" ? toolsResult.value : [];
180
+ this.resources = resourcesResult.status === "fulfilled" ? resourcesResult.value : [];
181
+ this.prompts = promptsResult.status === "fulfilled" ? promptsResult.value : [];
182
+ this.resourceTemplates = resourceTemplatesResult.status === "fulfilled" ? resourceTemplatesResult.value : [];
107
183
  this.connectionState = "ready";
108
184
  }
109
185
  /**
@@ -208,6 +284,63 @@ var MCPClientConnection = class {
208
284
  } while (templatesResult.nextCursor);
209
285
  return templatesAgg;
210
286
  }
287
+ /**
288
+ * Handle elicitation request from server
289
+ * Automatically uses the Agent's built-in elicitation handling if available
290
+ */
291
+ async handleElicitationRequest(_request) {
292
+ throw new Error(
293
+ "Elicitation handler must be implemented for your platform. Override handleElicitationRequest method."
294
+ );
295
+ }
296
+ /**
297
+ * Get the transport for the client
298
+ * @param transportType - The transport type to get
299
+ * @returns The transport for the client
300
+ */
301
+ getTransport(transportType) {
302
+ switch (transportType) {
303
+ case "streamable-http":
304
+ return new StreamableHTTPEdgeClientTransport(
305
+ this.url,
306
+ this.options.transport
307
+ );
308
+ case "sse":
309
+ return new SSEEdgeClientTransport(
310
+ this.url,
311
+ this.options.transport
312
+ );
313
+ default:
314
+ throw new Error(`Unsupported transport type: ${transportType}`);
315
+ }
316
+ }
317
+ async tryConnect(transportType, code) {
318
+ const transports = transportType === "auto" ? ["streamable-http", "sse"] : [transportType];
319
+ for (const currentTransportType of transports) {
320
+ const isLastTransport = currentTransportType === transports[transports.length - 1];
321
+ const hasFallback = transportType === "auto" && currentTransportType === "streamable-http" && !isLastTransport;
322
+ const transport = await this.getTransport(currentTransportType);
323
+ if (code) {
324
+ await transport.finishAuth(code);
325
+ }
326
+ try {
327
+ await this.client.connect(transport);
328
+ break;
329
+ } catch (e) {
330
+ const error = e instanceof Error ? e : new Error(String(e));
331
+ if (hasFallback && (error.message.includes("404") || error.message.includes("405"))) {
332
+ continue;
333
+ }
334
+ throw e;
335
+ }
336
+ }
337
+ this.client.setRequestHandler(
338
+ ElicitRequestSchema,
339
+ async (request) => {
340
+ return await this.handleElicitationRequest(request);
341
+ }
342
+ );
343
+ }
211
344
  };
212
345
  function capabilityErrorHandler(empty, method) {
213
346
  return (e) => {
@@ -222,8 +355,6 @@ function capabilityErrorHandler(empty, method) {
222
355
  }
223
356
 
224
357
  // src/mcp/client.ts
225
- import { jsonSchema } from "ai";
226
- import { nanoid } from "nanoid";
227
358
  var MCPClientManager = class {
228
359
  /**
229
360
  * @param _name Name of the MCP client
@@ -262,8 +393,8 @@ var MCPClientManager = class {
262
393
  version: this._version
263
394
  },
264
395
  {
265
- transport: options.transport ?? {},
266
- client: options.client ?? {}
396
+ client: options.client ?? {},
397
+ transport: options.transport ?? {}
267
398
  }
268
399
  );
269
400
  await this.mcpConnections[id].init(options.reconnect?.oauthCode);
@@ -273,9 +404,9 @@ var MCPClientManager = class {
273
404
  options.transport.authProvider.redirectUrl.toString()
274
405
  );
275
406
  return {
276
- id,
277
407
  authUrl,
278
- clientId: options.transport?.authProvider?.clientId
408
+ clientId: options.transport?.authProvider?.clientId,
409
+ id
279
410
  };
280
411
  }
281
412
  return {
@@ -350,21 +481,21 @@ var MCPClientManager = class {
350
481
  return Object.fromEntries(
351
482
  getNamespacedData(this.mcpConnections, "tools").map((tool) => {
352
483
  return [
353
- `${tool.serverId}_${tool.name}`,
484
+ `tool_${tool.serverId}_${tool.name}`,
354
485
  {
355
- parameters: jsonSchema(tool.inputSchema),
356
486
  description: tool.description,
357
487
  execute: async (args) => {
358
488
  const result = await this.callTool({
359
- name: tool.name,
360
489
  arguments: args,
490
+ name: tool.name,
361
491
  serverId: tool.serverId
362
492
  });
363
493
  if (result.isError) {
364
494
  throw new Error(result.content[0].text);
365
495
  }
366
496
  return result;
367
- }
497
+ },
498
+ parameters: jsonSchema(tool.inputSchema)
368
499
  }
369
500
  ];
370
501
  })
@@ -389,6 +520,7 @@ var MCPClientManager = class {
389
520
  throw new Error(`Connection with id "${id}" does not exist.`);
390
521
  }
391
522
  await this.mcpConnections[id].client.close();
523
+ delete this.mcpConnections[id];
392
524
  }
393
525
  /**
394
526
  * @returns namespaced list of prompts
@@ -443,7 +575,7 @@ var MCPClientManager = class {
443
575
  };
444
576
  function getNamespacedData(mcpClients, type) {
445
577
  const sets = Object.entries(mcpClients).map(([name, conn]) => {
446
- return { name, data: conn[type] };
578
+ return { data: conn[type], name };
447
579
  });
448
580
  const namespacedData = sets.flatMap(({ name: serverId, data }) => {
449
581
  return data.map((item) => {
@@ -458,7 +590,9 @@ function getNamespacedData(mcpClients, type) {
458
590
  }
459
591
 
460
592
  export {
593
+ SSEEdgeClientTransport,
594
+ StreamableHTTPEdgeClientTransport,
461
595
  MCPClientManager,
462
596
  getNamespacedData
463
597
  };
464
- //# sourceMappingURL=chunk-Y67CHZBI.js.map
598
+ //# sourceMappingURL=chunk-EM3J4KV7.js.map