agents 0.12.0 → 0.12.2

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/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["agentContext","_parseSubAgentPath"],"sources":["../src/index.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\nimport type { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport {\n __DO_NOT_USE_WILL_BREAK__agentContext as agentContext,\n type AgentEmail\n} from \"./internal_context\";\nexport { __DO_NOT_USE_WILL_BREAK__agentContext } from \"./internal_context\";\nimport {\n SUB_PREFIX,\n parseSubAgentPath as _parseSubAgentPath\n} from \"./sub-routing\";\nexport {\n routeSubAgentRequest,\n getSubAgentByName,\n parseSubAgentPath,\n SUB_PREFIX\n} from \"./sub-routing\";\nexport type { SubAgentPathMatch } from \"./sub-routing\";\nimport type { SSEClientTransportOptions } from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport { signAgentHeaders } from \"./email\";\n\nimport type {\n Prompt,\n Resource,\n ServerCapabilities,\n Tool\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { parseCronExpression } from \"cron-schedule\";\nimport { nanoid } from \"nanoid\";\nimport { EmailMessage } from \"cloudflare:email\";\nimport { RpcTarget } from \"cloudflare:workers\";\nimport {\n type Connection,\n type ConnectionContext,\n type PartyServerOptions,\n Server,\n type WSMessage,\n getServerByName,\n routePartykitRequest\n} from \"partyserver\";\nimport { camelCaseToKebabCase } from \"./utils\";\nimport {\n type RetryOptions,\n tryN,\n isErrorRetryable,\n validateRetryOptions\n} from \"./retries\";\nimport { MCPClientManager, type MCPClientOAuthResult } from \"./mcp/client\";\nimport type {\n WorkflowCallback,\n WorkflowTrackingRow,\n WorkflowStatus,\n RunWorkflowOptions,\n WorkflowEventPayload,\n WorkflowInfo,\n WorkflowQueryCriteria,\n WorkflowPage\n} from \"./workflow-types\";\nimport { MCPConnectionState } from \"./mcp/client-connection\";\nimport {\n DurableObjectOAuthClientProvider,\n type AgentMcpOAuthProvider\n} from \"./mcp/do-oauth-client-provider\";\nimport type { TransportType } from \"./mcp/types\";\nimport {\n genericObservability,\n type Observability,\n type ObservabilityEvent\n} from \"./observability\";\nimport { DisposableStore } from \"./core/events\";\nimport { MessageType } from \"./types\";\nimport { RPC_DO_PREFIX } from \"./mcp/rpc\";\nimport type { McpAgent } from \"./mcp\";\nimport type {\n AgentToolChildAdapter,\n AgentToolDisplayMetadata,\n AgentToolEvent,\n AgentToolEventMessage,\n AgentToolLifecycleResult,\n AgentToolRunInfo,\n AgentToolRunInspection,\n AgentToolRunStatus,\n AgentToolStoredChunk,\n ChatCapableAgentClass,\n RunAgentToolOptions,\n RunAgentToolResult\n} from \"./agent-tool-types\";\n\nexport type {\n AgentToolChildAdapter,\n AgentToolDisplayMetadata,\n AgentToolEvent,\n AgentToolEventMessage,\n AgentToolEventState,\n AgentToolLifecycleResult,\n AgentToolRunInfo,\n AgentToolRunInspection,\n AgentToolRunState,\n AgentToolRunStatus,\n AgentToolStoredChunk,\n AgentToolTerminalStatus,\n ChatCapableAgentClass,\n RunAgentToolOptions,\n RunAgentToolResult\n} from \"./agent-tool-types\";\n\nexport type { Connection, ConnectionContext, WSMessage } from \"partyserver\";\nexport { MessageType } from \"./types\";\n\n/**\n * Structural type for Cloudflare's `send_email` binding.\n * Accepts both raw MIME messages and structured builder objects.\n */\nexport type EmailSendBinding = {\n send(\n message:\n | EmailMessage\n | {\n from: string | { email: string; name?: string };\n to: string | string[];\n subject: string;\n replyTo?: string | { email: string; name?: string };\n cc?: string | string[];\n bcc?: string | string[];\n headers?: Record<string, string>;\n text?: string;\n html?: string;\n }\n ): Promise<EmailSendResult>;\n};\n\n/**\n * Options for Agent.sendEmail()\n */\nexport type SendEmailOptions = {\n binding: EmailSendBinding;\n to: string | string[];\n from: string | { email: string; name?: string };\n subject: string;\n text?: string;\n html?: string;\n replyTo?: string | { email: string; name?: string };\n cc?: string | string[];\n bcc?: string | string[];\n inReplyTo?: string;\n headers?: Record<string, string>;\n secret?: string;\n};\n\n/**\n * RPC request message from client\n */\nexport type RPCRequest = {\n type: \"rpc\";\n id: string;\n method: string;\n args: unknown[];\n};\n\n/**\n * State update message from client\n */\nexport type StateUpdateMessage = {\n type: MessageType.CF_AGENT_STATE;\n state: unknown;\n};\n\n/**\n * RPC response message to client\n */\nexport type RPCResponse = {\n type: MessageType.RPC;\n id: string;\n} & (\n | {\n success: true;\n result: unknown;\n done?: false;\n }\n | {\n success: true;\n result: unknown;\n done: true;\n }\n | {\n success: false;\n error: string;\n }\n);\n\n/**\n * Type guard for RPC request messages\n */\nfunction isRPCRequest(msg: unknown): msg is RPCRequest {\n return (\n typeof msg === \"object\" &&\n msg !== null &&\n \"type\" in msg &&\n msg.type === MessageType.RPC &&\n \"id\" in msg &&\n typeof msg.id === \"string\" &&\n \"method\" in msg &&\n typeof msg.method === \"string\" &&\n \"args\" in msg &&\n Array.isArray((msg as RPCRequest).args)\n );\n}\n\n/**\n * Type guard for state update messages\n */\nfunction isStateUpdateMessage(msg: unknown): msg is StateUpdateMessage {\n return (\n typeof msg === \"object\" &&\n msg !== null &&\n \"type\" in msg &&\n msg.type === MessageType.CF_AGENT_STATE &&\n \"state\" in msg\n );\n}\n\n/**\n * Metadata for a callable method\n */\nexport type CallableMetadata = {\n /** Optional description of what the method does */\n description?: string;\n /** Whether the method supports streaming responses */\n streaming?: boolean;\n};\n\nconst callableMetadata = new WeakMap<Function, CallableMetadata>();\n\n/**\n * Error class for SQL execution failures, containing the query that failed\n */\nexport class SqlError extends Error {\n /** The SQL query that failed */\n readonly query: string;\n\n constructor(query: string, cause: unknown) {\n const message = cause instanceof Error ? cause.message : String(cause);\n super(`SQL query failed: ${message}`, { cause });\n this.name = \"SqlError\";\n this.query = query;\n }\n}\n\n// ── Sub-agent (facet) types ──────────────────────────────────────────\n\n/**\n * Internal narrowing of `DurableObjectState` to the parts the facet\n * bootstrap path uses. We only need this because `ctx.exports` in the\n * real types (`Cloudflare.Exports`) is keyed by the *consumer's*\n * worker MainModule, which is invisible from inside this library —\n * so we widen it to a generic Record indexed by class name.\n *\n * @internal\n */\ninterface FacetCapableCtx {\n facets: DurableObjectFacets;\n /**\n * Worker exports keyed by class export name. workerd's runtime\n * contract: any class registered via `migrations.new_sqlite_classes`\n * (or `migrations.new_classes`) — including facet-only classes\n * that have NO entry in `durable_objects.bindings` — is exposed\n * here as BOTH a `DurableObjectClass` (usable as\n * `FacetStartupOptions.class`) AND a `DurableObjectNamespace`\n * (usable for `idFromName`/`getByName`). The intersection is what\n * makes `ctx.exports[OuterSubAgent].idFromName(...)` work from\n * inside a nested facet bootstrap, even though `OuterSubAgent`\n * isn't bound. Runtime lookups can still return `undefined` for\n * unregistered class names; callers must null-check.\n */\n exports: Record<\n string,\n (DurableObjectClass & DurableObjectNamespace) | undefined\n >;\n}\n\n/**\n * Constructor type for a sub-agent class.\n * Used by {@link Agent.subAgent} to reference the child class\n * via `ctx.exports`.\n *\n * The class name (`cls.name`) must match the export name in the\n * worker entry point — re-exports under a different name\n * (e.g. `export { Foo as Bar }`) are not supported.\n */\nexport type SubAgentClass<T extends Agent = Agent> = {\n new (ctx: DurableObjectState, env: never): T;\n};\n\n/**\n * Wraps `T` in a `Promise` unless it already is one.\n */\ntype Promisify<T> = T extends Promise<unknown> ? T : Promise<T>;\n\n/**\n * A typed RPC stub for a sub-agent. Exposes all public instance methods\n * as callable RPC methods with Promise-wrapped return types.\n *\n * Methods inherited from `Agent` / `Server` / `DurableObject` internals\n * are excluded — only user-defined methods on the subclass are exposed.\n */\nexport type SubAgentStub<T extends Agent> = {\n [K in keyof T as K extends keyof Agent\n ? never\n : T[K] extends (...args: never[]) => unknown\n ? K\n : never]: T[K] extends (...args: infer A) => infer R\n ? (...args: A) => Promisify<R>\n : never;\n};\n\n/**\n * Decorator that marks a method as callable by clients\n * @param metadata Optional metadata about the callable method\n */\nexport function callable(metadata: CallableMetadata = {}) {\n return function callableDecorator<This, Args extends unknown[], Return>(\n target: (this: This, ...args: Args) => Return,\n _context: ClassMethodDecoratorContext\n ) {\n if (!callableMetadata.has(target)) {\n callableMetadata.set(target, metadata);\n }\n\n return target;\n };\n}\n\nlet didWarnAboutUnstableCallable = false;\n\n/**\n * Decorator that marks a method as callable by clients\n * @deprecated this has been renamed to callable, and unstable_callable will be removed in the next major version\n * @param metadata Optional metadata about the callable method\n */\nexport const unstable_callable = (metadata: CallableMetadata = {}) => {\n if (!didWarnAboutUnstableCallable) {\n didWarnAboutUnstableCallable = true;\n console.warn(\n \"unstable_callable is deprecated, use callable instead. unstable_callable will be removed in the next major version.\"\n );\n }\n return callable(metadata);\n};\n\nexport type QueueItem<T = string> = {\n id: string;\n payload: T;\n callback: keyof Agent<Cloudflare.Env>;\n created_at: number;\n retry?: RetryOptions;\n};\n\n/**\n * Represents a scheduled task within an Agent\n * @template T Type of the payload data\n */\nexport type Schedule<T = string> = {\n /** Unique identifier for the schedule */\n id: string;\n /** Name of the method to be called */\n callback: string;\n /** Data to be passed to the callback */\n payload: T;\n /** Retry options for callback execution */\n retry?: RetryOptions;\n} & (\n | {\n /** Type of schedule for one-time execution at a specific time */\n type: \"scheduled\";\n /** Timestamp when the task should execute */\n time: number;\n }\n | {\n /** Type of schedule for delayed execution */\n type: \"delayed\";\n /** Timestamp when the task should execute */\n time: number;\n /** Number of seconds to delay execution */\n delayInSeconds: number;\n }\n | {\n /** Type of schedule for recurring execution based on cron expression */\n type: \"cron\";\n /** Timestamp for the next execution */\n time: number;\n /** Cron expression defining the schedule */\n cron: string;\n }\n | {\n /** Type of schedule for recurring execution at fixed intervals */\n type: \"interval\";\n /** Timestamp for the next execution */\n time: number;\n /** Number of seconds between executions */\n intervalSeconds: number;\n }\n);\n\ntype AgentPathStep = { className: string; name: string };\n\ntype ScheduleStorageRow = {\n id: string;\n callback: string;\n payload: string;\n type: \"scheduled\" | \"delayed\" | \"cron\" | \"interval\";\n time: number;\n delayInSeconds?: number;\n cron?: string;\n intervalSeconds?: number;\n retry?: RetryOptions;\n running?: number;\n execution_started_at?: number | null;\n retry_options?: string | null;\n owner_path?: string | null;\n owner_path_key?: string | null;\n};\n\ntype FacetRunStorageRow = {\n owner_path: string;\n owner_path_key: string;\n run_id: string;\n created_at: number;\n};\n\ntype AgentToolRunStorageRow = {\n run_id: string;\n parent_tool_call_id: string | null;\n agent_type: string;\n input_preview: string | null;\n status: AgentToolRunStatus;\n summary: string | null;\n output_json: string | null;\n error_message: string | null;\n display_metadata: string | null;\n display_order: number;\n started_at: number;\n completed_at: number | null;\n};\n\nexport type ScheduleCriteria = {\n id?: string;\n type?: \"scheduled\" | \"delayed\" | \"cron\" | \"interval\";\n timeRange?: { start?: Date; end?: Date };\n};\n\n/**\n * Internal RPC surface exposed by the root agent for facets to\n * delegate alarm-owning operations (schedules + facet teardown).\n * @internal\n */\ntype RootFacetRpcSurface = {\n _cf_scheduleForFacet<T>(\n ownerPath: ReadonlyArray<AgentPathStep>,\n when: Date | string | number,\n callback: string,\n payload?: T,\n options?: { retry?: RetryOptions; idempotent?: boolean }\n ): Promise<{ schedule: Schedule<T>; created: boolean }>;\n _cf_cancelScheduleForFacet(\n ownerPath: ReadonlyArray<AgentPathStep>,\n id: string\n ): Promise<{ ok: boolean; callback?: string }>;\n _cf_scheduleEveryForFacet<T>(\n ownerPath: ReadonlyArray<AgentPathStep>,\n intervalSeconds: number,\n callback: string,\n payload?: T,\n options?: { retry?: RetryOptions; _idempotent?: boolean }\n ): Promise<{ schedule: Schedule<T>; created: boolean }>;\n _cf_cleanupFacetPrefix(\n ownerPath: ReadonlyArray<AgentPathStep>\n ): Promise<void>;\n _cf_getScheduleForFacet(\n ownerPath: ReadonlyArray<AgentPathStep>,\n id: string\n ): Promise<Schedule<unknown> | undefined>;\n _cf_listSchedulesForFacet(\n ownerPath: ReadonlyArray<AgentPathStep>,\n criteria?: ScheduleCriteria\n ): Promise<Schedule<unknown>[]>;\n _cf_destroyDescendantFacet(\n targetPath: ReadonlyArray<AgentPathStep>\n ): Promise<void>;\n _cf_acquireFacetKeepAlive(\n ownerPath: ReadonlyArray<AgentPathStep>\n ): Promise<string>;\n _cf_releaseFacetKeepAlive(token: string): Promise<void>;\n _cf_registerFacetRun(\n ownerPath: ReadonlyArray<AgentPathStep>,\n runId: string\n ): Promise<void>;\n _cf_unregisterFacetRun(\n ownerPath: ReadonlyArray<AgentPathStep>,\n runId: string\n ): Promise<void>;\n};\n\n/**\n * Context passed to the `runFiber` callback. Provides checkpoint\n * and identity for durable execution.\n */\nexport type FiberContext = {\n /** Unique identifier for this fiber execution. */\n id: string;\n /** Checkpoint data during execution. Synchronous SQLite write. */\n stash(data: unknown): void;\n /** Last checkpoint data (null on first run, populated on recovery re-invocation). */\n snapshot: unknown | null;\n};\n\n/**\n * Context passed to the `onFiberRecovered` hook when an interrupted\n * fiber is detected after DO restart.\n */\nexport type FiberRecoveryContext = {\n /** Fiber ID. */\n id: string;\n /** Name passed to `runFiber`. */\n name: string;\n /** Last checkpoint data from `stash()`, or null if never stashed. */\n snapshot: unknown | null;\n /**\n * Epoch milliseconds when the fiber row was inserted (when `runFiber`\n * started). Use `Date.now() - createdAt` to gate stale recoveries.\n */\n createdAt: number;\n [key: string]: unknown;\n};\n\nconst _fiberALS = new AsyncLocalStorage<{\n id: string;\n stash: (data: unknown) => void;\n}>();\n\nfunction getNextCronTime(cron: string) {\n const interval = parseCronExpression(cron);\n return interval.getNextDate();\n}\n\nexport type { TransportType } from \"./mcp/types\";\nexport type { RetryOptions } from \"./retries\";\nexport {\n DurableObjectOAuthClientProvider,\n type AgentMcpOAuthProvider,\n /** @deprecated Use {@link AgentMcpOAuthProvider} instead. */\n type AgentsOAuthProvider\n} from \"./mcp/do-oauth-client-provider\";\n\n/**\n * MCP Server state update message from server -> Client\n */\nexport type MCPServerMessage = {\n type: MessageType.CF_AGENT_MCP_SERVERS;\n mcp: MCPServersState;\n};\n\nexport type MCPServersState = {\n servers: {\n [id: string]: MCPServer;\n };\n tools: (Tool & { serverId: string })[];\n prompts: (Prompt & { serverId: string })[];\n resources: (Resource & { serverId: string })[];\n};\n\nexport type MCPServer = {\n name: string;\n server_url: string;\n auth_url: string | null;\n // This state is specifically about the temporary process of getting a token (if needed).\n // Scope outside of that can't be relied upon because when the DO sleeps, there's no way\n // to communicate a change to a non-ready state.\n state: MCPConnectionState;\n /** May contain untrusted content from external OAuth providers. Escape appropriately for your output context. */\n error: string | null;\n instructions: string | null;\n capabilities: ServerCapabilities | null;\n};\n\n/**\n * Options for adding an MCP server\n */\nexport type AddMcpServerOptions = {\n /** OAuth callback host (auto-derived from request if omitted) */\n callbackHost?: string;\n /**\n * Custom callback URL path — bypasses the default `/agents/{class}/{name}/callback` construction.\n * Required when `sendIdentityOnConnect` is `false` to prevent leaking the instance name.\n * When set, the callback URL becomes `{callbackHost}/{callbackPath}`.\n * The developer must route this path to the agent instance via `getAgentByName`.\n * Should be a plain path (e.g., `/mcp-callback`) — do not include query strings or fragments.\n */\n callbackPath?: string;\n /** Agents routing prefix (default: \"agents\") */\n agentsPrefix?: string;\n /** MCP client options */\n client?: ConstructorParameters<typeof Client>[1];\n /** Transport options */\n transport?: {\n /** Custom headers for authentication (e.g., bearer tokens, CF Access) */\n headers?: HeadersInit;\n /** Transport type: \"sse\", \"streamable-http\", or \"auto\" (default) */\n type?: TransportType;\n };\n /** Retry options for connection and reconnection attempts */\n retry?: RetryOptions;\n};\n\n/**\n * Options for adding an MCP server via RPC (Durable Object binding)\n */\nexport type AddRpcMcpServerOptions = {\n /** Props to pass to the McpAgent instance */\n props?: Record<string, unknown>;\n};\n\nconst DEFAULT_KEEP_ALIVE_INTERVAL_MS = 30_000;\n\n/**\n * Schema version for the Agent's internal SQLite tables.\n * Bump this when adding new tables, columns, or migrations.\n * The constructor stores this as a row in cf_agents_state and checks it\n * on wake to skip DDL on established DOs.\n */\nconst CURRENT_SCHEMA_VERSION = 7;\n\nconst SCHEMA_VERSION_ROW_ID = \"cf_schema_version\";\nconst STATE_ROW_ID = \"cf_state_row_id\";\n// Legacy key — no longer written, but read for backward compatibility with\n// DOs that were created before the single-row state optimization.\nconst STATE_WAS_CHANGED = \"cf_state_was_changed\";\n\nconst DEFAULT_STATE = {} as unknown;\n\n/**\n * Validate that a stored `parentPath` has the expected shape. Used\n * when restoring from DO storage to guard against corrupted data.\n */\nfunction isValidParentPath(\n value: unknown\n): value is Array<{ className: string; name: string }> {\n if (!Array.isArray(value)) return false;\n return value.every(\n (entry) =>\n entry != null &&\n typeof entry === \"object\" &&\n typeof (entry as { className?: unknown }).className === \"string\" &&\n typeof (entry as { name?: unknown }).name === \"string\"\n );\n}\n\n/**\n * Internal key used to store the readonly flag in connection state.\n * Prefixed with _cf_ to avoid collision with user state keys.\n */\nconst CF_READONLY_KEY = \"_cf_readonly\";\n\n/**\n * Internal key used to store the no-protocol flag in connection state.\n * When set, protocol messages (identity, state sync, MCP servers) are not\n * sent to this connection — neither on connect nor via broadcasts.\n */\nconst CF_NO_PROTOCOL_KEY = \"_cf_no_protocol\";\n\n/**\n * Internal key used to store voice call state in connection state.\n * Used by the voice mixin to track whether a connection is in an active call.\n */\nconst CF_VOICE_IN_CALL_KEY = \"_cf_voiceInCall\";\n\n/**\n * The set of all internal keys stored in connection state that must be\n * hidden from user code and preserved across setState calls.\n */\nconst CF_INTERNAL_KEYS: ReadonlySet<string> = new Set([\n CF_READONLY_KEY,\n CF_NO_PROTOCOL_KEY,\n CF_VOICE_IN_CALL_KEY\n]);\n\n/** Check if a raw connection state object contains any internal keys. */\nfunction rawHasInternalKeys(raw: Record<string, unknown>): boolean {\n for (const key of Object.keys(raw)) {\n if (CF_INTERNAL_KEYS.has(key)) return true;\n }\n return false;\n}\n\n/** Return a copy of `raw` with all internal keys removed, or null if no user keys remain. */\nfunction stripInternalKeys(\n raw: Record<string, unknown>\n): Record<string, unknown> | null {\n const result: Record<string, unknown> = {};\n let hasUserKeys = false;\n for (const key of Object.keys(raw)) {\n if (!CF_INTERNAL_KEYS.has(key)) {\n result[key] = raw[key];\n hasUserKeys = true;\n }\n }\n return hasUserKeys ? result : null;\n}\n\n/** Return a copy containing only the internal keys present in `raw`. */\nfunction extractInternalFlags(\n raw: Record<string, unknown>\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(raw)) {\n if (CF_INTERNAL_KEYS.has(key)) {\n result[key] = raw[key];\n }\n }\n return result;\n}\n\n/** Max length for error strings broadcast to clients. */\nconst MAX_ERROR_STRING_LENGTH = 500;\n\n/**\n * Sanitize an error string before broadcasting to clients.\n * MCP error strings may contain untrusted content from external OAuth\n * providers — truncate and strip control characters to limit XSS risk.\n */\n// Regex to match C0 control characters (except \\t, \\n, \\r) and DEL.\nconst CONTROL_CHAR_RE = new RegExp(\n // oxlint-disable-next-line no-control-regex -- intentionally matching control chars for sanitization\n \"[\\\\u0000-\\\\u0008\\\\u000B\\\\u000C\\\\u000E-\\\\u001F\\\\u007F]\",\n \"g\"\n);\n\nfunction sanitizeErrorString(error: string | null): string | null {\n if (error === null) return null;\n // Strip control characters (keep printable ASCII + common unicode)\n let sanitized = error.replace(CONTROL_CHAR_RE, \"\");\n if (sanitized.length > MAX_ERROR_STRING_LENGTH) {\n sanitized = sanitized.substring(0, MAX_ERROR_STRING_LENGTH) + \"...\";\n }\n return sanitized;\n}\n\n/**\n * Tracks which agent constructors have already emitted the onStateUpdate\n * deprecation warning, so it fires at most once per class.\n */\nconst _onStateUpdateWarnedClasses = new WeakSet<Function>();\n\n/**\n * Tracks which agent constructors have already emitted the\n * sendIdentityOnConnect deprecation warning, so it fires at most once per class.\n */\nconst _sendIdentityWarnedClasses = new WeakSet<Function>();\n\n/**\n * Default options for Agent configuration.\n * Child classes can override specific options without spreading.\n */\nexport const DEFAULT_AGENT_STATIC_OPTIONS = {\n /** Whether the Agent should hibernate when inactive */\n hibernate: true,\n /** Whether to send identity (name, agent) to clients on connect */\n sendIdentityOnConnect: true,\n /**\n * Timeout in seconds before a running interval schedule is considered \"hung\"\n * and force-reset. Increase this if you have callbacks that legitimately\n * take longer than 30 seconds.\n */\n hungScheduleTimeoutSeconds: 30,\n /**\n * Interval in milliseconds for keepAlive() alarm heartbeats.\n * Lower values mean faster recovery after eviction but more frequent alarms.\n */\n keepAliveIntervalMs: DEFAULT_KEEP_ALIVE_INTERVAL_MS,\n /** Default retry options for schedule(), queue(), and this.retry() */\n retry: {\n maxAttempts: 3,\n baseDelayMs: 100,\n maxDelayMs: 3000\n } satisfies Required<RetryOptions>\n};\n\n/**\n * Fully resolved agent options — all fields are defined with concrete values.\n */\ninterface ResolvedAgentOptions {\n hibernate: boolean;\n sendIdentityOnConnect: boolean;\n hungScheduleTimeoutSeconds: number;\n keepAliveIntervalMs: number;\n retry: Required<RetryOptions>;\n}\n\n/**\n * Configuration options for the Agent.\n * Override in subclasses via `static options`.\n * All fields are optional - defaults are applied at runtime.\n * Note: `hibernate` defaults to `true` if not specified.\n */\nexport interface AgentStaticOptions {\n hibernate?: boolean;\n sendIdentityOnConnect?: boolean;\n hungScheduleTimeoutSeconds?: number;\n /**\n * Interval in milliseconds for keepAlive() alarm heartbeats.\n * Default: 30000 (30 seconds). Lower values mean faster recovery\n * after eviction but more frequent alarms.\n */\n keepAliveIntervalMs?: number;\n /** Default retry options for schedule(), queue(), and this.retry(). */\n retry?: RetryOptions;\n}\n\n/**\n * Parse the raw `retry_options` TEXT column from a SQLite row into a\n * typed `RetryOptions` object, or `undefined` if not set.\n */\nfunction parseRetryOptions(\n row: Record<string, unknown>\n): RetryOptions | undefined {\n const raw = row.retry_options;\n if (typeof raw !== \"string\") return undefined;\n return JSON.parse(raw) as RetryOptions;\n}\n\n/**\n * Resolve per-task retry options against class-level defaults and call\n * `tryN`. This is the shared retry-execution path used by both queue\n * flush and schedule alarm handlers.\n */\nfunction resolveRetryConfig(\n taskRetry: RetryOptions | undefined,\n defaults: Required<RetryOptions>\n): { maxAttempts: number; baseDelayMs: number; maxDelayMs: number } {\n return {\n maxAttempts: taskRetry?.maxAttempts ?? defaults.maxAttempts,\n baseDelayMs: taskRetry?.baseDelayMs ?? defaults.baseDelayMs,\n maxDelayMs: taskRetry?.maxDelayMs ?? defaults.maxDelayMs\n };\n}\n\nexport function getCurrentAgent<\n T extends Agent<Cloudflare.Env> = Agent<Cloudflare.Env>\n>(): {\n agent: T | undefined;\n connection: Connection | undefined;\n request: Request | undefined;\n email: AgentEmail | undefined;\n} {\n const store = agentContext.getStore() as\n | {\n agent: T;\n connection: Connection | undefined;\n request: Request | undefined;\n email: AgentEmail | undefined;\n }\n | undefined;\n if (!store) {\n return {\n agent: undefined,\n connection: undefined,\n request: undefined,\n email: undefined\n };\n }\n return store;\n}\n\n/**\n * Wraps a method to run within the agent context, ensuring getCurrentAgent() works properly\n * @param agent The agent instance\n * @param method The method to wrap\n * @returns A wrapped method that runs within the agent context\n */\n\n// oxlint-disable-next-line @typescript-eslint/no-explicit-any -- generic callable constraint\nfunction withAgentContext<T extends (...args: any[]) => any>(\n method: T\n): (\n this: Agent<Cloudflare.Env, unknown>,\n ...args: Parameters<T>\n) => ReturnType<T> {\n return function (...args: Parameters<T>): ReturnType<T> {\n const { agent } = getCurrentAgent();\n\n if (agent === this) {\n // already wrapped, so we can just call the method\n return method.apply(this, args);\n }\n // Crossing to a different Agent must not carry native I/O handles\n // from the previous request/WebSocket/email turn into the new DO.\n return agentContext.run(\n {\n agent: this,\n connection: undefined,\n request: undefined,\n email: undefined\n },\n () => {\n return method.apply(this, args);\n }\n );\n };\n}\n\n/**\n * Extract string keys from Env where the value is a Workflow binding.\n */\ntype WorkflowBinding<E> = {\n [K in keyof E & string]: E[K] extends Workflow ? K : never;\n}[keyof E & string];\n\n/**\n * Type for workflow name parameter.\n * When Env has typed Workflow bindings, provides autocomplete for those keys.\n * Also accepts any string for dynamic use cases and compatibility.\n * The `string & {}` trick preserves autocomplete while allowing any string.\n */\ntype WorkflowName<E> = WorkflowBinding<E> | (string & {});\n\n/**\n * Base class for creating Agent implementations\n * @template Env Environment type containing bindings\n * @template State State type to store within the Agent\n */\nexport class Agent<\n Env extends Cloudflare.Env = Cloudflare.Env,\n State = unknown,\n Props extends Record<string, unknown> = Record<string, unknown>\n> extends Server<Env, Props> {\n private _state = DEFAULT_STATE as State;\n private _disposables = new DisposableStore();\n private _destroyed = false;\n\n /**\n * Stores raw state accessors for wrapped connections.\n * Used by internal flag methods (readonly, no-protocol) to read/write\n * _cf_-prefixed keys without going through the user-facing state/setState.\n */\n private _rawStateAccessors = new WeakMap<\n Connection,\n {\n getRaw: () => Record<string, unknown> | null;\n setRaw: (state: unknown) => unknown;\n }\n >();\n\n /**\n * Cached persistence-hook dispatch mode, computed once in the constructor.\n * - \"new\" → call onStateChanged\n * - \"old\" → call onStateUpdate (deprecated)\n * - \"none\" → neither hook is overridden, skip entirely\n */\n private _persistenceHookMode: \"new\" | \"old\" | \"none\" = \"none\";\n\n /** True when this agent runs as a facet (sub-agent) inside a parent. */\n private _isFacet = false;\n\n /**\n * True only while the internal facet bootstrap RPC runs startup.\n * Startup may happen while the parent is handling a WebSocket\n * message, so protocol broadcasts must not touch any ambient\n * parent-owned WebSocket handles during this window.\n */\n private _suppressProtocolBroadcasts = false;\n\n /**\n * Ancestor chain, root-first. Empty for top-level DOs; populated at\n * facet init time from the parent's own `selfPath`. Exposed publicly\n * via the `parentPath` getter.\n * @internal\n */\n private _parentPath: ReadonlyArray<{ className: string; name: string }> = [];\n\n /** True while user's onStart() is executing. Used to warn about non-idempotent schedule() calls. */\n private _insideOnStart = false;\n\n /** Tracks callbacks already warned about during this onStart() to avoid log spam. */\n private _warnedScheduleInOnStart = new Set<string>();\n\n /**\n * Number of active keepAlive() callers. When > 0, `_scheduleNextAlarm()`\n * caps the next alarm at `keepAliveIntervalMs` so the DO stays alive.\n * Purely in-memory — lost on eviction, which is correct because the\n * in-memory work keepAlive was protecting is also lost.\n * @internal\n */\n _keepAliveRefs = 0;\n\n /**\n * In-memory tokens for keepAlive leases acquired by facets and held\n * on the root alarm owner. Lost on eviction, like `_keepAliveRefs`,\n * because the in-memory work those leases were protecting is also gone.\n * @internal\n */\n private _facetKeepAliveTokens = new Set<string>();\n\n /** @internal In-memory set of fiber IDs running in this process. */\n private _runFiberActiveFibers = new Set<string>();\n /** @internal Prevents re-entrant recovery from overlapping alarm ticks. */\n private _runFiberRecoveryInProgress = false;\n\n private _ParentClass: typeof Agent<Env, State> =\n Object.getPrototypeOf(this).constructor;\n\n readonly mcp: MCPClientManager;\n\n /**\n * Initial state for the Agent\n * Override to provide default state values\n */\n initialState: State = DEFAULT_STATE as State;\n\n /**\n * Stable key for Workers AI session affinity (prefix-cache optimization).\n *\n * Uses the Durable Object ID, which is globally unique across all agent\n * classes and stable for the lifetime of the instance. Pass this value as\n * the `sessionAffinity` option when creating a Workers AI model so that\n * requests from the same agent instance are routed to the same backend\n * replica, improving KV-prefix-cache hit rates across conversation turns.\n *\n * @example\n * ```typescript\n * const workersai = createWorkersAI({ binding: this.env.AI });\n * const model = workersai(\"@cf/meta/llama-3.3-70b-instruct-fp8-fast\", {\n * sessionAffinity: this.sessionAffinity,\n * });\n * ```\n */\n get sessionAffinity(): string {\n return this.ctx.id.toString();\n }\n\n /**\n * Current state of the Agent\n */\n get state(): State {\n if (this._state !== DEFAULT_STATE) {\n // state was previously set, and populated internal state\n return this._state;\n }\n // looks like this is the first time the state is being accessed\n // check if the state was set in a previous life\n const result = this.sql<{ state: State | undefined }>`\n SELECT state FROM cf_agents_state WHERE id = ${STATE_ROW_ID}\n `;\n\n // Row existence is the signal that state was previously set.\n // This handles all values including falsy ones (null, 0, false, \"\").\n if (result.length > 0) {\n const state = result[0].state as string;\n\n try {\n this._state = JSON.parse(state);\n } catch (e) {\n console.error(\n \"Failed to parse stored state, falling back to initialState:\",\n e\n );\n if (this.initialState !== DEFAULT_STATE) {\n this._state = this.initialState;\n // Persist the fixed state to prevent future parse errors\n this._setStateInternal(this.initialState);\n } else {\n // No initialState defined - clear corrupted data to prevent infinite retry loop\n this.sql`DELETE FROM cf_agents_state WHERE id = ${STATE_ROW_ID}`;\n return undefined as State;\n }\n }\n return this._state;\n }\n\n // ok, this is the first time the state is being accessed\n // and the state was not set in a previous life\n // so we need to set the initial state (if provided)\n if (this.initialState === DEFAULT_STATE) {\n // no initial state provided, so we return undefined\n return undefined as State;\n }\n // initial state provided, so we set the state,\n // update db and return the initial state\n this._setStateInternal(this.initialState);\n return this.initialState;\n }\n\n /**\n * Agent configuration options.\n * Override in subclasses - only specify what you want to change.\n * @example\n * class SecureAgent extends Agent {\n * static options = { sendIdentityOnConnect: false };\n * }\n */\n static options: AgentStaticOptions = { hibernate: true };\n\n /**\n * Resolved options (merges defaults with subclass overrides).\n * Cached after first access — static options never change during the\n * lifetime of a Durable Object instance.\n */\n private _cachedOptions?: ResolvedAgentOptions;\n private get _resolvedOptions(): ResolvedAgentOptions {\n if (this._cachedOptions) return this._cachedOptions;\n const ctor = this.constructor as typeof Agent;\n const userRetry = ctor.options?.retry;\n this._cachedOptions = {\n hibernate:\n ctor.options?.hibernate ?? DEFAULT_AGENT_STATIC_OPTIONS.hibernate,\n sendIdentityOnConnect:\n ctor.options?.sendIdentityOnConnect ??\n DEFAULT_AGENT_STATIC_OPTIONS.sendIdentityOnConnect,\n hungScheduleTimeoutSeconds:\n ctor.options?.hungScheduleTimeoutSeconds ??\n DEFAULT_AGENT_STATIC_OPTIONS.hungScheduleTimeoutSeconds,\n keepAliveIntervalMs:\n ctor.options?.keepAliveIntervalMs ??\n DEFAULT_AGENT_STATIC_OPTIONS.keepAliveIntervalMs,\n retry: {\n maxAttempts:\n userRetry?.maxAttempts ??\n DEFAULT_AGENT_STATIC_OPTIONS.retry.maxAttempts,\n baseDelayMs:\n userRetry?.baseDelayMs ??\n DEFAULT_AGENT_STATIC_OPTIONS.retry.baseDelayMs,\n maxDelayMs:\n userRetry?.maxDelayMs ?? DEFAULT_AGENT_STATIC_OPTIONS.retry.maxDelayMs\n }\n };\n return this._cachedOptions;\n }\n\n /**\n * The observability implementation to use for the Agent\n */\n observability?: Observability = genericObservability;\n\n /**\n * Emit an observability event with auto-generated timestamp.\n * @internal\n */\n protected _emit(\n type: ObservabilityEvent[\"type\"],\n payload: Record<string, unknown> = {}\n ): void {\n this.observability?.emit({\n type,\n agent: this._ParentClass.name,\n name: this.name,\n payload,\n timestamp: Date.now()\n } as ObservabilityEvent);\n }\n\n /**\n * Execute SQL queries against the Agent's database\n * @template T Type of the returned rows\n * @param strings SQL query template strings\n * @param values Values to be inserted into the query\n * @returns Array of query results\n */\n sql<T = Record<string, string | number | boolean | null>>(\n strings: TemplateStringsArray,\n ...values: (string | number | boolean | null)[]\n ) {\n let query = \"\";\n try {\n // Construct the SQL query with placeholders\n query = strings.reduce(\n (acc, str, i) => acc + str + (i < values.length ? \"?\" : \"\"),\n \"\"\n );\n\n // Execute the SQL query with the provided values\n return [...this.ctx.storage.sql.exec(query, ...values)] as T[];\n } catch (e) {\n throw new SqlError(query, e);\n }\n }\n /**\n * Create all internal tables and run migrations if needed.\n * Called by the constructor on every wake. Idempotent — skips DDL when\n * the stored schema version matches CURRENT_SCHEMA_VERSION.\n *\n * Protected so that test agents can re-run the real migration path\n * after manipulating DB state (since ctx.abort() is unavailable in\n * local dev and the constructor only runs once per DO instance).\n */\n protected _ensureSchema(): void {\n // Schema version gating: skip all DDL on established DOs whose schema\n // is already up-to-date. We always create cf_agents_state first (cheap\n // idempotent DDL) and store the version as a row inside it.\n this.sql`\n CREATE TABLE IF NOT EXISTS cf_agents_state (\n id TEXT PRIMARY KEY NOT NULL,\n state TEXT\n )\n `;\n\n const versionRow = this.sql<{ state: string | null }>`\n SELECT state FROM cf_agents_state WHERE id = ${SCHEMA_VERSION_ROW_ID}\n `;\n const schemaVersion =\n versionRow.length > 0 ? Number(versionRow[0].state) : 0;\n\n if (schemaVersion < CURRENT_SCHEMA_VERSION) {\n this.sql`\n CREATE TABLE IF NOT EXISTS cf_agents_mcp_servers (\n id TEXT PRIMARY KEY NOT NULL,\n name TEXT NOT NULL,\n server_url TEXT NOT NULL,\n callback_url TEXT NOT NULL,\n client_id TEXT,\n auth_url TEXT,\n server_options TEXT\n )\n `;\n\n this.sql`\n CREATE TABLE IF NOT EXISTS cf_agents_queues (\n id TEXT PRIMARY KEY NOT NULL,\n payload TEXT,\n callback TEXT,\n created_at INTEGER DEFAULT (unixepoch())\n )\n `;\n\n this.sql`\n CREATE TABLE IF NOT EXISTS cf_agents_schedules (\n id TEXT PRIMARY KEY NOT NULL DEFAULT (randomblob(9)),\n callback TEXT,\n payload TEXT,\n type TEXT NOT NULL CHECK(type IN ('scheduled', 'delayed', 'cron', 'interval')),\n time INTEGER,\n delayInSeconds INTEGER,\n cron TEXT,\n intervalSeconds INTEGER,\n running INTEGER DEFAULT 0,\n created_at INTEGER DEFAULT (unixepoch()),\n execution_started_at INTEGER,\n retry_options TEXT,\n owner_path TEXT,\n owner_path_key TEXT\n )\n `;\n\n // Migration: Add columns for interval scheduling (for existing agents)\n // Use raw exec to avoid error logging through onError for expected failures\n const addColumnIfNotExists = (sql: string) => {\n try {\n this.ctx.storage.sql.exec(sql);\n } catch (e) {\n // Only ignore \"duplicate column\" errors, re-throw unexpected errors\n const message = e instanceof Error ? e.message : String(e);\n if (!message.toLowerCase().includes(\"duplicate column\")) {\n throw e;\n }\n }\n };\n\n addColumnIfNotExists(\n \"ALTER TABLE cf_agents_schedules ADD COLUMN intervalSeconds INTEGER\"\n );\n addColumnIfNotExists(\n \"ALTER TABLE cf_agents_schedules ADD COLUMN running INTEGER DEFAULT 0\"\n );\n addColumnIfNotExists(\n \"ALTER TABLE cf_agents_schedules ADD COLUMN execution_started_at INTEGER\"\n );\n addColumnIfNotExists(\n \"ALTER TABLE cf_agents_schedules ADD COLUMN retry_options TEXT\"\n );\n addColumnIfNotExists(\n \"ALTER TABLE cf_agents_schedules ADD COLUMN owner_path TEXT\"\n );\n addColumnIfNotExists(\n \"ALTER TABLE cf_agents_schedules ADD COLUMN owner_path_key TEXT\"\n );\n addColumnIfNotExists(\n \"ALTER TABLE cf_agents_queues ADD COLUMN retry_options TEXT\"\n );\n\n // Migration: Update CHECK constraint on type column to include 'interval'.\n // SQLite doesn't support ALTER TABLE to modify constraints, so we recreate\n // the table when the old constraint is detected.\n {\n const rows = this.ctx.storage.sql\n .exec(\n \"SELECT sql FROM sqlite_master WHERE type='table' AND name='cf_agents_schedules'\"\n )\n .toArray();\n if (rows.length > 0) {\n const ddl = String(rows[0].sql);\n if (!ddl.includes(\"'interval'\")) {\n // Drop any leftover temp table from a previous partial migration\n this.ctx.storage.sql.exec(\n \"DROP TABLE IF EXISTS cf_agents_schedules_new\"\n );\n this.ctx.storage.sql.exec(`\n CREATE TABLE cf_agents_schedules_new (\n id TEXT PRIMARY KEY NOT NULL DEFAULT (randomblob(9)),\n callback TEXT,\n payload TEXT,\n type TEXT NOT NULL CHECK(type IN ('scheduled', 'delayed', 'cron', 'interval')),\n time INTEGER,\n delayInSeconds INTEGER,\n cron TEXT,\n intervalSeconds INTEGER,\n running INTEGER DEFAULT 0,\n created_at INTEGER DEFAULT (unixepoch()),\n execution_started_at INTEGER,\n retry_options TEXT,\n owner_path TEXT,\n owner_path_key TEXT\n )\n `);\n this.ctx.storage.sql.exec(`\n INSERT INTO cf_agents_schedules_new\n (id, callback, payload, type, time, delayInSeconds, cron,\n intervalSeconds, running, created_at, execution_started_at, retry_options,\n owner_path, owner_path_key)\n SELECT id, callback, payload, type, time, delayInSeconds, cron,\n intervalSeconds, running, created_at, execution_started_at, retry_options,\n owner_path, owner_path_key\n FROM cf_agents_schedules\n `);\n this.ctx.storage.sql.exec(\"DROP TABLE cf_agents_schedules\");\n this.ctx.storage.sql.exec(\n \"ALTER TABLE cf_agents_schedules_new RENAME TO cf_agents_schedules\"\n );\n }\n }\n }\n\n // Workflow tracking table for Agent-Workflow integration\n this.sql`\n CREATE TABLE IF NOT EXISTS cf_agents_workflows (\n id TEXT PRIMARY KEY NOT NULL,\n workflow_id TEXT NOT NULL UNIQUE,\n workflow_name TEXT NOT NULL,\n status TEXT NOT NULL CHECK(status IN (\n 'queued', 'running', 'paused', 'errored',\n 'terminated', 'complete', 'waiting',\n 'waitingForPause', 'unknown'\n )),\n metadata TEXT,\n error_name TEXT,\n error_message TEXT,\n created_at INTEGER NOT NULL DEFAULT (unixepoch()),\n updated_at INTEGER NOT NULL DEFAULT (unixepoch()),\n completed_at INTEGER\n )\n `;\n\n this.sql`\n CREATE INDEX IF NOT EXISTS idx_workflows_status ON cf_agents_workflows(status)\n `;\n\n this.sql`\n CREATE INDEX IF NOT EXISTS idx_workflows_name ON cf_agents_workflows(workflow_name)\n `;\n\n // Clean up legacy STATE_WAS_CHANGED rows from the single-row state optimization\n this.ctx.storage.sql.exec(\n \"DELETE FROM cf_agents_state WHERE id = ?\",\n STATE_WAS_CHANGED\n );\n\n // v2: keepAlive no longer uses schedule rows. Remove any orphaned\n // heartbeat schedules left over from the previous implementation.\n if (schemaVersion < 2) {\n this.ctx.storage.sql.exec(\n \"DELETE FROM cf_agents_schedules WHERE callback = '_cf_keepAliveHeartbeat'\"\n );\n }\n\n // v3: durable fibers table for runFiber\n this.sql`\n CREATE TABLE IF NOT EXISTS cf_agents_runs (\n id TEXT PRIMARY KEY NOT NULL,\n name TEXT NOT NULL,\n snapshot TEXT,\n created_at INTEGER NOT NULL\n )\n `;\n\n // v5: root-side index of descendant facet fibers. The fiber's\n // authoritative row stays in the facet's own cf_agents_runs table;\n // this table only lets the root alarm owner know which facets need\n // recovery checks while they are idle.\n this.sql`\n CREATE TABLE IF NOT EXISTS cf_agents_facet_runs (\n owner_path TEXT NOT NULL,\n owner_path_key TEXT NOT NULL,\n run_id TEXT NOT NULL,\n created_at INTEGER NOT NULL,\n PRIMARY KEY (owner_path_key, run_id)\n )\n `;\n\n this.sql`\n CREATE INDEX IF NOT EXISTS idx_facet_runs_owner_path_key\n ON cf_agents_facet_runs(owner_path_key)\n `;\n\n this.sql`\n CREATE TABLE IF NOT EXISTS cf_agent_tool_runs (\n run_id TEXT PRIMARY KEY,\n parent_tool_call_id TEXT,\n agent_type TEXT NOT NULL,\n input_preview TEXT,\n input_redacted INTEGER NOT NULL DEFAULT 1,\n status TEXT NOT NULL,\n summary TEXT,\n output_json TEXT,\n error_message TEXT,\n display_metadata TEXT,\n display_order INTEGER NOT NULL DEFAULT 0,\n started_at INTEGER NOT NULL,\n completed_at INTEGER\n )\n `;\n\n this.sql`\n CREATE INDEX IF NOT EXISTS idx_agent_tool_runs_parent_tool_call_id\n ON cf_agent_tool_runs(parent_tool_call_id, display_order)\n `;\n\n addColumnIfNotExists(\n \"ALTER TABLE cf_agent_tool_runs ADD COLUMN output_json TEXT\"\n );\n\n // Mark schema as up-to-date\n this.sql`\n INSERT OR REPLACE INTO cf_agents_state (id, state)\n VALUES (${SCHEMA_VERSION_ROW_ID}, ${String(CURRENT_SCHEMA_VERSION)})\n `;\n }\n }\n\n constructor(ctx: AgentContext, env: Env) {\n super(ctx, env);\n\n if (!wrappedClasses.has(this.constructor)) {\n // Auto-wrap custom methods with agent context\n this._autoWrapCustomMethods();\n wrappedClasses.add(this.constructor);\n }\n\n this._ensureSchema();\n\n // Initialize MCPClientManager AFTER tables are created\n this.mcp = new MCPClientManager(this._ParentClass.name, \"0.0.1\", {\n storage: this.ctx.storage,\n createAuthProvider: (callbackUrl) =>\n this.createMcpOAuthProvider(callbackUrl)\n });\n\n // Broadcast server state whenever MCP state changes (register, connect, OAuth, remove, etc.)\n this._disposables.add(\n this.mcp.onServerStateChanged(async () => {\n this.broadcastMcpServers();\n })\n );\n\n // Emit MCP observability events\n this._disposables.add(\n this.mcp.onObservabilityEvent((event) => {\n this.observability?.emit({\n ...event,\n agent: this._ParentClass.name,\n name: this.name\n });\n })\n );\n // Compute persistence-hook dispatch mode once.\n // Throws immediately if both hooks are overridden on the same class.\n {\n const proto = Object.getPrototypeOf(this);\n const hasOwnNew = Object.prototype.hasOwnProperty.call(\n proto,\n \"onStateChanged\"\n );\n const hasOwnOld = Object.prototype.hasOwnProperty.call(\n proto,\n \"onStateUpdate\"\n );\n\n if (hasOwnNew && hasOwnOld) {\n throw new Error(\n `[Agent] Cannot override both onStateChanged and onStateUpdate. ` +\n `Remove onStateUpdate — it has been renamed to onStateChanged.`\n );\n }\n\n if (hasOwnOld) {\n const ctor = this.constructor;\n if (!_onStateUpdateWarnedClasses.has(ctor)) {\n _onStateUpdateWarnedClasses.add(ctor);\n console.warn(\n `[Agent] onStateUpdate is deprecated. Rename to onStateChanged — the behavior is identical.`\n );\n }\n }\n\n const base = Agent.prototype;\n if (proto.onStateChanged !== base.onStateChanged) {\n this._persistenceHookMode = \"new\";\n } else if (proto.onStateUpdate !== base.onStateUpdate) {\n this._persistenceHookMode = \"old\";\n }\n // default \"none\" already set in field initializer\n }\n\n const _onRequest = this.onRequest.bind(this);\n this.onRequest = (request: Request) => {\n return agentContext.run(\n { agent: this, connection: undefined, request, email: undefined },\n async () => {\n // Handle MCP OAuth callback if this is one\n const oauthResponse = await this.handleMcpOAuthCallback(request);\n if (oauthResponse) {\n return oauthResponse;\n }\n\n return this._tryCatch(() => _onRequest(request));\n }\n );\n };\n\n const _onMessage = this.onMessage.bind(this);\n this.onMessage = async (connection: Connection, message: WSMessage) => {\n this._ensureConnectionWrapped(connection);\n return agentContext.run(\n { agent: this, connection, request: undefined, email: undefined },\n async () => {\n if (typeof message !== \"string\") {\n return this._tryCatch(() => _onMessage(connection, message));\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(message);\n } catch (_e) {\n // silently fail and let the onMessage handler handle it\n return this._tryCatch(() => _onMessage(connection, message));\n }\n\n if (isStateUpdateMessage(parsed)) {\n // Check if connection is readonly\n if (this.isConnectionReadonly(connection)) {\n // Send error response back to the connection\n connection.send(\n JSON.stringify({\n type: MessageType.CF_AGENT_STATE_ERROR,\n error: \"Connection is readonly\"\n })\n );\n return;\n }\n try {\n this._setStateInternal(parsed.state as State, connection);\n } catch (e) {\n // validateStateChange (or another sync error) rejected the update.\n // Log the full error server-side, send a generic message to the client.\n console.error(\"[Agent] State update rejected:\", e);\n connection.send(\n JSON.stringify({\n type: MessageType.CF_AGENT_STATE_ERROR,\n error: \"State update rejected\"\n })\n );\n }\n return;\n }\n\n if (isRPCRequest(parsed)) {\n try {\n const { id, method, args } = parsed;\n\n // Check if method exists and is callable\n const methodFn = this[method as keyof this];\n if (typeof methodFn !== \"function\") {\n throw new Error(`Method ${method} does not exist`);\n }\n\n if (!this._isCallable(method)) {\n throw new Error(`Method ${method} is not callable`);\n }\n\n const metadata = callableMetadata.get(methodFn as Function);\n\n // For streaming methods, pass a StreamingResponse object\n if (metadata?.streaming) {\n const stream = new StreamingResponse(connection, id);\n\n this._emit(\"rpc\", { method, streaming: true });\n\n try {\n await methodFn.apply(this, [stream, ...args]);\n } catch (err) {\n console.error(`Error in streaming method \"${method}\":`, err);\n this._emit(\"rpc:error\", {\n method,\n error: err instanceof Error ? err.message : String(err)\n });\n // Auto-close stream with error if method throws before closing\n if (!stream.isClosed) {\n stream.error(\n err instanceof Error ? err.message : String(err)\n );\n }\n }\n return;\n }\n\n // For regular methods, execute and send response\n const result = await methodFn.apply(this, args);\n\n this._emit(\"rpc\", { method, streaming: metadata?.streaming });\n\n const response: RPCResponse = {\n done: true,\n id,\n result,\n success: true,\n type: MessageType.RPC\n };\n connection.send(JSON.stringify(response));\n } catch (e) {\n // Send error response\n const response: RPCResponse = {\n error:\n e instanceof Error ? e.message : \"Unknown error occurred\",\n id: parsed.id,\n success: false,\n type: MessageType.RPC\n };\n connection.send(JSON.stringify(response));\n console.error(\"RPC error:\", e);\n this._emit(\"rpc:error\", {\n method: parsed.method,\n error: e instanceof Error ? e.message : String(e)\n });\n }\n return;\n }\n\n return this._tryCatch(() => _onMessage(connection, message));\n }\n );\n };\n\n const _onConnect = this.onConnect.bind(this);\n this.onConnect = (connection: Connection, ctx: ConnectionContext) => {\n this._ensureConnectionWrapped(connection);\n // TODO: This is a hack to ensure the state is sent after the connection is established\n // must fix this\n return agentContext.run(\n { agent: this, connection, request: ctx.request, email: undefined },\n async () => {\n // Check if connection should be readonly before sending any messages\n // so that the flag is set before the client can respond\n if (this.shouldConnectionBeReadonly(connection, ctx)) {\n this.setConnectionReadonly(connection, true);\n }\n\n // Check if protocol messages should be suppressed for this\n // connection. When disabled, no identity/state/MCP text frames\n // are sent — useful for binary-only clients (e.g. MQTT devices).\n if (this.shouldSendProtocolMessages(connection, ctx)) {\n // Send agent identity first so client knows which instance it's connected to\n // Can be disabled via static options for security-sensitive instance names\n if (this._resolvedOptions.sendIdentityOnConnect) {\n const ctor = this.constructor as typeof Agent;\n if (\n ctor.options?.sendIdentityOnConnect === undefined &&\n !_sendIdentityWarnedClasses.has(ctor) &&\n // Facets are always addressed via `/sub/{class}/{name}`\n // in the OUTER client URL, even though the request the\n // facet itself receives has that segment stripped by\n // `_cf_forwardToFacet`. The sendIdentityOnConnect\n // concern (name only reachable via identity push) does\n // not apply — skip the warning entirely for facets.\n !this._isFacet\n ) {\n // Only warn when using custom routing — with default routing\n // the name is already visible in the URL path (/agents/{class}/{name})\n // so sendIdentityOnConnect leaks no additional information.\n const urlPath = new URL(ctx.request.url).pathname;\n if (!urlPath.includes(this.name)) {\n _sendIdentityWarnedClasses.add(ctor);\n console.warn(\n `[Agent] ${ctor.name}: sending instance name \"${this.name}\" to clients ` +\n `via sendIdentityOnConnect (the name is not visible in the URL with ` +\n `custom routing). If this name is sensitive, add ` +\n `\\`static options = { sendIdentityOnConnect: false }\\` to opt out. ` +\n `Set it to true to silence this message.`\n );\n }\n }\n connection.send(\n JSON.stringify({\n name: this.name,\n agent: camelCaseToKebabCase(this._ParentClass.name),\n type: MessageType.CF_AGENT_IDENTITY\n })\n );\n }\n\n if (this.state) {\n connection.send(\n JSON.stringify({\n state: this.state,\n type: MessageType.CF_AGENT_STATE\n })\n );\n }\n\n connection.send(\n JSON.stringify({\n mcp: this.getMcpServers(),\n type: MessageType.CF_AGENT_MCP_SERVERS\n })\n );\n } else {\n this._setConnectionNoProtocol(connection);\n }\n\n this._emit(\"connect\", { connectionId: connection.id });\n await this._replayAgentToolRuns(connection);\n return this._tryCatch(() => _onConnect(connection, ctx));\n }\n );\n };\n\n const _onClose = this.onClose.bind(this);\n this.onClose = (\n connection: Connection,\n code: number,\n reason: string,\n wasClean: boolean\n ) => {\n return agentContext.run(\n { agent: this, connection, request: undefined, email: undefined },\n () => {\n this._emit(\"disconnect\", {\n connectionId: connection.id,\n code,\n reason\n });\n return _onClose(connection, code, reason, wasClean);\n }\n );\n };\n\n const _onStart = this.onStart.bind(this);\n this.onStart = async (props?: Props) => {\n return agentContext.run(\n {\n agent: this,\n connection: undefined,\n request: undefined,\n email: undefined\n },\n async () => {\n // Hydrate _isFacet from persistent storage so the flag\n // survives hibernation (the DO constructor resets it to false).\n const isFacet =\n await this.ctx.storage.get<boolean>(\"cf_agents_is_facet\");\n if (isFacet) this._isFacet = true;\n\n const storedParentPath = await this.ctx.storage.get<\n Array<{ className: string; name: string }>\n >(\"cf_agents_parent_path\");\n if (isValidParentPath(storedParentPath)) {\n this._parentPath = storedParentPath;\n }\n\n await this._tryCatch(async () => {\n await this.mcp.restoreConnectionsFromStorage(this.name);\n await this._restoreRpcMcpServers();\n this.broadcastMcpServers();\n\n this._checkOrphanedWorkflows();\n await this._checkRunFibers();\n await this._reconcileAgentToolRuns();\n\n this._insideOnStart = true;\n this._warnedScheduleInOnStart.clear();\n try {\n return await _onStart(props);\n } finally {\n this._insideOnStart = false;\n }\n });\n }\n );\n };\n }\n\n /**\n * Check for workflows referencing unknown bindings and warn with migration suggestion.\n */\n private _checkOrphanedWorkflows(): void {\n // Get distinct workflow names with counts by active/completed status\n const distinctNames = this.sql<{\n workflow_name: string;\n total: number;\n active: number;\n completed: number;\n }>`\n SELECT \n workflow_name,\n COUNT(*) as total,\n SUM(CASE WHEN status NOT IN ('complete', 'errored', 'terminated') THEN 1 ELSE 0 END) as active,\n SUM(CASE WHEN status IN ('complete', 'errored', 'terminated') THEN 1 ELSE 0 END) as completed\n FROM cf_agents_workflows \n GROUP BY workflow_name\n `;\n\n const orphaned = distinctNames.filter(\n (row) => !this._findWorkflowBindingByName(row.workflow_name)\n );\n\n if (orphaned.length > 0) {\n const currentBindings = this._getWorkflowBindingNames();\n for (const {\n workflow_name: oldName,\n total,\n active,\n completed\n } of orphaned) {\n const suggestion =\n currentBindings.length === 1\n ? `this.migrateWorkflowBinding('${oldName}', '${currentBindings[0]}')`\n : `this.migrateWorkflowBinding('${oldName}', '<NEW_BINDING_NAME>')`;\n const breakdown =\n active > 0 && completed > 0\n ? ` (${active} active, ${completed} completed)`\n : active > 0\n ? ` (${active} active)`\n : ` (${completed} completed)`;\n console.warn(\n `[Agent] Found ${total} workflow(s) referencing unknown binding '${oldName}'${breakdown}. ` +\n `If you renamed the binding, call: ${suggestion}`\n );\n }\n }\n }\n\n /**\n * Broadcast a protocol message only to connections that have protocol\n * messages enabled. Connections where shouldSendProtocolMessages returned\n * false are excluded automatically.\n * @param msg The JSON-encoded protocol message\n * @param excludeIds Additional connection IDs to exclude (e.g. the source)\n */\n private _broadcastProtocol(msg: string, excludeIds: string[] = []) {\n if (this._suppressProtocolBroadcasts) return;\n\n const exclude = [...excludeIds];\n for (const conn of this.getConnections()) {\n if (!this.isConnectionProtocolEnabled(conn)) {\n exclude.push(conn.id);\n }\n }\n this.broadcast(msg, exclude);\n }\n\n private _setStateInternal(\n nextState: State,\n source: Connection | \"server\" = \"server\"\n ): void {\n // Validation/gating hook (sync only)\n this.validateStateChange(nextState, source);\n\n // Persist state — row existence in cf_agents_state is the signal that\n // state was set (no separate wasChanged flag needed).\n this._state = nextState;\n this.sql`\n INSERT OR REPLACE INTO cf_agents_state (id, state)\n VALUES (${STATE_ROW_ID}, ${JSON.stringify(nextState)})\n `;\n\n // Broadcast state to protocol-enabled connections, excluding the source\n this._broadcastProtocol(\n JSON.stringify({\n state: nextState,\n type: MessageType.CF_AGENT_STATE\n }),\n source !== \"server\" ? [source.id] : []\n );\n\n // Notification hook (non-gating). Run after broadcast and do not block.\n // Use waitUntil for reliability after the handler returns.\n const { connection, request, email } = agentContext.getStore() || {};\n this.ctx.waitUntil(\n (async () => {\n try {\n await agentContext.run(\n { agent: this, connection, request, email },\n async () => {\n this._emit(\"state:update\");\n await this._callStatePersistenceHook(nextState, source);\n }\n );\n } catch (e) {\n // onStateChanged/onStateUpdate errors should not affect state or broadcasts\n try {\n await this.onError(e);\n } catch {\n // swallow\n }\n }\n })()\n );\n }\n\n /**\n * Update the Agent's state\n * @param state New state to set\n * @throws Error if called from a readonly connection context\n */\n setState(state: State): void {\n // Check if the current context has a readonly connection\n const store = agentContext.getStore();\n if (store?.connection && this.isConnectionReadonly(store.connection)) {\n throw new Error(\"Connection is readonly\");\n }\n this._setStateInternal(state, \"server\");\n }\n\n /**\n * Wraps connection.state and connection.setState so that internal\n * _cf_-prefixed flags (readonly, no-protocol) are hidden from user code\n * and cannot be accidentally overwritten.\n *\n * Idempotent — safe to call multiple times on the same connection.\n * After hibernation, the _rawStateAccessors WeakMap is empty but the\n * connection's state getter still reads from the persisted WebSocket\n * attachment. Calling this method re-captures the raw getter so that\n * predicate methods (isConnectionReadonly, isConnectionProtocolEnabled)\n * work correctly post-hibernation.\n */\n private _ensureConnectionWrapped(connection: Connection) {\n if (this._rawStateAccessors.has(connection)) return;\n\n // Determine whether `state` is an accessor (getter) or a data property.\n // partyserver always defines `state` as a getter via Object.defineProperties,\n // but we handle the data-property case to stay robust for hibernate: false\n // and any future connection implementations.\n const descriptor = Object.getOwnPropertyDescriptor(connection, \"state\");\n\n let getRaw: () => Record<string, unknown> | null;\n let setRaw: (state: unknown) => unknown;\n\n if (descriptor?.get) {\n // Accessor property — bind the original getter directly.\n // The getter reads from the serialized WebSocket attachment, so it\n // always returns the latest value even after setState updates it.\n getRaw = descriptor.get.bind(connection) as () => Record<\n string,\n unknown\n > | null;\n setRaw = connection.setState.bind(connection);\n } else {\n // Data property — track raw state in a closure variable.\n // Reading `connection.state` after our override would call our filtered\n // getter (circular), so we snapshot the value here and keep it in sync.\n let rawState = (connection.state ?? null) as Record<\n string,\n unknown\n > | null;\n getRaw = () => rawState;\n setRaw = (state: unknown) => {\n rawState = state as Record<string, unknown> | null;\n return rawState;\n };\n }\n\n this._rawStateAccessors.set(connection, { getRaw, setRaw });\n\n // Override state getter to hide all internal _cf_ flags from user code\n Object.defineProperty(connection, \"state\", {\n configurable: true,\n enumerable: true,\n get() {\n const raw = getRaw();\n if (raw != null && typeof raw === \"object\" && rawHasInternalKeys(raw)) {\n return stripInternalKeys(raw);\n }\n return raw;\n }\n });\n\n // Override setState to preserve internal flags when user sets state\n Object.defineProperty(connection, \"setState\", {\n configurable: true,\n writable: true,\n value(stateOrFn: unknown | ((prev: unknown) => unknown)) {\n const raw = getRaw();\n const flags =\n raw != null && typeof raw === \"object\"\n ? extractInternalFlags(raw as Record<string, unknown>)\n : {};\n const hasFlags = Object.keys(flags).length > 0;\n\n let newUserState: unknown;\n if (typeof stateOrFn === \"function\") {\n // Pass only the user-visible state (without internal flags) to the callback\n const userVisible = hasFlags\n ? stripInternalKeys(raw as Record<string, unknown>)\n : raw;\n newUserState = (stateOrFn as (prev: unknown) => unknown)(userVisible);\n } else {\n newUserState = stateOrFn;\n }\n\n // Merge back internal flags if any were set\n if (hasFlags) {\n if (newUserState != null && typeof newUserState === \"object\") {\n return setRaw({\n ...(newUserState as Record<string, unknown>),\n ...flags\n });\n }\n // User set null — store just the flags\n return setRaw(flags);\n }\n return setRaw(newUserState);\n }\n });\n }\n\n /**\n * Mark a connection as readonly or readwrite\n * @param connection The connection to mark\n * @param readonly Whether the connection should be readonly (default: true)\n */\n setConnectionReadonly(connection: Connection, readonly = true) {\n this._ensureConnectionWrapped(connection);\n const accessors = this._rawStateAccessors.get(connection)!;\n const raw = (accessors.getRaw() as Record<string, unknown> | null) ?? {};\n if (readonly) {\n accessors.setRaw({ ...raw, [CF_READONLY_KEY]: true });\n } else {\n // Remove the key entirely instead of storing false — avoids dead keys\n // accumulating in the connection attachment.\n const { [CF_READONLY_KEY]: _, ...rest } = raw;\n accessors.setRaw(Object.keys(rest).length > 0 ? rest : null);\n }\n }\n\n /**\n * Check if a connection is marked as readonly.\n *\n * Safe to call after hibernation — re-wraps the connection if the\n * in-memory accessor cache was cleared.\n * @param connection The connection to check\n * @returns True if the connection is readonly\n */\n isConnectionReadonly(connection: Connection): boolean {\n this._ensureConnectionWrapped(connection);\n const raw = this._rawStateAccessors.get(connection)!.getRaw() as Record<\n string,\n unknown\n > | null;\n return !!raw?.[CF_READONLY_KEY];\n }\n\n /**\n * ⚠️ INTERNAL — DO NOT USE IN APPLICATION CODE. ⚠️\n *\n * Read an internal `_cf_`-prefixed flag from the raw connection state,\n * bypassing the user-facing state wrapper that strips internal keys.\n *\n * This exists for framework mixins (e.g. voice) that need to persist\n * flags in the connection attachment across hibernation. Application\n * code should use `connection.state` and `connection.setState()` instead.\n *\n * @internal\n */\n _unsafe_getConnectionFlag(connection: Connection, key: string): unknown {\n this._ensureConnectionWrapped(connection);\n const raw = this._rawStateAccessors.get(connection)!.getRaw() as Record<\n string,\n unknown\n > | null;\n return raw?.[key];\n }\n\n /**\n * ⚠️ INTERNAL — DO NOT USE IN APPLICATION CODE. ⚠️\n *\n * Write an internal `_cf_`-prefixed flag to the raw connection state,\n * bypassing the user-facing state wrapper. The key must be registered\n * in `CF_INTERNAL_KEYS` so it is preserved across user `setState` calls\n * and hidden from `connection.state`.\n *\n * @internal\n */\n _unsafe_setConnectionFlag(\n connection: Connection,\n key: string,\n value: unknown\n ): void {\n this._ensureConnectionWrapped(connection);\n const accessors = this._rawStateAccessors.get(connection)!;\n const raw = (accessors.getRaw() as Record<string, unknown> | null) ?? {};\n if (value === undefined) {\n const { [key]: _, ...rest } = raw;\n accessors.setRaw(Object.keys(rest).length > 0 ? rest : null);\n } else {\n accessors.setRaw({ ...raw, [key]: value });\n }\n }\n\n /**\n * Override this method to determine if a connection should be readonly on connect\n * @param _connection The connection that is being established\n * @param _ctx Connection context\n * @returns True if the connection should be readonly\n */\n shouldConnectionBeReadonly(\n _connection: Connection,\n _ctx: ConnectionContext\n ): boolean {\n return false;\n }\n\n /**\n * Override this method to control whether protocol messages are sent to a\n * connection. Protocol messages include identity (CF_AGENT_IDENTITY), state\n * sync (CF_AGENT_STATE), and MCP server lists (CF_AGENT_MCP_SERVERS).\n *\n * When this returns `false` for a connection, that connection will not\n * receive any protocol text frames — neither on connect nor via broadcasts.\n * This is useful for binary-only clients (e.g. MQTT devices) that cannot\n * handle JSON text frames.\n *\n * The connection can still send and receive regular messages, use RPC, and\n * participate in all non-protocol communication.\n *\n * @param _connection The connection that is being established\n * @param _ctx Connection context (includes the upgrade request)\n * @returns True if protocol messages should be sent (default), false to suppress them\n */\n shouldSendProtocolMessages(\n _connection: Connection,\n _ctx: ConnectionContext\n ): boolean {\n return true;\n }\n\n /**\n * Check if a connection has protocol messages enabled.\n * Protocol messages include identity, state sync, and MCP server lists.\n *\n * Safe to call after hibernation — re-wraps the connection if the\n * in-memory accessor cache was cleared.\n * @param connection The connection to check\n * @returns True if the connection receives protocol messages\n */\n isConnectionProtocolEnabled(connection: Connection): boolean {\n this._ensureConnectionWrapped(connection);\n const raw = this._rawStateAccessors.get(connection)!.getRaw() as Record<\n string,\n unknown\n > | null;\n return !raw?.[CF_NO_PROTOCOL_KEY];\n }\n\n /**\n * Mark a connection as having protocol messages disabled.\n * Called internally when shouldSendProtocolMessages returns false.\n */\n private _setConnectionNoProtocol(connection: Connection) {\n this._ensureConnectionWrapped(connection);\n const accessors = this._rawStateAccessors.get(connection)!;\n const raw = (accessors.getRaw() as Record<string, unknown> | null) ?? {};\n accessors.setRaw({ ...raw, [CF_NO_PROTOCOL_KEY]: true });\n }\n\n /**\n * Called before the Agent's state is persisted and broadcast.\n * Override to validate or reject an update by throwing an error.\n *\n * IMPORTANT: This hook must be synchronous.\n */\n // oxlint-disable-next-line eslint(no-unused-vars) -- params used by subclass overrides\n validateStateChange(nextState: State, source: Connection | \"server\") {\n // override this to validate state updates\n }\n\n /**\n * Called after the Agent's state has been persisted and broadcast to all clients.\n * This is a notification hook — errors here are routed to onError and do not\n * affect state persistence or client broadcasts.\n *\n * @param state Updated state\n * @param source Source of the state update (\"server\" or a client connection)\n */\n // oxlint-disable-next-line eslint(no-unused-vars) -- params used by subclass overrides\n onStateChanged(state: State | undefined, source: Connection | \"server\") {\n // override this to handle state updates after persist + broadcast\n }\n\n /**\n * @deprecated Renamed to `onStateChanged` — the behavior is identical.\n * `onStateUpdate` will be removed in the next major version.\n *\n * Called after the Agent's state has been persisted and broadcast to all clients.\n * This is a server-side notification hook. For the client-side state callback,\n * see the `onStateUpdate` option in `useAgent` / `AgentClient`.\n *\n * @param state Updated state\n * @param source Source of the state update (\"server\" or a client connection)\n */\n // oxlint-disable-next-line eslint(no-unused-vars) -- params used by subclass overrides\n onStateUpdate(state: State | undefined, source: Connection | \"server\") {\n // override this to handle state updates (deprecated — use onStateChanged)\n }\n\n /**\n * Dispatch to the appropriate persistence hook based on the mode\n * cached in the constructor. No prototype walks at call time.\n */\n private async _callStatePersistenceHook(\n state: State | undefined,\n source: Connection | \"server\"\n ): Promise<void> {\n switch (this._persistenceHookMode) {\n case \"new\":\n await this.onStateChanged(state, source);\n break;\n case \"old\":\n await this.onStateUpdate(state, source);\n break;\n // \"none\": neither hook overridden — skip\n }\n }\n\n /**\n * Called when the Agent receives an email via routeAgentEmail()\n * Override this method to handle incoming emails\n * @param payload Internal wire format — plain data + RpcTarget bridge\n */\n async _onEmail(payload: {\n from: string;\n to: string;\n headers: Headers;\n rawSize: number;\n _secureRouted?: boolean;\n _bridge: EmailBridge;\n }) {\n // nb: we use this roundabout way of getting to onEmail\n // because of https://github.com/cloudflare/workerd/issues/4499\n\n // Reconstruct the AgentEmail interface from the payload so the\n // user's onEmail handler sees the same API as before\n const email: AgentEmail = {\n from: payload.from,\n to: payload.to,\n headers: payload.headers,\n rawSize: payload.rawSize,\n _secureRouted: payload._secureRouted,\n getRaw: () => payload._bridge.getRaw(),\n setReject: (reason: string) => payload._bridge.setReject(reason),\n forward: (rcptTo: string, headers?: Headers) =>\n payload._bridge.forward(rcptTo, headers),\n reply: (options: { from: string; to: string; raw: string }) =>\n payload._bridge.reply(options)\n };\n\n return agentContext.run(\n { agent: this, connection: undefined, request: undefined, email },\n async () => {\n this._emit(\"email:receive\", {\n from: email.from,\n to: email.to,\n subject: email.headers.get(\"subject\") ?? undefined\n });\n if (\"onEmail\" in this && typeof this.onEmail === \"function\") {\n return this._tryCatch(() =>\n (this.onEmail as (email: AgentEmail) => Promise<void>)(email)\n );\n } else {\n console.log(\"Received email from:\", email.from, \"to:\", email.to);\n console.log(\"Subject:\", email.headers.get(\"subject\"));\n console.log(\n \"Implement onEmail(email: AgentEmail): Promise<void> in your agent to process emails\"\n );\n }\n }\n );\n }\n\n /**\n * Reply to an email\n * @param email The email to reply to\n * @param options Options for the reply\n * @param options.secret Secret for signing agent headers (enables secure reply routing).\n * Required if the email was routed via createSecureReplyEmailResolver.\n * Pass explicit `null` to opt-out of signing (not recommended for secure routing).\n * @returns void\n */\n async replyToEmail(\n email: AgentEmail,\n options: {\n fromName: string;\n subject?: string | undefined;\n body: string;\n contentType?: string;\n headers?: Record<string, string>;\n secret?: string | null;\n }\n ): Promise<void> {\n return this._tryCatch(async () => {\n // Enforce signing for emails routed via createSecureReplyEmailResolver\n if (email._secureRouted && options.secret === undefined) {\n throw new Error(\n \"This email was routed via createSecureReplyEmailResolver. \" +\n \"You must pass a secret to replyToEmail() to sign replies, \" +\n \"or pass explicit null to opt-out (not recommended).\"\n );\n }\n\n const agentName = camelCaseToKebabCase(this._ParentClass.name);\n const agentId = this.name;\n\n const { createMimeMessage } = await import(\"mimetext\");\n const msg = createMimeMessage();\n msg.setSender({ addr: email.to, name: options.fromName });\n msg.setRecipient(email.from);\n msg.setSubject(\n options.subject || `Re: ${email.headers.get(\"subject\")}` || \"No subject\"\n );\n msg.addMessage({\n contentType: options.contentType || \"text/plain\",\n data: options.body\n });\n\n const domain = email.from.split(\"@\")[1];\n const messageId = `<${agentId}@${domain}>`;\n msg.setHeader(\"In-Reply-To\", email.headers.get(\"Message-ID\")!);\n msg.setHeader(\"Message-ID\", messageId);\n msg.setHeader(\"X-Agent-Name\", agentName);\n msg.setHeader(\"X-Agent-ID\", agentId);\n\n // Sign headers if secret is provided (enables secure reply routing)\n if (typeof options.secret === \"string\") {\n const signedHeaders = await signAgentHeaders(\n options.secret,\n agentName,\n agentId\n );\n msg.setHeader(\"X-Agent-Sig\", signedHeaders[\"X-Agent-Sig\"]);\n msg.setHeader(\"X-Agent-Sig-Ts\", signedHeaders[\"X-Agent-Sig-Ts\"]);\n }\n\n if (options.headers) {\n for (const [key, value] of Object.entries(options.headers)) {\n msg.setHeader(key, value);\n }\n }\n await email.reply({\n from: email.to,\n raw: msg.asRaw(),\n to: email.from\n });\n\n // Emit after the send succeeds — from/to are swapped because\n // this is a reply: the agent (email.to) is now the sender.\n const rawSubject = email.headers.get(\"subject\");\n this._emit(\"email:reply\", {\n from: email.to,\n to: email.from,\n subject:\n options.subject ?? (rawSubject ? `Re: ${rawSubject}` : undefined)\n });\n });\n }\n\n /**\n * Send an outbound email via an Email Service binding.\n *\n * Automatically injects agent routing headers (X-Agent-Name, X-Agent-ID).\n * When `secret` is provided, signs headers with HMAC-SHA256 so that replies\n * can be routed back to this agent instance via createSecureReplyEmailResolver.\n *\n * @param options.binding The send_email binding (e.g. this.env.EMAIL)\n * @param options.to Recipient address(es)\n * @param options.from Sender address or {email, name} object\n * @param options.subject Email subject line\n * @param options.text Plain text body (at least one of text/html required)\n * @param options.html HTML body (at least one of text/html required)\n * @param options.replyTo Reply-to address\n * @param options.cc CC recipient(s)\n * @param options.bcc BCC recipient(s)\n * @param options.inReplyTo Message-ID of the email this is replying to (for threading)\n * @param options.headers Additional custom headers\n * @param options.secret Secret for signing agent routing headers\n * @returns The messageId from Email Service\n */\n async sendEmail(options: SendEmailOptions): Promise<EmailSendResult> {\n return this._tryCatch(async () => {\n if (!options.binding) {\n throw new Error(\n \"binding is required. Pass your send_email binding, \" +\n \"e.g. this.sendEmail({ binding: this.env.EMAIL, ... }).\"\n );\n }\n\n const agentName = camelCaseToKebabCase(this._ParentClass.name);\n const agentId = this.name;\n\n const headers: Record<string, string> = {\n ...options.headers,\n \"X-Agent-Name\": agentName,\n \"X-Agent-ID\": agentId\n };\n\n if (options.inReplyTo) {\n headers[\"In-Reply-To\"] = options.inReplyTo;\n }\n\n if (typeof options.secret === \"string\") {\n const signedHeaders = await signAgentHeaders(\n options.secret,\n agentName,\n agentId\n );\n headers[\"X-Agent-Sig\"] = signedHeaders[\"X-Agent-Sig\"];\n headers[\"X-Agent-Sig-Ts\"] = signedHeaders[\"X-Agent-Sig-Ts\"];\n }\n\n const result = await options.binding.send({\n from: options.from,\n to: options.to,\n subject: options.subject,\n text: options.text,\n html: options.html,\n replyTo: options.replyTo,\n cc: options.cc,\n bcc: options.bcc,\n headers\n });\n\n const fromAddr =\n typeof options.from === \"string\" ? options.from : options.from.email;\n this._emit(\"email:send\", {\n from: fromAddr,\n to: options.to,\n subject: options.subject\n });\n\n return result;\n });\n }\n\n private async _tryCatch<T>(fn: () => T | Promise<T>) {\n try {\n return await fn();\n } catch (e) {\n throw this.onError(e);\n }\n }\n\n /**\n * Automatically wrap custom methods with agent context\n * This ensures getCurrentAgent() works in all custom methods without decorators\n */\n private _autoWrapCustomMethods() {\n // Collect all methods from base prototypes (Agent and Server)\n const basePrototypes = [Agent.prototype, Server.prototype];\n const baseMethods = new Set<string>();\n for (const baseProto of basePrototypes) {\n let proto = baseProto;\n while (proto && proto !== Object.prototype) {\n const methodNames = Object.getOwnPropertyNames(proto);\n for (const methodName of methodNames) {\n baseMethods.add(methodName);\n }\n proto = Object.getPrototypeOf(proto);\n }\n }\n // Get all methods from the current instance's prototype chain\n let proto = Object.getPrototypeOf(this);\n let depth = 0;\n while (proto && proto !== Object.prototype && depth < 10) {\n const methodNames = Object.getOwnPropertyNames(proto);\n for (const methodName of methodNames) {\n const descriptor = Object.getOwnPropertyDescriptor(proto, methodName);\n\n // Skip if it's a private method, a base method, a getter, or not a function,\n if (\n baseMethods.has(methodName) ||\n methodName.startsWith(\"_\") ||\n !descriptor ||\n !!descriptor.get ||\n typeof descriptor.value !== \"function\"\n ) {\n continue;\n }\n\n // Now, methodName is confirmed to be a custom method/function\n // Wrap the custom method with context\n /* oxlint-disable @typescript-eslint/no-explicit-any -- dynamic method wrapping requires any */\n const wrappedFunction = withAgentContext(\n this[methodName as keyof this] as (...args: any[]) => any\n ) as any;\n /* oxlint-enable @typescript-eslint/no-explicit-any */\n\n // if the method is callable, copy the metadata from the original method\n if (this._isCallable(methodName)) {\n callableMetadata.set(\n wrappedFunction,\n callableMetadata.get(this[methodName as keyof this] as Function)!\n );\n }\n\n // set the wrapped function on the prototype\n this.constructor.prototype[methodName as keyof this] = wrappedFunction;\n }\n\n proto = Object.getPrototypeOf(proto);\n depth++;\n }\n }\n\n override onError(\n connection: Connection,\n error: unknown\n ): void | Promise<void>;\n override onError(error: unknown): void | Promise<void>;\n override onError(connectionOrError: Connection | unknown, error?: unknown) {\n let theError: unknown;\n if (connectionOrError && error) {\n theError = error;\n // this is a websocket connection error\n console.error(\n \"Error on websocket connection:\",\n (connectionOrError as Connection).id,\n theError\n );\n console.error(\n \"Override onError(connection, error) to handle websocket connection errors\"\n );\n } else {\n theError = connectionOrError;\n // this is a server error\n console.error(\"Error on server:\", theError);\n console.error(\"Override onError(error) to handle server errors\");\n }\n throw theError;\n }\n\n /**\n * Render content (not implemented in base class)\n */\n render() {\n throw new Error(\"Not implemented\");\n }\n\n /**\n * Retry an async operation with exponential backoff and jitter.\n * Retries on all errors by default. Use `shouldRetry` to bail early on non-retryable errors.\n *\n * @param fn The async function to retry. Receives the current attempt number (1-indexed).\n * @param options Retry configuration.\n * @param options.maxAttempts Maximum number of attempts (including the first). Falls back to static options, then 3.\n * @param options.baseDelayMs Base delay in ms for exponential backoff. Falls back to static options, then 100.\n * @param options.maxDelayMs Maximum delay cap in ms. Falls back to static options, then 3000.\n * @param options.shouldRetry Predicate called with the error and next attempt number. Return false to stop retrying immediately. Default: retry all errors.\n * @returns The result of fn on success.\n * @throws The last error if all attempts fail or shouldRetry returns false.\n */\n async retry<T>(\n fn: (attempt: number) => Promise<T>,\n options?: RetryOptions & {\n /** Return false to stop retrying a specific error. Receives the error and the next attempt number. Default: retry all errors. */\n shouldRetry?: (err: unknown, nextAttempt: number) => boolean;\n }\n ): Promise<T> {\n const defaults = this._resolvedOptions.retry;\n if (options) {\n validateRetryOptions(options, defaults);\n }\n return tryN(options?.maxAttempts ?? defaults.maxAttempts, fn, {\n baseDelayMs: options?.baseDelayMs ?? defaults.baseDelayMs,\n maxDelayMs: options?.maxDelayMs ?? defaults.maxDelayMs,\n shouldRetry: options?.shouldRetry\n });\n }\n\n /**\n * Queue a task to be executed in the future\n * @param callback Name of the method to call\n * @param payload Payload to pass to the callback\n * @param options Options for the queued task\n * @param options.retry Retry options for the callback execution\n * @returns The ID of the queued task\n */\n async queue<T = unknown>(\n callback: keyof this,\n payload: T,\n options?: { retry?: RetryOptions }\n ): Promise<string> {\n const id = nanoid(9);\n if (typeof callback !== \"string\") {\n throw new Error(\"Callback must be a string\");\n }\n\n if (typeof this[callback] !== \"function\") {\n throw new Error(`this.${callback} is not a function`);\n }\n\n if (options?.retry) {\n validateRetryOptions(options.retry, this._resolvedOptions.retry);\n }\n\n const retryJson = options?.retry ? JSON.stringify(options.retry) : null;\n\n this.sql`\n INSERT OR REPLACE INTO cf_agents_queues (id, payload, callback, retry_options)\n VALUES (${id}, ${JSON.stringify(payload)}, ${callback}, ${retryJson})\n `;\n\n this._emit(\"queue:create\", { callback: callback as string, id });\n\n void this._flushQueue().catch((e) => {\n console.error(\"Error flushing queue:\", e);\n });\n\n return id;\n }\n\n private _flushingQueue = false;\n\n private async _flushQueue() {\n if (this._flushingQueue) {\n return;\n }\n this._flushingQueue = true;\n try {\n while (true) {\n const result = this.sql<QueueItem<string>>`\n SELECT * FROM cf_agents_queues\n ORDER BY created_at ASC\n `;\n\n if (!result || result.length === 0) {\n break;\n }\n\n for (const row of result || []) {\n const callback = this[row.callback as keyof Agent<Env>];\n if (!callback) {\n console.error(`callback ${row.callback} not found`);\n await this.dequeue(row.id);\n continue;\n }\n const { connection, request, email } = agentContext.getStore() || {};\n await agentContext.run(\n {\n agent: this,\n connection,\n request,\n email\n },\n async () => {\n const retryOpts = parseRetryOptions(\n row as unknown as Record<string, unknown>\n );\n const { maxAttempts, baseDelayMs, maxDelayMs } =\n resolveRetryConfig(retryOpts, this._resolvedOptions.retry);\n const parsedPayload = JSON.parse(row.payload as string);\n try {\n await tryN(\n maxAttempts,\n async (attempt) => {\n if (attempt > 1) {\n this._emit(\"queue:retry\", {\n callback: row.callback,\n id: row.id,\n attempt,\n maxAttempts\n });\n }\n await (\n callback as (\n payload: unknown,\n queueItem: QueueItem<string>\n ) => Promise<void>\n ).bind(this)(parsedPayload, row);\n },\n { baseDelayMs, maxDelayMs }\n );\n } catch (e) {\n console.error(\n `queue callback \"${row.callback}\" failed after ${maxAttempts} attempts`,\n e\n );\n this._emit(\"queue:error\", {\n callback: row.callback,\n id: row.id,\n error: e instanceof Error ? e.message : String(e),\n attempts: maxAttempts\n });\n try {\n await this.onError(e);\n } catch {\n // swallow onError errors\n }\n } finally {\n this.dequeue(row.id);\n }\n }\n );\n }\n }\n } finally {\n this._flushingQueue = false;\n }\n }\n\n /**\n * Dequeue a task by ID\n * @param id ID of the task to dequeue\n */\n dequeue(id: string) {\n this.sql`DELETE FROM cf_agents_queues WHERE id = ${id}`;\n }\n\n /**\n * Dequeue all tasks\n */\n dequeueAll() {\n this.sql`DELETE FROM cf_agents_queues`;\n }\n\n /**\n * Dequeue all tasks by callback\n * @param callback Name of the callback to dequeue\n */\n dequeueAllByCallback(callback: string) {\n this.sql`DELETE FROM cf_agents_queues WHERE callback = ${callback}`;\n }\n\n /**\n * Get a queued task by ID\n * @param id ID of the task to get\n * @returns The task or undefined if not found\n */\n getQueue(id: string): QueueItem<string> | undefined {\n const result = this.sql<QueueItem<string>>`\n SELECT * FROM cf_agents_queues WHERE id = ${id}\n `;\n if (!result || result.length === 0) return undefined;\n const row = result[0];\n return {\n ...row,\n payload: JSON.parse(row.payload as unknown as string),\n retry: parseRetryOptions(row as unknown as Record<string, unknown>)\n };\n }\n\n /**\n * Get all queues by key and value\n * @param key Key to filter by\n * @param value Value to filter by\n * @returns Array of matching QueueItem objects\n */\n getQueues(key: string, value: string): QueueItem<string>[] {\n const result = this.sql<QueueItem<string>>`\n SELECT * FROM cf_agents_queues\n `;\n return result\n .filter(\n (row) => JSON.parse(row.payload as unknown as string)[key] === value\n )\n .map((row) => ({\n ...row,\n payload: JSON.parse(row.payload as unknown as string),\n retry: parseRetryOptions(row as unknown as Record<string, unknown>)\n }));\n }\n\n private _scheduleOwnerPathKey(\n path: ReadonlyArray<AgentPathStep> | null\n ): string | null {\n if (!path) return null;\n return path\n .map(\n (step) =>\n `${encodeURIComponent(step.className)}:${encodeURIComponent(step.name)}`\n )\n .join(\"/\");\n }\n\n private _facetRunRowsForPrefix(\n ownerPath: ReadonlyArray<AgentPathStep>\n ): FacetRunStorageRow[] {\n const rows = this.sql<FacetRunStorageRow>`\n SELECT owner_path, owner_path_key, run_id, created_at\n FROM cf_agents_facet_runs\n `;\n return rows.filter((row) => {\n try {\n const rowOwnerPath = JSON.parse(row.owner_path) as AgentPathStep[];\n return this._isSameAgentPathPrefix(ownerPath, rowOwnerPath);\n } catch {\n return false;\n }\n });\n }\n\n private _deleteFacetRunRowsForPrefix(\n ownerPath: ReadonlyArray<AgentPathStep>\n ): void {\n for (const row of this._facetRunRowsForPrefix(ownerPath)) {\n this.sql`\n DELETE FROM cf_agents_facet_runs\n WHERE owner_path_key = ${row.owner_path_key}\n AND run_id = ${row.run_id}\n `;\n }\n }\n\n private async _rootAlarmOwner(): Promise<RootFacetRpcSurface> {\n const root = this._parentPath[0];\n if (!root) {\n throw new Error(\"Facet scheduler delegation requires a root parent.\");\n }\n\n const ctx = this.ctx as unknown as Partial<FacetCapableCtx>;\n const binding = ctx.exports?.[root.className] as\n | DurableObjectNamespace\n | undefined;\n if (!binding) {\n throw new Error(\n `Unable to resolve root scheduler \"${root.className}\" for sub-agent schedule delegation.`\n );\n }\n\n return (await getServerByName<Cloudflare.Env, Agent>(\n binding as DurableObjectNamespace<Agent>,\n root.name\n )) as unknown as RootFacetRpcSurface;\n }\n\n private _validateScheduleCallback(\n when: Date | string | number,\n callback: keyof this,\n options?: { retry?: RetryOptions; idempotent?: boolean }\n ): asserts callback is Extract<keyof this, string> {\n if (typeof callback !== \"string\") {\n throw new Error(\"Callback must be a string\");\n }\n\n if (typeof this[callback] !== \"function\") {\n throw new Error(`this.${callback} is not a function`);\n }\n\n if (options?.retry) {\n validateRetryOptions(options.retry, this._resolvedOptions.retry);\n }\n\n if (\n this._insideOnStart &&\n options?.idempotent === undefined &&\n typeof when !== \"string\" &&\n !this._warnedScheduleInOnStart.has(callback)\n ) {\n this._warnedScheduleInOnStart.add(callback);\n console.warn(\n `schedule(\"${callback}\") called inside onStart() without { idempotent: true }. ` +\n `This creates a new row on every Durable Object restart, which can cause ` +\n `duplicate executions. Pass { idempotent: true } to deduplicate, or use ` +\n `scheduleEvery() for recurring tasks.`\n );\n }\n }\n\n /**\n * Insert (or, for idempotent calls, return the existing row for) a\n * schedule owned by either this top-level agent (`ownerPath === null`)\n * or a descendant facet. Returns `{ schedule, created }` — `created`\n * is `false` when an idempotent insert deduplicates onto an existing\n * row, so callers can suppress the `schedule:create` event in that\n * case to match historic semantics.\n * @internal\n */\n private async _insertScheduleForOwner<T = string>(\n ownerPath: ReadonlyArray<AgentPathStep> | null,\n when: Date | string | number,\n callback: string,\n payload?: T,\n options?: { retry?: RetryOptions; idempotent?: boolean }\n ): Promise<{ schedule: Schedule<T>; created: boolean }> {\n const ownerPathJson = ownerPath ? JSON.stringify(ownerPath) : null;\n const ownerPathKey = this._scheduleOwnerPathKey(ownerPath);\n const retryJson = options?.retry ? JSON.stringify(options.retry) : null;\n const payloadJson = JSON.stringify(payload);\n\n if (when instanceof Date) {\n const timestamp = Math.floor(when.getTime() / 1000);\n\n if (options?.idempotent) {\n const existing = this.sql<ScheduleStorageRow>`\n SELECT * FROM cf_agents_schedules\n WHERE type = 'scheduled'\n AND callback = ${callback}\n AND payload IS ${payloadJson}\n AND owner_path_key IS ${ownerPathKey}\n LIMIT 1\n `;\n\n if (existing.length > 0) {\n const row = existing[0];\n await this._scheduleNextAlarm();\n return {\n schedule: {\n callback: row.callback,\n id: row.id,\n payload: JSON.parse(row.payload) as T,\n retry: parseRetryOptions(\n row as unknown as Record<string, unknown>\n ),\n time: row.time,\n type: \"scheduled\"\n },\n created: false\n };\n }\n }\n\n const id = nanoid(9);\n this.sql`\n INSERT OR REPLACE INTO cf_agents_schedules\n (id, callback, payload, type, time, retry_options, owner_path, owner_path_key)\n VALUES\n (${id}, ${callback}, ${payloadJson}, 'scheduled', ${timestamp}, ${retryJson}, ${ownerPathJson}, ${ownerPathKey})\n `;\n\n await this._scheduleNextAlarm();\n return {\n schedule: {\n callback,\n id,\n payload: payload as T,\n retry: options?.retry,\n time: timestamp,\n type: \"scheduled\"\n },\n created: true\n };\n }\n\n if (typeof when === \"number\") {\n const timestamp = Math.floor((Date.now() + when * 1000) / 1000);\n\n if (options?.idempotent) {\n const existing = this.sql<ScheduleStorageRow>`\n SELECT * FROM cf_agents_schedules\n WHERE type = 'delayed'\n AND callback = ${callback}\n AND payload IS ${payloadJson}\n AND owner_path_key IS ${ownerPathKey}\n LIMIT 1\n `;\n\n if (existing.length > 0) {\n const row = existing[0];\n await this._scheduleNextAlarm();\n return {\n schedule: {\n callback: row.callback,\n delayInSeconds: row.delayInSeconds ?? 0,\n id: row.id,\n payload: JSON.parse(row.payload) as T,\n retry: parseRetryOptions(\n row as unknown as Record<string, unknown>\n ),\n time: row.time,\n type: \"delayed\"\n },\n created: false\n };\n }\n }\n\n const id = nanoid(9);\n this.sql`\n INSERT OR REPLACE INTO cf_agents_schedules\n (id, callback, payload, type, delayInSeconds, time, retry_options, owner_path, owner_path_key)\n VALUES\n (${id}, ${callback}, ${payloadJson}, 'delayed', ${when}, ${timestamp}, ${retryJson}, ${ownerPathJson}, ${ownerPathKey})\n `;\n\n await this._scheduleNextAlarm();\n return {\n schedule: {\n callback,\n delayInSeconds: when,\n id,\n payload: payload as T,\n retry: options?.retry,\n time: timestamp,\n type: \"delayed\"\n },\n created: true\n };\n }\n\n if (typeof when === \"string\") {\n const timestamp = Math.floor(getNextCronTime(when).getTime() / 1000);\n const idempotent = options?.idempotent !== false;\n\n if (idempotent) {\n const existing = this.sql<ScheduleStorageRow>`\n SELECT * FROM cf_agents_schedules\n WHERE type = 'cron'\n AND callback = ${callback}\n AND cron = ${when}\n AND payload IS ${payloadJson}\n AND owner_path_key IS ${ownerPathKey}\n LIMIT 1\n `;\n\n if (existing.length > 0) {\n const row = existing[0];\n await this._scheduleNextAlarm();\n return {\n schedule: {\n callback: row.callback,\n cron: row.cron ?? when,\n id: row.id,\n payload: JSON.parse(row.payload) as T,\n retry: parseRetryOptions(\n row as unknown as Record<string, unknown>\n ),\n time: row.time,\n type: \"cron\"\n },\n created: false\n };\n }\n }\n\n const id = nanoid(9);\n this.sql`\n INSERT OR REPLACE INTO cf_agents_schedules\n (id, callback, payload, type, cron, time, retry_options, owner_path, owner_path_key)\n VALUES\n (${id}, ${callback}, ${payloadJson}, 'cron', ${when}, ${timestamp}, ${retryJson}, ${ownerPathJson}, ${ownerPathKey})\n `;\n\n await this._scheduleNextAlarm();\n return {\n schedule: {\n callback,\n cron: when,\n id,\n payload: payload as T,\n retry: options?.retry,\n time: timestamp,\n type: \"cron\"\n },\n created: true\n };\n }\n\n throw new Error(\n `Invalid schedule type: ${JSON.stringify(when)}(${typeof when}) trying to schedule ${callback}`\n );\n }\n\n /**\n * Insert a schedule row owned by a descendant facet. Called via RPC\n * from the facet's `schedule()`. Returns `{ schedule, created }`\n * so the originating facet can suppress `schedule:create` on\n * idempotent dedup. This method does not emit observability\n * events itself.\n * @internal\n */\n async _cf_scheduleForFacet<T = string>(\n ownerPath: ReadonlyArray<AgentPathStep>,\n when: Date | string | number,\n callback: string,\n payload?: T,\n options?: { retry?: RetryOptions; idempotent?: boolean }\n ): Promise<{ schedule: Schedule<T>; created: boolean }> {\n return this._insertScheduleForOwner(\n ownerPath,\n when,\n callback,\n payload,\n options\n );\n }\n\n /**\n * Insert (or, for idempotent calls, return the existing row for) an\n * interval schedule. Mirrors {@link _insertScheduleForOwner} —\n * returns `{ schedule, created }` so callers can suppress\n * `schedule:create` on dedup.\n * @internal\n */\n private async _insertIntervalScheduleForOwner<T = string>(\n ownerPath: ReadonlyArray<AgentPathStep> | null,\n intervalSeconds: number,\n callback: string,\n payload?: T,\n options?: { retry?: RetryOptions; _idempotent?: boolean }\n ): Promise<{ schedule: Schedule<T>; created: boolean }> {\n const ownerPathJson = ownerPath ? JSON.stringify(ownerPath) : null;\n const ownerPathKey = this._scheduleOwnerPathKey(ownerPath);\n const idempotent = options?._idempotent !== false;\n const payloadJson = JSON.stringify(payload);\n\n if (idempotent) {\n const existing = this.sql<ScheduleStorageRow>`\n SELECT * FROM cf_agents_schedules\n WHERE type = 'interval'\n AND callback = ${callback}\n AND intervalSeconds = ${intervalSeconds}\n AND payload IS ${payloadJson}\n AND owner_path_key IS ${ownerPathKey}\n LIMIT 1\n `;\n\n if (existing.length > 0) {\n const row = existing[0];\n await this._scheduleNextAlarm();\n return {\n schedule: {\n callback: row.callback,\n id: row.id,\n intervalSeconds: row.intervalSeconds ?? intervalSeconds,\n payload: JSON.parse(row.payload) as T,\n retry: parseRetryOptions(row as unknown as Record<string, unknown>),\n time: row.time,\n type: \"interval\"\n },\n created: false\n };\n }\n }\n\n const id = nanoid(9);\n const timestamp = Math.floor((Date.now() + intervalSeconds * 1000) / 1000);\n const retryJson = options?.retry ? JSON.stringify(options.retry) : null;\n\n this.sql`\n INSERT OR REPLACE INTO cf_agents_schedules\n (id, callback, payload, type, intervalSeconds, time, running, retry_options, owner_path, owner_path_key)\n VALUES\n (${id}, ${callback}, ${payloadJson}, 'interval', ${intervalSeconds}, ${timestamp}, 0, ${retryJson}, ${ownerPathJson}, ${ownerPathKey})\n `;\n\n await this._scheduleNextAlarm();\n return {\n schedule: {\n callback,\n id,\n intervalSeconds,\n payload: payload as T,\n retry: options?.retry,\n time: timestamp,\n type: \"interval\"\n },\n created: true\n };\n }\n\n /**\n * Insert an interval schedule row owned by a descendant facet.\n * Called via RPC from the facet's `scheduleEvery()`. Returns\n * `{ schedule, created }` so the originating facet can suppress\n * `schedule:create` on idempotent dedup. This method does not\n * emit observability events itself.\n * @internal\n */\n async _cf_scheduleEveryForFacet<T = string>(\n ownerPath: ReadonlyArray<AgentPathStep>,\n intervalSeconds: number,\n callback: string,\n payload?: T,\n options?: { retry?: RetryOptions; _idempotent?: boolean }\n ): Promise<{ schedule: Schedule<T>; created: boolean }> {\n return this._insertIntervalScheduleForOwner(\n ownerPath,\n intervalSeconds,\n callback,\n payload,\n options\n );\n }\n\n /**\n * Cancel a schedule row owned by a descendant facet, scoped by\n * `owner_path_key` so siblings can't reach each other's rows.\n * Returns the canceled row's callback name so the originating\n * facet can emit `schedule:cancel`. This method does not emit\n * observability events itself.\n * @internal\n */\n async _cf_cancelScheduleForFacet(\n ownerPath: ReadonlyArray<AgentPathStep>,\n id: string\n ): Promise<{ ok: boolean; callback?: string }> {\n const ownerPathKey = this._scheduleOwnerPathKey(ownerPath);\n const result = this.sql<ScheduleStorageRow>`\n SELECT * FROM cf_agents_schedules\n WHERE id = ${id} AND owner_path_key IS ${ownerPathKey}\n `;\n if (result.length === 0) return { ok: false };\n\n const callback = result[0].callback;\n this.sql`\n DELETE FROM cf_agents_schedules\n WHERE id = ${id} AND owner_path_key IS ${ownerPathKey}\n `;\n await this._scheduleNextAlarm();\n return { ok: true, callback };\n }\n\n /**\n * Clean root-owned bookkeeping for a sub-tree of facets. This\n * bulk-cancels schedules whose `owner_path` starts with the given\n * prefix and deletes root-side facet fiber recovery leases for the\n * same sub-tree. Used by `deleteSubAgent` and recursive facet\n * destroy. Emits `schedule:cancel` on this agent (the alarm-owning\n * root) for each schedule row removed — the facets being torn down\n * may not be alive to receive the events themselves.\n * @internal\n */\n async _cf_cleanupFacetPrefix(\n ownerPath: ReadonlyArray<AgentPathStep>\n ): Promise<void> {\n const rows = this.sql<ScheduleStorageRow>`\n SELECT * FROM cf_agents_schedules\n WHERE owner_path IS NOT NULL\n `;\n const rowsToDelete = rows.filter((row) => {\n if (!row.owner_path) return false;\n try {\n const rowOwnerPath = JSON.parse(row.owner_path) as AgentPathStep[];\n return this._isSameAgentPathPrefix(ownerPath, rowOwnerPath);\n } catch {\n return false;\n }\n });\n\n for (const row of rowsToDelete) {\n this._emit(\"schedule:cancel\", {\n callback: row.callback,\n id: row.id\n });\n this.sql`DELETE FROM cf_agents_schedules WHERE id = ${row.id}`;\n }\n\n this._deleteFacetRunRowsForPrefix(ownerPath);\n await this._scheduleNextAlarm();\n }\n\n private _scheduleRowToSchedule<T>(row: ScheduleStorageRow): Schedule<T> {\n const base = {\n callback: row.callback,\n id: row.id,\n payload: JSON.parse(row.payload) as T,\n retry: parseRetryOptions(row as unknown as Record<string, unknown>)\n };\n\n switch (row.type) {\n case \"scheduled\":\n return {\n ...base,\n time: row.time,\n type: \"scheduled\"\n };\n case \"delayed\":\n return {\n ...base,\n delayInSeconds: row.delayInSeconds ?? 0,\n time: row.time,\n type: \"delayed\"\n };\n case \"cron\":\n return {\n ...base,\n cron: row.cron ?? \"\",\n time: row.time,\n type: \"cron\"\n };\n case \"interval\":\n return {\n ...base,\n intervalSeconds: row.intervalSeconds ?? 0,\n time: row.time,\n type: \"interval\"\n };\n }\n }\n\n private _getScheduleForOwner<T = string>(\n ownerPath: ReadonlyArray<AgentPathStep> | null,\n id: string\n ): Schedule<T> | undefined {\n const ownerPathKey = this._scheduleOwnerPathKey(ownerPath);\n const result = this.sql<ScheduleStorageRow>`\n SELECT * FROM cf_agents_schedules\n WHERE id = ${id} AND owner_path_key IS ${ownerPathKey}\n `;\n if (!result || result.length === 0) {\n return undefined;\n }\n return this._scheduleRowToSchedule<T>(result[0]);\n }\n\n private _listSchedulesForOwner<T = string>(\n ownerPath: ReadonlyArray<AgentPathStep> | null,\n criteria: ScheduleCriteria = {}\n ): Schedule<T>[] {\n const ownerPathKey = this._scheduleOwnerPathKey(ownerPath);\n let query = \"SELECT * FROM cf_agents_schedules WHERE owner_path_key IS ?\";\n const params: Array<string | number | null> = [ownerPathKey];\n\n if (criteria.id) {\n query += \" AND id = ?\";\n params.push(criteria.id);\n }\n\n if (criteria.type) {\n query += \" AND type = ?\";\n params.push(criteria.type);\n }\n\n if (criteria.timeRange) {\n query += \" AND time >= ? AND time <= ?\";\n const start = criteria.timeRange.start || new Date(0);\n const end = criteria.timeRange.end || new Date(999999999999999);\n params.push(\n Math.floor(start.getTime() / 1000),\n Math.floor(end.getTime() / 1000)\n );\n }\n\n return this.ctx.storage.sql\n .exec(query, ...params)\n .toArray()\n .map((row) =>\n this._scheduleRowToSchedule<T>(row as unknown as ScheduleStorageRow)\n );\n }\n\n /**\n * Read a single schedule row owned by a descendant facet.\n * @internal\n */\n async _cf_getScheduleForFacet(\n ownerPath: ReadonlyArray<AgentPathStep>,\n id: string\n ): Promise<Schedule<unknown> | undefined> {\n return this._getScheduleForOwner(ownerPath, id);\n }\n\n /**\n * List schedule rows owned by a descendant facet, scoped by\n * `owner_path_key` so siblings remain isolated from each other.\n * @internal\n */\n async _cf_listSchedulesForFacet(\n ownerPath: ReadonlyArray<AgentPathStep>,\n criteria: ScheduleCriteria = {}\n ): Promise<Schedule<unknown>[]> {\n return this._listSchedulesForOwner(ownerPath, criteria);\n }\n\n /**\n * Acquire a root-owned keepAlive ref on behalf of a descendant facet.\n * Facets share the root isolate but cannot set their own physical\n * alarm, so this lets facet work use the root alarm heartbeat.\n * @internal\n */\n async _cf_acquireFacetKeepAlive(\n ownerPath: ReadonlyArray<AgentPathStep>\n ): Promise<string> {\n const ownerPathKey = this._scheduleOwnerPathKey(ownerPath);\n const token = `${ownerPathKey ?? \"unknown\"}:${nanoid(9)}`;\n this._facetKeepAliveTokens.add(token);\n this._keepAliveRefs++;\n if (this._keepAliveRefs === 1) {\n await this._scheduleNextAlarm();\n }\n return token;\n }\n\n /**\n * Release a root-owned keepAlive ref previously acquired for a facet.\n * Idempotent so disposer calls can safely race or run twice.\n * @internal\n */\n async _cf_releaseFacetKeepAlive(token: string): Promise<void> {\n if (!this._facetKeepAliveTokens.delete(token)) return;\n this._keepAliveRefs = Math.max(0, this._keepAliveRefs - 1);\n await this._scheduleNextAlarm();\n }\n\n /**\n * Register a facet's durable run row in the root-side index so root\n * alarm housekeeping can dispatch recovery checks into idle facets.\n * The facet remains authoritative for snapshots and recovery hooks.\n * @internal\n */\n async _cf_registerFacetRun(\n ownerPath: ReadonlyArray<AgentPathStep>,\n runId: string\n ): Promise<void> {\n const ownerPathJson = JSON.stringify(ownerPath);\n const ownerPathKey = this._scheduleOwnerPathKey(ownerPath);\n if (!ownerPathKey) {\n throw new Error(\"_cf_registerFacetRun requires a non-empty owner path.\");\n }\n this.sql`\n INSERT OR REPLACE INTO cf_agents_facet_runs\n (owner_path, owner_path_key, run_id, created_at)\n VALUES\n (${ownerPathJson}, ${ownerPathKey}, ${runId}, ${Date.now()})\n `;\n await this._scheduleNextAlarm();\n }\n\n /**\n * Remove a completed facet fiber from the root-side index.\n * @internal\n */\n async _cf_unregisterFacetRun(\n ownerPath: ReadonlyArray<AgentPathStep>,\n runId: string\n ): Promise<void> {\n const ownerPathKey = this._scheduleOwnerPathKey(ownerPath);\n this.sql`\n DELETE FROM cf_agents_facet_runs\n WHERE owner_path_key IS ${ownerPathKey}\n AND run_id = ${runId}\n `;\n await this._scheduleNextAlarm();\n }\n\n /**\n * Schedule a task to be executed in the future\n *\n * Cron schedules are **idempotent by default** — calling `schedule(\"0 * * * *\", \"tick\")`\n * multiple times with the same callback, cron expression, and payload returns\n * the existing schedule instead of creating a duplicate. Set `idempotent: false`\n * to override this.\n *\n * For delayed and scheduled (Date) types, set `idempotent: true` to opt in\n * to the same dedup behavior (matched on callback + payload). This is useful\n * when calling `schedule()` in `onStart()` to avoid accumulating duplicate\n * rows across Durable Object restarts.\n *\n * @template T Type of the payload data\n * @param when When to execute the task (Date, seconds delay, or cron expression)\n * @param callback Name of the method to call\n * @param payload Data to pass to the callback\n * @param options Options for the scheduled task\n * @param options.retry Retry options for the callback execution\n * @param options.idempotent Dedup by callback+payload. Defaults to `true` for cron, `false` otherwise.\n * @returns Schedule object representing the scheduled task\n */\n async schedule<T = string>(\n when: Date | string | number,\n callback: keyof this,\n payload?: T,\n options?: { retry?: RetryOptions; idempotent?: boolean }\n ): Promise<Schedule<T>> {\n this._validateScheduleCallback(when, callback, options);\n\n const result = this._isFacet\n ? await (\n await this._rootAlarmOwner()\n )._cf_scheduleForFacet<T>(\n this.selfPath,\n when,\n callback,\n payload,\n options\n )\n : await this._insertScheduleForOwner(\n null,\n when,\n callback,\n payload,\n options\n );\n\n if (result.created) {\n this._emit(\"schedule:create\", {\n callback: result.schedule.callback,\n id: result.schedule.id\n });\n }\n return result.schedule;\n }\n\n /**\n * Schedule a task to run repeatedly at a fixed interval.\n *\n * This method is **idempotent** — calling it multiple times with the same\n * `callback`, `intervalSeconds`, and `payload` returns the existing schedule\n * instead of creating a duplicate. A different interval or payload is\n * treated as a distinct schedule and creates a new row.\n *\n * This makes it safe to call in `onStart()`, which runs on every Durable\n * Object wake:\n *\n * ```ts\n * async onStart() {\n * // Only one schedule is created, no matter how many times the DO wakes\n * await this.scheduleEvery(30, \"tick\");\n * }\n * ```\n *\n * @template T Type of the payload data\n * @param intervalSeconds Number of seconds between executions\n * @param callback Name of the method to call\n * @param payload Data to pass to the callback\n * @param options Options for the scheduled task\n * @param options.retry Retry options for the callback execution\n * @returns Schedule object representing the scheduled task\n */\n async scheduleEvery<T = string>(\n intervalSeconds: number,\n callback: keyof this,\n payload?: T,\n options?: { retry?: RetryOptions; _idempotent?: boolean }\n ): Promise<Schedule<T>> {\n // DO alarms have a max schedule time of 30 days\n const MAX_INTERVAL_SECONDS = 30 * 24 * 60 * 60; // 30 days in seconds\n\n if (typeof intervalSeconds !== \"number\" || intervalSeconds <= 0) {\n throw new Error(\"intervalSeconds must be a positive number\");\n }\n\n if (intervalSeconds > MAX_INTERVAL_SECONDS) {\n throw new Error(\n `intervalSeconds cannot exceed ${MAX_INTERVAL_SECONDS} seconds (30 days)`\n );\n }\n\n if (typeof callback !== \"string\") {\n throw new Error(\"Callback must be a string\");\n }\n\n if (typeof this[callback] !== \"function\") {\n throw new Error(`this.${callback} is not a function`);\n }\n\n if (options?.retry) {\n validateRetryOptions(options.retry, this._resolvedOptions.retry);\n }\n\n const result = this._isFacet\n ? await (\n await this._rootAlarmOwner()\n )._cf_scheduleEveryForFacet<T>(\n this.selfPath,\n intervalSeconds,\n callback,\n payload,\n options\n )\n : await this._insertIntervalScheduleForOwner(\n null,\n intervalSeconds,\n callback,\n payload,\n options\n );\n\n if (result.created) {\n this._emit(\"schedule:create\", {\n callback: result.schedule.callback,\n id: result.schedule.id\n });\n }\n return result.schedule;\n }\n\n /**\n * Get a scheduled task by ID\n * @template T Type of the payload data\n * @param id ID of the scheduled task\n * @returns The Schedule object or undefined if not found\n * @deprecated Use {@link getScheduleById}. This synchronous API cannot cross\n * Durable Object boundaries and throws inside sub-agents.\n */\n getSchedule<T = string>(id: string): Schedule<T> | undefined {\n if (this._isFacet) {\n throw new Error(\n \"getSchedule() is synchronous and cannot read parent-owned sub-agent schedules. \" +\n \"Use await this.getScheduleById(id) instead.\"\n );\n }\n return this._getScheduleForOwner(null, id);\n }\n\n /**\n * Get a scheduled task by ID.\n *\n * Unlike the deprecated synchronous {@link getSchedule}, this works inside\n * sub-agents by delegating to the top-level parent that owns the alarm.\n *\n * @template T Type of the payload data\n * @param id ID of the scheduled task\n * @returns The Schedule object or undefined if not found\n */\n async getScheduleById(id: string): Promise<Schedule<unknown> | undefined> {\n if (this._isFacet) {\n const root = await this._rootAlarmOwner();\n return root._cf_getScheduleForFacet(this.selfPath, id);\n }\n return this._getScheduleForOwner(null, id);\n }\n\n /**\n * Get scheduled tasks matching the given criteria\n * @template T Type of the payload data\n * @param criteria Criteria to filter schedules\n * @returns Array of matching Schedule objects\n * @deprecated Use {@link listSchedules}. This synchronous API cannot cross\n * Durable Object boundaries and throws inside sub-agents.\n */\n getSchedules<T = string>(criteria: ScheduleCriteria = {}): Schedule<T>[] {\n if (this._isFacet) {\n throw new Error(\n \"getSchedules() is synchronous and cannot read parent-owned sub-agent schedules. \" +\n \"Use await this.listSchedules(criteria) instead.\"\n );\n }\n\n return this._listSchedulesForOwner(null, criteria);\n }\n\n /**\n * List scheduled tasks matching the given criteria.\n *\n * Unlike the deprecated synchronous {@link getSchedules}, this works inside\n * sub-agents by delegating to the top-level parent that owns the alarm.\n *\n * @template T Type of the payload data\n * @param criteria Criteria to filter schedules\n * @returns Array of matching Schedule objects\n */\n async listSchedules(\n criteria: ScheduleCriteria = {}\n ): Promise<Schedule<unknown>[]> {\n if (this._isFacet) {\n const root = await this._rootAlarmOwner();\n return root._cf_listSchedulesForFacet(this.selfPath, criteria);\n }\n return this._listSchedulesForOwner(null, criteria);\n }\n\n /**\n * Cancel a scheduled task.\n *\n * Schedules are isolated by owner: a top-level agent's\n * `cancelSchedule(id)` only matches its own schedules, and a\n * sub-agent's `cancelSchedule(id)` only matches schedules it\n * created. To clear every schedule under a sub-agent (and its\n * descendants), call `parent.deleteSubAgent(Cls, name)` from the\n * parent — that bulk-cleans root-owned bookkeeping via\n * {@link _cf_cleanupFacetPrefix}.\n *\n * @param id ID of the task to cancel\n * @returns true if the task was cancelled, false if the task was not found\n */\n async cancelSchedule(id: string): Promise<boolean> {\n if (this._isFacet) {\n const root = await this._rootAlarmOwner();\n const result = await root._cf_cancelScheduleForFacet(this.selfPath, id);\n if (result.ok && result.callback) {\n this._emit(\"schedule:cancel\", { callback: result.callback, id });\n }\n return result.ok;\n }\n const schedule = this._getScheduleForOwner(null, id);\n if (!schedule) {\n return false;\n }\n\n this._emit(\"schedule:cancel\", {\n callback: schedule.callback,\n id: schedule.id\n });\n\n this.sql`DELETE FROM cf_agents_schedules WHERE id = ${id}`;\n\n await this._scheduleNextAlarm();\n return true;\n }\n\n /**\n * Keep the Durable Object alive via alarm heartbeats.\n * Returns a disposer function that stops the heartbeat when called.\n *\n * Use this when you have long-running work and need to prevent the\n * DO from going idle (eviction after ~70-140s of inactivity).\n * The heartbeat fires every `keepAliveIntervalMs` (default 30s) via the\n * alarm system, without creating schedule rows or emitting observability\n * events. Configure via `static options = { keepAliveIntervalMs: 5000 }`.\n *\n * In facets, delegates the physical heartbeat to the root parent\n * because facets do not have independent alarm slots.\n *\n * @example\n * ```ts\n * const dispose = await this.keepAlive();\n * try {\n * // ... long-running work ...\n * } finally {\n * dispose();\n * }\n * ```\n */\n async keepAlive(): Promise<() => void> {\n if (this._isFacet) {\n const root = await this._rootAlarmOwner();\n const token = await root._cf_acquireFacetKeepAlive(this.selfPath);\n let disposed = false;\n return () => {\n if (disposed) return;\n disposed = true;\n const release = root._cf_releaseFacetKeepAlive(token).catch((e) => {\n console.error(\"[Agent] Failed to release facet keepAlive:\", e);\n });\n this.ctx.waitUntil(release);\n };\n }\n\n this._keepAliveRefs++;\n\n if (this._keepAliveRefs === 1) {\n await this._scheduleNextAlarm();\n }\n\n let disposed = false;\n return () => {\n if (disposed) return;\n disposed = true;\n this._keepAliveRefs = Math.max(0, this._keepAliveRefs - 1);\n };\n }\n\n /**\n * Run an async function while keeping the Durable Object alive.\n * The heartbeat is automatically stopped when the function completes\n * (whether it succeeds or throws).\n *\n * This is the recommended way to use keepAlive — it guarantees cleanup\n * so you cannot forget to dispose the heartbeat.\n *\n * @example\n * ```ts\n * const result = await this.keepAliveWhile(async () => {\n * const data = await longRunningComputation();\n * return data;\n * });\n * ```\n */\n async keepAliveWhile<T>(fn: () => Promise<T>): Promise<T> {\n const dispose = await this.keepAlive();\n try {\n return await fn();\n } finally {\n dispose();\n }\n }\n\n // ── Fibers: durable execution ───────────────────────────────────────\n\n /**\n * Run a function as a durable fiber. The fiber is registered in SQLite\n * before execution, checkpointable during execution via `ctx.stash()`,\n * and recoverable after eviction via `onFiberRecovered`.\n *\n * - Row created in `cf_agents_runs` at start, deleted on completion\n * - `keepAlive()` held for the duration — prevents idle eviction\n * - Inline (await result) or fire-and-forget (`void this.runFiber(...)`)\n *\n * @param name Informational name for debugging and recovery filtering\n * @param fn Async function to execute. Receives a FiberContext with stash/snapshot.\n * @returns The return value of fn\n */\n async runFiber<T>(\n name: string,\n fn: (ctx: FiberContext) => Promise<T>\n ): Promise<T> {\n const id = nanoid();\n this.sql`\n INSERT INTO cf_agents_runs (id, name, snapshot, created_at)\n VALUES (${id}, ${name}, NULL, ${Date.now()})\n `;\n this._runFiberActiveFibers.add(id);\n\n let root: RootFacetRpcSurface | undefined;\n let registeredFacetRun = false;\n let dispose: () => void = () => {};\n try {\n if (this._isFacet) {\n root = await this._rootAlarmOwner();\n await root._cf_registerFacetRun(this.selfPath, id);\n registeredFacetRun = true;\n }\n\n dispose = await this.keepAlive();\n const stash = (data: unknown) => {\n this.sql`\n UPDATE cf_agents_runs SET snapshot = ${JSON.stringify(data)}\n WHERE id = ${id}\n `;\n };\n\n return await _fiberALS.run({ id, stash }, () =>\n fn({ id, stash, snapshot: null })\n );\n } finally {\n this._runFiberActiveFibers.delete(id);\n this.sql`DELETE FROM cf_agents_runs WHERE id = ${id}`;\n dispose();\n if (root && registeredFacetRun) {\n try {\n await root._cf_unregisterFacetRun(this.selfPath, id);\n } catch (e) {\n // Leave the root-side lease behind if cleanup fails; root\n // housekeeping will re-enter the facet and prune stale rows\n // once it observes that this fiber row no longer exists.\n console.error(\"[Agent] Failed to unregister facet fiber:\", e);\n }\n }\n }\n }\n\n /**\n * Checkpoint data for the currently executing fiber.\n * Uses AsyncLocalStorage to identify the correct fiber,\n * so it works correctly even with concurrent fibers.\n *\n * Throws if called outside a `runFiber` callback.\n */\n stash(data: unknown): void {\n const ctx = _fiberALS.getStore();\n if (!ctx) {\n throw new Error(\"stash() called outside a fiber\");\n }\n ctx.stash(data);\n }\n\n /**\n * Called when an interrupted fiber is detected after restart.\n * Override to implement recovery (re-invoke work, notify clients, etc.).\n *\n * Internal framework fibers are filtered by `_handleInternalFiberRecovery`\n * before this hook runs — users only see their own fibers.\n *\n * Default: logs a warning.\n */\n async onFiberRecovered(\n // oxlint-disable-next-line @typescript-eslint/no-unused-vars -- overridable hook\n _ctx: FiberRecoveryContext\n ): Promise<void> {\n console.warn(\n `[Agent] Fiber \"${_ctx.name}\" (${_ctx.id}) was interrupted. ` +\n \"Override onFiberRecovered to handle recovery.\"\n );\n }\n\n /**\n * Override point for subclasses to handle internal (framework) fibers\n * before the user's recovery hook fires. Return `true` if handled.\n * @internal\n */\n protected async _handleInternalFiberRecovery(\n // oxlint-disable-next-line @typescript-eslint/no-unused-vars -- override point\n _ctx: FiberRecoveryContext\n ): Promise<boolean> {\n return false;\n }\n\n /** @internal Detect fibers left by a dead process (runFiber system). */\n private async _checkRunFibers(): Promise<void> {\n if (this._runFiberRecoveryInProgress) return;\n this._runFiberRecoveryInProgress = true;\n\n try {\n const rows = this.sql<{\n id: string;\n name: string;\n snapshot: string | null;\n created_at: number;\n }>`SELECT id, name, snapshot, created_at FROM cf_agents_runs`;\n\n for (const row of rows) {\n if (this._runFiberActiveFibers.has(row.id)) continue;\n\n let snapshot: unknown = null;\n if (row.snapshot) {\n try {\n snapshot = JSON.parse(row.snapshot);\n } catch {\n console.warn(\n `[Agent] Corrupted snapshot for fiber ${row.id}, treating as null`\n );\n }\n }\n\n const ctx: FiberRecoveryContext = {\n id: row.id,\n name: row.name,\n snapshot,\n createdAt: row.created_at\n };\n\n try {\n const handled = await this._handleInternalFiberRecovery(ctx);\n if (!handled) {\n await this.onFiberRecovered(ctx);\n }\n } catch (e) {\n console.error(\n `[Agent] Fiber recovery failed for \"${ctx.name}\" (${ctx.id}):`,\n e\n );\n }\n\n this.sql`DELETE FROM cf_agents_runs WHERE id = ${row.id}`;\n }\n } finally {\n this._runFiberRecoveryInProgress = false;\n }\n }\n\n /** @internal */\n async _onAlarmHousekeeping(): Promise<void> {\n await this._checkRunFibers();\n await this._checkFacetRunFibers();\n }\n\n private _isSameAgentPathPrefix(\n prefix: ReadonlyArray<AgentPathStep>,\n path: ReadonlyArray<AgentPathStep>\n ): boolean {\n if (prefix.length > path.length) return false;\n return prefix.every(\n (step, index) =>\n step.className === path[index].className &&\n step.name === path[index].name\n );\n }\n\n /**\n * Root-side scan for durable fibers owned by descendant facets.\n * `cf_agents_facet_runs` is only an index; actual snapshots and\n * recovery hooks live in each facet's own `cf_agents_runs` table.\n * @internal\n */\n private async _checkFacetRunFibers(): Promise<void> {\n // Only the root owns the physical alarm and facet-run index.\n if (this._parentPath.length > 0) return;\n\n const rows = this.sql<FacetRunStorageRow>`\n SELECT owner_path, owner_path_key, run_id, created_at\n FROM cf_agents_facet_runs\n ORDER BY created_at ASC\n `;\n const firstRowByOwner = new Map<string, FacetRunStorageRow>();\n for (const row of rows) {\n if (!firstRowByOwner.has(row.owner_path_key)) {\n firstRowByOwner.set(row.owner_path_key, row);\n }\n }\n\n for (const row of firstRowByOwner.values()) {\n let ownerPath: AgentPathStep[];\n try {\n ownerPath = JSON.parse(row.owner_path) as AgentPathStep[];\n } catch (e) {\n console.warn(\n `[Agent] Corrupted facet fiber owner path for ${row.owner_path_key}; pruning stale lease.`,\n e\n );\n this.sql`\n DELETE FROM cf_agents_facet_runs\n WHERE owner_path_key = ${row.owner_path_key}\n `;\n continue;\n }\n\n try {\n const remaining = await this._cf_checkRunFibersForFacet(ownerPath);\n if (remaining === 0) {\n this.sql`\n DELETE FROM cf_agents_facet_runs\n WHERE owner_path_key = ${row.owner_path_key}\n `;\n }\n } catch (e) {\n // Keep the lease so a transient failure (e.g. facet init error)\n // gets retried on the next root heartbeat.\n console.error(\n `[Agent] Facet fiber recovery check failed for ${row.owner_path_key}:`,\n e\n );\n }\n }\n }\n\n /**\n * Dispatch a runFiber recovery check into the facet identified by\n * `ownerPath`. Returns the number of remaining local `cf_agents_runs`\n * rows on the target facet after recovery.\n * @internal\n */\n async _cf_checkRunFibersForFacet(\n ownerPath: ReadonlyArray<AgentPathStep>\n ): Promise<number> {\n const selfPath = this.selfPath;\n if (!this._isSameAgentPathPrefix(selfPath, ownerPath)) {\n throw new Error(\n `Facet fiber owner path does not descend from ${JSON.stringify(selfPath)}.`\n );\n }\n\n if (selfPath.length === ownerPath.length) {\n await this._checkRunFibers();\n const rows = this.sql<{ count: number }>`\n SELECT COUNT(*) as count FROM cf_agents_runs\n `;\n return rows[0]?.count ?? 0;\n }\n\n const next = ownerPath[selfPath.length];\n if (!this.hasSubAgent(next.className, next.name)) {\n // The facet was deleted or its registry was cleared. The root\n // should prune the root-side lease; there is no remaining child\n // storage to recover through the public registry path.\n return 0;\n }\n\n const stub = await this._cf_resolveSubAgent(next.className, next.name);\n const handle = stub as unknown as {\n _cf_checkRunFibersForFacet(\n ownerPath: ReadonlyArray<AgentPathStep>\n ): Promise<number>;\n };\n return handle._cf_checkRunFibersForFacet(ownerPath);\n }\n\n /**\n * Dispatch a scheduled callback into the facet identified by\n * `ownerPath`. Walks one step at a time: if `ownerPath` matches\n * `selfPath`, executes the callback locally; otherwise resolves\n * the next descendant facet and recurses through its own RPC.\n *\n * Called by the root's `alarm()` (which owns the physical alarm\n * for facet-owned schedules) and by intermediate facets while\n * walking down the chain.\n * @internal\n */\n async _cf_dispatchScheduledCallback(\n ownerPath: ReadonlyArray<AgentPathStep>,\n row: ScheduleStorageRow\n ): Promise<void> {\n const selfPath = this.selfPath;\n if (!this._isSameAgentPathPrefix(selfPath, ownerPath)) {\n throw new Error(\n `Schedule owner path does not descend from ${JSON.stringify(selfPath)}.`\n );\n }\n\n if (selfPath.length === ownerPath.length) {\n await this._executeScheduleCallback(row);\n return;\n }\n\n const next = ownerPath[selfPath.length];\n if (!this.hasSubAgent(next.className, next.name)) {\n throw new Error(\n `Scheduled sub-agent ${next.className} \"${next.name}\" no longer exists.`\n );\n }\n\n const stub = await this._cf_resolveSubAgent(next.className, next.name);\n const handle = stub as unknown as {\n _cf_dispatchScheduledCallback(\n ownerPath: ReadonlyArray<AgentPathStep>,\n row: ScheduleStorageRow\n ): Promise<void>;\n };\n await handle._cf_dispatchScheduledCallback(ownerPath, row);\n }\n\n /**\n * Recursively destroy a descendant facet identified by\n * `targetPath`. Walks down from `selfPath` until reaching the\n * target's immediate parent, where it cancels the target's\n * parent-owned schedules (and any descendants), removes the\n * target from the registry, and calls `ctx.facets.delete` to\n * wipe the target's storage.\n *\n * Called by a facet's own `destroy()` (via the root) so that\n * `this.destroy()` inside a sub-agent results in the same\n * cleanup as `parent.deleteSubAgent(Cls, name)` from the parent.\n * @internal\n */\n async _cf_destroyDescendantFacet(\n targetPath: ReadonlyArray<AgentPathStep>\n ): Promise<void> {\n const selfPath = this.selfPath;\n\n if (targetPath.length === 0) {\n throw new Error(\n \"_cf_destroyDescendantFacet: target path must not be empty.\"\n );\n }\n if (selfPath.length >= targetPath.length) {\n throw new Error(\n \"_cf_destroyDescendantFacet: target must be a strict descendant.\"\n );\n }\n if (!this._isSameAgentPathPrefix(selfPath, targetPath)) {\n throw new Error(\n \"_cf_destroyDescendantFacet: target path does not descend from this agent.\"\n );\n }\n\n // The root owns every schedule row; cancel the target's prefix\n // upfront so we don't have to make an extra round trip back from\n // each intermediate hop.\n if (this._parentPath.length === 0) {\n await this._cf_cleanupFacetPrefix(targetPath);\n }\n\n if (selfPath.length === targetPath.length - 1) {\n // We are the immediate parent of the target — perform the local\n // facet teardown the same way `deleteSubAgent` does.\n const target = targetPath[targetPath.length - 1];\n const ctx = this.ctx as unknown as Partial<FacetCapableCtx>;\n if (!ctx.facets) {\n throw new Error(\n \"destroy() (delegated from facet) is not supported in this runtime — \" +\n \"`ctx.facets` is unavailable. \" +\n \"Update to the latest `compatibility_date` in your wrangler.jsonc.\"\n );\n }\n try {\n ctx.facets.delete(`${target.className}\\0${target.name}`);\n } catch {\n // no-op — facet wasn't registered (already deleted / never spawned)\n }\n this._forgetSubAgent(target.className, target.name);\n return;\n }\n\n // Recurse one step deeper.\n const next = targetPath[selfPath.length];\n if (!this.hasSubAgent(next.className, next.name)) {\n // Already gone — schedules are cleared, nothing more to do.\n return;\n }\n const stub = await this._cf_resolveSubAgent(next.className, next.name);\n const handle = stub as unknown as {\n _cf_destroyDescendantFacet(\n targetPath: ReadonlyArray<AgentPathStep>\n ): Promise<void>;\n };\n await handle._cf_destroyDescendantFacet(targetPath);\n }\n\n private async _executeScheduleCallback(\n row: ScheduleStorageRow\n ): Promise<void> {\n const callback = this[row.callback as keyof Agent<Env>];\n if (!callback) {\n console.error(`callback ${row.callback} not found`);\n return;\n }\n\n await agentContext.run(\n {\n agent: this,\n connection: undefined,\n request: undefined,\n email: undefined\n },\n async () => {\n const retryOpts = parseRetryOptions(\n row as unknown as Record<string, unknown>\n );\n const { maxAttempts, baseDelayMs, maxDelayMs } = resolveRetryConfig(\n retryOpts,\n this._resolvedOptions.retry\n );\n\n let parsedPayload: unknown;\n try {\n parsedPayload = JSON.parse(row.payload as string);\n } catch (e) {\n console.error(\n `Failed to parse payload for schedule \"${row.id}\" (callback \"${row.callback}\")`,\n e\n );\n this._emit(\"schedule:error\", {\n callback: row.callback,\n id: row.id,\n error: e instanceof Error ? e.message : String(e),\n attempts: 0\n });\n return;\n }\n\n try {\n this._emit(\"schedule:execute\", {\n callback: row.callback,\n id: row.id\n });\n\n await tryN(\n maxAttempts,\n async (attempt) => {\n if (attempt > 1) {\n this._emit(\"schedule:retry\", {\n callback: row.callback,\n id: row.id,\n attempt,\n maxAttempts\n });\n }\n await (\n callback as (\n payload: unknown,\n schedule: Schedule<unknown>\n ) => Promise<void>\n ).bind(this)(parsedPayload, row as unknown as Schedule<unknown>);\n },\n { baseDelayMs, maxDelayMs }\n );\n } catch (e) {\n console.error(\n `error executing callback \"${row.callback}\" after ${maxAttempts} attempts`,\n e\n );\n this._emit(\"schedule:error\", {\n callback: row.callback,\n id: row.id,\n error: e instanceof Error ? e.message : String(e),\n attempts: maxAttempts\n });\n try {\n await this.onError(e);\n } catch {\n // swallow onError errors\n }\n }\n }\n );\n }\n\n private async _scheduleNextAlarm() {\n const nowMs = Date.now();\n const nowSeconds = Math.floor(nowMs / 1000);\n const hungCutoffSeconds =\n nowSeconds - this._resolvedOptions.hungScheduleTimeoutSeconds;\n\n // Find the earliest schedule row that is safe to execute now, even if it\n // is already overdue. Overdue schedules can happen after a DO restart\n // because the SQLite row survives but the in-memory alarm does not.\n const readySchedules = this.sql<{\n time: number;\n }>`\n SELECT time FROM cf_agents_schedules\n WHERE type != 'interval'\n OR running = 0\n OR coalesce(execution_started_at, 0) <= ${hungCutoffSeconds}\n ORDER BY time ASC\n LIMIT 1\n `;\n\n // Running interval schedules that are not hung yet still need a future\n // alarm so the runtime can re-check them once they cross the hung timeout.\n const recoveringIntervals = this.sql<{\n execution_started_at: number | null;\n }>`\n SELECT execution_started_at FROM cf_agents_schedules\n WHERE type = 'interval'\n AND running = 1\n AND coalesce(execution_started_at, 0) > ${hungCutoffSeconds}\n ORDER BY execution_started_at ASC\n LIMIT 1\n `;\n\n let nextTimeMs: number | null = null;\n if (readySchedules.length > 0 && \"time\" in readySchedules[0]) {\n nextTimeMs = Math.max(\n (readySchedules[0].time as number) * 1000,\n nowMs + 1\n );\n }\n\n if (\n recoveringIntervals.length > 0 &&\n recoveringIntervals[0].execution_started_at !== null\n ) {\n const recoveryTimeMs =\n (recoveringIntervals[0].execution_started_at +\n this._resolvedOptions.hungScheduleTimeoutSeconds) *\n 1000;\n nextTimeMs =\n nextTimeMs === null\n ? recoveryTimeMs\n : Math.min(nextTimeMs, recoveryTimeMs);\n }\n\n if (this._keepAliveRefs > 0) {\n const keepAliveMs = nowMs + this._resolvedOptions.keepAliveIntervalMs;\n nextTimeMs =\n nextTimeMs === null ? keepAliveMs : Math.min(nextTimeMs, keepAliveMs);\n }\n\n const facetRuns = this.sql<{ count: number }>`\n SELECT COUNT(*) as count FROM cf_agents_facet_runs\n `;\n if ((facetRuns[0]?.count ?? 0) > 0) {\n const facetRecoveryMs = nowMs + this._resolvedOptions.keepAliveIntervalMs;\n nextTimeMs =\n nextTimeMs === null\n ? facetRecoveryMs\n : Math.min(nextTimeMs, facetRecoveryMs);\n }\n\n if (nextTimeMs !== null) {\n await this.ctx.storage.setAlarm(nextTimeMs);\n } else {\n await this.ctx.storage.deleteAlarm();\n }\n }\n\n /**\n * Override PartyServer's onAlarm hook as a no-op.\n * Agent handles alarm logic directly in the alarm() method override,\n * but super.alarm() calls onAlarm() after #ensureInitialized(),\n * so we suppress the default \"Implement onAlarm\" warning.\n */\n onAlarm(): void {}\n\n /**\n * Method called when an alarm fires.\n * Executes any scheduled tasks that are due.\n *\n * Calls super.alarm() first to ensure PartyServer's #ensureInitialized()\n * runs, which resolves this.name from ctx.id.name (including for\n * facets, which are spawned with an explicit id so they have their\n * own ctx.id.name; pre-2026-03-15 alarms fall back to the legacy\n * __ps_name storage record) and calls onStart() if needed.\n *\n * @remarks\n * To schedule a task, please use the `this.schedule` method instead.\n * See {@link https://developers.cloudflare.com/agents/api-reference/schedule-tasks/}\n */\n async alarm() {\n // Ensure PartyServer initialization (name resolution, onStart) runs\n // before processing any scheduled tasks.\n await super.alarm();\n\n const now = Math.floor(Date.now() / 1000);\n\n // Get all schedules that should be executed now\n const result = this.sql<ScheduleStorageRow>`\n SELECT * FROM cf_agents_schedules WHERE time <= ${now}\n `;\n\n if (result && Array.isArray(result)) {\n // Warn when many stale one-shot rows share the same callback — this\n // usually means schedule() was called repeatedly (e.g. in onStart)\n // without idempotent:true and rows accumulated across restarts.\n const DUPLICATE_SCHEDULE_THRESHOLD = 10;\n const oneShotCounts = new Map<string, number>();\n for (const row of result) {\n if (row.type === \"delayed\" || row.type === \"scheduled\") {\n oneShotCounts.set(\n row.callback,\n (oneShotCounts.get(row.callback) ?? 0) + 1\n );\n }\n }\n for (const [cb, count] of oneShotCounts) {\n if (count >= DUPLICATE_SCHEDULE_THRESHOLD) {\n try {\n console.warn(\n `Processing ${count} stale \"${cb}\" schedules in a single alarm cycle. ` +\n `This usually means schedule() is being called repeatedly without ` +\n `the idempotent option. Consider using scheduleEvery() for recurring ` +\n `tasks or passing { idempotent: true } to schedule().`\n );\n this._emit(\"schedule:duplicate_warning\", {\n callback: cb,\n count,\n type: \"one-shot\"\n });\n } catch {\n // Warning emission is non-critical — never block row processing.\n }\n }\n }\n\n for (const row of result as ScheduleStorageRow[]) {\n let executed = false;\n\n // Overlap prevention for interval schedules with hung callback detection\n if (row.type === \"interval\" && row.running === 1) {\n const executionStartedAt =\n (row as { execution_started_at?: number }).execution_started_at ??\n 0;\n const hungTimeoutSeconds =\n this._resolvedOptions.hungScheduleTimeoutSeconds;\n const elapsedSeconds = now - executionStartedAt;\n\n if (elapsedSeconds < hungTimeoutSeconds) {\n console.warn(\n `Skipping interval schedule ${row.id}: previous execution still running`\n );\n continue;\n }\n // Previous execution appears hung, force reset and re-execute\n console.warn(\n `Forcing reset of hung interval schedule ${row.id} (started ${elapsedSeconds}s ago)`\n );\n }\n\n // Mark interval as running before execution\n if (row.type === \"interval\") {\n this\n .sql`UPDATE cf_agents_schedules SET running = 1, execution_started_at = ${now} WHERE id = ${row.id}`;\n }\n\n if (row.owner_path) {\n try {\n const ownerPath = JSON.parse(row.owner_path) as AgentPathStep[];\n await this._cf_dispatchScheduledCallback(ownerPath, row);\n } catch (e) {\n console.error(\n `error dispatching scheduled callback \"${row.callback}\"`,\n e\n );\n this._emit(\"schedule:error\", {\n callback: row.callback,\n id: row.id,\n error: e instanceof Error ? e.message : String(e),\n attempts: 0\n });\n try {\n await this.onError(e);\n } catch {\n // swallow onError errors\n }\n // Reset the in-flight flag for interval rows so the row\n // doesn't stay stuck in `running=1` when dispatch fails\n // (e.g. the facet's registry entry is missing). The next\n // alarm cycle will retry.\n if (row.type === \"interval\") {\n this.sql`\n UPDATE cf_agents_schedules SET running = 0 WHERE id = ${row.id}\n `;\n }\n continue;\n }\n } else {\n await this._executeScheduleCallback(row);\n }\n executed = true;\n\n if (this._destroyed) return;\n if (!executed) continue;\n\n if (row.type === \"cron\") {\n // Update next execution time for cron schedules\n const nextExecutionTime = getNextCronTime(row.cron ?? \"\");\n const nextTimestamp = Math.floor(nextExecutionTime.getTime() / 1000);\n\n this.sql`\n UPDATE cf_agents_schedules SET time = ${nextTimestamp} WHERE id = ${row.id}\n `;\n } else if (row.type === \"interval\") {\n // Reset running flag and schedule next interval execution\n const nextTimestamp =\n Math.floor(Date.now() / 1000) + (row.intervalSeconds ?? 0);\n\n this.sql`\n UPDATE cf_agents_schedules SET running = 0, time = ${nextTimestamp} WHERE id = ${row.id}\n `;\n } else {\n // Delete one-time schedules after execution\n this.sql`\n DELETE FROM cf_agents_schedules WHERE id = ${row.id}\n `;\n }\n }\n }\n if (this._destroyed) return;\n\n await this._onAlarmHousekeeping();\n\n // Schedule the next alarm\n await this._scheduleNextAlarm();\n }\n\n // ── Sub-agent routing (external addressability for facets) ──────────────\n\n /**\n * Intercept incoming HTTP/WS requests whose URL contains a\n * `/sub/{child-class}/{child-name}` marker and forward them to\n * the facet. The `onBeforeSubAgent` hook fires first (authorize,\n * mutate, or short-circuit). If the hook doesn't return a\n * Response, the framework resolves the facet and hands the\n * request off.\n *\n * After a WebSocket upgrade completes, subsequent frames route\n * directly to the child — the parent is only on the path for the\n * initial request.\n *\n * @experimental The API surface may change before stabilizing.\n */\n override async fetch(request: Request): Promise<Response> {\n const ctx = this.ctx as unknown as Partial<FacetCapableCtx>;\n const match = _parseSubAgentPath(request.url, {\n knownClasses: ctx.exports ? Object.keys(ctx.exports) : undefined\n });\n\n if (!match) {\n return super.fetch(request);\n }\n\n // Hook runs in the parent's isolate before any facet work.\n const decision = await this.onBeforeSubAgent(request, {\n className: match.childClass,\n name: match.childName\n });\n if (decision instanceof Response) return decision;\n const forwardReq = decision instanceof Request ? decision : request;\n\n return this._cf_forwardToFacet(forwardReq, match);\n }\n\n /**\n * Parent-side middleware hook. Fires before a request is\n * forwarded into a facet sub-agent. Mirrors `onBeforeConnect` /\n * `onBeforeRequest`.\n *\n * - return `void` (default) → forward the original request\n * - return `Request` → forward this (modified) request\n * - return `Response` → return this response to the\n * client; do not wake the child\n *\n * Default implementation: return void (permissive).\n *\n * The hook receives the **original** request with its URL intact —\n * including the `/sub/{class}/{name}` segment. The routing\n * decision for which facet to wake is fixed at parse time, so if\n * you return a modified `Request`, its headers, body, method, and\n * query string flow through to the child, but the **pathname**\n * the child sees is always the tail after `/sub/{class}/{name}`.\n * Customize via headers/body rather than URL-rewriting.\n *\n * WebSocket upgrade requests flow through this hook the same way as\n * plain HTTP. If you return a mutated `Request`, make sure it still\n * carries the original `Upgrade: websocket` and `Sec-WebSocket-*`\n * headers — the simplest safe recipe is to clone the incoming\n * request's headers (via `new Headers(req.headers)`) and only add\n * or replace entries, rather than constructing a fresh `Headers`\n * object from scratch.\n *\n * @experimental The API surface may change before stabilizing.\n *\n * @example\n * ```ts\n * class Inbox extends Agent {\n * override async onBeforeSubAgent(req, { className, name }) {\n * // Strict registry gate\n * if (!this.hasSubAgent(className, name)) {\n * return new Response(\"Not found\", { status: 404 });\n * }\n * }\n * }\n * ```\n */\n async onBeforeSubAgent(\n // oxlint-disable-next-line eslint(no-unused-vars) -- subclass override\n _request: Request,\n // oxlint-disable-next-line eslint(no-unused-vars) -- subclass override\n _child: { className: string; name: string }\n ): Promise<Request | Response | void> {\n return undefined;\n }\n\n /**\n * Resolve the facet Fetcher for the match and forward the\n * request to it with `/sub/{class}/{name}` stripped.\n *\n * @internal\n */\n private async _cf_forwardToFacet(\n req: Request,\n match: {\n childClass: string;\n childName: string;\n remainingPath: string;\n }\n ): Promise<Response> {\n let fetcher: { fetch(r: Request): Promise<Response> };\n try {\n fetcher = (await this._cf_resolveSubAgent(\n match.childClass,\n match.childName\n )) as { fetch(r: Request): Promise<Response> };\n } catch (err) {\n // Keep the wire response terse: don't leak the parent's view of\n // exports or internal error text over HTTP. The full error is\n // still available to developers via worker logs / `console.error`.\n const message = err instanceof Error ? err.message : String(err);\n console.error(\"[agents] sub-agent route failed:\", message);\n if (/null character/i.test(message) || /reserved/i.test(message)) {\n return new Response(\"Bad Request\", { status: 400 });\n }\n return new Response(\"Not Found\", { status: 404 });\n }\n\n // Rewrite the URL to strip the /sub/{class}/{name} prefix. The\n // child's own fetch then processes either its own request (if\n // no further /sub/... remains) or recurses into its own child.\n const rewritten = new URL(req.url);\n rewritten.pathname = match.remainingPath;\n const forwarded = new Request(rewritten, req);\n return fetcher.fetch(forwarded);\n }\n\n /**\n * Bridge method used by `getSubAgentByName`. Resolves the facet\n * on each call (idempotent via `subAgent`) and dispatches one\n * RPC method. Stateless — no cached references.\n *\n * @internal\n */\n async _cf_invokeSubAgent(\n className: string,\n name: string,\n method: string,\n args: unknown[]\n ): Promise<unknown> {\n const stub = await this._cf_resolveSubAgent(className, name);\n // Must call `handle[method](...)` in one expression — extracting\n // via `const fn = handle[method]; fn.apply(handle, args)` breaks\n // the workerd RpcProperty binding. (Confirmed by the spike.)\n const handle = stub as unknown as Record<\n string,\n (...a: unknown[]) => Promise<unknown>\n >;\n if (typeof handle[method] !== \"function\") {\n throw new Error(`Method \"${method}\" not found on ${className}.`);\n }\n return await handle[method](...args);\n }\n\n // ── Sub-agent (facet) management ────────────────────────────────────────\n\n /**\n * Initialize this agent as a facet in a single RPC.\n *\n * Runs entirely inside the child's isolate, so every storage write\n * and `onStart()` I/O is owned by the child DO. This replaces the\n * previous \"construct a Request in the parent DO and `stub.fetch()`\n * it on the child\" handshake, whose native I/O was tied to the\n * parent and triggered \"Cannot perform I/O on behalf of a different\n * Durable Object\" on the child.\n *\n * We set `_isFacet` eagerly (before `__unsafe_ensureInitialized`\n * runs `onStart()`) so any code that legitimately branches on it\n * — e.g. skipping parent-owned alarms in schedule guards — sees\n * the flag during the first `onStart()` run. Protocol broadcasts are\n * suppressed only during this bootstrap window; afterward, facets can\n * broadcast to their own WebSocket clients reached via sub-agent\n * routing.\n *\n * The facet's name (and `this.name` getter) is handled entirely by\n * partyserver via `ctx.id.name`, which is populated because the\n * parent passed an explicit `id: parentNs.idFromName(name)` to\n * `ctx.facets.get()` — see {@link _cf_resolveSubAgent}. No\n * `setName()` call or `__ps_name` storage write is needed; the\n * facet's name survives cold wake automatically because the\n * factory re-runs and `idFromName` is deterministic.\n *\n * @internal Called by {@link subAgent}.\n */\n async _cf_initAsFacet(\n name: string,\n parentPath: ReadonlyArray<{ className: string; name: string }> = []\n ): Promise<void> {\n // Defense in depth: the parent is supposed to construct the\n // facet with `id: parentNs.idFromName(name)` via\n // `_cf_resolveSubAgent`, which makes `this.name` resolve to\n // `name` automatically through partyserver's `ctx.id.name`. If\n // it didn't (e.g. someone bypassed `_cf_resolveSubAgent`, or\n // the parent's id construction has a bug), `this.name` would\n // silently report the parent's name instead of the facet's\n // name. Fail loud instead of letting a misconfigured facet\n // operate with the wrong identity.\n if (this.name !== name) {\n throw new Error(\n `Facet bootstrap mismatch: expected this.name === \"${name}\" but got \"${this.name}\". ` +\n `This usually means the parent passed the wrong (or no) id to ctx.facets.get(). ` +\n `See _cf_resolveSubAgent.`\n );\n }\n this._isFacet = true;\n this._parentPath = parentPath;\n // Persist the agent-specific facet keys in parallel.\n await Promise.all([\n this.ctx.storage.put(\"cf_agents_is_facet\", true),\n this.ctx.storage.put(\"cf_agents_parent_path\", parentPath)\n ]);\n // Fire onStart() now since this RPC bypasses Server.fetch(),\n // which is the entry point that normally triggers it. Suppress\n // protocol broadcasts only during startup so bootstrap cannot touch\n // parent-owned WebSocket handles if the parent is inside onMessage().\n this._suppressProtocolBroadcasts = true;\n try {\n await this.__unsafe_ensureInitialized();\n } finally {\n this._suppressProtocolBroadcasts = false;\n }\n }\n\n /**\n * Ancestor chain for this agent, root-first. Empty for top-level\n * DOs. Populated at facet init time; survives hibernation.\n *\n * @example\n * ```ts\n * class Chat extends Agent {\n * onStart() {\n * console.log(\"chat started under:\", this.parentPath);\n * // → [{ className: \"Tenant\", name: \"acme\" }, { className: \"Inbox\", name: \"alice\" }]\n * }\n * }\n * ```\n *\n * @experimental The API surface may change before stabilizing.\n */\n get parentPath(): ReadonlyArray<{ className: string; name: string }> {\n return this._parentPath;\n }\n\n /**\n * Ancestor chain + self, root-first. Convenient for logging.\n *\n * @experimental The API surface may change before stabilizing.\n */\n get selfPath(): ReadonlyArray<{ className: string; name: string }> {\n return [\n ...this._parentPath,\n {\n className: (this.constructor as { name: string }).name,\n name: this.name\n }\n ];\n }\n\n /**\n * Resolve a typed RPC stub for this facet's **immediate** parent\n * agent.\n *\n * Symmetric with `subAgent(Cls, name)`: while `subAgent` opens a\n * stub from parent to child, `parentAgent` opens one from child\n * to parent. Pass the direct parent's class reference — the\n * framework verifies it matches the last entry of\n * `this.parentPath` at runtime, then looks up `env[Cls.name]` to\n * find the namespace binding.\n *\n * `this.parentPath` is root-first, so the direct parent is the\n * **last** entry: `this.parentPath.at(-1)`. For grandparents and\n * further ancestors, iterate `this.parentPath` and use\n * `getAgentByName(env.X, this.parentPath[i].name)` directly.\n *\n * Assumes the standard \"binding name matches class name\" convention.\n * If your `wrangler.jsonc` binds the parent under a different name\n * (e.g. `{ class_name: \"Inbox\", name: \"MY_INBOX\" }`), call\n * `getAgentByName(env.MY_INBOX, this.parentPath.at(-1)!.name)`\n * directly instead.\n *\n * @experimental The API surface may change before stabilizing.\n *\n * @throws If this agent is not a facet (no parent).\n * @throws If `Cls.name` doesn't match the recorded direct-parent\n * class (guards against accidentally reaching the wrong\n * DO, especially in nested Root → Mid → Leaf chains).\n * @throws If no env binding named `Cls.name` is found.\n *\n * @example\n * ```ts\n * class Chat extends AIChatAgent<Env> {\n * async onChatMessage(...) {\n * const inbox = await this.parentAgent(Inbox);\n * const memory = await inbox.getSharedMemory(\"facts\");\n * // ...\n * }\n * }\n * ```\n */\n async parentAgent<T extends Agent>(\n cls: SubAgentClass<T>\n ): Promise<DurableObjectStub<T>> {\n // `_parentPath` is root-first, so the *direct* parent is the\n // last entry. Destructuring with `[parent] = ...` would grab the\n // root ancestor instead — wrong for any chain deeper than one\n // level and silently routes to the wrong DO if the root and the\n // direct parent happen to be the same class.\n const parent = this._parentPath[this._parentPath.length - 1];\n if (!parent) {\n throw new Error(\n `parentAgent(): ${this.constructor.name} is not a facet — ` +\n `only sub-agents (spawned via \\`subAgent()\\`) have a parent.`\n );\n }\n if (cls.name !== parent.className) {\n throw new Error(\n `parentAgent(${cls.name}): this facet's recorded parent class ` +\n `is \"${parent.className}\", not \"${cls.name}\". Pass the class ` +\n `whose constructor actually spawned this facet.`\n );\n }\n const binding = (this.env as Record<string, unknown>)[cls.name] as\n | DurableObjectNamespace<T>\n | undefined;\n if (!binding) {\n throw new Error(\n `parentAgent(${cls.name}): no top-level binding \"${cls.name}\" ` +\n `found in env. If the parent is bound under a different name ` +\n `(e.g. \"MY_${cls.name.toUpperCase()}\"), use ` +\n `\\`getAgentByName(env.MY_${cls.name.toUpperCase()}, this.parentPath.at(-1)!.name)\\` directly.`\n );\n }\n return await getServerByName<Cloudflare.Env, T>(binding, parent.name);\n }\n\n /**\n * Get or create a named sub-agent — a child Durable Object (facet)\n * with its own isolated SQLite storage running on the same machine.\n *\n * The child class must extend `Agent` and be exported from the worker\n * entry point. The first call for a given name triggers the child's\n * `onStart()`. Subsequent calls return the existing instance.\n *\n * @experimental The API surface may change before stabilizing.\n *\n * @param cls The Agent subclass (must be exported from the worker)\n * @param name Unique name for this child instance\n * @returns A typed RPC stub for calling methods on the child\n *\n * @example\n * ```typescript\n * const searcher = await this.subAgent(SearchAgent, \"main-search\");\n * const results = await searcher.search(\"cloudflare agents\");\n * ```\n */\n async subAgent<T extends Agent>(\n cls: SubAgentClass<T>,\n name: string\n ): Promise<SubAgentStub<T>> {\n return (await this._cf_resolveSubAgent(cls.name, name)) as SubAgentStub<T>;\n }\n\n /** Maximum number of non-terminal agent-tool runs this parent may own at once. */\n maxConcurrentAgentTools = Infinity;\n\n async onAgentToolStart(_run: AgentToolRunInfo): Promise<void> {}\n\n async onAgentToolFinish(\n _run: AgentToolRunInfo,\n _result: AgentToolLifecycleResult\n ): Promise<void> {}\n\n async runAgentTool<Input = unknown, Output = unknown>(\n cls: ChatCapableAgentClass,\n options: RunAgentToolOptions<Input>\n ): Promise<RunAgentToolResult<Output>> {\n const runId = options.runId ?? nanoid(12);\n const agentType = cls.name;\n const existing = this._readAgentToolRun(runId);\n if (existing) {\n if (this._isAgentToolTerminal(existing.status)) {\n if (existing.status === \"completed\" && existing.output_json == null) {\n try {\n const child = await this.subAgent(\n cls as SubAgentClass<Agent>,\n runId\n );\n const adapter = this._asAgentToolChildAdapter<Input, Output>(child);\n const inspection = await adapter.inspectAgentToolRun(runId);\n if (inspection?.status === \"completed\") {\n const result = this._terminalResultFromInspection<Output>(\n agentType,\n inspection\n );\n this._updateAgentToolTerminal(\n runId,\n result,\n inspection.completedAt\n );\n return result;\n }\n } catch {\n // Fall back to the retained parent row.\n }\n }\n return this._resultFromAgentToolRow<Output>(existing);\n }\n return await this._replayAndInterruptAgentToolRun<Output>(\n cls,\n existing,\n \"Agent tool run was still running, but live-tail reattachment is not supported in this runtime.\"\n );\n }\n\n const displayOrder = options.displayOrder ?? 0;\n const inputPreview =\n options.inputPreview ?? this._defaultAgentToolPreview(options.input);\n const displayJson =\n options.display !== undefined ? JSON.stringify(options.display) : null;\n const inputPreviewJson =\n inputPreview !== undefined ? JSON.stringify(inputPreview) : null;\n const startedAt = Date.now();\n\n if (this._activeAgentToolRunCount() >= this.maxConcurrentAgentTools) {\n const error = `maxConcurrentAgentTools (${this.maxConcurrentAgentTools}) exceeded`;\n this.sql`\n INSERT INTO cf_agent_tool_runs (\n run_id, parent_tool_call_id, agent_type, input_preview,\n input_redacted, status, error_message, display_metadata,\n display_order, started_at, completed_at\n ) VALUES (\n ${runId}, ${options.parentToolCallId ?? null}, ${agentType},\n ${inputPreviewJson}, 1, 'error', ${error}, ${displayJson},\n ${displayOrder}, ${startedAt}, ${Date.now()}\n )\n `;\n this._broadcastAgentToolEvent(options.parentToolCallId, 0, {\n kind: \"started\",\n runId,\n agentType,\n inputPreview,\n order: displayOrder,\n display: options.display\n });\n this._broadcastAgentToolEvent(options.parentToolCallId, 1, {\n kind: \"error\",\n runId,\n error\n });\n return { runId, agentType, status: \"error\", error };\n }\n\n this.sql`\n INSERT INTO cf_agent_tool_runs (\n run_id, parent_tool_call_id, agent_type, input_preview,\n input_redacted, status, display_metadata, display_order, started_at\n ) VALUES (\n ${runId}, ${options.parentToolCallId ?? null}, ${agentType},\n ${inputPreviewJson}, 1, 'starting', ${displayJson}, ${displayOrder},\n ${startedAt}\n )\n `;\n\n const runInfo: AgentToolRunInfo = {\n runId,\n parentToolCallId: options.parentToolCallId,\n agentType,\n inputPreview,\n status: \"starting\",\n display: options.display,\n displayOrder,\n startedAt\n };\n await this.onAgentToolStart(runInfo);\n this._broadcastAgentToolEvent(options.parentToolCallId, 0, {\n kind: \"started\",\n runId,\n agentType,\n inputPreview,\n order: displayOrder,\n display: options.display\n });\n\n const child = await this.subAgent(cls as SubAgentClass<Agent>, runId);\n const adapter = this._asAgentToolChildAdapter<Input, Output>(child);\n const childStart = await adapter.startAgentToolRun(options.input, {\n runId\n });\n this._markAgentToolRunning(runId);\n let sequence = 1;\n let parentAbortListener: (() => void) | undefined;\n if (options.signal) {\n if (options.signal.aborted) {\n await adapter.cancelAgentToolRun(runId, options.signal.reason);\n const reason =\n options.signal.reason instanceof Error\n ? options.signal.reason.message\n : String(options.signal.reason ?? \"cancelled\");\n const result: RunAgentToolResult<Output> = {\n runId,\n agentType,\n status: \"aborted\",\n error: reason\n };\n this._updateAgentToolTerminal(runId, result);\n this._broadcastAgentToolTerminal(\n options.parentToolCallId,\n sequence,\n result\n );\n await this.onAgentToolFinish(\n { ...runInfo, status: \"aborted\", completedAt: Date.now() },\n result\n );\n return result;\n } else {\n parentAbortListener = () => {\n void adapter.cancelAgentToolRun(runId, options.signal?.reason);\n };\n options.signal.addEventListener(\"abort\", parentAbortListener, {\n once: true\n });\n }\n }\n\n try {\n if (adapter.tailAgentToolRun) {\n const stream = await adapter.tailAgentToolRun(runId, {\n afterSequence: -1\n });\n sequence = await this._forwardAgentToolStream(\n stream,\n options.parentToolCallId,\n runId,\n sequence,\n options.signal\n );\n } else {\n const chunks = await adapter.getAgentToolChunks(runId);\n sequence = this._broadcastAgentToolChunks(\n options.parentToolCallId,\n runId,\n chunks,\n sequence\n );\n }\n\n if (options.signal?.aborted) {\n await adapter.cancelAgentToolRun(runId, options.signal.reason);\n const reason =\n options.signal.reason instanceof Error\n ? options.signal.reason.message\n : String(options.signal.reason ?? \"cancelled\");\n const result: RunAgentToolResult<Output> = {\n runId,\n agentType,\n status: \"aborted\",\n error: reason\n };\n this._updateAgentToolTerminal(runId, result);\n this._broadcastAgentToolTerminal(\n options.parentToolCallId,\n sequence,\n result\n );\n await this.onAgentToolFinish(\n { ...runInfo, status: \"aborted\", completedAt: Date.now() },\n result\n );\n return result;\n }\n\n const inspection =\n (await adapter.inspectAgentToolRun(runId)) ?? childStart;\n const result = this._terminalResultFromInspection<Output>(\n agentType,\n inspection\n );\n this._updateAgentToolTerminal(runId, result, inspection.completedAt);\n this._broadcastAgentToolTerminal(\n options.parentToolCallId,\n sequence,\n result\n );\n await this.onAgentToolFinish(\n { ...runInfo, status: result.status, completedAt: Date.now() },\n result\n );\n return result;\n } catch (error) {\n if (options.signal?.aborted) {\n await adapter.cancelAgentToolRun(runId, options.signal.reason);\n const reason =\n options.signal.reason instanceof Error\n ? options.signal.reason.message\n : String(options.signal.reason ?? \"cancelled\");\n const result: RunAgentToolResult<Output> = {\n runId,\n agentType,\n status: \"aborted\",\n error: reason\n };\n this._updateAgentToolTerminal(runId, result);\n this._broadcastAgentToolTerminal(\n options.parentToolCallId,\n sequence,\n result\n );\n await this.onAgentToolFinish(\n { ...runInfo, status: \"aborted\", completedAt: Date.now() },\n result\n );\n return result;\n }\n const message = error instanceof Error ? error.message : String(error);\n const result: RunAgentToolResult<Output> = {\n runId,\n agentType,\n status: \"error\",\n error: message\n };\n this._updateAgentToolTerminal(runId, result);\n this._broadcastAgentToolTerminal(\n options.parentToolCallId,\n sequence,\n result\n );\n await this.onAgentToolFinish(\n { ...runInfo, status: \"error\", completedAt: Date.now() },\n result\n );\n return result;\n } finally {\n if (parentAbortListener && options.signal) {\n options.signal.removeEventListener(\"abort\", parentAbortListener);\n }\n }\n }\n\n hasAgentToolRun<T extends Agent>(\n cls: SubAgentClass<T>,\n runId: string\n ): boolean;\n hasAgentToolRun(agentType: string, runId: string): boolean;\n hasAgentToolRun(classOrName: SubAgentClass | string, runId: string): boolean {\n const agentType =\n typeof classOrName === \"string\" ? classOrName : classOrName.name;\n const rows = this.sql<{ n: number }>`\n SELECT COUNT(*) AS n FROM cf_agent_tool_runs\n WHERE run_id = ${runId} AND agent_type = ${agentType}\n `;\n return (rows[0]?.n ?? 0) > 0;\n }\n\n async clearAgentToolRuns(options?: {\n olderThan?: number;\n status?: AgentToolRunStatus[];\n }): Promise<void> {\n const rows = this.sql<{\n run_id: string;\n agent_type: string;\n status: string;\n }>`\n SELECT run_id, agent_type, status FROM cf_agent_tool_runs\n ORDER BY started_at ASC\n `;\n const statusFilter = options?.status\n ? new Set<string>(options.status)\n : null;\n const retained = rows.filter((row) => {\n if (statusFilter && !statusFilter.has(row.status)) return false;\n if (options?.olderThan !== undefined) {\n const full = this._readAgentToolRun(row.run_id);\n if (!full || full.started_at >= options.olderThan) return false;\n }\n return true;\n });\n\n for (const row of retained) {\n try {\n const cls = this._agentToolClassByName(row.agent_type);\n if (row.status === \"starting\" || row.status === \"running\") {\n const child = await this.subAgent(cls, row.run_id);\n const adapter = this._asAgentToolChildAdapter(child);\n await adapter.cancelAgentToolRun(\n row.run_id,\n \"clearing agent tool run\"\n );\n }\n await this.deleteSubAgent(cls, row.run_id);\n } catch {\n // Cleanup is intentionally idempotent.\n }\n this.sql`\n DELETE FROM cf_agent_tool_runs WHERE run_id = ${row.run_id}\n `;\n }\n }\n\n private _isAgentToolTerminal(status: string): boolean {\n return (\n status === \"completed\" ||\n status === \"error\" ||\n status === \"aborted\" ||\n status === \"interrupted\"\n );\n }\n\n private _activeAgentToolRunCount(): number {\n const rows = this.sql<{ n: number }>`\n SELECT COUNT(*) AS n FROM cf_agent_tool_runs\n WHERE status IN ('starting', 'running')\n `;\n return rows[0]?.n ?? 0;\n }\n\n private _defaultAgentToolPreview(input: unknown): unknown {\n if (typeof input === \"string\") return input.slice(0, 500);\n if (input === null || input === undefined) return input;\n try {\n const json = JSON.stringify(input);\n return json.length > 500 ? `${json.slice(0, 497)}...` : json;\n } catch {\n return String(input).slice(0, 500);\n }\n }\n\n private _readAgentToolRun(runId: string): AgentToolRunStorageRow | null {\n const rows = this.sql<AgentToolRunStorageRow>`\n SELECT run_id, parent_tool_call_id, agent_type, input_preview, status,\n summary, output_json, error_message, display_metadata, display_order,\n started_at, completed_at\n FROM cf_agent_tool_runs\n WHERE run_id = ${runId}\n LIMIT 1\n `;\n return rows[0] ?? null;\n }\n\n private _resultFromAgentToolRow<Output>(\n row: AgentToolRunStorageRow\n ): RunAgentToolResult<Output> {\n const output = this._parseAgentToolJson(row.output_json) as\n | Output\n | undefined;\n return {\n runId: row.run_id,\n agentType: row.agent_type,\n status: row.status as RunAgentToolResult<Output>[\"status\"],\n ...(output !== undefined ? { output } : {}),\n ...(row.summary !== null ? { summary: row.summary } : {}),\n ...(row.error_message !== null ? { error: row.error_message } : {})\n };\n }\n\n private _terminalResultFromInspection<Output>(\n agentType: string,\n inspection: AgentToolRunInspection<Output>\n ): RunAgentToolResult<Output> {\n if (inspection.status === \"completed\") {\n return {\n runId: inspection.runId,\n agentType,\n status: \"completed\",\n output: inspection.output,\n summary: inspection.summary\n };\n }\n if (inspection.status === \"aborted\") {\n return {\n runId: inspection.runId,\n agentType,\n status: \"aborted\",\n error: inspection.error\n };\n }\n return {\n runId: inspection.runId,\n agentType,\n status: \"error\",\n error: inspection.error ?? \"Agent tool run failed\"\n };\n }\n\n private _updateAgentToolTerminal<Output>(\n runId: string,\n result: RunAgentToolResult<Output>,\n completedAt = Date.now()\n ): void {\n this.sql`\n UPDATE cf_agent_tool_runs\n SET status = ${result.status},\n summary = ${result.summary ?? null},\n output_json = ${this._stringifyAgentToolOutput(result.output)},\n error_message = ${result.error ?? null},\n completed_at = ${completedAt}\n WHERE run_id = ${runId}\n AND status NOT IN ('completed', 'error', 'aborted', 'interrupted')\n `;\n if (result.status === \"completed\" && result.output !== undefined) {\n this.sql`\n UPDATE cf_agent_tool_runs\n SET output_json = COALESCE(output_json, ${this._stringifyAgentToolOutput(result.output)}),\n summary = COALESCE(summary, ${result.summary ?? null})\n WHERE run_id = ${runId} AND status = 'completed'\n `;\n }\n }\n\n private _markAgentToolRunning(runId: string): void {\n this.sql`\n UPDATE cf_agent_tool_runs\n SET status = 'running'\n WHERE run_id = ${runId} AND status = 'starting'\n `;\n }\n\n private _parseAgentToolJson(value: string | null): unknown {\n if (value === null) return undefined;\n try {\n return JSON.parse(value);\n } catch {\n return value;\n }\n }\n\n private _stringifyAgentToolOutput(output: unknown): string | null {\n if (output === undefined) return null;\n const json = JSON.stringify(output);\n return json === undefined ? null : json;\n }\n\n private _broadcastAgentToolEvent(\n parentToolCallId: string | undefined,\n sequence: number,\n event: AgentToolEvent,\n replay?: true,\n connection?: Connection\n ): void {\n const message: AgentToolEventMessage = {\n type: \"agent-tool-event\",\n parentToolCallId,\n sequence,\n event,\n ...(replay ? { replay } : {})\n };\n const body = JSON.stringify(message);\n if (connection) {\n connection.send(body);\n } else {\n this.broadcast(body);\n }\n }\n\n private _broadcastAgentToolChunks(\n parentToolCallId: string | undefined,\n runId: string,\n chunks: AgentToolStoredChunk[],\n sequence: number,\n replay?: true,\n connection?: Connection\n ): number {\n let next = sequence;\n for (const chunk of chunks) {\n this._broadcastAgentToolEvent(\n parentToolCallId,\n next++,\n { kind: \"chunk\", runId, body: chunk.body },\n replay,\n connection\n );\n }\n return next;\n }\n\n private async _forwardAgentToolStream(\n stream: ReadableStream<AgentToolStoredChunk>,\n parentToolCallId: string | undefined,\n runId: string,\n sequence: number,\n signal?: AbortSignal\n ): Promise<number> {\n let next = sequence;\n if (signal?.aborted) return next;\n const reader = (\n stream as ReadableStream<AgentToolStoredChunk | Uint8Array>\n ).getReader();\n const decoder = new TextDecoder();\n let bufferedBytes = \"\";\n let abortListener: (() => void) | undefined;\n if (signal) {\n abortListener = () => {\n // runAgentTool() also calls cancelAgentToolRun(), whose adapter should\n // close the tail stream. Avoid reader.cancel(reason) here because DO RPC\n // can surface cancellation reasons as unhandled stream rejections.\n };\n signal.addEventListener(\"abort\", abortListener, { once: true });\n }\n try {\n const forwardChunk = (chunk: AgentToolStoredChunk) => {\n this._broadcastAgentToolEvent(parentToolCallId, next++, {\n kind: \"chunk\",\n runId,\n body: chunk.body\n });\n };\n const forwardLine = (line: string) => {\n try {\n const chunk = JSON.parse(line) as Partial<AgentToolStoredChunk>;\n if (typeof chunk.body === \"string\") {\n forwardChunk(chunk as AgentToolStoredChunk);\n }\n } catch {\n // Skip malformed stream frames; the child remains authoritative for\n // final run status and durable chunk replay.\n }\n };\n const flushBufferedBytes = (final = false) => {\n while (true) {\n const newline = bufferedBytes.indexOf(\"\\n\");\n if (newline === -1) break;\n const line = bufferedBytes.slice(0, newline).trim();\n bufferedBytes = bufferedBytes.slice(newline + 1);\n if (line.length > 0) {\n forwardLine(line);\n }\n }\n if (final && bufferedBytes.trim().length > 0) {\n forwardLine(bufferedBytes);\n bufferedBytes = \"\";\n }\n };\n while (true) {\n let readResult: ReadableStreamReadResult<\n AgentToolStoredChunk | Uint8Array\n >;\n try {\n readResult = await reader.read();\n } catch (error) {\n if (signal?.aborted) break;\n throw error;\n }\n const { done, value } = readResult;\n if (done) {\n bufferedBytes += decoder.decode();\n flushBufferedBytes(true);\n break;\n }\n if (value instanceof Uint8Array) {\n bufferedBytes += decoder.decode(value, { stream: true });\n flushBufferedBytes();\n } else {\n forwardChunk(value);\n }\n }\n } finally {\n if (abortListener && signal) {\n signal.removeEventListener(\"abort\", abortListener);\n }\n reader.releaseLock();\n }\n return next;\n }\n\n private _broadcastAgentToolTerminal<Output>(\n parentToolCallId: string | undefined,\n sequence: number,\n result: RunAgentToolResult<Output>,\n replay?: true,\n connection?: Connection\n ): void {\n if (result.status === \"completed\") {\n this._broadcastAgentToolEvent(\n parentToolCallId,\n sequence,\n {\n kind: \"finished\",\n runId: result.runId,\n summary: result.summary ?? \"\"\n },\n replay,\n connection\n );\n } else if (result.status === \"aborted\") {\n this._broadcastAgentToolEvent(\n parentToolCallId,\n sequence,\n { kind: \"aborted\", runId: result.runId, reason: result.error },\n replay,\n connection\n );\n } else if (result.status === \"interrupted\") {\n this._broadcastAgentToolEvent(\n parentToolCallId,\n sequence,\n {\n kind: \"interrupted\",\n runId: result.runId,\n error: result.error ?? \"Agent tool run was interrupted\"\n },\n replay,\n connection\n );\n } else {\n this._broadcastAgentToolEvent(\n parentToolCallId,\n sequence,\n {\n kind: \"error\",\n runId: result.runId,\n error: result.error ?? \"Agent tool run failed\"\n },\n replay,\n connection\n );\n }\n }\n\n private _asAgentToolChildAdapter<Input = unknown, Output = unknown>(\n child: unknown\n ): AgentToolChildAdapter<Input, Output> {\n const candidate = child as Partial<AgentToolChildAdapter<Input, Output>>;\n if (\n typeof candidate.startAgentToolRun !== \"function\" ||\n typeof candidate.cancelAgentToolRun !== \"function\" ||\n typeof candidate.inspectAgentToolRun !== \"function\" ||\n typeof candidate.getAgentToolChunks !== \"function\"\n ) {\n throw new Error(\n \"Agent tool child must implement the framework agent-tool adapter. Use a @cloudflare/think Think subclass or an AIChatAgent subclass.\"\n );\n }\n return candidate as AgentToolChildAdapter<Input, Output>;\n }\n\n private _agentToolClassByName(className: string): SubAgentClass<Agent> {\n const ctx = this.ctx as unknown as Partial<FacetCapableCtx>;\n const cls = ctx.exports?.[className];\n if (!cls) {\n throw new Error(`Agent tool class \"${className}\" is not exported.`);\n }\n return cls as unknown as SubAgentClass<Agent>;\n }\n\n private async _replayAndInterruptAgentToolRun<Output>(\n cls: ChatCapableAgentClass,\n row: AgentToolRunStorageRow,\n message: string\n ): Promise<RunAgentToolResult<Output>> {\n const parentToolCallId = row.parent_tool_call_id ?? undefined;\n let sequence = 1;\n try {\n const child = await this.subAgent(\n cls as SubAgentClass<Agent>,\n row.run_id\n );\n const adapter = this._asAgentToolChildAdapter<unknown, Output>(child);\n const chunks = await adapter.getAgentToolChunks(row.run_id);\n sequence = this._broadcastAgentToolChunks(\n parentToolCallId,\n row.run_id,\n chunks,\n sequence\n );\n } catch {\n // Interruption is still the honest parent state if replay fails.\n }\n const result: RunAgentToolResult<Output> = {\n runId: row.run_id,\n agentType: row.agent_type,\n status: \"interrupted\",\n error: message\n };\n this._updateAgentToolTerminal(row.run_id, result);\n this._broadcastAgentToolTerminal(parentToolCallId, sequence, result);\n return result;\n }\n\n private async _replayAgentToolRuns(connection: Connection): Promise<void> {\n const rows = this.sql<{\n run_id: string;\n parent_tool_call_id: string | null;\n agent_type: string;\n input_preview: string | null;\n status: AgentToolRunStatus;\n summary: string | null;\n output_json: string | null;\n error_message: string | null;\n display_metadata: string | null;\n display_order: number;\n }>`\n SELECT run_id, parent_tool_call_id, agent_type, input_preview, status,\n summary, output_json, error_message, display_metadata, display_order\n FROM cf_agent_tool_runs\n ORDER BY started_at ASC\n `;\n\n for (const row of rows) {\n const parentToolCallId = row.parent_tool_call_id ?? undefined;\n let sequence = 0;\n this._broadcastAgentToolEvent(\n parentToolCallId,\n sequence++,\n {\n kind: \"started\",\n runId: row.run_id,\n agentType: row.agent_type,\n inputPreview: this._parseAgentToolJson(row.input_preview),\n order: row.display_order,\n display: this._parseAgentToolJson(row.display_metadata) as\n | AgentToolDisplayMetadata\n | undefined\n },\n true,\n connection\n );\n\n try {\n const child = await this.subAgent(\n this._agentToolClassByName(row.agent_type),\n row.run_id\n );\n const adapter = this._asAgentToolChildAdapter(child);\n const chunks = await adapter.getAgentToolChunks(row.run_id);\n sequence = this._broadcastAgentToolChunks(\n parentToolCallId,\n row.run_id,\n chunks,\n sequence,\n true,\n connection\n );\n } catch {\n // Keep replay best-effort per run.\n }\n\n if (this._isAgentToolTerminal(row.status)) {\n this._broadcastAgentToolTerminal(\n parentToolCallId,\n sequence,\n {\n runId: row.run_id,\n agentType: row.agent_type,\n status: row.status as RunAgentToolResult[\"status\"],\n output: this._parseAgentToolJson(row.output_json),\n summary: row.summary ?? undefined,\n error: row.error_message ?? undefined\n },\n true,\n connection\n );\n }\n }\n }\n\n private async _reconcileAgentToolRuns(): Promise<void> {\n const rows = this.sql<{ run_id: string; agent_type: string }>`\n SELECT run_id, agent_type FROM cf_agent_tool_runs\n WHERE status IN ('starting', 'running')\n ORDER BY started_at ASC\n `;\n for (const row of rows) {\n try {\n const cls = this._agentToolClassByName(row.agent_type);\n if (!this.hasSubAgent(cls, row.run_id)) {\n this._updateAgentToolTerminal(row.run_id, {\n runId: row.run_id,\n agentType: row.agent_type,\n status: \"interrupted\",\n error: \"Agent tool child was not found during parent recovery.\"\n });\n continue;\n }\n const child = await this.subAgent(cls, row.run_id);\n const adapter = this._asAgentToolChildAdapter(child);\n const inspection = await adapter.inspectAgentToolRun(row.run_id);\n if (\n !inspection ||\n inspection.status === \"running\" ||\n inspection.status === \"starting\"\n ) {\n this._updateAgentToolTerminal(row.run_id, {\n runId: row.run_id,\n agentType: row.agent_type,\n status: \"interrupted\",\n error:\n \"Agent tool run was still running, but live-tail reattachment is not supported in this runtime.\"\n });\n } else {\n this._updateAgentToolTerminal(\n row.run_id,\n this._terminalResultFromInspection(row.agent_type, inspection),\n inspection.completedAt\n );\n }\n } catch {\n this._updateAgentToolTerminal(row.run_id, {\n runId: row.run_id,\n agentType: row.agent_type,\n status: \"interrupted\",\n error: \"Agent tool run could not be inspected during parent recovery.\"\n });\n }\n }\n }\n\n /**\n * Shared facet resolution — takes a CamelCase class name string\n * (matching `ctx.exports`) rather than a class reference. Both\n * `subAgent(cls, name)` and `_cf_invokeSubAgent(className, ...)`\n * funnel through here so registry bookkeeping and the\n * `_cf_initAsFacet` handshake are consistent.\n *\n * @internal\n */\n private async _cf_resolveSubAgent(\n className: string,\n name: string\n ): Promise<unknown> {\n const ctx = this.ctx as unknown as Partial<FacetCapableCtx>;\n if (!ctx.facets || !ctx.exports) {\n throw new Error(\n \"subAgent() is not supported in this runtime — \" +\n \"`ctx.facets` / `ctx.exports` are unavailable. \" +\n \"Update to the latest `compatibility_date` in your wrangler.jsonc.\"\n );\n }\n if (camelCaseToKebabCase(className) === SUB_PREFIX) {\n // Any class whose kebab-cased name equals the `sub` URL\n // separator would make `/agents/.../sub/sub/...` ambiguous.\n // `Sub`, `SUB`, and `Sub_` all kebab-case to `\"sub\"` — catch\n // them uniformly rather than listing each spelling.\n throw new Error(\n `Sub-agent class name \"${className}\" kebab-cases to \"${SUB_PREFIX}\", ` +\n `which collides with the reserved URL separator — rename the ` +\n `class (e.g. \"SubThing\" or \"Subtask\").`\n );\n }\n const Cls = ctx.exports[className];\n if (!Cls) {\n throw new Error(\n `Sub-agent class \"${className}\" not found in worker exports. ` +\n `Make sure the class is exported from your worker entry point ` +\n `and that the export name matches the class name.`\n );\n }\n if (name.includes(\"\\0\")) {\n // Null char is reserved for the facet composite key delimiter —\n // letting it through would corrupt the `${class}\\0${name}` key.\n throw new Error(\n `Sub-agent name contains null character (\\\\0), which is reserved.`\n );\n }\n // Composite key: class name + NUL + facet name, so two different\n // classes can share the same user-facing name.\n const facetKey = `${className}\\0${name}`;\n // Pass an explicit `id` in FacetStartupOptions so the facet has\n // its own `ctx.id.name === name` (not the parent's name).\n // Without this, facets inherit the parent DO's `ctx.id` and\n // `this.name` on the facet would silently return the parent's\n // name. See:\n // https://developers.cloudflare.com/dynamic-workers/usage/durable-object-facets/\n //\n // The id is constructed from the parent's own bound namespace,\n // which is always present in `ctx.exports` because the parent\n // Agent class is bound as a DO. Any bound DurableObjectNamespace\n // would work — the id is opaque + a name; nothing routes\n // through the namespace at runtime for facets. We use the\n // parent's because it's guaranteed available without extra\n // env-binding lookups.\n const parentClassName = (this.constructor as { name: string }).name;\n const parentNs = ctx.exports[parentClassName];\n if (!parentNs?.idFromName) {\n // Minification is the most common cause of this error in\n // production builds: aggressive bundlers rewrite class\n // identifiers to short ids, so `this.constructor.name`\n // becomes something like `_a` and the ctx.exports lookup\n // misses. Detect that case and append a hint, otherwise\n // the message is mysterious.\n //\n // Heuristic: optional leading underscore(s), then 1–3\n // lowercase letters/digits starting with a letter (e.g.\n // `_a`, `_ab`, `_a1`, `__a`). Real class names like\n // `MyAgent` or `_UnboundParent` start with an uppercase\n // letter and won't match.\n const looksMinified = /^_*[a-z][a-z0-9]{0,2}$/.test(parentClassName);\n const minificationHint = looksMinified\n ? ` The class name \"${parentClassName}\" looks minified — make sure your bundler preserves class names (e.g. esbuild's \\`keepNames: true\\`).`\n : \"\";\n throw new Error(\n `Sub-agent bootstrap requires the parent class \"${parentClassName}\" to be bound as a Durable Object namespace, but ctx.exports[\"${parentClassName}\"] is missing or doesn't expose idFromName.${minificationHint} Make sure the parent agent class is registered in your wrangler.jsonc durable_objects.bindings under its class name.`\n );\n }\n const facetId = parentNs.idFromName(name);\n const stub = ctx.facets.get(facetKey, () => ({\n class: Cls as DurableObjectClass,\n id: facetId\n }));\n\n // Derive the child's ancestor chain: our own `parentPath` +\n // `{ class: this.constructor.name, name: this.name }`. Inductive\n // across recursive nesting.\n const childParentPath = this.selfPath;\n\n // Initialize the child as a facet via a single RPC that runs\n // inside the child's isolate. Avoids the cross-DO I/O error that\n // the previous `stub.fetch(req)` path triggered by handing a\n // parent-owned Request across the isolate boundary.\n //\n // The parent may be inside a WebSocket/message request context here.\n // Clear native context handles before the child facet RPC so workerd\n // never sees parent-owned I/O attached to child initialization.\n await agentContext.run(\n {\n agent: this,\n connection: undefined,\n request: undefined,\n email: undefined\n },\n async () => {\n await (\n stub as unknown as {\n _cf_initAsFacet(\n name: string,\n parentPath: ReadonlyArray<{ className: string; name: string }>\n ): Promise<void>;\n }\n )._cf_initAsFacet(name, childParentPath);\n }\n );\n\n // Record in the parent's sub-agent registry so `hasSubAgent` /\n // `listSubAgents` reflect the spawn. Idempotent.\n this._recordSubAgent(className, name);\n\n return stub;\n }\n\n /**\n * Forcefully abort a running sub-agent. The child stops executing\n * immediately and will be restarted on next {@link subAgent} call.\n * Pending RPC calls receive the reason as an error.\n * Transitively aborts the child's own children.\n *\n * @experimental The API surface may change before stabilizing.\n *\n * @param cls The Agent subclass used when creating the child\n * @param name Name of the child to abort\n * @param reason Error thrown to pending/future RPC callers\n */\n abortSubAgent(cls: SubAgentClass, name: string, reason?: unknown): void {\n const ctx = this.ctx as unknown as Partial<FacetCapableCtx>;\n if (!ctx.facets) {\n throw new Error(\n \"abortSubAgent() is not supported in this runtime — \" +\n \"`ctx.facets` is unavailable. \" +\n \"Update to the latest `compatibility_date` in your wrangler.jsonc.\"\n );\n }\n const facetKey = `${cls.name}\\0${name}`;\n ctx.facets.abort(facetKey, reason);\n }\n\n /**\n * Delete a sub-agent: abort it if running, then permanently wipe its\n * storage. Transitively deletes the child's own children.\n *\n * @experimental The API surface may change before stabilizing.\n *\n * @param cls The Agent subclass used when creating the child\n * @param name Name of the child to delete\n */\n async deleteSubAgent(cls: SubAgentClass, name: string): Promise<void> {\n const ctx = this.ctx as unknown as Partial<FacetCapableCtx>;\n if (!ctx.facets) {\n throw new Error(\n \"deleteSubAgent() is not supported in this runtime — \" +\n \"`ctx.facets` is unavailable. \" +\n \"Update to the latest `compatibility_date` in your wrangler.jsonc.\"\n );\n }\n const facetKey = `${cls.name}\\0${name}`;\n const childPath = [...this.selfPath, { className: cls.name, name }];\n if (this._isFacet) {\n const root = await this._rootAlarmOwner();\n await root._cf_cleanupFacetPrefix(childPath);\n } else {\n await this._cf_cleanupFacetPrefix(childPath);\n }\n\n // Idempotent: make `ctx.facets.delete` tolerant of missing keys.\n // workerd throws an opaque \"internal error\" when the key isn't\n // registered; swallow that so double-delete and\n // delete-never-spawned both succeed silently. The registry DELETE\n // is already idempotent.\n try {\n ctx.facets.delete(facetKey);\n } catch {\n // no-op — facet wasn't registered (already deleted / never spawned)\n }\n this._forgetSubAgent(cls.name, name);\n }\n\n // ── Sub-agent registry (backs `hasSubAgent` / `listSubAgents`) ──────────\n\n /** @internal */\n private _subAgentRegistryReady = false;\n\n /** @internal */\n private _ensureSubAgentRegistry(): void {\n if (this._subAgentRegistryReady) return;\n this.sql`\n CREATE TABLE IF NOT EXISTS cf_agents_sub_agents (\n class TEXT NOT NULL,\n name TEXT NOT NULL,\n created_at INTEGER NOT NULL,\n PRIMARY KEY (class, name)\n )\n `;\n this._subAgentRegistryReady = true;\n }\n\n /** @internal */\n private _recordSubAgent(className: string, name: string): void {\n this._ensureSubAgentRegistry();\n this.sql`\n INSERT OR IGNORE INTO cf_agents_sub_agents (class, name, created_at)\n VALUES (${className}, ${name}, ${Date.now()})\n `;\n }\n\n /** @internal */\n private _forgetSubAgent(className: string, name: string): void {\n this._ensureSubAgentRegistry();\n this.sql`\n DELETE FROM cf_agents_sub_agents\n WHERE class = ${className} AND name = ${name}\n `;\n }\n\n /**\n * Whether this agent has previously spawned (and not deleted) a\n * sub-agent of the given class and name. Backed by an\n * auto-maintained SQLite registry in the parent's storage.\n *\n * Intended for strict-registry access patterns in\n * `onBeforeSubAgent` or similar gating logic.\n *\n * @experimental The API surface may change before stabilizing.\n *\n * @example\n * ```ts\n * async onBeforeSubAgent(req, { className, name }) {\n * if (!this.hasSubAgent(className, name)) {\n * return new Response(\"Not found\", { status: 404 });\n * }\n * }\n * ```\n */\n hasSubAgent<T extends Agent>(cls: SubAgentClass<T>, name: string): boolean;\n hasSubAgent(className: string, name: string): boolean;\n hasSubAgent(classOrName: SubAgentClass | string, name: string): boolean {\n const className =\n typeof classOrName === \"string\" ? classOrName : classOrName.name;\n this._ensureSubAgentRegistry();\n const rows = this.sql<{ n: number }>`\n SELECT COUNT(*) AS n FROM cf_agents_sub_agents\n WHERE class = ${className} AND name = ${name}\n `;\n return (rows[0]?.n ?? 0) > 0;\n }\n\n /**\n * List known sub-agents, optionally filtered by class. Reflects\n * the registry rows written by {@link subAgent} and removed by\n * {@link deleteSubAgent}.\n *\n * @experimental The API surface may change before stabilizing.\n */\n listSubAgents<T extends Agent>(\n cls: SubAgentClass<T>\n ): Array<{ className: string; name: string; createdAt: number }>;\n listSubAgents(\n className?: string\n ): Array<{ className: string; name: string; createdAt: number }>;\n listSubAgents(\n classOrName?: SubAgentClass | string\n ): Array<{ className: string; name: string; createdAt: number }> {\n const className =\n typeof classOrName === \"string\" ? classOrName : classOrName?.name;\n this._ensureSubAgentRegistry();\n const rows = className\n ? this.sql<{ class: string; name: string; created_at: number }>`\n SELECT class, name, created_at FROM cf_agents_sub_agents\n WHERE class = ${className}\n ORDER BY created_at ASC\n `\n : this.sql<{ class: string; name: string; created_at: number }>`\n SELECT class, name, created_at FROM cf_agents_sub_agents\n ORDER BY created_at ASC\n `;\n return rows.map((r) => ({\n className: r.class,\n name: r.name,\n createdAt: r.created_at\n }));\n }\n\n /**\n * Destroy the Agent, removing all state and scheduled tasks.\n *\n * On a top-level agent: drops every table, clears the alarm, and\n * aborts the isolate.\n *\n * On a sub-agent (facet): delegates teardown to the immediate\n * parent so the parent-owned schedule rows for this sub-agent\n * (and any of its descendants) are cancelled, the parent's\n * `cf_agents_sub_agents` registry entry is cleared, and\n * `ctx.facets.delete` wipes the facet's own storage. The\n * `ctx.facets.delete` call aborts this isolate, so this method\n * may not return cleanly when invoked from inside the facet —\n * callers should treat it as fire-and-forget.\n */\n async destroy() {\n if (this._isFacet) {\n this._emit(\"destroy\");\n const root = await this._rootAlarmOwner();\n // The chain: root → … → direct-parent runs ctx.facets.delete\n // on this facet, which aborts this isolate. The await may\n // throw an abort error or never resolve depending on timing —\n // either is acceptable, the cleanup has already been applied.\n await root._cf_destroyDescendantFacet(this.selfPath);\n return;\n }\n\n this._dropInternalTablesForDestroy();\n\n // delete all alarms\n await this.ctx.storage.deleteAlarm();\n await this.ctx.storage.deleteAll();\n\n this._disposables.dispose();\n await this.mcp.dispose();\n\n this._destroyed = true;\n\n // `ctx.abort` throws an uncatchable error, so we yield to the event loop\n // to avoid capturing it and let handlers finish cleaning up\n setTimeout(() => {\n this.ctx.abort(\"destroyed\");\n }, 0);\n\n this._emit(\"destroy\");\n }\n\n /** @internal Drop every internal Agents SDK table during top-level destroy. */\n protected _dropInternalTablesForDestroy(): void {\n this.sql`DROP TABLE IF EXISTS cf_agents_mcp_servers`;\n this.sql`DROP TABLE IF EXISTS cf_agents_state`;\n this.sql`DROP TABLE IF EXISTS cf_agents_schedules`;\n this.sql`DROP TABLE IF EXISTS cf_agents_queues`;\n this.sql`DROP TABLE IF EXISTS cf_agents_workflows`;\n this.sql`DROP TABLE IF EXISTS cf_agents_sub_agents`;\n this.sql`DROP TABLE IF EXISTS cf_agents_runs`;\n this.sql`DROP TABLE IF EXISTS cf_agents_facet_runs`;\n this.sql`DROP TABLE IF EXISTS cf_agent_tool_runs`;\n }\n\n /**\n * Check if a method is callable\n * @param method The method name to check\n * @returns True if the method is marked as callable\n */\n private _isCallable(method: string): boolean {\n return callableMetadata.has(this[method as keyof this] as Function);\n }\n\n /**\n * Get all methods marked as callable on this Agent\n * @returns A map of method names to their metadata\n */\n getCallableMethods(): Map<string, CallableMetadata> {\n const result = new Map<string, CallableMetadata>();\n\n // Walk the entire prototype chain to find callable methods from parent classes\n let prototype = Object.getPrototypeOf(this);\n while (prototype && prototype !== Object.prototype) {\n for (const name of Object.getOwnPropertyNames(prototype)) {\n if (name === \"constructor\") continue;\n // Don't override child class methods (first one wins)\n if (result.has(name)) continue;\n\n try {\n const fn = prototype[name];\n if (typeof fn === \"function\") {\n const meta = callableMetadata.get(fn as Function);\n if (meta) {\n result.set(name, meta);\n }\n }\n } catch (e) {\n if (!(e instanceof TypeError)) {\n throw e;\n }\n }\n }\n prototype = Object.getPrototypeOf(prototype);\n }\n\n return result;\n }\n\n // ==========================================\n // Workflow Integration Methods\n // ==========================================\n\n /**\n * Start a workflow and track it in this Agent's database.\n * Automatically injects agent identity into the workflow params.\n *\n * @template P - Type of params to pass to the workflow\n * @param workflowName - Name of the workflow binding in env (e.g., 'MY_WORKFLOW')\n * @param params - Params to pass to the workflow\n * @param options - Optional workflow options\n * @returns The workflow instance ID\n *\n * @example\n * ```typescript\n * const workflowId = await this.runWorkflow(\n * 'MY_WORKFLOW',\n * { taskId: '123', data: 'process this' }\n * );\n * ```\n */\n async runWorkflow<P = unknown>(\n workflowName: WorkflowName<Env>,\n params: P,\n options?: RunWorkflowOptions\n ): Promise<string> {\n // Look up the workflow binding by name\n const workflow = this._findWorkflowBindingByName(workflowName);\n if (!workflow) {\n throw new Error(\n `Workflow binding '${workflowName}' not found in environment`\n );\n }\n\n // Find the binding name for this Agent's namespace\n const agentBindingName =\n options?.agentBinding ?? this._findAgentBindingName();\n if (!agentBindingName) {\n throw new Error(\n \"Could not detect Agent binding name from class name. \" +\n \"Pass it explicitly via options.agentBinding\"\n );\n }\n\n // Generate workflow ID if not provided\n const workflowId = options?.id ?? nanoid();\n\n // Inject agent identity and workflow name into params\n const augmentedParams = {\n ...params,\n __agentName: this.name,\n __agentBinding: agentBindingName,\n __workflowName: workflowName\n };\n\n // Create the workflow instance\n const instance = await workflow.create({\n id: workflowId,\n params: augmentedParams\n });\n\n // Track the workflow in our database\n const id = nanoid();\n const metadataJson = options?.metadata\n ? JSON.stringify(options.metadata)\n : null;\n try {\n this.sql`\n INSERT INTO cf_agents_workflows (id, workflow_id, workflow_name, status, metadata)\n VALUES (${id}, ${instance.id}, ${workflowName}, 'queued', ${metadataJson})\n `;\n } catch (e) {\n if (\n e instanceof Error &&\n e.message.includes(\"UNIQUE constraint failed\")\n ) {\n throw new Error(\n `Workflow with ID \"${workflowId}\" is already being tracked`\n );\n }\n throw e;\n }\n\n this._emit(\"workflow:start\", { workflowId: instance.id, workflowName });\n\n return instance.id;\n }\n\n /**\n * Send an event to a running workflow.\n * The workflow can wait for this event using step.waitForEvent().\n *\n * @param workflowName - Name of the workflow binding in env (e.g., 'MY_WORKFLOW')\n * @param workflowId - ID of the workflow instance\n * @param event - Event to send\n *\n * @example\n * ```typescript\n * await this.sendWorkflowEvent(\n * 'MY_WORKFLOW',\n * workflowId,\n * { type: 'approval', payload: { approved: true } }\n * );\n * ```\n */\n async sendWorkflowEvent(\n workflowName: WorkflowName<Env>,\n workflowId: string,\n event: WorkflowEventPayload\n ): Promise<void> {\n const workflow = this._findWorkflowBindingByName(workflowName);\n if (!workflow) {\n throw new Error(\n `Workflow binding '${workflowName}' not found in environment`\n );\n }\n\n const instance = await workflow.get(workflowId);\n await tryN(3, async () => instance.sendEvent(event), {\n shouldRetry: isErrorRetryable,\n baseDelayMs: 200,\n maxDelayMs: 3000\n });\n\n this._emit(\"workflow:event\", { workflowId, eventType: event.type });\n }\n\n /**\n * Approve a waiting workflow.\n * Sends an approval event to the workflow that can be received by waitForApproval().\n *\n * @param workflowId - ID of the workflow to approve\n * @param data - Optional approval data (reason, metadata)\n *\n * @example\n * ```typescript\n * await this.approveWorkflow(workflowId, {\n * reason: 'Approved by admin',\n * metadata: { approvedBy: userId }\n * });\n * ```\n */\n async approveWorkflow(\n workflowId: string,\n data?: { reason?: string; metadata?: Record<string, unknown> }\n ): Promise<void> {\n const workflowInfo = this.getWorkflow(workflowId);\n if (!workflowInfo) {\n throw new Error(`Workflow ${workflowId} not found in tracking table`);\n }\n\n await this.sendWorkflowEvent(\n workflowInfo.workflowName as WorkflowName<Env>,\n workflowId,\n {\n type: \"approval\",\n payload: {\n approved: true,\n reason: data?.reason,\n metadata: data?.metadata\n }\n }\n );\n\n this._emit(\"workflow:approved\", { workflowId, reason: data?.reason });\n }\n\n /**\n * Reject a waiting workflow.\n * Sends a rejection event to the workflow that will cause waitForApproval() to throw.\n *\n * @param workflowId - ID of the workflow to reject\n * @param data - Optional rejection data (reason)\n *\n * @example\n * ```typescript\n * await this.rejectWorkflow(workflowId, {\n * reason: 'Request denied by admin'\n * });\n * ```\n */\n async rejectWorkflow(\n workflowId: string,\n data?: { reason?: string }\n ): Promise<void> {\n const workflowInfo = this.getWorkflow(workflowId);\n if (!workflowInfo) {\n throw new Error(`Workflow ${workflowId} not found in tracking table`);\n }\n\n await this.sendWorkflowEvent(\n workflowInfo.workflowName as WorkflowName<Env>,\n workflowId,\n {\n type: \"approval\",\n payload: {\n approved: false,\n reason: data?.reason\n }\n }\n );\n\n this._emit(\"workflow:rejected\", { workflowId, reason: data?.reason });\n }\n\n /**\n * Terminate a running workflow.\n * This immediately stops the workflow and sets its status to \"terminated\".\n *\n * @param workflowId - ID of the workflow to terminate (must be tracked via runWorkflow)\n * @throws Error if workflow not found in tracking table\n * @throws Error if workflow binding not found in environment\n * @throws Error if workflow is already completed/errored/terminated (from Cloudflare)\n *\n * @example\n * ```typescript\n * await this.terminateWorkflow(workflowId);\n * ```\n */\n async terminateWorkflow(workflowId: string): Promise<void> {\n const workflowInfo = this.getWorkflow(workflowId);\n if (!workflowInfo) {\n throw new Error(`Workflow ${workflowId} not found in tracking table`);\n }\n\n const workflow = this._findWorkflowBindingByName(\n workflowInfo.workflowName as WorkflowName<Env>\n );\n if (!workflow) {\n throw new Error(\n `Workflow binding '${workflowInfo.workflowName}' not found in environment`\n );\n }\n\n const instance = await workflow.get(workflowId);\n await tryN(3, async () => instance.terminate(), {\n shouldRetry: isErrorRetryable,\n baseDelayMs: 200,\n maxDelayMs: 3000\n });\n\n // Update tracking table with new status\n const status = await instance.status();\n this._updateWorkflowTracking(workflowId, status);\n\n this._emit(\"workflow:terminated\", {\n workflowId,\n workflowName: workflowInfo.workflowName\n });\n }\n\n /**\n * Pause a running workflow.\n * The workflow can be resumed later with resumeWorkflow().\n *\n * @param workflowId - ID of the workflow to pause (must be tracked via runWorkflow)\n * @throws Error if workflow not found in tracking table\n * @throws Error if workflow binding not found in environment\n * @throws Error if workflow is not running (from Cloudflare)\n *\n * @example\n * ```typescript\n * await this.pauseWorkflow(workflowId);\n * ```\n */\n async pauseWorkflow(workflowId: string): Promise<void> {\n const workflowInfo = this.getWorkflow(workflowId);\n if (!workflowInfo) {\n throw new Error(`Workflow ${workflowId} not found in tracking table`);\n }\n\n const workflow = this._findWorkflowBindingByName(\n workflowInfo.workflowName as WorkflowName<Env>\n );\n if (!workflow) {\n throw new Error(\n `Workflow binding '${workflowInfo.workflowName}' not found in environment`\n );\n }\n\n const instance = await workflow.get(workflowId);\n await tryN(3, async () => instance.pause(), {\n shouldRetry: isErrorRetryable,\n baseDelayMs: 200,\n maxDelayMs: 3000\n });\n\n const status = await instance.status();\n this._updateWorkflowTracking(workflowId, status);\n\n this._emit(\"workflow:paused\", {\n workflowId,\n workflowName: workflowInfo.workflowName\n });\n }\n\n /**\n * Resume a paused workflow.\n *\n * @param workflowId - ID of the workflow to resume (must be tracked via runWorkflow)\n * @throws Error if workflow not found in tracking table\n * @throws Error if workflow binding not found in environment\n * @throws Error if workflow is not paused (from Cloudflare)\n *\n * @example\n * ```typescript\n * await this.resumeWorkflow(workflowId);\n * ```\n */\n async resumeWorkflow(workflowId: string): Promise<void> {\n const workflowInfo = this.getWorkflow(workflowId);\n if (!workflowInfo) {\n throw new Error(`Workflow ${workflowId} not found in tracking table`);\n }\n\n const workflow = this._findWorkflowBindingByName(\n workflowInfo.workflowName as WorkflowName<Env>\n );\n if (!workflow) {\n throw new Error(\n `Workflow binding '${workflowInfo.workflowName}' not found in environment`\n );\n }\n\n const instance = await workflow.get(workflowId);\n await tryN(3, async () => instance.resume(), {\n shouldRetry: isErrorRetryable,\n baseDelayMs: 200,\n maxDelayMs: 3000\n });\n\n const status = await instance.status();\n this._updateWorkflowTracking(workflowId, status);\n\n this._emit(\"workflow:resumed\", {\n workflowId,\n workflowName: workflowInfo.workflowName\n });\n }\n\n /**\n * Restart a workflow instance.\n * This re-runs the workflow from the beginning with the same ID.\n *\n * @param workflowId - ID of the workflow to restart (must be tracked via runWorkflow)\n * @param options - Optional settings\n * @param options.resetTracking - If true (default), resets created_at and clears error fields.\n * If false, preserves original timestamps.\n * @throws Error if workflow not found in tracking table\n * @throws Error if workflow binding not found in environment\n *\n * @example\n * ```typescript\n * // Reset tracking (default)\n * await this.restartWorkflow(workflowId);\n *\n * // Preserve original timestamps\n * await this.restartWorkflow(workflowId, { resetTracking: false });\n * ```\n */\n async restartWorkflow(\n workflowId: string,\n options: { resetTracking?: boolean } = {}\n ): Promise<void> {\n const { resetTracking = true } = options;\n\n const workflowInfo = this.getWorkflow(workflowId);\n if (!workflowInfo) {\n throw new Error(`Workflow ${workflowId} not found in tracking table`);\n }\n\n const workflow = this._findWorkflowBindingByName(\n workflowInfo.workflowName as WorkflowName<Env>\n );\n if (!workflow) {\n throw new Error(\n `Workflow binding '${workflowInfo.workflowName}' not found in environment`\n );\n }\n\n const instance = await workflow.get(workflowId);\n await tryN(3, async () => instance.restart(), {\n shouldRetry: isErrorRetryable,\n baseDelayMs: 200,\n maxDelayMs: 3000\n });\n\n if (resetTracking) {\n // Reset tracking fields for fresh start\n const now = Math.floor(Date.now() / 1000);\n this.sql`\n UPDATE cf_agents_workflows\n SET status = 'queued',\n created_at = ${now},\n updated_at = ${now},\n completed_at = NULL,\n error_name = NULL,\n error_message = NULL\n WHERE workflow_id = ${workflowId}\n `;\n } else {\n // Just update status from Cloudflare\n const status = await instance.status();\n this._updateWorkflowTracking(workflowId, status);\n }\n\n this._emit(\"workflow:restarted\", {\n workflowId,\n workflowName: workflowInfo.workflowName\n });\n }\n\n /**\n * Find a workflow binding by its name.\n */\n private _findWorkflowBindingByName(\n workflowName: string\n ): Workflow | undefined {\n const binding = (this.env as Record<string, unknown>)[workflowName];\n if (\n binding &&\n typeof binding === \"object\" &&\n \"create\" in binding &&\n \"get\" in binding\n ) {\n return binding as Workflow;\n }\n return undefined;\n }\n\n /**\n * Get all workflow binding names from the environment.\n */\n private _getWorkflowBindingNames(): string[] {\n const names: string[] = [];\n for (const [key, value] of Object.entries(\n this.env as Record<string, unknown>\n )) {\n if (\n value &&\n typeof value === \"object\" &&\n \"create\" in value &&\n \"get\" in value\n ) {\n names.push(key);\n }\n }\n return names;\n }\n\n /**\n * Get the status of a workflow and update the tracking record.\n *\n * @param workflowName - Name of the workflow binding in env (e.g., 'MY_WORKFLOW')\n * @param workflowId - ID of the workflow instance\n * @returns The workflow status\n */\n async getWorkflowStatus(\n workflowName: WorkflowName<Env>,\n workflowId: string\n ): Promise<InstanceStatus> {\n const workflow = this._findWorkflowBindingByName(workflowName);\n if (!workflow) {\n throw new Error(\n `Workflow binding '${workflowName}' not found in environment`\n );\n }\n\n const instance = await workflow.get(workflowId);\n const status = await instance.status();\n\n // Update the tracking record\n this._updateWorkflowTracking(workflowId, status);\n\n return status;\n }\n\n /**\n * Get a tracked workflow by ID.\n *\n * @param workflowId - Workflow instance ID\n * @returns Workflow info or undefined if not found\n */\n getWorkflow(workflowId: string): WorkflowInfo | undefined {\n const rows = this.sql<WorkflowTrackingRow>`\n SELECT * FROM cf_agents_workflows WHERE workflow_id = ${workflowId}\n `;\n\n if (!rows || rows.length === 0) {\n return undefined;\n }\n\n return this._rowToWorkflowInfo(rows[0]);\n }\n\n /**\n * Query tracked workflows with cursor-based pagination.\n *\n * @param criteria - Query criteria including optional cursor for pagination\n * @returns WorkflowPage with workflows, total count, and next cursor\n *\n * @example\n * ```typescript\n * // First page\n * const page1 = this.getWorkflows({ status: 'running', limit: 20 });\n *\n * // Next page\n * if (page1.nextCursor) {\n * const page2 = this.getWorkflows({\n * status: 'running',\n * limit: 20,\n * cursor: page1.nextCursor\n * });\n * }\n * ```\n */\n getWorkflows(criteria: WorkflowQueryCriteria = {}): WorkflowPage {\n const limit = Math.min(criteria.limit ?? 50, 100);\n const isAsc = criteria.orderBy === \"asc\";\n\n // Get total count (ignores cursor and limit)\n const total = this._countWorkflows(criteria);\n\n // Build base query\n let query = \"SELECT * FROM cf_agents_workflows WHERE 1=1\";\n const params: (string | number | boolean)[] = [];\n\n if (criteria.status) {\n const statuses = Array.isArray(criteria.status)\n ? criteria.status\n : [criteria.status];\n const placeholders = statuses.map(() => \"?\").join(\", \");\n query += ` AND status IN (${placeholders})`;\n params.push(...statuses);\n }\n\n if (criteria.workflowName) {\n query += \" AND workflow_name = ?\";\n params.push(criteria.workflowName);\n }\n\n if (criteria.metadata) {\n for (const [key, value] of Object.entries(criteria.metadata)) {\n query += ` AND json_extract(metadata, '$.' || ?) = ?`;\n params.push(key, value);\n }\n }\n\n // Apply cursor for keyset pagination\n if (criteria.cursor) {\n const cursor = this._decodeCursor(criteria.cursor);\n if (isAsc) {\n // ASC: get items after cursor\n query +=\n \" AND (created_at > ? OR (created_at = ? AND workflow_id > ?))\";\n } else {\n // DESC: get items before cursor\n query +=\n \" AND (created_at < ? OR (created_at = ? AND workflow_id < ?))\";\n }\n params.push(cursor.createdAt, cursor.createdAt, cursor.workflowId);\n }\n\n // Order by created_at and workflow_id for consistent keyset pagination\n query += ` ORDER BY created_at ${isAsc ? \"ASC\" : \"DESC\"}, workflow_id ${isAsc ? \"ASC\" : \"DESC\"}`;\n\n // Fetch limit + 1 to detect if there are more pages\n query += \" LIMIT ?\";\n params.push(limit + 1);\n\n const rows = this.ctx.storage.sql\n .exec(query, ...params)\n .toArray() as WorkflowTrackingRow[];\n\n const hasMore = rows.length > limit;\n const resultRows = hasMore ? rows.slice(0, limit) : rows;\n const workflows = resultRows.map((row) => this._rowToWorkflowInfo(row));\n\n // Build next cursor from last item\n const nextCursor =\n hasMore && workflows.length > 0\n ? this._encodeCursor(workflows[workflows.length - 1])\n : null;\n\n return { workflows, total, nextCursor };\n }\n\n /**\n * Count workflows matching criteria (for pagination total).\n */\n private _countWorkflows(\n criteria: Omit<WorkflowQueryCriteria, \"limit\" | \"cursor\" | \"orderBy\"> & {\n createdBefore?: Date;\n }\n ): number {\n let query = \"SELECT COUNT(*) as count FROM cf_agents_workflows WHERE 1=1\";\n const params: (string | number | boolean)[] = [];\n\n if (criteria.status) {\n const statuses = Array.isArray(criteria.status)\n ? criteria.status\n : [criteria.status];\n const placeholders = statuses.map(() => \"?\").join(\", \");\n query += ` AND status IN (${placeholders})`;\n params.push(...statuses);\n }\n\n if (criteria.workflowName) {\n query += \" AND workflow_name = ?\";\n params.push(criteria.workflowName);\n }\n\n if (criteria.metadata) {\n for (const [key, value] of Object.entries(criteria.metadata)) {\n query += ` AND json_extract(metadata, '$.' || ?) = ?`;\n params.push(key, value);\n }\n }\n\n if (criteria.createdBefore) {\n query += \" AND created_at < ?\";\n params.push(Math.floor(criteria.createdBefore.getTime() / 1000));\n }\n\n const result = this.ctx.storage.sql.exec(query, ...params).toArray() as {\n count: number;\n }[];\n\n return result[0]?.count ?? 0;\n }\n\n /**\n * Encode a cursor from workflow info for pagination.\n * Stores createdAt as Unix timestamp in seconds (matching DB storage).\n */\n private _encodeCursor(workflow: WorkflowInfo): string {\n return btoa(\n JSON.stringify({\n c: Math.floor(workflow.createdAt.getTime() / 1000),\n i: workflow.workflowId\n })\n );\n }\n\n /**\n * Decode a pagination cursor.\n * Returns createdAt as Unix timestamp in seconds (matching DB storage).\n */\n private _decodeCursor(cursor: string): {\n createdAt: number;\n workflowId: string;\n } {\n try {\n const data = JSON.parse(atob(cursor));\n if (typeof data.c !== \"number\" || typeof data.i !== \"string\") {\n throw new Error(\"Invalid cursor structure\");\n }\n return { createdAt: data.c, workflowId: data.i };\n } catch {\n throw new Error(\n \"Invalid pagination cursor. The cursor may be malformed or corrupted.\"\n );\n }\n }\n\n /**\n * Delete a workflow tracking record.\n *\n * @param workflowId - ID of the workflow to delete\n * @returns true if a record was deleted, false if not found\n */\n deleteWorkflow(workflowId: string): boolean {\n // First check if workflow exists\n const existing = this.sql<{ count: number }>`\n SELECT COUNT(*) as count FROM cf_agents_workflows WHERE workflow_id = ${workflowId}\n `;\n if (!existing[0] || existing[0].count === 0) {\n return false;\n }\n this.sql`DELETE FROM cf_agents_workflows WHERE workflow_id = ${workflowId}`;\n return true;\n }\n\n /**\n * Delete workflow tracking records matching criteria.\n * Useful for cleaning up old completed/errored workflows.\n *\n * @param criteria - Criteria for which workflows to delete\n * @returns Number of records matching criteria (expected deleted count)\n *\n * @example\n * ```typescript\n * // Delete all completed workflows created more than 7 days ago\n * const deleted = this.deleteWorkflows({\n * status: 'complete',\n * createdBefore: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000)\n * });\n *\n * // Delete all errored and terminated workflows\n * const deleted = this.deleteWorkflows({\n * status: ['errored', 'terminated']\n * });\n * ```\n */\n deleteWorkflows(\n criteria: Omit<WorkflowQueryCriteria, \"limit\" | \"orderBy\"> & {\n createdBefore?: Date;\n } = {}\n ): number {\n let query = \"DELETE FROM cf_agents_workflows WHERE 1=1\";\n const params: (string | number | boolean)[] = [];\n\n if (criteria.status) {\n const statuses = Array.isArray(criteria.status)\n ? criteria.status\n : [criteria.status];\n const placeholders = statuses.map(() => \"?\").join(\", \");\n query += ` AND status IN (${placeholders})`;\n params.push(...statuses);\n }\n\n if (criteria.workflowName) {\n query += \" AND workflow_name = ?\";\n params.push(criteria.workflowName);\n }\n\n if (criteria.metadata) {\n for (const [key, value] of Object.entries(criteria.metadata)) {\n query += ` AND json_extract(metadata, '$.' || ?) = ?`;\n params.push(key, value);\n }\n }\n\n if (criteria.createdBefore) {\n query += \" AND created_at < ?\";\n params.push(Math.floor(criteria.createdBefore.getTime() / 1000));\n }\n\n const cursor = this.ctx.storage.sql.exec(query, ...params);\n return cursor.rowsWritten;\n }\n\n /**\n * Migrate workflow tracking records from an old binding name to a new one.\n * Use this after renaming a workflow binding in wrangler.toml.\n *\n * @param oldName - Previous workflow binding name\n * @param newName - New workflow binding name\n * @returns Number of records migrated\n *\n * @example\n * ```typescript\n * // After renaming OLD_WORKFLOW to NEW_WORKFLOW in wrangler.toml\n * async onStart() {\n * const migrated = this.migrateWorkflowBinding('OLD_WORKFLOW', 'NEW_WORKFLOW');\n * }\n * ```\n */\n migrateWorkflowBinding(oldName: string, newName: string): number {\n // Validate new binding exists\n if (!this._findWorkflowBindingByName(newName)) {\n throw new Error(`Workflow binding '${newName}' not found in environment`);\n }\n\n const result = this.sql<{ count: number }>`\n SELECT COUNT(*) as count FROM cf_agents_workflows WHERE workflow_name = ${oldName}\n `;\n const count = result[0]?.count ?? 0;\n\n if (count > 0) {\n this\n .sql`UPDATE cf_agents_workflows SET workflow_name = ${newName} WHERE workflow_name = ${oldName}`;\n console.log(\n `[Agent] Migrated ${count} workflow(s) from '${oldName}' to '${newName}'`\n );\n }\n\n return count;\n }\n\n /**\n * Update workflow tracking record from InstanceStatus\n */\n private _updateWorkflowTracking(\n workflowId: string,\n status: InstanceStatus\n ): void {\n const statusName = status.status;\n const now = Math.floor(Date.now() / 1000);\n\n // Determine if workflow is complete\n const completedStatuses: WorkflowStatus[] = [\n \"complete\",\n \"errored\",\n \"terminated\"\n ];\n const completedAt = completedStatuses.includes(statusName) ? now : null;\n\n // Extract error info if present\n const errorName = status.error?.name ?? null;\n const errorMessage = status.error?.message ?? null;\n\n this.sql`\n UPDATE cf_agents_workflows\n SET status = ${statusName},\n error_name = ${errorName},\n error_message = ${errorMessage},\n updated_at = ${now},\n completed_at = ${completedAt}\n WHERE workflow_id = ${workflowId}\n `;\n }\n\n /**\n * Convert a database row to WorkflowInfo\n */\n private _rowToWorkflowInfo(row: WorkflowTrackingRow): WorkflowInfo {\n return {\n id: row.id,\n workflowId: row.workflow_id,\n workflowName: row.workflow_name,\n status: row.status,\n metadata: row.metadata ? JSON.parse(row.metadata) : null,\n error: row.error_name\n ? { name: row.error_name, message: row.error_message ?? \"\" }\n : null,\n createdAt: new Date(row.created_at * 1000),\n updatedAt: new Date(row.updated_at * 1000),\n completedAt: row.completed_at ? new Date(row.completed_at * 1000) : null\n };\n }\n\n /**\n * Find the binding name for this Agent's namespace by matching class name.\n * Returns undefined if no match found - use options.agentBinding as fallback.\n */\n private _findAgentBindingName(): string | undefined {\n const className = this._ParentClass.name;\n for (const [key, value] of Object.entries(\n this.env as Record<string, unknown>\n )) {\n if (\n value &&\n typeof value === \"object\" &&\n \"idFromName\" in value &&\n typeof value.idFromName === \"function\"\n ) {\n // Check if this namespace's binding name matches our class name\n if (\n key === className ||\n camelCaseToKebabCase(key) === camelCaseToKebabCase(className)\n ) {\n return key;\n }\n }\n }\n return undefined;\n }\n\n private _findBindingNameForNamespace(\n namespace: DurableObjectNamespace<McpAgent>\n ): string | undefined {\n for (const [key, value] of Object.entries(\n this.env as Record<string, unknown>\n )) {\n if (value === namespace) {\n return key;\n }\n }\n return undefined;\n }\n\n private async _restoreRpcMcpServers(): Promise<void> {\n const rpcServers = this.mcp.getRpcServersFromStorage();\n for (const server of rpcServers) {\n if (this.mcp.mcpConnections[server.id]) {\n continue;\n }\n\n const opts: { bindingName: string; props?: Record<string, unknown> } =\n server.server_options ? JSON.parse(server.server_options) : {};\n\n const namespace = (this.env as Record<string, unknown>)[\n opts.bindingName\n ] as DurableObjectNamespace<McpAgent> | undefined;\n if (!namespace) {\n console.warn(\n `[Agent] Cannot restore RPC MCP server \"${server.name}\": binding \"${opts.bindingName}\" not found in env`\n );\n continue;\n }\n\n const normalizedName = server.server_url.replace(RPC_DO_PREFIX, \"\");\n\n try {\n await this.mcp.connect(`${RPC_DO_PREFIX}${normalizedName}`, {\n reconnect: { id: server.id },\n transport: {\n type: \"rpc\" as TransportType,\n namespace,\n name: normalizedName,\n props: opts.props\n }\n });\n\n const conn = this.mcp.mcpConnections[server.id];\n if (conn && conn.connectionState === MCPConnectionState.CONNECTED) {\n await this.mcp.discoverIfConnected(server.id);\n }\n } catch (error) {\n console.error(\n `[Agent] Error restoring RPC MCP server \"${server.name}\":`,\n error\n );\n }\n }\n }\n\n // ==========================================\n // Workflow Lifecycle Callbacks\n // ==========================================\n\n /**\n * Handle a callback from a workflow.\n * Called when the Agent receives a callback at /_workflow/callback.\n * Override this to handle all callback types in one place.\n *\n * @param callback - The callback payload\n */\n async onWorkflowCallback(callback: WorkflowCallback): Promise<void> {\n const now = Math.floor(Date.now() / 1000);\n\n switch (callback.type) {\n case \"progress\":\n // Update tracking status to \"running\" when receiving progress\n // Only transition from queued/waiting to avoid overwriting terminal states\n this.sql`\n UPDATE cf_agents_workflows\n SET status = 'running', updated_at = ${now}\n WHERE workflow_id = ${callback.workflowId} AND status IN ('queued', 'waiting')\n `;\n await this.onWorkflowProgress(\n callback.workflowName,\n callback.workflowId,\n callback.progress\n );\n break;\n case \"complete\":\n // Update tracking status to \"complete\"\n // Don't overwrite if already terminated/paused (race condition protection)\n this.sql`\n UPDATE cf_agents_workflows\n SET status = 'complete', updated_at = ${now}, completed_at = ${now}\n WHERE workflow_id = ${callback.workflowId}\n AND status NOT IN ('terminated', 'paused')\n `;\n await this.onWorkflowComplete(\n callback.workflowName,\n callback.workflowId,\n callback.result\n );\n break;\n case \"error\":\n // Update tracking status to \"errored\"\n // Don't overwrite if already terminated/paused (race condition protection)\n this.sql`\n UPDATE cf_agents_workflows\n SET status = 'errored', updated_at = ${now}, completed_at = ${now},\n error_name = 'WorkflowError', error_message = ${callback.error}\n WHERE workflow_id = ${callback.workflowId}\n AND status NOT IN ('terminated', 'paused')\n `;\n await this.onWorkflowError(\n callback.workflowName,\n callback.workflowId,\n callback.error\n );\n break;\n case \"event\":\n // No status change for events - they can occur at any stage\n await this.onWorkflowEvent(\n callback.workflowName,\n callback.workflowId,\n callback.event\n );\n break;\n }\n }\n\n /**\n * Called when a workflow reports progress.\n * Override to handle progress updates.\n *\n * @param workflowName - Workflow binding name\n * @param workflowId - ID of the workflow\n * @param progress - Typed progress data (default: DefaultProgress)\n */\n async onWorkflowProgress(\n // oxlint-disable-next-line no-unused-vars\n workflowName: string,\n // oxlint-disable-next-line no-unused-vars\n workflowId: string,\n // oxlint-disable-next-line no-unused-vars\n progress: unknown\n ): Promise<void> {\n // Override to handle progress updates\n }\n\n /**\n * Called when a workflow completes successfully.\n * Override to handle completion.\n *\n * @param workflowName - Workflow binding name\n * @param workflowId - ID of the workflow\n * @param result - Optional result data\n */\n async onWorkflowComplete(\n // oxlint-disable-next-line no-unused-vars\n workflowName: string,\n // oxlint-disable-next-line no-unused-vars\n workflowId: string,\n // oxlint-disable-next-line no-unused-vars\n result?: unknown\n ): Promise<void> {\n // Override to handle completion\n }\n\n /**\n * Called when a workflow encounters an error.\n * Override to handle errors.\n *\n * @param workflowName - Workflow binding name\n * @param workflowId - ID of the workflow\n * @param error - Error message\n */\n async onWorkflowError(\n workflowName: string,\n workflowId: string,\n error: string\n ): Promise<void> {\n console.error(\n `Workflow error [${workflowName}/${workflowId}]: ${error}\\n` +\n \"Override onWorkflowError() in your Agent to handle workflow errors.\"\n );\n }\n\n /**\n * Called when a workflow sends a custom event.\n * Override to handle custom events.\n *\n * @param workflowName - Workflow binding name\n * @param workflowId - ID of the workflow\n * @param event - Custom event payload\n */\n async onWorkflowEvent(\n // oxlint-disable-next-line no-unused-vars\n workflowName: string,\n // oxlint-disable-next-line no-unused-vars\n workflowId: string,\n // oxlint-disable-next-line no-unused-vars\n event: unknown\n ): Promise<void> {\n // Override to handle custom events\n }\n\n // ============================================================\n // Internal RPC methods for AgentWorkflow communication\n // These are called via DO RPC, not exposed via HTTP\n // ============================================================\n\n /**\n * Handle a workflow callback via RPC.\n * @internal - Called by AgentWorkflow, do not call directly\n */\n async _workflow_handleCallback(callback: WorkflowCallback): Promise<void> {\n await this.__unsafe_ensureInitialized();\n await this.onWorkflowCallback(callback);\n }\n\n /**\n * Broadcast a message to all connected clients via RPC.\n * @internal - Called by AgentWorkflow, do not call directly\n */\n async _workflow_broadcast(message: unknown): Promise<void> {\n await this.__unsafe_ensureInitialized();\n this.broadcast(JSON.stringify(message));\n }\n\n /**\n * Update agent state via RPC.\n * @internal - Called by AgentWorkflow, do not call directly\n */\n async _workflow_updateState(\n action: \"set\" | \"merge\" | \"reset\",\n state?: unknown\n ): Promise<void> {\n await this.__unsafe_ensureInitialized();\n if (action === \"set\") {\n this.setState(state as State);\n } else if (action === \"merge\") {\n const currentState = this.state ?? ({} as State);\n this.setState({\n ...currentState,\n ...(state as Record<string, unknown>)\n } as State);\n } else if (action === \"reset\") {\n this.setState(this.initialState);\n }\n }\n\n /**\n * Connect to a new MCP Server via RPC (Durable Object binding)\n *\n * The binding name and props are persisted to storage so the connection\n * is automatically restored after Durable Object hibernation.\n *\n * @example\n * await this.addMcpServer(\"counter\", env.MY_MCP);\n * await this.addMcpServer(\"counter\", env.MY_MCP, { props: { userId: \"123\" } });\n */\n async addMcpServer<T extends McpAgent>(\n serverName: string,\n binding: DurableObjectNamespace<T>,\n options?: AddRpcMcpServerOptions\n ): Promise<{ id: string; state: typeof MCPConnectionState.READY }>;\n\n /**\n * Connect to a new MCP Server via HTTP (SSE or Streamable HTTP)\n *\n * @example\n * await this.addMcpServer(\"github\", \"https://mcp.github.com\");\n * await this.addMcpServer(\"github\", \"https://mcp.github.com\", { transport: { type: \"sse\" } });\n * await this.addMcpServer(\"github\", url, callbackHost, agentsPrefix, options); // legacy\n */\n async addMcpServer(\n serverName: string,\n url: string,\n callbackHostOrOptions?: string | AddMcpServerOptions,\n agentsPrefix?: string,\n options?: {\n client?: ConstructorParameters<typeof Client>[1];\n transport?: { headers?: HeadersInit; type?: TransportType };\n }\n ): Promise<\n | {\n id: string;\n state: typeof MCPConnectionState.AUTHENTICATING;\n authUrl: string;\n }\n | { id: string; state: typeof MCPConnectionState.READY }\n >;\n\n async addMcpServer<T extends McpAgent>(\n serverName: string,\n urlOrBinding: string | DurableObjectNamespace<T>,\n callbackHostOrOptions?:\n | string\n | AddMcpServerOptions\n | AddRpcMcpServerOptions,\n agentsPrefix?: string,\n options?: {\n client?: ConstructorParameters<typeof Client>[1];\n transport?: {\n headers?: HeadersInit;\n type?: TransportType;\n };\n }\n ): Promise<\n | {\n id: string;\n state: typeof MCPConnectionState.AUTHENTICATING;\n authUrl: string;\n }\n | {\n id: string;\n state: typeof MCPConnectionState.READY;\n authUrl?: undefined;\n }\n > {\n const isHttpTransport = typeof urlOrBinding === \"string\";\n const normalizedUrl = isHttpTransport\n ? new URL(urlOrBinding).href\n : undefined;\n const existingServer = this.mcp\n .listServers()\n .find(\n (s) =>\n s.name === serverName &&\n (!isHttpTransport || new URL(s.server_url).href === normalizedUrl)\n );\n if (existingServer && this.mcp.mcpConnections[existingServer.id]) {\n const conn = this.mcp.mcpConnections[existingServer.id];\n if (\n conn.connectionState === MCPConnectionState.AUTHENTICATING &&\n conn.options.transport.authProvider?.authUrl\n ) {\n return {\n id: existingServer.id,\n state: MCPConnectionState.AUTHENTICATING,\n authUrl: conn.options.transport.authProvider.authUrl\n };\n }\n if (conn.connectionState === MCPConnectionState.FAILED) {\n throw new Error(\n `MCP server \"${serverName}\" is in failed state: ${conn.connectionError}`\n );\n }\n return { id: existingServer.id, state: MCPConnectionState.READY };\n }\n\n // RPC transport path: second argument is a DurableObjectNamespace\n if (typeof urlOrBinding !== \"string\") {\n const rpcOpts = callbackHostOrOptions as\n | AddRpcMcpServerOptions\n | undefined;\n\n const normalizedName = serverName.toLowerCase().replace(/\\s+/g, \"-\");\n\n const reconnectId = existingServer?.id;\n const { id } = await this.mcp.connect(\n `${RPC_DO_PREFIX}${normalizedName}`,\n {\n reconnect: reconnectId ? { id: reconnectId } : undefined,\n transport: {\n type: \"rpc\" as TransportType,\n namespace:\n urlOrBinding as unknown as DurableObjectNamespace<McpAgent>,\n name: normalizedName,\n props: rpcOpts?.props\n }\n }\n );\n\n const conn = this.mcp.mcpConnections[id];\n if (conn && conn.connectionState === MCPConnectionState.CONNECTED) {\n const discoverResult = await this.mcp.discoverIfConnected(id);\n if (discoverResult && !discoverResult.success) {\n throw new Error(\n `Failed to discover MCP server capabilities: ${discoverResult.error}`\n );\n }\n } else if (conn && conn.connectionState === MCPConnectionState.FAILED) {\n throw new Error(\n `Failed to connect to MCP server \"${serverName}\" via RPC: ${conn.connectionError}`\n );\n }\n\n const bindingName = this._findBindingNameForNamespace(\n urlOrBinding as unknown as DurableObjectNamespace<McpAgent>\n );\n if (bindingName) {\n this.mcp.saveRpcServerToStorage(\n id,\n serverName,\n normalizedName,\n bindingName,\n rpcOpts?.props\n );\n }\n\n return { id, state: MCPConnectionState.READY };\n }\n\n // HTTP transport path\n const httpOptions = callbackHostOrOptions as\n | string\n | AddMcpServerOptions\n | undefined;\n\n let resolvedCallbackHost: string | undefined;\n let resolvedAgentsPrefix: string;\n let resolvedOptions:\n | {\n client?: ConstructorParameters<typeof Client>[1];\n transport?: {\n headers?: HeadersInit;\n type?: TransportType;\n };\n retry?: RetryOptions;\n }\n | undefined;\n\n let resolvedCallbackPath: string | undefined;\n\n if (typeof httpOptions === \"object\" && httpOptions !== null) {\n resolvedCallbackHost = httpOptions.callbackHost;\n resolvedCallbackPath = httpOptions.callbackPath;\n resolvedAgentsPrefix = httpOptions.agentsPrefix ?? \"agents\";\n resolvedOptions = {\n client: httpOptions.client,\n transport: httpOptions.transport,\n retry: httpOptions.retry\n };\n } else {\n resolvedCallbackHost = httpOptions;\n resolvedAgentsPrefix = agentsPrefix ?? \"agents\";\n resolvedOptions = options;\n }\n\n // Enforce callbackPath when sendIdentityOnConnect is false and callbackHost is provided\n if (\n !this._resolvedOptions.sendIdentityOnConnect &&\n resolvedCallbackHost &&\n !resolvedCallbackPath\n ) {\n throw new Error(\n \"callbackPath is required in addMcpServer options when sendIdentityOnConnect is false — \" +\n \"the default callback URL would expose the instance name. \" +\n \"Provide a callbackPath and route the callback request to this agent via getAgentByName.\"\n );\n }\n\n // Try to derive callbackHost from the current request or connection URI\n if (!resolvedCallbackHost) {\n const { request, connection } = getCurrentAgent();\n if (request) {\n const requestUrl = new URL(request.url);\n resolvedCallbackHost = `${requestUrl.protocol}//${requestUrl.host}`;\n } else if (connection?.uri) {\n const connectionUrl = new URL(connection.uri);\n resolvedCallbackHost = `${connectionUrl.protocol}//${connectionUrl.host}`;\n }\n }\n\n // Build the callback URL if we have a host (needed for OAuth, optional for non-OAuth servers)\n let callbackUrl: string | undefined;\n if (resolvedCallbackHost) {\n const normalizedHost = resolvedCallbackHost.replace(/\\/$/, \"\");\n callbackUrl = resolvedCallbackPath\n ? `${normalizedHost}/${resolvedCallbackPath.replace(/^\\//, \"\")}`\n : `${normalizedHost}/${resolvedAgentsPrefix}/${camelCaseToKebabCase(this._ParentClass.name)}/${this.name}/callback`;\n }\n\n const id = nanoid(8);\n\n // Only create authProvider if we have a callbackUrl (needed for OAuth servers)\n let authProvider:\n | ReturnType<typeof this.createMcpOAuthProvider>\n | undefined;\n if (callbackUrl) {\n authProvider = this.createMcpOAuthProvider(callbackUrl);\n authProvider.serverId = id;\n }\n\n // Use the transport type specified in options, or default to \"auto\"\n const transportType: TransportType =\n resolvedOptions?.transport?.type ?? \"auto\";\n\n // allows passing through transport headers if necessary\n // this handles some non-standard bearer auth setups (i.e. MCP server behind CF access instead of OAuth)\n let headerTransportOpts: SSEClientTransportOptions = {};\n if (resolvedOptions?.transport?.headers) {\n headerTransportOpts = {\n eventSourceInit: {\n fetch: (url, init) =>\n fetch(url, {\n ...init,\n headers: resolvedOptions?.transport?.headers\n })\n },\n requestInit: {\n headers: resolvedOptions?.transport?.headers\n }\n };\n }\n\n // Register server (also saves to storage)\n await this.mcp.registerServer(id, {\n url: normalizedUrl!,\n name: serverName,\n callbackUrl,\n client: resolvedOptions?.client,\n transport: {\n ...headerTransportOpts,\n authProvider,\n type: transportType\n },\n retry: resolvedOptions?.retry\n });\n\n const result = await this.mcp.connectToServer(id);\n\n if (result.state === MCPConnectionState.FAILED) {\n // Server stays in storage so user can retry via connectToServer(id)\n throw new Error(\n `Failed to connect to MCP server at ${normalizedUrl}: ${result.error}`\n );\n }\n\n if (result.state === MCPConnectionState.AUTHENTICATING) {\n if (!callbackUrl) {\n throw new Error(\n \"This MCP server requires OAuth authentication. \" +\n \"Provide callbackHost in addMcpServer options to enable the OAuth flow.\"\n );\n }\n return { id, state: result.state, authUrl: result.authUrl };\n }\n\n // State is CONNECTED - discover capabilities\n const discoverResult = await this.mcp.discoverIfConnected(id);\n\n if (discoverResult && !discoverResult.success) {\n // Server stays in storage - connection is still valid, user can retry discovery\n throw new Error(\n `Failed to discover MCP server capabilities: ${discoverResult.error}`\n );\n }\n\n return { id, state: MCPConnectionState.READY };\n }\n\n async removeMcpServer(id: string) {\n await this.mcp.removeServer(id);\n }\n\n getMcpServers(): MCPServersState {\n const mcpState: MCPServersState = {\n prompts: this.mcp.listPrompts(),\n resources: this.mcp.listResources(),\n servers: {},\n tools: this.mcp.listTools()\n };\n\n const servers = this.mcp.listServers();\n\n if (servers && Array.isArray(servers) && servers.length > 0) {\n for (const server of servers) {\n const serverConn = this.mcp.mcpConnections[server.id];\n\n // Determine the default state when no connection exists\n let defaultState: \"authenticating\" | \"not-connected\" = \"not-connected\";\n if (!serverConn && server.auth_url) {\n // If there's an auth_url but no connection, it's waiting for OAuth\n defaultState = \"authenticating\";\n }\n\n mcpState.servers[server.id] = {\n auth_url: server.auth_url,\n capabilities: serverConn?.serverCapabilities ?? null,\n error: sanitizeErrorString(serverConn?.connectionError ?? null),\n instructions: serverConn?.instructions ?? null,\n name: server.name,\n server_url: server.server_url,\n state: serverConn?.connectionState ?? defaultState\n };\n }\n }\n\n return mcpState;\n }\n\n /**\n * Create the OAuth provider used when connecting to MCP servers that require authentication.\n *\n * Override this method in a subclass to supply a custom OAuth provider implementation,\n * for example to use pre-registered client credentials, mTLS-based authentication,\n * or any other OAuth flow beyond dynamic client registration.\n *\n * @example\n * // Custom OAuth provider\n * class MyAgent extends Agent {\n * createMcpOAuthProvider(callbackUrl: string): AgentMcpOAuthProvider {\n * return new MyCustomOAuthProvider(\n * this.ctx.storage,\n * this.name,\n * callbackUrl\n * );\n * }\n * }\n *\n * @param callbackUrl The OAuth callback URL for the authorization flow\n * @returns An {@link AgentMcpOAuthProvider} instance used by {@link addMcpServer}\n */\n createMcpOAuthProvider(callbackUrl: string): AgentMcpOAuthProvider {\n return new DurableObjectOAuthClientProvider(\n this.ctx.storage,\n this.name,\n callbackUrl\n );\n }\n\n private broadcastMcpServers() {\n this._broadcastProtocol(\n JSON.stringify({\n mcp: this.getMcpServers(),\n type: MessageType.CF_AGENT_MCP_SERVERS\n })\n );\n }\n\n /**\n * Handle MCP OAuth callback request if it's an OAuth callback.\n *\n * This method encapsulates the entire OAuth callback flow:\n * 1. Checks if the request is an MCP OAuth callback\n * 2. Processes the OAuth code exchange\n * 3. Establishes the connection if successful\n * 4. Broadcasts MCP server state updates\n * 5. Returns the appropriate HTTP response\n *\n * @param request The incoming HTTP request\n * @returns Response if this was an OAuth callback, null otherwise\n */\n private async handleMcpOAuthCallback(\n request: Request\n ): Promise<Response | null> {\n // Check if this is an OAuth callback request\n const isCallback = this.mcp.isCallbackRequest(request);\n if (!isCallback) {\n return null;\n }\n\n // Handle the OAuth callback (exchanges code for token, clears OAuth credentials from storage)\n // This fires onServerStateChanged event which triggers broadcast\n const result = await this.mcp.handleCallbackRequest(request);\n\n // If auth was successful, establish the connection in the background\n // (establishConnection handles retries internally using per-server retry config)\n if (result.authSuccess) {\n this.mcp.establishConnection(result.serverId).catch((error) => {\n console.error(\n \"[Agent handleMcpOAuthCallback] Connection establishment failed:\",\n error\n );\n });\n }\n\n this.broadcastMcpServers();\n\n // Return the HTTP response for the OAuth callback\n return this.handleOAuthCallbackResponse(result, request);\n }\n\n /**\n * Handle OAuth callback response using MCPClientManager configuration\n * @param result OAuth callback result\n * @param request The original request (needed for base URL)\n * @returns Response for the OAuth callback\n */\n private handleOAuthCallbackResponse(\n result: MCPClientOAuthResult,\n request: Request\n ): Response {\n const config = this.mcp.getOAuthCallbackConfig();\n\n // Use custom handler if configured\n if (config?.customHandler) {\n return config.customHandler(result);\n }\n\n const baseOrigin = new URL(request.url).origin;\n\n // Redirect to success URL if configured\n if (config?.successRedirect && result.authSuccess) {\n try {\n return Response.redirect(\n new URL(config.successRedirect, baseOrigin).href\n );\n } catch (e) {\n console.error(\n \"Invalid successRedirect URL:\",\n config.successRedirect,\n e\n );\n return Response.redirect(baseOrigin);\n }\n }\n\n // Redirect to error URL if configured\n if (config?.errorRedirect && !result.authSuccess) {\n try {\n const errorUrl = `${config.errorRedirect}?error=${encodeURIComponent(\n result.authError || \"Unknown error\"\n )}`;\n return Response.redirect(new URL(errorUrl, baseOrigin).href);\n } catch (e) {\n console.error(\"Invalid errorRedirect URL:\", config.errorRedirect, e);\n return Response.redirect(baseOrigin);\n }\n }\n\n return Response.redirect(baseOrigin);\n }\n}\n\n// A set of classes that have been wrapped with agent context\nconst wrappedClasses = new Set<typeof Agent.prototype.constructor>();\n\n/**\n * Namespace for creating Agent instances\n * @template Agentic Type of the Agent class\n * @deprecated Use DurableObjectNamespace instead\n */\nexport type AgentNamespace<Agentic extends Agent<Cloudflare.Env>> =\n DurableObjectNamespace<Agentic>;\n\n/**\n * Agent's durable context\n */\nexport type AgentContext = DurableObjectState;\n\n/**\n * Configuration options for Agent routing\n */\nexport type AgentOptions<Env> = PartyServerOptions<Env>;\n\n/**\n * Route a request to the appropriate Agent\n * @param request Request to route\n * @param env Environment containing Agent bindings\n * @param options Routing options\n * @returns Response from the Agent or undefined if no route matched\n */\nexport async function routeAgentRequest<Env>(\n request: Request,\n env: Env,\n options?: AgentOptions<Env>\n) {\n // oxlint-disable-next-line typescript/no-explicit-any\n return routePartykitRequest(request, env as any, {\n prefix: \"agents\",\n ...(options as PartyServerOptions<Record<string, unknown>>)\n });\n}\n\n// Email routing - deprecated resolver kept in root for upgrade discoverability\n// Other email utilities moved to agents/email subpath\nexport { createHeaderBasedEmailResolver } from \"./email\";\n\nimport type { EmailResolver } from \"./email\";\n\nexport type EmailRoutingOptions<Env> = AgentOptions<Env> & {\n resolver: EmailResolver<Env>;\n /**\n * Callback invoked when no routing information is found for an email.\n * Use this to reject the email or perform custom handling.\n * If not provided, a warning is logged and the email is dropped.\n */\n onNoRoute?: (email: ForwardableEmailMessage) => void | Promise<void>;\n};\n\n// RpcTarget bridge for email callbacks. Consolidates the email event's\n// mutation methods (setReject, forward, reply) into a single disposable\n// RPC target instead of anonymous closures. This allows the runtime to\n// tear down the bidirectional RPC session when _onEmail returns,\n// rather than keeping the DO pinned for the caller's entire context\n// lifetime (~100-120s for CF Email Routing handlers).\nclass EmailBridge extends RpcTarget {\n #email: ForwardableEmailMessage;\n\n constructor(email: ForwardableEmailMessage) {\n super();\n this.#email = email;\n }\n\n async getRaw(): Promise<Uint8Array> {\n const reader = this.#email.raw.getReader();\n const chunks: Uint8Array[] = [];\n let done = false;\n while (!done) {\n const { value, done: readerDone } = await reader.read();\n done = readerDone;\n if (value) {\n chunks.push(value);\n }\n }\n const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);\n const combined = new Uint8Array(totalLength);\n let offset = 0;\n for (const chunk of chunks) {\n combined.set(chunk, offset);\n offset += chunk.length;\n }\n return combined;\n }\n\n setReject(reason: string) {\n this.#email.setReject(reason);\n }\n\n forward(rcptTo: string, headers?: Headers): Promise<EmailSendResult> {\n return this.#email.forward(rcptTo, headers);\n }\n\n reply(options: {\n from: string;\n to: string;\n raw: string;\n }): Promise<EmailSendResult> {\n return this.#email.reply(\n new EmailMessage(options.from, options.to, options.raw)\n );\n }\n\n [Symbol.dispose]() {\n // Intentionally empty — the runtime calls this when the last\n // stub is disposed, signaling that the RPC target is no longer\n // needed and the bidirectional connection can be torn down.\n }\n}\n\n// Cache the agent namespace map for email routing\n// This maps original names, kebab-case, and lowercase versions to namespaces\nconst agentMapCache = new WeakMap<\n Record<string, unknown>,\n { map: Record<string, unknown>; originalNames: string[] }\n>();\n\n/**\n * Route an email to the appropriate Agent\n * @param email The email to route\n * @param env The environment containing the Agent bindings\n * @param options The options for routing the email\n * @returns A promise that resolves when the email has been routed\n */\nexport async function routeAgentEmail<\n Env extends Cloudflare.Env = Cloudflare.Env\n>(\n email: ForwardableEmailMessage,\n env: Env,\n options: EmailRoutingOptions<Env>\n): Promise<void> {\n const routingInfo = await options.resolver(email, env);\n\n if (!routingInfo) {\n if (options.onNoRoute) {\n await options.onNoRoute(email);\n } else {\n console.warn(\"No routing information found for email, dropping message\");\n }\n return;\n }\n\n // Build a map that includes original names, kebab-case, and lowercase versions\n if (!agentMapCache.has(env as Record<string, unknown>)) {\n const map: Record<string, unknown> = {};\n const originalNames: string[] = [];\n for (const [key, value] of Object.entries(env as Record<string, unknown>)) {\n if (\n value &&\n typeof value === \"object\" &&\n \"idFromName\" in value &&\n typeof value.idFromName === \"function\"\n ) {\n // Add the original name, kebab-case version, and lowercase version\n map[key] = value;\n map[camelCaseToKebabCase(key)] = value;\n map[key.toLowerCase()] = value;\n originalNames.push(key);\n }\n }\n agentMapCache.set(env as Record<string, unknown>, {\n map,\n originalNames\n });\n }\n\n const cached = agentMapCache.get(env as Record<string, unknown>)!;\n const namespace = cached.map[routingInfo.agentName];\n\n if (!namespace) {\n // Provide helpful error message listing available agents\n const availableAgents = cached.originalNames.join(\", \");\n throw new Error(\n `Agent namespace '${routingInfo.agentName}' not found in environment. Available agents: ${availableAgents}`\n );\n }\n\n const agent = await getAgentByName(\n namespace as unknown as DurableObjectNamespace<Agent<Env>>,\n routingInfo.agentId\n );\n\n // Use an RpcTarget bridge instead of bare closures so the runtime\n // can cleanly tear down the bidirectional session after _onEmail returns\n const bridge = new EmailBridge(email);\n\n await agent._onEmail({\n from: email.from,\n to: email.to,\n headers: email.headers,\n rawSize: email.rawSize,\n _secureRouted: routingInfo._secureRouted,\n _bridge: bridge\n });\n}\n\n/**\n * Get or create an Agent by name\n * @template Env Environment type containing bindings\n * @template T Type of the Agent class\n * @param namespace Agent namespace\n * @param name Name of the Agent instance\n * @param options Options for Agent creation\n * @returns Promise resolving to an Agent instance stub\n */\nexport async function getAgentByName<\n Env extends Cloudflare.Env = Cloudflare.Env,\n T extends Agent<Env> = Agent<Env>,\n Props extends Record<string, unknown> = Record<string, unknown>\n>(\n namespace: DurableObjectNamespace<T>,\n name: string,\n options?: {\n jurisdiction?: DurableObjectJurisdiction;\n locationHint?: DurableObjectLocationHint;\n props?: Props;\n }\n) {\n return getServerByName<Env, T>(namespace, name, options);\n}\n\n/**\n * A wrapper for streaming responses in callable methods\n */\nexport class StreamingResponse {\n private _connection: Connection;\n private _id: string;\n private _closed = false;\n\n constructor(connection: Connection, id: string) {\n this._connection = connection;\n this._id = id;\n }\n\n /**\n * Whether the stream has been closed (via end() or error())\n */\n get isClosed(): boolean {\n return this._closed;\n }\n\n /**\n * Send a chunk of data to the client\n * @param chunk The data to send\n * @returns false if stream is already closed (no-op), true if sent\n */\n send(chunk: unknown): boolean {\n if (this._closed) {\n console.warn(\n \"StreamingResponse.send() called after stream was closed - data not sent\"\n );\n return false;\n }\n const response: RPCResponse = {\n done: false,\n id: this._id,\n result: chunk,\n success: true,\n type: MessageType.RPC\n };\n this._connection.send(JSON.stringify(response));\n return true;\n }\n\n /**\n * End the stream and send the final chunk (if any)\n * @param finalChunk Optional final chunk of data to send\n * @returns false if stream is already closed (no-op), true if sent\n */\n end(finalChunk?: unknown): boolean {\n if (this._closed) {\n return false;\n }\n this._closed = true;\n const response: RPCResponse = {\n done: true,\n id: this._id,\n result: finalChunk,\n success: true,\n type: MessageType.RPC\n };\n this._connection.send(JSON.stringify(response));\n return true;\n }\n\n /**\n * Send an error to the client and close the stream\n * @param message Error message to send\n * @returns false if stream is already closed (no-op), true if sent\n */\n error(message: string): boolean {\n if (this._closed) {\n return false;\n }\n this._closed = true;\n const response: RPCResponse = {\n error: message,\n id: this._id,\n success: false,\n type: MessageType.RPC\n };\n this._connection.send(JSON.stringify(response));\n return true;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["agentContext","_parseSubAgentPath"],"sources":["../src/index.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\nimport type { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport {\n __DO_NOT_USE_WILL_BREAK__agentContext as agentContext,\n type AgentEmail\n} from \"./internal_context\";\nexport { __DO_NOT_USE_WILL_BREAK__agentContext } from \"./internal_context\";\nimport {\n SUB_PREFIX,\n parseSubAgentPath as _parseSubAgentPath\n} from \"./sub-routing\";\nexport {\n routeSubAgentRequest,\n getSubAgentByName,\n parseSubAgentPath,\n SUB_PREFIX\n} from \"./sub-routing\";\nexport type { SubAgentPathMatch } from \"./sub-routing\";\nimport type { SSEClientTransportOptions } from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport { signAgentHeaders } from \"./email\";\n\nimport type {\n Prompt,\n Resource,\n ServerCapabilities,\n Tool\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { parseCronExpression } from \"cron-schedule\";\nimport { nanoid } from \"nanoid\";\nimport { EmailMessage } from \"cloudflare:email\";\nimport { RpcTarget } from \"cloudflare:workers\";\nimport {\n type Connection,\n type ConnectionContext,\n type PartyServerOptions,\n Server,\n type WSMessage,\n getServerByName,\n routePartykitRequest\n} from \"partyserver\";\nimport { camelCaseToKebabCase } from \"./utils\";\nimport {\n type RetryOptions,\n tryN,\n isErrorRetryable,\n validateRetryOptions\n} from \"./retries\";\nimport { MCPClientManager, type MCPClientOAuthResult } from \"./mcp/client\";\nimport type {\n WorkflowCallback,\n WorkflowTrackingRow,\n WorkflowStatus,\n RunWorkflowOptions,\n WorkflowEventPayload,\n WorkflowInfo,\n WorkflowQueryCriteria,\n WorkflowPage\n} from \"./workflow-types\";\nimport { MCPConnectionState } from \"./mcp/client-connection\";\nimport {\n DurableObjectOAuthClientProvider,\n type AgentMcpOAuthProvider\n} from \"./mcp/do-oauth-client-provider\";\nimport type { TransportType } from \"./mcp/types\";\nimport {\n genericObservability,\n type Observability,\n type ObservabilityEvent\n} from \"./observability\";\nimport { DisposableStore } from \"./core/events\";\nimport { MessageType } from \"./types\";\nimport { RPC_DO_PREFIX } from \"./mcp/rpc\";\nimport type { McpAgent } from \"./mcp\";\nimport type {\n AgentToolChildAdapter,\n AgentToolDisplayMetadata,\n AgentToolEvent,\n AgentToolEventMessage,\n AgentToolLifecycleResult,\n AgentToolRunInfo,\n AgentToolRunInspection,\n AgentToolRunStatus,\n AgentToolStoredChunk,\n ChatCapableAgentClass,\n RunAgentToolOptions,\n RunAgentToolResult\n} from \"./agent-tool-types\";\n\nexport type {\n AgentToolChildAdapter,\n AgentToolDisplayMetadata,\n AgentToolEvent,\n AgentToolEventMessage,\n AgentToolEventState,\n AgentToolLifecycleResult,\n AgentToolRunInfo,\n AgentToolRunInspection,\n AgentToolRunState,\n AgentToolRunStatus,\n AgentToolStoredChunk,\n AgentToolTerminalStatus,\n ChatCapableAgentClass,\n RunAgentToolOptions,\n RunAgentToolResult\n} from \"./agent-tool-types\";\n\nexport type { Connection, ConnectionContext, WSMessage } from \"partyserver\";\nexport { MessageType } from \"./types\";\n\n/**\n * Structural type for Cloudflare's `send_email` binding.\n * Accepts both raw MIME messages and structured builder objects.\n */\nexport type EmailSendBinding = {\n send(\n message:\n | EmailMessage\n | {\n from: string | { email: string; name?: string };\n to: string | string[];\n subject: string;\n replyTo?: string | { email: string; name?: string };\n cc?: string | string[];\n bcc?: string | string[];\n headers?: Record<string, string>;\n text?: string;\n html?: string;\n }\n ): Promise<EmailSendResult>;\n};\n\n/**\n * Options for Agent.sendEmail()\n */\nexport type SendEmailOptions = {\n binding: EmailSendBinding;\n to: string | string[];\n from: string | { email: string; name?: string };\n subject: string;\n text?: string;\n html?: string;\n replyTo?: string | { email: string; name?: string };\n cc?: string | string[];\n bcc?: string | string[];\n inReplyTo?: string;\n headers?: Record<string, string>;\n secret?: string;\n};\n\n/**\n * RPC request message from client\n */\nexport type RPCRequest = {\n type: \"rpc\";\n id: string;\n method: string;\n args: unknown[];\n};\n\n/**\n * State update message from client\n */\nexport type StateUpdateMessage = {\n type: MessageType.CF_AGENT_STATE;\n state: unknown;\n};\n\n/**\n * RPC response message to client\n */\nexport type RPCResponse = {\n type: MessageType.RPC;\n id: string;\n} & (\n | {\n success: true;\n result: unknown;\n done?: false;\n }\n | {\n success: true;\n result: unknown;\n done: true;\n }\n | {\n success: false;\n error: string;\n }\n);\n\n/**\n * Type guard for RPC request messages\n */\nfunction isRPCRequest(msg: unknown): msg is RPCRequest {\n return (\n typeof msg === \"object\" &&\n msg !== null &&\n \"type\" in msg &&\n msg.type === MessageType.RPC &&\n \"id\" in msg &&\n typeof msg.id === \"string\" &&\n \"method\" in msg &&\n typeof msg.method === \"string\" &&\n \"args\" in msg &&\n Array.isArray((msg as RPCRequest).args)\n );\n}\n\n/**\n * Type guard for state update messages\n */\nfunction isStateUpdateMessage(msg: unknown): msg is StateUpdateMessage {\n return (\n typeof msg === \"object\" &&\n msg !== null &&\n \"type\" in msg &&\n msg.type === MessageType.CF_AGENT_STATE &&\n \"state\" in msg\n );\n}\n\n/**\n * Metadata for a callable method\n */\nexport type CallableMetadata = {\n /** Optional description of what the method does */\n description?: string;\n /** Whether the method supports streaming responses */\n streaming?: boolean;\n};\n\nconst callableMetadata = new WeakMap<Function, CallableMetadata>();\n\n/**\n * Error class for SQL execution failures, containing the query that failed\n */\nexport class SqlError extends Error {\n /** The SQL query that failed */\n readonly query: string;\n\n constructor(query: string, cause: unknown) {\n const message = cause instanceof Error ? cause.message : String(cause);\n super(`SQL query failed: ${message}`, { cause });\n this.name = \"SqlError\";\n this.query = query;\n }\n}\n\n// ── Sub-agent (facet) types ──────────────────────────────────────────\n\n/**\n * Internal narrowing of `DurableObjectState` to the parts the facet\n * bootstrap path uses. We only need this because `ctx.exports` in the\n * real types (`Cloudflare.Exports`) is keyed by the *consumer's*\n * worker MainModule, which is invisible from inside this library —\n * so we widen it to a generic Record indexed by class name.\n *\n * @internal\n */\ninterface FacetCapableCtx {\n facets: DurableObjectFacets;\n /**\n * Worker exports keyed by class export name. workerd's runtime\n * contract: any class registered via `migrations.new_sqlite_classes`\n * (or `migrations.new_classes`) — including facet-only classes\n * that have NO entry in `durable_objects.bindings` — is exposed\n * here as BOTH a `DurableObjectClass` (usable as\n * `FacetStartupOptions.class`) AND a `DurableObjectNamespace`\n * (usable for `idFromName`/`getByName`). The intersection is what\n * makes `ctx.exports[OuterSubAgent].idFromName(...)` work from\n * inside a nested facet bootstrap, even though `OuterSubAgent`\n * isn't bound. Runtime lookups can still return `undefined` for\n * unregistered class names; callers must null-check.\n */\n exports: Record<\n string,\n (DurableObjectClass & DurableObjectNamespace) | undefined\n >;\n}\n\ntype SubAgentConnectionMeta = {\n id: string;\n uri: string | null;\n tags: string[];\n state: unknown;\n requestHeaders?: [string, string][];\n};\n\ntype SubAgentConnectionBridgeLike = {\n send(message: string | ArrayBuffer | ArrayBufferView): void;\n close(code?: number, reason?: string): void;\n setState(state: unknown): unknown;\n broadcast(\n ownerPath: ReadonlyArray<{ className: string; name: string }>,\n message: string | ArrayBuffer | ArrayBufferView,\n without?: string[]\n ): void;\n};\n\ntype StoredSubAgentConnection = {\n bridge: SubAgentConnectionBridgeLike;\n meta: SubAgentConnectionMeta;\n connection?: Connection;\n};\n\ntype SubAgentWebSocketEndpoint = {\n _cf_handleSubAgentWebSocketConnect(\n bridge: SubAgentConnectionBridge,\n meta: SubAgentConnectionMeta\n ): Promise<void>;\n _cf_handleSubAgentWebSocketMessage(\n message: WSMessage,\n bridge: SubAgentConnectionBridge,\n meta: SubAgentConnectionMeta\n ): Promise<void>;\n _cf_handleSubAgentWebSocketClose(\n code: number,\n reason: string,\n wasClean: boolean,\n bridge: SubAgentConnectionBridge,\n meta: SubAgentConnectionMeta\n ): Promise<void>;\n};\n\nclass SubAgentConnectionBridge\n extends RpcTarget\n implements SubAgentConnectionBridgeLike\n{\n #connection: Connection;\n #broadcast?: (\n ownerPath: ReadonlyArray<{ className: string; name: string }>,\n message: string | ArrayBuffer | ArrayBufferView,\n without?: string[]\n ) => void;\n\n constructor(\n connection: Connection,\n broadcast?: (\n ownerPath: ReadonlyArray<{ className: string; name: string }>,\n message: string | ArrayBuffer | ArrayBufferView,\n without?: string[]\n ) => void\n ) {\n super();\n this.#connection = connection;\n this.#broadcast = broadcast;\n }\n\n send(message: string | ArrayBuffer | ArrayBufferView): void {\n this.#connection.send(message);\n }\n\n close(code?: number, reason?: string): void {\n this.#connection.close(code, reason);\n }\n\n setState(state: unknown): unknown {\n return this.#connection.setState(state);\n }\n\n broadcast(\n ownerPath: ReadonlyArray<{ className: string; name: string }>,\n message: string | ArrayBuffer | ArrayBufferView,\n without?: string[]\n ): void {\n this.#broadcast?.(ownerPath, message, without);\n }\n}\n\nclass RootSubAgentConnectionBridge implements SubAgentConnectionBridgeLike {\n #root: RootFacetRpcSurface;\n #connectionId: string;\n\n constructor(root: RootFacetRpcSurface, connectionId: string) {\n this.#root = root;\n this.#connectionId = connectionId;\n }\n\n send(message: string | ArrayBuffer | ArrayBufferView): void {\n void this.#root._cf_sendToSubAgentConnection(this.#connectionId, message);\n }\n\n close(code?: number, reason?: string): void {\n void this.#root._cf_closeSubAgentConnection(\n this.#connectionId,\n code,\n reason\n );\n }\n\n setState(state: unknown): unknown {\n void this.#root._cf_setSubAgentConnectionState(this.#connectionId, state);\n return state;\n }\n\n broadcast(\n ownerPath: ReadonlyArray<{ className: string; name: string }>,\n message: string | ArrayBuffer | ArrayBufferView,\n without?: string[]\n ): void {\n void this.#root._cf_broadcastToSubAgent(ownerPath, message, without);\n }\n}\n\n/**\n * Constructor type for a sub-agent class.\n * Used by {@link Agent.subAgent} to reference the child class\n * via `ctx.exports`.\n *\n * The class name (`cls.name`) must match the export name in the\n * worker entry point — re-exports under a different name\n * (e.g. `export { Foo as Bar }`) are not supported.\n */\nexport type SubAgentClass<T extends Agent = Agent> = {\n new (ctx: DurableObjectState, env: never): T;\n};\n\n/**\n * Wraps `T` in a `Promise` unless it already is one.\n */\ntype Promisify<T> = T extends Promise<unknown> ? T : Promise<T>;\n\n/**\n * A typed RPC stub for a sub-agent. Exposes all public instance methods\n * as callable RPC methods with Promise-wrapped return types.\n *\n * Methods inherited from `Agent` / `Server` / `DurableObject` internals\n * are excluded — only user-defined methods on the subclass are exposed.\n */\nexport type SubAgentStub<T extends Agent> = {\n [K in keyof T as K extends keyof Agent\n ? never\n : T[K] extends (...args: never[]) => unknown\n ? K\n : never]: T[K] extends (...args: infer A) => infer R\n ? (...args: A) => Promisify<R>\n : never;\n};\n\n/**\n * Decorator that marks a method as callable by clients\n * @param metadata Optional metadata about the callable method\n */\nexport function callable(metadata: CallableMetadata = {}) {\n return function callableDecorator<This, Args extends unknown[], Return>(\n target: (this: This, ...args: Args) => Return,\n _context: ClassMethodDecoratorContext\n ) {\n if (!callableMetadata.has(target)) {\n callableMetadata.set(target, metadata);\n }\n\n return target;\n };\n}\n\nlet didWarnAboutUnstableCallable = false;\n\n/**\n * Decorator that marks a method as callable by clients\n * @deprecated this has been renamed to callable, and unstable_callable will be removed in the next major version\n * @param metadata Optional metadata about the callable method\n */\nexport const unstable_callable = (metadata: CallableMetadata = {}) => {\n if (!didWarnAboutUnstableCallable) {\n didWarnAboutUnstableCallable = true;\n console.warn(\n \"unstable_callable is deprecated, use callable instead. unstable_callable will be removed in the next major version.\"\n );\n }\n return callable(metadata);\n};\n\nexport type QueueItem<T = string> = {\n id: string;\n payload: T;\n callback: keyof Agent<Cloudflare.Env>;\n created_at: number;\n retry?: RetryOptions;\n};\n\n/**\n * Represents a scheduled task within an Agent\n * @template T Type of the payload data\n */\nexport type Schedule<T = string> = {\n /** Unique identifier for the schedule */\n id: string;\n /** Name of the method to be called */\n callback: string;\n /** Data to be passed to the callback */\n payload: T;\n /** Retry options for callback execution */\n retry?: RetryOptions;\n} & (\n | {\n /** Type of schedule for one-time execution at a specific time */\n type: \"scheduled\";\n /** Timestamp when the task should execute */\n time: number;\n }\n | {\n /** Type of schedule for delayed execution */\n type: \"delayed\";\n /** Timestamp when the task should execute */\n time: number;\n /** Number of seconds to delay execution */\n delayInSeconds: number;\n }\n | {\n /** Type of schedule for recurring execution based on cron expression */\n type: \"cron\";\n /** Timestamp for the next execution */\n time: number;\n /** Cron expression defining the schedule */\n cron: string;\n }\n | {\n /** Type of schedule for recurring execution at fixed intervals */\n type: \"interval\";\n /** Timestamp for the next execution */\n time: number;\n /** Number of seconds between executions */\n intervalSeconds: number;\n }\n);\n\ntype AgentPathStep = { className: string; name: string };\n\ntype ScheduleStorageRow = {\n id: string;\n callback: string;\n payload: string;\n type: \"scheduled\" | \"delayed\" | \"cron\" | \"interval\";\n time: number;\n delayInSeconds?: number;\n cron?: string;\n intervalSeconds?: number;\n retry?: RetryOptions;\n running?: number;\n execution_started_at?: number | null;\n retry_options?: string | null;\n owner_path?: string | null;\n owner_path_key?: string | null;\n};\n\ntype FacetRunStorageRow = {\n owner_path: string;\n owner_path_key: string;\n run_id: string;\n created_at: number;\n};\n\ntype AgentToolRunStorageRow = {\n run_id: string;\n parent_tool_call_id: string | null;\n agent_type: string;\n input_preview: string | null;\n status: AgentToolRunStatus;\n summary: string | null;\n output_json: string | null;\n error_message: string | null;\n display_metadata: string | null;\n display_order: number;\n started_at: number;\n completed_at: number | null;\n};\n\nexport type ScheduleCriteria = {\n id?: string;\n type?: \"scheduled\" | \"delayed\" | \"cron\" | \"interval\";\n timeRange?: { start?: Date; end?: Date };\n};\n\n/**\n * Internal RPC surface exposed by the root agent for facets to\n * delegate alarm-owning operations (schedules + facet teardown).\n * @internal\n */\ntype RootFacetRpcSurface = {\n _cf_scheduleForFacet<T>(\n ownerPath: ReadonlyArray<AgentPathStep>,\n when: Date | string | number,\n callback: string,\n payload?: T,\n options?: { retry?: RetryOptions; idempotent?: boolean }\n ): Promise<{ schedule: Schedule<T>; created: boolean }>;\n _cf_cancelScheduleForFacet(\n ownerPath: ReadonlyArray<AgentPathStep>,\n id: string\n ): Promise<{ ok: boolean; callback?: string }>;\n _cf_scheduleEveryForFacet<T>(\n ownerPath: ReadonlyArray<AgentPathStep>,\n intervalSeconds: number,\n callback: string,\n payload?: T,\n options?: { retry?: RetryOptions; _idempotent?: boolean }\n ): Promise<{ schedule: Schedule<T>; created: boolean }>;\n _cf_cleanupFacetPrefix(\n ownerPath: ReadonlyArray<AgentPathStep>\n ): Promise<void>;\n _cf_getScheduleForFacet(\n ownerPath: ReadonlyArray<AgentPathStep>,\n id: string\n ): Promise<Schedule<unknown> | undefined>;\n _cf_listSchedulesForFacet(\n ownerPath: ReadonlyArray<AgentPathStep>,\n criteria?: ScheduleCriteria\n ): Promise<Schedule<unknown>[]>;\n _cf_destroyDescendantFacet(\n targetPath: ReadonlyArray<AgentPathStep>\n ): Promise<void>;\n _cf_acquireFacetKeepAlive(\n ownerPath: ReadonlyArray<AgentPathStep>\n ): Promise<string>;\n _cf_releaseFacetKeepAlive(token: string): Promise<void>;\n _cf_registerFacetRun(\n ownerPath: ReadonlyArray<AgentPathStep>,\n runId: string\n ): Promise<void>;\n _cf_unregisterFacetRun(\n ownerPath: ReadonlyArray<AgentPathStep>,\n runId: string\n ): Promise<void>;\n _cf_broadcastToSubAgent(\n ownerPath: ReadonlyArray<AgentPathStep>,\n message: string | ArrayBuffer | ArrayBufferView,\n without?: string[]\n ): Promise<void>;\n _cf_subAgentConnectionMetas(\n ownerPath: ReadonlyArray<AgentPathStep>\n ): Promise<SubAgentConnectionMeta[]>;\n _cf_sendToSubAgentConnection(\n connectionId: string,\n message: string | ArrayBuffer | ArrayBufferView\n ): Promise<void>;\n _cf_closeSubAgentConnection(\n connectionId: string,\n code?: number,\n reason?: string\n ): Promise<void>;\n _cf_setSubAgentConnectionState(\n connectionId: string,\n state: unknown\n ): Promise<unknown>;\n};\n\n/**\n * Context passed to the `runFiber` callback. Provides checkpoint\n * and identity for durable execution.\n */\nexport type FiberContext = {\n /** Unique identifier for this fiber execution. */\n id: string;\n /** Checkpoint data during execution. Synchronous SQLite write. */\n stash(data: unknown): void;\n /** Last checkpoint data (null on first run, populated on recovery re-invocation). */\n snapshot: unknown | null;\n};\n\n/**\n * Context passed to the `onFiberRecovered` hook when an interrupted\n * fiber is detected after DO restart.\n */\nexport type FiberRecoveryContext = {\n /** Fiber ID. */\n id: string;\n /** Name passed to `runFiber`. */\n name: string;\n /** Last checkpoint data from `stash()`, or null if never stashed. */\n snapshot: unknown | null;\n /**\n * Epoch milliseconds when the fiber row was inserted (when `runFiber`\n * started). Use `Date.now() - createdAt` to gate stale recoveries.\n */\n createdAt: number;\n [key: string]: unknown;\n};\n\nconst _fiberALS = new AsyncLocalStorage<{\n id: string;\n stash: (data: unknown) => void;\n}>();\n\nfunction getNextCronTime(cron: string) {\n const interval = parseCronExpression(cron);\n return interval.getNextDate();\n}\n\nexport type { TransportType } from \"./mcp/types\";\nexport type { RetryOptions } from \"./retries\";\nexport {\n DurableObjectOAuthClientProvider,\n type AgentMcpOAuthProvider,\n /** @deprecated Use {@link AgentMcpOAuthProvider} instead. */\n type AgentsOAuthProvider\n} from \"./mcp/do-oauth-client-provider\";\n\n/**\n * MCP Server state update message from server -> Client\n */\nexport type MCPServerMessage = {\n type: MessageType.CF_AGENT_MCP_SERVERS;\n mcp: MCPServersState;\n};\n\nexport type MCPServersState = {\n servers: {\n [id: string]: MCPServer;\n };\n tools: (Tool & { serverId: string })[];\n prompts: (Prompt & { serverId: string })[];\n resources: (Resource & { serverId: string })[];\n};\n\nexport type MCPServer = {\n name: string;\n server_url: string;\n auth_url: string | null;\n // This state is specifically about the temporary process of getting a token (if needed).\n // Scope outside of that can't be relied upon because when the DO sleeps, there's no way\n // to communicate a change to a non-ready state.\n state: MCPConnectionState;\n /** May contain untrusted content from external OAuth providers. Escape appropriately for your output context. */\n error: string | null;\n instructions: string | null;\n capabilities: ServerCapabilities | null;\n};\n\n/**\n * Options for adding an MCP server\n */\nexport type AddMcpServerOptions = {\n /** OAuth callback host (auto-derived from request if omitted) */\n callbackHost?: string;\n /**\n * Custom callback URL path — bypasses the default `/agents/{class}/{name}/callback` construction.\n * Required when `sendIdentityOnConnect` is `false` to prevent leaking the instance name.\n * When set, the callback URL becomes `{callbackHost}/{callbackPath}`.\n * The developer must route this path to the agent instance via `getAgentByName`.\n * Should be a plain path (e.g., `/mcp-callback`) — do not include query strings or fragments.\n */\n callbackPath?: string;\n /** Agents routing prefix (default: \"agents\") */\n agentsPrefix?: string;\n /** MCP client options */\n client?: ConstructorParameters<typeof Client>[1];\n /** Transport options */\n transport?: {\n /** Custom headers for authentication (e.g., bearer tokens, CF Access) */\n headers?: HeadersInit;\n /** Transport type: \"sse\", \"streamable-http\", or \"auto\" (default) */\n type?: TransportType;\n };\n /** Retry options for connection and reconnection attempts */\n retry?: RetryOptions;\n};\n\n/**\n * Options for adding an MCP server via RPC (Durable Object binding)\n */\nexport type AddRpcMcpServerOptions = {\n /** Props to pass to the McpAgent instance */\n props?: Record<string, unknown>;\n};\n\nconst DEFAULT_KEEP_ALIVE_INTERVAL_MS = 30_000;\n\n/**\n * Schema version for the Agent's internal SQLite tables.\n * Bump this when adding new tables, columns, or migrations.\n * The constructor stores this as a row in cf_agents_state and checks it\n * on wake to skip DDL on established DOs.\n */\nconst CURRENT_SCHEMA_VERSION = 7;\n\nconst SCHEMA_VERSION_ROW_ID = \"cf_schema_version\";\nconst STATE_ROW_ID = \"cf_state_row_id\";\n// Legacy key — no longer written, but read for backward compatibility with\n// DOs that were created before the single-row state optimization.\nconst STATE_WAS_CHANGED = \"cf_state_was_changed\";\n\nconst DEFAULT_STATE = {} as unknown;\n\n/**\n * Validate that a stored `parentPath` has the expected shape. Used\n * when restoring from DO storage to guard against corrupted data.\n */\nfunction isValidParentPath(\n value: unknown\n): value is Array<{ className: string; name: string }> {\n if (!Array.isArray(value)) return false;\n return value.every(\n (entry) =>\n entry != null &&\n typeof entry === \"object\" &&\n typeof (entry as { className?: unknown }).className === \"string\" &&\n typeof (entry as { name?: unknown }).name === \"string\"\n );\n}\n\n/**\n * Internal key used to store the readonly flag in connection state.\n * Prefixed with _cf_ to avoid collision with user state keys.\n */\nconst CF_READONLY_KEY = \"_cf_readonly\";\n\n/**\n * Internal key used to store the no-protocol flag in connection state.\n * When set, protocol messages (identity, state sync, MCP servers) are not\n * sent to this connection — neither on connect nor via broadcasts.\n */\nconst CF_NO_PROTOCOL_KEY = \"_cf_no_protocol\";\n\n/**\n * Internal key used to store voice call state in connection state.\n * Used by the voice mixin to track whether a connection is in an active call.\n */\nconst CF_VOICE_IN_CALL_KEY = \"_cf_voiceInCall\";\n\n/**\n * Internal key used to remember the outer `/sub/...` URL for a\n * WebSocket accepted by the parent on behalf of a child facet.\n * Hibernated events then wake the parent, which forwards frames to\n * the child over serializable RPC while keeping native WebSocket I/O\n * parent-owned.\n */\nconst CF_SUB_AGENT_OUTER_URL_KEY = \"_cf_subAgentOuterUrl\";\nconst CF_SUB_AGENT_TAGS_KEY = \"_cf_subAgentTags\";\n\nconst SUB_AGENT_OUTER_URL_HEADER = \"x-cf-agents-subagent-url\";\n\n/**\n * The set of all internal keys stored in connection state that must be\n * hidden from user code and preserved across setState calls.\n */\nconst CF_INTERNAL_KEYS: ReadonlySet<string> = new Set([\n CF_READONLY_KEY,\n CF_NO_PROTOCOL_KEY,\n CF_VOICE_IN_CALL_KEY,\n CF_SUB_AGENT_OUTER_URL_KEY,\n CF_SUB_AGENT_TAGS_KEY\n]);\n\n/** Check if a raw connection state object contains any internal keys. */\nfunction rawHasInternalKeys(raw: Record<string, unknown>): boolean {\n for (const key of Object.keys(raw)) {\n if (CF_INTERNAL_KEYS.has(key)) return true;\n }\n return false;\n}\n\n/** Return a copy of `raw` with all internal keys removed, or null if no user keys remain. */\nfunction stripInternalKeys(\n raw: Record<string, unknown>\n): Record<string, unknown> | null {\n const result: Record<string, unknown> = {};\n let hasUserKeys = false;\n for (const key of Object.keys(raw)) {\n if (!CF_INTERNAL_KEYS.has(key)) {\n result[key] = raw[key];\n hasUserKeys = true;\n }\n }\n return hasUserKeys ? result : null;\n}\n\n/** Return a copy containing only the internal keys present in `raw`. */\nfunction extractInternalFlags(\n raw: Record<string, unknown>\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const key of Object.keys(raw)) {\n if (CF_INTERNAL_KEYS.has(key)) {\n result[key] = raw[key];\n }\n }\n return result;\n}\n\n/** Max length for error strings broadcast to clients. */\nconst MAX_ERROR_STRING_LENGTH = 500;\n\n/**\n * Sanitize an error string before broadcasting to clients.\n * MCP error strings may contain untrusted content from external OAuth\n * providers — truncate and strip control characters to limit XSS risk.\n */\n// Regex to match C0 control characters (except \\t, \\n, \\r) and DEL.\nconst CONTROL_CHAR_RE = new RegExp(\n // oxlint-disable-next-line no-control-regex -- intentionally matching control chars for sanitization\n \"[\\\\u0000-\\\\u0008\\\\u000B\\\\u000C\\\\u000E-\\\\u001F\\\\u007F]\",\n \"g\"\n);\n\nfunction sanitizeErrorString(error: string | null): string | null {\n if (error === null) return null;\n // Strip control characters (keep printable ASCII + common unicode)\n let sanitized = error.replace(CONTROL_CHAR_RE, \"\");\n if (sanitized.length > MAX_ERROR_STRING_LENGTH) {\n sanitized = sanitized.substring(0, MAX_ERROR_STRING_LENGTH) + \"...\";\n }\n return sanitized;\n}\n\n/**\n * Tracks which agent constructors have already emitted the onStateUpdate\n * deprecation warning, so it fires at most once per class.\n */\nconst _onStateUpdateWarnedClasses = new WeakSet<Function>();\n\n/**\n * Tracks which agent constructors have already emitted the\n * sendIdentityOnConnect deprecation warning, so it fires at most once per class.\n */\nconst _sendIdentityWarnedClasses = new WeakSet<Function>();\n\n/**\n * Default options for Agent configuration.\n * Child classes can override specific options without spreading.\n */\nexport const DEFAULT_AGENT_STATIC_OPTIONS = {\n /** Whether the Agent should hibernate when inactive */\n hibernate: true,\n /** Whether to send identity (name, agent) to clients on connect */\n sendIdentityOnConnect: true,\n /**\n * Timeout in seconds before a running interval schedule is considered \"hung\"\n * and force-reset. Increase this if you have callbacks that legitimately\n * take longer than 30 seconds.\n */\n hungScheduleTimeoutSeconds: 30,\n /**\n * Interval in milliseconds for keepAlive() alarm heartbeats.\n * Lower values mean faster recovery after eviction but more frequent alarms.\n */\n keepAliveIntervalMs: DEFAULT_KEEP_ALIVE_INTERVAL_MS,\n /** Default retry options for schedule(), queue(), and this.retry() */\n retry: {\n maxAttempts: 3,\n baseDelayMs: 100,\n maxDelayMs: 3000\n } satisfies Required<RetryOptions>\n};\n\n/**\n * Fully resolved agent options — all fields are defined with concrete values.\n */\ninterface ResolvedAgentOptions {\n hibernate: boolean;\n sendIdentityOnConnect: boolean;\n hungScheduleTimeoutSeconds: number;\n keepAliveIntervalMs: number;\n retry: Required<RetryOptions>;\n}\n\n/**\n * Configuration options for the Agent.\n * Override in subclasses via `static options`.\n * All fields are optional - defaults are applied at runtime.\n * Note: `hibernate` defaults to `true` if not specified.\n */\nexport interface AgentStaticOptions {\n hibernate?: boolean;\n sendIdentityOnConnect?: boolean;\n hungScheduleTimeoutSeconds?: number;\n /**\n * Interval in milliseconds for keepAlive() alarm heartbeats.\n * Default: 30000 (30 seconds). Lower values mean faster recovery\n * after eviction but more frequent alarms.\n */\n keepAliveIntervalMs?: number;\n /** Default retry options for schedule(), queue(), and this.retry(). */\n retry?: RetryOptions;\n}\n\n/**\n * Parse the raw `retry_options` TEXT column from a SQLite row into a\n * typed `RetryOptions` object, or `undefined` if not set.\n */\nfunction parseRetryOptions(\n row: Record<string, unknown>\n): RetryOptions | undefined {\n const raw = row.retry_options;\n if (typeof raw !== \"string\") return undefined;\n return JSON.parse(raw) as RetryOptions;\n}\n\n/**\n * Resolve per-task retry options against class-level defaults and call\n * `tryN`. This is the shared retry-execution path used by both queue\n * flush and schedule alarm handlers.\n */\nfunction resolveRetryConfig(\n taskRetry: RetryOptions | undefined,\n defaults: Required<RetryOptions>\n): { maxAttempts: number; baseDelayMs: number; maxDelayMs: number } {\n return {\n maxAttempts: taskRetry?.maxAttempts ?? defaults.maxAttempts,\n baseDelayMs: taskRetry?.baseDelayMs ?? defaults.baseDelayMs,\n maxDelayMs: taskRetry?.maxDelayMs ?? defaults.maxDelayMs\n };\n}\n\nexport function getCurrentAgent<\n T extends Agent<Cloudflare.Env> = Agent<Cloudflare.Env>\n>(): {\n agent: T | undefined;\n connection: Connection | undefined;\n request: Request | undefined;\n email: AgentEmail | undefined;\n} {\n const store = agentContext.getStore() as\n | {\n agent: T;\n connection: Connection | undefined;\n request: Request | undefined;\n email: AgentEmail | undefined;\n }\n | undefined;\n if (!store) {\n return {\n agent: undefined,\n connection: undefined,\n request: undefined,\n email: undefined\n };\n }\n return store;\n}\n\n/**\n * Wraps a method to run within the agent context, ensuring getCurrentAgent() works properly\n * @param agent The agent instance\n * @param method The method to wrap\n * @returns A wrapped method that runs within the agent context\n */\n\n// oxlint-disable-next-line @typescript-eslint/no-explicit-any -- generic callable constraint\nfunction withAgentContext<T extends (...args: any[]) => any>(\n method: T\n): (\n this: Agent<Cloudflare.Env, unknown>,\n ...args: Parameters<T>\n) => ReturnType<T> {\n return function (...args: Parameters<T>): ReturnType<T> {\n const { agent } = getCurrentAgent();\n\n if (agent === this) {\n // already wrapped, so we can just call the method\n return method.apply(this, args);\n }\n // Crossing to a different Agent must not carry native I/O handles\n // from the previous request/WebSocket/email turn into the new DO.\n return agentContext.run(\n {\n agent: this,\n connection: undefined,\n request: undefined,\n email: undefined\n },\n () => {\n return method.apply(this, args);\n }\n );\n };\n}\n\n/**\n * Extract string keys from Env where the value is a Workflow binding.\n */\ntype WorkflowBinding<E> = {\n [K in keyof E & string]: E[K] extends Workflow ? K : never;\n}[keyof E & string];\n\n/**\n * Type for workflow name parameter.\n * When Env has typed Workflow bindings, provides autocomplete for those keys.\n * Also accepts any string for dynamic use cases and compatibility.\n * The `string & {}` trick preserves autocomplete while allowing any string.\n */\ntype WorkflowName<E> = WorkflowBinding<E> | (string & {});\n\n/**\n * Base class for creating Agent implementations\n * @template Env Environment type containing bindings\n * @template State State type to store within the Agent\n */\nexport class Agent<\n Env extends Cloudflare.Env = Cloudflare.Env,\n State = unknown,\n Props extends Record<string, unknown> = Record<string, unknown>\n> extends Server<Env, Props> {\n private _state = DEFAULT_STATE as State;\n private _disposables = new DisposableStore();\n private _destroyed = false;\n\n /**\n * Stores raw state accessors for wrapped connections.\n * Used by internal flag methods (readonly, no-protocol) to read/write\n * _cf_-prefixed keys without going through the user-facing state/setState.\n */\n private _rawStateAccessors = new WeakMap<\n Connection,\n {\n getRaw: () => Record<string, unknown> | null;\n setRaw: (state: unknown) => unknown;\n }\n >();\n\n /**\n * Cached persistence-hook dispatch mode, computed once in the constructor.\n * - \"new\" → call onStateChanged\n * - \"old\" → call onStateUpdate (deprecated)\n * - \"none\" → neither hook is overridden, skip entirely\n */\n private _persistenceHookMode: \"new\" | \"old\" | \"none\" = \"none\";\n\n /** True when this agent runs as a facet (sub-agent) inside a parent. */\n private _isFacet = false;\n\n /**\n * True only while the internal facet bootstrap RPC runs startup.\n * Startup may happen while the parent is handling a WebSocket\n * message, so protocol broadcasts must not touch any ambient\n * parent-owned WebSocket handles during this window.\n */\n private _suppressProtocolBroadcasts = false;\n private _cf_currentSubAgentBridge?: SubAgentConnectionBridgeLike;\n private _cf_virtualSubAgentConnections = new Map<\n string,\n StoredSubAgentConnection\n >();\n\n /**\n * Ancestor chain, root-first. Empty for top-level DOs; populated at\n * facet init time from the parent's own `selfPath`. Exposed publicly\n * via the `parentPath` getter.\n * @internal\n */\n private _parentPath: ReadonlyArray<{ className: string; name: string }> = [];\n\n /** True while user's onStart() is executing. Used to warn about non-idempotent schedule() calls. */\n private _insideOnStart = false;\n\n /** Tracks callbacks already warned about during this onStart() to avoid log spam. */\n private _warnedScheduleInOnStart = new Set<string>();\n\n /**\n * Number of active keepAlive() callers. When > 0, `_scheduleNextAlarm()`\n * caps the next alarm at `keepAliveIntervalMs` so the DO stays alive.\n * Purely in-memory — lost on eviction, which is correct because the\n * in-memory work keepAlive was protecting is also lost.\n * @internal\n */\n _keepAliveRefs = 0;\n\n /**\n * In-memory tokens for keepAlive leases acquired by facets and held\n * on the root alarm owner. Lost on eviction, like `_keepAliveRefs`,\n * because the in-memory work those leases were protecting is also gone.\n * @internal\n */\n private _facetKeepAliveTokens = new Set<string>();\n\n /** @internal In-memory set of fiber IDs running in this process. */\n private _runFiberActiveFibers = new Set<string>();\n /** @internal Prevents re-entrant recovery from overlapping alarm ticks. */\n private _runFiberRecoveryInProgress = false;\n\n private _ParentClass: typeof Agent<Env, State> =\n Object.getPrototypeOf(this).constructor;\n\n readonly mcp: MCPClientManager;\n\n /**\n * Initial state for the Agent\n * Override to provide default state values\n */\n initialState: State = DEFAULT_STATE as State;\n\n /**\n * Stable key for Workers AI session affinity (prefix-cache optimization).\n *\n * Uses the Durable Object ID, which is globally unique across all agent\n * classes and stable for the lifetime of the instance. Pass this value as\n * the `sessionAffinity` option when creating a Workers AI model so that\n * requests from the same agent instance are routed to the same backend\n * replica, improving KV-prefix-cache hit rates across conversation turns.\n *\n * @example\n * ```typescript\n * const workersai = createWorkersAI({ binding: this.env.AI });\n * const model = workersai(\"@cf/meta/llama-3.3-70b-instruct-fp8-fast\", {\n * sessionAffinity: this.sessionAffinity,\n * });\n * ```\n */\n get sessionAffinity(): string {\n return this.ctx.id.toString();\n }\n\n /**\n * Current state of the Agent\n */\n get state(): State {\n if (this._state !== DEFAULT_STATE) {\n // state was previously set, and populated internal state\n return this._state;\n }\n // looks like this is the first time the state is being accessed\n // check if the state was set in a previous life\n const result = this.sql<{ state: State | undefined }>`\n SELECT state FROM cf_agents_state WHERE id = ${STATE_ROW_ID}\n `;\n\n // Row existence is the signal that state was previously set.\n // This handles all values including falsy ones (null, 0, false, \"\").\n if (result.length > 0) {\n const state = result[0].state as string;\n\n try {\n this._state = JSON.parse(state);\n } catch (e) {\n console.error(\n \"Failed to parse stored state, falling back to initialState:\",\n e\n );\n if (this.initialState !== DEFAULT_STATE) {\n this._state = this.initialState;\n // Persist the fixed state to prevent future parse errors\n this._setStateInternal(this.initialState);\n } else {\n // No initialState defined - clear corrupted data to prevent infinite retry loop\n this.sql`DELETE FROM cf_agents_state WHERE id = ${STATE_ROW_ID}`;\n return undefined as State;\n }\n }\n return this._state;\n }\n\n // ok, this is the first time the state is being accessed\n // and the state was not set in a previous life\n // so we need to set the initial state (if provided)\n if (this.initialState === DEFAULT_STATE) {\n // no initial state provided, so we return undefined\n return undefined as State;\n }\n // initial state provided, so we set the state,\n // update db and return the initial state\n this._setStateInternal(this.initialState);\n return this.initialState;\n }\n\n /**\n * Agent configuration options.\n * Override in subclasses - only specify what you want to change.\n * @example\n * class SecureAgent extends Agent {\n * static options = { sendIdentityOnConnect: false };\n * }\n */\n static options: AgentStaticOptions = { hibernate: true };\n\n /**\n * Resolved options (merges defaults with subclass overrides).\n * Cached after first access — static options never change during the\n * lifetime of a Durable Object instance.\n */\n private _cachedOptions?: ResolvedAgentOptions;\n private get _resolvedOptions(): ResolvedAgentOptions {\n if (this._cachedOptions) return this._cachedOptions;\n const ctor = this.constructor as typeof Agent;\n const userRetry = ctor.options?.retry;\n this._cachedOptions = {\n hibernate:\n ctor.options?.hibernate ?? DEFAULT_AGENT_STATIC_OPTIONS.hibernate,\n sendIdentityOnConnect:\n ctor.options?.sendIdentityOnConnect ??\n DEFAULT_AGENT_STATIC_OPTIONS.sendIdentityOnConnect,\n hungScheduleTimeoutSeconds:\n ctor.options?.hungScheduleTimeoutSeconds ??\n DEFAULT_AGENT_STATIC_OPTIONS.hungScheduleTimeoutSeconds,\n keepAliveIntervalMs:\n ctor.options?.keepAliveIntervalMs ??\n DEFAULT_AGENT_STATIC_OPTIONS.keepAliveIntervalMs,\n retry: {\n maxAttempts:\n userRetry?.maxAttempts ??\n DEFAULT_AGENT_STATIC_OPTIONS.retry.maxAttempts,\n baseDelayMs:\n userRetry?.baseDelayMs ??\n DEFAULT_AGENT_STATIC_OPTIONS.retry.baseDelayMs,\n maxDelayMs:\n userRetry?.maxDelayMs ?? DEFAULT_AGENT_STATIC_OPTIONS.retry.maxDelayMs\n }\n };\n return this._cachedOptions;\n }\n\n /**\n * The observability implementation to use for the Agent\n */\n observability?: Observability = genericObservability;\n\n /**\n * Emit an observability event with auto-generated timestamp.\n * @internal\n */\n protected _emit(\n type: ObservabilityEvent[\"type\"],\n payload: Record<string, unknown> = {}\n ): void {\n this.observability?.emit({\n type,\n agent: this._ParentClass.name,\n name: this.name,\n payload,\n timestamp: Date.now()\n } as ObservabilityEvent);\n }\n\n /**\n * Execute SQL queries against the Agent's database\n * @template T Type of the returned rows\n * @param strings SQL query template strings\n * @param values Values to be inserted into the query\n * @returns Array of query results\n */\n sql<T = Record<string, string | number | boolean | null>>(\n strings: TemplateStringsArray,\n ...values: (string | number | boolean | null)[]\n ) {\n let query = \"\";\n try {\n // Construct the SQL query with placeholders\n query = strings.reduce(\n (acc, str, i) => acc + str + (i < values.length ? \"?\" : \"\"),\n \"\"\n );\n\n // Execute the SQL query with the provided values\n return [...this.ctx.storage.sql.exec(query, ...values)] as T[];\n } catch (e) {\n throw new SqlError(query, e);\n }\n }\n /**\n * Create all internal tables and run migrations if needed.\n * Called by the constructor on every wake. Idempotent — skips DDL when\n * the stored schema version matches CURRENT_SCHEMA_VERSION.\n *\n * Protected so that test agents can re-run the real migration path\n * after manipulating DB state (since ctx.abort() is unavailable in\n * local dev and the constructor only runs once per DO instance).\n */\n protected _ensureSchema(): void {\n // Schema version gating: skip all DDL on established DOs whose schema\n // is already up-to-date. We always create cf_agents_state first (cheap\n // idempotent DDL) and store the version as a row inside it.\n this.sql`\n CREATE TABLE IF NOT EXISTS cf_agents_state (\n id TEXT PRIMARY KEY NOT NULL,\n state TEXT\n )\n `;\n\n const versionRow = this.sql<{ state: string | null }>`\n SELECT state FROM cf_agents_state WHERE id = ${SCHEMA_VERSION_ROW_ID}\n `;\n const schemaVersion =\n versionRow.length > 0 ? Number(versionRow[0].state) : 0;\n\n if (schemaVersion < CURRENT_SCHEMA_VERSION) {\n this.sql`\n CREATE TABLE IF NOT EXISTS cf_agents_mcp_servers (\n id TEXT PRIMARY KEY NOT NULL,\n name TEXT NOT NULL,\n server_url TEXT NOT NULL,\n callback_url TEXT NOT NULL,\n client_id TEXT,\n auth_url TEXT,\n server_options TEXT\n )\n `;\n\n this.sql`\n CREATE TABLE IF NOT EXISTS cf_agents_queues (\n id TEXT PRIMARY KEY NOT NULL,\n payload TEXT,\n callback TEXT,\n created_at INTEGER DEFAULT (unixepoch())\n )\n `;\n\n this.sql`\n CREATE TABLE IF NOT EXISTS cf_agents_schedules (\n id TEXT PRIMARY KEY NOT NULL DEFAULT (randomblob(9)),\n callback TEXT,\n payload TEXT,\n type TEXT NOT NULL CHECK(type IN ('scheduled', 'delayed', 'cron', 'interval')),\n time INTEGER,\n delayInSeconds INTEGER,\n cron TEXT,\n intervalSeconds INTEGER,\n running INTEGER DEFAULT 0,\n created_at INTEGER DEFAULT (unixepoch()),\n execution_started_at INTEGER,\n retry_options TEXT,\n owner_path TEXT,\n owner_path_key TEXT\n )\n `;\n\n // Migration: Add columns for interval scheduling (for existing agents)\n // Use raw exec to avoid error logging through onError for expected failures\n const addColumnIfNotExists = (sql: string) => {\n try {\n this.ctx.storage.sql.exec(sql);\n } catch (e) {\n // Only ignore \"duplicate column\" errors, re-throw unexpected errors\n const message = e instanceof Error ? e.message : String(e);\n if (!message.toLowerCase().includes(\"duplicate column\")) {\n throw e;\n }\n }\n };\n\n addColumnIfNotExists(\n \"ALTER TABLE cf_agents_schedules ADD COLUMN intervalSeconds INTEGER\"\n );\n addColumnIfNotExists(\n \"ALTER TABLE cf_agents_schedules ADD COLUMN running INTEGER DEFAULT 0\"\n );\n addColumnIfNotExists(\n \"ALTER TABLE cf_agents_schedules ADD COLUMN execution_started_at INTEGER\"\n );\n addColumnIfNotExists(\n \"ALTER TABLE cf_agents_schedules ADD COLUMN retry_options TEXT\"\n );\n addColumnIfNotExists(\n \"ALTER TABLE cf_agents_schedules ADD COLUMN owner_path TEXT\"\n );\n addColumnIfNotExists(\n \"ALTER TABLE cf_agents_schedules ADD COLUMN owner_path_key TEXT\"\n );\n addColumnIfNotExists(\n \"ALTER TABLE cf_agents_queues ADD COLUMN retry_options TEXT\"\n );\n\n // Migration: Update CHECK constraint on type column to include 'interval'.\n // SQLite doesn't support ALTER TABLE to modify constraints, so we recreate\n // the table when the old constraint is detected.\n {\n const rows = this.ctx.storage.sql\n .exec(\n \"SELECT sql FROM sqlite_master WHERE type='table' AND name='cf_agents_schedules'\"\n )\n .toArray();\n if (rows.length > 0) {\n const ddl = String(rows[0].sql);\n if (!ddl.includes(\"'interval'\")) {\n // Drop any leftover temp table from a previous partial migration\n this.ctx.storage.sql.exec(\n \"DROP TABLE IF EXISTS cf_agents_schedules_new\"\n );\n this.ctx.storage.sql.exec(`\n CREATE TABLE cf_agents_schedules_new (\n id TEXT PRIMARY KEY NOT NULL DEFAULT (randomblob(9)),\n callback TEXT,\n payload TEXT,\n type TEXT NOT NULL CHECK(type IN ('scheduled', 'delayed', 'cron', 'interval')),\n time INTEGER,\n delayInSeconds INTEGER,\n cron TEXT,\n intervalSeconds INTEGER,\n running INTEGER DEFAULT 0,\n created_at INTEGER DEFAULT (unixepoch()),\n execution_started_at INTEGER,\n retry_options TEXT,\n owner_path TEXT,\n owner_path_key TEXT\n )\n `);\n this.ctx.storage.sql.exec(`\n INSERT INTO cf_agents_schedules_new\n (id, callback, payload, type, time, delayInSeconds, cron,\n intervalSeconds, running, created_at, execution_started_at, retry_options,\n owner_path, owner_path_key)\n SELECT id, callback, payload, type, time, delayInSeconds, cron,\n intervalSeconds, running, created_at, execution_started_at, retry_options,\n owner_path, owner_path_key\n FROM cf_agents_schedules\n `);\n this.ctx.storage.sql.exec(\"DROP TABLE cf_agents_schedules\");\n this.ctx.storage.sql.exec(\n \"ALTER TABLE cf_agents_schedules_new RENAME TO cf_agents_schedules\"\n );\n }\n }\n }\n\n // Workflow tracking table for Agent-Workflow integration\n this.sql`\n CREATE TABLE IF NOT EXISTS cf_agents_workflows (\n id TEXT PRIMARY KEY NOT NULL,\n workflow_id TEXT NOT NULL UNIQUE,\n workflow_name TEXT NOT NULL,\n status TEXT NOT NULL CHECK(status IN (\n 'queued', 'running', 'paused', 'errored',\n 'terminated', 'complete', 'waiting',\n 'waitingForPause', 'unknown'\n )),\n metadata TEXT,\n error_name TEXT,\n error_message TEXT,\n created_at INTEGER NOT NULL DEFAULT (unixepoch()),\n updated_at INTEGER NOT NULL DEFAULT (unixepoch()),\n completed_at INTEGER\n )\n `;\n\n this.sql`\n CREATE INDEX IF NOT EXISTS idx_workflows_status ON cf_agents_workflows(status)\n `;\n\n this.sql`\n CREATE INDEX IF NOT EXISTS idx_workflows_name ON cf_agents_workflows(workflow_name)\n `;\n\n // Clean up legacy STATE_WAS_CHANGED rows from the single-row state optimization\n this.ctx.storage.sql.exec(\n \"DELETE FROM cf_agents_state WHERE id = ?\",\n STATE_WAS_CHANGED\n );\n\n // v2: keepAlive no longer uses schedule rows. Remove any orphaned\n // heartbeat schedules left over from the previous implementation.\n if (schemaVersion < 2) {\n this.ctx.storage.sql.exec(\n \"DELETE FROM cf_agents_schedules WHERE callback = '_cf_keepAliveHeartbeat'\"\n );\n }\n\n // v3: durable fibers table for runFiber\n this.sql`\n CREATE TABLE IF NOT EXISTS cf_agents_runs (\n id TEXT PRIMARY KEY NOT NULL,\n name TEXT NOT NULL,\n snapshot TEXT,\n created_at INTEGER NOT NULL\n )\n `;\n\n // v5: root-side index of descendant facet fibers. The fiber's\n // authoritative row stays in the facet's own cf_agents_runs table;\n // this table only lets the root alarm owner know which facets need\n // recovery checks while they are idle.\n this.sql`\n CREATE TABLE IF NOT EXISTS cf_agents_facet_runs (\n owner_path TEXT NOT NULL,\n owner_path_key TEXT NOT NULL,\n run_id TEXT NOT NULL,\n created_at INTEGER NOT NULL,\n PRIMARY KEY (owner_path_key, run_id)\n )\n `;\n\n this.sql`\n CREATE INDEX IF NOT EXISTS idx_facet_runs_owner_path_key\n ON cf_agents_facet_runs(owner_path_key)\n `;\n\n this.sql`\n CREATE TABLE IF NOT EXISTS cf_agent_tool_runs (\n run_id TEXT PRIMARY KEY,\n parent_tool_call_id TEXT,\n agent_type TEXT NOT NULL,\n input_preview TEXT,\n input_redacted INTEGER NOT NULL DEFAULT 1,\n status TEXT NOT NULL,\n summary TEXT,\n output_json TEXT,\n error_message TEXT,\n display_metadata TEXT,\n display_order INTEGER NOT NULL DEFAULT 0,\n started_at INTEGER NOT NULL,\n completed_at INTEGER\n )\n `;\n\n this.sql`\n CREATE INDEX IF NOT EXISTS idx_agent_tool_runs_parent_tool_call_id\n ON cf_agent_tool_runs(parent_tool_call_id, display_order)\n `;\n\n addColumnIfNotExists(\n \"ALTER TABLE cf_agent_tool_runs ADD COLUMN output_json TEXT\"\n );\n\n // Mark schema as up-to-date\n this.sql`\n INSERT OR REPLACE INTO cf_agents_state (id, state)\n VALUES (${SCHEMA_VERSION_ROW_ID}, ${String(CURRENT_SCHEMA_VERSION)})\n `;\n }\n }\n\n constructor(ctx: AgentContext, env: Env) {\n super(ctx, env);\n\n if (!wrappedClasses.has(this.constructor)) {\n // Auto-wrap custom methods with agent context\n this._autoWrapCustomMethods();\n wrappedClasses.add(this.constructor);\n }\n\n this._ensureSchema();\n\n // Initialize MCPClientManager AFTER tables are created\n this.mcp = new MCPClientManager(this._ParentClass.name, \"0.0.1\", {\n storage: this.ctx.storage,\n createAuthProvider: (callbackUrl) =>\n this.createMcpOAuthProvider(callbackUrl)\n });\n\n // Broadcast server state whenever MCP state changes (register, connect, OAuth, remove, etc.)\n this._disposables.add(\n this.mcp.onServerStateChanged(async () => {\n this.broadcastMcpServers();\n })\n );\n\n // Emit MCP observability events\n this._disposables.add(\n this.mcp.onObservabilityEvent((event) => {\n this.observability?.emit({\n ...event,\n agent: this._ParentClass.name,\n name: this.name\n });\n })\n );\n // Compute persistence-hook dispatch mode once.\n // Throws immediately if both hooks are overridden on the same class.\n {\n const proto = Object.getPrototypeOf(this);\n const hasOwnNew = Object.prototype.hasOwnProperty.call(\n proto,\n \"onStateChanged\"\n );\n const hasOwnOld = Object.prototype.hasOwnProperty.call(\n proto,\n \"onStateUpdate\"\n );\n\n if (hasOwnNew && hasOwnOld) {\n throw new Error(\n `[Agent] Cannot override both onStateChanged and onStateUpdate. ` +\n `Remove onStateUpdate — it has been renamed to onStateChanged.`\n );\n }\n\n if (hasOwnOld) {\n const ctor = this.constructor;\n if (!_onStateUpdateWarnedClasses.has(ctor)) {\n _onStateUpdateWarnedClasses.add(ctor);\n console.warn(\n `[Agent] onStateUpdate is deprecated. Rename to onStateChanged — the behavior is identical.`\n );\n }\n }\n\n const base = Agent.prototype;\n if (proto.onStateChanged !== base.onStateChanged) {\n this._persistenceHookMode = \"new\";\n } else if (proto.onStateUpdate !== base.onStateUpdate) {\n this._persistenceHookMode = \"old\";\n }\n // default \"none\" already set in field initializer\n }\n\n const _onRequest = this.onRequest.bind(this);\n this.onRequest = (request: Request) => {\n return agentContext.run(\n { agent: this, connection: undefined, request, email: undefined },\n async () => {\n // Handle MCP OAuth callback if this is one\n const oauthResponse = await this.handleMcpOAuthCallback(request);\n if (oauthResponse) {\n return oauthResponse;\n }\n\n return this._tryCatch(() => _onRequest(request));\n }\n );\n };\n\n const _onMessage = this.onMessage.bind(this);\n this.onMessage = async (connection: Connection, message: WSMessage) => {\n if (await this._cf_forwardSubAgentWebSocketMessage(connection, message)) {\n return;\n }\n this._ensureConnectionWrapped(connection);\n return agentContext.run(\n { agent: this, connection, request: undefined, email: undefined },\n async () => {\n if (typeof message !== \"string\") {\n return this._tryCatch(() => _onMessage(connection, message));\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(message);\n } catch (_e) {\n // silently fail and let the onMessage handler handle it\n return this._tryCatch(() => _onMessage(connection, message));\n }\n\n if (isStateUpdateMessage(parsed)) {\n // Check if connection is readonly\n if (this.isConnectionReadonly(connection)) {\n // Send error response back to the connection\n connection.send(\n JSON.stringify({\n type: MessageType.CF_AGENT_STATE_ERROR,\n error: \"Connection is readonly\"\n })\n );\n return;\n }\n try {\n this._setStateInternal(parsed.state as State, connection);\n } catch (e) {\n // validateStateChange (or another sync error) rejected the update.\n // Log the full error server-side, send a generic message to the client.\n console.error(\"[Agent] State update rejected:\", e);\n connection.send(\n JSON.stringify({\n type: MessageType.CF_AGENT_STATE_ERROR,\n error: \"State update rejected\"\n })\n );\n }\n return;\n }\n\n if (isRPCRequest(parsed)) {\n try {\n const { id, method, args } = parsed;\n\n // Check if method exists and is callable\n const methodFn = this[method as keyof this];\n if (typeof methodFn !== \"function\") {\n throw new Error(`Method ${method} does not exist`);\n }\n\n if (!this._isCallable(method)) {\n throw new Error(`Method ${method} is not callable`);\n }\n\n const metadata = callableMetadata.get(methodFn as Function);\n\n // For streaming methods, pass a StreamingResponse object\n if (metadata?.streaming) {\n const stream = new StreamingResponse(connection, id);\n\n this._emit(\"rpc\", { method, streaming: true });\n\n try {\n await methodFn.apply(this, [stream, ...args]);\n } catch (err) {\n console.error(`Error in streaming method \"${method}\":`, err);\n this._emit(\"rpc:error\", {\n method,\n error: err instanceof Error ? err.message : String(err)\n });\n // Auto-close stream with error if method throws before closing\n if (!stream.isClosed) {\n stream.error(\n err instanceof Error ? err.message : String(err)\n );\n }\n }\n return;\n }\n\n // For regular methods, execute and send response\n const result = await methodFn.apply(this, args);\n\n this._emit(\"rpc\", { method, streaming: metadata?.streaming });\n\n const response: RPCResponse = {\n done: true,\n id,\n result,\n success: true,\n type: MessageType.RPC\n };\n connection.send(JSON.stringify(response));\n } catch (e) {\n // Send error response\n const response: RPCResponse = {\n error:\n e instanceof Error ? e.message : \"Unknown error occurred\",\n id: parsed.id,\n success: false,\n type: MessageType.RPC\n };\n connection.send(JSON.stringify(response));\n console.error(\"RPC error:\", e);\n this._emit(\"rpc:error\", {\n method: parsed.method,\n error: e instanceof Error ? e.message : String(e)\n });\n }\n return;\n }\n\n return this._tryCatch(() => _onMessage(connection, message));\n }\n );\n };\n\n const _onConnect = this.onConnect.bind(this);\n this.onConnect = async (connection: Connection, ctx: ConnectionContext) => {\n this._ensureConnectionWrapped(connection);\n const subAgentOuterUrl = ctx.request.headers.get(\n SUB_AGENT_OUTER_URL_HEADER\n );\n if (subAgentOuterUrl) {\n this._unsafe_setConnectionFlag(\n connection,\n CF_SUB_AGENT_OUTER_URL_KEY,\n subAgentOuterUrl\n );\n }\n if (\n await this._cf_forwardSubAgentWebSocketConnect(\n connection,\n ctx.request,\n {\n gate: false\n }\n )\n ) {\n return;\n }\n // TODO: This is a hack to ensure the state is sent after the connection is established\n // must fix this\n return agentContext.run(\n { agent: this, connection, request: ctx.request, email: undefined },\n async () => {\n // Check if connection should be readonly before sending any messages\n // so that the flag is set before the client can respond\n if (this.shouldConnectionBeReadonly(connection, ctx)) {\n this.setConnectionReadonly(connection, true);\n }\n\n // Check if protocol messages should be suppressed for this\n // connection. When disabled, no identity/state/MCP text frames\n // are sent — useful for binary-only clients (e.g. MQTT devices).\n if (this.shouldSendProtocolMessages(connection, ctx)) {\n // Send agent identity first so client knows which instance it's connected to\n // Can be disabled via static options for security-sensitive instance names\n if (this._resolvedOptions.sendIdentityOnConnect) {\n const ctor = this.constructor as typeof Agent;\n if (\n ctor.options?.sendIdentityOnConnect === undefined &&\n !_sendIdentityWarnedClasses.has(ctor) &&\n // Facets are always addressed via `/sub/{class}/{name}`\n // in the OUTER client URL, even though the request the\n // facet itself receives has that segment stripped by\n // `_cf_forwardToFacet`. The sendIdentityOnConnect\n // concern (name only reachable via identity push) does\n // not apply — skip the warning entirely for facets.\n !this._isFacet\n ) {\n // Only warn when using custom routing — with default routing\n // the name is already visible in the URL path (/agents/{class}/{name})\n // so sendIdentityOnConnect leaks no additional information.\n const urlPath = new URL(ctx.request.url).pathname;\n if (!urlPath.includes(this.name)) {\n _sendIdentityWarnedClasses.add(ctor);\n console.warn(\n `[Agent] ${ctor.name}: sending instance name \"${this.name}\" to clients ` +\n `via sendIdentityOnConnect (the name is not visible in the URL with ` +\n `custom routing). If this name is sensitive, add ` +\n `\\`static options = { sendIdentityOnConnect: false }\\` to opt out. ` +\n `Set it to true to silence this message.`\n );\n }\n }\n connection.send(\n JSON.stringify({\n name: this.name,\n agent: camelCaseToKebabCase(this._ParentClass.name),\n type: MessageType.CF_AGENT_IDENTITY\n })\n );\n }\n\n if (this.state) {\n connection.send(\n JSON.stringify({\n state: this.state,\n type: MessageType.CF_AGENT_STATE\n })\n );\n }\n\n connection.send(\n JSON.stringify({\n mcp: this.getMcpServers(),\n type: MessageType.CF_AGENT_MCP_SERVERS\n })\n );\n } else {\n this._setConnectionNoProtocol(connection);\n }\n\n this._emit(\"connect\", { connectionId: connection.id });\n await this._replayAgentToolRuns(connection);\n return this._tryCatch(() => _onConnect(connection, ctx));\n }\n );\n };\n\n const _onClose = this.onClose.bind(this);\n this.onClose = async (\n connection: Connection,\n code: number,\n reason: string,\n wasClean: boolean\n ) => {\n if (\n await this._cf_forwardSubAgentWebSocketClose(\n connection,\n code,\n reason,\n wasClean\n )\n ) {\n return;\n }\n return agentContext.run(\n { agent: this, connection, request: undefined, email: undefined },\n () => {\n this._emit(\"disconnect\", {\n connectionId: connection.id,\n code,\n reason\n });\n return _onClose(connection, code, reason, wasClean);\n }\n );\n };\n\n const _onStart = this.onStart.bind(this);\n this.onStart = async (props?: Props) => {\n return agentContext.run(\n {\n agent: this,\n connection: undefined,\n request: undefined,\n email: undefined\n },\n async () => {\n // Hydrate _isFacet from persistent storage so the flag\n // survives hibernation (the DO constructor resets it to false).\n const isFacet =\n await this.ctx.storage.get<boolean>(\"cf_agents_is_facet\");\n if (isFacet) this._isFacet = true;\n\n const storedParentPath = await this.ctx.storage.get<\n Array<{ className: string; name: string }>\n >(\"cf_agents_parent_path\");\n if (isValidParentPath(storedParentPath)) {\n this._parentPath = storedParentPath;\n }\n try {\n await this._cf_hydrateSubAgentConnectionsFromRoot();\n } catch (error) {\n console.warn(\n \"[Agent] Unable to hydrate sub-agent WebSocket connections:\",\n error\n );\n }\n\n await this._tryCatch(async () => {\n await this.mcp.restoreConnectionsFromStorage(this.name);\n await this._restoreRpcMcpServers();\n this.broadcastMcpServers();\n\n this._checkOrphanedWorkflows();\n await this._checkRunFibers();\n await this._reconcileAgentToolRuns();\n\n this._insideOnStart = true;\n this._warnedScheduleInOnStart.clear();\n try {\n return await _onStart(props);\n } finally {\n this._insideOnStart = false;\n }\n });\n }\n );\n };\n }\n\n /**\n * Check for workflows referencing unknown bindings and warn with migration suggestion.\n */\n private _checkOrphanedWorkflows(): void {\n // Get distinct workflow names with counts by active/completed status\n const distinctNames = this.sql<{\n workflow_name: string;\n total: number;\n active: number;\n completed: number;\n }>`\n SELECT \n workflow_name,\n COUNT(*) as total,\n SUM(CASE WHEN status NOT IN ('complete', 'errored', 'terminated') THEN 1 ELSE 0 END) as active,\n SUM(CASE WHEN status IN ('complete', 'errored', 'terminated') THEN 1 ELSE 0 END) as completed\n FROM cf_agents_workflows \n GROUP BY workflow_name\n `;\n\n const orphaned = distinctNames.filter(\n (row) => !this._findWorkflowBindingByName(row.workflow_name)\n );\n\n if (orphaned.length > 0) {\n const currentBindings = this._getWorkflowBindingNames();\n for (const {\n workflow_name: oldName,\n total,\n active,\n completed\n } of orphaned) {\n const suggestion =\n currentBindings.length === 1\n ? `this.migrateWorkflowBinding('${oldName}', '${currentBindings[0]}')`\n : `this.migrateWorkflowBinding('${oldName}', '<NEW_BINDING_NAME>')`;\n const breakdown =\n active > 0 && completed > 0\n ? ` (${active} active, ${completed} completed)`\n : active > 0\n ? ` (${active} active)`\n : ` (${completed} completed)`;\n console.warn(\n `[Agent] Found ${total} workflow(s) referencing unknown binding '${oldName}'${breakdown}. ` +\n `If you renamed the binding, call: ${suggestion}`\n );\n }\n }\n }\n\n /**\n * Broadcast a protocol message only to connections that have protocol\n * messages enabled. Connections where shouldSendProtocolMessages returned\n * false are excluded automatically.\n * @param msg The JSON-encoded protocol message\n * @param excludeIds Additional connection IDs to exclude (e.g. the source)\n */\n private _broadcastProtocol(msg: string, excludeIds: string[] = []) {\n if (this._suppressProtocolBroadcasts) return;\n\n const exclude = [...excludeIds];\n for (const conn of this.getConnections()) {\n if (!this.isConnectionProtocolEnabled(conn)) {\n exclude.push(conn.id);\n }\n }\n this.broadcast(msg, exclude);\n }\n\n private _setStateInternal(\n nextState: State,\n source: Connection | \"server\" = \"server\"\n ): void {\n // Validation/gating hook (sync only)\n this.validateStateChange(nextState, source);\n\n // Persist state — row existence in cf_agents_state is the signal that\n // state was set (no separate wasChanged flag needed).\n this._state = nextState;\n this.sql`\n INSERT OR REPLACE INTO cf_agents_state (id, state)\n VALUES (${STATE_ROW_ID}, ${JSON.stringify(nextState)})\n `;\n\n // Broadcast state to protocol-enabled connections, excluding the source\n this._broadcastProtocol(\n JSON.stringify({\n state: nextState,\n type: MessageType.CF_AGENT_STATE\n }),\n source !== \"server\" ? [source.id] : []\n );\n\n // Notification hook (non-gating). Run after broadcast and do not block.\n // Use waitUntil for reliability after the handler returns.\n const { connection, request, email } = agentContext.getStore() || {};\n this.ctx.waitUntil(\n (async () => {\n try {\n await agentContext.run(\n { agent: this, connection, request, email },\n async () => {\n this._emit(\"state:update\");\n await this._callStatePersistenceHook(nextState, source);\n }\n );\n } catch (e) {\n // onStateChanged/onStateUpdate errors should not affect state or broadcasts\n try {\n await this.onError(e);\n } catch {\n // swallow\n }\n }\n })()\n );\n }\n\n /**\n * Update the Agent's state\n * @param state New state to set\n * @throws Error if called from a readonly connection context\n */\n setState(state: State): void {\n // Check if the current context has a readonly connection\n const store = agentContext.getStore();\n if (store?.connection && this.isConnectionReadonly(store.connection)) {\n throw new Error(\"Connection is readonly\");\n }\n this._setStateInternal(state, \"server\");\n }\n\n /**\n * Wraps connection.state and connection.setState so that internal\n * _cf_-prefixed flags (readonly, no-protocol) are hidden from user code\n * and cannot be accidentally overwritten.\n *\n * Idempotent — safe to call multiple times on the same connection.\n * After hibernation, the _rawStateAccessors WeakMap is empty but the\n * connection's state getter still reads from the persisted WebSocket\n * attachment. Calling this method re-captures the raw getter so that\n * predicate methods (isConnectionReadonly, isConnectionProtocolEnabled)\n * work correctly post-hibernation.\n */\n private _ensureConnectionWrapped(connection: Connection) {\n if (this._rawStateAccessors.has(connection)) return;\n\n // Determine whether `state` is an accessor (getter) or a data property.\n // partyserver always defines `state` as a getter via Object.defineProperties,\n // but we handle the data-property case to stay robust for hibernate: false\n // and any future connection implementations.\n const descriptor = Object.getOwnPropertyDescriptor(connection, \"state\");\n\n let getRaw: () => Record<string, unknown> | null;\n let setRaw: (state: unknown) => unknown;\n\n if (descriptor?.get) {\n // Accessor property — bind the original getter directly.\n // The getter reads from the serialized WebSocket attachment, so it\n // always returns the latest value even after setState updates it.\n getRaw = descriptor.get.bind(connection) as () => Record<\n string,\n unknown\n > | null;\n setRaw = connection.setState.bind(connection);\n } else {\n // Data property — track raw state in a closure variable.\n // Reading `connection.state` after our override would call our filtered\n // getter (circular), so we snapshot the value here and keep it in sync.\n let rawState = (connection.state ?? null) as Record<\n string,\n unknown\n > | null;\n getRaw = () => rawState;\n setRaw = (state: unknown) => {\n rawState = state as Record<string, unknown> | null;\n return rawState;\n };\n }\n\n this._rawStateAccessors.set(connection, { getRaw, setRaw });\n\n // Override state getter to hide all internal _cf_ flags from user code\n Object.defineProperty(connection, \"state\", {\n configurable: true,\n enumerable: true,\n get() {\n const raw = getRaw();\n if (raw != null && typeof raw === \"object\" && rawHasInternalKeys(raw)) {\n return stripInternalKeys(raw);\n }\n return raw;\n }\n });\n\n // Override setState to preserve internal flags when user sets state\n Object.defineProperty(connection, \"setState\", {\n configurable: true,\n writable: true,\n value(stateOrFn: unknown | ((prev: unknown) => unknown)) {\n const raw = getRaw();\n const flags =\n raw != null && typeof raw === \"object\"\n ? extractInternalFlags(raw as Record<string, unknown>)\n : {};\n const hasFlags = Object.keys(flags).length > 0;\n\n let newUserState: unknown;\n if (typeof stateOrFn === \"function\") {\n // Pass only the user-visible state (without internal flags) to the callback\n const userVisible = hasFlags\n ? stripInternalKeys(raw as Record<string, unknown>)\n : raw;\n newUserState = (stateOrFn as (prev: unknown) => unknown)(userVisible);\n } else {\n newUserState = stateOrFn;\n }\n\n // Merge back internal flags if any were set\n if (hasFlags) {\n if (newUserState != null && typeof newUserState === \"object\") {\n return setRaw({\n ...(newUserState as Record<string, unknown>),\n ...flags\n });\n }\n // User set null — store just the flags\n return setRaw(flags);\n }\n return setRaw(newUserState);\n }\n });\n }\n\n /**\n * Mark a connection as readonly or readwrite\n * @param connection The connection to mark\n * @param readonly Whether the connection should be readonly (default: true)\n */\n setConnectionReadonly(connection: Connection, readonly = true) {\n this._ensureConnectionWrapped(connection);\n const accessors = this._rawStateAccessors.get(connection)!;\n const raw = (accessors.getRaw() as Record<string, unknown> | null) ?? {};\n if (readonly) {\n accessors.setRaw({ ...raw, [CF_READONLY_KEY]: true });\n } else {\n // Remove the key entirely instead of storing false — avoids dead keys\n // accumulating in the connection attachment.\n const { [CF_READONLY_KEY]: _, ...rest } = raw;\n accessors.setRaw(Object.keys(rest).length > 0 ? rest : null);\n }\n }\n\n /**\n * Check if a connection is marked as readonly.\n *\n * Safe to call after hibernation — re-wraps the connection if the\n * in-memory accessor cache was cleared.\n * @param connection The connection to check\n * @returns True if the connection is readonly\n */\n isConnectionReadonly(connection: Connection): boolean {\n this._ensureConnectionWrapped(connection);\n const raw = this._rawStateAccessors.get(connection)!.getRaw() as Record<\n string,\n unknown\n > | null;\n return !!raw?.[CF_READONLY_KEY];\n }\n\n /**\n * ⚠️ INTERNAL — DO NOT USE IN APPLICATION CODE. ⚠️\n *\n * Read an internal `_cf_`-prefixed flag from the raw connection state,\n * bypassing the user-facing state wrapper that strips internal keys.\n *\n * This exists for framework mixins (e.g. voice) that need to persist\n * flags in the connection attachment across hibernation. Application\n * code should use `connection.state` and `connection.setState()` instead.\n *\n * @internal\n */\n _unsafe_getConnectionFlag(connection: Connection, key: string): unknown {\n this._ensureConnectionWrapped(connection);\n const raw = this._rawStateAccessors.get(connection)!.getRaw() as Record<\n string,\n unknown\n > | null;\n return raw?.[key];\n }\n\n /**\n * ⚠️ INTERNAL — DO NOT USE IN APPLICATION CODE. ⚠️\n *\n * Write an internal `_cf_`-prefixed flag to the raw connection state,\n * bypassing the user-facing state wrapper. The key must be registered\n * in `CF_INTERNAL_KEYS` so it is preserved across user `setState` calls\n * and hidden from `connection.state`.\n *\n * @internal\n */\n _unsafe_setConnectionFlag(\n connection: Connection,\n key: string,\n value: unknown\n ): void {\n this._ensureConnectionWrapped(connection);\n const accessors = this._rawStateAccessors.get(connection)!;\n const raw = (accessors.getRaw() as Record<string, unknown> | null) ?? {};\n if (value === undefined) {\n const { [key]: _, ...rest } = raw;\n accessors.setRaw(Object.keys(rest).length > 0 ? rest : null);\n } else {\n accessors.setRaw({ ...raw, [key]: value });\n }\n }\n\n /**\n * Override this method to determine if a connection should be readonly on connect\n * @param _connection The connection that is being established\n * @param _ctx Connection context\n * @returns True if the connection should be readonly\n */\n shouldConnectionBeReadonly(\n _connection: Connection,\n _ctx: ConnectionContext\n ): boolean {\n return false;\n }\n\n /**\n * Override this method to control whether protocol messages are sent to a\n * connection. Protocol messages include identity (CF_AGENT_IDENTITY), state\n * sync (CF_AGENT_STATE), and MCP server lists (CF_AGENT_MCP_SERVERS).\n *\n * When this returns `false` for a connection, that connection will not\n * receive any protocol text frames — neither on connect nor via broadcasts.\n * This is useful for binary-only clients (e.g. MQTT devices) that cannot\n * handle JSON text frames.\n *\n * The connection can still send and receive regular messages, use RPC, and\n * participate in all non-protocol communication.\n *\n * @param _connection The connection that is being established\n * @param _ctx Connection context (includes the upgrade request)\n * @returns True if protocol messages should be sent (default), false to suppress them\n */\n shouldSendProtocolMessages(\n _connection: Connection,\n _ctx: ConnectionContext\n ): boolean {\n return true;\n }\n\n /**\n * Check if a connection has protocol messages enabled.\n * Protocol messages include identity, state sync, and MCP server lists.\n *\n * Safe to call after hibernation — re-wraps the connection if the\n * in-memory accessor cache was cleared.\n * @param connection The connection to check\n * @returns True if the connection receives protocol messages\n */\n isConnectionProtocolEnabled(connection: Connection): boolean {\n this._ensureConnectionWrapped(connection);\n const raw = this._rawStateAccessors.get(connection)!.getRaw() as Record<\n string,\n unknown\n > | null;\n return !raw?.[CF_NO_PROTOCOL_KEY];\n }\n\n /**\n * Mark a connection as having protocol messages disabled.\n * Called internally when shouldSendProtocolMessages returns false.\n */\n private _setConnectionNoProtocol(connection: Connection) {\n this._ensureConnectionWrapped(connection);\n const accessors = this._rawStateAccessors.get(connection)!;\n const raw = (accessors.getRaw() as Record<string, unknown> | null) ?? {};\n accessors.setRaw({ ...raw, [CF_NO_PROTOCOL_KEY]: true });\n }\n\n /**\n * Called before the Agent's state is persisted and broadcast.\n * Override to validate or reject an update by throwing an error.\n *\n * IMPORTANT: This hook must be synchronous.\n */\n // oxlint-disable-next-line eslint(no-unused-vars) -- params used by subclass overrides\n validateStateChange(nextState: State, source: Connection | \"server\") {\n // override this to validate state updates\n }\n\n /**\n * Called after the Agent's state has been persisted and broadcast to all clients.\n * This is a notification hook — errors here are routed to onError and do not\n * affect state persistence or client broadcasts.\n *\n * @param state Updated state\n * @param source Source of the state update (\"server\" or a client connection)\n */\n // oxlint-disable-next-line eslint(no-unused-vars) -- params used by subclass overrides\n onStateChanged(state: State | undefined, source: Connection | \"server\") {\n // override this to handle state updates after persist + broadcast\n }\n\n /**\n * @deprecated Renamed to `onStateChanged` — the behavior is identical.\n * `onStateUpdate` will be removed in the next major version.\n *\n * Called after the Agent's state has been persisted and broadcast to all clients.\n * This is a server-side notification hook. For the client-side state callback,\n * see the `onStateUpdate` option in `useAgent` / `AgentClient`.\n *\n * @param state Updated state\n * @param source Source of the state update (\"server\" or a client connection)\n */\n // oxlint-disable-next-line eslint(no-unused-vars) -- params used by subclass overrides\n onStateUpdate(state: State | undefined, source: Connection | \"server\") {\n // override this to handle state updates (deprecated — use onStateChanged)\n }\n\n /**\n * Dispatch to the appropriate persistence hook based on the mode\n * cached in the constructor. No prototype walks at call time.\n */\n private async _callStatePersistenceHook(\n state: State | undefined,\n source: Connection | \"server\"\n ): Promise<void> {\n switch (this._persistenceHookMode) {\n case \"new\":\n await this.onStateChanged(state, source);\n break;\n case \"old\":\n await this.onStateUpdate(state, source);\n break;\n // \"none\": neither hook overridden — skip\n }\n }\n\n /**\n * Called when the Agent receives an email via routeAgentEmail()\n * Override this method to handle incoming emails\n * @param payload Internal wire format — plain data + RpcTarget bridge\n */\n async _onEmail(payload: {\n from: string;\n to: string;\n headers: Headers;\n rawSize: number;\n _secureRouted?: boolean;\n _bridge: EmailBridge;\n }) {\n // nb: we use this roundabout way of getting to onEmail\n // because of https://github.com/cloudflare/workerd/issues/4499\n\n // Reconstruct the AgentEmail interface from the payload so the\n // user's onEmail handler sees the same API as before\n const email: AgentEmail = {\n from: payload.from,\n to: payload.to,\n headers: payload.headers,\n rawSize: payload.rawSize,\n _secureRouted: payload._secureRouted,\n getRaw: () => payload._bridge.getRaw(),\n setReject: (reason: string) => payload._bridge.setReject(reason),\n forward: (rcptTo: string, headers?: Headers) =>\n payload._bridge.forward(rcptTo, headers),\n reply: (options: { from: string; to: string; raw: string }) =>\n payload._bridge.reply(options)\n };\n\n return agentContext.run(\n { agent: this, connection: undefined, request: undefined, email },\n async () => {\n this._emit(\"email:receive\", {\n from: email.from,\n to: email.to,\n subject: email.headers.get(\"subject\") ?? undefined\n });\n if (\"onEmail\" in this && typeof this.onEmail === \"function\") {\n return this._tryCatch(() =>\n (this.onEmail as (email: AgentEmail) => Promise<void>)(email)\n );\n } else {\n console.log(\"Received email from:\", email.from, \"to:\", email.to);\n console.log(\"Subject:\", email.headers.get(\"subject\"));\n console.log(\n \"Implement onEmail(email: AgentEmail): Promise<void> in your agent to process emails\"\n );\n }\n }\n );\n }\n\n /**\n * Reply to an email\n * @param email The email to reply to\n * @param options Options for the reply\n * @param options.secret Secret for signing agent headers (enables secure reply routing).\n * Required if the email was routed via createSecureReplyEmailResolver.\n * Pass explicit `null` to opt-out of signing (not recommended for secure routing).\n * @returns void\n */\n async replyToEmail(\n email: AgentEmail,\n options: {\n fromName: string;\n subject?: string | undefined;\n body: string;\n contentType?: string;\n headers?: Record<string, string>;\n secret?: string | null;\n }\n ): Promise<void> {\n return this._tryCatch(async () => {\n // Enforce signing for emails routed via createSecureReplyEmailResolver\n if (email._secureRouted && options.secret === undefined) {\n throw new Error(\n \"This email was routed via createSecureReplyEmailResolver. \" +\n \"You must pass a secret to replyToEmail() to sign replies, \" +\n \"or pass explicit null to opt-out (not recommended).\"\n );\n }\n\n const agentName = camelCaseToKebabCase(this._ParentClass.name);\n const agentId = this.name;\n\n const { createMimeMessage } = await import(\"mimetext\");\n const msg = createMimeMessage();\n msg.setSender({ addr: email.to, name: options.fromName });\n msg.setRecipient(email.from);\n msg.setSubject(\n options.subject || `Re: ${email.headers.get(\"subject\")}` || \"No subject\"\n );\n msg.addMessage({\n contentType: options.contentType || \"text/plain\",\n data: options.body\n });\n\n const domain = email.from.split(\"@\")[1];\n const messageId = `<${agentId}@${domain}>`;\n msg.setHeader(\"In-Reply-To\", email.headers.get(\"Message-ID\")!);\n msg.setHeader(\"Message-ID\", messageId);\n msg.setHeader(\"X-Agent-Name\", agentName);\n msg.setHeader(\"X-Agent-ID\", agentId);\n\n // Sign headers if secret is provided (enables secure reply routing)\n if (typeof options.secret === \"string\") {\n const signedHeaders = await signAgentHeaders(\n options.secret,\n agentName,\n agentId\n );\n msg.setHeader(\"X-Agent-Sig\", signedHeaders[\"X-Agent-Sig\"]);\n msg.setHeader(\"X-Agent-Sig-Ts\", signedHeaders[\"X-Agent-Sig-Ts\"]);\n }\n\n if (options.headers) {\n for (const [key, value] of Object.entries(options.headers)) {\n msg.setHeader(key, value);\n }\n }\n await email.reply({\n from: email.to,\n raw: msg.asRaw(),\n to: email.from\n });\n\n // Emit after the send succeeds — from/to are swapped because\n // this is a reply: the agent (email.to) is now the sender.\n const rawSubject = email.headers.get(\"subject\");\n this._emit(\"email:reply\", {\n from: email.to,\n to: email.from,\n subject:\n options.subject ?? (rawSubject ? `Re: ${rawSubject}` : undefined)\n });\n });\n }\n\n /**\n * Send an outbound email via an Email Service binding.\n *\n * Automatically injects agent routing headers (X-Agent-Name, X-Agent-ID).\n * When `secret` is provided, signs headers with HMAC-SHA256 so that replies\n * can be routed back to this agent instance via createSecureReplyEmailResolver.\n *\n * @param options.binding The send_email binding (e.g. this.env.EMAIL)\n * @param options.to Recipient address(es)\n * @param options.from Sender address or {email, name} object\n * @param options.subject Email subject line\n * @param options.text Plain text body (at least one of text/html required)\n * @param options.html HTML body (at least one of text/html required)\n * @param options.replyTo Reply-to address\n * @param options.cc CC recipient(s)\n * @param options.bcc BCC recipient(s)\n * @param options.inReplyTo Message-ID of the email this is replying to (for threading)\n * @param options.headers Additional custom headers\n * @param options.secret Secret for signing agent routing headers\n * @returns The messageId from Email Service\n */\n async sendEmail(options: SendEmailOptions): Promise<EmailSendResult> {\n return this._tryCatch(async () => {\n if (!options.binding) {\n throw new Error(\n \"binding is required. Pass your send_email binding, \" +\n \"e.g. this.sendEmail({ binding: this.env.EMAIL, ... }).\"\n );\n }\n\n const agentName = camelCaseToKebabCase(this._ParentClass.name);\n const agentId = this.name;\n\n const headers: Record<string, string> = {\n ...options.headers,\n \"X-Agent-Name\": agentName,\n \"X-Agent-ID\": agentId\n };\n\n if (options.inReplyTo) {\n headers[\"In-Reply-To\"] = options.inReplyTo;\n }\n\n if (typeof options.secret === \"string\") {\n const signedHeaders = await signAgentHeaders(\n options.secret,\n agentName,\n agentId\n );\n headers[\"X-Agent-Sig\"] = signedHeaders[\"X-Agent-Sig\"];\n headers[\"X-Agent-Sig-Ts\"] = signedHeaders[\"X-Agent-Sig-Ts\"];\n }\n\n const result = await options.binding.send({\n from: options.from,\n to: options.to,\n subject: options.subject,\n text: options.text,\n html: options.html,\n replyTo: options.replyTo,\n cc: options.cc,\n bcc: options.bcc,\n headers\n });\n\n const fromAddr =\n typeof options.from === \"string\" ? options.from : options.from.email;\n this._emit(\"email:send\", {\n from: fromAddr,\n to: options.to,\n subject: options.subject\n });\n\n return result;\n });\n }\n\n private async _tryCatch<T>(fn: () => T | Promise<T>) {\n try {\n return await fn();\n } catch (e) {\n throw this.onError(e);\n }\n }\n\n /**\n * Automatically wrap custom methods with agent context\n * This ensures getCurrentAgent() works in all custom methods without decorators\n */\n private _autoWrapCustomMethods() {\n // Collect all methods from base prototypes (Agent and Server)\n const basePrototypes = [Agent.prototype, Server.prototype];\n const baseMethods = new Set<string>();\n for (const baseProto of basePrototypes) {\n let proto = baseProto;\n while (proto && proto !== Object.prototype) {\n const methodNames = Object.getOwnPropertyNames(proto);\n for (const methodName of methodNames) {\n baseMethods.add(methodName);\n }\n proto = Object.getPrototypeOf(proto);\n }\n }\n // Get all methods from the current instance's prototype chain\n let proto = Object.getPrototypeOf(this);\n let depth = 0;\n while (proto && proto !== Object.prototype && depth < 10) {\n const methodNames = Object.getOwnPropertyNames(proto);\n for (const methodName of methodNames) {\n const descriptor = Object.getOwnPropertyDescriptor(proto, methodName);\n\n // Skip if it's a private method, a base method, a getter, or not a function,\n if (\n baseMethods.has(methodName) ||\n methodName.startsWith(\"_\") ||\n !descriptor ||\n !!descriptor.get ||\n typeof descriptor.value !== \"function\"\n ) {\n continue;\n }\n\n // Now, methodName is confirmed to be a custom method/function\n // Wrap the custom method with context\n /* oxlint-disable @typescript-eslint/no-explicit-any -- dynamic method wrapping requires any */\n const wrappedFunction = withAgentContext(\n this[methodName as keyof this] as (...args: any[]) => any\n ) as any;\n /* oxlint-enable @typescript-eslint/no-explicit-any */\n\n // if the method is callable, copy the metadata from the original method\n if (this._isCallable(methodName)) {\n callableMetadata.set(\n wrappedFunction,\n callableMetadata.get(this[methodName as keyof this] as Function)!\n );\n }\n\n // set the wrapped function on the prototype\n this.constructor.prototype[methodName as keyof this] = wrappedFunction;\n }\n\n proto = Object.getPrototypeOf(proto);\n depth++;\n }\n }\n\n override onError(\n connection: Connection,\n error: unknown\n ): void | Promise<void>;\n override onError(error: unknown): void | Promise<void>;\n override onError(connectionOrError: Connection | unknown, error?: unknown) {\n let theError: unknown;\n if (connectionOrError && error) {\n theError = error;\n // this is a websocket connection error\n console.error(\n \"Error on websocket connection:\",\n (connectionOrError as Connection).id,\n theError\n );\n console.error(\n \"Override onError(connection, error) to handle websocket connection errors\"\n );\n } else {\n theError = connectionOrError;\n // this is a server error\n console.error(\"Error on server:\", theError);\n console.error(\"Override onError(error) to handle server errors\");\n }\n throw theError;\n }\n\n /**\n * Render content (not implemented in base class)\n */\n render() {\n throw new Error(\"Not implemented\");\n }\n\n /**\n * Retry an async operation with exponential backoff and jitter.\n * Retries on all errors by default. Use `shouldRetry` to bail early on non-retryable errors.\n *\n * @param fn The async function to retry. Receives the current attempt number (1-indexed).\n * @param options Retry configuration.\n * @param options.maxAttempts Maximum number of attempts (including the first). Falls back to static options, then 3.\n * @param options.baseDelayMs Base delay in ms for exponential backoff. Falls back to static options, then 100.\n * @param options.maxDelayMs Maximum delay cap in ms. Falls back to static options, then 3000.\n * @param options.shouldRetry Predicate called with the error and next attempt number. Return false to stop retrying immediately. Default: retry all errors.\n * @returns The result of fn on success.\n * @throws The last error if all attempts fail or shouldRetry returns false.\n */\n async retry<T>(\n fn: (attempt: number) => Promise<T>,\n options?: RetryOptions & {\n /** Return false to stop retrying a specific error. Receives the error and the next attempt number. Default: retry all errors. */\n shouldRetry?: (err: unknown, nextAttempt: number) => boolean;\n }\n ): Promise<T> {\n const defaults = this._resolvedOptions.retry;\n if (options) {\n validateRetryOptions(options, defaults);\n }\n return tryN(options?.maxAttempts ?? defaults.maxAttempts, fn, {\n baseDelayMs: options?.baseDelayMs ?? defaults.baseDelayMs,\n maxDelayMs: options?.maxDelayMs ?? defaults.maxDelayMs,\n shouldRetry: options?.shouldRetry\n });\n }\n\n /**\n * Queue a task to be executed in the future\n * @param callback Name of the method to call\n * @param payload Payload to pass to the callback\n * @param options Options for the queued task\n * @param options.retry Retry options for the callback execution\n * @returns The ID of the queued task\n */\n async queue<T = unknown>(\n callback: keyof this,\n payload: T,\n options?: { retry?: RetryOptions }\n ): Promise<string> {\n const id = nanoid(9);\n if (typeof callback !== \"string\") {\n throw new Error(\"Callback must be a string\");\n }\n\n if (typeof this[callback] !== \"function\") {\n throw new Error(`this.${callback} is not a function`);\n }\n\n if (options?.retry) {\n validateRetryOptions(options.retry, this._resolvedOptions.retry);\n }\n\n const retryJson = options?.retry ? JSON.stringify(options.retry) : null;\n\n this.sql`\n INSERT OR REPLACE INTO cf_agents_queues (id, payload, callback, retry_options)\n VALUES (${id}, ${JSON.stringify(payload)}, ${callback}, ${retryJson})\n `;\n\n this._emit(\"queue:create\", { callback: callback as string, id });\n\n void this._flushQueue().catch((e) => {\n console.error(\"Error flushing queue:\", e);\n });\n\n return id;\n }\n\n private _flushingQueue = false;\n\n private async _flushQueue() {\n if (this._flushingQueue) {\n return;\n }\n this._flushingQueue = true;\n try {\n while (true) {\n const result = this.sql<QueueItem<string>>`\n SELECT * FROM cf_agents_queues\n ORDER BY created_at ASC\n `;\n\n if (!result || result.length === 0) {\n break;\n }\n\n for (const row of result || []) {\n const callback = this[row.callback as keyof Agent<Env>];\n if (!callback) {\n console.error(`callback ${row.callback} not found`);\n await this.dequeue(row.id);\n continue;\n }\n const { connection, request, email } = agentContext.getStore() || {};\n await agentContext.run(\n {\n agent: this,\n connection,\n request,\n email\n },\n async () => {\n const retryOpts = parseRetryOptions(\n row as unknown as Record<string, unknown>\n );\n const { maxAttempts, baseDelayMs, maxDelayMs } =\n resolveRetryConfig(retryOpts, this._resolvedOptions.retry);\n const parsedPayload = JSON.parse(row.payload as string);\n try {\n await tryN(\n maxAttempts,\n async (attempt) => {\n if (attempt > 1) {\n this._emit(\"queue:retry\", {\n callback: row.callback,\n id: row.id,\n attempt,\n maxAttempts\n });\n }\n await (\n callback as (\n payload: unknown,\n queueItem: QueueItem<string>\n ) => Promise<void>\n ).bind(this)(parsedPayload, row);\n },\n { baseDelayMs, maxDelayMs }\n );\n } catch (e) {\n console.error(\n `queue callback \"${row.callback}\" failed after ${maxAttempts} attempts`,\n e\n );\n this._emit(\"queue:error\", {\n callback: row.callback,\n id: row.id,\n error: e instanceof Error ? e.message : String(e),\n attempts: maxAttempts\n });\n try {\n await this.onError(e);\n } catch {\n // swallow onError errors\n }\n } finally {\n this.dequeue(row.id);\n }\n }\n );\n }\n }\n } finally {\n this._flushingQueue = false;\n }\n }\n\n /**\n * Dequeue a task by ID\n * @param id ID of the task to dequeue\n */\n dequeue(id: string) {\n this.sql`DELETE FROM cf_agents_queues WHERE id = ${id}`;\n }\n\n /**\n * Dequeue all tasks\n */\n dequeueAll() {\n this.sql`DELETE FROM cf_agents_queues`;\n }\n\n /**\n * Dequeue all tasks by callback\n * @param callback Name of the callback to dequeue\n */\n dequeueAllByCallback(callback: string) {\n this.sql`DELETE FROM cf_agents_queues WHERE callback = ${callback}`;\n }\n\n /**\n * Get a queued task by ID\n * @param id ID of the task to get\n * @returns The task or undefined if not found\n */\n getQueue(id: string): QueueItem<string> | undefined {\n const result = this.sql<QueueItem<string>>`\n SELECT * FROM cf_agents_queues WHERE id = ${id}\n `;\n if (!result || result.length === 0) return undefined;\n const row = result[0];\n return {\n ...row,\n payload: JSON.parse(row.payload as unknown as string),\n retry: parseRetryOptions(row as unknown as Record<string, unknown>)\n };\n }\n\n /**\n * Get all queues by key and value\n * @param key Key to filter by\n * @param value Value to filter by\n * @returns Array of matching QueueItem objects\n */\n getQueues(key: string, value: string): QueueItem<string>[] {\n const result = this.sql<QueueItem<string>>`\n SELECT * FROM cf_agents_queues\n `;\n return result\n .filter(\n (row) => JSON.parse(row.payload as unknown as string)[key] === value\n )\n .map((row) => ({\n ...row,\n payload: JSON.parse(row.payload as unknown as string),\n retry: parseRetryOptions(row as unknown as Record<string, unknown>)\n }));\n }\n\n private _scheduleOwnerPathKey(\n path: ReadonlyArray<AgentPathStep> | null\n ): string | null {\n if (!path) return null;\n return path\n .map(\n (step) =>\n `${encodeURIComponent(step.className)}:${encodeURIComponent(step.name)}`\n )\n .join(\"/\");\n }\n\n private _facetRunRowsForPrefix(\n ownerPath: ReadonlyArray<AgentPathStep>\n ): FacetRunStorageRow[] {\n const rows = this.sql<FacetRunStorageRow>`\n SELECT owner_path, owner_path_key, run_id, created_at\n FROM cf_agents_facet_runs\n `;\n return rows.filter((row) => {\n try {\n const rowOwnerPath = JSON.parse(row.owner_path) as AgentPathStep[];\n return this._isSameAgentPathPrefix(ownerPath, rowOwnerPath);\n } catch {\n return false;\n }\n });\n }\n\n private _deleteFacetRunRowsForPrefix(\n ownerPath: ReadonlyArray<AgentPathStep>\n ): void {\n for (const row of this._facetRunRowsForPrefix(ownerPath)) {\n this.sql`\n DELETE FROM cf_agents_facet_runs\n WHERE owner_path_key = ${row.owner_path_key}\n AND run_id = ${row.run_id}\n `;\n }\n }\n\n private async _rootAlarmOwner(): Promise<RootFacetRpcSurface> {\n const root = this._parentPath[0];\n if (!root) {\n throw new Error(\"Facet scheduler delegation requires a root parent.\");\n }\n\n const ctx = this.ctx as unknown as Partial<FacetCapableCtx>;\n const binding = ctx.exports?.[root.className] as\n | DurableObjectNamespace\n | undefined;\n if (!binding) {\n throw new Error(\n `Unable to resolve root scheduler \"${root.className}\" for sub-agent schedule delegation.`\n );\n }\n\n return (await getServerByName<Cloudflare.Env, Agent>(\n binding as DurableObjectNamespace<Agent>,\n root.name\n )) as unknown as RootFacetRpcSurface;\n }\n\n private _validateScheduleCallback(\n when: Date | string | number,\n callback: keyof this,\n options?: { retry?: RetryOptions; idempotent?: boolean }\n ): asserts callback is Extract<keyof this, string> {\n if (typeof callback !== \"string\") {\n throw new Error(\"Callback must be a string\");\n }\n\n if (typeof this[callback] !== \"function\") {\n throw new Error(`this.${callback} is not a function`);\n }\n\n if (options?.retry) {\n validateRetryOptions(options.retry, this._resolvedOptions.retry);\n }\n\n if (\n this._insideOnStart &&\n options?.idempotent === undefined &&\n typeof when !== \"string\" &&\n !this._warnedScheduleInOnStart.has(callback)\n ) {\n this._warnedScheduleInOnStart.add(callback);\n console.warn(\n `schedule(\"${callback}\") called inside onStart() without { idempotent: true }. ` +\n `This creates a new row on every Durable Object restart, which can cause ` +\n `duplicate executions. Pass { idempotent: true } to deduplicate, or use ` +\n `scheduleEvery() for recurring tasks.`\n );\n }\n }\n\n /**\n * Insert (or, for idempotent calls, return the existing row for) a\n * schedule owned by either this top-level agent (`ownerPath === null`)\n * or a descendant facet. Returns `{ schedule, created }` — `created`\n * is `false` when an idempotent insert deduplicates onto an existing\n * row, so callers can suppress the `schedule:create` event in that\n * case to match historic semantics.\n * @internal\n */\n private async _insertScheduleForOwner<T = string>(\n ownerPath: ReadonlyArray<AgentPathStep> | null,\n when: Date | string | number,\n callback: string,\n payload?: T,\n options?: { retry?: RetryOptions; idempotent?: boolean }\n ): Promise<{ schedule: Schedule<T>; created: boolean }> {\n const ownerPathJson = ownerPath ? JSON.stringify(ownerPath) : null;\n const ownerPathKey = this._scheduleOwnerPathKey(ownerPath);\n const retryJson = options?.retry ? JSON.stringify(options.retry) : null;\n const payloadJson = JSON.stringify(payload);\n\n if (when instanceof Date) {\n const timestamp = Math.floor(when.getTime() / 1000);\n\n if (options?.idempotent) {\n const existing = this.sql<ScheduleStorageRow>`\n SELECT * FROM cf_agents_schedules\n WHERE type = 'scheduled'\n AND callback = ${callback}\n AND payload IS ${payloadJson}\n AND owner_path_key IS ${ownerPathKey}\n LIMIT 1\n `;\n\n if (existing.length > 0) {\n const row = existing[0];\n await this._scheduleNextAlarm();\n return {\n schedule: {\n callback: row.callback,\n id: row.id,\n payload: JSON.parse(row.payload) as T,\n retry: parseRetryOptions(\n row as unknown as Record<string, unknown>\n ),\n time: row.time,\n type: \"scheduled\"\n },\n created: false\n };\n }\n }\n\n const id = nanoid(9);\n this.sql`\n INSERT OR REPLACE INTO cf_agents_schedules\n (id, callback, payload, type, time, retry_options, owner_path, owner_path_key)\n VALUES\n (${id}, ${callback}, ${payloadJson}, 'scheduled', ${timestamp}, ${retryJson}, ${ownerPathJson}, ${ownerPathKey})\n `;\n\n await this._scheduleNextAlarm();\n return {\n schedule: {\n callback,\n id,\n payload: payload as T,\n retry: options?.retry,\n time: timestamp,\n type: \"scheduled\"\n },\n created: true\n };\n }\n\n if (typeof when === \"number\") {\n const timestamp = Math.floor((Date.now() + when * 1000) / 1000);\n\n if (options?.idempotent) {\n const existing = this.sql<ScheduleStorageRow>`\n SELECT * FROM cf_agents_schedules\n WHERE type = 'delayed'\n AND callback = ${callback}\n AND payload IS ${payloadJson}\n AND owner_path_key IS ${ownerPathKey}\n LIMIT 1\n `;\n\n if (existing.length > 0) {\n const row = existing[0];\n await this._scheduleNextAlarm();\n return {\n schedule: {\n callback: row.callback,\n delayInSeconds: row.delayInSeconds ?? 0,\n id: row.id,\n payload: JSON.parse(row.payload) as T,\n retry: parseRetryOptions(\n row as unknown as Record<string, unknown>\n ),\n time: row.time,\n type: \"delayed\"\n },\n created: false\n };\n }\n }\n\n const id = nanoid(9);\n this.sql`\n INSERT OR REPLACE INTO cf_agents_schedules\n (id, callback, payload, type, delayInSeconds, time, retry_options, owner_path, owner_path_key)\n VALUES\n (${id}, ${callback}, ${payloadJson}, 'delayed', ${when}, ${timestamp}, ${retryJson}, ${ownerPathJson}, ${ownerPathKey})\n `;\n\n await this._scheduleNextAlarm();\n return {\n schedule: {\n callback,\n delayInSeconds: when,\n id,\n payload: payload as T,\n retry: options?.retry,\n time: timestamp,\n type: \"delayed\"\n },\n created: true\n };\n }\n\n if (typeof when === \"string\") {\n const timestamp = Math.floor(getNextCronTime(when).getTime() / 1000);\n const idempotent = options?.idempotent !== false;\n\n if (idempotent) {\n const existing = this.sql<ScheduleStorageRow>`\n SELECT * FROM cf_agents_schedules\n WHERE type = 'cron'\n AND callback = ${callback}\n AND cron = ${when}\n AND payload IS ${payloadJson}\n AND owner_path_key IS ${ownerPathKey}\n LIMIT 1\n `;\n\n if (existing.length > 0) {\n const row = existing[0];\n await this._scheduleNextAlarm();\n return {\n schedule: {\n callback: row.callback,\n cron: row.cron ?? when,\n id: row.id,\n payload: JSON.parse(row.payload) as T,\n retry: parseRetryOptions(\n row as unknown as Record<string, unknown>\n ),\n time: row.time,\n type: \"cron\"\n },\n created: false\n };\n }\n }\n\n const id = nanoid(9);\n this.sql`\n INSERT OR REPLACE INTO cf_agents_schedules\n (id, callback, payload, type, cron, time, retry_options, owner_path, owner_path_key)\n VALUES\n (${id}, ${callback}, ${payloadJson}, 'cron', ${when}, ${timestamp}, ${retryJson}, ${ownerPathJson}, ${ownerPathKey})\n `;\n\n await this._scheduleNextAlarm();\n return {\n schedule: {\n callback,\n cron: when,\n id,\n payload: payload as T,\n retry: options?.retry,\n time: timestamp,\n type: \"cron\"\n },\n created: true\n };\n }\n\n throw new Error(\n `Invalid schedule type: ${JSON.stringify(when)}(${typeof when}) trying to schedule ${callback}`\n );\n }\n\n /**\n * Insert a schedule row owned by a descendant facet. Called via RPC\n * from the facet's `schedule()`. Returns `{ schedule, created }`\n * so the originating facet can suppress `schedule:create` on\n * idempotent dedup. This method does not emit observability\n * events itself.\n * @internal\n */\n async _cf_scheduleForFacet<T = string>(\n ownerPath: ReadonlyArray<AgentPathStep>,\n when: Date | string | number,\n callback: string,\n payload?: T,\n options?: { retry?: RetryOptions; idempotent?: boolean }\n ): Promise<{ schedule: Schedule<T>; created: boolean }> {\n return this._insertScheduleForOwner(\n ownerPath,\n when,\n callback,\n payload,\n options\n );\n }\n\n /**\n * Insert (or, for idempotent calls, return the existing row for) an\n * interval schedule. Mirrors {@link _insertScheduleForOwner} —\n * returns `{ schedule, created }` so callers can suppress\n * `schedule:create` on dedup.\n * @internal\n */\n private async _insertIntervalScheduleForOwner<T = string>(\n ownerPath: ReadonlyArray<AgentPathStep> | null,\n intervalSeconds: number,\n callback: string,\n payload?: T,\n options?: { retry?: RetryOptions; _idempotent?: boolean }\n ): Promise<{ schedule: Schedule<T>; created: boolean }> {\n const ownerPathJson = ownerPath ? JSON.stringify(ownerPath) : null;\n const ownerPathKey = this._scheduleOwnerPathKey(ownerPath);\n const idempotent = options?._idempotent !== false;\n const payloadJson = JSON.stringify(payload);\n\n if (idempotent) {\n const existing = this.sql<ScheduleStorageRow>`\n SELECT * FROM cf_agents_schedules\n WHERE type = 'interval'\n AND callback = ${callback}\n AND intervalSeconds = ${intervalSeconds}\n AND payload IS ${payloadJson}\n AND owner_path_key IS ${ownerPathKey}\n LIMIT 1\n `;\n\n if (existing.length > 0) {\n const row = existing[0];\n await this._scheduleNextAlarm();\n return {\n schedule: {\n callback: row.callback,\n id: row.id,\n intervalSeconds: row.intervalSeconds ?? intervalSeconds,\n payload: JSON.parse(row.payload) as T,\n retry: parseRetryOptions(row as unknown as Record<string, unknown>),\n time: row.time,\n type: \"interval\"\n },\n created: false\n };\n }\n }\n\n const id = nanoid(9);\n const timestamp = Math.floor((Date.now() + intervalSeconds * 1000) / 1000);\n const retryJson = options?.retry ? JSON.stringify(options.retry) : null;\n\n this.sql`\n INSERT OR REPLACE INTO cf_agents_schedules\n (id, callback, payload, type, intervalSeconds, time, running, retry_options, owner_path, owner_path_key)\n VALUES\n (${id}, ${callback}, ${payloadJson}, 'interval', ${intervalSeconds}, ${timestamp}, 0, ${retryJson}, ${ownerPathJson}, ${ownerPathKey})\n `;\n\n await this._scheduleNextAlarm();\n return {\n schedule: {\n callback,\n id,\n intervalSeconds,\n payload: payload as T,\n retry: options?.retry,\n time: timestamp,\n type: \"interval\"\n },\n created: true\n };\n }\n\n /**\n * Insert an interval schedule row owned by a descendant facet.\n * Called via RPC from the facet's `scheduleEvery()`. Returns\n * `{ schedule, created }` so the originating facet can suppress\n * `schedule:create` on idempotent dedup. This method does not\n * emit observability events itself.\n * @internal\n */\n async _cf_scheduleEveryForFacet<T = string>(\n ownerPath: ReadonlyArray<AgentPathStep>,\n intervalSeconds: number,\n callback: string,\n payload?: T,\n options?: { retry?: RetryOptions; _idempotent?: boolean }\n ): Promise<{ schedule: Schedule<T>; created: boolean }> {\n return this._insertIntervalScheduleForOwner(\n ownerPath,\n intervalSeconds,\n callback,\n payload,\n options\n );\n }\n\n /**\n * Cancel a schedule row owned by a descendant facet, scoped by\n * `owner_path_key` so siblings can't reach each other's rows.\n * Returns the canceled row's callback name so the originating\n * facet can emit `schedule:cancel`. This method does not emit\n * observability events itself.\n * @internal\n */\n async _cf_cancelScheduleForFacet(\n ownerPath: ReadonlyArray<AgentPathStep>,\n id: string\n ): Promise<{ ok: boolean; callback?: string }> {\n const ownerPathKey = this._scheduleOwnerPathKey(ownerPath);\n const result = this.sql<ScheduleStorageRow>`\n SELECT * FROM cf_agents_schedules\n WHERE id = ${id} AND owner_path_key IS ${ownerPathKey}\n `;\n if (result.length === 0) return { ok: false };\n\n const callback = result[0].callback;\n this.sql`\n DELETE FROM cf_agents_schedules\n WHERE id = ${id} AND owner_path_key IS ${ownerPathKey}\n `;\n await this._scheduleNextAlarm();\n return { ok: true, callback };\n }\n\n /**\n * Clean root-owned bookkeeping for a sub-tree of facets. This\n * bulk-cancels schedules whose `owner_path` starts with the given\n * prefix and deletes root-side facet fiber recovery leases for the\n * same sub-tree. Used by `deleteSubAgent` and recursive facet\n * destroy. Emits `schedule:cancel` on this agent (the alarm-owning\n * root) for each schedule row removed — the facets being torn down\n * may not be alive to receive the events themselves.\n * @internal\n */\n async _cf_cleanupFacetPrefix(\n ownerPath: ReadonlyArray<AgentPathStep>\n ): Promise<void> {\n const rows = this.sql<ScheduleStorageRow>`\n SELECT * FROM cf_agents_schedules\n WHERE owner_path IS NOT NULL\n `;\n const rowsToDelete = rows.filter((row) => {\n if (!row.owner_path) return false;\n try {\n const rowOwnerPath = JSON.parse(row.owner_path) as AgentPathStep[];\n return this._isSameAgentPathPrefix(ownerPath, rowOwnerPath);\n } catch {\n return false;\n }\n });\n\n for (const row of rowsToDelete) {\n this._emit(\"schedule:cancel\", {\n callback: row.callback,\n id: row.id\n });\n this.sql`DELETE FROM cf_agents_schedules WHERE id = ${row.id}`;\n }\n\n this._deleteFacetRunRowsForPrefix(ownerPath);\n await this._scheduleNextAlarm();\n }\n\n private _scheduleRowToSchedule<T>(row: ScheduleStorageRow): Schedule<T> {\n const base = {\n callback: row.callback,\n id: row.id,\n payload: JSON.parse(row.payload) as T,\n retry: parseRetryOptions(row as unknown as Record<string, unknown>)\n };\n\n switch (row.type) {\n case \"scheduled\":\n return {\n ...base,\n time: row.time,\n type: \"scheduled\"\n };\n case \"delayed\":\n return {\n ...base,\n delayInSeconds: row.delayInSeconds ?? 0,\n time: row.time,\n type: \"delayed\"\n };\n case \"cron\":\n return {\n ...base,\n cron: row.cron ?? \"\",\n time: row.time,\n type: \"cron\"\n };\n case \"interval\":\n return {\n ...base,\n intervalSeconds: row.intervalSeconds ?? 0,\n time: row.time,\n type: \"interval\"\n };\n }\n }\n\n private _getScheduleForOwner<T = string>(\n ownerPath: ReadonlyArray<AgentPathStep> | null,\n id: string\n ): Schedule<T> | undefined {\n const ownerPathKey = this._scheduleOwnerPathKey(ownerPath);\n const result = this.sql<ScheduleStorageRow>`\n SELECT * FROM cf_agents_schedules\n WHERE id = ${id} AND owner_path_key IS ${ownerPathKey}\n `;\n if (!result || result.length === 0) {\n return undefined;\n }\n return this._scheduleRowToSchedule<T>(result[0]);\n }\n\n private _listSchedulesForOwner<T = string>(\n ownerPath: ReadonlyArray<AgentPathStep> | null,\n criteria: ScheduleCriteria = {}\n ): Schedule<T>[] {\n const ownerPathKey = this._scheduleOwnerPathKey(ownerPath);\n let query = \"SELECT * FROM cf_agents_schedules WHERE owner_path_key IS ?\";\n const params: Array<string | number | null> = [ownerPathKey];\n\n if (criteria.id) {\n query += \" AND id = ?\";\n params.push(criteria.id);\n }\n\n if (criteria.type) {\n query += \" AND type = ?\";\n params.push(criteria.type);\n }\n\n if (criteria.timeRange) {\n query += \" AND time >= ? AND time <= ?\";\n const start = criteria.timeRange.start || new Date(0);\n const end = criteria.timeRange.end || new Date(999999999999999);\n params.push(\n Math.floor(start.getTime() / 1000),\n Math.floor(end.getTime() / 1000)\n );\n }\n\n return this.ctx.storage.sql\n .exec(query, ...params)\n .toArray()\n .map((row) =>\n this._scheduleRowToSchedule<T>(row as unknown as ScheduleStorageRow)\n );\n }\n\n /**\n * Read a single schedule row owned by a descendant facet.\n * @internal\n */\n async _cf_getScheduleForFacet(\n ownerPath: ReadonlyArray<AgentPathStep>,\n id: string\n ): Promise<Schedule<unknown> | undefined> {\n return this._getScheduleForOwner(ownerPath, id);\n }\n\n /**\n * List schedule rows owned by a descendant facet, scoped by\n * `owner_path_key` so siblings remain isolated from each other.\n * @internal\n */\n async _cf_listSchedulesForFacet(\n ownerPath: ReadonlyArray<AgentPathStep>,\n criteria: ScheduleCriteria = {}\n ): Promise<Schedule<unknown>[]> {\n return this._listSchedulesForOwner(ownerPath, criteria);\n }\n\n /**\n * Acquire a root-owned keepAlive ref on behalf of a descendant facet.\n * Facets share the root isolate but cannot set their own physical\n * alarm, so this lets facet work use the root alarm heartbeat.\n * @internal\n */\n async _cf_acquireFacetKeepAlive(\n ownerPath: ReadonlyArray<AgentPathStep>\n ): Promise<string> {\n const ownerPathKey = this._scheduleOwnerPathKey(ownerPath);\n const token = `${ownerPathKey ?? \"unknown\"}:${nanoid(9)}`;\n this._facetKeepAliveTokens.add(token);\n this._keepAliveRefs++;\n if (this._keepAliveRefs === 1) {\n await this._scheduleNextAlarm();\n }\n return token;\n }\n\n /**\n * Release a root-owned keepAlive ref previously acquired for a facet.\n * Idempotent so disposer calls can safely race or run twice.\n * @internal\n */\n async _cf_releaseFacetKeepAlive(token: string): Promise<void> {\n if (!this._facetKeepAliveTokens.delete(token)) return;\n this._keepAliveRefs = Math.max(0, this._keepAliveRefs - 1);\n await this._scheduleNextAlarm();\n }\n\n /**\n * Register a facet's durable run row in the root-side index so root\n * alarm housekeeping can dispatch recovery checks into idle facets.\n * The facet remains authoritative for snapshots and recovery hooks.\n * @internal\n */\n async _cf_registerFacetRun(\n ownerPath: ReadonlyArray<AgentPathStep>,\n runId: string\n ): Promise<void> {\n const ownerPathJson = JSON.stringify(ownerPath);\n const ownerPathKey = this._scheduleOwnerPathKey(ownerPath);\n if (!ownerPathKey) {\n throw new Error(\"_cf_registerFacetRun requires a non-empty owner path.\");\n }\n this.sql`\n INSERT OR REPLACE INTO cf_agents_facet_runs\n (owner_path, owner_path_key, run_id, created_at)\n VALUES\n (${ownerPathJson}, ${ownerPathKey}, ${runId}, ${Date.now()})\n `;\n await this._scheduleNextAlarm();\n }\n\n /**\n * Remove a completed facet fiber from the root-side index.\n * @internal\n */\n async _cf_unregisterFacetRun(\n ownerPath: ReadonlyArray<AgentPathStep>,\n runId: string\n ): Promise<void> {\n const ownerPathKey = this._scheduleOwnerPathKey(ownerPath);\n this.sql`\n DELETE FROM cf_agents_facet_runs\n WHERE owner_path_key IS ${ownerPathKey}\n AND run_id = ${runId}\n `;\n await this._scheduleNextAlarm();\n }\n\n /**\n * Schedule a task to be executed in the future\n *\n * Cron schedules are **idempotent by default** — calling `schedule(\"0 * * * *\", \"tick\")`\n * multiple times with the same callback, cron expression, and payload returns\n * the existing schedule instead of creating a duplicate. Set `idempotent: false`\n * to override this.\n *\n * For delayed and scheduled (Date) types, set `idempotent: true` to opt in\n * to the same dedup behavior (matched on callback + payload). This is useful\n * when calling `schedule()` in `onStart()` to avoid accumulating duplicate\n * rows across Durable Object restarts.\n *\n * @template T Type of the payload data\n * @param when When to execute the task (Date, seconds delay, or cron expression)\n * @param callback Name of the method to call\n * @param payload Data to pass to the callback\n * @param options Options for the scheduled task\n * @param options.retry Retry options for the callback execution\n * @param options.idempotent Dedup by callback+payload. Defaults to `true` for cron, `false` otherwise.\n * @returns Schedule object representing the scheduled task\n */\n async schedule<T = string>(\n when: Date | string | number,\n callback: keyof this,\n payload?: T,\n options?: { retry?: RetryOptions; idempotent?: boolean }\n ): Promise<Schedule<T>> {\n this._validateScheduleCallback(when, callback, options);\n\n const result = this._isFacet\n ? await (\n await this._rootAlarmOwner()\n )._cf_scheduleForFacet<T>(\n this.selfPath,\n when,\n callback,\n payload,\n options\n )\n : await this._insertScheduleForOwner(\n null,\n when,\n callback,\n payload,\n options\n );\n\n if (result.created) {\n this._emit(\"schedule:create\", {\n callback: result.schedule.callback,\n id: result.schedule.id\n });\n }\n return result.schedule;\n }\n\n /**\n * Schedule a task to run repeatedly at a fixed interval.\n *\n * This method is **idempotent** — calling it multiple times with the same\n * `callback`, `intervalSeconds`, and `payload` returns the existing schedule\n * instead of creating a duplicate. A different interval or payload is\n * treated as a distinct schedule and creates a new row.\n *\n * This makes it safe to call in `onStart()`, which runs on every Durable\n * Object wake:\n *\n * ```ts\n * async onStart() {\n * // Only one schedule is created, no matter how many times the DO wakes\n * await this.scheduleEvery(30, \"tick\");\n * }\n * ```\n *\n * @template T Type of the payload data\n * @param intervalSeconds Number of seconds between executions\n * @param callback Name of the method to call\n * @param payload Data to pass to the callback\n * @param options Options for the scheduled task\n * @param options.retry Retry options for the callback execution\n * @returns Schedule object representing the scheduled task\n */\n async scheduleEvery<T = string>(\n intervalSeconds: number,\n callback: keyof this,\n payload?: T,\n options?: { retry?: RetryOptions; _idempotent?: boolean }\n ): Promise<Schedule<T>> {\n // DO alarms have a max schedule time of 30 days\n const MAX_INTERVAL_SECONDS = 30 * 24 * 60 * 60; // 30 days in seconds\n\n if (typeof intervalSeconds !== \"number\" || intervalSeconds <= 0) {\n throw new Error(\"intervalSeconds must be a positive number\");\n }\n\n if (intervalSeconds > MAX_INTERVAL_SECONDS) {\n throw new Error(\n `intervalSeconds cannot exceed ${MAX_INTERVAL_SECONDS} seconds (30 days)`\n );\n }\n\n if (typeof callback !== \"string\") {\n throw new Error(\"Callback must be a string\");\n }\n\n if (typeof this[callback] !== \"function\") {\n throw new Error(`this.${callback} is not a function`);\n }\n\n if (options?.retry) {\n validateRetryOptions(options.retry, this._resolvedOptions.retry);\n }\n\n const result = this._isFacet\n ? await (\n await this._rootAlarmOwner()\n )._cf_scheduleEveryForFacet<T>(\n this.selfPath,\n intervalSeconds,\n callback,\n payload,\n options\n )\n : await this._insertIntervalScheduleForOwner(\n null,\n intervalSeconds,\n callback,\n payload,\n options\n );\n\n if (result.created) {\n this._emit(\"schedule:create\", {\n callback: result.schedule.callback,\n id: result.schedule.id\n });\n }\n return result.schedule;\n }\n\n /**\n * Get a scheduled task by ID\n * @template T Type of the payload data\n * @param id ID of the scheduled task\n * @returns The Schedule object or undefined if not found\n * @deprecated Use {@link getScheduleById}. This synchronous API cannot cross\n * Durable Object boundaries and throws inside sub-agents.\n */\n getSchedule<T = string>(id: string): Schedule<T> | undefined {\n if (this._isFacet) {\n throw new Error(\n \"getSchedule() is synchronous and cannot read parent-owned sub-agent schedules. \" +\n \"Use await this.getScheduleById(id) instead.\"\n );\n }\n return this._getScheduleForOwner(null, id);\n }\n\n /**\n * Get a scheduled task by ID.\n *\n * Unlike the deprecated synchronous {@link getSchedule}, this works inside\n * sub-agents by delegating to the top-level parent that owns the alarm.\n *\n * @template T Type of the payload data\n * @param id ID of the scheduled task\n * @returns The Schedule object or undefined if not found\n */\n async getScheduleById(id: string): Promise<Schedule<unknown> | undefined> {\n if (this._isFacet) {\n const root = await this._rootAlarmOwner();\n return root._cf_getScheduleForFacet(this.selfPath, id);\n }\n return this._getScheduleForOwner(null, id);\n }\n\n /**\n * Get scheduled tasks matching the given criteria\n * @template T Type of the payload data\n * @param criteria Criteria to filter schedules\n * @returns Array of matching Schedule objects\n * @deprecated Use {@link listSchedules}. This synchronous API cannot cross\n * Durable Object boundaries and throws inside sub-agents.\n */\n getSchedules<T = string>(criteria: ScheduleCriteria = {}): Schedule<T>[] {\n if (this._isFacet) {\n throw new Error(\n \"getSchedules() is synchronous and cannot read parent-owned sub-agent schedules. \" +\n \"Use await this.listSchedules(criteria) instead.\"\n );\n }\n\n return this._listSchedulesForOwner(null, criteria);\n }\n\n /**\n * List scheduled tasks matching the given criteria.\n *\n * Unlike the deprecated synchronous {@link getSchedules}, this works inside\n * sub-agents by delegating to the top-level parent that owns the alarm.\n *\n * @template T Type of the payload data\n * @param criteria Criteria to filter schedules\n * @returns Array of matching Schedule objects\n */\n async listSchedules(\n criteria: ScheduleCriteria = {}\n ): Promise<Schedule<unknown>[]> {\n if (this._isFacet) {\n const root = await this._rootAlarmOwner();\n return root._cf_listSchedulesForFacet(this.selfPath, criteria);\n }\n return this._listSchedulesForOwner(null, criteria);\n }\n\n /**\n * Cancel a scheduled task.\n *\n * Schedules are isolated by owner: a top-level agent's\n * `cancelSchedule(id)` only matches its own schedules, and a\n * sub-agent's `cancelSchedule(id)` only matches schedules it\n * created. To clear every schedule under a sub-agent (and its\n * descendants), call `parent.deleteSubAgent(Cls, name)` from the\n * parent — that bulk-cleans root-owned bookkeeping via\n * {@link _cf_cleanupFacetPrefix}.\n *\n * @param id ID of the task to cancel\n * @returns true if the task was cancelled, false if the task was not found\n */\n async cancelSchedule(id: string): Promise<boolean> {\n if (this._isFacet) {\n const root = await this._rootAlarmOwner();\n const result = await root._cf_cancelScheduleForFacet(this.selfPath, id);\n if (result.ok && result.callback) {\n this._emit(\"schedule:cancel\", { callback: result.callback, id });\n }\n return result.ok;\n }\n const schedule = this._getScheduleForOwner(null, id);\n if (!schedule) {\n return false;\n }\n\n this._emit(\"schedule:cancel\", {\n callback: schedule.callback,\n id: schedule.id\n });\n\n this.sql`DELETE FROM cf_agents_schedules WHERE id = ${id}`;\n\n await this._scheduleNextAlarm();\n return true;\n }\n\n /**\n * Keep the Durable Object alive via alarm heartbeats.\n * Returns a disposer function that stops the heartbeat when called.\n *\n * Use this when you have long-running work and need to prevent the\n * DO from going idle (eviction after ~70-140s of inactivity).\n * The heartbeat fires every `keepAliveIntervalMs` (default 30s) via the\n * alarm system, without creating schedule rows or emitting observability\n * events. Configure via `static options = { keepAliveIntervalMs: 5000 }`.\n *\n * In facets, delegates the physical heartbeat to the root parent\n * because facets do not have independent alarm slots.\n *\n * @example\n * ```ts\n * const dispose = await this.keepAlive();\n * try {\n * // ... long-running work ...\n * } finally {\n * dispose();\n * }\n * ```\n */\n async keepAlive(): Promise<() => void> {\n if (this._isFacet) {\n const root = await this._rootAlarmOwner();\n const token = await root._cf_acquireFacetKeepAlive(this.selfPath);\n let disposed = false;\n return () => {\n if (disposed) return;\n disposed = true;\n const release = root._cf_releaseFacetKeepAlive(token).catch((e) => {\n console.error(\"[Agent] Failed to release facet keepAlive:\", e);\n });\n this.ctx.waitUntil(release);\n };\n }\n\n this._keepAliveRefs++;\n\n if (this._keepAliveRefs === 1) {\n await this._scheduleNextAlarm();\n }\n\n let disposed = false;\n return () => {\n if (disposed) return;\n disposed = true;\n this._keepAliveRefs = Math.max(0, this._keepAliveRefs - 1);\n };\n }\n\n /**\n * Run an async function while keeping the Durable Object alive.\n * The heartbeat is automatically stopped when the function completes\n * (whether it succeeds or throws).\n *\n * This is the recommended way to use keepAlive — it guarantees cleanup\n * so you cannot forget to dispose the heartbeat.\n *\n * @example\n * ```ts\n * const result = await this.keepAliveWhile(async () => {\n * const data = await longRunningComputation();\n * return data;\n * });\n * ```\n */\n async keepAliveWhile<T>(fn: () => Promise<T>): Promise<T> {\n const dispose = await this.keepAlive();\n try {\n return await fn();\n } finally {\n dispose();\n }\n }\n\n // ── Fibers: durable execution ───────────────────────────────────────\n\n /**\n * Run a function as a durable fiber. The fiber is registered in SQLite\n * before execution, checkpointable during execution via `ctx.stash()`,\n * and recoverable after eviction via `onFiberRecovered`.\n *\n * - Row created in `cf_agents_runs` at start, deleted on completion\n * - `keepAlive()` held for the duration — prevents idle eviction\n * - Inline (await result) or fire-and-forget (`void this.runFiber(...)`)\n *\n * @param name Informational name for debugging and recovery filtering\n * @param fn Async function to execute. Receives a FiberContext with stash/snapshot.\n * @returns The return value of fn\n */\n async runFiber<T>(\n name: string,\n fn: (ctx: FiberContext) => Promise<T>\n ): Promise<T> {\n const id = nanoid();\n this.sql`\n INSERT INTO cf_agents_runs (id, name, snapshot, created_at)\n VALUES (${id}, ${name}, NULL, ${Date.now()})\n `;\n this._runFiberActiveFibers.add(id);\n\n let root: RootFacetRpcSurface | undefined;\n let registeredFacetRun = false;\n let dispose: () => void = () => {};\n try {\n if (this._isFacet) {\n root = await this._rootAlarmOwner();\n await root._cf_registerFacetRun(this.selfPath, id);\n registeredFacetRun = true;\n }\n\n dispose = await this.keepAlive();\n const stash = (data: unknown) => {\n this.sql`\n UPDATE cf_agents_runs SET snapshot = ${JSON.stringify(data)}\n WHERE id = ${id}\n `;\n };\n\n return await _fiberALS.run({ id, stash }, () =>\n fn({ id, stash, snapshot: null })\n );\n } finally {\n this._runFiberActiveFibers.delete(id);\n this.sql`DELETE FROM cf_agents_runs WHERE id = ${id}`;\n dispose();\n if (root && registeredFacetRun) {\n try {\n await root._cf_unregisterFacetRun(this.selfPath, id);\n } catch (e) {\n // Leave the root-side lease behind if cleanup fails; root\n // housekeeping will re-enter the facet and prune stale rows\n // once it observes that this fiber row no longer exists.\n console.error(\"[Agent] Failed to unregister facet fiber:\", e);\n }\n }\n }\n }\n\n /**\n * Checkpoint data for the currently executing fiber.\n * Uses AsyncLocalStorage to identify the correct fiber,\n * so it works correctly even with concurrent fibers.\n *\n * Throws if called outside a `runFiber` callback.\n */\n stash(data: unknown): void {\n const ctx = _fiberALS.getStore();\n if (!ctx) {\n throw new Error(\"stash() called outside a fiber\");\n }\n ctx.stash(data);\n }\n\n /**\n * Called when an interrupted fiber is detected after restart.\n * Override to implement recovery (re-invoke work, notify clients, etc.).\n *\n * Internal framework fibers are filtered by `_handleInternalFiberRecovery`\n * before this hook runs — users only see their own fibers.\n *\n * Default: logs a warning.\n */\n async onFiberRecovered(\n // oxlint-disable-next-line @typescript-eslint/no-unused-vars -- overridable hook\n _ctx: FiberRecoveryContext\n ): Promise<void> {\n console.warn(\n `[Agent] Fiber \"${_ctx.name}\" (${_ctx.id}) was interrupted. ` +\n \"Override onFiberRecovered to handle recovery.\"\n );\n }\n\n /**\n * Override point for subclasses to handle internal (framework) fibers\n * before the user's recovery hook fires. Return `true` if handled.\n * @internal\n */\n protected async _handleInternalFiberRecovery(\n // oxlint-disable-next-line @typescript-eslint/no-unused-vars -- override point\n _ctx: FiberRecoveryContext\n ): Promise<boolean> {\n return false;\n }\n\n /** @internal Detect fibers left by a dead process (runFiber system). */\n private async _checkRunFibers(): Promise<void> {\n if (this._runFiberRecoveryInProgress) return;\n this._runFiberRecoveryInProgress = true;\n\n try {\n const rows = this.sql<{\n id: string;\n name: string;\n snapshot: string | null;\n created_at: number;\n }>`SELECT id, name, snapshot, created_at FROM cf_agents_runs`;\n\n for (const row of rows) {\n if (this._runFiberActiveFibers.has(row.id)) continue;\n\n let snapshot: unknown = null;\n if (row.snapshot) {\n try {\n snapshot = JSON.parse(row.snapshot);\n } catch {\n console.warn(\n `[Agent] Corrupted snapshot for fiber ${row.id}, treating as null`\n );\n }\n }\n\n const ctx: FiberRecoveryContext = {\n id: row.id,\n name: row.name,\n snapshot,\n createdAt: row.created_at\n };\n\n try {\n const handled = await this._handleInternalFiberRecovery(ctx);\n if (!handled) {\n await this.onFiberRecovered(ctx);\n }\n } catch (e) {\n console.error(\n `[Agent] Fiber recovery failed for \"${ctx.name}\" (${ctx.id}):`,\n e\n );\n }\n\n this.sql`DELETE FROM cf_agents_runs WHERE id = ${row.id}`;\n }\n } finally {\n this._runFiberRecoveryInProgress = false;\n }\n }\n\n /** @internal */\n async _onAlarmHousekeeping(): Promise<void> {\n await this._checkRunFibers();\n await this._checkFacetRunFibers();\n }\n\n private _isSameAgentPathPrefix(\n prefix: ReadonlyArray<AgentPathStep>,\n path: ReadonlyArray<AgentPathStep>\n ): boolean {\n if (prefix.length > path.length) return false;\n return prefix.every(\n (step, index) =>\n step.className === path[index].className &&\n step.name === path[index].name\n );\n }\n\n /**\n * Root-side scan for durable fibers owned by descendant facets.\n * `cf_agents_facet_runs` is only an index; actual snapshots and\n * recovery hooks live in each facet's own `cf_agents_runs` table.\n * @internal\n */\n private async _checkFacetRunFibers(): Promise<void> {\n // Only the root owns the physical alarm and facet-run index.\n if (this._parentPath.length > 0) return;\n\n const rows = this.sql<FacetRunStorageRow>`\n SELECT owner_path, owner_path_key, run_id, created_at\n FROM cf_agents_facet_runs\n ORDER BY created_at ASC\n `;\n const firstRowByOwner = new Map<string, FacetRunStorageRow>();\n for (const row of rows) {\n if (!firstRowByOwner.has(row.owner_path_key)) {\n firstRowByOwner.set(row.owner_path_key, row);\n }\n }\n\n for (const row of firstRowByOwner.values()) {\n let ownerPath: AgentPathStep[];\n try {\n ownerPath = JSON.parse(row.owner_path) as AgentPathStep[];\n } catch (e) {\n console.warn(\n `[Agent] Corrupted facet fiber owner path for ${row.owner_path_key}; pruning stale lease.`,\n e\n );\n this.sql`\n DELETE FROM cf_agents_facet_runs\n WHERE owner_path_key = ${row.owner_path_key}\n `;\n continue;\n }\n\n try {\n const remaining = await this._cf_checkRunFibersForFacet(ownerPath);\n if (remaining === 0) {\n this.sql`\n DELETE FROM cf_agents_facet_runs\n WHERE owner_path_key = ${row.owner_path_key}\n `;\n }\n } catch (e) {\n // Keep the lease so a transient failure (e.g. facet init error)\n // gets retried on the next root heartbeat.\n console.error(\n `[Agent] Facet fiber recovery check failed for ${row.owner_path_key}:`,\n e\n );\n }\n }\n }\n\n /**\n * Dispatch a runFiber recovery check into the facet identified by\n * `ownerPath`. Returns the number of remaining local `cf_agents_runs`\n * rows on the target facet after recovery.\n * @internal\n */\n async _cf_checkRunFibersForFacet(\n ownerPath: ReadonlyArray<AgentPathStep>\n ): Promise<number> {\n const selfPath = this.selfPath;\n if (!this._isSameAgentPathPrefix(selfPath, ownerPath)) {\n throw new Error(\n `Facet fiber owner path does not descend from ${JSON.stringify(selfPath)}.`\n );\n }\n\n if (selfPath.length === ownerPath.length) {\n await this._checkRunFibers();\n const rows = this.sql<{ count: number }>`\n SELECT COUNT(*) as count FROM cf_agents_runs\n `;\n return rows[0]?.count ?? 0;\n }\n\n const next = ownerPath[selfPath.length];\n if (!this.hasSubAgent(next.className, next.name)) {\n // The facet was deleted or its registry was cleared. The root\n // should prune the root-side lease; there is no remaining child\n // storage to recover through the public registry path.\n return 0;\n }\n\n const stub = await this._cf_resolveSubAgent(next.className, next.name);\n const handle = stub as unknown as {\n _cf_checkRunFibersForFacet(\n ownerPath: ReadonlyArray<AgentPathStep>\n ): Promise<number>;\n };\n return handle._cf_checkRunFibersForFacet(ownerPath);\n }\n\n /**\n * Dispatch a scheduled callback into the facet identified by\n * `ownerPath`. Walks one step at a time: if `ownerPath` matches\n * `selfPath`, executes the callback locally; otherwise resolves\n * the next descendant facet and recurses through its own RPC.\n *\n * Called by the root's `alarm()` (which owns the physical alarm\n * for facet-owned schedules) and by intermediate facets while\n * walking down the chain.\n * @internal\n */\n async _cf_dispatchScheduledCallback(\n ownerPath: ReadonlyArray<AgentPathStep>,\n row: ScheduleStorageRow\n ): Promise<void> {\n const selfPath = this.selfPath;\n if (!this._isSameAgentPathPrefix(selfPath, ownerPath)) {\n throw new Error(\n `Schedule owner path does not descend from ${JSON.stringify(selfPath)}.`\n );\n }\n\n if (selfPath.length === ownerPath.length) {\n await this._executeScheduleCallback(row);\n return;\n }\n\n const next = ownerPath[selfPath.length];\n if (!this.hasSubAgent(next.className, next.name)) {\n throw new Error(\n `Scheduled sub-agent ${next.className} \"${next.name}\" no longer exists.`\n );\n }\n\n const stub = await this._cf_resolveSubAgent(next.className, next.name);\n const handle = stub as unknown as {\n _cf_dispatchScheduledCallback(\n ownerPath: ReadonlyArray<AgentPathStep>,\n row: ScheduleStorageRow\n ): Promise<void>;\n };\n await handle._cf_dispatchScheduledCallback(ownerPath, row);\n }\n\n /**\n * Recursively destroy a descendant facet identified by\n * `targetPath`. Walks down from `selfPath` until reaching the\n * target's immediate parent, where it cancels the target's\n * parent-owned schedules (and any descendants), removes the\n * target from the registry, and calls `ctx.facets.delete` to\n * wipe the target's storage.\n *\n * Called by a facet's own `destroy()` (via the root) so that\n * `this.destroy()` inside a sub-agent results in the same\n * cleanup as `parent.deleteSubAgent(Cls, name)` from the parent.\n * @internal\n */\n async _cf_destroyDescendantFacet(\n targetPath: ReadonlyArray<AgentPathStep>\n ): Promise<void> {\n const selfPath = this.selfPath;\n\n if (targetPath.length === 0) {\n throw new Error(\n \"_cf_destroyDescendantFacet: target path must not be empty.\"\n );\n }\n if (selfPath.length >= targetPath.length) {\n throw new Error(\n \"_cf_destroyDescendantFacet: target must be a strict descendant.\"\n );\n }\n if (!this._isSameAgentPathPrefix(selfPath, targetPath)) {\n throw new Error(\n \"_cf_destroyDescendantFacet: target path does not descend from this agent.\"\n );\n }\n\n // The root owns every schedule row; cancel the target's prefix\n // upfront so we don't have to make an extra round trip back from\n // each intermediate hop.\n if (this._parentPath.length === 0) {\n await this._cf_cleanupFacetPrefix(targetPath);\n }\n\n if (selfPath.length === targetPath.length - 1) {\n // We are the immediate parent of the target — perform the local\n // facet teardown the same way `deleteSubAgent` does.\n const target = targetPath[targetPath.length - 1];\n const ctx = this.ctx as unknown as Partial<FacetCapableCtx>;\n if (!ctx.facets) {\n throw new Error(\n \"destroy() (delegated from facet) is not supported in this runtime — \" +\n \"`ctx.facets` is unavailable. \" +\n \"Update to the latest `compatibility_date` in your wrangler.jsonc.\"\n );\n }\n try {\n ctx.facets.delete(`${target.className}\\0${target.name}`);\n } catch {\n // no-op — facet wasn't registered (already deleted / never spawned)\n }\n this._forgetSubAgent(target.className, target.name);\n return;\n }\n\n // Recurse one step deeper.\n const next = targetPath[selfPath.length];\n if (!this.hasSubAgent(next.className, next.name)) {\n // Already gone — schedules are cleared, nothing more to do.\n return;\n }\n const stub = await this._cf_resolveSubAgent(next.className, next.name);\n const handle = stub as unknown as {\n _cf_destroyDescendantFacet(\n targetPath: ReadonlyArray<AgentPathStep>\n ): Promise<void>;\n };\n await handle._cf_destroyDescendantFacet(targetPath);\n }\n\n private async _executeScheduleCallback(\n row: ScheduleStorageRow\n ): Promise<void> {\n const callback = this[row.callback as keyof Agent<Env>];\n if (!callback) {\n console.error(`callback ${row.callback} not found`);\n return;\n }\n\n await agentContext.run(\n {\n agent: this,\n connection: undefined,\n request: undefined,\n email: undefined\n },\n async () => {\n const retryOpts = parseRetryOptions(\n row as unknown as Record<string, unknown>\n );\n const { maxAttempts, baseDelayMs, maxDelayMs } = resolveRetryConfig(\n retryOpts,\n this._resolvedOptions.retry\n );\n\n let parsedPayload: unknown;\n try {\n parsedPayload = JSON.parse(row.payload as string);\n } catch (e) {\n console.error(\n `Failed to parse payload for schedule \"${row.id}\" (callback \"${row.callback}\")`,\n e\n );\n this._emit(\"schedule:error\", {\n callback: row.callback,\n id: row.id,\n error: e instanceof Error ? e.message : String(e),\n attempts: 0\n });\n return;\n }\n\n try {\n this._emit(\"schedule:execute\", {\n callback: row.callback,\n id: row.id\n });\n\n await tryN(\n maxAttempts,\n async (attempt) => {\n if (attempt > 1) {\n this._emit(\"schedule:retry\", {\n callback: row.callback,\n id: row.id,\n attempt,\n maxAttempts\n });\n }\n await (\n callback as (\n payload: unknown,\n schedule: Schedule<unknown>\n ) => Promise<void>\n ).bind(this)(parsedPayload, row as unknown as Schedule<unknown>);\n },\n { baseDelayMs, maxDelayMs }\n );\n } catch (e) {\n console.error(\n `error executing callback \"${row.callback}\" after ${maxAttempts} attempts`,\n e\n );\n this._emit(\"schedule:error\", {\n callback: row.callback,\n id: row.id,\n error: e instanceof Error ? e.message : String(e),\n attempts: maxAttempts\n });\n try {\n await this.onError(e);\n } catch {\n // swallow onError errors\n }\n }\n }\n );\n }\n\n private async _scheduleNextAlarm() {\n const nowMs = Date.now();\n const nowSeconds = Math.floor(nowMs / 1000);\n const hungCutoffSeconds =\n nowSeconds - this._resolvedOptions.hungScheduleTimeoutSeconds;\n\n // Find the earliest schedule row that is safe to execute now, even if it\n // is already overdue. Overdue schedules can happen after a DO restart\n // because the SQLite row survives but the in-memory alarm does not.\n const readySchedules = this.sql<{\n time: number;\n }>`\n SELECT time FROM cf_agents_schedules\n WHERE type != 'interval'\n OR running = 0\n OR coalesce(execution_started_at, 0) <= ${hungCutoffSeconds}\n ORDER BY time ASC\n LIMIT 1\n `;\n\n // Running interval schedules that are not hung yet still need a future\n // alarm so the runtime can re-check them once they cross the hung timeout.\n const recoveringIntervals = this.sql<{\n execution_started_at: number | null;\n }>`\n SELECT execution_started_at FROM cf_agents_schedules\n WHERE type = 'interval'\n AND running = 1\n AND coalesce(execution_started_at, 0) > ${hungCutoffSeconds}\n ORDER BY execution_started_at ASC\n LIMIT 1\n `;\n\n let nextTimeMs: number | null = null;\n if (readySchedules.length > 0 && \"time\" in readySchedules[0]) {\n nextTimeMs = Math.max(\n (readySchedules[0].time as number) * 1000,\n nowMs + 1\n );\n }\n\n if (\n recoveringIntervals.length > 0 &&\n recoveringIntervals[0].execution_started_at !== null\n ) {\n const recoveryTimeMs =\n (recoveringIntervals[0].execution_started_at +\n this._resolvedOptions.hungScheduleTimeoutSeconds) *\n 1000;\n nextTimeMs =\n nextTimeMs === null\n ? recoveryTimeMs\n : Math.min(nextTimeMs, recoveryTimeMs);\n }\n\n if (this._keepAliveRefs > 0) {\n const keepAliveMs = nowMs + this._resolvedOptions.keepAliveIntervalMs;\n nextTimeMs =\n nextTimeMs === null ? keepAliveMs : Math.min(nextTimeMs, keepAliveMs);\n }\n\n const facetRuns = this.sql<{ count: number }>`\n SELECT COUNT(*) as count FROM cf_agents_facet_runs\n `;\n if ((facetRuns[0]?.count ?? 0) > 0) {\n const facetRecoveryMs = nowMs + this._resolvedOptions.keepAliveIntervalMs;\n nextTimeMs =\n nextTimeMs === null\n ? facetRecoveryMs\n : Math.min(nextTimeMs, facetRecoveryMs);\n }\n\n if (nextTimeMs !== null) {\n await this.ctx.storage.setAlarm(nextTimeMs);\n } else {\n await this.ctx.storage.deleteAlarm();\n }\n }\n\n /**\n * Override PartyServer's onAlarm hook as a no-op.\n * Agent handles alarm logic directly in the alarm() method override,\n * but super.alarm() calls onAlarm() after #ensureInitialized(),\n * so we suppress the default \"Implement onAlarm\" warning.\n */\n onAlarm(): void {}\n\n /**\n * Method called when an alarm fires.\n * Executes any scheduled tasks that are due.\n *\n * Calls super.alarm() first to ensure PartyServer's #ensureInitialized()\n * runs, which resolves this.name from ctx.id.name (including for\n * facets, which are spawned with an explicit id so they have their\n * own ctx.id.name; pre-2026-03-15 alarms fall back to the legacy\n * __ps_name storage record) and calls onStart() if needed.\n *\n * @remarks\n * To schedule a task, please use the `this.schedule` method instead.\n * See {@link https://developers.cloudflare.com/agents/api-reference/schedule-tasks/}\n */\n async alarm() {\n // Ensure PartyServer initialization (name resolution, onStart) runs\n // before processing any scheduled tasks.\n await super.alarm();\n\n const now = Math.floor(Date.now() / 1000);\n\n // Get all schedules that should be executed now\n const result = this.sql<ScheduleStorageRow>`\n SELECT * FROM cf_agents_schedules WHERE time <= ${now}\n `;\n\n if (result && Array.isArray(result)) {\n // Warn when many stale one-shot rows share the same callback — this\n // usually means schedule() was called repeatedly (e.g. in onStart)\n // without idempotent:true and rows accumulated across restarts.\n const DUPLICATE_SCHEDULE_THRESHOLD = 10;\n const oneShotCounts = new Map<string, number>();\n for (const row of result) {\n if (row.type === \"delayed\" || row.type === \"scheduled\") {\n oneShotCounts.set(\n row.callback,\n (oneShotCounts.get(row.callback) ?? 0) + 1\n );\n }\n }\n for (const [cb, count] of oneShotCounts) {\n if (count >= DUPLICATE_SCHEDULE_THRESHOLD) {\n try {\n console.warn(\n `Processing ${count} stale \"${cb}\" schedules in a single alarm cycle. ` +\n `This usually means schedule() is being called repeatedly without ` +\n `the idempotent option. Consider using scheduleEvery() for recurring ` +\n `tasks or passing { idempotent: true } to schedule().`\n );\n this._emit(\"schedule:duplicate_warning\", {\n callback: cb,\n count,\n type: \"one-shot\"\n });\n } catch {\n // Warning emission is non-critical — never block row processing.\n }\n }\n }\n\n for (const row of result as ScheduleStorageRow[]) {\n let executed = false;\n\n // Overlap prevention for interval schedules with hung callback detection\n if (row.type === \"interval\" && row.running === 1) {\n const executionStartedAt =\n (row as { execution_started_at?: number }).execution_started_at ??\n 0;\n const hungTimeoutSeconds =\n this._resolvedOptions.hungScheduleTimeoutSeconds;\n const elapsedSeconds = now - executionStartedAt;\n\n if (elapsedSeconds < hungTimeoutSeconds) {\n console.warn(\n `Skipping interval schedule ${row.id}: previous execution still running`\n );\n continue;\n }\n // Previous execution appears hung, force reset and re-execute\n console.warn(\n `Forcing reset of hung interval schedule ${row.id} (started ${elapsedSeconds}s ago)`\n );\n }\n\n // Mark interval as running before execution\n if (row.type === \"interval\") {\n this\n .sql`UPDATE cf_agents_schedules SET running = 1, execution_started_at = ${now} WHERE id = ${row.id}`;\n }\n\n if (row.owner_path) {\n try {\n const ownerPath = JSON.parse(row.owner_path) as AgentPathStep[];\n await this._cf_dispatchScheduledCallback(ownerPath, row);\n } catch (e) {\n console.error(\n `error dispatching scheduled callback \"${row.callback}\"`,\n e\n );\n this._emit(\"schedule:error\", {\n callback: row.callback,\n id: row.id,\n error: e instanceof Error ? e.message : String(e),\n attempts: 0\n });\n try {\n await this.onError(e);\n } catch {\n // swallow onError errors\n }\n // Reset the in-flight flag for interval rows so the row\n // doesn't stay stuck in `running=1` when dispatch fails\n // (e.g. the facet's registry entry is missing). The next\n // alarm cycle will retry.\n if (row.type === \"interval\") {\n this.sql`\n UPDATE cf_agents_schedules SET running = 0 WHERE id = ${row.id}\n `;\n }\n continue;\n }\n } else {\n await this._executeScheduleCallback(row);\n }\n executed = true;\n\n if (this._destroyed) return;\n if (!executed) continue;\n\n if (row.type === \"cron\") {\n // Update next execution time for cron schedules\n const nextExecutionTime = getNextCronTime(row.cron ?? \"\");\n const nextTimestamp = Math.floor(nextExecutionTime.getTime() / 1000);\n\n this.sql`\n UPDATE cf_agents_schedules SET time = ${nextTimestamp} WHERE id = ${row.id}\n `;\n } else if (row.type === \"interval\") {\n // Reset running flag and schedule next interval execution\n const nextTimestamp =\n Math.floor(Date.now() / 1000) + (row.intervalSeconds ?? 0);\n\n this.sql`\n UPDATE cf_agents_schedules SET running = 0, time = ${nextTimestamp} WHERE id = ${row.id}\n `;\n } else {\n // Delete one-time schedules after execution\n this.sql`\n DELETE FROM cf_agents_schedules WHERE id = ${row.id}\n `;\n }\n }\n }\n if (this._destroyed) return;\n\n await this._onAlarmHousekeeping();\n\n // Schedule the next alarm\n await this._scheduleNextAlarm();\n }\n\n // ── Sub-agent routing (external addressability for facets) ──────────────\n\n /**\n * Intercept incoming HTTP/WS requests whose URL contains a\n * `/sub/{child-class}/{child-name}` marker and forward them to\n * the facet. The `onBeforeSubAgent` hook fires first (authorize,\n * mutate, or short-circuit). If the hook doesn't return a\n * Response, the framework resolves the facet and hands the\n * request off.\n *\n * After a WebSocket upgrade completes, subsequent frames route\n * directly to the child — the parent is only on the path for the\n * initial request.\n *\n * @experimental The API surface may change before stabilizing.\n */\n override async fetch(request: Request): Promise<Response> {\n const ctx = this.ctx as unknown as Partial<FacetCapableCtx>;\n const match = _parseSubAgentPath(request.url, {\n knownClasses: ctx.exports ? Object.keys(ctx.exports) : undefined\n });\n\n if (!match) {\n return super.fetch(request);\n }\n\n // Hook runs in the parent's isolate before any facet work.\n const decision = await this.onBeforeSubAgent(request, {\n className: match.childClass,\n name: match.childName\n });\n if (decision instanceof Response) return decision;\n const forwardReq = decision instanceof Request ? decision : request;\n\n if (request.headers.get(\"Upgrade\")?.toLowerCase() === \"websocket\") {\n const acceptHeaders = new Headers(forwardReq.headers);\n const routedUrl = new URL(forwardReq.url);\n routedUrl.pathname = new URL(request.url).pathname;\n acceptHeaders.set(SUB_AGENT_OUTER_URL_HEADER, routedUrl.toString());\n return super.fetch(new Request(forwardReq, { headers: acceptHeaders }));\n }\n\n return this._cf_forwardToFacet(forwardReq, match);\n }\n\n override broadcast(\n msg: string | ArrayBuffer | ArrayBufferView,\n without?: string[]\n ): void {\n if (this._isFacet) {\n void this._cf_broadcastToParentSubAgent(msg, without);\n return;\n }\n\n for (const connection of super.getConnections()) {\n if (without?.includes(connection.id)) continue;\n if (this._cf_connectionHasSubAgentTarget(connection)) continue;\n connection.send(msg);\n }\n }\n\n override getConnection<TState = unknown>(\n id: string\n ): Connection<TState> | undefined {\n if (this._isFacet) {\n const stored = this._cf_virtualSubAgentConnections.get(id);\n if (stored) {\n return this._cf_createSubAgentBridgeConnection(\n stored.bridge,\n stored.meta\n ) as Connection<TState>;\n }\n }\n\n const connection = super.getConnection<TState>(id);\n if (!connection || this._cf_connectionHasSubAgentTarget(connection)) {\n return undefined;\n }\n return connection;\n }\n\n override *getConnections<TState = unknown>(\n tag?: string\n ): Iterable<Connection<TState>> {\n if (this._isFacet) {\n for (const stored of this._cf_virtualSubAgentConnections.values()) {\n if (!tag || stored.meta.tags.includes(tag)) {\n yield this._cf_createSubAgentBridgeConnection(\n stored.bridge,\n stored.meta\n ) as Connection<TState>;\n }\n }\n }\n\n for (const connection of super.getConnections<TState>(tag)) {\n if (this._cf_connectionHasSubAgentTarget(connection)) continue;\n yield connection;\n }\n }\n\n private async _cf_broadcastToParentSubAgent(\n message: string | ArrayBuffer | ArrayBufferView,\n without?: string[]\n ): Promise<void> {\n if (this._cf_currentSubAgentBridge) {\n this._cf_currentSubAgentBridge.broadcast(this.selfPath, message, without);\n return;\n }\n const root = await this._rootAlarmOwner();\n await root._cf_broadcastToSubAgent(this.selfPath, message, without);\n }\n\n async _cf_broadcastToSubAgent(\n ownerPath: ReadonlyArray<AgentPathStep>,\n message: string | ArrayBuffer | ArrayBufferView,\n without?: string[]\n ): Promise<void> {\n if (this._isFacet && this._cf_currentSubAgentBridge) {\n this._cf_currentSubAgentBridge.broadcast(ownerPath, message, without);\n return;\n }\n\n for (const connection of super.getConnections()) {\n if (without?.includes(connection.id)) continue;\n const targetPath = this._cf_subAgentTargetPath(connection);\n if (!targetPath) continue;\n if (!this._isSameAgentPath(targetPath, ownerPath)) continue;\n connection.send(message);\n }\n }\n\n async _cf_subAgentConnectionMetas(\n ownerPath: ReadonlyArray<AgentPathStep>\n ): Promise<SubAgentConnectionMeta[]> {\n const metas: SubAgentConnectionMeta[] = [];\n for (const connection of super.getConnections()) {\n const meta = this._cf_subAgentConnectionMetaForPath(\n connection,\n ownerPath\n );\n if (meta) metas.push(meta);\n }\n return metas;\n }\n\n async _cf_sendToSubAgentConnection(\n connectionId: string,\n message: string | ArrayBuffer | ArrayBufferView\n ): Promise<void> {\n const connection = super.getConnection(connectionId);\n if (!connection || !this._cf_connectionHasSubAgentTarget(connection)) {\n return;\n }\n connection.send(message);\n }\n\n async _cf_closeSubAgentConnection(\n connectionId: string,\n code?: number,\n reason?: string\n ): Promise<void> {\n const connection = super.getConnection(connectionId);\n if (!connection || !this._cf_connectionHasSubAgentTarget(connection)) {\n return;\n }\n connection.close(code, reason);\n }\n\n async _cf_setSubAgentConnectionState(\n connectionId: string,\n state: unknown\n ): Promise<unknown> {\n const connection = super.getConnection(connectionId);\n if (!connection || !this._cf_connectionHasSubAgentTarget(connection)) {\n return null;\n }\n this._ensureConnectionWrapped(connection);\n connection.setState(state);\n return this._cf_getForwardedSubAgentState(connection);\n }\n\n private _cf_subAgentConnectionMetaForPath(\n connection: Connection,\n ownerPath: ReadonlyArray<AgentPathStep>\n ): SubAgentConnectionMeta | null {\n this._ensureConnectionWrapped(connection);\n const outerUri = this._unsafe_getConnectionFlag(\n connection,\n CF_SUB_AGENT_OUTER_URL_KEY\n );\n if (typeof outerUri !== \"string\") return null;\n\n const target = this._cf_subAgentPathFromOuterUri(outerUri, ownerPath);\n if (!target) return null;\n\n const raw = this._cf_getRawConnectionState(connection);\n const rawTags =\n raw != null && typeof raw === \"object\"\n ? (raw as Record<string, unknown>)[CF_SUB_AGENT_TAGS_KEY]\n : undefined;\n const tags = Array.isArray(rawTags)\n ? rawTags.filter((tag): tag is string => typeof tag === \"string\")\n : [...connection.tags];\n return {\n id: connection.id,\n uri: target.uri,\n tags,\n state: this._cf_getForwardedSubAgentState(connection)\n };\n }\n\n private _cf_subAgentTargetPath(\n connection: Connection\n ): ReadonlyArray<AgentPathStep> | null {\n this._ensureConnectionWrapped(connection);\n const outerUri = this._unsafe_getConnectionFlag(\n connection,\n CF_SUB_AGENT_OUTER_URL_KEY\n );\n if (typeof outerUri !== \"string\") return null;\n\n return this._cf_subAgentPathFromOuterUri(outerUri)?.path ?? null;\n }\n\n private _cf_subAgentPathFromOuterUri(\n outerUri: string,\n stopAt?: ReadonlyArray<AgentPathStep>\n ): { path: ReadonlyArray<AgentPathStep>; uri: string } | null {\n const ctx = this.ctx as unknown as Partial<FacetCapableCtx>;\n const knownClasses = ctx.exports ? Object.keys(ctx.exports) : undefined;\n const path: AgentPathStep[] = [...this.selfPath];\n let currentUrl = outerUri;\n\n while (true) {\n const match = _parseSubAgentPath(currentUrl, { knownClasses });\n if (!match) break;\n path.push({ className: match.childClass, name: match.childName });\n const rewritten = new URL(currentUrl);\n rewritten.pathname = match.remainingPath;\n currentUrl = rewritten.toString();\n if (stopAt && this._isSameAgentPath(path, stopAt)) {\n return { path, uri: currentUrl };\n }\n }\n\n if (path.length === this.selfPath.length) return null;\n if (stopAt) return null;\n return { path, uri: currentUrl };\n }\n\n private _isSameAgentPath(\n a: ReadonlyArray<AgentPathStep>,\n b: ReadonlyArray<AgentPathStep>\n ): boolean {\n if (a.length !== b.length) return false;\n return a.every(\n (step, index) =>\n step.className === b[index]?.className && step.name === b[index]?.name\n );\n }\n\n private _cf_connectionHasSubAgentTarget(connection: Connection): boolean {\n this._ensureConnectionWrapped(connection);\n return (\n typeof this._unsafe_getConnectionFlag(\n connection,\n CF_SUB_AGENT_OUTER_URL_KEY\n ) === \"string\"\n );\n }\n\n protected _cf_connectionTargetsSubAgent(connection: Connection): boolean {\n if (!connection.uri) return false;\n const ctx = this.ctx as unknown as Partial<FacetCapableCtx>;\n return (\n _parseSubAgentPath(connection.uri, {\n knownClasses: ctx.exports ? Object.keys(ctx.exports) : undefined\n }) !== null\n );\n }\n\n /**\n * Returns true when the current request is addressed to a child facet of\n * this agent rather than to this agent itself.\n *\n * Chat-style subclasses wrap `onConnect` before the base Agent forwarding\n * wrapper runs, so they need a request-level check to avoid sending their\n * own protocol frames on sockets that are about to be forwarded to a child.\n */\n protected _cf_requestTargetsSubAgent(request: Request): boolean {\n const ctx = this.ctx as unknown as Partial<FacetCapableCtx>;\n return (\n _parseSubAgentPath(request.url, {\n knownClasses: ctx.exports ? Object.keys(ctx.exports) : undefined\n }) !== null\n );\n }\n\n private async _cf_forwardSubAgentWebSocketConnect(\n connection: Connection,\n request: Request,\n options: { gate: boolean }\n ): Promise<boolean> {\n const routed = await this._cf_resolveSubAgentConnection(\n connection,\n request,\n options\n );\n if (!routed) return false;\n\n await routed.child._cf_handleSubAgentWebSocketConnect(\n this._cf_createSubAgentConnectionBridge(connection),\n routed.meta\n );\n return true;\n }\n\n private _cf_createSubAgentConnectionBridge(\n connection: Connection\n ): SubAgentConnectionBridge {\n return new SubAgentConnectionBridge(\n connection,\n (ownerPath, message, without) => {\n void this._cf_broadcastToSubAgent(ownerPath, message, without);\n }\n );\n }\n\n private async _cf_forwardSubAgentWebSocketMessage(\n connection: Connection,\n message: WSMessage\n ): Promise<boolean> {\n const routed = await this._cf_resolveSubAgentConnection(connection);\n if (!routed) return false;\n\n await routed.child._cf_handleSubAgentWebSocketMessage(\n message,\n this._cf_createSubAgentConnectionBridge(connection),\n routed.meta\n );\n return true;\n }\n\n private async _cf_forwardSubAgentWebSocketClose(\n connection: Connection,\n code: number,\n reason: string,\n wasClean: boolean\n ): Promise<boolean> {\n const routed = await this._cf_resolveSubAgentConnection(connection);\n if (!routed) return false;\n\n await routed.child._cf_handleSubAgentWebSocketClose(\n code,\n reason,\n wasClean,\n this._cf_createSubAgentConnectionBridge(connection),\n routed.meta\n );\n return true;\n }\n\n private async _cf_resolveSubAgentConnection(\n connection: Connection,\n request?: Request,\n options: { gate: boolean } = { gate: false }\n ): Promise<{\n child: SubAgentWebSocketEndpoint;\n meta: SubAgentConnectionMeta;\n } | null> {\n this._ensureConnectionWrapped(connection);\n const outerUri = this._unsafe_getConnectionFlag(\n connection,\n CF_SUB_AGENT_OUTER_URL_KEY\n );\n const uri = typeof outerUri === \"string\" ? outerUri : connection.uri;\n if (!uri) return null;\n\n const ctx = this.ctx as unknown as Partial<FacetCapableCtx>;\n let match = _parseSubAgentPath(uri, {\n knownClasses: ctx.exports ? Object.keys(ctx.exports) : undefined\n });\n if (!match) return null;\n if (\n this._ParentClass.name === match.childClass &&\n this.name === match.childName\n ) {\n const tailUri = new URL(uri);\n tailUri.pathname = match.remainingPath;\n match = _parseSubAgentPath(tailUri.toString(), {\n knownClasses: ctx.exports ? Object.keys(ctx.exports) : undefined\n });\n if (!match) return null;\n }\n\n let forwardReq = request;\n if (request && options.gate) {\n const decision = await this.onBeforeSubAgent(request, {\n className: match.childClass,\n name: match.childName\n });\n if (decision instanceof Response) {\n connection.close(1008, \"Sub-agent connection rejected\");\n return null;\n }\n forwardReq = decision instanceof Request ? decision : request;\n }\n\n const child = (await this._cf_resolveSubAgent(\n match.childClass,\n match.childName\n )) as SubAgentWebSocketEndpoint;\n\n const childUri = new URL(forwardReq?.url ?? uri);\n childUri.pathname = match.remainingPath;\n const raw = this._cf_getRawConnectionState(connection);\n const rawTags =\n raw != null && typeof raw === \"object\"\n ? (raw as Record<string, unknown>)[CF_SUB_AGENT_TAGS_KEY]\n : undefined;\n const tags = Array.isArray(rawTags)\n ? rawTags.filter((tag): tag is string => typeof tag === \"string\")\n : [...connection.tags];\n\n return {\n child,\n meta: {\n id: connection.id,\n uri: childUri.toString(),\n tags,\n state: this._cf_getForwardedSubAgentState(connection),\n requestHeaders: forwardReq ? [...forwardReq.headers] : undefined\n }\n };\n }\n\n async _cf_handleSubAgentWebSocketConnect(\n bridge: SubAgentConnectionBridge,\n meta: SubAgentConnectionMeta\n ): Promise<void> {\n await this._cf_runWithSubAgentBridge(bridge, async () => {\n const connection = this._cf_createSubAgentBridgeConnection(bridge, meta);\n const request = new Request(meta.uri ?? \"http://placeholder/\", {\n headers: meta.requestHeaders\n });\n if (\n await this._cf_forwardSubAgentWebSocketConnect(connection, request, {\n gate: true\n })\n ) {\n return;\n }\n\n if (this.shouldConnectionBeReadonly(connection, { request })) {\n this.setConnectionReadonly(connection, true);\n }\n if (!this.shouldSendProtocolMessages(connection, { request })) {\n this._setConnectionNoProtocol(connection);\n }\n\n const childTags = await this.getConnectionTags(connection, { request });\n (connection as unknown as { tags: string[] }).tags = [\n connection.id,\n ...childTags.filter((tag) => tag !== connection.id)\n ];\n this._cf_storeVirtualSubAgentConnection(bridge, connection);\n await this.onConnect(connection, { request });\n this._cf_storeVirtualSubAgentConnection(bridge, connection);\n });\n }\n\n async _cf_handleSubAgentWebSocketMessage(\n message: WSMessage,\n bridge: SubAgentConnectionBridge,\n meta: SubAgentConnectionMeta\n ): Promise<void> {\n const connection = this._cf_createSubAgentBridgeConnection(bridge, meta);\n this._cf_storeVirtualSubAgentConnection(bridge, connection);\n await this._cf_runWithSubAgentBridge(bridge, () =>\n this.onMessage(connection, message)\n );\n }\n\n async _cf_handleSubAgentWebSocketClose(\n code: number,\n reason: string,\n wasClean: boolean,\n bridge: SubAgentConnectionBridge,\n meta: SubAgentConnectionMeta\n ): Promise<void> {\n const connection = this._cf_createSubAgentBridgeConnection(bridge, meta);\n this._cf_storeVirtualSubAgentConnection(bridge, connection);\n await this._cf_runWithSubAgentBridge(bridge, () =>\n this.onClose(connection, code, reason, wasClean)\n );\n this._cf_virtualSubAgentConnections.delete(meta.id);\n }\n\n private async _cf_runWithSubAgentBridge<T>(\n bridge: SubAgentConnectionBridgeLike,\n fn: () => Promise<T> | T\n ): Promise<T> {\n const previous = this._cf_currentSubAgentBridge;\n this._cf_currentSubAgentBridge = bridge;\n try {\n return await fn();\n } finally {\n this._cf_currentSubAgentBridge = previous;\n }\n }\n\n private _cf_createSubAgentBridgeConnection(\n bridge: SubAgentConnectionBridgeLike,\n meta: SubAgentConnectionMeta\n ): Connection {\n let stored = this._cf_virtualSubAgentConnections.get(meta.id);\n if (stored) {\n stored.bridge = bridge;\n stored.meta = meta;\n if (stored.connection) {\n (\n stored.connection as unknown as {\n uri: string | null;\n tags: string[];\n }\n ).uri = meta.uri;\n (\n stored.connection as unknown as {\n uri: string | null;\n tags: string[];\n }\n ).tags = meta.tags;\n return stored.connection;\n }\n } else {\n stored = { bridge, meta };\n this._cf_virtualSubAgentConnections.set(meta.id, stored);\n }\n\n const getStored = () =>\n this._cf_virtualSubAgentConnections.get(meta.id) ?? stored;\n const updateStoredState = (nextState: unknown) => {\n const current = this._cf_virtualSubAgentConnections.get(meta.id);\n if (current) {\n current.meta = { ...current.meta, state: nextState };\n }\n };\n\n const connection = {\n id: meta.id,\n uri: meta.uri,\n tags: meta.tags,\n server: this.name,\n get state() {\n return getStored().meta.state;\n },\n setState(next: unknown | ((prev: unknown) => unknown)) {\n const currentState = getStored().meta.state;\n const state = typeof next === \"function\" ? next(currentState) : next;\n updateStoredState(state);\n void getStored().bridge.setState(state);\n return state;\n },\n send(message: string | ArrayBuffer | ArrayBufferView) {\n void getStored().bridge.send(message);\n },\n close(code?: number, reason?: string) {\n void getStored().bridge.close(code, reason);\n },\n addEventListener() {},\n removeEventListener() {}\n } as unknown as Connection;\n\n stored.connection = connection;\n this._ensureConnectionWrapped(connection);\n return connection;\n }\n\n private _cf_storeVirtualSubAgentConnection(\n bridge: SubAgentConnectionBridgeLike,\n connection: Connection\n ): void {\n this._unsafe_setConnectionFlag(connection, CF_SUB_AGENT_TAGS_KEY, [\n ...connection.tags\n ]);\n const stored = this._cf_virtualSubAgentConnections.get(connection.id);\n this._cf_virtualSubAgentConnections.set(connection.id, {\n bridge,\n meta: {\n id: connection.id,\n uri: connection.uri,\n tags: [...connection.tags],\n state: this._cf_getRawConnectionState(connection)\n },\n connection: stored?.connection ?? connection\n });\n }\n\n protected async _cf_hydrateSubAgentConnectionsFromRoot(): Promise<void> {\n if (!this._isFacet || this._parentPath.length === 0) return;\n\n const root = await this._rootAlarmOwner();\n const metas = await root._cf_subAgentConnectionMetas(this.selfPath);\n for (const meta of metas) {\n this._cf_virtualSubAgentConnections.set(meta.id, {\n bridge: new RootSubAgentConnectionBridge(root, meta.id),\n meta\n });\n }\n }\n\n private _cf_getRawConnectionState(connection: Connection): unknown {\n this._ensureConnectionWrapped(connection);\n return this._rawStateAccessors.get(connection)?.getRaw() ?? null;\n }\n\n private _cf_getForwardedSubAgentState(connection: Connection): unknown {\n const raw = this._cf_getRawConnectionState(connection);\n if (raw == null || typeof raw !== \"object\") return raw;\n const { [CF_SUB_AGENT_OUTER_URL_KEY]: _, ...rest } = raw as Record<\n string,\n unknown\n >;\n return Object.keys(rest).length > 0 ? rest : null;\n }\n\n /**\n * Parent-side middleware hook. Fires before a request is\n * forwarded into a facet sub-agent. Mirrors `onBeforeConnect` /\n * `onBeforeRequest`.\n *\n * - return `void` (default) → forward the original request\n * - return `Request` → forward this (modified) request\n * - return `Response` → return this response to the\n * client; do not wake the child\n *\n * Default implementation: return void (permissive).\n *\n * The hook receives the **original** request with its URL intact —\n * including the `/sub/{class}/{name}` segment. The routing\n * decision for which facet to wake is fixed at parse time, so if\n * you return a modified `Request`, its headers, body, method, and\n * query string flow through to the child, but the **pathname**\n * the child sees is always the tail after `/sub/{class}/{name}`.\n * Customize via headers/body rather than URL-rewriting.\n *\n * WebSocket upgrade requests flow through this hook the same way as\n * plain HTTP. If you return a mutated `Request`, make sure it still\n * carries the original `Upgrade: websocket` and `Sec-WebSocket-*`\n * headers — the simplest safe recipe is to clone the incoming\n * request's headers (via `new Headers(req.headers)`) and only add\n * or replace entries, rather than constructing a fresh `Headers`\n * object from scratch.\n *\n * @experimental The API surface may change before stabilizing.\n *\n * @example\n * ```ts\n * class Inbox extends Agent {\n * override async onBeforeSubAgent(req, { className, name }) {\n * // Strict registry gate\n * if (!this.hasSubAgent(className, name)) {\n * return new Response(\"Not found\", { status: 404 });\n * }\n * }\n * }\n * ```\n */\n async onBeforeSubAgent(\n // oxlint-disable-next-line eslint(no-unused-vars) -- subclass override\n _request: Request,\n // oxlint-disable-next-line eslint(no-unused-vars) -- subclass override\n _child: { className: string; name: string }\n ): Promise<Request | Response | void> {\n return undefined;\n }\n\n /**\n * Resolve the facet Fetcher for the match and forward the\n * request to it with `/sub/{class}/{name}` stripped.\n *\n * @internal\n */\n private async _cf_forwardToFacet(\n req: Request,\n match: {\n childClass: string;\n childName: string;\n remainingPath: string;\n }\n ): Promise<Response> {\n let fetcher: { fetch(r: Request): Promise<Response> };\n try {\n fetcher = (await this._cf_resolveSubAgent(\n match.childClass,\n match.childName\n )) as { fetch(r: Request): Promise<Response> };\n } catch (err) {\n // Keep the wire response terse: don't leak the parent's view of\n // exports or internal error text over HTTP. The full error is\n // still available to developers via worker logs / `console.error`.\n const message = err instanceof Error ? err.message : String(err);\n console.error(\"[agents] sub-agent route failed:\", message);\n if (/null character/i.test(message) || /reserved/i.test(message)) {\n return new Response(\"Bad Request\", { status: 400 });\n }\n return new Response(\"Not Found\", { status: 404 });\n }\n\n // Rewrite the URL to strip the /sub/{class}/{name} prefix. The\n // child's own fetch then processes either its own request (if\n // no further /sub/... remains) or recurses into its own child.\n const rewritten = new URL(req.url);\n rewritten.pathname = match.remainingPath;\n const forwardedHeaders = new Headers(req.headers);\n const forwardedInit: RequestInit = {\n method: req.method,\n headers: forwardedHeaders\n };\n if (req.headers.get(\"Upgrade\")?.toLowerCase() === \"websocket\") {\n forwardedHeaders.set(SUB_AGENT_OUTER_URL_HEADER, req.url);\n }\n if (req.body && req.method !== \"GET\" && req.method !== \"HEAD\") {\n forwardedInit.body = await req.arrayBuffer();\n }\n const forwarded = new Request(rewritten, forwardedInit);\n return fetcher.fetch(forwarded);\n }\n\n /**\n * Bridge method used by `getSubAgentByName`. Resolves the facet\n * on each call (idempotent via `subAgent`) and dispatches one\n * RPC method. Stateless — no cached references.\n *\n * @internal\n */\n async _cf_invokeSubAgent(\n className: string,\n name: string,\n method: string,\n args: unknown[]\n ): Promise<unknown> {\n const stub = await this._cf_resolveSubAgent(className, name);\n // Must call `handle[method](...)` in one expression — extracting\n // via `const fn = handle[method]; fn.apply(handle, args)` breaks\n // the workerd RpcProperty binding. (Confirmed by the spike.)\n const handle = stub as unknown as Record<\n string,\n (...a: unknown[]) => Promise<unknown>\n >;\n if (typeof handle[method] !== \"function\") {\n throw new Error(`Method \"${method}\" not found on ${className}.`);\n }\n return await handle[method](...args);\n }\n\n // ── Sub-agent (facet) management ────────────────────────────────────────\n\n /**\n * Initialize this agent as a facet in a single RPC.\n *\n * Runs entirely inside the child's isolate, so every storage write\n * and `onStart()` I/O is owned by the child DO. This replaces the\n * previous \"construct a Request in the parent DO and `stub.fetch()`\n * it on the child\" handshake, whose native I/O was tied to the\n * parent and triggered \"Cannot perform I/O on behalf of a different\n * Durable Object\" on the child.\n *\n * We set `_isFacet` eagerly (before `__unsafe_ensureInitialized`\n * runs `onStart()`) so any code that legitimately branches on it\n * — e.g. skipping parent-owned alarms in schedule guards — sees\n * the flag during the first `onStart()` run. Protocol broadcasts are\n * suppressed only during this bootstrap window; afterward, facets can\n * broadcast to their own WebSocket clients reached via sub-agent\n * routing.\n *\n * The facet's name (and `this.name` getter) is handled entirely by\n * partyserver via `ctx.id.name`, which is populated because the\n * parent passed an explicit `id: parentNs.idFromName(name)` to\n * `ctx.facets.get()` — see {@link _cf_resolveSubAgent}. No\n * `setName()` call or `__ps_name` storage write is needed; the\n * facet's name survives cold wake automatically because the\n * factory re-runs and `idFromName` is deterministic.\n *\n * @internal Called by {@link subAgent}.\n */\n async _cf_initAsFacet(\n name: string,\n parentPath: ReadonlyArray<{ className: string; name: string }> = []\n ): Promise<void> {\n // Defense in depth: the parent is supposed to construct the\n // facet with `id: parentNs.idFromName(name)` via\n // `_cf_resolveSubAgent`, which makes `this.name` resolve to\n // `name` automatically through partyserver's `ctx.id.name`. If\n // it didn't (e.g. someone bypassed `_cf_resolveSubAgent`, or\n // the parent's id construction has a bug), `this.name` would\n // silently report the parent's name instead of the facet's\n // name. Fail loud instead of letting a misconfigured facet\n // operate with the wrong identity.\n if (this.name !== name) {\n throw new Error(\n `Facet bootstrap mismatch: expected this.name === \"${name}\" but got \"${this.name}\". ` +\n `This usually means the parent passed the wrong (or no) id to ctx.facets.get(). ` +\n `See _cf_resolveSubAgent.`\n );\n }\n this._isFacet = true;\n this._parentPath = parentPath;\n // Persist the agent-specific facet keys in parallel.\n await Promise.all([\n this.ctx.storage.put(\"cf_agents_is_facet\", true),\n this.ctx.storage.put(\"cf_agents_parent_path\", parentPath)\n ]);\n // Fire onStart() now since this RPC bypasses Server.fetch(),\n // which is the entry point that normally triggers it. Suppress\n // protocol broadcasts only during startup so bootstrap cannot touch\n // parent-owned WebSocket handles if the parent is inside onMessage().\n this._suppressProtocolBroadcasts = true;\n try {\n await this.__unsafe_ensureInitialized();\n } finally {\n this._suppressProtocolBroadcasts = false;\n }\n }\n\n /**\n * Ancestor chain for this agent, root-first. Empty for top-level\n * DOs. Populated at facet init time; survives hibernation.\n *\n * @example\n * ```ts\n * class Chat extends Agent {\n * onStart() {\n * console.log(\"chat started under:\", this.parentPath);\n * // → [{ className: \"Tenant\", name: \"acme\" }, { className: \"Inbox\", name: \"alice\" }]\n * }\n * }\n * ```\n *\n * @experimental The API surface may change before stabilizing.\n */\n get parentPath(): ReadonlyArray<{ className: string; name: string }> {\n return this._parentPath;\n }\n\n /**\n * Ancestor chain + self, root-first. Convenient for logging.\n *\n * @experimental The API surface may change before stabilizing.\n */\n get selfPath(): ReadonlyArray<{ className: string; name: string }> {\n return [\n ...this._parentPath,\n {\n className: (this.constructor as { name: string }).name,\n name: this.name\n }\n ];\n }\n\n /**\n * Resolve a typed RPC stub for this facet's **immediate** parent\n * agent.\n *\n * Symmetric with `subAgent(Cls, name)`: while `subAgent` opens a\n * stub from parent to child, `parentAgent` opens one from child\n * to parent. Pass the direct parent's class reference — the\n * framework verifies it matches the last entry of\n * `this.parentPath` at runtime, then looks up `env[Cls.name]` to\n * find the namespace binding.\n *\n * `this.parentPath` is root-first, so the direct parent is the\n * **last** entry: `this.parentPath.at(-1)`. For grandparents and\n * further ancestors, iterate `this.parentPath` and use\n * `getAgentByName(env.X, this.parentPath[i].name)` directly.\n *\n * Assumes the standard \"binding name matches class name\" convention.\n * If your `wrangler.jsonc` binds the parent under a different name\n * (e.g. `{ class_name: \"Inbox\", name: \"MY_INBOX\" }`), call\n * `getAgentByName(env.MY_INBOX, this.parentPath.at(-1)!.name)`\n * directly instead.\n *\n * @experimental The API surface may change before stabilizing.\n *\n * @throws If this agent is not a facet (no parent).\n * @throws If `Cls.name` doesn't match the recorded direct-parent\n * class (guards against accidentally reaching the wrong\n * DO, especially in nested Root → Mid → Leaf chains).\n * @throws If no env binding named `Cls.name` is found.\n *\n * @example\n * ```ts\n * class Chat extends AIChatAgent<Env> {\n * async onChatMessage(...) {\n * const inbox = await this.parentAgent(Inbox);\n * const memory = await inbox.getSharedMemory(\"facts\");\n * // ...\n * }\n * }\n * ```\n */\n async parentAgent<T extends Agent>(\n cls: SubAgentClass<T>\n ): Promise<DurableObjectStub<T>> {\n // `_parentPath` is root-first, so the *direct* parent is the\n // last entry. Destructuring with `[parent] = ...` would grab the\n // root ancestor instead — wrong for any chain deeper than one\n // level and silently routes to the wrong DO if the root and the\n // direct parent happen to be the same class.\n const parent = this._parentPath[this._parentPath.length - 1];\n if (!parent) {\n throw new Error(\n `parentAgent(): ${this.constructor.name} is not a facet — ` +\n `only sub-agents (spawned via \\`subAgent()\\`) have a parent.`\n );\n }\n if (cls.name !== parent.className) {\n throw new Error(\n `parentAgent(${cls.name}): this facet's recorded parent class ` +\n `is \"${parent.className}\", not \"${cls.name}\". Pass the class ` +\n `whose constructor actually spawned this facet.`\n );\n }\n const binding = (this.env as Record<string, unknown>)[cls.name] as\n | DurableObjectNamespace<T>\n | undefined;\n if (!binding) {\n throw new Error(\n `parentAgent(${cls.name}): no top-level binding \"${cls.name}\" ` +\n `found in env. If the parent is bound under a different name ` +\n `(e.g. \"MY_${cls.name.toUpperCase()}\"), use ` +\n `\\`getAgentByName(env.MY_${cls.name.toUpperCase()}, this.parentPath.at(-1)!.name)\\` directly.`\n );\n }\n return await getServerByName<Cloudflare.Env, T>(binding, parent.name);\n }\n\n /**\n * Get or create a named sub-agent — a child Durable Object (facet)\n * with its own isolated SQLite storage running on the same machine.\n *\n * The child class must extend `Agent` and be exported from the worker\n * entry point. The first call for a given name triggers the child's\n * `onStart()`. Subsequent calls return the existing instance.\n *\n * @experimental The API surface may change before stabilizing.\n *\n * @param cls The Agent subclass (must be exported from the worker)\n * @param name Unique name for this child instance\n * @returns A typed RPC stub for calling methods on the child\n *\n * @example\n * ```typescript\n * const searcher = await this.subAgent(SearchAgent, \"main-search\");\n * const results = await searcher.search(\"cloudflare agents\");\n * ```\n */\n async subAgent<T extends Agent>(\n cls: SubAgentClass<T>,\n name: string\n ): Promise<SubAgentStub<T>> {\n return (await this._cf_resolveSubAgent(cls.name, name)) as SubAgentStub<T>;\n }\n\n /** Maximum number of non-terminal agent-tool runs this parent may own at once. */\n maxConcurrentAgentTools = Infinity;\n\n async onAgentToolStart(_run: AgentToolRunInfo): Promise<void> {}\n\n async onAgentToolFinish(\n _run: AgentToolRunInfo,\n _result: AgentToolLifecycleResult\n ): Promise<void> {}\n\n async runAgentTool<Input = unknown, Output = unknown>(\n cls: ChatCapableAgentClass,\n options: RunAgentToolOptions<Input>\n ): Promise<RunAgentToolResult<Output>> {\n const runId = options.runId ?? nanoid(12);\n const agentType = cls.name;\n const existing = this._readAgentToolRun(runId);\n if (existing) {\n if (this._isAgentToolTerminal(existing.status)) {\n if (existing.status === \"completed\" && existing.output_json == null) {\n try {\n const child = await this.subAgent(\n cls as SubAgentClass<Agent>,\n runId\n );\n const adapter = this._asAgentToolChildAdapter<Input, Output>(child);\n const inspection = await adapter.inspectAgentToolRun(runId);\n if (inspection?.status === \"completed\") {\n const result = this._terminalResultFromInspection<Output>(\n agentType,\n inspection\n );\n this._updateAgentToolTerminal(\n runId,\n result,\n inspection.completedAt\n );\n return result;\n }\n } catch {\n // Fall back to the retained parent row.\n }\n }\n return this._resultFromAgentToolRow<Output>(existing);\n }\n return await this._replayAndInterruptAgentToolRun<Output>(\n cls,\n existing,\n \"Agent tool run was still running, but live-tail reattachment is not supported in this runtime.\"\n );\n }\n\n const displayOrder = options.displayOrder ?? 0;\n const inputPreview =\n options.inputPreview ?? this._defaultAgentToolPreview(options.input);\n const displayJson =\n options.display !== undefined ? JSON.stringify(options.display) : null;\n const inputPreviewJson =\n inputPreview !== undefined ? JSON.stringify(inputPreview) : null;\n const startedAt = Date.now();\n\n if (this._activeAgentToolRunCount() >= this.maxConcurrentAgentTools) {\n const error = `maxConcurrentAgentTools (${this.maxConcurrentAgentTools}) exceeded`;\n this.sql`\n INSERT INTO cf_agent_tool_runs (\n run_id, parent_tool_call_id, agent_type, input_preview,\n input_redacted, status, error_message, display_metadata,\n display_order, started_at, completed_at\n ) VALUES (\n ${runId}, ${options.parentToolCallId ?? null}, ${agentType},\n ${inputPreviewJson}, 1, 'error', ${error}, ${displayJson},\n ${displayOrder}, ${startedAt}, ${Date.now()}\n )\n `;\n this._broadcastAgentToolEvent(options.parentToolCallId, 0, {\n kind: \"started\",\n runId,\n agentType,\n inputPreview,\n order: displayOrder,\n display: options.display\n });\n this._broadcastAgentToolEvent(options.parentToolCallId, 1, {\n kind: \"error\",\n runId,\n error\n });\n return { runId, agentType, status: \"error\", error };\n }\n\n this.sql`\n INSERT INTO cf_agent_tool_runs (\n run_id, parent_tool_call_id, agent_type, input_preview,\n input_redacted, status, display_metadata, display_order, started_at\n ) VALUES (\n ${runId}, ${options.parentToolCallId ?? null}, ${agentType},\n ${inputPreviewJson}, 1, 'starting', ${displayJson}, ${displayOrder},\n ${startedAt}\n )\n `;\n\n const runInfo: AgentToolRunInfo = {\n runId,\n parentToolCallId: options.parentToolCallId,\n agentType,\n inputPreview,\n status: \"starting\",\n display: options.display,\n displayOrder,\n startedAt\n };\n await this.onAgentToolStart(runInfo);\n this._broadcastAgentToolEvent(options.parentToolCallId, 0, {\n kind: \"started\",\n runId,\n agentType,\n inputPreview,\n order: displayOrder,\n display: options.display\n });\n\n const child = await this.subAgent(cls as SubAgentClass<Agent>, runId);\n const adapter = this._asAgentToolChildAdapter<Input, Output>(child);\n const childStart = await adapter.startAgentToolRun(options.input, {\n runId\n });\n this._markAgentToolRunning(runId);\n let sequence = 1;\n let parentAbortListener: (() => void) | undefined;\n if (options.signal) {\n if (options.signal.aborted) {\n await adapter.cancelAgentToolRun(runId, options.signal.reason);\n const reason =\n options.signal.reason instanceof Error\n ? options.signal.reason.message\n : String(options.signal.reason ?? \"cancelled\");\n const result: RunAgentToolResult<Output> = {\n runId,\n agentType,\n status: \"aborted\",\n error: reason\n };\n this._updateAgentToolTerminal(runId, result);\n this._broadcastAgentToolTerminal(\n options.parentToolCallId,\n sequence,\n result\n );\n await this.onAgentToolFinish(\n { ...runInfo, status: \"aborted\", completedAt: Date.now() },\n result\n );\n return result;\n } else {\n parentAbortListener = () => {\n void adapter.cancelAgentToolRun(runId, options.signal?.reason);\n };\n options.signal.addEventListener(\"abort\", parentAbortListener, {\n once: true\n });\n }\n }\n\n try {\n if (adapter.tailAgentToolRun) {\n const stream = await adapter.tailAgentToolRun(runId, {\n afterSequence: -1\n });\n sequence = await this._forwardAgentToolStream(\n stream,\n options.parentToolCallId,\n runId,\n sequence,\n options.signal\n );\n } else {\n const chunks = await adapter.getAgentToolChunks(runId);\n sequence = this._broadcastAgentToolChunks(\n options.parentToolCallId,\n runId,\n chunks,\n sequence\n );\n }\n\n if (options.signal?.aborted) {\n await adapter.cancelAgentToolRun(runId, options.signal.reason);\n const reason =\n options.signal.reason instanceof Error\n ? options.signal.reason.message\n : String(options.signal.reason ?? \"cancelled\");\n const result: RunAgentToolResult<Output> = {\n runId,\n agentType,\n status: \"aborted\",\n error: reason\n };\n this._updateAgentToolTerminal(runId, result);\n this._broadcastAgentToolTerminal(\n options.parentToolCallId,\n sequence,\n result\n );\n await this.onAgentToolFinish(\n { ...runInfo, status: \"aborted\", completedAt: Date.now() },\n result\n );\n return result;\n }\n\n const inspection =\n (await adapter.inspectAgentToolRun(runId)) ?? childStart;\n const result = this._terminalResultFromInspection<Output>(\n agentType,\n inspection\n );\n this._updateAgentToolTerminal(runId, result, inspection.completedAt);\n this._broadcastAgentToolTerminal(\n options.parentToolCallId,\n sequence,\n result\n );\n await this.onAgentToolFinish(\n { ...runInfo, status: result.status, completedAt: Date.now() },\n result\n );\n return result;\n } catch (error) {\n if (options.signal?.aborted) {\n await adapter.cancelAgentToolRun(runId, options.signal.reason);\n const reason =\n options.signal.reason instanceof Error\n ? options.signal.reason.message\n : String(options.signal.reason ?? \"cancelled\");\n const result: RunAgentToolResult<Output> = {\n runId,\n agentType,\n status: \"aborted\",\n error: reason\n };\n this._updateAgentToolTerminal(runId, result);\n this._broadcastAgentToolTerminal(\n options.parentToolCallId,\n sequence,\n result\n );\n await this.onAgentToolFinish(\n { ...runInfo, status: \"aborted\", completedAt: Date.now() },\n result\n );\n return result;\n }\n const message = error instanceof Error ? error.message : String(error);\n const result: RunAgentToolResult<Output> = {\n runId,\n agentType,\n status: \"error\",\n error: message\n };\n this._updateAgentToolTerminal(runId, result);\n this._broadcastAgentToolTerminal(\n options.parentToolCallId,\n sequence,\n result\n );\n await this.onAgentToolFinish(\n { ...runInfo, status: \"error\", completedAt: Date.now() },\n result\n );\n return result;\n } finally {\n if (parentAbortListener && options.signal) {\n options.signal.removeEventListener(\"abort\", parentAbortListener);\n }\n }\n }\n\n hasAgentToolRun<T extends Agent>(\n cls: SubAgentClass<T>,\n runId: string\n ): boolean;\n hasAgentToolRun(agentType: string, runId: string): boolean;\n hasAgentToolRun(classOrName: SubAgentClass | string, runId: string): boolean {\n const agentType =\n typeof classOrName === \"string\" ? classOrName : classOrName.name;\n const rows = this.sql<{ n: number }>`\n SELECT COUNT(*) AS n FROM cf_agent_tool_runs\n WHERE run_id = ${runId} AND agent_type = ${agentType}\n `;\n return (rows[0]?.n ?? 0) > 0;\n }\n\n async clearAgentToolRuns(options?: {\n olderThan?: number;\n status?: AgentToolRunStatus[];\n }): Promise<void> {\n const rows = this.sql<{\n run_id: string;\n agent_type: string;\n status: string;\n }>`\n SELECT run_id, agent_type, status FROM cf_agent_tool_runs\n ORDER BY started_at ASC\n `;\n const statusFilter = options?.status\n ? new Set<string>(options.status)\n : null;\n const retained = rows.filter((row) => {\n if (statusFilter && !statusFilter.has(row.status)) return false;\n if (options?.olderThan !== undefined) {\n const full = this._readAgentToolRun(row.run_id);\n if (!full || full.started_at >= options.olderThan) return false;\n }\n return true;\n });\n\n for (const row of retained) {\n try {\n const cls = this._agentToolClassByName(row.agent_type);\n if (row.status === \"starting\" || row.status === \"running\") {\n const child = await this.subAgent(cls, row.run_id);\n const adapter = this._asAgentToolChildAdapter(child);\n await adapter.cancelAgentToolRun(\n row.run_id,\n \"clearing agent tool run\"\n );\n }\n await this.deleteSubAgent(cls, row.run_id);\n } catch {\n // Cleanup is intentionally idempotent.\n }\n this.sql`\n DELETE FROM cf_agent_tool_runs WHERE run_id = ${row.run_id}\n `;\n }\n }\n\n private _isAgentToolTerminal(status: string): boolean {\n return (\n status === \"completed\" ||\n status === \"error\" ||\n status === \"aborted\" ||\n status === \"interrupted\"\n );\n }\n\n private _activeAgentToolRunCount(): number {\n const rows = this.sql<{ n: number }>`\n SELECT COUNT(*) AS n FROM cf_agent_tool_runs\n WHERE status IN ('starting', 'running')\n `;\n return rows[0]?.n ?? 0;\n }\n\n private _defaultAgentToolPreview(input: unknown): unknown {\n if (typeof input === \"string\") return input.slice(0, 500);\n if (input === null || input === undefined) return input;\n try {\n const json = JSON.stringify(input);\n return json.length > 500 ? `${json.slice(0, 497)}...` : json;\n } catch {\n return String(input).slice(0, 500);\n }\n }\n\n private _readAgentToolRun(runId: string): AgentToolRunStorageRow | null {\n const rows = this.sql<AgentToolRunStorageRow>`\n SELECT run_id, parent_tool_call_id, agent_type, input_preview, status,\n summary, output_json, error_message, display_metadata, display_order,\n started_at, completed_at\n FROM cf_agent_tool_runs\n WHERE run_id = ${runId}\n LIMIT 1\n `;\n return rows[0] ?? null;\n }\n\n private _resultFromAgentToolRow<Output>(\n row: AgentToolRunStorageRow\n ): RunAgentToolResult<Output> {\n const output = this._parseAgentToolJson(row.output_json) as\n | Output\n | undefined;\n return {\n runId: row.run_id,\n agentType: row.agent_type,\n status: row.status as RunAgentToolResult<Output>[\"status\"],\n ...(output !== undefined ? { output } : {}),\n ...(row.summary !== null ? { summary: row.summary } : {}),\n ...(row.error_message !== null ? { error: row.error_message } : {})\n };\n }\n\n private _terminalResultFromInspection<Output>(\n agentType: string,\n inspection: AgentToolRunInspection<Output>\n ): RunAgentToolResult<Output> {\n if (inspection.status === \"completed\") {\n return {\n runId: inspection.runId,\n agentType,\n status: \"completed\",\n output: inspection.output,\n summary: inspection.summary\n };\n }\n if (inspection.status === \"aborted\") {\n return {\n runId: inspection.runId,\n agentType,\n status: \"aborted\",\n error: inspection.error\n };\n }\n return {\n runId: inspection.runId,\n agentType,\n status: \"error\",\n error: inspection.error ?? \"Agent tool run failed\"\n };\n }\n\n private _updateAgentToolTerminal<Output>(\n runId: string,\n result: RunAgentToolResult<Output>,\n completedAt = Date.now()\n ): void {\n this.sql`\n UPDATE cf_agent_tool_runs\n SET status = ${result.status},\n summary = ${result.summary ?? null},\n output_json = ${this._stringifyAgentToolOutput(result.output)},\n error_message = ${result.error ?? null},\n completed_at = ${completedAt}\n WHERE run_id = ${runId}\n AND status NOT IN ('completed', 'error', 'aborted', 'interrupted')\n `;\n if (result.status === \"completed\" && result.output !== undefined) {\n this.sql`\n UPDATE cf_agent_tool_runs\n SET output_json = COALESCE(output_json, ${this._stringifyAgentToolOutput(result.output)}),\n summary = COALESCE(summary, ${result.summary ?? null})\n WHERE run_id = ${runId} AND status = 'completed'\n `;\n }\n }\n\n private _markAgentToolRunning(runId: string): void {\n this.sql`\n UPDATE cf_agent_tool_runs\n SET status = 'running'\n WHERE run_id = ${runId} AND status = 'starting'\n `;\n }\n\n private _parseAgentToolJson(value: string | null): unknown {\n if (value === null) return undefined;\n try {\n return JSON.parse(value);\n } catch {\n return value;\n }\n }\n\n private _stringifyAgentToolOutput(output: unknown): string | null {\n if (output === undefined) return null;\n const json = JSON.stringify(output);\n return json === undefined ? null : json;\n }\n\n private _broadcastAgentToolEvent(\n parentToolCallId: string | undefined,\n sequence: number,\n event: AgentToolEvent,\n replay?: true,\n connection?: Connection\n ): void {\n const message: AgentToolEventMessage = {\n type: \"agent-tool-event\",\n parentToolCallId,\n sequence,\n event,\n ...(replay ? { replay } : {})\n };\n const body = JSON.stringify(message);\n if (connection) {\n connection.send(body);\n } else {\n this.broadcast(body);\n }\n }\n\n private _broadcastAgentToolChunks(\n parentToolCallId: string | undefined,\n runId: string,\n chunks: AgentToolStoredChunk[],\n sequence: number,\n replay?: true,\n connection?: Connection\n ): number {\n let next = sequence;\n for (const chunk of chunks) {\n this._broadcastAgentToolEvent(\n parentToolCallId,\n next++,\n { kind: \"chunk\", runId, body: chunk.body },\n replay,\n connection\n );\n }\n return next;\n }\n\n private async _forwardAgentToolStream(\n stream: ReadableStream<AgentToolStoredChunk>,\n parentToolCallId: string | undefined,\n runId: string,\n sequence: number,\n signal?: AbortSignal\n ): Promise<number> {\n let next = sequence;\n if (signal?.aborted) return next;\n const reader = (\n stream as ReadableStream<AgentToolStoredChunk | Uint8Array>\n ).getReader();\n const decoder = new TextDecoder();\n let bufferedBytes = \"\";\n let abortListener: (() => void) | undefined;\n if (signal) {\n abortListener = () => {\n // runAgentTool() also calls cancelAgentToolRun(), whose adapter should\n // close the tail stream. Avoid reader.cancel(reason) here because DO RPC\n // can surface cancellation reasons as unhandled stream rejections.\n };\n signal.addEventListener(\"abort\", abortListener, { once: true });\n }\n try {\n const forwardChunk = (chunk: AgentToolStoredChunk) => {\n this._broadcastAgentToolEvent(parentToolCallId, next++, {\n kind: \"chunk\",\n runId,\n body: chunk.body\n });\n };\n const forwardLine = (line: string) => {\n try {\n const chunk = JSON.parse(line) as Partial<AgentToolStoredChunk>;\n if (typeof chunk.body === \"string\") {\n forwardChunk(chunk as AgentToolStoredChunk);\n }\n } catch {\n // Skip malformed stream frames; the child remains authoritative for\n // final run status and durable chunk replay.\n }\n };\n const flushBufferedBytes = (final = false) => {\n while (true) {\n const newline = bufferedBytes.indexOf(\"\\n\");\n if (newline === -1) break;\n const line = bufferedBytes.slice(0, newline).trim();\n bufferedBytes = bufferedBytes.slice(newline + 1);\n if (line.length > 0) {\n forwardLine(line);\n }\n }\n if (final && bufferedBytes.trim().length > 0) {\n forwardLine(bufferedBytes);\n bufferedBytes = \"\";\n }\n };\n while (true) {\n let readResult: ReadableStreamReadResult<\n AgentToolStoredChunk | Uint8Array\n >;\n try {\n readResult = await reader.read();\n } catch (error) {\n if (signal?.aborted) break;\n throw error;\n }\n const { done, value } = readResult;\n if (done) {\n bufferedBytes += decoder.decode();\n flushBufferedBytes(true);\n break;\n }\n if (value instanceof Uint8Array) {\n bufferedBytes += decoder.decode(value, { stream: true });\n flushBufferedBytes();\n } else {\n forwardChunk(value);\n }\n }\n } finally {\n if (abortListener && signal) {\n signal.removeEventListener(\"abort\", abortListener);\n }\n reader.releaseLock();\n }\n return next;\n }\n\n private _broadcastAgentToolTerminal<Output>(\n parentToolCallId: string | undefined,\n sequence: number,\n result: RunAgentToolResult<Output>,\n replay?: true,\n connection?: Connection\n ): void {\n if (result.status === \"completed\") {\n this._broadcastAgentToolEvent(\n parentToolCallId,\n sequence,\n {\n kind: \"finished\",\n runId: result.runId,\n summary: result.summary ?? \"\"\n },\n replay,\n connection\n );\n } else if (result.status === \"aborted\") {\n this._broadcastAgentToolEvent(\n parentToolCallId,\n sequence,\n { kind: \"aborted\", runId: result.runId, reason: result.error },\n replay,\n connection\n );\n } else if (result.status === \"interrupted\") {\n this._broadcastAgentToolEvent(\n parentToolCallId,\n sequence,\n {\n kind: \"interrupted\",\n runId: result.runId,\n error: result.error ?? \"Agent tool run was interrupted\"\n },\n replay,\n connection\n );\n } else {\n this._broadcastAgentToolEvent(\n parentToolCallId,\n sequence,\n {\n kind: \"error\",\n runId: result.runId,\n error: result.error ?? \"Agent tool run failed\"\n },\n replay,\n connection\n );\n }\n }\n\n private _asAgentToolChildAdapter<Input = unknown, Output = unknown>(\n child: unknown\n ): AgentToolChildAdapter<Input, Output> {\n const candidate = child as Partial<AgentToolChildAdapter<Input, Output>>;\n if (\n typeof candidate.startAgentToolRun !== \"function\" ||\n typeof candidate.cancelAgentToolRun !== \"function\" ||\n typeof candidate.inspectAgentToolRun !== \"function\" ||\n typeof candidate.getAgentToolChunks !== \"function\"\n ) {\n throw new Error(\n \"Agent tool child must implement the framework agent-tool adapter. Use a @cloudflare/think Think subclass or an AIChatAgent subclass.\"\n );\n }\n return candidate as AgentToolChildAdapter<Input, Output>;\n }\n\n private _agentToolClassByName(className: string): SubAgentClass<Agent> {\n const ctx = this.ctx as unknown as Partial<FacetCapableCtx>;\n const cls = ctx.exports?.[className];\n if (!cls) {\n throw new Error(`Agent tool class \"${className}\" is not exported.`);\n }\n return cls as unknown as SubAgentClass<Agent>;\n }\n\n private async _replayAndInterruptAgentToolRun<Output>(\n cls: ChatCapableAgentClass,\n row: AgentToolRunStorageRow,\n message: string\n ): Promise<RunAgentToolResult<Output>> {\n const parentToolCallId = row.parent_tool_call_id ?? undefined;\n let sequence = 1;\n try {\n const child = await this.subAgent(\n cls as SubAgentClass<Agent>,\n row.run_id\n );\n const adapter = this._asAgentToolChildAdapter<unknown, Output>(child);\n const chunks = await adapter.getAgentToolChunks(row.run_id);\n sequence = this._broadcastAgentToolChunks(\n parentToolCallId,\n row.run_id,\n chunks,\n sequence\n );\n } catch {\n // Interruption is still the honest parent state if replay fails.\n }\n const result: RunAgentToolResult<Output> = {\n runId: row.run_id,\n agentType: row.agent_type,\n status: \"interrupted\",\n error: message\n };\n this._updateAgentToolTerminal(row.run_id, result);\n this._broadcastAgentToolTerminal(parentToolCallId, sequence, result);\n return result;\n }\n\n private async _replayAgentToolRuns(connection: Connection): Promise<void> {\n const rows = this.sql<{\n run_id: string;\n parent_tool_call_id: string | null;\n agent_type: string;\n input_preview: string | null;\n status: AgentToolRunStatus;\n summary: string | null;\n output_json: string | null;\n error_message: string | null;\n display_metadata: string | null;\n display_order: number;\n }>`\n SELECT run_id, parent_tool_call_id, agent_type, input_preview, status,\n summary, output_json, error_message, display_metadata, display_order\n FROM cf_agent_tool_runs\n ORDER BY started_at ASC\n `;\n\n for (const row of rows) {\n const parentToolCallId = row.parent_tool_call_id ?? undefined;\n let sequence = 0;\n this._broadcastAgentToolEvent(\n parentToolCallId,\n sequence++,\n {\n kind: \"started\",\n runId: row.run_id,\n agentType: row.agent_type,\n inputPreview: this._parseAgentToolJson(row.input_preview),\n order: row.display_order,\n display: this._parseAgentToolJson(row.display_metadata) as\n | AgentToolDisplayMetadata\n | undefined\n },\n true,\n connection\n );\n\n try {\n const child = await this.subAgent(\n this._agentToolClassByName(row.agent_type),\n row.run_id\n );\n const adapter = this._asAgentToolChildAdapter(child);\n const chunks = await adapter.getAgentToolChunks(row.run_id);\n sequence = this._broadcastAgentToolChunks(\n parentToolCallId,\n row.run_id,\n chunks,\n sequence,\n true,\n connection\n );\n } catch {\n // Keep replay best-effort per run.\n }\n\n if (this._isAgentToolTerminal(row.status)) {\n this._broadcastAgentToolTerminal(\n parentToolCallId,\n sequence,\n {\n runId: row.run_id,\n agentType: row.agent_type,\n status: row.status as RunAgentToolResult[\"status\"],\n output: this._parseAgentToolJson(row.output_json),\n summary: row.summary ?? undefined,\n error: row.error_message ?? undefined\n },\n true,\n connection\n );\n }\n }\n }\n\n private async _reconcileAgentToolRuns(): Promise<void> {\n const rows = this.sql<{ run_id: string; agent_type: string }>`\n SELECT run_id, agent_type FROM cf_agent_tool_runs\n WHERE status IN ('starting', 'running')\n ORDER BY started_at ASC\n `;\n for (const row of rows) {\n try {\n const cls = this._agentToolClassByName(row.agent_type);\n if (!this.hasSubAgent(cls, row.run_id)) {\n this._updateAgentToolTerminal(row.run_id, {\n runId: row.run_id,\n agentType: row.agent_type,\n status: \"interrupted\",\n error: \"Agent tool child was not found during parent recovery.\"\n });\n continue;\n }\n const child = await this.subAgent(cls, row.run_id);\n const adapter = this._asAgentToolChildAdapter(child);\n const inspection = await adapter.inspectAgentToolRun(row.run_id);\n if (\n !inspection ||\n inspection.status === \"running\" ||\n inspection.status === \"starting\"\n ) {\n this._updateAgentToolTerminal(row.run_id, {\n runId: row.run_id,\n agentType: row.agent_type,\n status: \"interrupted\",\n error:\n \"Agent tool run was still running, but live-tail reattachment is not supported in this runtime.\"\n });\n } else {\n this._updateAgentToolTerminal(\n row.run_id,\n this._terminalResultFromInspection(row.agent_type, inspection),\n inspection.completedAt\n );\n }\n } catch {\n this._updateAgentToolTerminal(row.run_id, {\n runId: row.run_id,\n agentType: row.agent_type,\n status: \"interrupted\",\n error: \"Agent tool run could not be inspected during parent recovery.\"\n });\n }\n }\n }\n\n /**\n * Shared facet resolution — takes a CamelCase class name string\n * (matching `ctx.exports`) rather than a class reference. Both\n * `subAgent(cls, name)` and `_cf_invokeSubAgent(className, ...)`\n * funnel through here so registry bookkeeping and the\n * `_cf_initAsFacet` handshake are consistent.\n *\n * @internal\n */\n private async _cf_resolveSubAgent(\n className: string,\n name: string\n ): Promise<unknown> {\n const ctx = this.ctx as unknown as Partial<FacetCapableCtx>;\n if (!ctx.facets || !ctx.exports) {\n throw new Error(\n \"subAgent() is not supported in this runtime — \" +\n \"`ctx.facets` / `ctx.exports` are unavailable. \" +\n \"Update to the latest `compatibility_date` in your wrangler.jsonc.\"\n );\n }\n if (camelCaseToKebabCase(className) === SUB_PREFIX) {\n // Any class whose kebab-cased name equals the `sub` URL\n // separator would make `/agents/.../sub/sub/...` ambiguous.\n // `Sub`, `SUB`, and `Sub_` all kebab-case to `\"sub\"` — catch\n // them uniformly rather than listing each spelling.\n throw new Error(\n `Sub-agent class name \"${className}\" kebab-cases to \"${SUB_PREFIX}\", ` +\n `which collides with the reserved URL separator — rename the ` +\n `class (e.g. \"SubThing\" or \"Subtask\").`\n );\n }\n const Cls = ctx.exports[className];\n if (!Cls) {\n throw new Error(\n `Sub-agent class \"${className}\" not found in worker exports. ` +\n `Make sure the class is exported from your worker entry point ` +\n `and that the export name matches the class name.`\n );\n }\n if (name.includes(\"\\0\")) {\n // Null char is reserved for the facet composite key delimiter —\n // letting it through would corrupt the `${class}\\0${name}` key.\n throw new Error(\n `Sub-agent name contains null character (\\\\0), which is reserved.`\n );\n }\n // Composite key: class name + NUL + facet name, so two different\n // classes can share the same user-facing name.\n const facetKey = `${className}\\0${name}`;\n // Pass an explicit `id` in FacetStartupOptions so the facet has\n // its own `ctx.id.name === name` (not the parent's name).\n // Without this, facets inherit the parent DO's `ctx.id` and\n // `this.name` on the facet would silently return the parent's\n // name. See:\n // https://developers.cloudflare.com/dynamic-workers/usage/durable-object-facets/\n //\n // The id is constructed from the parent's own bound namespace,\n // which is always present in `ctx.exports` because the parent\n // Agent class is bound as a DO. Any bound DurableObjectNamespace\n // would work — the id is opaque + a name; nothing routes\n // through the namespace at runtime for facets. We use the\n // parent's because it's guaranteed available without extra\n // env-binding lookups.\n const parentClassName = (this.constructor as { name: string }).name;\n const parentNs = ctx.exports[parentClassName];\n if (!parentNs?.idFromName) {\n // Minification is the most common cause of this error in\n // production builds: aggressive bundlers rewrite class\n // identifiers to short ids, so `this.constructor.name`\n // becomes something like `_a` and the ctx.exports lookup\n // misses. Detect that case and append a hint, otherwise\n // the message is mysterious.\n //\n // Heuristic: optional leading underscore(s), then 1–3\n // lowercase letters/digits starting with a letter (e.g.\n // `_a`, `_ab`, `_a1`, `__a`). Real class names like\n // `MyAgent` or `_UnboundParent` start with an uppercase\n // letter and won't match.\n const looksMinified = /^_*[a-z][a-z0-9]{0,2}$/.test(parentClassName);\n const minificationHint = looksMinified\n ? ` The class name \"${parentClassName}\" looks minified — make sure your bundler preserves class names (e.g. esbuild's \\`keepNames: true\\`).`\n : \"\";\n throw new Error(\n `Sub-agent bootstrap requires the parent class \"${parentClassName}\" to be bound as a Durable Object namespace, but ctx.exports[\"${parentClassName}\"] is missing or doesn't expose idFromName.${minificationHint} Make sure the parent agent class is registered in your wrangler.jsonc durable_objects.bindings under its class name.`\n );\n }\n const facetId = parentNs.idFromName(name);\n const stub = ctx.facets.get(facetKey, () => ({\n class: Cls as DurableObjectClass,\n id: facetId\n }));\n\n // Derive the child's ancestor chain: our own `parentPath` +\n // `{ class: this.constructor.name, name: this.name }`. Inductive\n // across recursive nesting.\n const childParentPath = this.selfPath;\n\n // Initialize the child as a facet via a single RPC that runs\n // inside the child's isolate. Avoids the cross-DO I/O error that\n // the previous `stub.fetch(req)` path triggered by handing a\n // parent-owned Request across the isolate boundary.\n //\n // The parent may be inside a WebSocket/message request context here.\n // Clear native context handles before the child facet RPC so workerd\n // never sees parent-owned I/O attached to child initialization.\n await agentContext.run(\n {\n agent: this,\n connection: undefined,\n request: undefined,\n email: undefined\n },\n async () => {\n await (\n stub as unknown as {\n _cf_initAsFacet(\n name: string,\n parentPath: ReadonlyArray<{ className: string; name: string }>\n ): Promise<void>;\n }\n )._cf_initAsFacet(name, childParentPath);\n }\n );\n\n // Record in the parent's sub-agent registry so `hasSubAgent` /\n // `listSubAgents` reflect the spawn. Idempotent.\n this._recordSubAgent(className, name);\n\n return stub;\n }\n\n /**\n * Forcefully abort a running sub-agent. The child stops executing\n * immediately and will be restarted on next {@link subAgent} call.\n * Pending RPC calls receive the reason as an error.\n * Transitively aborts the child's own children.\n *\n * @experimental The API surface may change before stabilizing.\n *\n * @param cls The Agent subclass used when creating the child\n * @param name Name of the child to abort\n * @param reason Error thrown to pending/future RPC callers\n */\n abortSubAgent(cls: SubAgentClass, name: string, reason?: unknown): void {\n const ctx = this.ctx as unknown as Partial<FacetCapableCtx>;\n if (!ctx.facets) {\n throw new Error(\n \"abortSubAgent() is not supported in this runtime — \" +\n \"`ctx.facets` is unavailable. \" +\n \"Update to the latest `compatibility_date` in your wrangler.jsonc.\"\n );\n }\n const facetKey = `${cls.name}\\0${name}`;\n ctx.facets.abort(facetKey, reason);\n }\n\n /**\n * Delete a sub-agent: abort it if running, then permanently wipe its\n * storage. Transitively deletes the child's own children.\n *\n * @experimental The API surface may change before stabilizing.\n *\n * @param cls The Agent subclass used when creating the child\n * @param name Name of the child to delete\n */\n async deleteSubAgent(cls: SubAgentClass, name: string): Promise<void> {\n const ctx = this.ctx as unknown as Partial<FacetCapableCtx>;\n if (!ctx.facets) {\n throw new Error(\n \"deleteSubAgent() is not supported in this runtime — \" +\n \"`ctx.facets` is unavailable. \" +\n \"Update to the latest `compatibility_date` in your wrangler.jsonc.\"\n );\n }\n const facetKey = `${cls.name}\\0${name}`;\n const childPath = [...this.selfPath, { className: cls.name, name }];\n if (this._isFacet) {\n const root = await this._rootAlarmOwner();\n await root._cf_cleanupFacetPrefix(childPath);\n } else {\n await this._cf_cleanupFacetPrefix(childPath);\n }\n\n // Idempotent: make `ctx.facets.delete` tolerant of missing keys.\n // workerd throws an opaque \"internal error\" when the key isn't\n // registered; swallow that so double-delete and\n // delete-never-spawned both succeed silently. The registry DELETE\n // is already idempotent.\n try {\n ctx.facets.delete(facetKey);\n } catch {\n // no-op — facet wasn't registered (already deleted / never spawned)\n }\n this._forgetSubAgent(cls.name, name);\n }\n\n // ── Sub-agent registry (backs `hasSubAgent` / `listSubAgents`) ──────────\n\n /** @internal */\n private _subAgentRegistryReady = false;\n\n /** @internal */\n private _ensureSubAgentRegistry(): void {\n if (this._subAgentRegistryReady) return;\n this.sql`\n CREATE TABLE IF NOT EXISTS cf_agents_sub_agents (\n class TEXT NOT NULL,\n name TEXT NOT NULL,\n created_at INTEGER NOT NULL,\n PRIMARY KEY (class, name)\n )\n `;\n this._subAgentRegistryReady = true;\n }\n\n /** @internal */\n private _recordSubAgent(className: string, name: string): void {\n this._ensureSubAgentRegistry();\n this.sql`\n INSERT OR IGNORE INTO cf_agents_sub_agents (class, name, created_at)\n VALUES (${className}, ${name}, ${Date.now()})\n `;\n }\n\n /** @internal */\n private _forgetSubAgent(className: string, name: string): void {\n this._ensureSubAgentRegistry();\n this.sql`\n DELETE FROM cf_agents_sub_agents\n WHERE class = ${className} AND name = ${name}\n `;\n }\n\n /**\n * Whether this agent has previously spawned (and not deleted) a\n * sub-agent of the given class and name. Backed by an\n * auto-maintained SQLite registry in the parent's storage.\n *\n * Intended for strict-registry access patterns in\n * `onBeforeSubAgent` or similar gating logic.\n *\n * @experimental The API surface may change before stabilizing.\n *\n * @example\n * ```ts\n * async onBeforeSubAgent(req, { className, name }) {\n * if (!this.hasSubAgent(className, name)) {\n * return new Response(\"Not found\", { status: 404 });\n * }\n * }\n * ```\n */\n hasSubAgent<T extends Agent>(cls: SubAgentClass<T>, name: string): boolean;\n hasSubAgent(className: string, name: string): boolean;\n hasSubAgent(classOrName: SubAgentClass | string, name: string): boolean {\n const className =\n typeof classOrName === \"string\" ? classOrName : classOrName.name;\n this._ensureSubAgentRegistry();\n const rows = this.sql<{ n: number }>`\n SELECT COUNT(*) AS n FROM cf_agents_sub_agents\n WHERE class = ${className} AND name = ${name}\n `;\n return (rows[0]?.n ?? 0) > 0;\n }\n\n /**\n * List known sub-agents, optionally filtered by class. Reflects\n * the registry rows written by {@link subAgent} and removed by\n * {@link deleteSubAgent}.\n *\n * @experimental The API surface may change before stabilizing.\n */\n listSubAgents<T extends Agent>(\n cls: SubAgentClass<T>\n ): Array<{ className: string; name: string; createdAt: number }>;\n listSubAgents(\n className?: string\n ): Array<{ className: string; name: string; createdAt: number }>;\n listSubAgents(\n classOrName?: SubAgentClass | string\n ): Array<{ className: string; name: string; createdAt: number }> {\n const className =\n typeof classOrName === \"string\" ? classOrName : classOrName?.name;\n this._ensureSubAgentRegistry();\n const rows = className\n ? this.sql<{ class: string; name: string; created_at: number }>`\n SELECT class, name, created_at FROM cf_agents_sub_agents\n WHERE class = ${className}\n ORDER BY created_at ASC\n `\n : this.sql<{ class: string; name: string; created_at: number }>`\n SELECT class, name, created_at FROM cf_agents_sub_agents\n ORDER BY created_at ASC\n `;\n return rows.map((r) => ({\n className: r.class,\n name: r.name,\n createdAt: r.created_at\n }));\n }\n\n /**\n * Destroy the Agent, removing all state and scheduled tasks.\n *\n * On a top-level agent: drops every table, clears the alarm, and\n * aborts the isolate.\n *\n * On a sub-agent (facet): delegates teardown to the immediate\n * parent so the parent-owned schedule rows for this sub-agent\n * (and any of its descendants) are cancelled, the parent's\n * `cf_agents_sub_agents` registry entry is cleared, and\n * `ctx.facets.delete` wipes the facet's own storage. The\n * `ctx.facets.delete` call aborts this isolate, so this method\n * may not return cleanly when invoked from inside the facet —\n * callers should treat it as fire-and-forget.\n */\n async destroy() {\n if (this._isFacet) {\n this._emit(\"destroy\");\n const root = await this._rootAlarmOwner();\n // The chain: root → … → direct-parent runs ctx.facets.delete\n // on this facet, which aborts this isolate. The await may\n // throw an abort error or never resolve depending on timing —\n // either is acceptable, the cleanup has already been applied.\n await root._cf_destroyDescendantFacet(this.selfPath);\n return;\n }\n\n this._dropInternalTablesForDestroy();\n\n // delete all alarms\n await this.ctx.storage.deleteAlarm();\n await this.ctx.storage.deleteAll();\n\n this._disposables.dispose();\n await this.mcp.dispose();\n\n this._destroyed = true;\n\n // `ctx.abort` throws an uncatchable error, so we yield to the event loop\n // to avoid capturing it and let handlers finish cleaning up\n setTimeout(() => {\n this.ctx.abort(\"destroyed\");\n }, 0);\n\n this._emit(\"destroy\");\n }\n\n /** @internal Drop every internal Agents SDK table during top-level destroy. */\n protected _dropInternalTablesForDestroy(): void {\n this.sql`DROP TABLE IF EXISTS cf_agents_mcp_servers`;\n this.sql`DROP TABLE IF EXISTS cf_agents_state`;\n this.sql`DROP TABLE IF EXISTS cf_agents_schedules`;\n this.sql`DROP TABLE IF EXISTS cf_agents_queues`;\n this.sql`DROP TABLE IF EXISTS cf_agents_workflows`;\n this.sql`DROP TABLE IF EXISTS cf_agents_sub_agents`;\n this.sql`DROP TABLE IF EXISTS cf_agents_runs`;\n this.sql`DROP TABLE IF EXISTS cf_agents_facet_runs`;\n this.sql`DROP TABLE IF EXISTS cf_agent_tool_runs`;\n }\n\n /**\n * Check if a method is callable\n * @param method The method name to check\n * @returns True if the method is marked as callable\n */\n private _isCallable(method: string): boolean {\n return callableMetadata.has(this[method as keyof this] as Function);\n }\n\n /**\n * Get all methods marked as callable on this Agent\n * @returns A map of method names to their metadata\n */\n getCallableMethods(): Map<string, CallableMetadata> {\n const result = new Map<string, CallableMetadata>();\n\n // Walk the entire prototype chain to find callable methods from parent classes\n let prototype = Object.getPrototypeOf(this);\n while (prototype && prototype !== Object.prototype) {\n for (const name of Object.getOwnPropertyNames(prototype)) {\n if (name === \"constructor\") continue;\n // Don't override child class methods (first one wins)\n if (result.has(name)) continue;\n\n try {\n const fn = prototype[name];\n if (typeof fn === \"function\") {\n const meta = callableMetadata.get(fn as Function);\n if (meta) {\n result.set(name, meta);\n }\n }\n } catch (e) {\n if (!(e instanceof TypeError)) {\n throw e;\n }\n }\n }\n prototype = Object.getPrototypeOf(prototype);\n }\n\n return result;\n }\n\n // ==========================================\n // Workflow Integration Methods\n // ==========================================\n\n /**\n * Start a workflow and track it in this Agent's database.\n * Automatically injects agent identity into the workflow params.\n *\n * @template P - Type of params to pass to the workflow\n * @param workflowName - Name of the workflow binding in env (e.g., 'MY_WORKFLOW')\n * @param params - Params to pass to the workflow\n * @param options - Optional workflow options\n * @returns The workflow instance ID\n *\n * @example\n * ```typescript\n * const workflowId = await this.runWorkflow(\n * 'MY_WORKFLOW',\n * { taskId: '123', data: 'process this' }\n * );\n * ```\n */\n async runWorkflow<P = unknown>(\n workflowName: WorkflowName<Env>,\n params: P,\n options?: RunWorkflowOptions\n ): Promise<string> {\n // Look up the workflow binding by name\n const workflow = this._findWorkflowBindingByName(workflowName);\n if (!workflow) {\n throw new Error(\n `Workflow binding '${workflowName}' not found in environment`\n );\n }\n\n // Find the binding name for this Agent's namespace\n const agentBindingName =\n options?.agentBinding ?? this._findAgentBindingName();\n if (!agentBindingName) {\n throw new Error(\n \"Could not detect Agent binding name from class name. \" +\n \"Pass it explicitly via options.agentBinding\"\n );\n }\n\n // Generate workflow ID if not provided\n const workflowId = options?.id ?? nanoid();\n\n // Inject agent identity and workflow name into params\n const augmentedParams = {\n ...params,\n __agentName: this.name,\n __agentBinding: agentBindingName,\n __workflowName: workflowName\n };\n\n // Create the workflow instance\n const instance = await workflow.create({\n id: workflowId,\n params: augmentedParams\n });\n\n // Track the workflow in our database\n const id = nanoid();\n const metadataJson = options?.metadata\n ? JSON.stringify(options.metadata)\n : null;\n try {\n this.sql`\n INSERT INTO cf_agents_workflows (id, workflow_id, workflow_name, status, metadata)\n VALUES (${id}, ${instance.id}, ${workflowName}, 'queued', ${metadataJson})\n `;\n } catch (e) {\n if (\n e instanceof Error &&\n e.message.includes(\"UNIQUE constraint failed\")\n ) {\n throw new Error(\n `Workflow with ID \"${workflowId}\" is already being tracked`\n );\n }\n throw e;\n }\n\n this._emit(\"workflow:start\", { workflowId: instance.id, workflowName });\n\n return instance.id;\n }\n\n /**\n * Send an event to a running workflow.\n * The workflow can wait for this event using step.waitForEvent().\n *\n * @param workflowName - Name of the workflow binding in env (e.g., 'MY_WORKFLOW')\n * @param workflowId - ID of the workflow instance\n * @param event - Event to send\n *\n * @example\n * ```typescript\n * await this.sendWorkflowEvent(\n * 'MY_WORKFLOW',\n * workflowId,\n * { type: 'approval', payload: { approved: true } }\n * );\n * ```\n */\n async sendWorkflowEvent(\n workflowName: WorkflowName<Env>,\n workflowId: string,\n event: WorkflowEventPayload\n ): Promise<void> {\n const workflow = this._findWorkflowBindingByName(workflowName);\n if (!workflow) {\n throw new Error(\n `Workflow binding '${workflowName}' not found in environment`\n );\n }\n\n const instance = await workflow.get(workflowId);\n await tryN(3, async () => instance.sendEvent(event), {\n shouldRetry: isErrorRetryable,\n baseDelayMs: 200,\n maxDelayMs: 3000\n });\n\n this._emit(\"workflow:event\", { workflowId, eventType: event.type });\n }\n\n /**\n * Approve a waiting workflow.\n * Sends an approval event to the workflow that can be received by waitForApproval().\n *\n * @param workflowId - ID of the workflow to approve\n * @param data - Optional approval data (reason, metadata)\n *\n * @example\n * ```typescript\n * await this.approveWorkflow(workflowId, {\n * reason: 'Approved by admin',\n * metadata: { approvedBy: userId }\n * });\n * ```\n */\n async approveWorkflow(\n workflowId: string,\n data?: { reason?: string; metadata?: Record<string, unknown> }\n ): Promise<void> {\n const workflowInfo = this.getWorkflow(workflowId);\n if (!workflowInfo) {\n throw new Error(`Workflow ${workflowId} not found in tracking table`);\n }\n\n await this.sendWorkflowEvent(\n workflowInfo.workflowName as WorkflowName<Env>,\n workflowId,\n {\n type: \"approval\",\n payload: {\n approved: true,\n reason: data?.reason,\n metadata: data?.metadata\n }\n }\n );\n\n this._emit(\"workflow:approved\", { workflowId, reason: data?.reason });\n }\n\n /**\n * Reject a waiting workflow.\n * Sends a rejection event to the workflow that will cause waitForApproval() to throw.\n *\n * @param workflowId - ID of the workflow to reject\n * @param data - Optional rejection data (reason)\n *\n * @example\n * ```typescript\n * await this.rejectWorkflow(workflowId, {\n * reason: 'Request denied by admin'\n * });\n * ```\n */\n async rejectWorkflow(\n workflowId: string,\n data?: { reason?: string }\n ): Promise<void> {\n const workflowInfo = this.getWorkflow(workflowId);\n if (!workflowInfo) {\n throw new Error(`Workflow ${workflowId} not found in tracking table`);\n }\n\n await this.sendWorkflowEvent(\n workflowInfo.workflowName as WorkflowName<Env>,\n workflowId,\n {\n type: \"approval\",\n payload: {\n approved: false,\n reason: data?.reason\n }\n }\n );\n\n this._emit(\"workflow:rejected\", { workflowId, reason: data?.reason });\n }\n\n /**\n * Terminate a running workflow.\n * This immediately stops the workflow and sets its status to \"terminated\".\n *\n * @param workflowId - ID of the workflow to terminate (must be tracked via runWorkflow)\n * @throws Error if workflow not found in tracking table\n * @throws Error if workflow binding not found in environment\n * @throws Error if workflow is already completed/errored/terminated (from Cloudflare)\n *\n * @example\n * ```typescript\n * await this.terminateWorkflow(workflowId);\n * ```\n */\n async terminateWorkflow(workflowId: string): Promise<void> {\n const workflowInfo = this.getWorkflow(workflowId);\n if (!workflowInfo) {\n throw new Error(`Workflow ${workflowId} not found in tracking table`);\n }\n\n const workflow = this._findWorkflowBindingByName(\n workflowInfo.workflowName as WorkflowName<Env>\n );\n if (!workflow) {\n throw new Error(\n `Workflow binding '${workflowInfo.workflowName}' not found in environment`\n );\n }\n\n const instance = await workflow.get(workflowId);\n await tryN(3, async () => instance.terminate(), {\n shouldRetry: isErrorRetryable,\n baseDelayMs: 200,\n maxDelayMs: 3000\n });\n\n // Update tracking table with new status\n const status = await instance.status();\n this._updateWorkflowTracking(workflowId, status);\n\n this._emit(\"workflow:terminated\", {\n workflowId,\n workflowName: workflowInfo.workflowName\n });\n }\n\n /**\n * Pause a running workflow.\n * The workflow can be resumed later with resumeWorkflow().\n *\n * @param workflowId - ID of the workflow to pause (must be tracked via runWorkflow)\n * @throws Error if workflow not found in tracking table\n * @throws Error if workflow binding not found in environment\n * @throws Error if workflow is not running (from Cloudflare)\n *\n * @example\n * ```typescript\n * await this.pauseWorkflow(workflowId);\n * ```\n */\n async pauseWorkflow(workflowId: string): Promise<void> {\n const workflowInfo = this.getWorkflow(workflowId);\n if (!workflowInfo) {\n throw new Error(`Workflow ${workflowId} not found in tracking table`);\n }\n\n const workflow = this._findWorkflowBindingByName(\n workflowInfo.workflowName as WorkflowName<Env>\n );\n if (!workflow) {\n throw new Error(\n `Workflow binding '${workflowInfo.workflowName}' not found in environment`\n );\n }\n\n const instance = await workflow.get(workflowId);\n await tryN(3, async () => instance.pause(), {\n shouldRetry: isErrorRetryable,\n baseDelayMs: 200,\n maxDelayMs: 3000\n });\n\n const status = await instance.status();\n this._updateWorkflowTracking(workflowId, status);\n\n this._emit(\"workflow:paused\", {\n workflowId,\n workflowName: workflowInfo.workflowName\n });\n }\n\n /**\n * Resume a paused workflow.\n *\n * @param workflowId - ID of the workflow to resume (must be tracked via runWorkflow)\n * @throws Error if workflow not found in tracking table\n * @throws Error if workflow binding not found in environment\n * @throws Error if workflow is not paused (from Cloudflare)\n *\n * @example\n * ```typescript\n * await this.resumeWorkflow(workflowId);\n * ```\n */\n async resumeWorkflow(workflowId: string): Promise<void> {\n const workflowInfo = this.getWorkflow(workflowId);\n if (!workflowInfo) {\n throw new Error(`Workflow ${workflowId} not found in tracking table`);\n }\n\n const workflow = this._findWorkflowBindingByName(\n workflowInfo.workflowName as WorkflowName<Env>\n );\n if (!workflow) {\n throw new Error(\n `Workflow binding '${workflowInfo.workflowName}' not found in environment`\n );\n }\n\n const instance = await workflow.get(workflowId);\n await tryN(3, async () => instance.resume(), {\n shouldRetry: isErrorRetryable,\n baseDelayMs: 200,\n maxDelayMs: 3000\n });\n\n const status = await instance.status();\n this._updateWorkflowTracking(workflowId, status);\n\n this._emit(\"workflow:resumed\", {\n workflowId,\n workflowName: workflowInfo.workflowName\n });\n }\n\n /**\n * Restart a workflow instance.\n * This re-runs the workflow from the beginning with the same ID.\n *\n * @param workflowId - ID of the workflow to restart (must be tracked via runWorkflow)\n * @param options - Optional settings\n * @param options.resetTracking - If true (default), resets created_at and clears error fields.\n * If false, preserves original timestamps.\n * @throws Error if workflow not found in tracking table\n * @throws Error if workflow binding not found in environment\n *\n * @example\n * ```typescript\n * // Reset tracking (default)\n * await this.restartWorkflow(workflowId);\n *\n * // Preserve original timestamps\n * await this.restartWorkflow(workflowId, { resetTracking: false });\n * ```\n */\n async restartWorkflow(\n workflowId: string,\n options: { resetTracking?: boolean } = {}\n ): Promise<void> {\n const { resetTracking = true } = options;\n\n const workflowInfo = this.getWorkflow(workflowId);\n if (!workflowInfo) {\n throw new Error(`Workflow ${workflowId} not found in tracking table`);\n }\n\n const workflow = this._findWorkflowBindingByName(\n workflowInfo.workflowName as WorkflowName<Env>\n );\n if (!workflow) {\n throw new Error(\n `Workflow binding '${workflowInfo.workflowName}' not found in environment`\n );\n }\n\n const instance = await workflow.get(workflowId);\n await tryN(3, async () => instance.restart(), {\n shouldRetry: isErrorRetryable,\n baseDelayMs: 200,\n maxDelayMs: 3000\n });\n\n if (resetTracking) {\n // Reset tracking fields for fresh start\n const now = Math.floor(Date.now() / 1000);\n this.sql`\n UPDATE cf_agents_workflows\n SET status = 'queued',\n created_at = ${now},\n updated_at = ${now},\n completed_at = NULL,\n error_name = NULL,\n error_message = NULL\n WHERE workflow_id = ${workflowId}\n `;\n } else {\n // Just update status from Cloudflare\n const status = await instance.status();\n this._updateWorkflowTracking(workflowId, status);\n }\n\n this._emit(\"workflow:restarted\", {\n workflowId,\n workflowName: workflowInfo.workflowName\n });\n }\n\n /**\n * Find a workflow binding by its name.\n */\n private _findWorkflowBindingByName(\n workflowName: string\n ): Workflow | undefined {\n const binding = (this.env as Record<string, unknown>)[workflowName];\n if (\n binding &&\n typeof binding === \"object\" &&\n \"create\" in binding &&\n \"get\" in binding\n ) {\n return binding as Workflow;\n }\n return undefined;\n }\n\n /**\n * Get all workflow binding names from the environment.\n */\n private _getWorkflowBindingNames(): string[] {\n const names: string[] = [];\n for (const [key, value] of Object.entries(\n this.env as Record<string, unknown>\n )) {\n if (\n value &&\n typeof value === \"object\" &&\n \"create\" in value &&\n \"get\" in value\n ) {\n names.push(key);\n }\n }\n return names;\n }\n\n /**\n * Get the status of a workflow and update the tracking record.\n *\n * @param workflowName - Name of the workflow binding in env (e.g., 'MY_WORKFLOW')\n * @param workflowId - ID of the workflow instance\n * @returns The workflow status\n */\n async getWorkflowStatus(\n workflowName: WorkflowName<Env>,\n workflowId: string\n ): Promise<InstanceStatus> {\n const workflow = this._findWorkflowBindingByName(workflowName);\n if (!workflow) {\n throw new Error(\n `Workflow binding '${workflowName}' not found in environment`\n );\n }\n\n const instance = await workflow.get(workflowId);\n const status = await instance.status();\n\n // Update the tracking record\n this._updateWorkflowTracking(workflowId, status);\n\n return status;\n }\n\n /**\n * Get a tracked workflow by ID.\n *\n * @param workflowId - Workflow instance ID\n * @returns Workflow info or undefined if not found\n */\n getWorkflow(workflowId: string): WorkflowInfo | undefined {\n const rows = this.sql<WorkflowTrackingRow>`\n SELECT * FROM cf_agents_workflows WHERE workflow_id = ${workflowId}\n `;\n\n if (!rows || rows.length === 0) {\n return undefined;\n }\n\n return this._rowToWorkflowInfo(rows[0]);\n }\n\n /**\n * Query tracked workflows with cursor-based pagination.\n *\n * @param criteria - Query criteria including optional cursor for pagination\n * @returns WorkflowPage with workflows, total count, and next cursor\n *\n * @example\n * ```typescript\n * // First page\n * const page1 = this.getWorkflows({ status: 'running', limit: 20 });\n *\n * // Next page\n * if (page1.nextCursor) {\n * const page2 = this.getWorkflows({\n * status: 'running',\n * limit: 20,\n * cursor: page1.nextCursor\n * });\n * }\n * ```\n */\n getWorkflows(criteria: WorkflowQueryCriteria = {}): WorkflowPage {\n const limit = Math.min(criteria.limit ?? 50, 100);\n const isAsc = criteria.orderBy === \"asc\";\n\n // Get total count (ignores cursor and limit)\n const total = this._countWorkflows(criteria);\n\n // Build base query\n let query = \"SELECT * FROM cf_agents_workflows WHERE 1=1\";\n const params: (string | number | boolean)[] = [];\n\n if (criteria.status) {\n const statuses = Array.isArray(criteria.status)\n ? criteria.status\n : [criteria.status];\n const placeholders = statuses.map(() => \"?\").join(\", \");\n query += ` AND status IN (${placeholders})`;\n params.push(...statuses);\n }\n\n if (criteria.workflowName) {\n query += \" AND workflow_name = ?\";\n params.push(criteria.workflowName);\n }\n\n if (criteria.metadata) {\n for (const [key, value] of Object.entries(criteria.metadata)) {\n query += ` AND json_extract(metadata, '$.' || ?) = ?`;\n params.push(key, value);\n }\n }\n\n // Apply cursor for keyset pagination\n if (criteria.cursor) {\n const cursor = this._decodeCursor(criteria.cursor);\n if (isAsc) {\n // ASC: get items after cursor\n query +=\n \" AND (created_at > ? OR (created_at = ? AND workflow_id > ?))\";\n } else {\n // DESC: get items before cursor\n query +=\n \" AND (created_at < ? OR (created_at = ? AND workflow_id < ?))\";\n }\n params.push(cursor.createdAt, cursor.createdAt, cursor.workflowId);\n }\n\n // Order by created_at and workflow_id for consistent keyset pagination\n query += ` ORDER BY created_at ${isAsc ? \"ASC\" : \"DESC\"}, workflow_id ${isAsc ? \"ASC\" : \"DESC\"}`;\n\n // Fetch limit + 1 to detect if there are more pages\n query += \" LIMIT ?\";\n params.push(limit + 1);\n\n const rows = this.ctx.storage.sql\n .exec(query, ...params)\n .toArray() as WorkflowTrackingRow[];\n\n const hasMore = rows.length > limit;\n const resultRows = hasMore ? rows.slice(0, limit) : rows;\n const workflows = resultRows.map((row) => this._rowToWorkflowInfo(row));\n\n // Build next cursor from last item\n const nextCursor =\n hasMore && workflows.length > 0\n ? this._encodeCursor(workflows[workflows.length - 1])\n : null;\n\n return { workflows, total, nextCursor };\n }\n\n /**\n * Count workflows matching criteria (for pagination total).\n */\n private _countWorkflows(\n criteria: Omit<WorkflowQueryCriteria, \"limit\" | \"cursor\" | \"orderBy\"> & {\n createdBefore?: Date;\n }\n ): number {\n let query = \"SELECT COUNT(*) as count FROM cf_agents_workflows WHERE 1=1\";\n const params: (string | number | boolean)[] = [];\n\n if (criteria.status) {\n const statuses = Array.isArray(criteria.status)\n ? criteria.status\n : [criteria.status];\n const placeholders = statuses.map(() => \"?\").join(\", \");\n query += ` AND status IN (${placeholders})`;\n params.push(...statuses);\n }\n\n if (criteria.workflowName) {\n query += \" AND workflow_name = ?\";\n params.push(criteria.workflowName);\n }\n\n if (criteria.metadata) {\n for (const [key, value] of Object.entries(criteria.metadata)) {\n query += ` AND json_extract(metadata, '$.' || ?) = ?`;\n params.push(key, value);\n }\n }\n\n if (criteria.createdBefore) {\n query += \" AND created_at < ?\";\n params.push(Math.floor(criteria.createdBefore.getTime() / 1000));\n }\n\n const result = this.ctx.storage.sql.exec(query, ...params).toArray() as {\n count: number;\n }[];\n\n return result[0]?.count ?? 0;\n }\n\n /**\n * Encode a cursor from workflow info for pagination.\n * Stores createdAt as Unix timestamp in seconds (matching DB storage).\n */\n private _encodeCursor(workflow: WorkflowInfo): string {\n return btoa(\n JSON.stringify({\n c: Math.floor(workflow.createdAt.getTime() / 1000),\n i: workflow.workflowId\n })\n );\n }\n\n /**\n * Decode a pagination cursor.\n * Returns createdAt as Unix timestamp in seconds (matching DB storage).\n */\n private _decodeCursor(cursor: string): {\n createdAt: number;\n workflowId: string;\n } {\n try {\n const data = JSON.parse(atob(cursor));\n if (typeof data.c !== \"number\" || typeof data.i !== \"string\") {\n throw new Error(\"Invalid cursor structure\");\n }\n return { createdAt: data.c, workflowId: data.i };\n } catch {\n throw new Error(\n \"Invalid pagination cursor. The cursor may be malformed or corrupted.\"\n );\n }\n }\n\n /**\n * Delete a workflow tracking record.\n *\n * @param workflowId - ID of the workflow to delete\n * @returns true if a record was deleted, false if not found\n */\n deleteWorkflow(workflowId: string): boolean {\n // First check if workflow exists\n const existing = this.sql<{ count: number }>`\n SELECT COUNT(*) as count FROM cf_agents_workflows WHERE workflow_id = ${workflowId}\n `;\n if (!existing[0] || existing[0].count === 0) {\n return false;\n }\n this.sql`DELETE FROM cf_agents_workflows WHERE workflow_id = ${workflowId}`;\n return true;\n }\n\n /**\n * Delete workflow tracking records matching criteria.\n * Useful for cleaning up old completed/errored workflows.\n *\n * @param criteria - Criteria for which workflows to delete\n * @returns Number of records matching criteria (expected deleted count)\n *\n * @example\n * ```typescript\n * // Delete all completed workflows created more than 7 days ago\n * const deleted = this.deleteWorkflows({\n * status: 'complete',\n * createdBefore: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000)\n * });\n *\n * // Delete all errored and terminated workflows\n * const deleted = this.deleteWorkflows({\n * status: ['errored', 'terminated']\n * });\n * ```\n */\n deleteWorkflows(\n criteria: Omit<WorkflowQueryCriteria, \"limit\" | \"orderBy\"> & {\n createdBefore?: Date;\n } = {}\n ): number {\n let query = \"DELETE FROM cf_agents_workflows WHERE 1=1\";\n const params: (string | number | boolean)[] = [];\n\n if (criteria.status) {\n const statuses = Array.isArray(criteria.status)\n ? criteria.status\n : [criteria.status];\n const placeholders = statuses.map(() => \"?\").join(\", \");\n query += ` AND status IN (${placeholders})`;\n params.push(...statuses);\n }\n\n if (criteria.workflowName) {\n query += \" AND workflow_name = ?\";\n params.push(criteria.workflowName);\n }\n\n if (criteria.metadata) {\n for (const [key, value] of Object.entries(criteria.metadata)) {\n query += ` AND json_extract(metadata, '$.' || ?) = ?`;\n params.push(key, value);\n }\n }\n\n if (criteria.createdBefore) {\n query += \" AND created_at < ?\";\n params.push(Math.floor(criteria.createdBefore.getTime() / 1000));\n }\n\n const cursor = this.ctx.storage.sql.exec(query, ...params);\n return cursor.rowsWritten;\n }\n\n /**\n * Migrate workflow tracking records from an old binding name to a new one.\n * Use this after renaming a workflow binding in wrangler.toml.\n *\n * @param oldName - Previous workflow binding name\n * @param newName - New workflow binding name\n * @returns Number of records migrated\n *\n * @example\n * ```typescript\n * // After renaming OLD_WORKFLOW to NEW_WORKFLOW in wrangler.toml\n * async onStart() {\n * const migrated = this.migrateWorkflowBinding('OLD_WORKFLOW', 'NEW_WORKFLOW');\n * }\n * ```\n */\n migrateWorkflowBinding(oldName: string, newName: string): number {\n // Validate new binding exists\n if (!this._findWorkflowBindingByName(newName)) {\n throw new Error(`Workflow binding '${newName}' not found in environment`);\n }\n\n const result = this.sql<{ count: number }>`\n SELECT COUNT(*) as count FROM cf_agents_workflows WHERE workflow_name = ${oldName}\n `;\n const count = result[0]?.count ?? 0;\n\n if (count > 0) {\n this\n .sql`UPDATE cf_agents_workflows SET workflow_name = ${newName} WHERE workflow_name = ${oldName}`;\n console.log(\n `[Agent] Migrated ${count} workflow(s) from '${oldName}' to '${newName}'`\n );\n }\n\n return count;\n }\n\n /**\n * Update workflow tracking record from InstanceStatus\n */\n private _updateWorkflowTracking(\n workflowId: string,\n status: InstanceStatus\n ): void {\n const statusName = status.status;\n const now = Math.floor(Date.now() / 1000);\n\n // Determine if workflow is complete\n const completedStatuses: WorkflowStatus[] = [\n \"complete\",\n \"errored\",\n \"terminated\"\n ];\n const completedAt = completedStatuses.includes(statusName) ? now : null;\n\n // Extract error info if present\n const errorName = status.error?.name ?? null;\n const errorMessage = status.error?.message ?? null;\n\n this.sql`\n UPDATE cf_agents_workflows\n SET status = ${statusName},\n error_name = ${errorName},\n error_message = ${errorMessage},\n updated_at = ${now},\n completed_at = ${completedAt}\n WHERE workflow_id = ${workflowId}\n `;\n }\n\n /**\n * Convert a database row to WorkflowInfo\n */\n private _rowToWorkflowInfo(row: WorkflowTrackingRow): WorkflowInfo {\n return {\n id: row.id,\n workflowId: row.workflow_id,\n workflowName: row.workflow_name,\n status: row.status,\n metadata: row.metadata ? JSON.parse(row.metadata) : null,\n error: row.error_name\n ? { name: row.error_name, message: row.error_message ?? \"\" }\n : null,\n createdAt: new Date(row.created_at * 1000),\n updatedAt: new Date(row.updated_at * 1000),\n completedAt: row.completed_at ? new Date(row.completed_at * 1000) : null\n };\n }\n\n /**\n * Find the binding name for this Agent's namespace by matching class name.\n * Returns undefined if no match found - use options.agentBinding as fallback.\n */\n private _findAgentBindingName(): string | undefined {\n const className = this._ParentClass.name;\n for (const [key, value] of Object.entries(\n this.env as Record<string, unknown>\n )) {\n if (\n value &&\n typeof value === \"object\" &&\n \"idFromName\" in value &&\n typeof value.idFromName === \"function\"\n ) {\n // Check if this namespace's binding name matches our class name\n if (\n key === className ||\n camelCaseToKebabCase(key) === camelCaseToKebabCase(className)\n ) {\n return key;\n }\n }\n }\n return undefined;\n }\n\n private _findBindingNameForNamespace(\n namespace: DurableObjectNamespace<McpAgent>\n ): string | undefined {\n for (const [key, value] of Object.entries(\n this.env as Record<string, unknown>\n )) {\n if (value === namespace) {\n return key;\n }\n }\n return undefined;\n }\n\n private async _restoreRpcMcpServers(): Promise<void> {\n const rpcServers = this.mcp.getRpcServersFromStorage();\n for (const server of rpcServers) {\n if (this.mcp.mcpConnections[server.id]) {\n continue;\n }\n\n const opts: { bindingName: string; props?: Record<string, unknown> } =\n server.server_options ? JSON.parse(server.server_options) : {};\n\n const namespace = (this.env as Record<string, unknown>)[\n opts.bindingName\n ] as DurableObjectNamespace<McpAgent> | undefined;\n if (!namespace) {\n console.warn(\n `[Agent] Cannot restore RPC MCP server \"${server.name}\": binding \"${opts.bindingName}\" not found in env`\n );\n continue;\n }\n\n const normalizedName = server.server_url.replace(RPC_DO_PREFIX, \"\");\n\n try {\n await this.mcp.connect(`${RPC_DO_PREFIX}${normalizedName}`, {\n reconnect: { id: server.id },\n transport: {\n type: \"rpc\" as TransportType,\n namespace,\n name: normalizedName,\n props: opts.props\n }\n });\n\n const conn = this.mcp.mcpConnections[server.id];\n if (conn && conn.connectionState === MCPConnectionState.CONNECTED) {\n await this.mcp.discoverIfConnected(server.id);\n }\n } catch (error) {\n console.error(\n `[Agent] Error restoring RPC MCP server \"${server.name}\":`,\n error\n );\n }\n }\n }\n\n // ==========================================\n // Workflow Lifecycle Callbacks\n // ==========================================\n\n /**\n * Handle a callback from a workflow.\n * Called when the Agent receives a callback at /_workflow/callback.\n * Override this to handle all callback types in one place.\n *\n * @param callback - The callback payload\n */\n async onWorkflowCallback(callback: WorkflowCallback): Promise<void> {\n const now = Math.floor(Date.now() / 1000);\n\n switch (callback.type) {\n case \"progress\":\n // Update tracking status to \"running\" when receiving progress\n // Only transition from queued/waiting to avoid overwriting terminal states\n this.sql`\n UPDATE cf_agents_workflows\n SET status = 'running', updated_at = ${now}\n WHERE workflow_id = ${callback.workflowId} AND status IN ('queued', 'waiting')\n `;\n await this.onWorkflowProgress(\n callback.workflowName,\n callback.workflowId,\n callback.progress\n );\n break;\n case \"complete\":\n // Update tracking status to \"complete\"\n // Don't overwrite if already terminated/paused (race condition protection)\n this.sql`\n UPDATE cf_agents_workflows\n SET status = 'complete', updated_at = ${now}, completed_at = ${now}\n WHERE workflow_id = ${callback.workflowId}\n AND status NOT IN ('terminated', 'paused')\n `;\n await this.onWorkflowComplete(\n callback.workflowName,\n callback.workflowId,\n callback.result\n );\n break;\n case \"error\":\n // Update tracking status to \"errored\"\n // Don't overwrite if already terminated/paused (race condition protection)\n this.sql`\n UPDATE cf_agents_workflows\n SET status = 'errored', updated_at = ${now}, completed_at = ${now},\n error_name = 'WorkflowError', error_message = ${callback.error}\n WHERE workflow_id = ${callback.workflowId}\n AND status NOT IN ('terminated', 'paused')\n `;\n await this.onWorkflowError(\n callback.workflowName,\n callback.workflowId,\n callback.error\n );\n break;\n case \"event\":\n // No status change for events - they can occur at any stage\n await this.onWorkflowEvent(\n callback.workflowName,\n callback.workflowId,\n callback.event\n );\n break;\n }\n }\n\n /**\n * Called when a workflow reports progress.\n * Override to handle progress updates.\n *\n * @param workflowName - Workflow binding name\n * @param workflowId - ID of the workflow\n * @param progress - Typed progress data (default: DefaultProgress)\n */\n async onWorkflowProgress(\n // oxlint-disable-next-line no-unused-vars\n workflowName: string,\n // oxlint-disable-next-line no-unused-vars\n workflowId: string,\n // oxlint-disable-next-line no-unused-vars\n progress: unknown\n ): Promise<void> {\n // Override to handle progress updates\n }\n\n /**\n * Called when a workflow completes successfully.\n * Override to handle completion.\n *\n * @param workflowName - Workflow binding name\n * @param workflowId - ID of the workflow\n * @param result - Optional result data\n */\n async onWorkflowComplete(\n // oxlint-disable-next-line no-unused-vars\n workflowName: string,\n // oxlint-disable-next-line no-unused-vars\n workflowId: string,\n // oxlint-disable-next-line no-unused-vars\n result?: unknown\n ): Promise<void> {\n // Override to handle completion\n }\n\n /**\n * Called when a workflow encounters an error.\n * Override to handle errors.\n *\n * @param workflowName - Workflow binding name\n * @param workflowId - ID of the workflow\n * @param error - Error message\n */\n async onWorkflowError(\n workflowName: string,\n workflowId: string,\n error: string\n ): Promise<void> {\n console.error(\n `Workflow error [${workflowName}/${workflowId}]: ${error}\\n` +\n \"Override onWorkflowError() in your Agent to handle workflow errors.\"\n );\n }\n\n /**\n * Called when a workflow sends a custom event.\n * Override to handle custom events.\n *\n * @param workflowName - Workflow binding name\n * @param workflowId - ID of the workflow\n * @param event - Custom event payload\n */\n async onWorkflowEvent(\n // oxlint-disable-next-line no-unused-vars\n workflowName: string,\n // oxlint-disable-next-line no-unused-vars\n workflowId: string,\n // oxlint-disable-next-line no-unused-vars\n event: unknown\n ): Promise<void> {\n // Override to handle custom events\n }\n\n // ============================================================\n // Internal RPC methods for AgentWorkflow communication\n // These are called via DO RPC, not exposed via HTTP\n // ============================================================\n\n /**\n * Handle a workflow callback via RPC.\n * @internal - Called by AgentWorkflow, do not call directly\n */\n async _workflow_handleCallback(callback: WorkflowCallback): Promise<void> {\n await this.__unsafe_ensureInitialized();\n await this.onWorkflowCallback(callback);\n }\n\n /**\n * Broadcast a message to all connected clients via RPC.\n * @internal - Called by AgentWorkflow, do not call directly\n */\n async _workflow_broadcast(message: unknown): Promise<void> {\n await this.__unsafe_ensureInitialized();\n this.broadcast(JSON.stringify(message));\n }\n\n /**\n * Update agent state via RPC.\n * @internal - Called by AgentWorkflow, do not call directly\n */\n async _workflow_updateState(\n action: \"set\" | \"merge\" | \"reset\",\n state?: unknown\n ): Promise<void> {\n await this.__unsafe_ensureInitialized();\n if (action === \"set\") {\n this.setState(state as State);\n } else if (action === \"merge\") {\n const currentState = this.state ?? ({} as State);\n this.setState({\n ...currentState,\n ...(state as Record<string, unknown>)\n } as State);\n } else if (action === \"reset\") {\n this.setState(this.initialState);\n }\n }\n\n /**\n * Connect to a new MCP Server via RPC (Durable Object binding)\n *\n * The binding name and props are persisted to storage so the connection\n * is automatically restored after Durable Object hibernation.\n *\n * @example\n * await this.addMcpServer(\"counter\", env.MY_MCP);\n * await this.addMcpServer(\"counter\", env.MY_MCP, { props: { userId: \"123\" } });\n */\n async addMcpServer<T extends McpAgent>(\n serverName: string,\n binding: DurableObjectNamespace<T>,\n options?: AddRpcMcpServerOptions\n ): Promise<{ id: string; state: typeof MCPConnectionState.READY }>;\n\n /**\n * Connect to a new MCP Server via HTTP (SSE or Streamable HTTP)\n *\n * @example\n * await this.addMcpServer(\"github\", \"https://mcp.github.com\");\n * await this.addMcpServer(\"github\", \"https://mcp.github.com\", { transport: { type: \"sse\" } });\n * await this.addMcpServer(\"github\", url, callbackHost, agentsPrefix, options); // legacy\n */\n async addMcpServer(\n serverName: string,\n url: string,\n callbackHostOrOptions?: string | AddMcpServerOptions,\n agentsPrefix?: string,\n options?: {\n client?: ConstructorParameters<typeof Client>[1];\n transport?: { headers?: HeadersInit; type?: TransportType };\n }\n ): Promise<\n | {\n id: string;\n state: typeof MCPConnectionState.AUTHENTICATING;\n authUrl: string;\n }\n | { id: string; state: typeof MCPConnectionState.READY }\n >;\n\n async addMcpServer<T extends McpAgent>(\n serverName: string,\n urlOrBinding: string | DurableObjectNamespace<T>,\n callbackHostOrOptions?:\n | string\n | AddMcpServerOptions\n | AddRpcMcpServerOptions,\n agentsPrefix?: string,\n options?: {\n client?: ConstructorParameters<typeof Client>[1];\n transport?: {\n headers?: HeadersInit;\n type?: TransportType;\n };\n }\n ): Promise<\n | {\n id: string;\n state: typeof MCPConnectionState.AUTHENTICATING;\n authUrl: string;\n }\n | {\n id: string;\n state: typeof MCPConnectionState.READY;\n authUrl?: undefined;\n }\n > {\n const isHttpTransport = typeof urlOrBinding === \"string\";\n const normalizedUrl = isHttpTransport\n ? new URL(urlOrBinding).href\n : undefined;\n const existingServer = this.mcp\n .listServers()\n .find(\n (s) =>\n s.name === serverName &&\n (!isHttpTransport || new URL(s.server_url).href === normalizedUrl)\n );\n if (existingServer && this.mcp.mcpConnections[existingServer.id]) {\n const conn = this.mcp.mcpConnections[existingServer.id];\n if (\n conn.connectionState === MCPConnectionState.AUTHENTICATING &&\n conn.options.transport.authProvider?.authUrl\n ) {\n return {\n id: existingServer.id,\n state: MCPConnectionState.AUTHENTICATING,\n authUrl: conn.options.transport.authProvider.authUrl\n };\n }\n if (conn.connectionState === MCPConnectionState.FAILED) {\n throw new Error(\n `MCP server \"${serverName}\" is in failed state: ${conn.connectionError}`\n );\n }\n return { id: existingServer.id, state: MCPConnectionState.READY };\n }\n\n // RPC transport path: second argument is a DurableObjectNamespace\n if (typeof urlOrBinding !== \"string\") {\n const rpcOpts = callbackHostOrOptions as\n | AddRpcMcpServerOptions\n | undefined;\n\n const normalizedName = serverName.toLowerCase().replace(/\\s+/g, \"-\");\n\n const reconnectId = existingServer?.id;\n const { id } = await this.mcp.connect(\n `${RPC_DO_PREFIX}${normalizedName}`,\n {\n reconnect: reconnectId ? { id: reconnectId } : undefined,\n transport: {\n type: \"rpc\" as TransportType,\n namespace:\n urlOrBinding as unknown as DurableObjectNamespace<McpAgent>,\n name: normalizedName,\n props: rpcOpts?.props\n }\n }\n );\n\n const conn = this.mcp.mcpConnections[id];\n if (conn && conn.connectionState === MCPConnectionState.CONNECTED) {\n const discoverResult = await this.mcp.discoverIfConnected(id);\n if (discoverResult && !discoverResult.success) {\n throw new Error(\n `Failed to discover MCP server capabilities: ${discoverResult.error}`\n );\n }\n } else if (conn && conn.connectionState === MCPConnectionState.FAILED) {\n throw new Error(\n `Failed to connect to MCP server \"${serverName}\" via RPC: ${conn.connectionError}`\n );\n }\n\n const bindingName = this._findBindingNameForNamespace(\n urlOrBinding as unknown as DurableObjectNamespace<McpAgent>\n );\n if (bindingName) {\n this.mcp.saveRpcServerToStorage(\n id,\n serverName,\n normalizedName,\n bindingName,\n rpcOpts?.props\n );\n }\n\n return { id, state: MCPConnectionState.READY };\n }\n\n // HTTP transport path\n const httpOptions = callbackHostOrOptions as\n | string\n | AddMcpServerOptions\n | undefined;\n\n let resolvedCallbackHost: string | undefined;\n let resolvedAgentsPrefix: string;\n let resolvedOptions:\n | {\n client?: ConstructorParameters<typeof Client>[1];\n transport?: {\n headers?: HeadersInit;\n type?: TransportType;\n };\n retry?: RetryOptions;\n }\n | undefined;\n\n let resolvedCallbackPath: string | undefined;\n\n if (typeof httpOptions === \"object\" && httpOptions !== null) {\n resolvedCallbackHost = httpOptions.callbackHost;\n resolvedCallbackPath = httpOptions.callbackPath;\n resolvedAgentsPrefix = httpOptions.agentsPrefix ?? \"agents\";\n resolvedOptions = {\n client: httpOptions.client,\n transport: httpOptions.transport,\n retry: httpOptions.retry\n };\n } else {\n resolvedCallbackHost = httpOptions;\n resolvedAgentsPrefix = agentsPrefix ?? \"agents\";\n resolvedOptions = options;\n }\n\n // Enforce callbackPath when sendIdentityOnConnect is false and callbackHost is provided\n if (\n !this._resolvedOptions.sendIdentityOnConnect &&\n resolvedCallbackHost &&\n !resolvedCallbackPath\n ) {\n throw new Error(\n \"callbackPath is required in addMcpServer options when sendIdentityOnConnect is false — \" +\n \"the default callback URL would expose the instance name. \" +\n \"Provide a callbackPath and route the callback request to this agent via getAgentByName.\"\n );\n }\n\n // Try to derive callbackHost from the current request or connection URI\n if (!resolvedCallbackHost) {\n const { request, connection } = getCurrentAgent();\n if (request) {\n const requestUrl = new URL(request.url);\n resolvedCallbackHost = `${requestUrl.protocol}//${requestUrl.host}`;\n } else if (connection?.uri) {\n const connectionUrl = new URL(connection.uri);\n resolvedCallbackHost = `${connectionUrl.protocol}//${connectionUrl.host}`;\n }\n }\n\n // Build the callback URL if we have a host (needed for OAuth, optional for non-OAuth servers)\n let callbackUrl: string | undefined;\n if (resolvedCallbackHost) {\n const normalizedHost = resolvedCallbackHost.replace(/\\/$/, \"\");\n callbackUrl = resolvedCallbackPath\n ? `${normalizedHost}/${resolvedCallbackPath.replace(/^\\//, \"\")}`\n : `${normalizedHost}/${resolvedAgentsPrefix}/${camelCaseToKebabCase(this._ParentClass.name)}/${this.name}/callback`;\n }\n\n const id = nanoid(8);\n\n // Only create authProvider if we have a callbackUrl (needed for OAuth servers)\n let authProvider:\n | ReturnType<typeof this.createMcpOAuthProvider>\n | undefined;\n if (callbackUrl) {\n authProvider = this.createMcpOAuthProvider(callbackUrl);\n authProvider.serverId = id;\n }\n\n // Use the transport type specified in options, or default to \"auto\"\n const transportType: TransportType =\n resolvedOptions?.transport?.type ?? \"auto\";\n\n // allows passing through transport headers if necessary\n // this handles some non-standard bearer auth setups (i.e. MCP server behind CF access instead of OAuth)\n let headerTransportOpts: SSEClientTransportOptions = {};\n if (resolvedOptions?.transport?.headers) {\n headerTransportOpts = {\n eventSourceInit: {\n fetch: (url, init) =>\n fetch(url, {\n ...init,\n headers: resolvedOptions?.transport?.headers\n })\n },\n requestInit: {\n headers: resolvedOptions?.transport?.headers\n }\n };\n }\n\n // Register server (also saves to storage)\n await this.mcp.registerServer(id, {\n url: normalizedUrl!,\n name: serverName,\n callbackUrl,\n client: resolvedOptions?.client,\n transport: {\n ...headerTransportOpts,\n authProvider,\n type: transportType\n },\n retry: resolvedOptions?.retry\n });\n\n const result = await this.mcp.connectToServer(id);\n\n if (result.state === MCPConnectionState.FAILED) {\n // Server stays in storage so user can retry via connectToServer(id)\n throw new Error(\n `Failed to connect to MCP server at ${normalizedUrl}: ${result.error}`\n );\n }\n\n if (result.state === MCPConnectionState.AUTHENTICATING) {\n if (!callbackUrl) {\n throw new Error(\n \"This MCP server requires OAuth authentication. \" +\n \"Provide callbackHost in addMcpServer options to enable the OAuth flow.\"\n );\n }\n return { id, state: result.state, authUrl: result.authUrl };\n }\n\n // State is CONNECTED - discover capabilities\n const discoverResult = await this.mcp.discoverIfConnected(id);\n\n if (discoverResult && !discoverResult.success) {\n // Server stays in storage - connection is still valid, user can retry discovery\n throw new Error(\n `Failed to discover MCP server capabilities: ${discoverResult.error}`\n );\n }\n\n return { id, state: MCPConnectionState.READY };\n }\n\n async removeMcpServer(id: string) {\n await this.mcp.removeServer(id);\n }\n\n getMcpServers(): MCPServersState {\n const mcpState: MCPServersState = {\n prompts: this.mcp.listPrompts(),\n resources: this.mcp.listResources(),\n servers: {},\n tools: this.mcp.listTools()\n };\n\n const servers = this.mcp.listServers();\n\n if (servers && Array.isArray(servers) && servers.length > 0) {\n for (const server of servers) {\n const serverConn = this.mcp.mcpConnections[server.id];\n\n // Determine the default state when no connection exists\n let defaultState: \"authenticating\" | \"not-connected\" = \"not-connected\";\n if (!serverConn && server.auth_url) {\n // If there's an auth_url but no connection, it's waiting for OAuth\n defaultState = \"authenticating\";\n }\n\n mcpState.servers[server.id] = {\n auth_url: server.auth_url,\n capabilities: serverConn?.serverCapabilities ?? null,\n error: sanitizeErrorString(serverConn?.connectionError ?? null),\n instructions: serverConn?.instructions ?? null,\n name: server.name,\n server_url: server.server_url,\n state: serverConn?.connectionState ?? defaultState\n };\n }\n }\n\n return mcpState;\n }\n\n /**\n * Create the OAuth provider used when connecting to MCP servers that require authentication.\n *\n * Override this method in a subclass to supply a custom OAuth provider implementation,\n * for example to use pre-registered client credentials, mTLS-based authentication,\n * or any other OAuth flow beyond dynamic client registration.\n *\n * @example\n * // Custom OAuth provider\n * class MyAgent extends Agent {\n * createMcpOAuthProvider(callbackUrl: string): AgentMcpOAuthProvider {\n * return new MyCustomOAuthProvider(\n * this.ctx.storage,\n * this.name,\n * callbackUrl\n * );\n * }\n * }\n *\n * @param callbackUrl The OAuth callback URL for the authorization flow\n * @returns An {@link AgentMcpOAuthProvider} instance used by {@link addMcpServer}\n */\n createMcpOAuthProvider(callbackUrl: string): AgentMcpOAuthProvider {\n return new DurableObjectOAuthClientProvider(\n this.ctx.storage,\n this.name,\n callbackUrl\n );\n }\n\n private broadcastMcpServers() {\n this._broadcastProtocol(\n JSON.stringify({\n mcp: this.getMcpServers(),\n type: MessageType.CF_AGENT_MCP_SERVERS\n })\n );\n }\n\n /**\n * Handle MCP OAuth callback request if it's an OAuth callback.\n *\n * This method encapsulates the entire OAuth callback flow:\n * 1. Checks if the request is an MCP OAuth callback\n * 2. Processes the OAuth code exchange\n * 3. Establishes the connection if successful\n * 4. Broadcasts MCP server state updates\n * 5. Returns the appropriate HTTP response\n *\n * @param request The incoming HTTP request\n * @returns Response if this was an OAuth callback, null otherwise\n */\n private async handleMcpOAuthCallback(\n request: Request\n ): Promise<Response | null> {\n // Check if this is an OAuth callback request\n const isCallback = this.mcp.isCallbackRequest(request);\n if (!isCallback) {\n return null;\n }\n\n // Handle the OAuth callback (exchanges code for token, clears OAuth credentials from storage)\n // This fires onServerStateChanged event which triggers broadcast\n const result = await this.mcp.handleCallbackRequest(request);\n\n // If auth was successful, establish the connection in the background\n // (establishConnection handles retries internally using per-server retry config)\n if (result.authSuccess) {\n this.mcp.establishConnection(result.serverId).catch((error) => {\n console.error(\n \"[Agent handleMcpOAuthCallback] Connection establishment failed:\",\n error\n );\n });\n }\n\n this.broadcastMcpServers();\n\n // Return the HTTP response for the OAuth callback\n return this.handleOAuthCallbackResponse(result, request);\n }\n\n /**\n * Handle OAuth callback response using MCPClientManager configuration\n * @param result OAuth callback result\n * @param request The original request (needed for base URL)\n * @returns Response for the OAuth callback\n */\n private handleOAuthCallbackResponse(\n result: MCPClientOAuthResult,\n request: Request\n ): Response {\n const config = this.mcp.getOAuthCallbackConfig();\n\n // Use custom handler if configured\n if (config?.customHandler) {\n return config.customHandler(result);\n }\n\n const baseOrigin = new URL(request.url).origin;\n\n // Redirect to success URL if configured\n if (config?.successRedirect && result.authSuccess) {\n try {\n return Response.redirect(\n new URL(config.successRedirect, baseOrigin).href\n );\n } catch (e) {\n console.error(\n \"Invalid successRedirect URL:\",\n config.successRedirect,\n e\n );\n return Response.redirect(baseOrigin);\n }\n }\n\n // Redirect to error URL if configured\n if (config?.errorRedirect && !result.authSuccess) {\n try {\n const errorUrl = `${config.errorRedirect}?error=${encodeURIComponent(\n result.authError || \"Unknown error\"\n )}`;\n return Response.redirect(new URL(errorUrl, baseOrigin).href);\n } catch (e) {\n console.error(\"Invalid errorRedirect URL:\", config.errorRedirect, e);\n return Response.redirect(baseOrigin);\n }\n }\n\n return Response.redirect(baseOrigin);\n }\n}\n\n// A set of classes that have been wrapped with agent context\nconst wrappedClasses = new Set<typeof Agent.prototype.constructor>();\n\n/**\n * Namespace for creating Agent instances\n * @template Agentic Type of the Agent class\n * @deprecated Use DurableObjectNamespace instead\n */\nexport type AgentNamespace<Agentic extends Agent<Cloudflare.Env>> =\n DurableObjectNamespace<Agentic>;\n\n/**\n * Agent's durable context\n */\nexport type AgentContext = DurableObjectState;\n\n/**\n * Configuration options for Agent routing\n */\nexport type AgentOptions<Env> = PartyServerOptions<Env>;\n\n/**\n * Route a request to the appropriate Agent\n * @param request Request to route\n * @param env Environment containing Agent bindings\n * @param options Routing options\n * @returns Response from the Agent or undefined if no route matched\n */\nexport async function routeAgentRequest<Env>(\n request: Request,\n env: Env,\n options?: AgentOptions<Env>\n) {\n // oxlint-disable-next-line typescript/no-explicit-any\n return routePartykitRequest(request, env as any, {\n prefix: \"agents\",\n ...(options as PartyServerOptions<Record<string, unknown>>)\n });\n}\n\n// Email routing - deprecated resolver kept in root for upgrade discoverability\n// Other email utilities moved to agents/email subpath\nexport { createHeaderBasedEmailResolver } from \"./email\";\n\nimport type { EmailResolver } from \"./email\";\n\nexport type EmailRoutingOptions<Env> = AgentOptions<Env> & {\n resolver: EmailResolver<Env>;\n /**\n * Callback invoked when no routing information is found for an email.\n * Use this to reject the email or perform custom handling.\n * If not provided, a warning is logged and the email is dropped.\n */\n onNoRoute?: (email: ForwardableEmailMessage) => void | Promise<void>;\n};\n\n// RpcTarget bridge for email callbacks. Consolidates the email event's\n// mutation methods (setReject, forward, reply) into a single disposable\n// RPC target instead of anonymous closures. This allows the runtime to\n// tear down the bidirectional RPC session when _onEmail returns,\n// rather than keeping the DO pinned for the caller's entire context\n// lifetime (~100-120s for CF Email Routing handlers).\nclass EmailBridge extends RpcTarget {\n #email: ForwardableEmailMessage;\n\n constructor(email: ForwardableEmailMessage) {\n super();\n this.#email = email;\n }\n\n async getRaw(): Promise<Uint8Array> {\n const reader = this.#email.raw.getReader();\n const chunks: Uint8Array[] = [];\n let done = false;\n while (!done) {\n const { value, done: readerDone } = await reader.read();\n done = readerDone;\n if (value) {\n chunks.push(value);\n }\n }\n const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);\n const combined = new Uint8Array(totalLength);\n let offset = 0;\n for (const chunk of chunks) {\n combined.set(chunk, offset);\n offset += chunk.length;\n }\n return combined;\n }\n\n setReject(reason: string) {\n this.#email.setReject(reason);\n }\n\n forward(rcptTo: string, headers?: Headers): Promise<EmailSendResult> {\n return this.#email.forward(rcptTo, headers);\n }\n\n reply(options: {\n from: string;\n to: string;\n raw: string;\n }): Promise<EmailSendResult> {\n return this.#email.reply(\n new EmailMessage(options.from, options.to, options.raw)\n );\n }\n\n [Symbol.dispose]() {\n // Intentionally empty — the runtime calls this when the last\n // stub is disposed, signaling that the RPC target is no longer\n // needed and the bidirectional connection can be torn down.\n }\n}\n\n// Cache the agent namespace map for email routing\n// This maps original names, kebab-case, and lowercase versions to namespaces\nconst agentMapCache = new WeakMap<\n Record<string, unknown>,\n { map: Record<string, unknown>; originalNames: string[] }\n>();\n\n/**\n * Route an email to the appropriate Agent\n * @param email The email to route\n * @param env The environment containing the Agent bindings\n * @param options The options for routing the email\n * @returns A promise that resolves when the email has been routed\n */\nexport async function routeAgentEmail<\n Env extends Cloudflare.Env = Cloudflare.Env\n>(\n email: ForwardableEmailMessage,\n env: Env,\n options: EmailRoutingOptions<Env>\n): Promise<void> {\n const routingInfo = await options.resolver(email, env);\n\n if (!routingInfo) {\n if (options.onNoRoute) {\n await options.onNoRoute(email);\n } else {\n console.warn(\"No routing information found for email, dropping message\");\n }\n return;\n }\n\n // Build a map that includes original names, kebab-case, and lowercase versions\n if (!agentMapCache.has(env as Record<string, unknown>)) {\n const map: Record<string, unknown> = {};\n const originalNames: string[] = [];\n for (const [key, value] of Object.entries(env as Record<string, unknown>)) {\n if (\n value &&\n typeof value === \"object\" &&\n \"idFromName\" in value &&\n typeof value.idFromName === \"function\"\n ) {\n // Add the original name, kebab-case version, and lowercase version\n map[key] = value;\n map[camelCaseToKebabCase(key)] = value;\n map[key.toLowerCase()] = value;\n originalNames.push(key);\n }\n }\n agentMapCache.set(env as Record<string, unknown>, {\n map,\n originalNames\n });\n }\n\n const cached = agentMapCache.get(env as Record<string, unknown>)!;\n const namespace = cached.map[routingInfo.agentName];\n\n if (!namespace) {\n // Provide helpful error message listing available agents\n const availableAgents = cached.originalNames.join(\", \");\n throw new Error(\n `Agent namespace '${routingInfo.agentName}' not found in environment. Available agents: ${availableAgents}`\n );\n }\n\n const agent = await getAgentByName(\n namespace as unknown as DurableObjectNamespace<Agent<Env>>,\n routingInfo.agentId\n );\n\n // Use an RpcTarget bridge instead of bare closures so the runtime\n // can cleanly tear down the bidirectional session after _onEmail returns\n const bridge = new EmailBridge(email);\n\n await agent._onEmail({\n from: email.from,\n to: email.to,\n headers: email.headers,\n rawSize: email.rawSize,\n _secureRouted: routingInfo._secureRouted,\n _bridge: bridge\n });\n}\n\n/**\n * Get or create an Agent by name\n * @template Env Environment type containing bindings\n * @template T Type of the Agent class\n * @param namespace Agent namespace\n * @param name Name of the Agent instance\n * @param options Options for Agent creation\n * @returns Promise resolving to an Agent instance stub\n */\nexport async function getAgentByName<\n Env extends Cloudflare.Env = Cloudflare.Env,\n T extends Agent<Env> = Agent<Env>,\n Props extends Record<string, unknown> = Record<string, unknown>\n>(\n namespace: DurableObjectNamespace<T>,\n name: string,\n options?: {\n jurisdiction?: DurableObjectJurisdiction;\n locationHint?: DurableObjectLocationHint;\n props?: Props;\n }\n) {\n return getServerByName<Env, T>(namespace, name, options);\n}\n\n/**\n * A wrapper for streaming responses in callable methods\n */\nexport class StreamingResponse {\n private _connection: Connection;\n private _id: string;\n private _closed = false;\n\n constructor(connection: Connection, id: string) {\n this._connection = connection;\n this._id = id;\n }\n\n /**\n * Whether the stream has been closed (via end() or error())\n */\n get isClosed(): boolean {\n return this._closed;\n }\n\n /**\n * Send a chunk of data to the client\n * @param chunk The data to send\n * @returns false if stream is already closed (no-op), true if sent\n */\n send(chunk: unknown): boolean {\n if (this._closed) {\n console.warn(\n \"StreamingResponse.send() called after stream was closed - data not sent\"\n );\n return false;\n }\n const response: RPCResponse = {\n done: false,\n id: this._id,\n result: chunk,\n success: true,\n type: MessageType.RPC\n };\n this._connection.send(JSON.stringify(response));\n return true;\n }\n\n /**\n * End the stream and send the final chunk (if any)\n * @param finalChunk Optional final chunk of data to send\n * @returns false if stream is already closed (no-op), true if sent\n */\n end(finalChunk?: unknown): boolean {\n if (this._closed) {\n return false;\n }\n this._closed = true;\n const response: RPCResponse = {\n done: true,\n id: this._id,\n result: finalChunk,\n success: true,\n type: MessageType.RPC\n };\n this._connection.send(JSON.stringify(response));\n return true;\n }\n\n /**\n * Send an error to the client and close the stream\n * @param message Error message to send\n * @returns false if stream is already closed (no-op), true if sent\n */\n error(message: string): boolean {\n if (this._closed) {\n return false;\n }\n this._closed = true;\n const response: RPCResponse = {\n error: message,\n id: this._id,\n success: false,\n type: MessageType.RPC\n };\n this._connection.send(JSON.stringify(response));\n return true;\n }\n}\n"],"mappings":"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"}