agents 0.3.10 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/{index-N6791tVt.d.ts → agent-DY6QmSI_.d.ts} +3 -25
- package/dist/ai-types.js +1 -1
- package/dist/client-connection-CGMuV62J.js +472 -0
- package/dist/client-connection-CGMuV62J.js.map +1 -0
- package/dist/client-storage-Cvy5r9FG.d.ts +355 -0
- package/dist/client.d.ts +11 -7
- package/dist/client.js +6 -2
- package/dist/client.js.map +1 -1
- package/dist/email.d.ts +146 -16
- package/dist/email.js +222 -2
- package/dist/email.js.map +1 -0
- package/dist/index.d.ts +138 -41
- package/dist/index.js +2317 -6
- package/dist/index.js.map +1 -0
- package/dist/internal_context.d.ts +28 -5
- package/dist/internal_context.js +7 -2
- package/dist/internal_context.js.map +1 -0
- package/dist/mcp/client.d.ts +516 -2
- package/dist/mcp/client.js +662 -3
- package/dist/mcp/client.js.map +1 -0
- package/dist/mcp/do-oauth-client-provider.d.ts +61 -2
- package/dist/mcp/do-oauth-client-provider.js +154 -2
- package/dist/mcp/do-oauth-client-provider.js.map +1 -0
- package/dist/mcp/index.d.ts +3 -5
- package/dist/mcp/index.js +8 -7
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/x402.d.ts +34 -14
- package/dist/mcp/x402.js +128 -66
- package/dist/mcp/x402.js.map +1 -1
- package/dist/{mcp-BwPscEiF.d.ts → mcp-Dw5vDrY8.d.ts} +1 -1
- package/dist/observability/index.d.ts +23 -2
- package/dist/observability/index.js +25 -6
- package/dist/observability/index.js.map +1 -0
- package/dist/react.d.ts +10 -10
- package/dist/react.js +6 -2
- package/dist/react.js.map +1 -1
- package/dist/types.d.ts +14 -1
- package/dist/types.js +16 -2
- package/dist/types.js.map +1 -0
- package/dist/utils.js +15 -2
- package/dist/utils.js.map +1 -0
- package/dist/workflow-types.d.ts +235 -23
- package/dist/workflows.d.ts +22 -24
- package/dist/workflows.js +2 -5
- package/dist/workflows.js.map +1 -1
- package/package.json +24 -23
- package/dist/client-CtC9E06G.js +0 -1122
- package/dist/client-CtC9E06G.js.map +0 -1
- package/dist/client-DV1CZKqa.d.ts +0 -969
- package/dist/do-oauth-client-provider-BqnOQzjy.d.ts +0 -70
- package/dist/do-oauth-client-provider-DDg8QrEA.js +0 -155
- package/dist/do-oauth-client-provider-DDg8QrEA.js.map +0 -1
- package/dist/email-8ljcpvwV.d.ts +0 -157
- package/dist/email-XHsSYsTO.js +0 -223
- package/dist/email-XHsSYsTO.js.map +0 -1
- package/dist/internal_context-CEu5ji80.d.ts +0 -29
- package/dist/internal_context-D9eKFth1.js +0 -8
- package/dist/internal_context-D9eKFth1.js.map +0 -1
- package/dist/src-i_UcyBYf.js +0 -2147
- package/dist/src-i_UcyBYf.js.map +0 -1
- package/dist/types-BITaDFf-.js +0 -16
- package/dist/types-BITaDFf-.js.map +0 -1
- package/dist/types-DSSHBW6w.d.ts +0 -14
- package/dist/utils-B49TmLCI.js +0 -16
- package/dist/utils-B49TmLCI.js.map +0 -1
- package/dist/workflow-types-Z_Oem1FJ.d.ts +0 -260
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
import { t as MCPObservabilityEvent } from "./mcp-Dw5vDrY8.js";
|
|
2
|
+
import { AgentMcpOAuthProvider } from "./mcp/do-oauth-client-provider.js";
|
|
3
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
4
|
+
import {
|
|
5
|
+
SSEClientTransport,
|
|
6
|
+
SSEClientTransportOptions
|
|
7
|
+
} from "@modelcontextprotocol/sdk/client/sse.js";
|
|
8
|
+
import {
|
|
9
|
+
StreamableHTTPClientTransport,
|
|
10
|
+
StreamableHTTPClientTransportOptions
|
|
11
|
+
} from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
12
|
+
import {
|
|
13
|
+
ElicitRequest,
|
|
14
|
+
ElicitResult,
|
|
15
|
+
Prompt,
|
|
16
|
+
Resource,
|
|
17
|
+
ResourceTemplate,
|
|
18
|
+
ServerCapabilities,
|
|
19
|
+
Tool
|
|
20
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
21
|
+
|
|
22
|
+
//#region src/core/events.d.ts
|
|
23
|
+
interface Disposable {
|
|
24
|
+
dispose(): void;
|
|
25
|
+
}
|
|
26
|
+
type Event<T> = (listener: (e: T) => void) => Disposable;
|
|
27
|
+
declare class Emitter<T> implements Disposable {
|
|
28
|
+
private _listeners;
|
|
29
|
+
readonly event: Event<T>;
|
|
30
|
+
fire(data: T): void;
|
|
31
|
+
dispose(): void;
|
|
32
|
+
}
|
|
33
|
+
//#endregion
|
|
34
|
+
//#region src/mcp/types.d.ts
|
|
35
|
+
type MaybePromise<T> = T | Promise<T>;
|
|
36
|
+
type BaseTransportType = "sse" | "streamable-http";
|
|
37
|
+
type TransportType = BaseTransportType | "auto";
|
|
38
|
+
interface CORSOptions {
|
|
39
|
+
origin?: string;
|
|
40
|
+
methods?: string;
|
|
41
|
+
headers?: string;
|
|
42
|
+
maxAge?: number;
|
|
43
|
+
exposeHeaders?: string;
|
|
44
|
+
}
|
|
45
|
+
interface ServeOptions {
|
|
46
|
+
binding?: string;
|
|
47
|
+
corsOptions?: CORSOptions;
|
|
48
|
+
transport?: BaseTransportType;
|
|
49
|
+
jurisdiction?: DurableObjectJurisdiction;
|
|
50
|
+
}
|
|
51
|
+
//#endregion
|
|
52
|
+
//#region src/mcp/client-connection.d.ts
|
|
53
|
+
/**
|
|
54
|
+
* Connection state machine for MCP client connections.
|
|
55
|
+
*
|
|
56
|
+
* State transitions:
|
|
57
|
+
* - Non-OAuth: init() → CONNECTING → DISCOVERING → READY
|
|
58
|
+
* - OAuth: init() → AUTHENTICATING → (callback) → CONNECTING → DISCOVERING → READY
|
|
59
|
+
* - Any state can transition to FAILED on error
|
|
60
|
+
*/
|
|
61
|
+
declare const MCPConnectionState: {
|
|
62
|
+
/** Waiting for OAuth authorization to complete */ readonly AUTHENTICATING: "authenticating" /** Establishing transport connection to MCP server */;
|
|
63
|
+
readonly CONNECTING: "connecting" /** Transport connection established */;
|
|
64
|
+
readonly CONNECTED: "connected" /** Discovering server capabilities (tools, resources, prompts) */;
|
|
65
|
+
readonly DISCOVERING: "discovering" /** Fully connected and ready to use */;
|
|
66
|
+
readonly READY: "ready" /** Connection failed at some point */;
|
|
67
|
+
readonly FAILED: "failed";
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* Connection state type for MCP client connections.
|
|
71
|
+
*/
|
|
72
|
+
type MCPConnectionState =
|
|
73
|
+
(typeof MCPConnectionState)[keyof typeof MCPConnectionState];
|
|
74
|
+
type MCPTransportOptions = (
|
|
75
|
+
| SSEClientTransportOptions
|
|
76
|
+
| StreamableHTTPClientTransportOptions
|
|
77
|
+
) & {
|
|
78
|
+
authProvider?: AgentMcpOAuthProvider;
|
|
79
|
+
type?: TransportType;
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* Result of a discovery operation.
|
|
83
|
+
* success indicates whether discovery completed successfully.
|
|
84
|
+
* error is present when success is false.
|
|
85
|
+
*/
|
|
86
|
+
type MCPDiscoveryResult = {
|
|
87
|
+
success: boolean;
|
|
88
|
+
error?: string;
|
|
89
|
+
};
|
|
90
|
+
declare class MCPClientConnection {
|
|
91
|
+
url: URL;
|
|
92
|
+
options: {
|
|
93
|
+
transport: MCPTransportOptions;
|
|
94
|
+
client: ConstructorParameters<typeof Client>[1];
|
|
95
|
+
};
|
|
96
|
+
client: Client;
|
|
97
|
+
connectionState: MCPConnectionState;
|
|
98
|
+
connectionError: string | null;
|
|
99
|
+
lastConnectedTransport: BaseTransportType | undefined;
|
|
100
|
+
instructions?: string;
|
|
101
|
+
tools: Tool[];
|
|
102
|
+
prompts: Prompt[];
|
|
103
|
+
resources: Resource[];
|
|
104
|
+
resourceTemplates: ResourceTemplate[];
|
|
105
|
+
serverCapabilities: ServerCapabilities | undefined;
|
|
106
|
+
/** Tracks in-flight discovery to allow cancellation */
|
|
107
|
+
private _discoveryAbortController;
|
|
108
|
+
private readonly _onObservabilityEvent;
|
|
109
|
+
readonly onObservabilityEvent: Event<MCPObservabilityEvent>;
|
|
110
|
+
constructor(
|
|
111
|
+
url: URL,
|
|
112
|
+
info: ConstructorParameters<typeof Client>[0],
|
|
113
|
+
options?: {
|
|
114
|
+
transport: MCPTransportOptions;
|
|
115
|
+
client: ConstructorParameters<typeof Client>[1];
|
|
116
|
+
}
|
|
117
|
+
);
|
|
118
|
+
/**
|
|
119
|
+
* Initialize a client connection, if authentication is required, the connection will be in the AUTHENTICATING state
|
|
120
|
+
* Sets connection state based on the result and emits observability events
|
|
121
|
+
*
|
|
122
|
+
* @returns Error message if connection failed, undefined otherwise
|
|
123
|
+
*/
|
|
124
|
+
init(): Promise<string | undefined>;
|
|
125
|
+
/**
|
|
126
|
+
* Finish OAuth by probing transports based on configured type.
|
|
127
|
+
* - Explicit: finish on that transport
|
|
128
|
+
* - Auto: try streamable-http, then sse on 404/405/Not Implemented
|
|
129
|
+
*/
|
|
130
|
+
private finishAuthProbe;
|
|
131
|
+
/**
|
|
132
|
+
* Complete OAuth authorization
|
|
133
|
+
*/
|
|
134
|
+
completeAuthorization(code: string): Promise<void>;
|
|
135
|
+
/**
|
|
136
|
+
* Discover server capabilities and register tools, resources, prompts, and templates.
|
|
137
|
+
* This method does the work but does not manage connection state - that's handled by discover().
|
|
138
|
+
*/
|
|
139
|
+
discoverAndRegister(): Promise<void>;
|
|
140
|
+
/**
|
|
141
|
+
* Discover server capabilities with timeout and cancellation support.
|
|
142
|
+
* If called while a previous discovery is in-flight, the previous discovery will be aborted.
|
|
143
|
+
*
|
|
144
|
+
* @param options Optional configuration
|
|
145
|
+
* @param options.timeoutMs Timeout in milliseconds (default: 15000)
|
|
146
|
+
* @returns Result indicating success/failure with optional error message
|
|
147
|
+
*/
|
|
148
|
+
discover(options?: { timeoutMs?: number }): Promise<MCPDiscoveryResult>;
|
|
149
|
+
/**
|
|
150
|
+
* Cancel any in-flight discovery operation.
|
|
151
|
+
* Called when closing the connection.
|
|
152
|
+
*/
|
|
153
|
+
cancelDiscovery(): void;
|
|
154
|
+
/**
|
|
155
|
+
* Notification handler registration for tools
|
|
156
|
+
* Should only be called if serverCapabilities.tools exists
|
|
157
|
+
*/
|
|
158
|
+
registerTools(): Promise<Tool[]>;
|
|
159
|
+
/**
|
|
160
|
+
* Notification handler registration for resources
|
|
161
|
+
* Should only be called if serverCapabilities.resources exists
|
|
162
|
+
*/
|
|
163
|
+
registerResources(): Promise<Resource[]>;
|
|
164
|
+
/**
|
|
165
|
+
* Notification handler registration for prompts
|
|
166
|
+
* Should only be called if serverCapabilities.prompts exists
|
|
167
|
+
*/
|
|
168
|
+
registerPrompts(): Promise<Prompt[]>;
|
|
169
|
+
registerResourceTemplates(): Promise<ResourceTemplate[]>;
|
|
170
|
+
fetchTools(): Promise<
|
|
171
|
+
{
|
|
172
|
+
inputSchema: {
|
|
173
|
+
[x: string]: unknown;
|
|
174
|
+
type: "object";
|
|
175
|
+
properties?:
|
|
176
|
+
| {
|
|
177
|
+
[x: string]: object;
|
|
178
|
+
}
|
|
179
|
+
| undefined;
|
|
180
|
+
required?: string[] | undefined;
|
|
181
|
+
};
|
|
182
|
+
name: string;
|
|
183
|
+
description?: string | undefined;
|
|
184
|
+
outputSchema?:
|
|
185
|
+
| {
|
|
186
|
+
[x: string]: unknown;
|
|
187
|
+
type: "object";
|
|
188
|
+
properties?:
|
|
189
|
+
| {
|
|
190
|
+
[x: string]: object;
|
|
191
|
+
}
|
|
192
|
+
| undefined;
|
|
193
|
+
required?: string[] | undefined;
|
|
194
|
+
}
|
|
195
|
+
| undefined;
|
|
196
|
+
annotations?:
|
|
197
|
+
| {
|
|
198
|
+
title?: string | undefined;
|
|
199
|
+
readOnlyHint?: boolean | undefined;
|
|
200
|
+
destructiveHint?: boolean | undefined;
|
|
201
|
+
idempotentHint?: boolean | undefined;
|
|
202
|
+
openWorldHint?: boolean | undefined;
|
|
203
|
+
}
|
|
204
|
+
| undefined;
|
|
205
|
+
execution?:
|
|
206
|
+
| {
|
|
207
|
+
taskSupport?: "optional" | "required" | "forbidden" | undefined;
|
|
208
|
+
}
|
|
209
|
+
| undefined;
|
|
210
|
+
_meta?:
|
|
211
|
+
| {
|
|
212
|
+
[x: string]: unknown;
|
|
213
|
+
}
|
|
214
|
+
| undefined;
|
|
215
|
+
icons?:
|
|
216
|
+
| {
|
|
217
|
+
src: string;
|
|
218
|
+
mimeType?: string | undefined;
|
|
219
|
+
sizes?: string[] | undefined;
|
|
220
|
+
theme?: "light" | "dark" | undefined;
|
|
221
|
+
}[]
|
|
222
|
+
| undefined;
|
|
223
|
+
title?: string | undefined;
|
|
224
|
+
}[]
|
|
225
|
+
>;
|
|
226
|
+
fetchResources(): Promise<
|
|
227
|
+
{
|
|
228
|
+
uri: string;
|
|
229
|
+
name: string;
|
|
230
|
+
description?: string | undefined;
|
|
231
|
+
mimeType?: string | undefined;
|
|
232
|
+
annotations?:
|
|
233
|
+
| {
|
|
234
|
+
audience?: ("user" | "assistant")[] | undefined;
|
|
235
|
+
priority?: number | undefined;
|
|
236
|
+
lastModified?: string | undefined;
|
|
237
|
+
}
|
|
238
|
+
| undefined;
|
|
239
|
+
_meta?:
|
|
240
|
+
| {
|
|
241
|
+
[x: string]: unknown;
|
|
242
|
+
}
|
|
243
|
+
| undefined;
|
|
244
|
+
icons?:
|
|
245
|
+
| {
|
|
246
|
+
src: string;
|
|
247
|
+
mimeType?: string | undefined;
|
|
248
|
+
sizes?: string[] | undefined;
|
|
249
|
+
theme?: "light" | "dark" | undefined;
|
|
250
|
+
}[]
|
|
251
|
+
| undefined;
|
|
252
|
+
title?: string | undefined;
|
|
253
|
+
}[]
|
|
254
|
+
>;
|
|
255
|
+
fetchPrompts(): Promise<
|
|
256
|
+
{
|
|
257
|
+
name: string;
|
|
258
|
+
description?: string | undefined;
|
|
259
|
+
arguments?:
|
|
260
|
+
| {
|
|
261
|
+
name: string;
|
|
262
|
+
description?: string | undefined;
|
|
263
|
+
required?: boolean | undefined;
|
|
264
|
+
}[]
|
|
265
|
+
| undefined;
|
|
266
|
+
_meta?:
|
|
267
|
+
| {
|
|
268
|
+
[x: string]: unknown;
|
|
269
|
+
}
|
|
270
|
+
| undefined;
|
|
271
|
+
icons?:
|
|
272
|
+
| {
|
|
273
|
+
src: string;
|
|
274
|
+
mimeType?: string | undefined;
|
|
275
|
+
sizes?: string[] | undefined;
|
|
276
|
+
theme?: "light" | "dark" | undefined;
|
|
277
|
+
}[]
|
|
278
|
+
| undefined;
|
|
279
|
+
title?: string | undefined;
|
|
280
|
+
}[]
|
|
281
|
+
>;
|
|
282
|
+
fetchResourceTemplates(): Promise<
|
|
283
|
+
{
|
|
284
|
+
uriTemplate: string;
|
|
285
|
+
name: string;
|
|
286
|
+
description?: string | undefined;
|
|
287
|
+
mimeType?: string | undefined;
|
|
288
|
+
annotations?:
|
|
289
|
+
| {
|
|
290
|
+
audience?: ("user" | "assistant")[] | undefined;
|
|
291
|
+
priority?: number | undefined;
|
|
292
|
+
lastModified?: string | undefined;
|
|
293
|
+
}
|
|
294
|
+
| undefined;
|
|
295
|
+
_meta?:
|
|
296
|
+
| {
|
|
297
|
+
[x: string]: unknown;
|
|
298
|
+
}
|
|
299
|
+
| undefined;
|
|
300
|
+
icons?:
|
|
301
|
+
| {
|
|
302
|
+
src: string;
|
|
303
|
+
mimeType?: string | undefined;
|
|
304
|
+
sizes?: string[] | undefined;
|
|
305
|
+
theme?: "light" | "dark" | undefined;
|
|
306
|
+
}[]
|
|
307
|
+
| undefined;
|
|
308
|
+
title?: string | undefined;
|
|
309
|
+
}[]
|
|
310
|
+
>;
|
|
311
|
+
/**
|
|
312
|
+
* Handle elicitation request from server
|
|
313
|
+
* Automatically uses the Agent's built-in elicitation handling if available
|
|
314
|
+
*/
|
|
315
|
+
handleElicitationRequest(_request: ElicitRequest): Promise<ElicitResult>;
|
|
316
|
+
/**
|
|
317
|
+
* Get the transport for the client
|
|
318
|
+
* @param transportType - The transport type to get
|
|
319
|
+
* @returns The transport for the client
|
|
320
|
+
*/
|
|
321
|
+
getTransport(
|
|
322
|
+
transportType: BaseTransportType
|
|
323
|
+
): StreamableHTTPClientTransport | SSEClientTransport;
|
|
324
|
+
private tryConnect;
|
|
325
|
+
private _capabilityErrorHandler;
|
|
326
|
+
}
|
|
327
|
+
//#endregion
|
|
328
|
+
//#region src/mcp/client-storage.d.ts
|
|
329
|
+
/**
|
|
330
|
+
* Represents a row in the cf_agents_mcp_servers table
|
|
331
|
+
*/
|
|
332
|
+
type MCPServerRow = {
|
|
333
|
+
id: string;
|
|
334
|
+
name: string;
|
|
335
|
+
server_url: string;
|
|
336
|
+
client_id: string | null;
|
|
337
|
+
auth_url: string | null;
|
|
338
|
+
callback_url: string;
|
|
339
|
+
server_options: string | null;
|
|
340
|
+
};
|
|
341
|
+
//#endregion
|
|
342
|
+
export {
|
|
343
|
+
BaseTransportType as a,
|
|
344
|
+
ServeOptions as c,
|
|
345
|
+
Event as d,
|
|
346
|
+
MCPTransportOptions as i,
|
|
347
|
+
TransportType as l,
|
|
348
|
+
MCPClientConnection as n,
|
|
349
|
+
CORSOptions as o,
|
|
350
|
+
MCPConnectionState as r,
|
|
351
|
+
MaybePromise as s,
|
|
352
|
+
MCPServerRow as t,
|
|
353
|
+
Emitter as u
|
|
354
|
+
};
|
|
355
|
+
//# sourceMappingURL=client-storage-Cvy5r9FG.d.ts.map
|
package/dist/client.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ type AgentClientOptions<State = unknown> = Omit<
|
|
|
13
13
|
PartySocketOptions,
|
|
14
14
|
"party" | "room"
|
|
15
15
|
> & {
|
|
16
|
-
/** Name of the agent to connect to (ignored if basePath is set) */ agent: string
|
|
16
|
+
/** Name of the agent to connect to (ignored if basePath is set) */ agent: string /** Name of the specific Agent instance (ignored if basePath is set) */;
|
|
17
17
|
name?: string;
|
|
18
18
|
/**
|
|
19
19
|
* Full URL path - bypasses agent/name URL construction.
|
|
@@ -23,8 +23,12 @@ type AgentClientOptions<State = unknown> = Omit<
|
|
|
23
23
|
* // Client connects to /user, server routes based on session
|
|
24
24
|
* useAgent({ agent: "UserAgent", basePath: "user" })
|
|
25
25
|
*/
|
|
26
|
-
basePath?: string
|
|
27
|
-
onStateUpdate?: (
|
|
26
|
+
basePath?: string /** Called when the Agent's state is updated */;
|
|
27
|
+
onStateUpdate?: (
|
|
28
|
+
state: State,
|
|
29
|
+
source: "server" | "client"
|
|
30
|
+
) => void /** Called when a state update fails (e.g., connection is readonly) */;
|
|
31
|
+
onStateUpdateError?: (error: string) => void;
|
|
28
32
|
/**
|
|
29
33
|
* Called when the server sends the agent's identity on connect.
|
|
30
34
|
* Useful when using basePath, as the actual instance name is determined server-side.
|
|
@@ -63,22 +67,22 @@ type AgentClientOptions<State = unknown> = Omit<
|
|
|
63
67
|
type StreamOptions = {
|
|
64
68
|
/** Called when a chunk of data is received */ onChunk?: (
|
|
65
69
|
chunk: unknown
|
|
66
|
-
) => void
|
|
67
|
-
onDone?: (finalChunk: unknown) => void
|
|
70
|
+
) => void /** Called when the stream ends */;
|
|
71
|
+
onDone?: (finalChunk: unknown) => void /** Called when an error occurs */;
|
|
68
72
|
onError?: (error: string) => void;
|
|
69
73
|
};
|
|
70
74
|
/**
|
|
71
75
|
* Options for RPC calls
|
|
72
76
|
*/
|
|
73
77
|
type CallOptions = {
|
|
74
|
-
/** Timeout in milliseconds. If the call doesn't complete within this time, it will be rejected. */ timeout?: number
|
|
78
|
+
/** Timeout in milliseconds. If the call doesn't complete within this time, it will be rejected. */ timeout?: number /** Streaming options for handling streaming responses */;
|
|
75
79
|
stream?: StreamOptions;
|
|
76
80
|
};
|
|
77
81
|
/**
|
|
78
82
|
* Options for the agentFetch function
|
|
79
83
|
*/
|
|
80
84
|
type AgentClientFetchOptions = Omit<PartyFetchOptions, "party" | "room"> & {
|
|
81
|
-
/** Name of the agent to connect to (ignored if basePath is set) */ agent: string
|
|
85
|
+
/** Name of the agent to connect to (ignored if basePath is set) */ agent: string /** Name of the specific Agent instance (ignored if basePath is set) */;
|
|
82
86
|
name?: string;
|
|
83
87
|
/**
|
|
84
88
|
* Full URL path - bypasses agent/name URL construction.
|
package/dist/client.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { MessageType } from "./types.js";
|
|
2
|
+
import { camelCaseToKebabCase } from "./utils.js";
|
|
3
3
|
import { PartySocket } from "partysocket";
|
|
4
4
|
|
|
5
5
|
//#region src/client.ts
|
|
@@ -84,6 +84,10 @@ var AgentClient = class extends PartySocket {
|
|
|
84
84
|
this.options.onStateUpdate?.(parsedMessage.state, "server");
|
|
85
85
|
return;
|
|
86
86
|
}
|
|
87
|
+
if (parsedMessage.type === MessageType.CF_AGENT_STATE_ERROR) {
|
|
88
|
+
this.options.onStateUpdateError?.(parsedMessage.error);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
87
91
|
if (parsedMessage.type === MessageType.RPC) {
|
|
88
92
|
const response = parsedMessage;
|
|
89
93
|
const pending = this._pendingCalls.get(response.id);
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","names":[],"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 \"./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 (ignored if basePath is set) */\n agent: string;\n /** Name of the specific Agent instance (ignored if basePath is set) */\n name?: string;\n /**\n * Full URL path - bypasses agent/name URL construction.\n * When set, the client connects to this path directly.\n * Server must handle routing manually (e.g., with getAgentByName + fetch).\n * @example\n * // Client connects to /user, server routes based on session\n * useAgent({ agent: \"UserAgent\", basePath: \"user\" })\n */\n basePath?: string;\n /** Called when the Agent's state is updated */\n onStateUpdate?: (state: State, source: \"server\" | \"client\") => void;\n /**\n * Called when the server sends the agent's identity on connect.\n * Useful when using basePath, as the actual instance name is determined server-side.\n * @param name The actual agent instance name\n * @param agent The agent class name (kebab-case)\n */\n onIdentity?: (name: string, agent: string) => void;\n /**\n * Called when identity changes on reconnect (different instance than before).\n * If not provided and identity changes, a warning will be logged.\n * @param oldName Previous instance name\n * @param newName New instance name\n * @param oldAgent Previous agent class name\n * @param newAgent New agent class name\n */\n onIdentityChange?: (\n oldName: string,\n newName: string,\n oldAgent: string,\n newAgent: string\n ) => void;\n /**\n * Additional path to append to the URL.\n * Works with both standard routing and basePath.\n * @example\n * // With basePath: /user/settings\n * { basePath: \"user\", path: \"settings\" }\n * // Standard: /agents/my-agent/room/settings\n * { agent: \"MyAgent\", name: \"room\", path: \"settings\" }\n */\n path?: string;\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 RPC calls\n */\nexport type CallOptions = {\n /** Timeout in milliseconds. If the call doesn't complete within this time, it will be rejected. */\n timeout?: number;\n /** Streaming options for handling streaming responses */\n stream?: StreamOptions;\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 (ignored if basePath is set) */\n agent: string;\n /** Name of the specific Agent instance (ignored if basePath is set) */\n name?: string;\n /**\n * Full URL path - bypasses agent/name URL construction.\n * When set, the request is made to this path directly.\n */\n basePath?: string;\n};\n\nimport { camelCaseToKebabCase } from \"./utils\";\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\n /**\n * Whether the client has received identity from the server.\n * Becomes true after the first identity message is received.\n * Resets to false on connection close.\n */\n identified = false;\n\n /**\n * Promise that resolves when identity has been received from the server.\n * Useful for waiting before making calls that depend on knowing the instance.\n * Resets on connection close so it can be awaited again after reconnect.\n */\n get ready(): Promise<void> {\n return this._readyPromise;\n }\n\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 private _readyPromise!: Promise<void>;\n private _resolveReady!: () => void;\n private _previousName: string | null = null;\n private _previousAgent: string | null = null;\n\n private _resetReady() {\n this._readyPromise = new Promise((resolve) => {\n this._resolveReady = resolve;\n });\n }\n\n constructor(options: AgentClientOptions<State>) {\n const agentNamespace = camelCaseToKebabCase(options.agent);\n\n // If basePath is provided, use it directly; otherwise construct from agent/name\n const socketOptions = options.basePath\n ? { basePath: options.basePath, path: options.path, ...options }\n : {\n party: agentNamespace,\n prefix: \"agents\",\n room: options.name || \"default\",\n path: options.path,\n ...options\n };\n\n super(socketOptions);\n this.agent = agentNamespace;\n this.name = options.name || \"default\";\n this.options = options;\n\n // Initialize ready promise\n this._resetReady();\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_IDENTITY) {\n const oldName = this._previousName;\n const oldAgent = this._previousAgent;\n const newName = parsedMessage.name as string;\n const newAgent = parsedMessage.agent as string;\n\n // Resolve ready/identified\n this.identified = true;\n this._resolveReady();\n\n // Detect identity change on reconnect\n if (\n oldName !== null &&\n oldAgent !== null &&\n (oldName !== newName || oldAgent !== newAgent)\n ) {\n if (this.options.onIdentityChange) {\n this.options.onIdentityChange(\n oldName,\n newName,\n oldAgent,\n newAgent\n );\n } else {\n const agentChanged = oldAgent !== newAgent;\n const nameChanged = oldName !== newName;\n let changeDescription = \"\";\n if (agentChanged && nameChanged) {\n changeDescription = `agent \"${oldAgent}\" → \"${newAgent}\", instance \"${oldName}\" → \"${newName}\"`;\n } else if (agentChanged) {\n changeDescription = `agent \"${oldAgent}\" → \"${newAgent}\"`;\n } else {\n changeDescription = `instance \"${oldName}\" → \"${newName}\"`;\n }\n console.warn(\n `[agents] Identity changed on reconnect: ${changeDescription}. ` +\n \"This can happen with server-side routing (e.g., basePath with getAgentByName) \" +\n \"where the instance is determined by auth/session. \" +\n \"Provide onIdentityChange callback to handle this explicitly, \" +\n \"or ignore if this is expected for your routing pattern.\"\n );\n }\n }\n\n // Always update from server identity (server is authoritative)\n this._previousName = newName;\n this._previousAgent = newAgent;\n this.name = newName;\n this.agent = newAgent;\n\n // Call onIdentity callback\n this.options.onIdentity?.(newName, newAgent);\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 // Clean up pending calls and reset ready state when connection closes\n this.addEventListener(\"close\", () => {\n // Reset ready state for next connection\n this.identified = false;\n this._resetReady();\n\n // Reject any remaining pending calls (e.g., from unexpected disconnect)\n this._rejectPendingCalls(\"Connection closed\");\n });\n }\n\n /**\n * Reject all pending RPC calls with the given reason.\n */\n private _rejectPendingCalls(reason: string) {\n const error = new Error(reason);\n for (const pending of this._pendingCalls.values()) {\n pending.reject(error);\n pending.stream?.onError?.(reason);\n }\n this._pendingCalls.clear();\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 * Close the connection and immediately reject all pending RPC calls.\n * This provides immediate feedback on intentional close rather than\n * waiting for the WebSocket close handshake to complete.\n *\n * Note: Any calls made after `close()` will be rejected when the\n * underlying WebSocket close event fires.\n */\n close(code?: number, reason?: string) {\n // Immediately reject all pending calls on intentional close\n this._rejectPendingCalls(\"Connection closed\");\n\n // Then close the underlying socket\n super.close(code, reason);\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 options Options for the call (timeout, streaming) or legacy StreamOptions\n * @returns Promise that resolves with the method's return value\n */\n call<T extends SerializableReturnValue>(\n method: string,\n args?: SerializableValue[],\n options?: CallOptions | StreamOptions\n ): Promise<T>;\n call<T = unknown>(\n method: string,\n args?: unknown[],\n options?: CallOptions | StreamOptions\n ): Promise<T>;\n async call<T>(\n method: string,\n args: unknown[] = [],\n options?: CallOptions | StreamOptions\n ): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const id = crypto.randomUUID();\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n // Detect legacy format: { onChunk?, onDone?, onError? } vs new format: { timeout?, stream? }\n const isLegacyFormat =\n options &&\n (\"onChunk\" in options || \"onDone\" in options || \"onError\" in options);\n const streamOptions = isLegacyFormat\n ? (options as StreamOptions)\n : (options as CallOptions | undefined)?.stream;\n const timeout = isLegacyFormat\n ? undefined\n : (options as CallOptions | undefined)?.timeout;\n\n // Set up timeout if specified\n if (timeout) {\n timeoutId = setTimeout(() => {\n const pending = this._pendingCalls.get(id);\n this._pendingCalls.delete(id);\n const errorMessage = `RPC call to ${method} timed out after ${timeout}ms`;\n // Call stream onError callback if present (for streaming calls)\n pending?.stream?.onError?.(errorMessage);\n reject(new Error(errorMessage));\n }, timeout);\n }\n\n this._pendingCalls.set(id, {\n reject: (e: Error) => {\n if (timeoutId) clearTimeout(timeoutId);\n reject(e);\n },\n resolve: (value: unknown) => {\n if (timeoutId) clearTimeout(timeoutId);\n resolve(value as T);\n },\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 // If basePath is provided, use it directly; otherwise construct from agent/name\n // When basePath is set, room/party aren't used by PartySocket (basePath replaces the URL)\n if (opts.basePath) {\n return PartySocket.fetch(\n { basePath: opts.basePath, ...opts } as unknown as PartyFetchOptions,\n init\n );\n }\n\n return PartySocket.fetch(\n {\n party: agentNamespace,\n prefix: \"agents\",\n room: opts.name || \"default\",\n ...opts\n },\n init\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"client.js","names":[],"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 \"./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 (ignored if basePath is set) */\n agent: string;\n /** Name of the specific Agent instance (ignored if basePath is set) */\n name?: string;\n /**\n * Full URL path - bypasses agent/name URL construction.\n * When set, the client connects to this path directly.\n * Server must handle routing manually (e.g., with getAgentByName + fetch).\n * @example\n * // Client connects to /user, server routes based on session\n * useAgent({ agent: \"UserAgent\", basePath: \"user\" })\n */\n basePath?: string;\n /** Called when the Agent's state is updated */\n onStateUpdate?: (state: State, source: \"server\" | \"client\") => void;\n /** Called when a state update fails (e.g., connection is readonly) */\n onStateUpdateError?: (error: string) => void;\n /**\n * Called when the server sends the agent's identity on connect.\n * Useful when using basePath, as the actual instance name is determined server-side.\n * @param name The actual agent instance name\n * @param agent The agent class name (kebab-case)\n */\n onIdentity?: (name: string, agent: string) => void;\n /**\n * Called when identity changes on reconnect (different instance than before).\n * If not provided and identity changes, a warning will be logged.\n * @param oldName Previous instance name\n * @param newName New instance name\n * @param oldAgent Previous agent class name\n * @param newAgent New agent class name\n */\n onIdentityChange?: (\n oldName: string,\n newName: string,\n oldAgent: string,\n newAgent: string\n ) => void;\n /**\n * Additional path to append to the URL.\n * Works with both standard routing and basePath.\n * @example\n * // With basePath: /user/settings\n * { basePath: \"user\", path: \"settings\" }\n * // Standard: /agents/my-agent/room/settings\n * { agent: \"MyAgent\", name: \"room\", path: \"settings\" }\n */\n path?: string;\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 RPC calls\n */\nexport type CallOptions = {\n /** Timeout in milliseconds. If the call doesn't complete within this time, it will be rejected. */\n timeout?: number;\n /** Streaming options for handling streaming responses */\n stream?: StreamOptions;\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 (ignored if basePath is set) */\n agent: string;\n /** Name of the specific Agent instance (ignored if basePath is set) */\n name?: string;\n /**\n * Full URL path - bypasses agent/name URL construction.\n * When set, the request is made to this path directly.\n */\n basePath?: string;\n};\n\nimport { camelCaseToKebabCase } from \"./utils\";\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\n /**\n * Whether the client has received identity from the server.\n * Becomes true after the first identity message is received.\n * Resets to false on connection close.\n */\n identified = false;\n\n /**\n * Promise that resolves when identity has been received from the server.\n * Useful for waiting before making calls that depend on knowing the instance.\n * Resets on connection close so it can be awaited again after reconnect.\n */\n get ready(): Promise<void> {\n return this._readyPromise;\n }\n\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 private _readyPromise!: Promise<void>;\n private _resolveReady!: () => void;\n private _previousName: string | null = null;\n private _previousAgent: string | null = null;\n\n private _resetReady() {\n this._readyPromise = new Promise((resolve) => {\n this._resolveReady = resolve;\n });\n }\n\n constructor(options: AgentClientOptions<State>) {\n const agentNamespace = camelCaseToKebabCase(options.agent);\n\n // If basePath is provided, use it directly; otherwise construct from agent/name\n const socketOptions = options.basePath\n ? { basePath: options.basePath, path: options.path, ...options }\n : {\n party: agentNamespace,\n prefix: \"agents\",\n room: options.name || \"default\",\n path: options.path,\n ...options\n };\n\n super(socketOptions);\n this.agent = agentNamespace;\n this.name = options.name || \"default\";\n this.options = options;\n\n // Initialize ready promise\n this._resetReady();\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_IDENTITY) {\n const oldName = this._previousName;\n const oldAgent = this._previousAgent;\n const newName = parsedMessage.name as string;\n const newAgent = parsedMessage.agent as string;\n\n // Resolve ready/identified\n this.identified = true;\n this._resolveReady();\n\n // Detect identity change on reconnect\n if (\n oldName !== null &&\n oldAgent !== null &&\n (oldName !== newName || oldAgent !== newAgent)\n ) {\n if (this.options.onIdentityChange) {\n this.options.onIdentityChange(\n oldName,\n newName,\n oldAgent,\n newAgent\n );\n } else {\n const agentChanged = oldAgent !== newAgent;\n const nameChanged = oldName !== newName;\n let changeDescription = \"\";\n if (agentChanged && nameChanged) {\n changeDescription = `agent \"${oldAgent}\" → \"${newAgent}\", instance \"${oldName}\" → \"${newName}\"`;\n } else if (agentChanged) {\n changeDescription = `agent \"${oldAgent}\" → \"${newAgent}\"`;\n } else {\n changeDescription = `instance \"${oldName}\" → \"${newName}\"`;\n }\n console.warn(\n `[agents] Identity changed on reconnect: ${changeDescription}. ` +\n \"This can happen with server-side routing (e.g., basePath with getAgentByName) \" +\n \"where the instance is determined by auth/session. \" +\n \"Provide onIdentityChange callback to handle this explicitly, \" +\n \"or ignore if this is expected for your routing pattern.\"\n );\n }\n }\n\n // Always update from server identity (server is authoritative)\n this._previousName = newName;\n this._previousAgent = newAgent;\n this.name = newName;\n this.agent = newAgent;\n\n // Call onIdentity callback\n this.options.onIdentity?.(newName, newAgent);\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.CF_AGENT_STATE_ERROR) {\n this.options.onStateUpdateError?.(parsedMessage.error as string);\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 // Clean up pending calls and reset ready state when connection closes\n this.addEventListener(\"close\", () => {\n // Reset ready state for next connection\n this.identified = false;\n this._resetReady();\n\n // Reject any remaining pending calls (e.g., from unexpected disconnect)\n this._rejectPendingCalls(\"Connection closed\");\n });\n }\n\n /**\n * Reject all pending RPC calls with the given reason.\n */\n private _rejectPendingCalls(reason: string) {\n const error = new Error(reason);\n for (const pending of this._pendingCalls.values()) {\n pending.reject(error);\n pending.stream?.onError?.(reason);\n }\n this._pendingCalls.clear();\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 * Close the connection and immediately reject all pending RPC calls.\n * This provides immediate feedback on intentional close rather than\n * waiting for the WebSocket close handshake to complete.\n *\n * Note: Any calls made after `close()` will be rejected when the\n * underlying WebSocket close event fires.\n */\n close(code?: number, reason?: string) {\n // Immediately reject all pending calls on intentional close\n this._rejectPendingCalls(\"Connection closed\");\n\n // Then close the underlying socket\n super.close(code, reason);\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 options Options for the call (timeout, streaming) or legacy StreamOptions\n * @returns Promise that resolves with the method's return value\n */\n call<T extends SerializableReturnValue>(\n method: string,\n args?: SerializableValue[],\n options?: CallOptions | StreamOptions\n ): Promise<T>;\n call<T = unknown>(\n method: string,\n args?: unknown[],\n options?: CallOptions | StreamOptions\n ): Promise<T>;\n async call<T>(\n method: string,\n args: unknown[] = [],\n options?: CallOptions | StreamOptions\n ): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const id = crypto.randomUUID();\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n // Detect legacy format: { onChunk?, onDone?, onError? } vs new format: { timeout?, stream? }\n const isLegacyFormat =\n options &&\n (\"onChunk\" in options || \"onDone\" in options || \"onError\" in options);\n const streamOptions = isLegacyFormat\n ? (options as StreamOptions)\n : (options as CallOptions | undefined)?.stream;\n const timeout = isLegacyFormat\n ? undefined\n : (options as CallOptions | undefined)?.timeout;\n\n // Set up timeout if specified\n if (timeout) {\n timeoutId = setTimeout(() => {\n const pending = this._pendingCalls.get(id);\n this._pendingCalls.delete(id);\n const errorMessage = `RPC call to ${method} timed out after ${timeout}ms`;\n // Call stream onError callback if present (for streaming calls)\n pending?.stream?.onError?.(errorMessage);\n reject(new Error(errorMessage));\n }, timeout);\n }\n\n this._pendingCalls.set(id, {\n reject: (e: Error) => {\n if (timeoutId) clearTimeout(timeoutId);\n reject(e);\n },\n resolve: (value: unknown) => {\n if (timeoutId) clearTimeout(timeoutId);\n resolve(value as T);\n },\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 // If basePath is provided, use it directly; otherwise construct from agent/name\n // When basePath is set, room/party aren't used by PartySocket (basePath replaces the URL)\n if (opts.basePath) {\n return PartySocket.fetch(\n { basePath: opts.basePath, ...opts } as unknown as PartyFetchOptions,\n init\n );\n }\n\n return PartySocket.fetch(\n {\n party: agentNamespace,\n prefix: \"agents\",\n room: opts.name || \"default\",\n ...opts\n },\n init\n );\n}\n"],"mappings":"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"}
|
package/dist/email.d.ts
CHANGED
|
@@ -1,20 +1,149 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
1
|
+
import { AgentEmail } from "./internal_context.js";
|
|
2
|
+
|
|
3
|
+
//#region src/email.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Header object as returned by postal-mime and similar email parsing libraries.
|
|
6
|
+
* Each header has a lowercase key and a string value.
|
|
7
|
+
*/
|
|
8
|
+
type EmailHeader = {
|
|
9
|
+
/** Lowercase header name (e.g., "content-type", "x-custom-header") */ key: string /** Header value */;
|
|
10
|
+
value: string;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Check if an email appears to be an auto-reply based on standard headers.
|
|
14
|
+
* Checks for Auto-Submitted (RFC 3834), X-Auto-Response-Suppress, and Precedence headers.
|
|
15
|
+
*
|
|
16
|
+
* @param headers - Headers array from postal-mime Email.headers or similar format
|
|
17
|
+
* @returns true if email appears to be an auto-reply
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* if (isAutoReplyEmail(parsed.headers)) {
|
|
22
|
+
* // Skip processing auto-replies
|
|
23
|
+
* return;
|
|
24
|
+
* }
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
declare function isAutoReplyEmail(headers: EmailHeader[]): boolean;
|
|
28
|
+
/** Default signature expiration: 30 days in seconds */
|
|
29
|
+
declare const DEFAULT_MAX_AGE_SECONDS: number;
|
|
30
|
+
/**
|
|
31
|
+
* Sign agent routing headers for secure reply flows.
|
|
32
|
+
* Use this when sending outbound emails to ensure replies can be securely routed back.
|
|
33
|
+
*
|
|
34
|
+
* @param secret - Secret key for HMAC signing (store in environment variables)
|
|
35
|
+
* @param agentName - Name of the agent
|
|
36
|
+
* @param agentId - ID of the agent instance
|
|
37
|
+
* @returns Headers object with X-Agent-Name, X-Agent-ID, X-Agent-Sig, and X-Agent-Sig-Ts
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```typescript
|
|
41
|
+
* const headers = await signAgentHeaders(env.EMAIL_SECRET, "MyAgent", this.name);
|
|
42
|
+
* // Use these headers when sending outbound emails
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
declare function signAgentHeaders(
|
|
46
|
+
secret: string,
|
|
47
|
+
agentName: string,
|
|
48
|
+
agentId: string
|
|
49
|
+
): Promise<Record<string, string>>;
|
|
50
|
+
type EmailResolverResult = {
|
|
51
|
+
agentName: string;
|
|
52
|
+
agentId: string /** @internal Indicates this resolver requires secure reply signing */;
|
|
53
|
+
_secureRouted?: boolean;
|
|
54
|
+
} | null;
|
|
55
|
+
type EmailResolver<Env> = (
|
|
56
|
+
email: ForwardableEmailMessage,
|
|
57
|
+
env: Env
|
|
58
|
+
) => Promise<EmailResolverResult>;
|
|
59
|
+
/**
|
|
60
|
+
* Reason for signature verification failure
|
|
61
|
+
*/
|
|
62
|
+
type SignatureFailureReason =
|
|
63
|
+
| "missing_headers"
|
|
64
|
+
| "expired"
|
|
65
|
+
| "invalid"
|
|
66
|
+
| "malformed_timestamp";
|
|
67
|
+
/**
|
|
68
|
+
* Options for createSecureReplyEmailResolver
|
|
69
|
+
*/
|
|
70
|
+
type SecureReplyResolverOptions = {
|
|
71
|
+
/**
|
|
72
|
+
* Maximum age of signature in seconds.
|
|
73
|
+
* Signatures older than this will be rejected.
|
|
74
|
+
* Default: 30 days (2592000 seconds)
|
|
75
|
+
*/
|
|
76
|
+
maxAge?: number;
|
|
77
|
+
/**
|
|
78
|
+
* Callback invoked when signature verification fails.
|
|
79
|
+
* Useful for logging and debugging.
|
|
80
|
+
*/
|
|
81
|
+
onInvalidSignature?: (
|
|
82
|
+
email: ForwardableEmailMessage,
|
|
83
|
+
reason: SignatureFailureReason
|
|
84
|
+
) => void;
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* @deprecated REMOVED due to security vulnerability (IDOR via spoofed headers).
|
|
88
|
+
* @throws Always throws an error with migration guidance.
|
|
89
|
+
*/
|
|
90
|
+
declare function createHeaderBasedEmailResolver<Env>(): EmailResolver<Env>;
|
|
91
|
+
/**
|
|
92
|
+
* Create a resolver for routing email replies with signature verification.
|
|
93
|
+
* This resolver verifies that replies contain a valid HMAC signature, preventing
|
|
94
|
+
* attackers from routing emails to arbitrary agent instances.
|
|
95
|
+
*
|
|
96
|
+
* @param secret - Secret key for HMAC verification (must match the key used with signAgentHeaders)
|
|
97
|
+
* @param options - Optional configuration for signature verification
|
|
98
|
+
* @returns A function that resolves the agent to route the email to, or null if signature is invalid
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```typescript
|
|
102
|
+
* // In your email handler
|
|
103
|
+
* const secureResolver = createSecureReplyEmailResolver(env.EMAIL_SECRET, {
|
|
104
|
+
* maxAge: 7 * 24 * 60 * 60, // 7 days
|
|
105
|
+
* onInvalidSignature: (email, reason) => {
|
|
106
|
+
* console.warn(`Invalid signature from ${email.from}: ${reason}`);
|
|
107
|
+
* }
|
|
108
|
+
* });
|
|
109
|
+
* const addressResolver = createAddressBasedEmailResolver("MyAgent");
|
|
110
|
+
*
|
|
111
|
+
* await routeAgentEmail(email, env, {
|
|
112
|
+
* resolver: async (email, env) => {
|
|
113
|
+
* // Try secure reply routing first
|
|
114
|
+
* const replyRouting = await secureResolver(email, env);
|
|
115
|
+
* if (replyRouting) return replyRouting;
|
|
116
|
+
* // Fall back to address-based routing
|
|
117
|
+
* return addressResolver(email, env);
|
|
118
|
+
* }
|
|
119
|
+
* });
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
122
|
+
declare function createSecureReplyEmailResolver<Env>(
|
|
123
|
+
secret: string,
|
|
124
|
+
options?: SecureReplyResolverOptions
|
|
125
|
+
): EmailResolver<Env>;
|
|
126
|
+
/**
|
|
127
|
+
* Create a resolver that uses the email address to determine the agent to route the email to
|
|
128
|
+
* @param defaultAgentName The default agent name to use if the email address does not contain a sub-address
|
|
129
|
+
* @returns A function that resolves the agent to route the email to
|
|
130
|
+
*/
|
|
131
|
+
declare function createAddressBasedEmailResolver<Env>(
|
|
132
|
+
defaultAgentName: string
|
|
133
|
+
): EmailResolver<Env>;
|
|
134
|
+
/**
|
|
135
|
+
* Create a resolver that uses the agentName and agentId to determine the agent to route the email to
|
|
136
|
+
* @param agentName The name of the agent to route the email to
|
|
137
|
+
* @param agentId The id of the agent to route the email to
|
|
138
|
+
* @returns A function that resolves the agent to route the email to
|
|
139
|
+
*/
|
|
140
|
+
declare function createCatchAllEmailResolver<Env>(
|
|
141
|
+
agentName: string,
|
|
142
|
+
agentId: string
|
|
143
|
+
): EmailResolver<Env>;
|
|
144
|
+
//#endregion
|
|
16
145
|
export {
|
|
17
|
-
AgentEmail,
|
|
146
|
+
type AgentEmail,
|
|
18
147
|
DEFAULT_MAX_AGE_SECONDS,
|
|
19
148
|
EmailHeader,
|
|
20
149
|
EmailResolver,
|
|
@@ -28,3 +157,4 @@ export {
|
|
|
28
157
|
isAutoReplyEmail,
|
|
29
158
|
signAgentHeaders
|
|
30
159
|
};
|
|
160
|
+
//# sourceMappingURL=email.d.ts.map
|