agents 0.7.2 → 0.7.4

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.
@@ -0,0 +1,205 @@
1
+ import { Server } from "partyserver";
2
+
3
+ //#region src/experimental/sub-agent.d.ts
4
+ /** @internal */
5
+ interface FacetCapableCtx {
6
+ facets: {
7
+ get(name: string, getStartupOptions: () => {
8
+ id?: DurableObjectId | string;
9
+ class: DurableObjectClass;
10
+ } | Promise<{
11
+ id?: DurableObjectId | string;
12
+ class: DurableObjectClass;
13
+ }>): Fetcher;
14
+ abort(name: string, reason: unknown): void;
15
+ delete(name: string): void;
16
+ };
17
+ exports: Record<string, DurableObjectClass>;
18
+ }
19
+ /**
20
+ * Constructor type for a SubAgent subclass.
21
+ * Used by {@link SubAgent.subAgent} to reference the child class
22
+ * via `ctx.exports`.
23
+ *
24
+ * The class name (`cls.name`) must match the export name in the
25
+ * worker entry point — re-exports under a different name
26
+ * (e.g. `export { Foo as Bar }`) are not supported.
27
+ */
28
+ type SubAgentClass<T extends SubAgent = SubAgent> = {
29
+ new (ctx: DurableObjectState, env: never): T;
30
+ };
31
+ /**
32
+ * Wraps `T` in a `Promise` unless it already is one.
33
+ */
34
+ type Promisify<T> = T extends Promise<unknown> ? T : Promise<T>;
35
+ /**
36
+ * Server / DurableObject internals excluded from the RPC stub.
37
+ * This is a blocklist — if `Server` or `SubAgent` gains new methods
38
+ * they must be added here to stay hidden from the stub type.
39
+ */
40
+ type SubAgentInternals = "fetch" | "alarm" | "webSocketMessage" | "webSocketClose" | "webSocketError" | "sql" | "broadcast" | "getConnection" | "getConnections" | "getConnectionTags" | "setName" | "onStart" | "onConnect" | "onMessage" | "onClose" | "onError" | "onRequest" | "onException" | "onAlarm" | "subAgent" | "abortSubAgent" | "deleteSubAgent";
41
+ /**
42
+ * A typed RPC stub for a SubAgent. Exposes all public instance methods
43
+ * as callable RPC methods with Promise-wrapped return types.
44
+ *
45
+ * Methods inherited from `Server` / `DurableObject` internals are
46
+ * excluded — only user-defined methods on the SubAgent subclass are
47
+ * exposed.
48
+ */
49
+ type SubAgentStub<T extends SubAgent> = { [K in keyof T as K extends SubAgentInternals ? never : T[K] extends ((...args: never[]) => unknown) ? K : never]: T[K] extends ((...args: infer A) => infer R) ? (...args: A) => Promisify<R> : never };
50
+ /**
51
+ * Base class for sub-agents — child Durable Objects that run as facets
52
+ * of a parent Agent (or another SubAgent) on the same machine, each
53
+ * with their own isolated SQLite storage.
54
+ *
55
+ * Extends partyserver's `Server`, so inherits:
56
+ * - `this.sql` tagged-template SQL helper
57
+ * - `this.name` identity
58
+ * - WebSocket hibernation + `onConnect`/`onMessage`/`onClose`
59
+ * - `broadcast()`, `getConnection()`, `getConnections()`
60
+ *
61
+ * SubAgents do **not** need wrangler.jsonc entries — they are
62
+ * referenced via `ctx.exports` and instantiated through the
63
+ * experimental facets API.
64
+ *
65
+ * @experimental Requires the `"experimental"` compatibility flag.
66
+ *
67
+ * @example
68
+ * ```typescript
69
+ * import { SubAgent } from "agents/experimental/subagent";
70
+ *
71
+ * export class SearchAgent extends SubAgent {
72
+ * async search(query: string): Promise<Result[]> {
73
+ * const cached = this.sql`SELECT * FROM cache WHERE q = ${query}`;
74
+ * if (cached.length) return cached;
75
+ * // ... fetch, cache, return
76
+ * }
77
+ * }
78
+ * ```
79
+ */
80
+ declare class SubAgent<Env extends Cloudflare.Env = Cloudflare.Env> extends Server<Env> {
81
+ /**
82
+ * Get or create a named child sub-agent — a facet with its own
83
+ * isolated SQLite storage running on the same machine.
84
+ *
85
+ * The first call for a given name triggers the child's `onStart()`.
86
+ * Subsequent calls with the same name return the existing instance
87
+ * (the set-name fetch is a no-op if already initialized).
88
+ *
89
+ * @experimental Requires the `"experimental"` compatibility flag.
90
+ *
91
+ * @param cls The SubAgent subclass (must be exported from the worker)
92
+ * @param name Unique name for this child instance
93
+ * @returns A typed RPC stub for calling methods on the child
94
+ *
95
+ * @example
96
+ * ```typescript
97
+ * const searcher = await this.subAgent(SearchAgent, "main-search");
98
+ * const results = await searcher.search("cloudflare agents");
99
+ * ```
100
+ */
101
+ subAgent<T extends SubAgent>(cls: SubAgentClass<T>, name: string): Promise<SubAgentStub<T>>;
102
+ /**
103
+ * Forcefully abort a running child sub-agent. The child stops
104
+ * executing immediately and will be restarted on next
105
+ * {@link subAgent} call. Pending RPC calls receive the reason
106
+ * as an error. Transitively aborts the child's own children.
107
+ *
108
+ * @experimental Requires the `"experimental"` compatibility flag.
109
+ *
110
+ * @param name Name of the child to abort
111
+ * @param reason Error thrown to pending/future RPC callers
112
+ */
113
+ abortSubAgent(name: string, reason?: unknown): void;
114
+ /**
115
+ * Delete a child sub-agent: abort it if running, then permanently
116
+ * wipe its storage. Transitively deletes the child's own children.
117
+ *
118
+ * @experimental Requires the `"experimental"` compatibility flag.
119
+ *
120
+ * @param name Name of the child to delete
121
+ */
122
+ deleteSubAgent(name: string): void;
123
+ }
124
+ type Constructor<T = object> = new (...args: any[]) => T;
125
+ /**
126
+ * Mixin that adds sub-agent management methods to an Agent (or
127
+ * AIChatAgent, McpAgent, etc.) without shipping them in the base
128
+ * `Agent` class.
129
+ *
130
+ * @experimental Requires the `"experimental"` compatibility flag.
131
+ *
132
+ * @example
133
+ * ```typescript
134
+ * import { Agent } from "agents";
135
+ * import { withSubAgents, SubAgent } from "agents/experimental/subagent";
136
+ *
137
+ * export class SearchAgent extends SubAgent {
138
+ * async search(query: string) { ... }
139
+ * }
140
+ *
141
+ * const SubAgentParent = withSubAgents(Agent);
142
+ *
143
+ * export class MyAgent extends SubAgentParent<Env> {
144
+ * async doStuff() {
145
+ * const searcher = await this.subAgent(SearchAgent, "main");
146
+ * await searcher.search("hello");
147
+ * }
148
+ * }
149
+ * ```
150
+ */
151
+ declare function withSubAgents<TBase extends Constructor>(Base: TBase): {
152
+ new (...args: any[]): {
153
+ /**
154
+ * Get or create a named sub-agent — a child Durable Object with its
155
+ * own isolated SQLite storage, running alongside this Agent on the
156
+ * same machine. The child class must extend `SubAgent` and be exported
157
+ * from the worker entry point.
158
+ *
159
+ * @experimental Requires the `"experimental"` compatibility flag.
160
+ *
161
+ * @param cls The SubAgent subclass (must be exported from the worker)
162
+ * @param name Unique name for this child instance
163
+ * @returns A typed RPC stub for calling methods on the child
164
+ */
165
+ subAgent<T extends SubAgent>(cls: SubAgentClass<T>, name: string): Promise<SubAgentStub<T>>;
166
+ /**
167
+ * Forcefully abort a running sub-agent. The child stops executing
168
+ * immediately and will be restarted on next {@link subAgent} call.
169
+ * Pending RPC calls receive the reason as an error.
170
+ * Transitively aborts the child's own children.
171
+ *
172
+ * @experimental Requires the `"experimental"` compatibility flag.
173
+ *
174
+ * @param name Name of the child to abort
175
+ * @param reason Error thrown to pending/future RPC callers
176
+ */
177
+ abortSubAgent(name: string, reason?: unknown): void;
178
+ /**
179
+ * Delete a sub-agent: abort it if running, then permanently wipe its
180
+ * storage. Transitively deletes the child's own children.
181
+ *
182
+ * @experimental Requires the `"experimental"` compatibility flag.
183
+ *
184
+ * @param name Name of the child to delete
185
+ */
186
+ deleteSubAgent(name: string): void;
187
+ };
188
+ } & TBase;
189
+ /**
190
+ * Synchronous validation that the SubAgent class exists in worker exports.
191
+ * Call this before `_getSubAgent` so the error is thrown synchronously
192
+ * in the caller’s scope (not as a rejected promise from an async function).
193
+ * This avoids unhandled-rejection noise in the workerd runtime.
194
+ * @internal
195
+ */
196
+ declare function _validateSubAgentExport(ctx: DurableObjectState, cls: SubAgentClass): void;
197
+ /** @internal */
198
+ declare function _getSubAgent<T extends SubAgent>(ctx: DurableObjectState, cls: SubAgentClass<T>, name: string): Promise<SubAgentStub<T>>;
199
+ /** @internal */
200
+ declare function _abortSubAgent(ctx: DurableObjectState, name: string, reason?: unknown): void;
201
+ /** @internal */
202
+ declare function _deleteSubAgent(ctx: DurableObjectState, name: string): void;
203
+ //#endregion
204
+ export { FacetCapableCtx, SubAgent, SubAgentClass, SubAgentStub, _abortSubAgent, _deleteSubAgent, _getSubAgent, _validateSubAgentExport, withSubAgents };
205
+ //# sourceMappingURL=sub-agent.d.ts.map
@@ -0,0 +1,191 @@
1
+ import { Server } from "partyserver";
2
+
3
+ //#region src/experimental/sub-agent.ts
4
+ /**
5
+ * Base class for sub-agents — child Durable Objects that run as facets
6
+ * of a parent Agent (or another SubAgent) on the same machine, each
7
+ * with their own isolated SQLite storage.
8
+ *
9
+ * Extends partyserver's `Server`, so inherits:
10
+ * - `this.sql` tagged-template SQL helper
11
+ * - `this.name` identity
12
+ * - WebSocket hibernation + `onConnect`/`onMessage`/`onClose`
13
+ * - `broadcast()`, `getConnection()`, `getConnections()`
14
+ *
15
+ * SubAgents do **not** need wrangler.jsonc entries — they are
16
+ * referenced via `ctx.exports` and instantiated through the
17
+ * experimental facets API.
18
+ *
19
+ * @experimental Requires the `"experimental"` compatibility flag.
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * import { SubAgent } from "agents/experimental/subagent";
24
+ *
25
+ * export class SearchAgent extends SubAgent {
26
+ * async search(query: string): Promise<Result[]> {
27
+ * const cached = this.sql`SELECT * FROM cache WHERE q = ${query}`;
28
+ * if (cached.length) return cached;
29
+ * // ... fetch, cache, return
30
+ * }
31
+ * }
32
+ * ```
33
+ */
34
+ var SubAgent = class extends Server {
35
+ /**
36
+ * Get or create a named child sub-agent — a facet with its own
37
+ * isolated SQLite storage running on the same machine.
38
+ *
39
+ * The first call for a given name triggers the child's `onStart()`.
40
+ * Subsequent calls with the same name return the existing instance
41
+ * (the set-name fetch is a no-op if already initialized).
42
+ *
43
+ * @experimental Requires the `"experimental"` compatibility flag.
44
+ *
45
+ * @param cls The SubAgent subclass (must be exported from the worker)
46
+ * @param name Unique name for this child instance
47
+ * @returns A typed RPC stub for calling methods on the child
48
+ *
49
+ * @example
50
+ * ```typescript
51
+ * const searcher = await this.subAgent(SearchAgent, "main-search");
52
+ * const results = await searcher.search("cloudflare agents");
53
+ * ```
54
+ */
55
+ async subAgent(cls, name) {
56
+ _validateSubAgentExport(this.ctx, cls);
57
+ return _getSubAgent(this.ctx, cls, name);
58
+ }
59
+ /**
60
+ * Forcefully abort a running child sub-agent. The child stops
61
+ * executing immediately and will be restarted on next
62
+ * {@link subAgent} call. Pending RPC calls receive the reason
63
+ * as an error. Transitively aborts the child's own children.
64
+ *
65
+ * @experimental Requires the `"experimental"` compatibility flag.
66
+ *
67
+ * @param name Name of the child to abort
68
+ * @param reason Error thrown to pending/future RPC callers
69
+ */
70
+ abortSubAgent(name, reason) {
71
+ _abortSubAgent(this.ctx, name, reason);
72
+ }
73
+ /**
74
+ * Delete a child sub-agent: abort it if running, then permanently
75
+ * wipe its storage. Transitively deletes the child's own children.
76
+ *
77
+ * @experimental Requires the `"experimental"` compatibility flag.
78
+ *
79
+ * @param name Name of the child to delete
80
+ */
81
+ deleteSubAgent(name) {
82
+ _deleteSubAgent(this.ctx, name);
83
+ }
84
+ };
85
+ /**
86
+ * Mixin that adds sub-agent management methods to an Agent (or
87
+ * AIChatAgent, McpAgent, etc.) without shipping them in the base
88
+ * `Agent` class.
89
+ *
90
+ * @experimental Requires the `"experimental"` compatibility flag.
91
+ *
92
+ * @example
93
+ * ```typescript
94
+ * import { Agent } from "agents";
95
+ * import { withSubAgents, SubAgent } from "agents/experimental/subagent";
96
+ *
97
+ * export class SearchAgent extends SubAgent {
98
+ * async search(query: string) { ... }
99
+ * }
100
+ *
101
+ * const SubAgentParent = withSubAgents(Agent);
102
+ *
103
+ * export class MyAgent extends SubAgentParent<Env> {
104
+ * async doStuff() {
105
+ * const searcher = await this.subAgent(SearchAgent, "main");
106
+ * await searcher.search("hello");
107
+ * }
108
+ * }
109
+ * ```
110
+ */
111
+ function withSubAgents(Base) {
112
+ class WithSubAgents extends Base {
113
+ /**
114
+ * Get or create a named sub-agent — a child Durable Object with its
115
+ * own isolated SQLite storage, running alongside this Agent on the
116
+ * same machine. The child class must extend `SubAgent` and be exported
117
+ * from the worker entry point.
118
+ *
119
+ * @experimental Requires the `"experimental"` compatibility flag.
120
+ *
121
+ * @param cls The SubAgent subclass (must be exported from the worker)
122
+ * @param name Unique name for this child instance
123
+ * @returns A typed RPC stub for calling methods on the child
124
+ */
125
+ async subAgent(cls, name) {
126
+ const { ctx } = this;
127
+ _validateSubAgentExport(ctx, cls);
128
+ return _getSubAgent(ctx, cls, name);
129
+ }
130
+ /**
131
+ * Forcefully abort a running sub-agent. The child stops executing
132
+ * immediately and will be restarted on next {@link subAgent} call.
133
+ * Pending RPC calls receive the reason as an error.
134
+ * Transitively aborts the child's own children.
135
+ *
136
+ * @experimental Requires the `"experimental"` compatibility flag.
137
+ *
138
+ * @param name Name of the child to abort
139
+ * @param reason Error thrown to pending/future RPC callers
140
+ */
141
+ abortSubAgent(name, reason) {
142
+ const { ctx } = this;
143
+ _abortSubAgent(ctx, name, reason);
144
+ }
145
+ /**
146
+ * Delete a sub-agent: abort it if running, then permanently wipe its
147
+ * storage. Transitively deletes the child's own children.
148
+ *
149
+ * @experimental Requires the `"experimental"` compatibility flag.
150
+ *
151
+ * @param name Name of the child to delete
152
+ */
153
+ deleteSubAgent(name) {
154
+ const { ctx } = this;
155
+ _deleteSubAgent(ctx, name);
156
+ }
157
+ }
158
+ return WithSubAgents;
159
+ }
160
+ /**
161
+ * Synchronous validation that the SubAgent class exists in worker exports.
162
+ * Call this before `_getSubAgent` so the error is thrown synchronously
163
+ * in the caller’s scope (not as a rejected promise from an async function).
164
+ * This avoids unhandled-rejection noise in the workerd runtime.
165
+ * @internal
166
+ */
167
+ function _validateSubAgentExport(ctx, cls) {
168
+ const { exports } = ctx;
169
+ if (!exports[cls.name]) throw new Error(`SubAgent class "${cls.name}" not found in worker exports. Make sure the class is exported from your worker entry point and that the export name matches the class name.`);
170
+ }
171
+ /** @internal */
172
+ async function _getSubAgent(ctx, cls, name) {
173
+ const { facets, exports } = ctx;
174
+ const stub = facets.get(name, () => ({ class: exports[cls.name] }));
175
+ const req = new Request("http://dummy-example.cloudflare.com/cdn-cgi/partyserver/set-name/");
176
+ req.headers.set("x-partykit-room", name);
177
+ await stub.fetch(req).then((res) => res.text());
178
+ return stub;
179
+ }
180
+ /** @internal */
181
+ function _abortSubAgent(ctx, name, reason) {
182
+ ctx.facets.abort(name, reason);
183
+ }
184
+ /** @internal */
185
+ function _deleteSubAgent(ctx, name) {
186
+ ctx.facets.delete(name);
187
+ }
188
+
189
+ //#endregion
190
+ export { SubAgent, _abortSubAgent, _deleteSubAgent, _getSubAgent, _validateSubAgentExport, withSubAgents };
191
+ //# sourceMappingURL=sub-agent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sub-agent.js","names":[],"sources":["../../src/experimental/sub-agent.ts"],"sourcesContent":["import { Server } from \"partyserver\";\n\n// ── Internal facet access types ─────────────────────────────────────\n// These mirror the experimental workerd `ctx.facets` API without\n// depending on the \"experimental\" compat flag at the type level.\n\n/** @internal */\nexport interface FacetCapableCtx {\n facets: {\n get(\n name: string,\n getStartupOptions: () =>\n | { id?: DurableObjectId | string; class: DurableObjectClass }\n | Promise<{\n id?: DurableObjectId | string;\n class: DurableObjectClass;\n }>\n ): Fetcher;\n abort(name: string, reason: unknown): void;\n delete(name: string): void;\n };\n exports: Record<string, DurableObjectClass>;\n}\n\n// ── Public types ────────────────────────────────────────────────────\n\n/**\n * Constructor type for a SubAgent subclass.\n * Used by {@link SubAgent.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 SubAgent = SubAgent> = {\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 * Server / DurableObject internals excluded from the RPC stub.\n * This is a blocklist — if `Server` or `SubAgent` gains new methods\n * they must be added here to stay hidden from the stub type.\n */\ntype SubAgentInternals =\n | \"fetch\"\n | \"alarm\"\n | \"webSocketMessage\"\n | \"webSocketClose\"\n | \"webSocketError\"\n | \"sql\"\n | \"broadcast\"\n | \"getConnection\"\n | \"getConnections\"\n | \"getConnectionTags\"\n | \"setName\"\n | \"onStart\"\n | \"onConnect\"\n | \"onMessage\"\n | \"onClose\"\n | \"onError\"\n | \"onRequest\"\n | \"onException\"\n | \"onAlarm\"\n | \"subAgent\"\n | \"abortSubAgent\"\n | \"deleteSubAgent\";\n\n/**\n * A typed RPC stub for a SubAgent. Exposes all public instance methods\n * as callable RPC methods with Promise-wrapped return types.\n *\n * Methods inherited from `Server` / `DurableObject` internals are\n * excluded — only user-defined methods on the SubAgent subclass are\n * exposed.\n */\nexport type SubAgentStub<T extends SubAgent> = {\n [K in keyof T as K extends SubAgentInternals\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// ── SubAgent class ──────────────────────────────────────────────────\n\n/**\n * Base class for sub-agents — child Durable Objects that run as facets\n * of a parent Agent (or another SubAgent) on the same machine, each\n * with their own isolated SQLite storage.\n *\n * Extends partyserver's `Server`, so inherits:\n * - `this.sql` tagged-template SQL helper\n * - `this.name` identity\n * - WebSocket hibernation + `onConnect`/`onMessage`/`onClose`\n * - `broadcast()`, `getConnection()`, `getConnections()`\n *\n * SubAgents do **not** need wrangler.jsonc entries — they are\n * referenced via `ctx.exports` and instantiated through the\n * experimental facets API.\n *\n * @experimental Requires the `\"experimental\"` compatibility flag.\n *\n * @example\n * ```typescript\n * import { SubAgent } from \"agents/experimental/subagent\";\n *\n * export class SearchAgent extends SubAgent {\n * async search(query: string): Promise<Result[]> {\n * const cached = this.sql`SELECT * FROM cache WHERE q = ${query}`;\n * if (cached.length) return cached;\n * // ... fetch, cache, return\n * }\n * }\n * ```\n */\nexport class SubAgent<\n Env extends Cloudflare.Env = Cloudflare.Env\n> extends Server<Env> {\n /**\n * Get or create a named child sub-agent — a facet with its own\n * isolated SQLite storage running on the same machine.\n *\n * The first call for a given name triggers the child's `onStart()`.\n * Subsequent calls with the same name return the existing instance\n * (the set-name fetch is a no-op if already initialized).\n *\n * @experimental Requires the `\"experimental\"` compatibility flag.\n *\n * @param cls The SubAgent 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 SubAgent>(\n cls: SubAgentClass<T>,\n name: string\n ): Promise<SubAgentStub<T>> {\n _validateSubAgentExport(this.ctx, cls);\n return _getSubAgent(this.ctx, cls, name);\n }\n\n /**\n * Forcefully abort a running child sub-agent. The child stops\n * executing immediately and will be restarted on next\n * {@link subAgent} call. Pending RPC calls receive the reason\n * as an error. Transitively aborts the child's own children.\n *\n * @experimental Requires the `\"experimental\"` compatibility flag.\n *\n * @param name Name of the child to abort\n * @param reason Error thrown to pending/future RPC callers\n */\n abortSubAgent(name: string, reason?: unknown): void {\n _abortSubAgent(this.ctx, name, reason);\n }\n\n /**\n * Delete a child sub-agent: abort it if running, then permanently\n * wipe its storage. Transitively deletes the child's own children.\n *\n * @experimental Requires the `\"experimental\"` compatibility flag.\n *\n * @param name Name of the child to delete\n */\n deleteSubAgent(name: string): void {\n _deleteSubAgent(this.ctx, name);\n }\n}\n\n// ── withSubAgents mixin ─────────────────────────────────────────────\n\n// oxlint-disable-next-line @typescript-eslint/no-explicit-any -- mixin constructor constraint\ntype Constructor<T = object> = new (...args: any[]) => T;\n\n/**\n * Mixin that adds sub-agent management methods to an Agent (or\n * AIChatAgent, McpAgent, etc.) without shipping them in the base\n * `Agent` class.\n *\n * @experimental Requires the `\"experimental\"` compatibility flag.\n *\n * @example\n * ```typescript\n * import { Agent } from \"agents\";\n * import { withSubAgents, SubAgent } from \"agents/experimental/subagent\";\n *\n * export class SearchAgent extends SubAgent {\n * async search(query: string) { ... }\n * }\n *\n * const SubAgentParent = withSubAgents(Agent);\n *\n * export class MyAgent extends SubAgentParent<Env> {\n * async doStuff() {\n * const searcher = await this.subAgent(SearchAgent, \"main\");\n * await searcher.search(\"hello\");\n * }\n * }\n * ```\n */\nexport function withSubAgents<TBase extends Constructor>(Base: TBase) {\n class WithSubAgents extends Base {\n /**\n * Get or create a named sub-agent — a child Durable Object with its\n * own isolated SQLite storage, running alongside this Agent on the\n * same machine. The child class must extend `SubAgent` and be exported\n * from the worker entry point.\n *\n * @experimental Requires the `\"experimental\"` compatibility flag.\n *\n * @param cls The SubAgent 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 async subAgent<T extends SubAgent>(\n cls: SubAgentClass<T>,\n name: string\n ): Promise<SubAgentStub<T>> {\n const { ctx } = this as unknown as { ctx: DurableObjectState };\n _validateSubAgentExport(ctx, cls);\n return _getSubAgent(ctx, cls, name);\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 Requires the `\"experimental\"` compatibility flag.\n *\n * @param name Name of the child to abort\n * @param reason Error thrown to pending/future RPC callers\n */\n abortSubAgent(name: string, reason?: unknown): void {\n const { ctx } = this as unknown as { ctx: DurableObjectState };\n _abortSubAgent(ctx, name, 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 Requires the `\"experimental\"` compatibility flag.\n *\n * @param name Name of the child to delete\n */\n deleteSubAgent(name: string): void {\n const { ctx } = this as unknown as { ctx: DurableObjectState };\n _deleteSubAgent(ctx, name);\n }\n }\n return WithSubAgents;\n}\n\n// ── Shared helpers (used by both SubAgent and withSubAgents mixin) ───\n\n/**\n * Synchronous validation that the SubAgent class exists in worker exports.\n * Call this before `_getSubAgent` so the error is thrown synchronously\n * in the caller’s scope (not as a rejected promise from an async function).\n * This avoids unhandled-rejection noise in the workerd runtime.\n * @internal\n */\nexport function _validateSubAgentExport(\n ctx: DurableObjectState,\n cls: SubAgentClass\n): void {\n const { exports } = ctx as unknown as FacetCapableCtx;\n if (!exports[cls.name]) {\n throw new Error(\n `SubAgent class \"${cls.name}\" 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}\n\n/** @internal */\nexport async function _getSubAgent<T extends SubAgent>(\n ctx: DurableObjectState,\n cls: SubAgentClass<T>,\n name: string\n): Promise<SubAgentStub<T>> {\n const { facets, exports } = ctx as unknown as FacetCapableCtx;\n const stub = facets.get(name, () => ({\n class: exports[cls.name] as DurableObjectClass\n }));\n\n // Trigger Server initialization (setName → onStart) via fetch,\n // same pattern as getAgentByName / getServerByName.\n const req = new Request(\n \"http://dummy-example.cloudflare.com/cdn-cgi/partyserver/set-name/\"\n );\n req.headers.set(\"x-partykit-room\", name);\n await stub.fetch(req).then((res) => res.text());\n\n return stub as unknown as SubAgentStub<T>;\n}\n\n/** @internal */\nexport function _abortSubAgent(\n ctx: DurableObjectState,\n name: string,\n reason?: unknown\n): void {\n (ctx as unknown as FacetCapableCtx).facets.abort(name, reason);\n}\n\n/** @internal */\nexport function _deleteSubAgent(ctx: DurableObjectState, name: string): void {\n (ctx as unknown as FacetCapableCtx).facets.delete(name);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2HA,IAAa,WAAb,cAEU,OAAY;;;;;;;;;;;;;;;;;;;;;CAqBpB,MAAM,SACJ,KACA,MAC0B;AAC1B,0BAAwB,KAAK,KAAK,IAAI;AACtC,SAAO,aAAa,KAAK,KAAK,KAAK,KAAK;;;;;;;;;;;;;CAc1C,cAAc,MAAc,QAAwB;AAClD,iBAAe,KAAK,KAAK,MAAM,OAAO;;;;;;;;;;CAWxC,eAAe,MAAoB;AACjC,kBAAgB,KAAK,KAAK,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCnC,SAAgB,cAAyC,MAAa;CACpE,MAAM,sBAAsB,KAAK;;;;;;;;;;;;;EAa/B,MAAM,SACJ,KACA,MAC0B;GAC1B,MAAM,EAAE,QAAQ;AAChB,2BAAwB,KAAK,IAAI;AACjC,UAAO,aAAa,KAAK,KAAK,KAAK;;;;;;;;;;;;;EAcrC,cAAc,MAAc,QAAwB;GAClD,MAAM,EAAE,QAAQ;AAChB,kBAAe,KAAK,MAAM,OAAO;;;;;;;;;;EAWnC,eAAe,MAAoB;GACjC,MAAM,EAAE,QAAQ;AAChB,mBAAgB,KAAK,KAAK;;;AAG9B,QAAO;;;;;;;;;AAYT,SAAgB,wBACd,KACA,KACM;CACN,MAAM,EAAE,YAAY;AACpB,KAAI,CAAC,QAAQ,IAAI,MACf,OAAM,IAAI,MACR,mBAAmB,IAAI,KAAK,8IAG7B;;;AAKL,eAAsB,aACpB,KACA,KACA,MAC0B;CAC1B,MAAM,EAAE,QAAQ,YAAY;CAC5B,MAAM,OAAO,OAAO,IAAI,aAAa,EACnC,OAAO,QAAQ,IAAI,OACpB,EAAE;CAIH,MAAM,MAAM,IAAI,QACd,oEACD;AACD,KAAI,QAAQ,IAAI,mBAAmB,KAAK;AACxC,OAAM,KAAK,MAAM,IAAI,CAAC,MAAM,QAAQ,IAAI,MAAM,CAAC;AAE/C,QAAO;;;AAIT,SAAgB,eACd,KACA,MACA,QACM;AACN,CAAC,IAAmC,OAAO,MAAM,MAAM,OAAO;;;AAIhE,SAAgB,gBAAgB,KAAyB,MAAoB;AAC3E,CAAC,IAAmC,OAAO,OAAO,KAAK"}
package/dist/index.d.ts CHANGED
@@ -1104,7 +1104,7 @@ declare class Agent<
1104
1104
  * Broadcast a message to all connected clients via RPC.
