@economic/agents 2.2.1 → 2.2.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/README.md +8 -0
- package/dist/index.d.mts +36 -14
- package/dist/index.mjs +102 -41
- package/dist/v1.d.mts +1 -1
- package/dist/v1.mjs +1 -1
- package/package.json +1 -1
- package/schema/0001_v2_release.sql +18 -0
- package/schema/agent/0001_initial.sql +0 -12
- /package/schema/{chat → v1}/0001_initial.sql +0 -0
- /package/schema/{chat → v1}/0002_add_rating_comment.sql +0 -0
- /package/schema/{chat → v1}/0003_drop_events.sql +0 -0
package/README.md
CHANGED
|
@@ -92,6 +92,14 @@ export default {
|
|
|
92
92
|
},
|
|
93
93
|
"migrations": [{ "tag": "v1", "new_sqlite_classes": ["SupportAgent"] }],
|
|
94
94
|
// see "Bindings"
|
|
95
|
+
"d1_databases": [
|
|
96
|
+
{
|
|
97
|
+
"binding": "AGENTS_DB",
|
|
98
|
+
"database_name": "agents",
|
|
99
|
+
"database_id": "agents",
|
|
100
|
+
"migrations_dir": "node_modules/@economic/agents/schema",
|
|
101
|
+
},
|
|
102
|
+
],
|
|
95
103
|
"r2_buckets": [{ "binding": "AGENTS_AUDIT_LOGS", "bucket_name": "agents-audit-logs" }],
|
|
96
104
|
"analytics_engine_datasets": [{ "binding": "AGENTS_ANALYTICS", "dataset": "agents-analytics" }],
|
|
97
105
|
}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { n as JwtAuthConfig, t as routeAgentRequest } from "./route-agent-request-DmwIOBJS.mjs";
|
|
2
|
+
import { Agent as Agent$1, Connection, ConnectionContext, SubAgentClass } from "agents";
|
|
2
3
|
import { ChatResponseResult, Session, StepConfig, Think, ToolCallContext, ToolCallDecision, TurnConfig, TurnContext } from "@cloudflare/think";
|
|
3
4
|
import { JSONValue, LanguageModel, Tool as Tool$1, UIMessage } from "ai";
|
|
4
|
-
import { Agent as Agent$1, Connection, ConnectionContext, SubAgentClass } from "agents";
|
|
5
5
|
//#region src/server/types.d.ts
|
|
6
6
|
/**
|
|
7
7
|
* The context object available throughout an agent's lifetime — passed via
|
|
@@ -13,10 +13,11 @@ type ToolContext<RequestContext extends Record<string, unknown> = Record<string,
|
|
|
13
13
|
_userContext?: UserContext;
|
|
14
14
|
};
|
|
15
15
|
interface AgentEnv {
|
|
16
|
-
|
|
16
|
+
AGENTS_DB: D1Database;
|
|
17
17
|
AGENTS_AUDIT_LOGS: R2Bucket;
|
|
18
18
|
AGENTS_ANALYTICS: AnalyticsEngineDataset;
|
|
19
19
|
SKILLS_BUCKET: R2Bucket;
|
|
20
|
+
LOCAL_AGENT_DB?: D1Database;
|
|
20
21
|
}
|
|
21
22
|
type SqlFn = InstanceType<typeof Agent$1>["sql"];
|
|
22
23
|
type AgentConnectionStatus = "connecting" | "connected" | "disconnected" | "unauthorized";
|
|
@@ -45,7 +46,6 @@ interface Skill<Context extends Record<string, unknown> = Record<string, unknown
|
|
|
45
46
|
declare function skill<Context extends Record<string, unknown> = Record<string, unknown>>(definition: Skill<Context>): Skill<Context>;
|
|
46
47
|
//#endregion
|
|
47
48
|
//#region src/server/agents/Agent.d.ts
|
|
48
|
-
declare function getCurrentToolContext(): any;
|
|
49
49
|
declare abstract class Agent<RequestContext extends Record<string, unknown> = Record<string, unknown>, UserContext extends Record<string, unknown> = Record<string, unknown>> extends Think<Cloudflare.Env & AgentEnv, AgentConnectionState> {
|
|
50
50
|
initialState: AgentConnectionState;
|
|
51
51
|
protected clientIp?: string;
|
|
@@ -57,10 +57,10 @@ declare abstract class Agent<RequestContext extends Record<string, unknown> = Re
|
|
|
57
57
|
protected getParentAgent<T extends Agent$1>(): T | undefined;
|
|
58
58
|
abstract getModel(ctx?: ToolContext<RequestContext, UserContext>): LanguageModel;
|
|
59
59
|
abstract getSystemPrompt(ctx?: ToolContext<RequestContext, UserContext>): string;
|
|
60
|
-
configureSession(session: Session): Session;
|
|
61
60
|
onStart(): Promise<void>;
|
|
62
61
|
onClose(): Promise<void>;
|
|
63
62
|
onConnect(connection: Connection, ctx: ConnectionContext): Promise<void>;
|
|
63
|
+
configureSession(session: Session): Session;
|
|
64
64
|
/**
|
|
65
65
|
* Merges the client request `body` into `experimental_context` for tools
|
|
66
66
|
* returned from {@link getTools} only (Think-internal tools are unchanged).
|
|
@@ -83,7 +83,6 @@ declare abstract class Agent<RequestContext extends Record<string, unknown> = Re
|
|
|
83
83
|
* Returns the remote skills to be loaded from SKILLS_BUCKET.
|
|
84
84
|
* @returns The remote skills to be loaded from SKILLS_BUCKET.
|
|
85
85
|
*/
|
|
86
|
-
protected getRemoteSkills(): string[];
|
|
87
86
|
/**
|
|
88
87
|
* Returns the skills to load for the agent.
|
|
89
88
|
* @returns The skills to load for the agent.
|
|
@@ -116,6 +115,16 @@ declare abstract class Agent<RequestContext extends Record<string, unknown> = Re
|
|
|
116
115
|
* @param jwtToken - A valid JWT token following authentication.
|
|
117
116
|
*/
|
|
118
117
|
protected getUserContext?(jwtToken: string): Promise<UserContext>;
|
|
118
|
+
/**
|
|
119
|
+
* Self-registers this DO in the global `agent_registry`. Only top-level DOs
|
|
120
|
+
* are registered — facets are enumerable via their parent's own index, so
|
|
121
|
+
* registering them would explode the row count and duplicate that index.
|
|
122
|
+
*
|
|
123
|
+
* Best-effort and idempotent: called once per cold start from `onStart`, the
|
|
124
|
+
* insert no-ops on conflict. A failed write is simply retried on the next
|
|
125
|
+
* cold start, so registration is not allowed to block the connection.
|
|
126
|
+
*/
|
|
127
|
+
protected registerInstance(): Promise<void>;
|
|
119
128
|
}
|
|
120
129
|
//#endregion
|
|
121
130
|
//#region src/server/features/messages.d.ts
|
|
@@ -152,9 +161,7 @@ type MigrationDeps = {
|
|
|
152
161
|
/** The `Assistant` DO's bound `sql` tag (used to register migrated chats). */sql: SqlFn; /** Shared D1 database holding v1 `conversations` and `message_ratings`. */
|
|
153
162
|
db: D1Database; /** The user being migrated (the `Assistant` DO name). */
|
|
154
163
|
userId: string; /** Resolves a v1 chat DO stub by its `userId:chatId` name. */
|
|
155
|
-
|
|
156
|
-
getByName(name: string): LegacyChatStub;
|
|
157
|
-
}; /** Creates (or resolves) a v2 chat facet for the given chat id and returns its stub. */
|
|
164
|
+
durableObjectBinding: DurableObjectNamespace; /** Creates (or resolves) a v2 chat facet for the given chat id and returns its stub. */
|
|
158
165
|
createFacet: (chatId: string) => Promise<FacetStub>;
|
|
159
166
|
};
|
|
160
167
|
/**
|
|
@@ -221,22 +228,25 @@ type Chat = {
|
|
|
221
228
|
declare const DELETE_CHAT_CALLBACK: "deleteChatCallback";
|
|
222
229
|
//#endregion
|
|
223
230
|
//#region src/server/agents/Assistant.d.ts
|
|
224
|
-
declare abstract class Assistant extends Agent$1<Cloudflare.Env, AgentConnectionState> {
|
|
231
|
+
declare abstract class Assistant extends Agent$1<Cloudflare.Env & AgentEnv, AgentConnectionState> {
|
|
225
232
|
initialState: AgentConnectionState;
|
|
226
233
|
protected abstract agent: SubAgentClass<ChatAgent>;
|
|
227
234
|
protected abstract fastModel: LanguageModel;
|
|
235
|
+
onStart(): void;
|
|
236
|
+
onClose(): Promise<void>;
|
|
237
|
+
onConnect(connection: Connection, ctx: ConnectionContext): Promise<void>;
|
|
228
238
|
/**
|
|
229
|
-
* Binding
|
|
239
|
+
* Binding of the legacy v1 chat Durable Object class, used to migrate a
|
|
230
240
|
* user's v1 chats into facets the first time they connect. Set this on the
|
|
231
241
|
* concrete subclass to enable lazy v1 -> v2 migration; leave undefined to
|
|
232
242
|
* disable it (e.g. for greenfield deployments with no v1 data).
|
|
233
243
|
*/
|
|
234
|
-
protected
|
|
244
|
+
protected migrationBinding?: {
|
|
245
|
+
binding: DurableObjectNamespace;
|
|
246
|
+
db: D1Database;
|
|
247
|
+
};
|
|
235
248
|
/** In-flight migration, shared across concurrent connections to this DO. */
|
|
236
249
|
private _migrationPromise?;
|
|
237
|
-
onStart(): void;
|
|
238
|
-
onClose(): Promise<void>;
|
|
239
|
-
onConnect(connection: Connection, ctx: ConnectionContext): Promise<void>;
|
|
240
250
|
/**
|
|
241
251
|
* Runs the lazy v1 -> v2 migration for this user. Concurrent connections to
|
|
242
252
|
* this DO share a single in-flight run. Idempotency across runs/restarts is
|
|
@@ -251,6 +261,18 @@ declare abstract class Assistant extends Agent$1<Cloudflare.Env, AgentConnection
|
|
|
251
261
|
recordChatTurn(durableObjectName: string, messages: UIMessage[]): Promise<void>;
|
|
252
262
|
private [DELETE_CHAT_CALLBACK];
|
|
253
263
|
private scheduleChatForAutoDeletion;
|
|
264
|
+
/**
|
|
265
|
+
* Self-registers this Assistant in the global `agent_registry`. An Assistant
|
|
266
|
+
* is a top-level DO keyed directly by user id, so the DO name *is* the actor.
|
|
267
|
+
*
|
|
268
|
+
* Runs pre-auth in onStart (the DO has already persisted state by this point,
|
|
269
|
+
* so it must be tracked regardless of whether auth later succeeds).
|
|
270
|
+
* Best-effort and idempotent: no-ops on conflict, retried on the next start.
|
|
271
|
+
*/
|
|
272
|
+
private registerInstance;
|
|
254
273
|
}
|
|
255
274
|
//#endregion
|
|
275
|
+
//#region src/server/index.d.ts
|
|
276
|
+
declare function getCurrentToolContext(): any;
|
|
277
|
+
//#endregion
|
|
256
278
|
export { Agent, type AgentConnectionState, type AgentConnectionStatus, type AgentConnectionType, type AgentEnv, Assistant, ChatAgent, type FacetStub, type LegacyChatStub, type LegacyMessageFeedback, type MigrationDeps, type Skill, type Tool, type ToolContext, type ToolSet, getCurrentToolContext, migrateUserFromV1, routeAgentRequest, skill, tool };
|
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { i as verifyJwt, n as createAgentTracer, r as extractTokenFromConnectRequest, t as routeAgentRequest } from "./route-agent-request-DKDvDYnR.mjs";
|
|
2
|
+
import { Agent as Agent$1, callable, getCurrentAgent } from "agents";
|
|
2
3
|
import { Think } from "@cloudflare/think";
|
|
3
4
|
import { Output, convertToModelMessages, generateText, jsonSchema, pruneMessages, tool as tool$1 } from "ai";
|
|
4
|
-
import { Agent as Agent$1, callable, getCurrentAgent } from "agents";
|
|
5
|
-
import { R2SkillProvider } from "agents/experimental/memory/session";
|
|
6
5
|
import { nanoid } from "nanoid";
|
|
7
6
|
import { createCompactFunction } from "agents/experimental/memory/utils";
|
|
8
7
|
//#region src/server/util/tools.ts
|
|
@@ -42,10 +41,20 @@ var LocalSkillProvider = class {
|
|
|
42
41
|
}
|
|
43
42
|
};
|
|
44
43
|
//#endregion
|
|
45
|
-
//#region src/server/
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
//#region src/server/features/registry.ts
|
|
45
|
+
/**
|
|
46
|
+
* Registers a top-level DO in the global registry.
|
|
47
|
+
*
|
|
48
|
+
* Idempotent: keyed on `(agent_name, durable_object_name)`, so repeated calls
|
|
49
|
+
* across cold starts no-op and `created_at` reflects the first registration.
|
|
50
|
+
*/
|
|
51
|
+
async function registerAgent(db, input) {
|
|
52
|
+
await db.prepare(`INSERT INTO agent_registry (agent_name, durable_object_name, actor_id, created_at)
|
|
53
|
+
VALUES (?, ?, ?, ?)
|
|
54
|
+
ON CONFLICT (agent_name, durable_object_name) DO NOTHING`).bind(input.agentName, input.durableObjectName, input.actorId, input.createdAt).run();
|
|
48
55
|
}
|
|
56
|
+
//#endregion
|
|
57
|
+
//#region src/server/agents/Agent.ts
|
|
49
58
|
var Agent = class extends Think {
|
|
50
59
|
initialState = {
|
|
51
60
|
status: "connecting",
|
|
@@ -66,26 +75,16 @@ var Agent = class extends Think {
|
|
|
66
75
|
if (parent) return this.env[parent.className]?.getByName(parent.name);
|
|
67
76
|
}
|
|
68
77
|
}
|
|
69
|
-
configureSession(session) {
|
|
70
|
-
let configuredSession = session.withContext("soul", { provider: { get: async () => {
|
|
71
|
-
return this.getSystemPrompt(this._requestContext !== void 0 ? this._buildToolContext() : void 0);
|
|
72
|
-
} } }).withContext("critical-rules", { provider: { get: async () => SECURITY_RULES_PROMPT } }).withContext("turn-protocol-rules", { provider: { get: async () => TURN_PROTOCOL_RULES_PROMPT } });
|
|
73
|
-
const remoteSkills = this.getRemoteSkills();
|
|
74
|
-
if (remoteSkills.length) if (this.env.SKILLS_BUCKET) configuredSession = configuredSession.withContext("skills", { provider: new R2SkillProvider(this.env.SKILLS_BUCKET, {
|
|
75
|
-
prefix: "skills/",
|
|
76
|
-
keys: remoteSkills
|
|
77
|
-
}) });
|
|
78
|
-
else console.error("[Agent] Connection rejected: Remote skills defined, but no SKILLS_BUCKET R2 binding found");
|
|
79
|
-
const localSkills = this.getSkills();
|
|
80
|
-
if (localSkills.length) configuredSession = configuredSession.withContext("local-skills", { provider: new LocalSkillProvider(localSkills) });
|
|
81
|
-
return configuredSession.withCachedPrompt();
|
|
82
|
-
}
|
|
83
78
|
async onStart() {
|
|
84
79
|
this.setState({
|
|
85
80
|
...this.initialState,
|
|
86
81
|
status: "connecting"
|
|
87
82
|
});
|
|
88
83
|
let hasCorrectBindings = true;
|
|
84
|
+
if (!this.env.AGENTS_DB) {
|
|
85
|
+
hasCorrectBindings = false;
|
|
86
|
+
console.warn("[Agent] Connection rejected: no AGENTS_DB bound. Agents database is required for registration.");
|
|
87
|
+
}
|
|
89
88
|
if (!this.env.AGENTS_AUDIT_LOGS) {
|
|
90
89
|
hasCorrectBindings = false;
|
|
91
90
|
console.error("[Agent] Connection rejected: no AGENTS_AUDIT_LOGS bound. Audit logs are required.");
|
|
@@ -98,6 +97,7 @@ var Agent = class extends Think {
|
|
|
98
97
|
});
|
|
99
98
|
throw new Error("Could not connect to agent, bindings not found");
|
|
100
99
|
}
|
|
100
|
+
this.registerInstance();
|
|
101
101
|
}
|
|
102
102
|
async onClose() {
|
|
103
103
|
this.setState({
|
|
@@ -148,6 +148,14 @@ var Agent = class extends Think {
|
|
|
148
148
|
status: "connected"
|
|
149
149
|
});
|
|
150
150
|
}
|
|
151
|
+
configureSession(session) {
|
|
152
|
+
let configuredSession = session.withContext("soul", { provider: { get: async () => {
|
|
153
|
+
return this.getSystemPrompt(this._requestContext !== void 0 ? this._buildToolContext() : void 0);
|
|
154
|
+
} } }).withContext("critical-rules", { provider: { get: async () => SECURITY_RULES_PROMPT } }).withContext("turn-protocol-rules", { provider: { get: async () => TURN_PROTOCOL_RULES_PROMPT } });
|
|
155
|
+
const localSkills = this.getSkills();
|
|
156
|
+
if (localSkills.length) configuredSession = configuredSession.withContext("local-skills", { provider: new LocalSkillProvider(localSkills) });
|
|
157
|
+
return configuredSession.withCachedPrompt();
|
|
158
|
+
}
|
|
151
159
|
/**
|
|
152
160
|
* Merges the client request `body` into `experimental_context` for tools
|
|
153
161
|
* returned from {@link getTools} only (Think-internal tools are unchanged).
|
|
@@ -226,9 +234,6 @@ var Agent = class extends Think {
|
|
|
226
234
|
* Returns the remote skills to be loaded from SKILLS_BUCKET.
|
|
227
235
|
* @returns The remote skills to be loaded from SKILLS_BUCKET.
|
|
228
236
|
*/
|
|
229
|
-
getRemoteSkills() {
|
|
230
|
-
return [];
|
|
231
|
-
}
|
|
232
237
|
/**
|
|
233
238
|
* Returns the skills to load for the agent.
|
|
234
239
|
* @returns The skills to load for the agent.
|
|
@@ -268,6 +273,28 @@ var Agent = class extends Think {
|
|
|
268
273
|
* Define getUserContext to set a user context.
|
|
269
274
|
*/
|
|
270
275
|
_userContext;
|
|
276
|
+
/**
|
|
277
|
+
* Self-registers this DO in the global `agent_registry`. Only top-level DOs
|
|
278
|
+
* are registered — facets are enumerable via their parent's own index, so
|
|
279
|
+
* registering them would explode the row count and duplicate that index.
|
|
280
|
+
*
|
|
281
|
+
* Best-effort and idempotent: called once per cold start from `onStart`, the
|
|
282
|
+
* insert no-ops on conflict. A failed write is simply retried on the next
|
|
283
|
+
* cold start, so registration is not allowed to block the connection.
|
|
284
|
+
*/
|
|
285
|
+
async registerInstance() {
|
|
286
|
+
if (this.parentPath.length > 0) return;
|
|
287
|
+
try {
|
|
288
|
+
await registerAgent(this.env.AGENTS_DB, {
|
|
289
|
+
agentName: this.constructor.name,
|
|
290
|
+
durableObjectName: this.name,
|
|
291
|
+
actorId: this.getActorIdFromDurableObjectName(),
|
|
292
|
+
createdAt: Date.now()
|
|
293
|
+
});
|
|
294
|
+
} catch (error) {
|
|
295
|
+
console.error("[Agent] Failed to register in agent_registry", error);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
271
298
|
};
|
|
272
299
|
//#endregion
|
|
273
300
|
//#region src/server/features/chats.ts
|
|
@@ -423,14 +450,14 @@ function toEpochMs(value) {
|
|
|
423
450
|
* remain as a backstop until then.
|
|
424
451
|
*/
|
|
425
452
|
async function migrateUserFromV1(deps) {
|
|
426
|
-
const { sql, db, userId,
|
|
453
|
+
const { sql, db, userId, durableObjectBinding, createFacet } = deps;
|
|
427
454
|
const conversations = await listLegacyConversations(db, userId);
|
|
428
455
|
let migrated = 0;
|
|
429
456
|
let failed = 0;
|
|
430
457
|
for (const conversation of conversations) {
|
|
431
458
|
const legacyName = conversation.durable_object_name;
|
|
432
459
|
try {
|
|
433
|
-
const { messages } = await
|
|
460
|
+
const { messages } = await durableObjectBinding.getByName(legacyName).exportForMigration();
|
|
434
461
|
const feedback = await listLegacyFeedback(db, legacyName);
|
|
435
462
|
const newChatId = nanoid();
|
|
436
463
|
const facet = await createFacet(newChatId);
|
|
@@ -463,15 +490,6 @@ var Assistant = class extends Agent$1 {
|
|
|
463
490
|
status: "connecting",
|
|
464
491
|
type: "assistant"
|
|
465
492
|
};
|
|
466
|
-
/**
|
|
467
|
-
* Binding name of the legacy v1 chat Durable Object class, used to migrate a
|
|
468
|
-
* user's v1 chats into facets the first time they connect. Set this on the
|
|
469
|
-
* concrete subclass to enable lazy v1 -> v2 migration; leave undefined to
|
|
470
|
-
* disable it (e.g. for greenfield deployments with no v1 data).
|
|
471
|
-
*/
|
|
472
|
-
legacyBinding;
|
|
473
|
-
/** In-flight migration, shared across concurrent connections to this DO. */
|
|
474
|
-
_migrationPromise;
|
|
475
493
|
onStart() {
|
|
476
494
|
this.setState({
|
|
477
495
|
...this.initialState,
|
|
@@ -479,6 +497,19 @@ var Assistant = class extends Agent$1 {
|
|
|
479
497
|
subAgentName: this.agent.name
|
|
480
498
|
});
|
|
481
499
|
ensureChatsTableExists(this.sql.bind(this));
|
|
500
|
+
let hasCorrectBindings = true;
|
|
501
|
+
if (!this.env.AGENTS_DB) {
|
|
502
|
+
hasCorrectBindings = false;
|
|
503
|
+
console.warn("[Agent] Connection rejected: no AGENTS_DB bound. Agents database is required for registration.");
|
|
504
|
+
}
|
|
505
|
+
if (!hasCorrectBindings) {
|
|
506
|
+
this.setState({
|
|
507
|
+
...this.initialState,
|
|
508
|
+
status: "disconnected"
|
|
509
|
+
});
|
|
510
|
+
throw new Error("Could not connect to agent, bindings not found");
|
|
511
|
+
}
|
|
512
|
+
this.registerInstance();
|
|
482
513
|
}
|
|
483
514
|
async onClose() {
|
|
484
515
|
this.setState({
|
|
@@ -529,30 +560,35 @@ var Assistant = class extends Agent$1 {
|
|
|
529
560
|
});
|
|
530
561
|
}
|
|
531
562
|
/**
|
|
563
|
+
* Binding of the legacy v1 chat Durable Object class, used to migrate a
|
|
564
|
+
* user's v1 chats into facets the first time they connect. Set this on the
|
|
565
|
+
* concrete subclass to enable lazy v1 -> v2 migration; leave undefined to
|
|
566
|
+
* disable it (e.g. for greenfield deployments with no v1 data).
|
|
567
|
+
*/
|
|
568
|
+
migrationBinding;
|
|
569
|
+
/** In-flight migration, shared across concurrent connections to this DO. */
|
|
570
|
+
_migrationPromise;
|
|
571
|
+
/**
|
|
532
572
|
* Runs the lazy v1 -> v2 migration for this user. Concurrent connections to
|
|
533
573
|
* this DO share a single in-flight run. Idempotency across runs/restarts is
|
|
534
574
|
* handled by `migrateUserFromV1` deleting each chat's v1 `conversations` row,
|
|
535
575
|
* so an already-migrated chat is never re-enumerated.
|
|
536
576
|
*/
|
|
537
577
|
async ensureMigrated() {
|
|
538
|
-
if (!this.
|
|
578
|
+
if (!this.migrationBinding) return;
|
|
539
579
|
this._migrationPromise ??= this.runMigration().finally(() => {
|
|
540
580
|
this._migrationPromise = void 0;
|
|
541
581
|
});
|
|
542
582
|
await this._migrationPromise;
|
|
543
583
|
}
|
|
544
584
|
async runMigration() {
|
|
545
|
-
|
|
546
|
-
if (!legacyNamespace?.getByName) {
|
|
547
|
-
console.error("[Assistant] Migration skipped: legacy binding not found", { legacyBinding: this.legacyBinding });
|
|
548
|
-
return;
|
|
549
|
-
}
|
|
585
|
+
if (!this.migrationBinding) return;
|
|
550
586
|
try {
|
|
551
587
|
const result = await migrateUserFromV1({
|
|
552
588
|
sql: this.sql.bind(this),
|
|
553
|
-
db: this.
|
|
589
|
+
db: this.migrationBinding.db,
|
|
554
590
|
userId: this.name,
|
|
555
|
-
|
|
591
|
+
durableObjectBinding: this.migrationBinding.binding,
|
|
556
592
|
createFacet: async (chatId) => {
|
|
557
593
|
return await this.subAgent(this.agent, chatId);
|
|
558
594
|
}
|
|
@@ -596,6 +632,26 @@ var Assistant = class extends Agent$1 {
|
|
|
596
632
|
await Promise.all(scheduleIds.map((scheduleId) => this.cancelSchedule(scheduleId)));
|
|
597
633
|
await this.schedule(new Date(Date.now() + retentionMs), DELETE_CHAT_CALLBACK, durableObjectName, { idempotent: true });
|
|
598
634
|
}
|
|
635
|
+
/**
|
|
636
|
+
* Self-registers this Assistant in the global `agent_registry`. An Assistant
|
|
637
|
+
* is a top-level DO keyed directly by user id, so the DO name *is* the actor.
|
|
638
|
+
*
|
|
639
|
+
* Runs pre-auth in onStart (the DO has already persisted state by this point,
|
|
640
|
+
* so it must be tracked regardless of whether auth later succeeds).
|
|
641
|
+
* Best-effort and idempotent: no-ops on conflict, retried on the next start.
|
|
642
|
+
*/
|
|
643
|
+
async registerInstance() {
|
|
644
|
+
try {
|
|
645
|
+
await registerAgent(this.env.AGENTS_DB, {
|
|
646
|
+
agentName: this.constructor.name,
|
|
647
|
+
durableObjectName: this.name,
|
|
648
|
+
actorId: this.name,
|
|
649
|
+
createdAt: Date.now()
|
|
650
|
+
});
|
|
651
|
+
} catch (error) {
|
|
652
|
+
console.error("[Assistant] Failed to register in agent_registry", error);
|
|
653
|
+
}
|
|
654
|
+
}
|
|
599
655
|
};
|
|
600
656
|
//#endregion
|
|
601
657
|
//#region src/server/features/messages.ts
|
|
@@ -718,4 +774,9 @@ function skill(definition) {
|
|
|
718
774
|
return definition;
|
|
719
775
|
}
|
|
720
776
|
//#endregion
|
|
777
|
+
//#region src/server/index.ts
|
|
778
|
+
function getCurrentToolContext() {
|
|
779
|
+
return getCurrentAgent().agent._lastBody;
|
|
780
|
+
}
|
|
781
|
+
//#endregion
|
|
721
782
|
export { Agent, Assistant, ChatAgent, getCurrentToolContext, migrateUserFromV1, routeAgentRequest, skill, tool };
|
package/dist/v1.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { n as JwtAuthConfig, t as routeAgentRequest } from "./route-agent-request-DmwIOBJS.mjs";
|
|
2
|
-
import { LanguageModel, StreamTextOnFinishCallback, ToolSet, UIMessage, generateText, streamText } from "ai";
|
|
3
2
|
import { Agent as Agent$1, Connection, ConnectionContext } from "agents";
|
|
3
|
+
import { LanguageModel, StreamTextOnFinishCallback, ToolSet, UIMessage, generateText, streamText } from "ai";
|
|
4
4
|
import { AIChatAgent, ChatResponseResult, OnChatMessageOptions } from "@cloudflare/ai-chat";
|
|
5
5
|
|
|
6
6
|
//#region src/server/features/skills/index.d.ts
|
package/dist/v1.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { i as verifyJwt, n as createAgentTracer, r as extractTokenFromConnectRequest, t as routeAgentRequest } from "./route-agent-request-DKDvDYnR.mjs";
|
|
2
|
-
import { Output, convertToModelMessages, generateText, jsonSchema, stepCountIs, streamText, tool } from "ai";
|
|
3
2
|
import { Agent as Agent$1, callable, getCurrentAgent } from "agents";
|
|
3
|
+
import { Output, convertToModelMessages, generateText, jsonSchema, stepCountIs, streamText, tool } from "ai";
|
|
4
4
|
import { AIChatAgent } from "@cloudflare/ai-chat";
|
|
5
5
|
//#region src/server/features/skills/index.ts
|
|
6
6
|
const TOOL_NAME_ACTIVATE_SKILL = "activate_skill";
|
package/package.json
CHANGED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
-- ─── Agents registry ────────────────────────────────────────────────────────────
|
|
2
|
+
-- A directory of every top-level Durable Object in the system. DOs cannot be
|
|
3
|
+
-- enumerated via the runtime, so each top-level DO self-registers here on
|
|
4
|
+
-- creation (facets are omitted — they are enumerable via their parent's own
|
|
5
|
+
-- index). Source of truth for "what exists" and "all DOs for a given user".
|
|
6
|
+
-- Distinct from the audit/analytics event stream, which records "what happened".
|
|
7
|
+
|
|
8
|
+
CREATE TABLE IF NOT EXISTS agent_registry (
|
|
9
|
+
agent_name TEXT NOT NULL,
|
|
10
|
+
durable_object_name TEXT NOT NULL,
|
|
11
|
+
actor_id TEXT NOT NULL,
|
|
12
|
+
created_at INTEGER NOT NULL,
|
|
13
|
+
|
|
14
|
+
PRIMARY KEY (agent_name, durable_object_name)
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
CREATE INDEX IF NOT EXISTS agent_registry_actor ON agent_registry(actor_id);
|
|
18
|
+
CREATE INDEX IF NOT EXISTS agent_registry_class ON agent_registry(agent_name);
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
-- ─── Audit logging ────────────────────────────────────────────────────────────
|
|
2
|
-
|
|
3
|
-
CREATE TABLE IF NOT EXISTS audit_events (
|
|
4
|
-
id TEXT PRIMARY KEY,
|
|
5
|
-
durable_object_name TEXT NOT NULL,
|
|
6
|
-
message TEXT NOT NULL,
|
|
7
|
-
payload TEXT,
|
|
8
|
-
created_at TEXT NOT NULL
|
|
9
|
-
);
|
|
10
|
-
|
|
11
|
-
CREATE INDEX IF NOT EXISTS audit_events_do ON audit_events(durable_object_name);
|
|
12
|
-
CREATE INDEX IF NOT EXISTS audit_events_ts ON audit_events(created_at);
|
|
File without changes
|
|
File without changes
|
|
File without changes
|