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.
- package/dist/experimental/forever.d.ts +2 -1
- 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 +31 -4
- package/dist/index.js +146 -84
- package/dist/index.js.map +1 -1
- package/package.json +11 -6
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
*
|