agents 0.2.31 → 0.2.32

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.
@@ -18,7 +18,11 @@ declare enum MessageType {
18
18
  CF_AGENT_MCP_SERVERS = "cf_agent_mcp_servers",
19
19
  CF_MCP_AGENT_EVENT = "cf_mcp_agent_event",
20
20
  CF_AGENT_STATE = "cf_agent_state",
21
- RPC = "rpc"
21
+ RPC = "rpc",
22
+ /** Client sends tool result to server (for client-side tools) */
23
+ CF_AGENT_TOOL_RESULT = "cf_agent_tool_result",
24
+ /** Server notifies client that a message was updated (e.g., tool result applied) */
25
+ CF_AGENT_MESSAGE_UPDATED = "cf_agent_message_updated"
22
26
  }
23
27
  /**
24
28
  * Types of messages sent from the Agent to clients
@@ -45,12 +49,20 @@ type OutgoingMessage<ChatMessage extends UIMessage = UIMessage> =
45
49
  done: boolean;
46
50
  /** Whether this response contains an error */
47
51
  error?: boolean;
52
+ /** Whether this is a continuation (append to last assistant message) */
53
+ continuation?: boolean;
48
54
  }
49
55
  | {
50
56
  /** Indicates the server is resuming an active stream */
51
57
  type: MessageType.CF_AGENT_STREAM_RESUMING;
52
58
  /** The request ID of the stream being resumed */
53
59
  id: string;
60
+ }
61
+ | {
62
+ /** Server notifies client that a message was updated (e.g., tool result applied) */
63
+ type: MessageType.CF_AGENT_MESSAGE_UPDATED;
64
+ /** The updated message */
65
+ message: ChatMessage;
54
66
  };
55
67
  /**
56
68
  * Types of messages sent from clients to the Agent
@@ -97,7 +109,19 @@ type IncomingMessage<ChatMessage extends UIMessage = UIMessage> =
97
109
  type: MessageType.CF_AGENT_STREAM_RESUME_ACK;
98
110
  /** The request ID of the stream being resumed */
99
111
  id: string;
112
+ }
113
+ | {
114
+ /** Client sends tool result to server (for client-side tools) */
115
+ type: MessageType.CF_AGENT_TOOL_RESULT;
116
+ /** The tool call ID this result is for */
117
+ toolCallId: string;
118
+ /** The name of the tool */
119
+ toolName: string;
120
+ /** The output from the tool execution */
121
+ output: unknown;
122
+ /** Whether server should auto-continue the conversation after applying result */
123
+ autoContinue?: boolean;
100
124
  };
101
125
  //#endregion
102
126
  export { MessageType as n, OutgoingMessage as r, IncomingMessage as t };
103
- //# sourceMappingURL=ai-types-D_hTbf25.d.ts.map
127
+ //# sourceMappingURL=ai-types-U8lYA0o8.d.ts.map
@@ -2,5 +2,5 @@ import {
2
2
  n as MessageType,
3
3
  r as OutgoingMessage,
4
4
  t as IncomingMessage
5
- } from "./ai-types-D_hTbf25.js";
5
+ } from "./ai-types-U8lYA0o8.js";
6
6
  export { IncomingMessage, MessageType, OutgoingMessage };
package/dist/ai-types.js CHANGED
@@ -1,3 +1,3 @@
1
- import { t as MessageType } from "./ai-types-CwgHzwUb.js";
1
+ import { t as MessageType } from "./ai-types-DEtF_8Km.js";
2
2
 
3
3
  export { MessageType };
@@ -1,5 +1,7 @@
1
1
  import { t as MCPObservabilityEvent } from "./mcp-CzbSsLfc.js";
2
2
  import { t as AgentsOAuthProvider } from "./do-oauth-client-provider-B-ryFIPr.js";
3
+ import * as ai0 from "ai";
4
+ import { ToolSet } from "ai";
3
5
  import { Client } from "@modelcontextprotocol/sdk/client/index.js";
