agents 0.7.1 → 0.7.3

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.
@@ -92,10 +92,11 @@ declare function withFibers<TBase extends AgentLike>(Base: TBase, options?: {
92
92
  _checkInterruptedFibers(): Promise<void>; /** @internal */
93
93
  _cleanupOrphanedHeartbeats(): void; /** @internal */
94
94
  _maybeCleanupFibers(): void;
95
- readonly alarm: () => Promise<void>;
95
+ alarm: () => Promise<void>;
96
96
  sql: <T = Record<string, string | number | boolean | null>>(strings: TemplateStringsArray, ...values: (string | number | boolean | null)[]) => T[];
97
97
  scheduleEvery: <T = string>(intervalSeconds: number, callback: keyof Agent<Cloudflare.Env, unknown, Record<string, unknown>>, payload?: T | undefined, options?: {
98
98
  retry?: RetryOptions;
99
+ _idempotent?: boolean;
99
100
  }) => Promise<Schedule<T>>;
100
101
  cancelSchedule: (id: string) => Promise<boolean>;
101
102
  keepAlive: () => Promise<() => void>;
@@ -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
@@ -596,7 +596,23 @@ declare class Agent<
596
596
  }
597
597
  ): Promise<Schedule<T>>;
598
598
  /**
599
- * Schedule a task to run repeatedly at a fixed interval
599
+ * Schedule a task to run repeatedly at a fixed interval.
600
+ *
601
+ * This method is **idempotent** — calling it multiple times with the same
602
+ * `callback`, `intervalSeconds`, and `payload` returns the existing schedule
603
+ * instead of creating a duplicate. A different interval or payload is
604
+ * treated as a distinct schedule and creates a new row.
605
+ *
606
+ * This makes it safe to call in `onStart()`, which runs on every Durable
607
+ * Object wake:
608
+ *
609
+ * ```ts
610
+ * async onStart() {
611
+ * // Only one schedule is created, no matter how many times the DO wakes
612
+ * await this.scheduleEvery(30, "tick");
613
+ * }
614
+ * ```
615
+ *
600
616
  * @template T Type of the payload data
601
617
  * @param intervalSeconds Number of seconds between executions
602
618
  * @param callback Name of the method to call
@@ -611,6 +627,7 @@ declare class Agent<
611
627
  payload?: T,
612
628
  options?: {
613
629
  retry?: RetryOptions;
630
+ _idempotent?: boolean;
614
631
  }
615
632
  ): Promise<Schedule<T>>;
616
633
  /**
@@ -688,15 +705,25 @@ declare class Agent<
688
705
  */
689
706
  _cf_keepAliveHeartbeat(): Promise<void>;
690
707
  private _scheduleNextAlarm;
708
+ /**
709
+ * Override PartyServer's onAlarm hook as a no-op.
710
+ * Agent handles alarm logic directly in the alarm() method override,
711
+ * but super.alarm() calls onAlarm() after #ensureInitialized(),
712
+ * so we suppress the default "Implement onAlarm" warning.
713
+ */
714
+ onAlarm(): void;
691
715
  /**
692
716
  * Method called when an alarm fires.
693
717
  * Executes any scheduled tasks that are due.
694
718
  *
719
+ * Calls super.alarm() first to ensure PartyServer's #ensureInitialized()
720
+ * runs, which hydrates this.name from storage and calls onStart() if needed.
721
+ *
695
722
  * @remarks
696
723
  * To schedule a task, please use the `this.schedule` method instead.
697
724
  * See {@link https://developers.cloudflare.com/agents/api-reference/schedule-tasks/}
698
725
  */
699
- readonly alarm: () => Promise<void>;
726
+ alarm(): Promise<void>;
700
727
  /**
701
728
  * Destroy the Agent, removing all state and scheduled tasks
702
729
  */
@@ -1077,7 +1104,7 @@ declare class Agent<
1077
1104
  * Broadcast a message to all connected clients via RPC.
1078
1105
  * @internal - Called by AgentWorkflow, do not call directly
1079
1106
  */
1080
- _workflow_broadcast(message: unknown): void;
1107
+ _workflow_broadcast(message: unknown): Promise<void>;
1081
1108
  /**
1082
1109
  * Update agent state via RPC.
1083
1110
  * @internal - Called by AgentWorkflow, do not call directly
@@ -1085,7 +1112,7 @@ declare class Agent<
1085
1112
  _workflow_updateState(
1086
1113
  action: "set" | "merge" | "reset",
1087
1114
  state?: unknown
1088
- ): void;
1115
+ ): Promise<void>;
1089
1116
  /**
1090
1117
  * Connect to a new MCP Server via RPC (Durable Object binding)
1091
1118
  *