agents 0.3.9 → 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 +139 -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 +16 -10
- package/dist/react.js +34 -16
- 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 +26 -23
- package/dist/client-BA8NJB6l.js +0 -1124
- package/dist/client-BA8NJB6l.js.map +0 -1
- package/dist/client-Ba-xntmv.d.ts +0 -963
- 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-CqnVUbg1.js +0 -2146
- package/dist/src-CqnVUbg1.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
package/dist/email.js
CHANGED
|
@@ -1,3 +1,223 @@
|
|
|
1
|
-
|
|
1
|
+
//#region src/email.ts
|
|
2
|
+
/**
|
|
3
|
+
* Check if an email appears to be an auto-reply based on standard headers.
|
|
4
|
+
* Checks for Auto-Submitted (RFC 3834), X-Auto-Response-Suppress, and Precedence headers.
|
|
5
|
+
*
|
|
6
|
+
* @param headers - Headers array from postal-mime Email.headers or similar format
|
|
7
|
+
* @returns true if email appears to be an auto-reply
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* if (isAutoReplyEmail(parsed.headers)) {
|
|
12
|
+
* // Skip processing auto-replies
|
|
13
|
+
* return;
|
|
14
|
+
* }
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
function isAutoReplyEmail(headers) {
|
|
18
|
+
return headers.some((h) => {
|
|
19
|
+
const key = h.key.toLowerCase();
|
|
20
|
+
const value = h.value.toLowerCase();
|
|
21
|
+
if (key === "auto-submitted") return value !== "no";
|
|
22
|
+
if (key === "x-auto-response-suppress") return true;
|
|
23
|
+
if (key === "precedence") return value === "bulk" || value === "junk" || value === "list";
|
|
24
|
+
return false;
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
/** Default signature expiration: 30 days in seconds */
|
|
28
|
+
const DEFAULT_MAX_AGE_SECONDS = 720 * 60 * 60;
|
|
29
|
+
/** Maximum allowed clock skew for future timestamps: 5 minutes */
|
|
30
|
+
const MAX_CLOCK_SKEW_SECONDS = 300;
|
|
31
|
+
/**
|
|
32
|
+
* Compute HMAC-SHA256 signature for agent routing headers
|
|
33
|
+
* @param secret - Secret key for HMAC
|
|
34
|
+
* @param agentName - Name of the agent
|
|
35
|
+
* @param agentId - ID of the agent instance
|
|
36
|
+
* @param timestamp - Unix timestamp in seconds
|
|
37
|
+
* @returns Base64-encoded HMAC signature
|
|
38
|
+
*/
|
|
39
|
+
async function computeAgentSignature(secret, agentName, agentId, timestamp) {
|
|
40
|
+
const encoder = new TextEncoder();
|
|
41
|
+
const key = await crypto.subtle.importKey("raw", encoder.encode(secret), {
|
|
42
|
+
name: "HMAC",
|
|
43
|
+
hash: "SHA-256"
|
|
44
|
+
}, false, ["sign"]);
|
|
45
|
+
const data = encoder.encode(`${agentName}:${agentId}:${timestamp}`);
|
|
46
|
+
const signature = await crypto.subtle.sign("HMAC", key, data);
|
|
47
|
+
return btoa(String.fromCharCode(...new Uint8Array(signature)));
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Verify HMAC-SHA256 signature for agent routing headers
|
|
51
|
+
* @param secret - Secret key for HMAC
|
|
52
|
+
* @param agentName - Name of the agent
|
|
53
|
+
* @param agentId - ID of the agent instance
|
|
54
|
+
* @param signature - Base64-encoded signature to verify
|
|
55
|
+
* @param timestamp - Unix timestamp in seconds when signature was created
|
|
56
|
+
* @param maxAgeSeconds - Maximum age of signature in seconds (default: 30 days)
|
|
57
|
+
* @returns Verification result with reason if invalid
|
|
58
|
+
*/
|
|
59
|
+
async function verifyAgentSignature(secret, agentName, agentId, signature, timestamp, maxAgeSeconds = DEFAULT_MAX_AGE_SECONDS) {
|
|
60
|
+
try {
|
|
61
|
+
const timestampNum = Number.parseInt(timestamp, 10);
|
|
62
|
+
if (Number.isNaN(timestampNum)) return {
|
|
63
|
+
valid: false,
|
|
64
|
+
reason: "malformed_timestamp"
|
|
65
|
+
};
|
|
66
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
67
|
+
if (timestampNum > now + MAX_CLOCK_SKEW_SECONDS) return {
|
|
68
|
+
valid: false,
|
|
69
|
+
reason: "invalid"
|
|
70
|
+
};
|
|
71
|
+
if (now - timestampNum > maxAgeSeconds) return {
|
|
72
|
+
valid: false,
|
|
73
|
+
reason: "expired"
|
|
74
|
+
};
|
|
75
|
+
const expected = await computeAgentSignature(secret, agentName, agentId, timestamp);
|
|
76
|
+
if (expected.length !== signature.length) return {
|
|
77
|
+
valid: false,
|
|
78
|
+
reason: "invalid"
|
|
79
|
+
};
|
|
80
|
+
let result = 0;
|
|
81
|
+
for (let i = 0; i < expected.length; i++) result |= expected.charCodeAt(i) ^ signature.charCodeAt(i);
|
|
82
|
+
if (result !== 0) return {
|
|
83
|
+
valid: false,
|
|
84
|
+
reason: "invalid"
|
|
85
|
+
};
|
|
86
|
+
return { valid: true };
|
|
87
|
+
} catch (error) {
|
|
88
|
+
console.warn("[agents] Signature verification error:", error);
|
|
89
|
+
return {
|
|
90
|
+
valid: false,
|
|
91
|
+
reason: "invalid"
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Sign agent routing headers for secure reply flows.
|
|
97
|
+
* Use this when sending outbound emails to ensure replies can be securely routed back.
|
|
98
|
+
*
|
|
99
|
+
* @param secret - Secret key for HMAC signing (store in environment variables)
|
|
100
|
+
* @param agentName - Name of the agent
|
|
101
|
+
* @param agentId - ID of the agent instance
|
|
102
|
+
* @returns Headers object with X-Agent-Name, X-Agent-ID, X-Agent-Sig, and X-Agent-Sig-Ts
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```typescript
|
|
106
|
+
* const headers = await signAgentHeaders(env.EMAIL_SECRET, "MyAgent", this.name);
|
|
107
|
+
* // Use these headers when sending outbound emails
|
|
108
|
+
* ```
|
|
109
|
+
*/
|
|
110
|
+
async function signAgentHeaders(secret, agentName, agentId) {
|
|
111
|
+
if (!secret) throw new Error("secret is required for signing agent headers");
|
|
112
|
+
if (!agentName) throw new Error("agentName is required for signing agent headers");
|
|
113
|
+
if (!agentId) throw new Error("agentId is required for signing agent headers");
|
|
114
|
+
if (agentName.includes(":")) throw new Error("agentName cannot contain colons");
|
|
115
|
+
if (agentId.includes(":")) throw new Error("agentId cannot contain colons");
|
|
116
|
+
const timestamp = Math.floor(Date.now() / 1e3).toString();
|
|
117
|
+
const signature = await computeAgentSignature(secret, agentName, agentId, timestamp);
|
|
118
|
+
return {
|
|
119
|
+
"X-Agent-Name": agentName,
|
|
120
|
+
"X-Agent-ID": agentId,
|
|
121
|
+
"X-Agent-Sig": signature,
|
|
122
|
+
"X-Agent-Sig-Ts": timestamp
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* @deprecated REMOVED due to security vulnerability (IDOR via spoofed headers).
|
|
127
|
+
* @throws Always throws an error with migration guidance.
|
|
128
|
+
*/
|
|
129
|
+
function createHeaderBasedEmailResolver() {
|
|
130
|
+
throw new Error("createHeaderBasedEmailResolver has been removed due to a security vulnerability. It trusted attacker-controlled email headers for routing, enabling IDOR attacks.\n\nMigration options:\n - For inbound mail: use createAddressBasedEmailResolver(agentName)\n - For reply flows: use createSecureReplyEmailResolver(secret) with signed headers\n\nSee https://github.com/cloudflare/agents/blob/main/docs/email.md for details.");
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Create a resolver for routing email replies with signature verification.
|
|
134
|
+
* This resolver verifies that replies contain a valid HMAC signature, preventing
|
|
135
|
+
* attackers from routing emails to arbitrary agent instances.
|
|
136
|
+
*
|
|
137
|
+
* @param secret - Secret key for HMAC verification (must match the key used with signAgentHeaders)
|
|
138
|
+
* @param options - Optional configuration for signature verification
|
|
139
|
+
* @returns A function that resolves the agent to route the email to, or null if signature is invalid
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* ```typescript
|
|
143
|
+
* // In your email handler
|
|
144
|
+
* const secureResolver = createSecureReplyEmailResolver(env.EMAIL_SECRET, {
|
|
145
|
+
* maxAge: 7 * 24 * 60 * 60, // 7 days
|
|
146
|
+
* onInvalidSignature: (email, reason) => {
|
|
147
|
+
* console.warn(`Invalid signature from ${email.from}: ${reason}`);
|
|
148
|
+
* }
|
|
149
|
+
* });
|
|
150
|
+
* const addressResolver = createAddressBasedEmailResolver("MyAgent");
|
|
151
|
+
*
|
|
152
|
+
* await routeAgentEmail(email, env, {
|
|
153
|
+
* resolver: async (email, env) => {
|
|
154
|
+
* // Try secure reply routing first
|
|
155
|
+
* const replyRouting = await secureResolver(email, env);
|
|
156
|
+
* if (replyRouting) return replyRouting;
|
|
157
|
+
* // Fall back to address-based routing
|
|
158
|
+
* return addressResolver(email, env);
|
|
159
|
+
* }
|
|
160
|
+
* });
|
|
161
|
+
* ```
|
|
162
|
+
*/
|
|
163
|
+
function createSecureReplyEmailResolver(secret, options) {
|
|
164
|
+
if (!secret) throw new Error("secret is required for createSecureReplyEmailResolver");
|
|
165
|
+
const maxAge = options?.maxAge ?? DEFAULT_MAX_AGE_SECONDS;
|
|
166
|
+
const onInvalidSignature = options?.onInvalidSignature;
|
|
167
|
+
return async (email, _env) => {
|
|
168
|
+
const agentName = email.headers.get("x-agent-name");
|
|
169
|
+
const agentId = email.headers.get("x-agent-id");
|
|
170
|
+
const signature = email.headers.get("x-agent-sig");
|
|
171
|
+
const timestamp = email.headers.get("x-agent-sig-ts");
|
|
172
|
+
if (!agentName || !agentId || !signature || !timestamp) {
|
|
173
|
+
onInvalidSignature?.(email, "missing_headers");
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
const result = await verifyAgentSignature(secret, agentName, agentId, signature, timestamp, maxAge);
|
|
177
|
+
if (!result.valid) {
|
|
178
|
+
onInvalidSignature?.(email, result.reason);
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
return {
|
|
182
|
+
agentName,
|
|
183
|
+
agentId,
|
|
184
|
+
_secureRouted: true
|
|
185
|
+
};
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Create a resolver that uses the email address to determine the agent to route the email to
|
|
190
|
+
* @param defaultAgentName The default agent name to use if the email address does not contain a sub-address
|
|
191
|
+
* @returns A function that resolves the agent to route the email to
|
|
192
|
+
*/
|
|
193
|
+
function createAddressBasedEmailResolver(defaultAgentName) {
|
|
194
|
+
return async (email, _env) => {
|
|
195
|
+
const emailMatch = email.to.match(/^([^+@]{1,64})(?:\+([^@]{1,64}))?@(.{1,253})$/);
|
|
196
|
+
if (!emailMatch) return null;
|
|
197
|
+
const [, localPart, subAddress] = emailMatch;
|
|
198
|
+
if (subAddress) return {
|
|
199
|
+
agentName: localPart,
|
|
200
|
+
agentId: subAddress
|
|
201
|
+
};
|
|
202
|
+
return {
|
|
203
|
+
agentName: defaultAgentName,
|
|
204
|
+
agentId: localPart
|
|
205
|
+
};
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Create a resolver that uses the agentName and agentId to determine the agent to route the email to
|
|
210
|
+
* @param agentName The name of the agent to route the email to
|
|
211
|
+
* @param agentId The id of the agent to route the email to
|
|
212
|
+
* @returns A function that resolves the agent to route the email to
|
|
213
|
+
*/
|
|
214
|
+
function createCatchAllEmailResolver(agentName, agentId) {
|
|
215
|
+
return async () => ({
|
|
216
|
+
agentName,
|
|
217
|
+
agentId
|
|
218
|
+
});
|
|
219
|
+
}
|
|
2
220
|
|
|
3
|
-
|
|
221
|
+
//#endregion
|
|
222
|
+
export { DEFAULT_MAX_AGE_SECONDS, createAddressBasedEmailResolver, createCatchAllEmailResolver, createHeaderBasedEmailResolver, createSecureReplyEmailResolver, isAutoReplyEmail, signAgentHeaders };
|
|
223
|
+
//# sourceMappingURL=email.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email.js","names":[],"sources":["../src/email.ts"],"sourcesContent":["/**\n * Email routing types, resolvers, and signing utilities for Agents\n */\n\n// Re-export AgentEmail type\nexport type { AgentEmail } from \"./internal_context\";\n\n// ============================================================================\n// Email header utilities\n// ============================================================================\n\n/**\n * Header object as returned by postal-mime and similar email parsing libraries.\n * Each header has a lowercase key and a string value.\n */\nexport type EmailHeader = {\n /** Lowercase header name (e.g., \"content-type\", \"x-custom-header\") */\n key: string;\n /** Header value */\n value: string;\n};\n\n/**\n * Check if an email appears to be an auto-reply based on standard headers.\n * Checks for Auto-Submitted (RFC 3834), X-Auto-Response-Suppress, and Precedence headers.\n *\n * @param headers - Headers array from postal-mime Email.headers or similar format\n * @returns true if email appears to be an auto-reply\n *\n * @example\n * ```typescript\n * if (isAutoReplyEmail(parsed.headers)) {\n * // Skip processing auto-replies\n * return;\n * }\n * ```\n */\nexport function isAutoReplyEmail(headers: EmailHeader[]): boolean {\n return headers.some((h) => {\n const key = h.key.toLowerCase();\n const value = h.value.toLowerCase();\n\n // RFC 3834: Auto-Submitted header\n // \"no\" means normal (human-sent) email, anything else indicates auto-reply\n if (key === \"auto-submitted\") {\n return value !== \"no\";\n }\n\n // X-Auto-Response-Suppress: any value indicates sender doesn't want auto-replies\n if (key === \"x-auto-response-suppress\") {\n return true;\n }\n\n // Precedence: only bulk/junk/list indicate automated/mass mail\n if (key === \"precedence\") {\n return value === \"bulk\" || value === \"junk\" || value === \"list\";\n }\n\n return false;\n });\n}\n\n// ============================================================================\n// Signing utilities\n// ============================================================================\n\n/** Default signature expiration: 30 days in seconds */\nexport const DEFAULT_MAX_AGE_SECONDS = 30 * 24 * 60 * 60;\n\n/** Maximum allowed clock skew for future timestamps: 5 minutes */\nconst MAX_CLOCK_SKEW_SECONDS = 5 * 60;\n\n/**\n * Compute HMAC-SHA256 signature for agent routing headers\n * @param secret - Secret key for HMAC\n * @param agentName - Name of the agent\n * @param agentId - ID of the agent instance\n * @param timestamp - Unix timestamp in seconds\n * @returns Base64-encoded HMAC signature\n */\nasync function computeAgentSignature(\n secret: string,\n agentName: string,\n agentId: string,\n timestamp: string\n): Promise<string> {\n const encoder = new TextEncoder();\n const key = await crypto.subtle.importKey(\n \"raw\",\n encoder.encode(secret),\n { name: \"HMAC\", hash: \"SHA-256\" },\n false,\n [\"sign\"]\n );\n const data = encoder.encode(`${agentName}:${agentId}:${timestamp}`);\n const signature = await crypto.subtle.sign(\"HMAC\", key, data);\n return btoa(String.fromCharCode(...new Uint8Array(signature)));\n}\n\n/**\n * Result of signature verification\n */\ntype SignatureVerificationResult =\n | { valid: true }\n | { valid: false; reason: \"expired\" | \"invalid\" | \"malformed_timestamp\" };\n\n/**\n * Verify HMAC-SHA256 signature for agent routing headers\n * @param secret - Secret key for HMAC\n * @param agentName - Name of the agent\n * @param agentId - ID of the agent instance\n * @param signature - Base64-encoded signature to verify\n * @param timestamp - Unix timestamp in seconds when signature was created\n * @param maxAgeSeconds - Maximum age of signature in seconds (default: 30 days)\n * @returns Verification result with reason if invalid\n */\nasync function verifyAgentSignature(\n secret: string,\n agentName: string,\n agentId: string,\n signature: string,\n timestamp: string,\n maxAgeSeconds: number = DEFAULT_MAX_AGE_SECONDS\n): Promise<SignatureVerificationResult> {\n try {\n // Validate timestamp format\n const timestampNum = Number.parseInt(timestamp, 10);\n if (Number.isNaN(timestampNum)) {\n return { valid: false, reason: \"malformed_timestamp\" };\n }\n\n // Check timestamp validity\n const now = Math.floor(Date.now() / 1000);\n\n // Reject timestamps too far in the future (prevents extending signature validity)\n if (timestampNum > now + MAX_CLOCK_SKEW_SECONDS) {\n return { valid: false, reason: \"invalid\" };\n }\n\n // Check if signature has expired\n if (now - timestampNum > maxAgeSeconds) {\n return { valid: false, reason: \"expired\" };\n }\n\n const expected = await computeAgentSignature(\n secret,\n agentName,\n agentId,\n timestamp\n );\n // Constant-time comparison to prevent timing attacks\n if (expected.length !== signature.length) {\n return { valid: false, reason: \"invalid\" };\n }\n let result = 0;\n for (let i = 0; i < expected.length; i++) {\n result |= expected.charCodeAt(i) ^ signature.charCodeAt(i);\n }\n if (result !== 0) {\n return { valid: false, reason: \"invalid\" };\n }\n return { valid: true };\n } catch (error) {\n console.warn(\"[agents] Signature verification error:\", error);\n return { valid: false, reason: \"invalid\" };\n }\n}\n\n/**\n * Sign agent routing headers for secure reply flows.\n * Use this when sending outbound emails to ensure replies can be securely routed back.\n *\n * @param secret - Secret key for HMAC signing (store in environment variables)\n * @param agentName - Name of the agent\n * @param agentId - ID of the agent instance\n * @returns Headers object with X-Agent-Name, X-Agent-ID, X-Agent-Sig, and X-Agent-Sig-Ts\n *\n * @example\n * ```typescript\n * const headers = await signAgentHeaders(env.EMAIL_SECRET, \"MyAgent\", this.name);\n * // Use these headers when sending outbound emails\n * ```\n */\nexport async function signAgentHeaders(\n secret: string,\n agentName: string,\n agentId: string\n): Promise<Record<string, string>> {\n if (!secret) {\n throw new Error(\"secret is required for signing agent headers\");\n }\n if (!agentName) {\n throw new Error(\"agentName is required for signing agent headers\");\n }\n if (!agentId) {\n throw new Error(\"agentId is required for signing agent headers\");\n }\n // Reject colons to prevent signature confusion attacks\n // (signature payload uses colon as delimiter: \"agentName:agentId:timestamp\")\n if (agentName.includes(\":\")) {\n throw new Error(\"agentName cannot contain colons\");\n }\n if (agentId.includes(\":\")) {\n throw new Error(\"agentId cannot contain colons\");\n }\n\n const timestamp = Math.floor(Date.now() / 1000).toString();\n const signature = await computeAgentSignature(\n secret,\n agentName,\n agentId,\n timestamp\n );\n return {\n \"X-Agent-Name\": agentName,\n \"X-Agent-ID\": agentId,\n \"X-Agent-Sig\": signature,\n \"X-Agent-Sig-Ts\": timestamp\n };\n}\n\n// ============================================================================\n// Email routing types and resolvers\n// ============================================================================\n\nexport type EmailResolverResult = {\n agentName: string;\n agentId: string;\n /** @internal Indicates this resolver requires secure reply signing */\n _secureRouted?: boolean;\n} | null;\n\nexport type EmailResolver<Env> = (\n email: ForwardableEmailMessage,\n env: Env\n) => Promise<EmailResolverResult>;\n\n/**\n * Reason for signature verification failure\n */\nexport type SignatureFailureReason =\n | \"missing_headers\"\n | \"expired\"\n | \"invalid\"\n | \"malformed_timestamp\";\n\n/**\n * Options for createSecureReplyEmailResolver\n */\nexport type SecureReplyResolverOptions = {\n /**\n * Maximum age of signature in seconds.\n * Signatures older than this will be rejected.\n * Default: 30 days (2592000 seconds)\n */\n maxAge?: number;\n /**\n * Callback invoked when signature verification fails.\n * Useful for logging and debugging.\n */\n onInvalidSignature?: (\n email: ForwardableEmailMessage,\n reason: SignatureFailureReason\n ) => void;\n};\n\n/**\n * @deprecated REMOVED due to security vulnerability (IDOR via spoofed headers).\n * @throws Always throws an error with migration guidance.\n */\nexport function createHeaderBasedEmailResolver<Env>(): EmailResolver<Env> {\n throw new Error(\n \"createHeaderBasedEmailResolver has been removed due to a security vulnerability. \" +\n \"It trusted attacker-controlled email headers for routing, enabling IDOR attacks.\\n\\n\" +\n \"Migration options:\\n\" +\n \" - For inbound mail: use createAddressBasedEmailResolver(agentName)\\n\" +\n \" - For reply flows: use createSecureReplyEmailResolver(secret) with signed headers\\n\\n\" +\n \"See https://github.com/cloudflare/agents/blob/main/docs/email.md for details.\"\n );\n}\n\n/**\n * Create a resolver for routing email replies with signature verification.\n * This resolver verifies that replies contain a valid HMAC signature, preventing\n * attackers from routing emails to arbitrary agent instances.\n *\n * @param secret - Secret key for HMAC verification (must match the key used with signAgentHeaders)\n * @param options - Optional configuration for signature verification\n * @returns A function that resolves the agent to route the email to, or null if signature is invalid\n *\n * @example\n * ```typescript\n * // In your email handler\n * const secureResolver = createSecureReplyEmailResolver(env.EMAIL_SECRET, {\n * maxAge: 7 * 24 * 60 * 60, // 7 days\n * onInvalidSignature: (email, reason) => {\n * console.warn(`Invalid signature from ${email.from}: ${reason}`);\n * }\n * });\n * const addressResolver = createAddressBasedEmailResolver(\"MyAgent\");\n *\n * await routeAgentEmail(email, env, {\n * resolver: async (email, env) => {\n * // Try secure reply routing first\n * const replyRouting = await secureResolver(email, env);\n * if (replyRouting) return replyRouting;\n * // Fall back to address-based routing\n * return addressResolver(email, env);\n * }\n * });\n * ```\n */\nexport function createSecureReplyEmailResolver<Env>(\n secret: string,\n options?: SecureReplyResolverOptions\n): EmailResolver<Env> {\n if (!secret) {\n throw new Error(\"secret is required for createSecureReplyEmailResolver\");\n }\n\n const maxAge = options?.maxAge ?? DEFAULT_MAX_AGE_SECONDS;\n const onInvalidSignature = options?.onInvalidSignature;\n\n return async (email: ForwardableEmailMessage, _env: Env) => {\n const agentName = email.headers.get(\"x-agent-name\");\n const agentId = email.headers.get(\"x-agent-id\");\n const signature = email.headers.get(\"x-agent-sig\");\n const timestamp = email.headers.get(\"x-agent-sig-ts\");\n\n if (!agentName || !agentId || !signature || !timestamp) {\n onInvalidSignature?.(email, \"missing_headers\");\n return null;\n }\n\n const result = await verifyAgentSignature(\n secret,\n agentName,\n agentId,\n signature,\n timestamp,\n maxAge\n );\n\n if (!result.valid) {\n onInvalidSignature?.(email, result.reason);\n return null;\n }\n\n return { agentName, agentId, _secureRouted: true };\n };\n}\n\n/**\n * Create a resolver that uses the email address to determine the agent to route the email to\n * @param defaultAgentName The default agent name to use if the email address does not contain a sub-address\n * @returns A function that resolves the agent to route the email to\n */\nexport function createAddressBasedEmailResolver<Env>(\n defaultAgentName: string\n): EmailResolver<Env> {\n return async (email: ForwardableEmailMessage, _env: Env) => {\n // Length limits per RFC 5321: local part max 64 chars, domain max 253 chars\n const emailMatch = email.to.match(\n /^([^+@]{1,64})(?:\\+([^@]{1,64}))?@(.{1,253})$/\n );\n if (!emailMatch) {\n return null;\n }\n\n const [, localPart, subAddress] = emailMatch;\n\n if (subAddress) {\n return {\n agentName: localPart,\n agentId: subAddress\n };\n }\n\n // Option 2: Use defaultAgentName namespace, localPart as agentId\n // Common for catch-all email routing to a single EmailAgent namespace\n return {\n agentName: defaultAgentName,\n agentId: localPart\n };\n };\n}\n\n/**\n * Create a resolver that uses the agentName and agentId to determine the agent to route the email to\n * @param agentName The name of the agent to route the email to\n * @param agentId The id of the agent to route the email to\n * @returns A function that resolves the agent to route the email to\n */\nexport function createCatchAllEmailResolver<Env>(\n agentName: string,\n agentId: string\n): EmailResolver<Env> {\n return async () => ({ agentName, agentId });\n}\n"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,27 +1,29 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AgentEmail } from "./internal_context.js";
|
|
2
|
+
import { EmailResolver, createHeaderBasedEmailResolver } from "./email.js";
|
|
2
3
|
import {
|
|
3
|
-
l as
|
|
4
|
-
r as
|
|
5
|
-
} from "./
|
|
4
|
+
l as TransportType,
|
|
5
|
+
r as MCPConnectionState
|
|
6
|
+
} from "./client-storage-Cvy5r9FG.js";
|
|
6
7
|
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
} from "./client
|
|
8
|
+
AgentMcpOAuthProvider,
|
|
9
|
+
AgentsOAuthProvider
|
|
10
|
+
} from "./mcp/do-oauth-client-provider.js";
|
|
11
|
+
import { MCPClientManager } from "./mcp/client.js";
|
|
11
12
|
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
} from "./workflow-types
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
13
|
+
RunWorkflowOptions,
|
|
14
|
+
WorkflowCallback,
|
|
15
|
+
WorkflowEventPayload,
|
|
16
|
+
WorkflowInfo,
|
|
17
|
+
WorkflowPage,
|
|
18
|
+
WorkflowQueryCriteria
|
|
19
|
+
} from "./workflow-types.js";
|
|
20
|
+
import { Observability } from "./observability/index.js";
|
|
21
|
+
import { MessageType } from "./types.js";
|
|
21
22
|
import {
|
|
22
23
|
Connection,
|
|
23
24
|
Connection as Connection$1,
|
|
24
25
|
ConnectionContext,
|
|
26
|
+
ConnectionContext as ConnectionContext$1,
|
|
25
27
|
PartyServerOptions,
|
|
26
28
|
Server,
|
|
27
29
|
WSMessage
|
|
@@ -77,7 +79,7 @@ type RPCResponse = {
|
|
|
77
79
|
* Metadata for a callable method
|
|
78
80
|
*/
|
|
79
81
|
type CallableMetadata = {
|
|
80
|
-
/** Optional description of what the method does */ description?: string
|
|
82
|
+
/** Optional description of what the method does */ description?: string /** Whether the method supports streaming responses */;
|
|
81
83
|
streaming?: boolean;
|
|
82
84
|
};
|
|
83
85
|
/**
|
|
@@ -96,7 +98,7 @@ declare function callable(
|
|
|
96
98
|
metadata?: CallableMetadata
|
|
97
99
|
): <This, Args extends unknown[], Return>(
|
|
98
100
|
target: (this: This, ...args: Args) => Return,
|
|
99
|
-
|
|
101
|
+
_context: ClassMethodDecoratorContext
|
|
100
102
|
) => (this: This, ...args: Args) => Return;
|
|
101
103
|
/**
|
|
102
104
|
* Decorator that marks a method as callable by clients
|
|
@@ -107,7 +109,7 @@ declare const unstable_callable: (
|
|
|
107
109
|
metadata?: CallableMetadata
|
|
108
110
|
) => <This, Args extends unknown[], Return>(
|
|
109
111
|
target: (this: This, ...args: Args) => Return,
|
|
110
|
-
|
|
112
|
+
_context: ClassMethodDecoratorContext
|
|
111
113
|
) => (this: This, ...args: Args) => Return;
|
|
112
114
|
type QueueItem<T = string> = {
|
|
113
115
|
id: string;
|
|
@@ -120,27 +122,27 @@ type QueueItem<T = string> = {
|
|
|
120
122
|
* @template T Type of the payload data
|
|
121
123
|
*/
|
|
122
124
|
type Schedule<T = string> = {
|
|
123
|
-
/** Unique identifier for the schedule */ id: string
|
|
124
|
-
callback: string
|
|
125
|
+
/** Unique identifier for the schedule */ id: string /** Name of the method to be called */;
|
|
126
|
+
callback: string /** Data to be passed to the callback */;
|
|
125
127
|
payload: T;
|
|
126
128
|
} & (
|
|
127
129
|
| {
|
|
128
|
-
/** Type of schedule for one-time execution at a specific time */ type: "scheduled"
|
|
130
|
+
/** Type of schedule for one-time execution at a specific time */ type: "scheduled" /** Timestamp when the task should execute */;
|
|
129
131
|
time: number;
|
|
130
132
|
}
|
|
131
133
|
| {
|
|
132
|
-
/** Type of schedule for delayed execution */ type: "delayed"
|
|
133
|
-
time: number
|
|
134
|
+
/** Type of schedule for delayed execution */ type: "delayed" /** Timestamp when the task should execute */;
|
|
135
|
+
time: number /** Number of seconds to delay execution */;
|
|
134
136
|
delayInSeconds: number;
|
|
135
137
|
}
|
|
136
138
|
| {
|
|
137
|
-
/** Type of schedule for recurring execution based on cron expression */ type: "cron"
|
|
138
|
-
time: number
|
|
139
|
+
/** Type of schedule for recurring execution based on cron expression */ type: "cron" /** Timestamp for the next execution */;
|
|
140
|
+
time: number /** Cron expression defining the schedule */;
|
|
139
141
|
cron: string;
|
|
140
142
|
}
|
|
141
143
|
| {
|
|
142
|
-
/** Type of schedule for recurring execution at fixed intervals */ type: "interval"
|
|
143
|
-
time: number
|
|
144
|
+
/** Type of schedule for recurring execution at fixed intervals */ type: "interval" /** Timestamp for the next execution */;
|
|
145
|
+
time: number /** Number of seconds between executions */;
|
|
144
146
|
intervalSeconds: number;
|
|
145
147
|
}
|
|
146
148
|
);
|
|
@@ -170,6 +172,7 @@ type MCPServer = {
|
|
|
170
172
|
server_url: string;
|
|
171
173
|
auth_url: string | null;
|
|
172
174
|
state: MCPConnectionState;
|
|
175
|
+
error: string | null;
|
|
173
176
|
instructions: string | null;
|
|
174
177
|
capabilities: ServerCapabilities | null;
|
|
175
178
|
};
|
|
@@ -177,11 +180,19 @@ type MCPServer = {
|
|
|
177
180
|
* Options for adding an MCP server
|
|
178
181
|
*/
|
|
179
182
|
type AddMcpServerOptions = {
|
|
180
|
-
/** OAuth callback host (auto-derived from request if omitted) */ callbackHost?: string;
|
|
181
|
-
|
|
182
|
-
|
|
183
|
+
/** OAuth callback host (auto-derived from request if omitted) */ callbackHost?: string;
|
|
184
|
+
/**
|
|
185
|
+
* Custom callback URL path — bypasses the default `/agents/{class}/{name}/callback` construction.
|
|
186
|
+
* Required when `sendIdentityOnConnect` is `false` to prevent leaking the instance name.
|
|
187
|
+
* When set, the callback URL becomes `{callbackHost}/{callbackPath}`.
|
|
188
|
+
* The developer must route this path to the agent instance via `getAgentByName`.
|
|
189
|
+
* Should be a plain path (e.g., `/mcp-callback`) — do not include query strings or fragments.
|
|
190
|
+
*/
|
|
191
|
+
callbackPath?: string /** Agents routing prefix (default: "agents") */;
|
|
192
|
+
agentsPrefix?: string /** MCP client options */;
|
|
193
|
+
client?: ConstructorParameters<typeof Client>[1] /** Transport options */;
|
|
183
194
|
transport?: {
|
|
184
|
-
/** Custom headers for authentication (e.g., bearer tokens, CF Access) */ headers?: HeadersInit
|
|
195
|
+
/** Custom headers for authentication (e.g., bearer tokens, CF Access) */ headers?: HeadersInit /** Transport type: "sse", "streamable-http", or "auto" (default) */;
|
|
185
196
|
type?: TransportType;
|
|
186
197
|
};
|
|
187
198
|
};
|
|
@@ -190,7 +201,7 @@ type AddMcpServerOptions = {
|
|
|
190
201
|
* Child classes can override specific options without spreading.
|
|
191
202
|
*/
|
|
192
203
|
declare const DEFAULT_AGENT_STATIC_OPTIONS: {
|
|
193
|
-
/** Whether the Agent should hibernate when inactive */ hibernate: boolean
|
|
204
|
+
/** Whether the Agent should hibernate when inactive */ hibernate: boolean /** Whether to send identity (name, agent) to clients on connect */;
|
|
194
205
|
sendIdentityOnConnect: boolean;
|
|
195
206
|
/**
|
|
196
207
|
* Timeout in seconds before a running interval schedule is considered "hung"
|
|
@@ -241,6 +252,19 @@ declare class Agent<
|
|
|
241
252
|
private _state;
|
|
242
253
|
private _disposables;
|
|
243
254
|
private _destroyed;
|
|
255
|
+
/**
|
|
256
|
+
* Stores raw state accessors for wrapped connections.
|
|
257
|
+
* Used by setConnectionReadonly/isConnectionReadonly to read/write the
|
|
258
|
+
* _cf_readonly flag without going through the user-facing state/setState.
|
|
259
|
+
*/
|
|
260
|
+
private _rawStateAccessors;
|
|
261
|
+
/**
|
|
262
|
+
* Cached persistence-hook dispatch mode, computed once in the constructor.
|
|
263
|
+
* - "new" → call onStateChanged
|
|
264
|
+
* - "old" → call onStateUpdate (deprecated)
|
|
265
|
+
* - "none" → neither hook is overridden, skip entirely
|
|
266
|
+
*/
|
|
267
|
+
private _persistenceHookMode;
|
|
244
268
|
private _ParentClass;
|
|
245
269
|
readonly mcp: MCPClientManager;
|
|
246
270
|
/**
|
|
@@ -289,8 +313,39 @@ declare class Agent<
|
|
|
289
313
|
/**
|
|
290
314
|
* Update the Agent's state
|
|
291
315
|
* @param state New state to set
|
|
316
|
+
* @throws Error if called from a readonly connection context
|
|
292
317
|
*/
|
|
293
318
|
setState(state: State): void;
|
|
319
|
+
/**
|
|
320
|
+
* Wraps connection.state and connection.setState so that the internal
|
|
321
|
+
* _cf_readonly flag is hidden from user code and cannot be accidentally
|
|
322
|
+
* overwritten. Must be called before any user code sees the connection.
|
|
323
|
+
*
|
|
324
|
+
* Idempotent — safe to call multiple times on the same connection.
|
|
325
|
+
*/
|
|
326
|
+
private _ensureConnectionWrapped;
|
|
327
|
+
/**
|
|
328
|
+
* Mark a connection as readonly or readwrite
|
|
329
|
+
* @param connection The connection to mark
|
|
330
|
+
* @param readonly Whether the connection should be readonly (default: true)
|
|
331
|
+
*/
|
|
332
|
+
setConnectionReadonly(connection: Connection$1, readonly?: boolean): void;
|
|
333
|
+
/**
|
|
334
|
+
* Check if a connection is marked as readonly
|
|
335
|
+
* @param connection The connection to check
|
|
336
|
+
* @returns True if the connection is readonly
|
|
337
|
+
*/
|
|
338
|
+
isConnectionReadonly(connection: Connection$1): boolean;
|
|
339
|
+
/**
|
|
340
|
+
* Override this method to determine if a connection should be readonly on connect
|
|
341
|
+
* @param _connection The connection that is being established
|
|
342
|
+
* @param _ctx Connection context
|
|
343
|
+
* @returns True if the connection should be readonly
|
|
344
|
+
*/
|
|
345
|
+
shouldConnectionBeReadonly(
|
|
346
|
+
_connection: Connection$1,
|
|
347
|
+
_ctx: ConnectionContext$1
|
|
348
|
+
): boolean;
|
|
294
349
|
/**
|
|
295
350
|
* Called before the Agent's state is persisted and broadcast.
|
|
296
351
|
* Override to validate or reject an update by throwing an error.
|
|
@@ -299,7 +354,25 @@ declare class Agent<
|
|
|
299
354
|
*/
|
|
300
355
|
validateStateChange(nextState: State, source: Connection$1 | "server"): void;
|
|
301
356
|
/**
|
|
302
|
-
* Called
|
|
357
|
+
* Called after the Agent's state has been persisted and broadcast to all clients.
|
|
358
|
+
* This is a notification hook — errors here are routed to onError and do not
|
|
359
|
+
* affect state persistence or client broadcasts.
|
|
360
|
+
*
|
|
361
|
+
* @param state Updated state
|
|
362
|
+
* @param source Source of the state update ("server" or a client connection)
|
|
363
|
+
*/
|
|
364
|
+
onStateChanged(
|
|
365
|
+
state: State | undefined,
|
|
366
|
+
source: Connection$1 | "server"
|
|
367
|
+
): void;
|
|
368
|
+
/**
|
|
369
|
+
* @deprecated Renamed to `onStateChanged` — the behavior is identical.
|
|
370
|
+
* `onStateUpdate` will be removed in the next major version.
|
|
371
|
+
*
|
|
372
|
+
* Called after the Agent's state has been persisted and broadcast to all clients.
|
|
373
|
+
* This is a server-side notification hook. For the client-side state callback,
|
|
374
|
+
* see the `onStateUpdate` option in `useAgent` / `AgentClient`.
|
|
375
|
+
*
|
|
303
376
|
* @param state Updated state
|
|
304
377
|
* @param source Source of the state update ("server" or a client connection)
|
|
305
378
|
*/
|
|
@@ -307,6 +380,11 @@ declare class Agent<
|
|
|
307
380
|
state: State | undefined,
|
|
308
381
|
source: Connection$1 | "server"
|
|
309
382
|
): void;
|
|
383
|
+
/**
|
|
384
|
+
* Dispatch to the appropriate persistence hook based on the mode
|
|
385
|
+
* cached in the constructor. No prototype walks at call time.
|
|
386
|
+
*/
|
|
387
|
+
private _callStatePersistenceHook;
|
|
310
388
|
/**
|
|
311
389
|
* Called when the Agent receives an email via routeAgentEmail()
|
|
312
390
|
* Override this method to handle incoming emails
|
|
@@ -882,6 +960,29 @@ declare class Agent<
|
|
|
882
960
|
>;
|
|
883
961
|
removeMcpServer(id: string): Promise<void>;
|
|
884
962
|
getMcpServers(): MCPServersState;
|
|
963
|
+
/**
|
|
964
|
+
* Create the OAuth provider used when connecting to MCP servers that require authentication.
|
|
965
|
+
*
|
|
966
|
+
* Override this method in a subclass to supply a custom OAuth provider implementation,
|
|
967
|
+
* for example to use pre-registered client credentials, mTLS-based authentication,
|
|
968
|
+
* or any other OAuth flow beyond dynamic client registration.
|
|
969
|
+
*
|
|
970
|
+
* @example
|
|
971
|
+
* // Custom OAuth provider
|
|
972
|
+
* class MyAgent extends Agent {
|
|
973
|
+
* createMcpOAuthProvider(callbackUrl: string): AgentMcpOAuthProvider {
|
|
974
|
+
* return new MyCustomOAuthProvider(
|
|
975
|
+
* this.ctx.storage,
|
|
976
|
+
* this.name,
|
|
977
|
+
* callbackUrl
|
|
978
|
+
* );
|
|
979
|
+
* }
|
|
980
|
+
* }
|
|
981
|
+
*
|
|
982
|
+
* @param callbackUrl The OAuth callback URL for the authorization flow
|
|
983
|
+
* @returns An {@link AgentMcpOAuthProvider} instance used by {@link addMcpServer}
|
|
984
|
+
*/
|
|
985
|
+
createMcpOAuthProvider(callbackUrl: string): AgentMcpOAuthProvider;
|
|
885
986
|
private broadcastMcpServers;
|
|
886
987
|
/**
|
|
887
988
|
* Handle MCP OAuth callback request if it's an OAuth callback.
|
|
@@ -919,12 +1020,7 @@ type AgentContext = DurableObjectState;
|
|
|
919
1020
|
/**
|
|
920
1021
|
* Configuration options for Agent routing
|
|
921
1022
|
*/
|
|
922
|
-
type AgentOptions<Env> = PartyServerOptions<Env
|
|
923
|
-
/**
|
|
924
|
-
* Whether to enable CORS for the Agent
|
|
925
|
-
*/
|
|
926
|
-
cors?: boolean | HeadersInit | undefined;
|
|
927
|
-
};
|
|
1023
|
+
type AgentOptions<Env> = PartyServerOptions<Env>;
|
|
928
1024
|
/**
|
|
929
1025
|
* Route a request to the appropriate Agent
|
|
930
1026
|
* @param request Request to route
|
|
@@ -1016,9 +1112,11 @@ export {
|
|
|
1016
1112
|
AddMcpServerOptions,
|
|
1017
1113
|
Agent,
|
|
1018
1114
|
AgentContext,
|
|
1115
|
+
type AgentMcpOAuthProvider,
|
|
1019
1116
|
AgentNamespace,
|
|
1020
1117
|
AgentOptions,
|
|
1021
1118
|
AgentStaticOptions,
|
|
1119
|
+
type AgentsOAuthProvider,
|
|
1022
1120
|
CallableMetadata,
|
|
1023
1121
|
type Connection,
|
|
1024
1122
|
type ConnectionContext,
|