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.
- package/dist/experimental/sub-agent.d.ts +205 -0
- package/dist/experimental/sub-agent.js +191 -0
- package/dist/experimental/sub-agent.js.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +42 -3
- package/dist/index.js.map +1 -1
- package/package.json +11 -6
|
@@ -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 ?? {};
|