@economic/agents 2.1.1 → 2.1.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/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { n as extractTokenFromConnectRequest, r as verifyJwt, t as createAgentTracer } from "./telemetry-BKgBMVF0.mjs";
1
+ import { n as extractTokenFromConnectRequest, r as verifyJwt, t as createAgentTracer } from "./telemetry-BDxmv_R7.mjs";
2
2
  import { Output, convertToModelMessages, generateText, jsonSchema, stepCountIs, streamText, tool } from "ai";
3
3
  import { Agent as Agent$1, callable, getCurrentAgent, routeAgentRequest as routeAgentRequest$1 } from "agents";
4
4
  import { AIChatAgent } from "@cloudflare/ai-chat";
@@ -359,16 +359,16 @@ var Agent = class extends Agent$1 {
359
359
  isEnabled: true,
360
360
  tracer: createAgentTracer(this.env.AGENTS_AUDIT_LOGS, this.env.AGENTS_ANALYTICS, {
361
361
  agentName: this.constructor.name,
362
- chatId: this.name,
363
- userId: this.getUserId(),
362
+ durableObjectName: this.name,
363
+ actorId: this.getUserId(),
364
364
  ...this.clientIp ? { clientIp: this.clientIp } : {},
365
365
  ...this.forwardedFor ? { forwardedFor: this.forwardedFor } : {}
366
366
  }),
367
367
  metadata: {
368
368
  agentName: this.constructor.name,
369
369
  version: "v1",
370
- chatId: this.name,
371
- userId: this.getUserId(),
370
+ durableObjectName: this.name,
371
+ actorId: this.getUserId(),
372
372
  ...this.clientIp ? { clientIp: this.clientIp } : {},
373
373
  ...this.forwardedFor ? { forwardedFor: this.forwardedFor } : {},
374
374
  ...config.experimental_telemetry?.metadata
@@ -769,16 +769,16 @@ var ChatAgent = class extends AIChatAgent {
769
769
  isEnabled: true,
770
770
  tracer: createAgentTracer(this.env.AGENTS_AUDIT_LOGS, this.env.AGENTS_ANALYTICS, {
771
771
  agentName: this.constructor.name,
772
- chatId: this.name,
773
- userId: this.getUserId(),
772
+ durableObjectName: this.name,
773
+ actorId: this.getUserId(),
774
774
  ...this.clientIp ? { clientIp: this.clientIp } : {},
775
775
  ...this.forwardedFor ? { forwardedFor: this.forwardedFor } : {}
776
776
  }),
777
777
  metadata: {
778
778
  agentName: this.constructor.name,
779
779
  version: "v1",
780
- chatId: this.name,
781
- userId: this.getUserId(),
780
+ durableObjectName: this.name,
781
+ actorId: this.getUserId(),
782
782
  ...this.clientIp ? { clientIp: this.clientIp } : {},
783
783
  ...this.forwardedFor ? { forwardedFor: this.forwardedFor } : {},
784
784
  ...config.experimental_telemetry?.metadata
@@ -125,12 +125,12 @@ function parseJson(value) {
125
125
  function safePathSegment(value, fallback) {
126
126
  return (value || fallback).replace(/[^a-zA-Z0-9._-]/g, "_");
127
127
  }
128
- function createAuditLogKey(agentName, chatId) {
128
+ function createAuditLogKey(agentName, durableObjectName) {
129
129
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replaceAll(":", "-");
130
130
  const id = crypto.randomUUID().slice(0, 8);
131
131
  return [
132
132
  safePathSegment(agentName, "unknown-agent"),
133
- safePathSegment(chatId, "unknown-chat"),
133
+ safePathSegment(durableObjectName, "unknown-chat"),
134
134
  `${timestamp}-${id}.json`
135
135
  ].join("/");
136
136
  }
@@ -208,34 +208,34 @@ function rememberToolCall(span) {
208
208
  if (parentSpanId) pushToolCall(toolCallsByParentSpan, parentSpanId, toolCall);
209
209
  pendingToolCalls.push(toolCall);
210
210
  }
211
- function attachToolCallsToChat(span, chatId) {
211
+ function attachToolCallsToChat(span, durableObjectName) {
212
212
  const spanId = span.spanContext().spanId;
213
213
  const toolCalls = toolCallsByParentSpan.get(spanId) ?? pendingToolCalls.splice(0);
214
214
  if (!toolCalls.length) return;
215
215
  toolCallsByParentSpan.delete(spanId);
216
- const currentSkill = currentSkillByChat.get(chatId);
216
+ const currentSkill = currentSkillByChat.get(durableObjectName);
217
217
  const attributedToolCalls = toolCalls.map((toolCall) => {
218
218
  const skillName = toolCall.skillName ?? currentSkill;
219
- if (toolCall.skillName) currentSkillByChat.set(chatId, toolCall.skillName);
219
+ if (toolCall.skillName) currentSkillByChat.set(durableObjectName, toolCall.skillName);
220
220
  return {
221
221
  ...toolCall,
222
222
  ...skillName ? { skillName } : {}
223
223
  };
224
224
  });
225
- toolCallsByChat.set(chatId, [...toolCallsByChat.get(chatId) ?? [], ...attributedToolCalls]);
225
+ toolCallsByChat.set(durableObjectName, [...toolCallsByChat.get(durableObjectName) ?? [], ...attributedToolCalls]);
226
226
  }
227
227
  function buildAuditLog(span, context) {
228
- const lastDoStream = lastDoStreamByChat.get(context.chatId);
229
- lastDoStreamByChat.delete(context.chatId);
228
+ const lastDoStream = lastDoStreamByChat.get(context.durableObjectName);
229
+ lastDoStreamByChat.delete(context.durableObjectName);
230
230
  const promptMessages = parseJson(stringAttribute(lastDoStream ?? span, "ai.prompt.messages"));
231
231
  const fallbackPrompt = parseJson(stringAttribute(span, "ai.prompt"));
232
232
  const inputMessages = promptMessages ?? fallbackPrompt?.messages ?? [];
233
- const spanToolCalls = toolCallsByChat.get(context.chatId) ?? [];
234
- toolCallsByChat.delete(context.chatId);
233
+ const spanToolCalls = toolCallsByChat.get(context.durableObjectName) ?? [];
234
+ toolCallsByChat.delete(context.durableObjectName);
235
235
  return {
236
- id: createAuditLogKey(context.agentName, context.chatId),
236
+ id: createAuditLogKey(context.agentName, context.durableObjectName),
237
237
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
238
- chatId: context.chatId,
238
+ durableObjectName: context.durableObjectName,
239
239
  agent: {
240
240
  name: context.agentName,
241
241
  llm: {
@@ -244,7 +244,7 @@ function buildAuditLog(span, context) {
244
244
  }
245
245
  },
246
246
  actor: {
247
- userId: context.userId,
247
+ id: context.actorId,
248
248
  ip: {
249
249
  client: context.clientIp ?? context.forwardedFor?.split(",").map((ip) => ip.trim()).filter(Boolean)[0],
250
250
  forwardedFor: context.forwardedFor?.split(",").map((ip) => ip.trim()).filter(Boolean) ?? []
@@ -256,8 +256,8 @@ function buildAuditLog(span, context) {
256
256
  tools: [...extractTools(inputMessages), ...spanToolCalls]
257
257
  };
258
258
  }
259
- function rememberDoStream(span, chatId) {
260
- lastDoStreamByChat.set(chatId, span);
259
+ function rememberDoStream(span, durableObjectName) {
260
+ lastDoStreamByChat.set(durableObjectName, span);
261
261
  }
262
262
  async function handleAuditSpan(span, auditLogs, context) {
263
263
  const auditLog = buildAuditLog(span, context);
@@ -280,11 +280,11 @@ function handleAnalyticsSpan(span, analytics) {
280
280
  const promptMessages = parseJson(stringAttribute(span, "ai.prompt.messages"));
281
281
  const responseText = stringAttribute(span, "ai.response.text") ?? "";
282
282
  writeAnalyticsDatapoint(analytics, {
283
- indexes: [stringAttribute(span, "ai.telemetry.metadata.userId") ?? ""],
283
+ indexes: [stringAttribute(span, "ai.telemetry.metadata.actorId") ?? ""],
284
284
  blobs: [
285
285
  "llm_call",
286
286
  stringAttribute(span, "ai.telemetry.metadata.agentName") ?? "",
287
- stringAttribute(span, "ai.telemetry.metadata.chatId") ?? "",
287
+ stringAttribute(span, "ai.telemetry.metadata.durableObjectName") ?? "",
288
288
  stringAttribute(span, "ai.model.id") ?? "",
289
289
  stringAttribute(span, "ai.model.provider") ?? "",
290
290
  stringAttribute(span, "ai.response.finishReason") ?? ""
@@ -305,15 +305,15 @@ function handleAnalyticsSpan(span, analytics) {
305
305
  if (span.name === "ai.toolCall") {
306
306
  const toolName = stringAttribute(span, "ai.toolCall.name");
307
307
  const toolInput = parseJson(stringAttribute(span, "ai.toolCall.args"));
308
- const chatId = stringAttribute(span, "ai.telemetry.metadata.chatId") ?? "";
309
- const skillName = extractSkillName(toolName, toolInput) ?? currentSkillByChat.get(chatId) ?? "";
308
+ const durableObjectName = stringAttribute(span, "ai.telemetry.metadata.durableObjectName") ?? "";
309
+ const skillName = extractSkillName(toolName, toolInput) ?? currentSkillByChat.get(durableObjectName) ?? "";
310
310
  const success = span.status.code === 0;
311
311
  writeAnalyticsDatapoint(analytics, {
312
- indexes: [stringAttribute(span, "ai.telemetry.metadata.userId") ?? ""],
312
+ indexes: [stringAttribute(span, "ai.telemetry.metadata.actorId") ?? ""],
313
313
  blobs: [
314
314
  "tool_call",
315
315
  stringAttribute(span, "ai.telemetry.metadata.agentName") ?? "",
316
- chatId,
316
+ durableObjectName,
317
317
  toolName ?? "",
318
318
  skillName,
319
319
  success ? "success" : "error"
@@ -346,8 +346,8 @@ var AgentSpanExporter = class {
346
346
  (async () => {
347
347
  try {
348
348
  for (const span of spans) if (span.name === "ai.streamText.doStream") {
349
- rememberDoStream(span, this.context.chatId);
350
- attachToolCallsToChat(span, this.context.chatId);
349
+ rememberDoStream(span, this.context.durableObjectName);
350
+ attachToolCallsToChat(span, this.context.durableObjectName);
351
351
  handleAnalyticsSpan(span, this.analytics);
352
352
  } else if (span.name === "ai.streamText") await handleAuditSpan(span, this.auditLogs, this.context);
353
353
  else if (span.name === "ai.toolCall") {
package/dist/v2.d.mts CHANGED
@@ -53,7 +53,7 @@ declare abstract class Agent<RequestContext extends Record<string, unknown> = Re
53
53
  /**
54
54
  * Returns the user ID from the durable object name.
55
55
  */
56
- protected getUserIdFromDurableObjectName(): string;
56
+ protected getActorIdFromDurableObjectName(): string;
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;
@@ -155,7 +155,7 @@ declare abstract class Assistant extends Agent$1<Cloudflare.Env, AgentConnection
155
155
  protected abstract fastModel: LanguageModel;
156
156
  onStart(): void;
157
157
  onClose(): Promise<void>;
158
- onConnect(): Promise<void>;
158
+ onConnect(connection: Connection, ctx: ConnectionContext): Promise<void>;
159
159
  createChat(): Promise<string>;
160
160
  deleteChat(id: string): Promise<void>;
161
161
  getChats(): Promise<Chat[]>;
package/dist/v2.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { n as extractTokenFromConnectRequest, r as verifyJwt, t as createAgentTracer } from "./telemetry-BKgBMVF0.mjs";
1
+ import { n as extractTokenFromConnectRequest, r as verifyJwt, t as createAgentTracer } from "./telemetry-BDxmv_R7.mjs";
2
2
  import { Output, convertToModelMessages, generateText, jsonSchema, pruneMessages, tool as tool$1 } from "ai";
3
3
  import { Agent as Agent$1, callable, getCurrentAgent } from "agents";
4
4
  import { Think } from "@cloudflare/think";
@@ -56,8 +56,9 @@ var Agent = class extends Think {
56
56
  /**
57
57
  * Returns the user ID from the durable object name.
58
58
  */
59
- getUserIdFromDurableObjectName() {
60
- return this.name.split(":")[0];
59
+ getActorIdFromDurableObjectName() {
60
+ if (this.name.includes(":")) return this.name.split(":")[0];
61
+ return "system";
61
62
  }
62
63
  getParentAgent() {
63
64
  if (this.parentPath.length) {
@@ -94,10 +95,6 @@ var Agent = class extends Think {
94
95
  console.error("[Agent] Connection rejected: no AGENTS_AUDIT_LOGS bound. Audit logs are required.");
95
96
  }
96
97
  if (!this.env.AGENTS_ANALYTICS) console.warn("[Agent] No AGENTS_ANALYTICS bound. Analytics will not be collected.");
97
- if (!this.getUserIdFromDurableObjectName()) {
98
- hasCorrectBindings = false;
99
- console.error("[Agent] Connection rejected: name must be in the format userId:uniqueChatId");
100
- }
101
98
  if (!hasCorrectBindings) {
102
99
  this.setState({
103
100
  ...this.initialState,
@@ -185,16 +182,16 @@ var Agent = class extends Think {
185
182
  isEnabled: true,
186
183
  tracer: createAgentTracer(this.env.AGENTS_AUDIT_LOGS, this.env.AGENTS_ANALYTICS, {
187
184
  agentName: this.constructor.name,
188
- chatId: this.name,
189
- userId: this.getUserIdFromDurableObjectName(),
185
+ durableObjectName: this.name,
186
+ actorId: this.getActorIdFromDurableObjectName(),
190
187
  clientIp: this.clientIp,
191
188
  forwardedFor: this.forwardedFor
192
189
  }),
193
190
  metadata: {
194
191
  agentName: this.constructor.name,
195
192
  version: "v2",
196
- chatId: this.name,
197
- userId: this.getUserIdFromDurableObjectName()
193
+ durableObjectName: this.name,
194
+ actorId: this.getActorIdFromDurableObjectName()
198
195
  }
199
196
  }
200
197
  };
@@ -379,7 +376,7 @@ var Assistant = class extends Agent$1 {
379
376
  };
380
377
  onStart() {
381
378
  this.setState({
382
- type: "assistant",
379
+ ...this.initialState,
383
380
  status: "connecting",
384
381
  subAgentName: this.agent.name
385
382
  });
@@ -387,14 +384,47 @@ var Assistant = class extends Agent$1 {
387
384
  }
388
385
  async onClose() {
389
386
  this.setState({
390
- type: "assistant",
387
+ ...this.initialState,
391
388
  status: "disconnected",
392
389
  subAgentName: this.agent.name
393
390
  });
394
391
  }
395
- async onConnect() {
392
+ async onConnect(connection, ctx) {
393
+ const getJwtAuthConfig = this.agent.getJwtAuthConfig;
394
+ if (getJwtAuthConfig) {
395
+ const config = getJwtAuthConfig(this.env);
396
+ if (config) {
397
+ let result;
398
+ try {
399
+ result = await verifyJwt(ctx.request, config);
400
+ } catch (error) {
401
+ this.setState({
402
+ ...this.initialState,
403
+ status: "unauthorized",
404
+ subAgentName: this.agent.name
405
+ });
406
+ console.error(`[Assistant] JWT verification error - ${error}`);
407
+ connection.close(4001, "Unauthorized");
408
+ return;
409
+ }
410
+ if (!result.success) {
411
+ this.setState({
412
+ ...this.initialState,
413
+ status: "unauthorized",
414
+ subAgentName: this.agent.name
415
+ });
416
+ console.error(`[Assistant] JWT verification error - ${result.message}`);
417
+ connection.close(result.status === 401 ? 4001 : 4003, result.message);
418
+ return;
419
+ }
420
+ connection.setState({
421
+ authenticated: true,
422
+ claims: result.claims
423
+ });
424
+ }
425
+ }
396
426
  this.setState({
397
- type: "assistant",
427
+ ...this.initialState,
398
428
  status: "connected",
399
429
  subAgentName: this.agent.name
400
430
  });
@@ -443,12 +473,11 @@ function ensureRatingsTableExists(sql) {
443
473
  try {
444
474
  sql`CREATE TABLE IF NOT EXISTS assistant_messages_ratings (
445
475
  message_id TEXT NOT NULL,
446
- durable_object_name TEXT NOT NULL,
447
476
  rating INTEGER,
448
477
  comment TEXT,
449
- created_at TEXT NOT NULL,
450
- updated_at TEXT NOT NULL,
451
- PRIMARY KEY (message_id, durable_object_name)
478
+ created_at INTEGER NOT NULL,
479
+ updated_at INTEGER NOT NULL,
480
+ PRIMARY KEY (message_id)
452
481
  )`;
453
482
  } catch (error) {
454
483
  console.error("[Agent] Failed to create ratings table", error);
@@ -458,15 +487,14 @@ function ensureRatingsTableExists(sql) {
458
487
  * Rates a message.
459
488
  * @param sql - The SQL function to use to execute the query.
460
489
  * @param messageId - The ID of the message to rate.
461
- * @param durable_object_name - The name of the Durable Object to rate the message for.
462
490
  * @param rating - The rating to give the message.
463
491
  * @param now - The date and time to use for the created_at and updated_at columns.
464
492
  */
465
- function rateMessage(sql, messageId, durable_object_name, rating, comment, now = /* @__PURE__ */ new Date()) {
493
+ function rateMessage(sql, messageId, rating, comment, now = /* @__PURE__ */ new Date()) {
466
494
  try {
467
- sql`INSERT INTO assistant_messages_ratings (message_id, durable_object_name, rating, comment, created_at, updated_at)
468
- VALUES (${messageId}, ${durable_object_name}, ${rating}, ${comment ?? null}, ${now.toISOString()}, ${now.toISOString()})
469
- ON CONFLICT (message_id, durable_object_name) DO UPDATE SET
495
+ sql`INSERT INTO assistant_messages_ratings (message_id, rating, comment, created_at, updated_at)
496
+ VALUES (${messageId}, ${rating}, ${comment ?? null}, ${now.getTime()}, ${now.getTime()})
497
+ ON CONFLICT (message_id) DO UPDATE SET
470
498
  rating = excluded.rating,
471
499
  comment = excluded.comment,
472
500
  updated_at = excluded.updated_at`;
@@ -477,12 +505,11 @@ function rateMessage(sql, messageId, durable_object_name, rating, comment, now =
477
505
  /**
478
506
  * Gets the ratings for a message.
479
507
  * @param sql - The SQL function to use to execute the query.
480
- * @param durable_object_name - The name of the Durable Object to get the ratings for.
481
508
  * @returns A record of message IDs and their ratings.
482
509
  */
483
- function getMessageRatings(sql, durable_object_name) {
510
+ function getMessageRatings(sql) {
484
511
  try {
485
- const ratings = sql`SELECT message_id, rating, comment FROM assistant_messages_ratings WHERE durable_object_name = ${durable_object_name}`;
512
+ const ratings = sql`SELECT message_id, rating, comment FROM assistant_messages_ratings`;
486
513
  return Object.fromEntries(ratings.map((row) => [row.message_id, {
487
514
  rating: row.rating,
488
515
  comment: row.comment
@@ -516,14 +543,14 @@ var ChatAgent = class extends Agent {
516
543
  * @returns The message id and the rating.
517
544
  */
518
545
  @callable({ description: "Rate a message by its id" }) async rateMessage(messageId, rating, comment) {
519
- return rateMessage(this.sql.bind(this), messageId, this.name, rating, comment);
546
+ return rateMessage(this.sql.bind(this), messageId, rating, comment);
520
547
  }
521
548
  /**
522
549
  * Returns all message ratings for the current chat.
523
550
  * @returns All message ratings for the current chat.
524
551
  */
525
552
  @callable({ description: "Returns all message ratings for the current chat" }) async getMessageRatings() {
526
- return getMessageRatings(this.sql.bind(this), this.name);
553
+ return getMessageRatings(this.sql.bind(this));
527
554
  }
528
555
  };
529
556
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@economic/agents",
3
- "version": "2.1.1",
3
+ "version": "2.1.3",
4
4
  "description": "A starter for creating a TypeScript package.",
5
5
  "license": "MIT",
6
6
  "bin": {