1105
1105
  * @internal - Called by AgentWorkflow, do not call directly
1106
1106
  */
1107
- _workflow_broadcast(message: unknown): void;
1107
+ _workflow_broadcast(message: unknown): Promise<void>;
1108
1108
  /**
1109
1109
  * Update agent state via RPC.
1110
1110
  * @internal - Called by AgentWorkflow, do not call directly
@@ -1112,7 +1112,7 @@ declare class Agent<
1112
1112
  _workflow_updateState(
1113
1113
  action: "set" | "merge" | "reset",
1114
1114
  state?: unknown
1115
- ): void;
1115
+ ): Promise<void>;
1116
1116
  /**
1117
1117
  * Connect to a new MCP Server via RPC (Durable Object binding)
1118
1118
  *
package/dist/index.js CHANGED
@@ -333,7 +333,9 @@ var Agent = class Agent extends Server {
333
333
  cron TEXT,
334
334
  intervalSeconds INTEGER,
335
335
  running INTEGER DEFAULT 0,
336
- created_at INTEGER DEFAULT (unixepoch())
336
+ created_at INTEGER DEFAULT (unixepoch()),
337
+ execution_started_at INTEGER,
338
+ retry_options TEXT
337
339
  )
338
340
  `;
339
341
  const addColumnIfNotExists = (sql) => {
@@ -348,6 +350,40 @@ var Agent = class Agent extends Server {
348
350
  addColumnIfNotExists("ALTER TABLE cf_agents_schedules ADD COLUMN execution_started_at INTEGER");
349
351
  addColumnIfNotExists("ALTER TABLE cf_agents_schedules ADD COLUMN retry_options TEXT");
350
352
  addColumnIfNotExists("ALTER TABLE cf_agents_queues ADD COLUMN retry_options TEXT");
353
+ {
354
+ const rows = this.ctx.storage.sql.exec("SELECT sql FROM sqlite_master WHERE type='table' AND name='cf_agents_schedules'").toArray();
355
+ if (rows.length > 0) {
356
+ if (!String(rows[0].sql).includes("'interval'")) {
357
+ this.ctx.storage.sql.exec("DROP TABLE IF EXISTS cf_agents_schedules_new");
358
+ this.ctx.storage.sql.exec(`
359
+ CREATE TABLE cf_agents_schedules_new (
360
+ id TEXT PRIMARY KEY NOT NULL DEFAULT (randomblob(9)),
361
+ callback TEXT,
362
+ payload TEXT,
363
+ type TEXT NOT NULL CHECK(type IN ('scheduled', 'delayed', 'cron', 'interval')),
364
+ time INTEGER,
365
+ delayInSeconds INTEGER,
366
+ cron TEXT,
367
+ intervalSeconds INTEGER,
368
+ running INTEGER DEFAULT 0,
369
+ created_at INTEGER DEFAULT (unixepoch()),
370
+ execution_started_at INTEGER,
371
+ retry_options TEXT
372
+ )
373
+ `);
374
+ this.ctx.storage.sql.exec(`
375
+ INSERT INTO cf_agents_schedules_new
376
+ (id, callback, payload, type, time, delayInSeconds, cron,
377
+ intervalSeconds, running, created_at, execution_started_at, retry_options)
378
+ SELECT id, callback, payload, type, time, delayInSeconds, cron,
379
+ intervalSeconds, running, created_at, execution_started_at, retry_options
380
+ FROM cf_agents_schedules
381
+ `);
382
+ this.ctx.storage.sql.exec("DROP TABLE cf_agents_schedules");
383
+ this.ctx.storage.sql.exec("ALTER TABLE cf_agents_schedules_new RENAME TO cf_agents_schedules");
384
+ }
385
+ }
386
+ }
351
387
  this.sql`
352
388
  CREATE TABLE IF NOT EXISTS cf_agents_workflows (
353
389
  id TEXT PRIMARY KEY NOT NULL,
@@ -2316,20 +2352,23 @@ var Agent = class Agent extends Server {
2316
2352
  * @internal - Called by AgentWorkflow, do not call directly
2317
2353
  */
2318
2354
  async _workflow_handleCallback(callback) {
2355
+ await this.__unsafe_ensureInitialized();
2319
2356
  await this.onWorkflowCallback(callback);
2320
2357
  }
2321
2358
  /**
2322
2359
  * Broadcast a message to all connected clients via RPC.
2323
2360
  * @internal - Called by AgentWorkflow, do not call directly
2324
2361
  */
2325
- _workflow_broadcast(message) {
2362
+ async _workflow_broadcast(message) {
2363
+ await this.__unsafe_ensureInitialized();
2326
2364
  this.broadcast(JSON.stringify(message));
2327
2365
  }
2328
2366
  /**
2329
2367
  * Update agent state via RPC.
2330
2368
  * @internal - Called by AgentWorkflow, do not call directly
2331
2369
  */
2332
- _workflow_updateState(action, state) {
2370
+ async _workflow_updateState(action, state) {
2371
+ await this.__unsafe_ensureInitialized();
2333
2372
  if (action === "set") this.setState(state);
2334
2373
  else if (action === "merge") {
2335
2374
  const currentState = this.state ?? {};