4
6
  import {
5
7
  SSEClientTransport,
@@ -21,10 +23,8 @@ import {
21
23
  Resource,
22
24
  ResourceTemplate,
23
25
  ServerCapabilities,
24
- Tool
26
+ Tool as Tool$1
25
27
  } from "@modelcontextprotocol/sdk/types.js";
26
- import * as ai0 from "ai";
27
- import { ToolSet } from "ai";
28
28
  import { RequestOptions } from "@modelcontextprotocol/sdk/shared/protocol.js";
29
29
 
30
30
  //#region src/core/events.d.ts
@@ -111,7 +111,7 @@ declare class MCPClientConnection {
111
111
  connectionState: MCPConnectionState;
112
112
  lastConnectedTransport: BaseTransportType | undefined;
113
113
  instructions?: string;
114
- tools: Tool[];
114
+ tools: Tool$1[];
115
115
  prompts: Prompt[];
116
116
  resources: Resource[];
117
117
  resourceTemplates: ResourceTemplate[];
@@ -168,7 +168,7 @@ declare class MCPClientConnection {
168
168
  * Notification handler registration for tools
169
169
  * Should only be called if serverCapabilities.tools exists
170
170
  */
171
- registerTools(): Promise<Tool[]>;
171
+ registerTools(): Promise<Tool$1[]>;
172
172
  /**
173
173
  * Notification handler registration for resources
174
174
  * Should only be called if serverCapabilities.resources exists
@@ -796,7 +796,7 @@ declare class MCPClientManager {
796
796
  }>;
797
797
  }
798
798
  type NamespacedData = {
799
- tools: (Tool & {
799
+ tools: (Tool$1 & {
800
800
  serverId: string;
801
801
  })[];
802
802
  prompts: (Prompt & {
@@ -831,4 +831,4 @@ export {
831
831
  MCPClientManager as t,
832
832
  MCPConnectionState as u
833
833
  };
834
- //# sourceMappingURL=client-DfIOsabL.d.ts.map
834
+ //# sourceMappingURL=client-BZVYeBmf.d.ts.map
@@ -1,4 +1,4 @@
1
- import { t as MessageType } from "./ai-types-CwgHzwUb.js";
1
+ import { t as MessageType } from "./ai-types-DEtF_8Km.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-CcyhkGfN.js.map
117
+ //# sourceMappingURL=client-DjTPRM8-.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"client-CcyhkGfN.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
+ {"version":3,"file":"client-DjTPRM8-.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"}
package/dist/client.js CHANGED
@@ -1,4 +1,4 @@
1
- import "./ai-types-CwgHzwUb.js";
2
- import { n as agentFetch, r as camelCaseToKebabCase, t as AgentClient } from "./client-CcyhkGfN.js";
1
+ import "./ai-types-DEtF_8Km.js";
2
+ import { n as agentFetch, r as camelCaseToKebabCase, t as AgentClient } from "./client-DjTPRM8-.js";
3
3
 
4
4
  export { AgentClient, agentFetch, camelCaseToKebabCase };
@@ -1,9 +1,9 @@
1
1
  import "../context-BkKbAa1R.js";
2
- import "../ai-types-CwgHzwUb.js";
3
- import "../client-CcyhkGfN.js";
2
+ import "../ai-types-DEtF_8Km.js";
3
+ import "../client-DjTPRM8-.js";
4
4
  import "../client-QZa2Rq0l.js";
5
5
  import "../do-oauth-client-provider-B1fVIshX.js";
6
- import { s as getAgentByName } from "../src-BmbDclOA.js";
6
+ import { s as getAgentByName } from "../src-BZDh910Z.js";
7
7
  import { generateObject, tool } from "ai";
8
8
  import { openai } from "@ai-sdk/openai";
9
9
  import { z } from "zod/v3";
@@ -3,9 +3,9 @@ import {
3
3
  h as TransportType,
4
4
  t as MCPClientManager,
5
5
  u as MCPConnectionState
6
- } from "./client-DfIOsabL.js";
6
+ } from "./client-BZVYeBmf.js";
7
7
  import { t as Observability } from "./index-CyDpAVHZ.js";
8
- import { n as MessageType } from "./ai-types-D_hTbf25.js";
8
+ import { n as MessageType } from "./ai-types-U8lYA0o8.js";
9
9
  import {
10
10
  Connection,
11
11
  Connection as Connection$1,
@@ -574,4 +574,4 @@ export {
574
574
  callable as x,
575
575
  StreamingResponse as y
576
576
  };
577
- //# sourceMappingURL=index-DPJ32qQn.d.ts.map
577
+ //# sourceMappingURL=index-B6XHf8p0.d.ts.map
package/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import { n as AgentEmail } from "./context-_sPQqJWv.js";
2
- import { h as TransportType } from "./client-DfIOsabL.js";
2
+ import { h as TransportType } from "./client-BZVYeBmf.js";
3
3
  import "./mcp-CzbSsLfc.js";
4
4
  import "./do-oauth-client-provider-B-ryFIPr.js";
5
5
  import "./index-CyDpAVHZ.js";
6
- import "./ai-types-D_hTbf25.js";
6
+ import "./ai-types-U8lYA0o8.js";
7
7
  import {
8
8
  C as createCatchAllEmailResolver,
9
9
  D as routeAgentEmail,
@@ -34,7 +34,7 @@ import {
34
34
  w as createHeaderBasedEmailResolver,
35
35
  x as callable,
36
36
  y as StreamingResponse
37
- } from "./index-DPJ32qQn.js";
37
+ } from "./index-B6XHf8p0.js";
38
38
  export {
39
39
  Agent,
40
40
  AgentContext,
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import "./context-BkKbAa1R.js";
2
- import "./ai-types-CwgHzwUb.js";
3
- import "./client-CcyhkGfN.js";
2
+ import "./ai-types-DEtF_8Km.js";
3
+ import "./client-DjTPRM8-.js";
4
4
  import "./client-QZa2Rq0l.js";
5
5
  import "./do-oauth-client-provider-B1fVIshX.js";
6
- import { a as createCatchAllEmailResolver, c as getCurrentAgent, d as unstable_callable, i as createAddressBasedEmailResolver, l as routeAgentEmail, n as StreamingResponse, o as createHeaderBasedEmailResolver, r as callable, s as getAgentByName, t as Agent, u as routeAgentRequest } from "./src-BmbDclOA.js";
6
+ import { a as createCatchAllEmailResolver, c as getCurrentAgent, d as unstable_callable, i as createAddressBasedEmailResolver, l as routeAgentEmail, n as StreamingResponse, o as createHeaderBasedEmailResolver, r as callable, s as getAgentByName, t as Agent, u as routeAgentRequest } from "./src-BZDh910Z.js";
7
7
 
8
8
  export { Agent, StreamingResponse, callable, createAddressBasedEmailResolver, createCatchAllEmailResolver, createHeaderBasedEmailResolver, getAgentByName, getCurrentAgent, routeAgentEmail, routeAgentRequest, unstable_callable };
@@ -1,4 +1,4 @@
1
- import { a as MCPConnectionResult, c as RegisterServerOptions, i as MCPClientOAuthResult, l as getNamespacedData, n as MCPClientManagerOptions, o as MCPDiscoverResult, r as MCPClientOAuthCallbackConfig, s as MCPServerOptions, t as MCPClientManager } from "../client-DfIOsabL.js";
1
+ import { a as MCPConnectionResult, c as RegisterServerOptions, i as MCPClientOAuthResult, l as getNamespacedData, n as MCPClientManagerOptions, o as MCPDiscoverResult, r as MCPClientOAuthCallbackConfig, s as MCPServerOptions, t as MCPClientManager } from "../client-BZVYeBmf.js";
2
2
  import "../mcp-CzbSsLfc.js";
3
3
  import "../do-oauth-client-provider-B-ryFIPr.js";
4
4
  export { MCPClientManager, MCPClientManagerOptions, MCPClientOAuthCallbackConfig, MCPClientOAuthResult, MCPConnectionResult, MCPDiscoverResult, MCPServerOptions, RegisterServerOptions, getNamespacedData };
@@ -1,10 +1,10 @@
1
1
  import "../context-_sPQqJWv.js";
2
- import { a as MCPConnectionResult, d as BaseTransportType, f as CORSOptions, i as MCPClientOAuthResult, m as ServeOptions, o as MCPDiscoverResult, p as MaybePromise, r as MCPClientOAuthCallbackConfig, s as MCPServerOptions } from "../client-DfIOsabL.js";
2
+ import { a as MCPConnectionResult, d as BaseTransportType, f as CORSOptions, i as MCPClientOAuthResult, m as ServeOptions, o as MCPDiscoverResult, p as MaybePromise, r as MCPClientOAuthCallbackConfig, s as MCPServerOptions } from "../client-BZVYeBmf.js";
3
3
  import "../mcp-CzbSsLfc.js";
4
4
  import "../do-oauth-client-provider-B-ryFIPr.js";
5
5
  import "../index-CyDpAVHZ.js";
6
- import "../ai-types-D_hTbf25.js";
7
- import { o as Connection, s as ConnectionContext, t as Agent } from "../index-DPJ32qQn.js";
6
+ import "../ai-types-U8lYA0o8.js";
7
+ import { o as Connection, s as ConnectionContext, t as Agent } from "../index-B6XHf8p0.js";
8
8
  import { SSEClientTransport, SSEClientTransportOptions } from "@modelcontextprotocol/sdk/client/sse.js";
9
9
  import { StreamableHTTPClientTransport, StreamableHTTPClientTransportOptions } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
10
10
  import { ElicitRequest, ElicitRequestSchema, ElicitResult, ElicitResult as ElicitResult$1, JSONRPCMessage, MessageExtraInfo } from "@modelcontextprotocol/sdk/types.js";
package/dist/mcp/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import "../context-BkKbAa1R.js";
2
- import { t as MessageType } from "../ai-types-CwgHzwUb.js";
3
- import "../client-CcyhkGfN.js";
2
+ import { t as MessageType } from "../ai-types-DEtF_8Km.js";
3
+ import "../client-DjTPRM8-.js";
4
4
  import "../client-QZa2Rq0l.js";
5
5
  import "../do-oauth-client-provider-B1fVIshX.js";
6
- import { c as getCurrentAgent, s as getAgentByName, t as Agent } from "../src-BmbDclOA.js";
6
+ import { c as getCurrentAgent, s as getAgentByName, t as Agent } from "../src-BZDh910Z.js";
7
7
  import { AsyncLocalStorage } from "node:async_hooks";
8
8
  import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
9
9
  import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
@@ -1,8 +1,8 @@
1
1
  import "../context-BkKbAa1R.js";
2
- import "../ai-types-CwgHzwUb.js";
3
- import "../client-CcyhkGfN.js";
2
+ import "../ai-types-DEtF_8Km.js";
3
+ import "../client-DjTPRM8-.js";
4
4
  import "../client-QZa2Rq0l.js";
5
5
  import "../do-oauth-client-provider-B1fVIshX.js";
6
- import { f as genericObservability } from "../src-BmbDclOA.js";
6
+ import { f as genericObservability } from "../src-BZDh910Z.js";
7
7
 
8
8
  export { genericObservability };
@@ -1,4 +1,4 @@
1
- import { p as MCPServersState, t as Agent } from "./index-DPJ32qQn.js";
1
+ import { p as MCPServersState, t as Agent } from "./index-B6XHf8p0.js";
2
2
  import { n as RPCMethod, t as Method } from "./serializable-C4GLimgv.js";
3
3
  import { i as StreamOptions } from "./client-ClORm6f0.js";
4
4
  import { PartySocket } from "partysocket";
@@ -6,28 +6,22 @@ import { usePartySocket } from "partysocket/react";
6
6
 
7
7
  //#region src/react.d.ts
8
8
  type QueryObject = Record<string, string | null>;
9
- declare function findCacheEntry(
10
- targetKey: unknown[]
11
- ): Promise<QueryObject> | undefined;
9
+ interface CacheEntry {
10
+ promise: Promise<QueryObject>;
11
+ expiresAt: number;
12
+ }
13
+ declare function getCacheEntry(key: string): CacheEntry | undefined;
12
14
  declare function setCacheEntry(
13
- key: unknown[],
14
- value: Promise<QueryObject>,
15
- cacheTtl?: number
16
- ): void;
17
- declare function decrementCacheEntry(targetKey: unknown[]): boolean;
15
+ key: string,
16
+ promise: Promise<QueryObject>,
17
+ cacheTtl: number
18
+ ): CacheEntry;
19
+ declare function deleteCacheEntry(key: string): void;
18
20
  declare const _testUtils: {
19
- queryCache: Map<
20
- unknown[],
21
- {
22
- promise: Promise<QueryObject>;
23
- refCount: number;
24
- expiresAt: number;
25
- cacheTtl?: number;
26
- }
27
- >;
21
+ queryCache: Map<string, CacheEntry>;
28
22
  setCacheEntry: typeof setCacheEntry;
29
- findCacheEntry: typeof findCacheEntry;
30
- decrementCacheEntry: typeof decrementCacheEntry;
23
+ getCacheEntry: typeof getCacheEntry;
24
+ deleteCacheEntry: typeof deleteCacheEntry;
31
25
  clearCache: () => void;
32
26
  };
33
27
  /**
@@ -134,4 +128,4 @@ declare function useAgent<
134
128
  };
135
129
  //#endregion
136
130
  export { _testUtils as n, useAgent as r, UseAgentOptions as t };
137
- //# sourceMappingURL=react-DTzwSLAh.d.ts.map
131
+ //# sourceMappingURL=react-DYwejKBr.d.ts.map
package/dist/react.d.ts CHANGED
@@ -1,15 +1,15 @@
1
1
  import "./context-_sPQqJWv.js";
2
- import "./client-DfIOsabL.js";
2
+ import "./client-BZVYeBmf.js";
3
3
  import "./mcp-CzbSsLfc.js";
4
4
  import "./do-oauth-client-provider-B-ryFIPr.js";
5
5
  import "./index-CyDpAVHZ.js";
6
- import "./ai-types-D_hTbf25.js";
7
- import "./index-DPJ32qQn.js";
6
+ import "./ai-types-U8lYA0o8.js";
7
+ import "./index-B6XHf8p0.js";
8
8
  import "./serializable-C4GLimgv.js";
9
9
  import "./client-ClORm6f0.js";
10
10
  import {
11
11
  n as _testUtils,
12
12
  r as useAgent,
13
13
  t as UseAgentOptions
14
- } from "./react-DTzwSLAh.js";
14
+ } from "./react-DYwejKBr.js";
15
15
  export { UseAgentOptions, _testUtils, useAgent };
package/dist/react.js CHANGED
@@ -1,5 +1,5 @@
1
- import { t as MessageType } from "./ai-types-CwgHzwUb.js";
2
- import { use, useCallback, useEffect, useMemo, useRef } from "react";
1
+ import { t as MessageType } from "./ai-types-DEtF_8Km.js";
2
+ import { use, useCallback, useEffect, useMemo, useRef, useState } from "react";
3
3
  import { usePartySocket } from "partysocket/react";
4
4
 
5
5
  //#region src/react.tsx
@@ -15,85 +15,83 @@ function camelCaseToKebabCase(str) {
15
15
  return kebabified.replace(/_/g, "-").replace(/-$/, "");
16
16
  }
17
17
  const queryCache = /* @__PURE__ */ new Map();
18
- function arraysEqual(a, b) {
19
- if (a === b) return true;
20
- if (a.length !== b.length) return false;
21
- for (let i = 0; i < a.length; i++) if (!Object.is(a[i], b[i])) return false;
22
- return true;
18
+ function createCacheKey(agentNamespace, name, deps) {
19
+ return JSON.stringify([
20
+ agentNamespace,
21
+ name || "default",
22
+ ...deps
23
+ ]);
23
24
  }
24
- function findCacheEntry(targetKey) {
25
- for (const [existingKey, entry] of queryCache.entries()) if (arraysEqual(existingKey, targetKey)) {
26
- if (Date.now() > entry.expiresAt) {
27
- queryCache.delete(existingKey);
28
- return;
29
- }
30
- entry.refCount++;
31
- return entry.promise;
25
+ function getCacheEntry(key) {
26
+ const entry = queryCache.get(key);
27
+ if (!entry) return void 0;
28
+ if (Date.now() >= entry.expiresAt) {
29
+ queryCache.delete(key);
30
+ return;
32
31
  }
32
+ return entry;
33
33
  }
34
- function setCacheEntry(key, value, cacheTtl) {
35
- for (const [existingKey] of queryCache.entries()) if (arraysEqual(existingKey, key)) {
36
- queryCache.delete(existingKey);
37
- break;
38
- }
39
- const expiresAt = cacheTtl !== void 0 ? Date.now() + cacheTtl : Date.now() + 300 * 1e3;
40
- queryCache.set(key, {
41
- promise: value,
42
- refCount: 1,
43
- expiresAt,
44
- cacheTtl
45
- });
34
+ function setCacheEntry(key, promise, cacheTtl) {
35
+ const entry = {
36
+ promise,
37
+ expiresAt: Date.now() + cacheTtl
38
+ };
39
+ queryCache.set(key, entry);
40
+ return entry;
46
41
  }
47
- function decrementCacheEntry(targetKey) {
48
- for (const [existingKey, entry] of queryCache.entries()) if (arraysEqual(existingKey, targetKey)) {
49
- entry.refCount--;
50
- if (entry.refCount <= 0) queryCache.delete(existingKey);
51
- return true;
52
- }
53
- return false;
42
+ function deleteCacheEntry(key) {
43
+ queryCache.delete(key);
54
44
  }
55
45
  const _testUtils = {
56
46
  queryCache,
57
47
  setCacheEntry,
58
- findCacheEntry,
59
- decrementCacheEntry,
48
+ getCacheEntry,
49
+ deleteCacheEntry,
60
50
  clearCache: () => queryCache.clear()
61
51
  };
62
- function createCacheKey(agentNamespace, name, deps) {
63
- return [
64
- agentNamespace,
65
- name || "default",
66
- ...deps
67
- ];
68
- }
69
52
  function useAgent(options) {
70
53
  const agentNamespace = camelCaseToKebabCase(options.agent);
71
54
  const { query, queryDeps, cacheTtl, ...restOptions } = options;
72
55
  const pendingCallsRef = useRef(/* @__PURE__ */ new Map());
73
- const cacheKey = useMemo(() => {
74
- const deps = queryDeps || [];
75
- return createCacheKey(agentNamespace, options.name, deps);
76
- }, [
56
+ const cacheKey = useMemo(() => createCacheKey(agentNamespace, options.name, queryDeps || []), [
77
57
  agentNamespace,
78
58
  options.name,
79
59
  queryDeps
80
60
  ]);
61
+ const ttl = cacheTtl ?? 300 * 1e3;
62
+ const [cacheInvalidatedAt, setCacheInvalidatedAt] = useState(0);
81
63
  const queryPromise = useMemo(() => {
82
64
  if (!query || typeof query !== "function") return null;
83
- const existingPromise = findCacheEntry(cacheKey);
84
- if (existingPromise) return existingPromise;
65
+ const cached = getCacheEntry(cacheKey);
66
+ if (cached) return cached.promise;
85
67
  const promise = query().catch((error) => {
86
68
  console.error(`[useAgent] Query failed for agent "${options.agent}":`, error);
87
- decrementCacheEntry(cacheKey);
69
+ deleteCacheEntry(cacheKey);
88
70
  throw error;
89
71
  });
90
- setCacheEntry(cacheKey, promise, cacheTtl);
72
+ setCacheEntry(cacheKey, promise, ttl);
91
73
  return promise;
92
74
  }, [
93
75
  cacheKey,
94
76
  query,
95
77
  options.agent,
96
- cacheTtl
78
+ ttl,
79
+ cacheInvalidatedAt
80
+ ]);
81
+ useEffect(() => {
82
+ if (!queryPromise || ttl <= 0) return;
83
+ const entry = getCacheEntry(cacheKey);
84
+ if (!entry) return;
85
+ const timeUntilExpiry = entry.expiresAt - Date.now();
86
+ const timer = setTimeout(() => {
87
+ deleteCacheEntry(cacheKey);
88
+ setCacheInvalidatedAt(Date.now());
89
+ }, Math.max(0, timeUntilExpiry));
90
+ return () => clearTimeout(timer);
91
+ }, [
92
+ cacheKey,
93
+ queryPromise,
94
+ ttl
97
95
  ]);
98
96
  let resolvedQuery;
99
97
  if (query) if (typeof query === "function") {
@@ -103,11 +101,6 @@ function useAgent(options) {
103
101
  resolvedQuery = queryResult;
104
102
  }
105
103
  } else resolvedQuery = query;
106
- useEffect(() => {
107
- return () => {
108
- if (queryPromise) decrementCacheEntry(cacheKey);
109
- };
110
- }, [cacheKey, queryPromise]);
111
104
  const agent = usePartySocket({
112
105
  party: agentNamespace,
113
106
  prefix: "agents",
package/dist/react.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"react.js","names":["resolvedQuery: QueryObject | undefined","parsedMessage: Record<string, unknown>","request: RPCRequest"],"sources":["../src/react.tsx"],"sourcesContent":["import type { PartySocket } from \"partysocket\";\nimport { usePartySocket } from \"partysocket/react\";\nimport { useCallback, useRef, use, useMemo, useEffect } from \"react\";\nimport type { Agent, MCPServersState, RPCRequest, RPCResponse } from \"./\";\nimport type { StreamOptions } from \"./client\";\nimport type { Method, RPCMethod } from \"./serializable\";\nimport { MessageType } from \"./ai-types\";\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 */\nfunction 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\ntype QueryObject = Record<string, string | null>;\n\nconst queryCache = new Map<\n unknown[],\n {\n promise: Promise<QueryObject>;\n refCount: number;\n expiresAt: number;\n cacheTtl?: number;\n }\n>();\n\nfunction arraysEqual(a: unknown[], b: unknown[]): boolean {\n if (a === b) return true;\n if (a.length !== b.length) return false;\n\n for (let i = 0; i < a.length; i++) {\n if (!Object.is(a[i], b[i])) return false;\n }\n return true;\n}\n\nfunction findCacheEntry(\n targetKey: unknown[]\n): Promise<QueryObject> | undefined {\n for (const [existingKey, entry] of queryCache.entries()) {\n if (arraysEqual(existingKey, targetKey)) {\n // Check if entry has expired\n if (Date.now() > entry.expiresAt) {\n queryCache.delete(existingKey);\n return undefined;\n }\n entry.refCount++;\n return entry.promise;\n }\n }\n return undefined;\n}\n\nfunction setCacheEntry(\n key: unknown[],\n value: Promise<QueryObject>,\n cacheTtl?: number\n): void {\n // Remove any existing entry with matching members\n for (const [existingKey] of queryCache.entries()) {\n if (arraysEqual(existingKey, key)) {\n queryCache.delete(existingKey);\n break;\n }\n }\n\n const expiresAt =\n cacheTtl !== undefined ? Date.now() + cacheTtl : Date.now() + 5 * 60 * 1000; // Default 5 minutes\n queryCache.set(key, { promise: value, refCount: 1, expiresAt, cacheTtl });\n}\n\nfunction decrementCacheEntry(targetKey: unknown[]): boolean {\n for (const [existingKey, entry] of queryCache.entries()) {\n if (arraysEqual(existingKey, targetKey)) {\n entry.refCount--;\n if (entry.refCount <= 0) {\n queryCache.delete(existingKey);\n }\n return true;\n }\n }\n return false;\n}\n\n// Export for testing purposes\nexport const _testUtils = {\n queryCache,\n setCacheEntry,\n findCacheEntry,\n decrementCacheEntry,\n clearCache: () => queryCache.clear()\n};\n\nfunction createCacheKey(\n agentNamespace: string,\n name: string | undefined,\n deps: unknown[]\n): unknown[] {\n return [agentNamespace, name || \"default\", ...deps];\n}\n\n/**\n * Options for the useAgent hook\n * @template State Type of the Agent's state\n */\nexport type UseAgentOptions<State = unknown> = Omit<\n Parameters<typeof usePartySocket>[0],\n \"party\" | \"room\" | \"query\"\n> & {\n /** Name of the agent to connect to */\n agent: string;\n /** Name of the specific Agent instance */\n name?: string;\n /** Query parameters - can be static object or async function */\n query?: QueryObject | (() => Promise<QueryObject>);\n /** Dependencies for async query caching */\n queryDeps?: unknown[];\n /** Cache TTL in milliseconds for auth tokens/time-sensitive data */\n cacheTtl?: number;\n /** Called when the Agent's state is updated */\n onStateUpdate?: (state: State, source: \"server\" | \"client\") => void;\n /** Called when MCP server state is updated */\n onMcpUpdate?: (mcpServers: MCPServersState) => void;\n};\n\ntype AllOptional<T> = T extends [infer A, ...infer R]\n ? undefined extends A\n ? AllOptional<R>\n : false\n : true; // no params means optional by default\n\ntype RPCMethods<T> = {\n [K in keyof T as T[K] extends RPCMethod<T[K]> ? K : never]: RPCMethod<T[K]>;\n};\n\ntype OptionalParametersMethod<T extends RPCMethod> =\n AllOptional<Parameters<T>> extends true ? T : never;\n\n// all methods of the Agent, excluding the ones that are declared in the base Agent class\n// biome-ignore lint: suppressions/parse\ntype AgentMethods<T> = Omit<RPCMethods<T>, keyof Agent<any, any>>;\n\ntype OptionalAgentMethods<T> = {\n [K in keyof AgentMethods<T> as AgentMethods<T>[K] extends OptionalParametersMethod<\n AgentMethods<T>[K]\n >\n ? K\n : never]: OptionalParametersMethod<AgentMethods<T>[K]>;\n};\n\ntype RequiredAgentMethods<T> = Omit<\n AgentMethods<T>,\n keyof OptionalAgentMethods<T>\n>;\n\ntype AgentPromiseReturnType<T, K extends keyof AgentMethods<T>> =\n // biome-ignore lint: suppressions/parse\n ReturnType<AgentMethods<T>[K]> extends Promise<any>\n ? ReturnType<AgentMethods<T>[K]>\n : Promise<ReturnType<AgentMethods<T>[K]>>;\n\ntype OptionalArgsAgentMethodCall<AgentT> = <\n K extends keyof OptionalAgentMethods<AgentT>\n>(\n method: K,\n args?: Parameters<OptionalAgentMethods<AgentT>[K]>,\n streamOptions?: StreamOptions\n) => AgentPromiseReturnType<AgentT, K>;\n\ntype RequiredArgsAgentMethodCall<AgentT> = <\n K extends keyof RequiredAgentMethods<AgentT>\n>(\n method: K,\n args: Parameters<RequiredAgentMethods<AgentT>[K]>,\n streamOptions?: StreamOptions\n) => AgentPromiseReturnType<AgentT, K>;\n\ntype AgentMethodCall<AgentT> = OptionalArgsAgentMethodCall<AgentT> &\n RequiredArgsAgentMethodCall<AgentT>;\n\ntype UntypedAgentMethodCall = <T = unknown>(\n method: string,\n args?: unknown[],\n streamOptions?: StreamOptions\n) => Promise<T>;\n\ntype AgentStub<T> = {\n [K in keyof AgentMethods<T>]: (\n ...args: Parameters<AgentMethods<T>[K]>\n ) => AgentPromiseReturnType<AgentMethods<T>, K>;\n};\n\n// we neet to use Method instead of RPCMethod here for retro-compatibility\ntype UntypedAgentStub = Record<string, Method>;\n\n/**\n * React hook for connecting to an Agent\n */\nexport function useAgent<State = unknown>(\n options: UseAgentOptions<State>\n): PartySocket & {\n agent: string;\n name: string;\n setState: (state: State) => void;\n call: UntypedAgentMethodCall;\n stub: UntypedAgentStub;\n};\nexport function useAgent<\n AgentT extends {\n get state(): State;\n },\n State\n>(\n options: UseAgentOptions<State>\n): PartySocket & {\n agent: string;\n name: string;\n setState: (state: State) => void;\n call: AgentMethodCall<AgentT>;\n stub: AgentStub<AgentT>;\n};\nexport function useAgent<State>(\n options: UseAgentOptions<unknown>\n): PartySocket & {\n agent: string;\n name: string;\n setState: (state: State) => void;\n call: UntypedAgentMethodCall | AgentMethodCall<unknown>;\n stub: UntypedAgentStub;\n} {\n const agentNamespace = camelCaseToKebabCase(options.agent);\n const { query, queryDeps, cacheTtl, ...restOptions } = options;\n\n // Keep track of pending RPC calls\n const pendingCallsRef = useRef(\n new Map<\n string,\n {\n resolve: (value: unknown) => void;\n reject: (error: Error) => void;\n stream?: StreamOptions;\n }\n >()\n );\n\n // Handle both sync and async query patterns\n const cacheKey = useMemo(() => {\n const deps = queryDeps || [];\n return createCacheKey(agentNamespace, options.name, deps);\n }, [agentNamespace, options.name, queryDeps]);\n\n const queryPromise = useMemo(() => {\n if (!query || typeof query !== \"function\") {\n return null;\n }\n\n const existingPromise = findCacheEntry(cacheKey);\n if (existingPromise) {\n return existingPromise;\n }\n\n const promise = query().catch((error) => {\n console.error(\n `[useAgent] Query failed for agent \"${options.agent}\":`,\n error\n );\n decrementCacheEntry(cacheKey); // Remove failed promise from cache\n throw error; // Re-throw for Suspense error boundary\n });\n\n setCacheEntry(cacheKey, promise, cacheTtl);\n\n return promise;\n }, [cacheKey, query, options.agent, cacheTtl]);\n\n let resolvedQuery: QueryObject | undefined;\n\n if (query) {\n if (typeof query === \"function\") {\n // Use React's use() to resolve the promise\n const queryResult = use(queryPromise!);\n\n // Check for non-primitive values and warn\n if (queryResult) {\n for (const [key, value] of Object.entries(queryResult)) {\n if (\n value !== null &&\n value !== undefined &&\n typeof value !== \"string\" &&\n typeof value !== \"number\" &&\n typeof value !== \"boolean\"\n ) {\n console.warn(\n `[useAgent] Query parameter \"${key}\" is an object and will be converted to \"[object Object]\". ` +\n \"Query parameters should be string, number, boolean, or null.\"\n );\n }\n }\n resolvedQuery = queryResult;\n }\n } else {\n // Sync query - use directly\n resolvedQuery = query;\n }\n }\n\n // Cleanup cache on unmount\n useEffect(() => {\n return () => {\n if (queryPromise) {\n decrementCacheEntry(cacheKey);\n }\n };\n }, [cacheKey, queryPromise]);\n\n const agent = usePartySocket({\n party: agentNamespace,\n prefix: \"agents\",\n room: options.name || \"default\",\n query: resolvedQuery,\n ...restOptions,\n onMessage: (message) => {\n if (typeof message.data === \"string\") {\n let parsedMessage: Record<string, unknown>;\n try {\n parsedMessage = JSON.parse(message.data);\n } catch (_error) {\n // silently ignore invalid messages for now\n // TODO: log errors with log levels\n return options.onMessage?.(message);\n }\n if (parsedMessage.type === MessageType.CF_AGENT_STATE) {\n options.onStateUpdate?.(parsedMessage.state as State, \"server\");\n return;\n }\n if (parsedMessage.type === MessageType.CF_AGENT_MCP_SERVERS) {\n options.onMcpUpdate?.(parsedMessage.mcp as MCPServersState);\n return;\n }\n if (parsedMessage.type === MessageType.RPC) {\n const response = parsedMessage as RPCResponse;\n const pending = pendingCallsRef.current.get(response.id);\n if (!pending) return;\n\n if (!response.success) {\n pending.reject(new Error(response.error));\n pendingCallsRef.current.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 pendingCallsRef.current.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 pendingCallsRef.current.delete(response.id);\n }\n return;\n }\n }\n options.onMessage?.(message);\n }\n }) as PartySocket & {\n agent: string;\n name: string;\n setState: (state: State) => void;\n call: UntypedAgentMethodCall;\n stub: UntypedAgentStub;\n };\n // Create the call method\n const call = useCallback(\n <T = unknown,>(\n method: string,\n args: unknown[] = [],\n streamOptions?: StreamOptions\n ): Promise<T> => {\n return new Promise((resolve, reject) => {\n const id = Math.random().toString(36).slice(2);\n pendingCallsRef.current.set(id, {\n reject,\n resolve: resolve as (value: unknown) => void,\n stream: streamOptions\n });\n\n const request: RPCRequest = {\n args,\n id,\n method,\n type: MessageType.RPC\n };\n\n agent.send(JSON.stringify(request));\n });\n },\n [agent]\n );\n\n agent.setState = (state: State) => {\n agent.send(JSON.stringify({ state, type: MessageType.CF_AGENT_STATE }));\n options.onStateUpdate?.(state, \"client\");\n };\n\n agent.call = call;\n agent.agent = agentNamespace;\n agent.name = options.name || \"default\";\n // biome-ignore lint: suppressions/parse\n agent.stub = new Proxy<any>(\n {},\n {\n get: (_target, method) => {\n return (...args: unknown[]) => {\n return call(method as string, args);\n };\n }\n }\n );\n\n // warn if agent isn't in lowercase\n if (agent.agent !== agent.agent.toLowerCase()) {\n console.warn(\n `Agent name: ${agent.agent} should probably be in lowercase. Received: ${agent.agent}`\n );\n }\n\n return agent;\n}\n"],"mappings":";;;;;;;;;;AAaA,SAAS,qBAAqB,KAAqB;AAEjD,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;;AAKxD,MAAM,6BAAa,IAAI,KAQpB;AAEH,SAAS,YAAY,GAAc,GAAuB;AACxD,KAAI,MAAM,EAAG,QAAO;AACpB,KAAI,EAAE,WAAW,EAAE,OAAQ,QAAO;AAElC,MAAK,IAAI,IAAI,GAAG,IAAI,EAAE,QAAQ,IAC5B,KAAI,CAAC,OAAO,GAAG,EAAE,IAAI,EAAE,GAAG,CAAE,QAAO;AAErC,QAAO;;AAGT,SAAS,eACP,WACkC;AAClC,MAAK,MAAM,CAAC,aAAa,UAAU,WAAW,SAAS,CACrD,KAAI,YAAY,aAAa,UAAU,EAAE;AAEvC,MAAI,KAAK,KAAK,GAAG,MAAM,WAAW;AAChC,cAAW,OAAO,YAAY;AAC9B;;AAEF,QAAM;AACN,SAAO,MAAM;;;AAMnB,SAAS,cACP,KACA,OACA,UACM;AAEN,MAAK,MAAM,CAAC,gBAAgB,WAAW,SAAS,CAC9C,KAAI,YAAY,aAAa,IAAI,EAAE;AACjC,aAAW,OAAO,YAAY;AAC9B;;CAIJ,MAAM,YACJ,aAAa,SAAY,KAAK,KAAK,GAAG,WAAW,KAAK,KAAK,GAAG,MAAS;AACzE,YAAW,IAAI,KAAK;EAAE,SAAS;EAAO,UAAU;EAAG;EAAW;EAAU,CAAC;;AAG3E,SAAS,oBAAoB,WAA+B;AAC1D,MAAK,MAAM,CAAC,aAAa,UAAU,WAAW,SAAS,CACrD,KAAI,YAAY,aAAa,UAAU,EAAE;AACvC,QAAM;AACN,MAAI,MAAM,YAAY,EACpB,YAAW,OAAO,YAAY;AAEhC,SAAO;;AAGX,QAAO;;AAIT,MAAa,aAAa;CACxB;CACA;CACA;CACA;CACA,kBAAkB,WAAW,OAAO;CACrC;AAED,SAAS,eACP,gBACA,MACA,MACW;AACX,QAAO;EAAC;EAAgB,QAAQ;EAAW,GAAG;EAAK;;AA2HrD,SAAgB,SACd,SAOA;CACA,MAAM,iBAAiB,qBAAqB,QAAQ,MAAM;CAC1D,MAAM,EAAE,OAAO,WAAW,UAAU,GAAG,gBAAgB;CAGvD,MAAM,kBAAkB,uBACtB,IAAI,KAOD,CACJ;CAGD,MAAM,WAAW,cAAc;EAC7B,MAAM,OAAO,aAAa,EAAE;AAC5B,SAAO,eAAe,gBAAgB,QAAQ,MAAM,KAAK;IACxD;EAAC;EAAgB,QAAQ;EAAM;EAAU,CAAC;CAE7C,MAAM,eAAe,cAAc;AACjC,MAAI,CAAC,SAAS,OAAO,UAAU,WAC7B,QAAO;EAGT,MAAM,kBAAkB,eAAe,SAAS;AAChD,MAAI,gBACF,QAAO;EAGT,MAAM,UAAU,OAAO,CAAC,OAAO,UAAU;AACvC,WAAQ,MACN,sCAAsC,QAAQ,MAAM,KACpD,MACD;AACD,uBAAoB,SAAS;AAC7B,SAAM;IACN;AAEF,gBAAc,UAAU,SAAS,SAAS;AAE1C,SAAO;IACN;EAAC;EAAU;EAAO,QAAQ;EAAO;EAAS,CAAC;CAE9C,IAAIA;AAEJ,KAAI,MACF,KAAI,OAAO,UAAU,YAAY;EAE/B,MAAM,cAAc,IAAI,aAAc;AAGtC,MAAI,aAAa;AACf,QAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,YAAY,CACpD,KACE,UAAU,QACV,UAAU,UACV,OAAO,UAAU,YACjB,OAAO,UAAU,YACjB,OAAO,UAAU,UAEjB,SAAQ,KACN,+BAA+B,IAAI,yHAEpC;AAGL,mBAAgB;;OAIlB,iBAAgB;AAKpB,iBAAgB;AACd,eAAa;AACX,OAAI,aACF,qBAAoB,SAAS;;IAGhC,CAAC,UAAU,aAAa,CAAC;CAE5B,MAAM,QAAQ,eAAe;EAC3B,OAAO;EACP,QAAQ;EACR,MAAM,QAAQ,QAAQ;EACtB,OAAO;EACP,GAAG;EACH,YAAY,YAAY;AACtB,OAAI,OAAO,QAAQ,SAAS,UAAU;IACpC,IAAIC;AACJ,QAAI;AACF,qBAAgB,KAAK,MAAM,QAAQ,KAAK;aACjC,QAAQ;AAGf,YAAO,QAAQ,YAAY,QAAQ;;AAErC,QAAI,cAAc,SAAS,YAAY,gBAAgB;AACrD,aAAQ,gBAAgB,cAAc,OAAgB,SAAS;AAC/D;;AAEF,QAAI,cAAc,SAAS,YAAY,sBAAsB;AAC3D,aAAQ,cAAc,cAAc,IAAuB;AAC3D;;AAEF,QAAI,cAAc,SAAS,YAAY,KAAK;KAC1C,MAAM,WAAW;KACjB,MAAM,UAAU,gBAAgB,QAAQ,IAAI,SAAS,GAAG;AACxD,SAAI,CAAC,QAAS;AAEd,SAAI,CAAC,SAAS,SAAS;AACrB,cAAQ,OAAO,IAAI,MAAM,SAAS,MAAM,CAAC;AACzC,sBAAgB,QAAQ,OAAO,SAAS,GAAG;AAC3C,cAAQ,QAAQ,UAAU,SAAS,MAAM;AACzC;;AAIF,SAAI,UAAU,SACZ,KAAI,SAAS,MAAM;AACjB,cAAQ,QAAQ,SAAS,OAAO;AAChC,sBAAgB,QAAQ,OAAO,SAAS,GAAG;AAC3C,cAAQ,QAAQ,SAAS,SAAS,OAAO;WAEzC,SAAQ,QAAQ,UAAU,SAAS,OAAO;UAEvC;AAEL,cAAQ,QAAQ,SAAS,OAAO;AAChC,sBAAgB,QAAQ,OAAO,SAAS,GAAG;;AAE7C;;;AAGJ,WAAQ,YAAY,QAAQ;;EAE/B,CAAC;CAQF,MAAM,OAAO,aAET,QACA,OAAkB,EAAE,EACpB,kBACe;AACf,SAAO,IAAI,SAAS,SAAS,WAAW;GACtC,MAAM,KAAK,KAAK,QAAQ,CAAC,SAAS,GAAG,CAAC,MAAM,EAAE;AAC9C,mBAAgB,QAAQ,IAAI,IAAI;IAC9B;IACS;IACT,QAAQ;IACT,CAAC;GAEF,MAAMC,UAAsB;IAC1B;IACA;IACA;IACA,MAAM,YAAY;IACnB;AAED,SAAM,KAAK,KAAK,UAAU,QAAQ,CAAC;IACnC;IAEJ,CAAC,MAAM,CACR;AAED,OAAM,YAAY,UAAiB;AACjC,QAAM,KAAK,KAAK,UAAU;GAAE;GAAO,MAAM,YAAY;GAAgB,CAAC,CAAC;AACvE,UAAQ,gBAAgB,OAAO,SAAS;;AAG1C,OAAM,OAAO;AACb,OAAM,QAAQ;AACd,OAAM,OAAO,QAAQ,QAAQ;AAE7B,OAAM,OAAO,IAAI,MACf,EAAE,EACF,EACE,MAAM,SAAS,WAAW;AACxB,UAAQ,GAAG,SAAoB;AAC7B,UAAO,KAAK,QAAkB,KAAK;;IAGxC,CACF;AAGD,KAAI,MAAM,UAAU,MAAM,MAAM,aAAa,CAC3C,SAAQ,KACN,eAAe,MAAM,MAAM,8CAA8C,MAAM,QAChF;AAGH,QAAO"}
1
+ {"version":3,"file":"react.js","names":["entry: CacheEntry","resolvedQuery: QueryObject | undefined","parsedMessage: Record<string, unknown>","request: RPCRequest"],"sources":["../src/react.tsx"],"sourcesContent":["import type { PartySocket } from \"partysocket\";\nimport { usePartySocket } from \"partysocket/react\";\nimport { useCallback, useRef, use, useMemo, useState, useEffect } from \"react\";\nimport type { Agent, MCPServersState, RPCRequest, RPCResponse } from \"./\";\nimport type { StreamOptions } from \"./client\";\nimport type { Method, RPCMethod } from \"./serializable\";\nimport { MessageType } from \"./ai-types\";\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 */\nfunction 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\ntype QueryObject = Record<string, string | null>;\n\ninterface CacheEntry {\n promise: Promise<QueryObject>;\n expiresAt: number;\n}\n\nconst queryCache = new Map<string, CacheEntry>();\n\nfunction createCacheKey(\n agentNamespace: string,\n name: string | undefined,\n deps: unknown[]\n): string {\n return JSON.stringify([agentNamespace, name || \"default\", ...deps]);\n}\n\nfunction getCacheEntry(key: string): CacheEntry | undefined {\n const entry = queryCache.get(key);\n if (!entry) return undefined;\n\n if (Date.now() >= entry.expiresAt) {\n queryCache.delete(key);\n return undefined;\n }\n\n return entry;\n}\n\nfunction setCacheEntry(\n key: string,\n promise: Promise<QueryObject>,\n cacheTtl: number\n): CacheEntry {\n const entry: CacheEntry = {\n promise,\n expiresAt: Date.now() + cacheTtl\n };\n queryCache.set(key, entry);\n return entry;\n}\n\nfunction deleteCacheEntry(key: string): void {\n queryCache.delete(key);\n}\n\n// Export for testing purposes\nexport const _testUtils = {\n queryCache,\n setCacheEntry,\n getCacheEntry,\n deleteCacheEntry,\n clearCache: () => queryCache.clear()\n};\n\n/**\n * Options for the useAgent hook\n * @template State Type of the Agent's state\n */\nexport type UseAgentOptions<State = unknown> = Omit<\n Parameters<typeof usePartySocket>[0],\n \"party\" | \"room\" | \"query\"\n> & {\n /** Name of the agent to connect to */\n agent: string;\n /** Name of the specific Agent instance */\n name?: string;\n /** Query parameters - can be static object or async function */\n query?: QueryObject | (() => Promise<QueryObject>);\n /** Dependencies for async query caching */\n queryDeps?: unknown[];\n /** Cache TTL in milliseconds for auth tokens/time-sensitive data */\n cacheTtl?: number;\n /** Called when the Agent's state is updated */\n onStateUpdate?: (state: State, source: \"server\" | \"client\") => void;\n /** Called when MCP server state is updated */\n onMcpUpdate?: (mcpServers: MCPServersState) => void;\n};\n\ntype AllOptional<T> = T extends [infer A, ...infer R]\n ? undefined extends A\n ? AllOptional<R>\n : false\n : true; // no params means optional by default\n\ntype RPCMethods<T> = {\n [K in keyof T as T[K] extends RPCMethod<T[K]> ? K : never]: RPCMethod<T[K]>;\n};\n\ntype OptionalParametersMethod<T extends RPCMethod> =\n AllOptional<Parameters<T>> extends true ? T : never;\n\n// all methods of the Agent, excluding the ones that are declared in the base Agent class\n// biome-ignore lint: suppressions/parse\ntype AgentMethods<T> = Omit<RPCMethods<T>, keyof Agent<any, any>>;\n\ntype OptionalAgentMethods<T> = {\n [K in keyof AgentMethods<T> as AgentMethods<T>[K] extends OptionalParametersMethod<\n AgentMethods<T>[K]\n >\n ? K\n : never]: OptionalParametersMethod<AgentMethods<T>[K]>;\n};\n\ntype RequiredAgentMethods<T> = Omit<\n AgentMethods<T>,\n keyof OptionalAgentMethods<T>\n>;\n\ntype AgentPromiseReturnType<T, K extends keyof AgentMethods<T>> =\n // biome-ignore lint: suppressions/parse\n ReturnType<AgentMethods<T>[K]> extends Promise<any>\n ? ReturnType<AgentMethods<T>[K]>\n : Promise<ReturnType<AgentMethods<T>[K]>>;\n\ntype OptionalArgsAgentMethodCall<AgentT> = <\n K extends keyof OptionalAgentMethods<AgentT>\n>(\n method: K,\n args?: Parameters<OptionalAgentMethods<AgentT>[K]>,\n streamOptions?: StreamOptions\n) => AgentPromiseReturnType<AgentT, K>;\n\ntype RequiredArgsAgentMethodCall<AgentT> = <\n K extends keyof RequiredAgentMethods<AgentT>\n>(\n method: K,\n args: Parameters<RequiredAgentMethods<AgentT>[K]>,\n streamOptions?: StreamOptions\n) => AgentPromiseReturnType<AgentT, K>;\n\ntype AgentMethodCall<AgentT> = OptionalArgsAgentMethodCall<AgentT> &\n RequiredArgsAgentMethodCall<AgentT>;\n\ntype UntypedAgentMethodCall = <T = unknown>(\n method: string,\n args?: unknown[],\n streamOptions?: StreamOptions\n) => Promise<T>;\n\ntype AgentStub<T> = {\n [K in keyof AgentMethods<T>]: (\n ...args: Parameters<AgentMethods<T>[K]>\n ) => AgentPromiseReturnType<AgentMethods<T>, K>;\n};\n\n// we neet to use Method instead of RPCMethod here for retro-compatibility\ntype UntypedAgentStub = Record<string, Method>;\n\n/**\n * React hook for connecting to an Agent\n */\nexport function useAgent<State = unknown>(\n options: UseAgentOptions<State>\n): PartySocket & {\n agent: string;\n name: string;\n setState: (state: State) => void;\n call: UntypedAgentMethodCall;\n stub: UntypedAgentStub;\n};\nexport function useAgent<\n AgentT extends {\n get state(): State;\n },\n State\n>(\n options: UseAgentOptions<State>\n): PartySocket & {\n agent: string;\n name: string;\n setState: (state: State) => void;\n call: AgentMethodCall<AgentT>;\n stub: AgentStub<AgentT>;\n};\nexport function useAgent<State>(\n options: UseAgentOptions<unknown>\n): PartySocket & {\n agent: string;\n name: string;\n setState: (state: State) => void;\n call: UntypedAgentMethodCall | AgentMethodCall<unknown>;\n stub: UntypedAgentStub;\n} {\n const agentNamespace = camelCaseToKebabCase(options.agent);\n const { query, queryDeps, cacheTtl, ...restOptions } = options;\n\n // Keep track of pending RPC calls\n const pendingCallsRef = useRef(\n new Map<\n string,\n {\n resolve: (value: unknown) => void;\n reject: (error: Error) => void;\n stream?: StreamOptions;\n }\n >()\n );\n\n const cacheKey = useMemo(\n () => createCacheKey(agentNamespace, options.name, queryDeps || []),\n [agentNamespace, options.name, queryDeps]\n );\n\n const ttl = cacheTtl ?? 5 * 60 * 1000;\n\n // Track cache invalidation to force re-render when TTL expires\n const [cacheInvalidatedAt, setCacheInvalidatedAt] = useState<number>(0);\n\n // Get or create the query promise\n // biome-ignore lint/correctness/useExhaustiveDependencies: cacheInvalidatedAt intentionally forces re-evaluation when TTL expires\n const queryPromise = useMemo(() => {\n if (!query || typeof query !== \"function\") {\n return null;\n }\n\n // Always check cache first to deduplicate concurrent requests\n const cached = getCacheEntry(cacheKey);\n if (cached) {\n return cached.promise;\n }\n\n // Create new promise\n const promise = query().catch((error) => {\n console.error(\n `[useAgent] Query failed for agent \"${options.agent}\":`,\n error\n );\n deleteCacheEntry(cacheKey);\n throw error;\n });\n\n // Always cache to deduplicate concurrent requests\n setCacheEntry(cacheKey, promise, ttl);\n\n return promise;\n }, [cacheKey, query, options.agent, ttl, cacheInvalidatedAt]);\n\n // Schedule cache invalidation when TTL expires\n useEffect(() => {\n if (!queryPromise || ttl <= 0) return;\n\n const entry = getCacheEntry(cacheKey);\n if (!entry) return;\n\n const timeUntilExpiry = entry.expiresAt - Date.now();\n\n // Always set a timer (with min 0ms) to ensure cleanup function is returned\n const timer = setTimeout(\n () => {\n deleteCacheEntry(cacheKey);\n setCacheInvalidatedAt(Date.now());\n },\n Math.max(0, timeUntilExpiry)\n );\n\n return () => clearTimeout(timer);\n }, [cacheKey, queryPromise, ttl]);\n\n let resolvedQuery: QueryObject | undefined;\n\n if (query) {\n if (typeof query === \"function\") {\n // Use React's use() to resolve the promise\n const queryResult = use(queryPromise!);\n\n // Check for non-primitive values and warn\n if (queryResult) {\n for (const [key, value] of Object.entries(queryResult)) {\n if (\n value !== null &&\n value !== undefined &&\n typeof value !== \"string\" &&\n typeof value !== \"number\" &&\n typeof value !== \"boolean\"\n ) {\n console.warn(\n `[useAgent] Query parameter \"${key}\" is an object and will be converted to \"[object Object]\". ` +\n \"Query parameters should be string, number, boolean, or null.\"\n );\n }\n }\n resolvedQuery = queryResult;\n }\n } else {\n // Sync query - use directly\n resolvedQuery = query;\n }\n }\n\n const agent = usePartySocket({\n party: agentNamespace,\n prefix: \"agents\",\n room: options.name || \"default\",\n query: resolvedQuery,\n ...restOptions,\n onMessage: (message) => {\n if (typeof message.data === \"string\") {\n let parsedMessage: Record<string, unknown>;\n try {\n parsedMessage = JSON.parse(message.data);\n } catch (_error) {\n // silently ignore invalid messages for now\n // TODO: log errors with log levels\n return options.onMessage?.(message);\n }\n if (parsedMessage.type === MessageType.CF_AGENT_STATE) {\n options.onStateUpdate?.(parsedMessage.state as State, \"server\");\n return;\n }\n if (parsedMessage.type === MessageType.CF_AGENT_MCP_SERVERS) {\n options.onMcpUpdate?.(parsedMessage.mcp as MCPServersState);\n return;\n }\n if (parsedMessage.type === MessageType.RPC) {\n const response = parsedMessage as RPCResponse;\n const pending = pendingCallsRef.current.get(response.id);\n if (!pending) return;\n\n if (!response.success) {\n pending.reject(new Error(response.error));\n pendingCallsRef.current.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 pendingCallsRef.current.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 pendingCallsRef.current.delete(response.id);\n }\n return;\n }\n }\n options.onMessage?.(message);\n }\n }) as PartySocket & {\n agent: string;\n name: string;\n setState: (state: State) => void;\n call: UntypedAgentMethodCall;\n stub: UntypedAgentStub;\n };\n // Create the call method\n const call = useCallback(\n <T = unknown,>(\n method: string,\n args: unknown[] = [],\n streamOptions?: StreamOptions\n ): Promise<T> => {\n return new Promise((resolve, reject) => {\n const id = Math.random().toString(36).slice(2);\n pendingCallsRef.current.set(id, {\n reject,\n resolve: resolve as (value: unknown) => void,\n stream: streamOptions\n });\n\n const request: RPCRequest = {\n args,\n id,\n method,\n type: MessageType.RPC\n };\n\n agent.send(JSON.stringify(request));\n });\n },\n [agent]\n );\n\n agent.setState = (state: State) => {\n agent.send(JSON.stringify({ state, type: MessageType.CF_AGENT_STATE }));\n options.onStateUpdate?.(state, \"client\");\n };\n\n agent.call = call;\n agent.agent = agentNamespace;\n agent.name = options.name || \"default\";\n // biome-ignore lint: suppressions/parse\n agent.stub = new Proxy<any>(\n {},\n {\n get: (_target, method) => {\n return (...args: unknown[]) => {\n return call(method as string, args);\n };\n }\n }\n );\n\n // warn if agent isn't in lowercase\n if (agent.agent !== agent.agent.toLowerCase()) {\n console.warn(\n `Agent name: ${agent.agent} should probably be in lowercase. Received: ${agent.agent}`\n );\n }\n\n return agent;\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { t as agentContext } from "./context-BkKbAa1R.js";
2
- import { t as MessageType } from "./ai-types-CwgHzwUb.js";
3
- import { r as camelCaseToKebabCase } from "./client-CcyhkGfN.js";
2
+ import { t as MessageType } from "./ai-types-DEtF_8Km.js";
3
+ import { r as camelCaseToKebabCase } from "./client-DjTPRM8-.js";
4
4
  import { i as DisposableStore, r as MCPConnectionState, t as MCPClientManager } from "./client-QZa2Rq0l.js";
5
5
  import { t as DurableObjectOAuthClientProvider } from "./do-oauth-client-provider-B1fVIshX.js";
6
6
  import { parseCronExpression } from "cron-schedule";
@@ -1178,4 +1178,4 @@ var StreamingResponse = class {
1178
1178
 
1179
1179
  //#endregion
1180
1180
  export { createCatchAllEmailResolver as a, getCurrentAgent as c, unstable_callable as d, genericObservability as f, createAddressBasedEmailResolver as i, routeAgentEmail as l, StreamingResponse as n, createHeaderBasedEmailResolver as o, callable as r, getAgentByName as s, Agent as t, routeAgentRequest as u };
1181
- //# sourceMappingURL=src-BmbDclOA.js.map
1181
+ //# sourceMappingURL=src-BZDh910Z.js.map