@economic/agents 2.3.18 → 2.3.19
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.d.mts
CHANGED
|
@@ -114,6 +114,17 @@ declare abstract class Agent<RequestContext extends Record<string, unknown> = Re
|
|
|
114
114
|
* cold start, so registration is not allowed to block the connection.
|
|
115
115
|
*/
|
|
116
116
|
protected registerInstance(): Promise<void>;
|
|
117
|
+
/**
|
|
118
|
+
* Resolves the analytics/telemetry agent name to the entry-point agent: the
|
|
119
|
+
* top-level DO registered in the `agent` catalog table.
|
|
120
|
+
*
|
|
121
|
+
* `parentPath` is root-first and empty for top-level DOs, so:
|
|
122
|
+
* - chat agent running under an Assistant → the Assistant's class name
|
|
123
|
+
* (e.g. `EvaAssistant`), since the Assistant is the catalog entry point;
|
|
124
|
+
* - standalone chat agent → its own class name (e.g. `EvaAgent`).
|
|
125
|
+
*/
|
|
126
|
+
protected getTelemetryAgentName(): string;
|
|
127
|
+
protected getTelemetryActorId(): string;
|
|
117
128
|
}
|
|
118
129
|
//#endregion
|
|
119
130
|
//#region src/server/features/messages.d.ts
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as verifyJwt, i as extractTokenFromConnectRequest, n as createAgentTracer, r as recordFeedbackAnalytics, t as routeAgentRequest } from "./route-agent-request-sspiKVkm.mjs";
|
|
2
2
|
import { Agent as Agent$1, callable, getCurrentAgent } from "agents";
|
|
3
3
|
import { Think, skills } from "@cloudflare/think";
|
|
4
4
|
import { Output, convertToModelMessages, generateText, jsonSchema, pruneMessages, tool as tool$1 } from "ai";
|
|
@@ -195,17 +195,17 @@ var Agent = class extends Think {
|
|
|
195
195
|
experimental_telemetry: {
|
|
196
196
|
isEnabled: true,
|
|
197
197
|
tracer: createAgentTracer(this.env.AGENTS_AUDIT_LOGS, this.env.AGENTS_ANALYTICS, {
|
|
198
|
-
agentName: this.
|
|
198
|
+
agentName: this.getTelemetryAgentName(),
|
|
199
199
|
durableObjectName: this.name,
|
|
200
|
-
actorId: this.
|
|
200
|
+
actorId: this.getTelemetryActorId(),
|
|
201
201
|
clientIp: this.clientIp,
|
|
202
202
|
forwardedFor: this.forwardedFor
|
|
203
203
|
}),
|
|
204
204
|
metadata: {
|
|
205
|
-
agentName: this.
|
|
205
|
+
agentName: this.getTelemetryAgentName(),
|
|
206
206
|
version: "v2",
|
|
207
207
|
durableObjectName: this.name,
|
|
208
|
-
actorId: this.
|
|
208
|
+
actorId: this.getTelemetryActorId()
|
|
209
209
|
}
|
|
210
210
|
}
|
|
211
211
|
};
|
|
@@ -312,6 +312,21 @@ var Agent = class extends Think {
|
|
|
312
312
|
console.error("[Agent] Failed to register in agent_registry", error);
|
|
313
313
|
}
|
|
314
314
|
}
|
|
315
|
+
/**
|
|
316
|
+
* Resolves the analytics/telemetry agent name to the entry-point agent: the
|
|
317
|
+
* top-level DO registered in the `agent` catalog table.
|
|
318
|
+
*
|
|
319
|
+
* `parentPath` is root-first and empty for top-level DOs, so:
|
|
320
|
+
* - chat agent running under an Assistant → the Assistant's class name
|
|
321
|
+
* (e.g. `EvaAssistant`), since the Assistant is the catalog entry point;
|
|
322
|
+
* - standalone chat agent → its own class name (e.g. `EvaAgent`).
|
|
323
|
+
*/
|
|
324
|
+
getTelemetryAgentName() {
|
|
325
|
+
return this.parentPath[0]?.className ?? this.constructor.name;
|
|
326
|
+
}
|
|
327
|
+
getTelemetryActorId() {
|
|
328
|
+
return this.parentPath[0]?.name ?? this.getActorIdFromDurableObjectName();
|
|
329
|
+
}
|
|
315
330
|
};
|
|
316
331
|
//#endregion
|
|
317
332
|
//#region src/server/features/chats.ts
|
|
@@ -1012,7 +1027,13 @@ var ChatAgent = class extends Agent {
|
|
|
1012
1027
|
* @returns The message id and the rating.
|
|
1013
1028
|
*/
|
|
1014
1029
|
async submitMessageFeedback(messageId, rating, comment) {
|
|
1015
|
-
|
|
1030
|
+
const result = submitMessageFeedback(this.sql.bind(this), messageId, rating, comment);
|
|
1031
|
+
recordFeedbackAnalytics(this.env.AGENTS_ANALYTICS, {
|
|
1032
|
+
agentName: this.getTelemetryAgentName(),
|
|
1033
|
+
durableObjectName: this.name,
|
|
1034
|
+
actorId: this.getTelemetryActorId()
|
|
1035
|
+
}, messageId, rating);
|
|
1036
|
+
return result;
|
|
1016
1037
|
}
|
|
1017
1038
|
/**
|
|
1018
1039
|
* Returns all message feedback for the current chat.
|
|
@@ -101,6 +101,27 @@ async function verifyJwt(request, config) {
|
|
|
101
101
|
};
|
|
102
102
|
}
|
|
103
103
|
//#endregion
|
|
104
|
+
//#region src/server/features/telemetry/skills.ts
|
|
105
|
+
/**
|
|
106
|
+
* Extracts the skill names loaded by an `activate_skill` tool call.
|
|
107
|
+
*
|
|
108
|
+
* v2 `activate_skill` input is `{ skills: string[] }` — a single call can load
|
|
109
|
+
* multiple skills, so this returns every requested skill name.
|
|
110
|
+
*/
|
|
111
|
+
function extractSkillNames(toolName, input) {
|
|
112
|
+
if (toolName !== "activate_skill" || !input || typeof input !== "object") return [];
|
|
113
|
+
const { skills } = input;
|
|
114
|
+
if (!Array.isArray(skills)) return [];
|
|
115
|
+
return skills.filter((skill) => typeof skill === "string");
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Single-skill variant used where one representative skill name is sufficient
|
|
119
|
+
* (e.g. audit-log attribution and current-skill tracking).
|
|
120
|
+
*/
|
|
121
|
+
function extractSkillName(toolName, input) {
|
|
122
|
+
return extractSkillNames(toolName, input)[0];
|
|
123
|
+
}
|
|
124
|
+
//#endregion
|
|
104
125
|
//#region src/server/features/telemetry/utils.ts
|
|
105
126
|
function durationMs(duration) {
|
|
106
127
|
return duration[0] * 1e3 + duration[1] / 1e6;
|
|
@@ -169,18 +190,6 @@ function extractTools(messages) {
|
|
|
169
190
|
}
|
|
170
191
|
return tools;
|
|
171
192
|
}
|
|
172
|
-
function extractSkillName(toolName, input) {
|
|
173
|
-
if (!input || typeof input !== "object") return;
|
|
174
|
-
const record = input;
|
|
175
|
-
if (toolName === "load_context") {
|
|
176
|
-
const key = record.key;
|
|
177
|
-
return typeof key === "string" ? key : void 0;
|
|
178
|
-
}
|
|
179
|
-
if (toolName === "activate_skill") {
|
|
180
|
-
const skill = record.skill ?? record.name ?? record.key;
|
|
181
|
-
return typeof skill === "string" ? skill : void 0;
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
193
|
function pushToolCall(map, key, toolCall) {
|
|
185
194
|
const existing = map.get(key);
|
|
186
195
|
if (existing) existing.push(toolCall);
|
|
@@ -276,16 +285,35 @@ function writeAnalyticsDatapoint(analytics, dataPoint) {
|
|
|
276
285
|
console.error("[Agent] Failed to write analytics datapoint", error);
|
|
277
286
|
}
|
|
278
287
|
}
|
|
279
|
-
|
|
288
|
+
/**
|
|
289
|
+
* Writes a message-feedback rating to Analytics Engine so sentiment can be
|
|
290
|
+
* aggregated across all chats without fanning out to every chat DO.
|
|
291
|
+
*
|
|
292
|
+
* Emitted on every rating change; the dashboard takes the latest rating per
|
|
293
|
+
* `messageId` (blob4) so re-rates and clears are idempotent.
|
|
294
|
+
*/
|
|
295
|
+
function recordFeedbackAnalytics(analytics, context, messageId, rating) {
|
|
296
|
+
writeAnalyticsDatapoint(analytics, {
|
|
297
|
+
indexes: [context.actorId],
|
|
298
|
+
blobs: [
|
|
299
|
+
"feedback",
|
|
300
|
+
context.agentName,
|
|
301
|
+
context.durableObjectName,
|
|
302
|
+
messageId
|
|
303
|
+
],
|
|
304
|
+
doubles: [rating]
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
function handleAnalyticsSpan(span, analytics, context) {
|
|
280
308
|
if (span.name === "ai.streamText.doStream") {
|
|
281
309
|
const promptMessages = parseJson(stringAttribute(span, "ai.prompt.messages"));
|
|
282
310
|
const responseText = stringAttribute(span, "ai.response.text") ?? "";
|
|
283
311
|
writeAnalyticsDatapoint(analytics, {
|
|
284
|
-
indexes: [
|
|
312
|
+
indexes: [context.actorId],
|
|
285
313
|
blobs: [
|
|
286
314
|
"llm_call",
|
|
287
|
-
|
|
288
|
-
|
|
315
|
+
context.agentName,
|
|
316
|
+
context.durableObjectName,
|
|
289
317
|
stringAttribute(span, "ai.model.id") ?? "",
|
|
290
318
|
stringAttribute(span, "ai.model.provider") ?? "",
|
|
291
319
|
stringAttribute(span, "ai.response.finishReason") ?? ""
|
|
@@ -305,25 +333,29 @@ function handleAnalyticsSpan(span, analytics) {
|
|
|
305
333
|
}
|
|
306
334
|
if (span.name === "ai.toolCall") {
|
|
307
335
|
const toolName = stringAttribute(span, "ai.toolCall.name");
|
|
308
|
-
const
|
|
309
|
-
const
|
|
310
|
-
const skillName = extractSkillName(toolName, toolInput) ?? currentSkillByChat.get(durableObjectName) ?? "";
|
|
336
|
+
const argsRaw = stringAttribute(span, "ai.toolCall.args");
|
|
337
|
+
const toolInput = parseJson(argsRaw);
|
|
311
338
|
const success = span.status.code === 0;
|
|
312
|
-
|
|
313
|
-
|
|
339
|
+
const duration = durationMs(span.duration);
|
|
340
|
+
const argsSize = argsRaw?.length ?? 0;
|
|
341
|
+
const resultSize = stringAttribute(span, "ai.toolCall.result")?.length ?? 0;
|
|
342
|
+
const activatedSkills = extractSkillNames(toolName, toolInput);
|
|
343
|
+
const skillNames = activatedSkills.length ? activatedSkills : [currentSkillByChat.get(context.durableObjectName) ?? ""];
|
|
344
|
+
for (const skillName of skillNames) writeAnalyticsDatapoint(analytics, {
|
|
345
|
+
indexes: [context.actorId],
|
|
314
346
|
blobs: [
|
|
315
347
|
"tool_call",
|
|
316
|
-
|
|
317
|
-
durableObjectName,
|
|
348
|
+
context.agentName,
|
|
349
|
+
context.durableObjectName,
|
|
318
350
|
toolName ?? "",
|
|
319
351
|
skillName,
|
|
320
352
|
success ? "success" : "error"
|
|
321
353
|
],
|
|
322
354
|
doubles: [
|
|
323
|
-
|
|
355
|
+
duration,
|
|
324
356
|
success ? 1 : 0,
|
|
325
|
-
|
|
326
|
-
|
|
357
|
+
argsSize,
|
|
358
|
+
resultSize,
|
|
327
359
|
0,
|
|
328
360
|
0,
|
|
329
361
|
0,
|
|
@@ -349,11 +381,11 @@ var AgentSpanExporter = class {
|
|
|
349
381
|
for (const span of spans) if (span.name === "ai.streamText.doStream") {
|
|
350
382
|
rememberDoStream(span, this.context.durableObjectName);
|
|
351
383
|
attachToolCallsToChat(span, this.context.durableObjectName);
|
|
352
|
-
handleAnalyticsSpan(span, this.analytics);
|
|
384
|
+
handleAnalyticsSpan(span, this.analytics, this.context);
|
|
353
385
|
} else if (span.name === "ai.streamText") await handleAuditSpan(span, this.auditLogs, this.context);
|
|
354
386
|
else if (span.name === "ai.toolCall") {
|
|
355
387
|
rememberToolCall(span);
|
|
356
|
-
handleAnalyticsSpan(span, this.analytics);
|
|
388
|
+
handleAnalyticsSpan(span, this.analytics, this.context);
|
|
357
389
|
}
|
|
358
390
|
resultCallback({ code: 0 });
|
|
359
391
|
} catch (error) {
|
|
@@ -383,4 +415,4 @@ async function routeAgentRequest$1(request, env, options) {
|
|
|
383
415
|
return response;
|
|
384
416
|
}
|
|
385
417
|
//#endregion
|
|
386
|
-
export { verifyJwt as i, createAgentTracer as n,
|
|
418
|
+
export { verifyJwt as a, extractTokenFromConnectRequest as i, createAgentTracer as n, recordFeedbackAnalytics as r, routeAgentRequest$1 as t };
|
package/dist/v1.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as verifyJwt, i as extractTokenFromConnectRequest, n as createAgentTracer, t as routeAgentRequest } from "./route-agent-request-sspiKVkm.mjs";
|
|
2
2
|
import { Agent as Agent$1, callable, getCurrentAgent } from "agents";
|
|
3
3
|
import { Output, convertToModelMessages, generateText, jsonSchema, stepCountIs, streamText, tool } from "ai";
|
|
4
4
|
import { AIChatAgent } from "@cloudflare/ai-chat";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@economic/agents",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.19",
|
|
4
4
|
"description": "A starter for creating a TypeScript package.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"files": [
|
|
@@ -26,9 +26,9 @@
|
|
|
26
26
|
"@ai-sdk/anthropic": "^3.0.77",
|
|
27
27
|
"@ai-sdk/google": "^3.0.73",
|
|
28
28
|
"@cloudflare/ai-chat": "^0.8.5",
|
|
29
|
-
"@cloudflare/think": "
|
|
29
|
+
"@cloudflare/think": ">=0.9.0",
|
|
30
30
|
"@opentelemetry/sdk-trace-base": "^2.8.0",
|
|
31
|
-
"agents": "
|
|
31
|
+
"agents": ">=0.16.0 <1.0.0",
|
|
32
32
|
"ai": "^6.0.197",
|
|
33
33
|
"jose": "^6.2.3",
|
|
34
34
|
"nanoid": "^5.1.11"
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
},
|
|
47
47
|
"peerDependencies": {
|
|
48
48
|
"@cloudflare/think": ">=0.9.0",
|
|
49
|
-
"@cloudflare/vite-plugin": "
|
|
49
|
+
"@cloudflare/vite-plugin": "^1.42.0",
|
|
50
50
|
"@cloudflare/worker-bundler": ">=0.2.1",
|
|
51
51
|
"agents": ">=0.16.0 <1.0.0",
|
|
52
52
|
"vite": ">=8.0.0"
|