@economic/agents 2.1.0 → 2.1.2
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 +9 -9
- package/dist/{telemetry-a-1XBTxr.mjs → telemetry-BDxmv_R7.mjs} +28 -28
- package/dist/v2.d.mts +13 -13
- package/dist/v2.mjs +100 -70
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as extractTokenFromConnectRequest, r as verifyJwt, t as createAgentTracer } from "./telemetry-
|
|
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
|
-
|
|
363
|
-
|
|
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
|
-
|
|
371
|
-
|
|
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
|
-
|
|
773
|
-
|
|
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
|
-
|
|
781
|
-
|
|
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,
|
|
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(
|
|
133
|
+
safePathSegment(durableObjectName, "unknown-chat"),
|
|
134
134
|
`${timestamp}-${id}.json`
|
|
135
135
|
].join("/");
|
|
136
136
|
}
|
|
@@ -186,15 +186,15 @@ function pushToolCall(map, key, toolCall) {
|
|
|
186
186
|
else map.set(key, [toolCall]);
|
|
187
187
|
}
|
|
188
188
|
/**
|
|
189
|
-
* Stores the last ai.streamText.doStream span per
|
|
190
|
-
* Its ai.prompt.messages contains the full
|
|
189
|
+
* Stores the last ai.streamText.doStream span per chat.
|
|
190
|
+
* Its ai.prompt.messages contains the full chat history including all
|
|
191
191
|
* intermediate tool_use + tool_result turns from the agentic loop.
|
|
192
192
|
*/
|
|
193
|
-
const
|
|
193
|
+
const lastDoStreamByChat = /* @__PURE__ */ new Map();
|
|
194
194
|
const toolCallsByParentSpan = /* @__PURE__ */ new Map();
|
|
195
|
-
const
|
|
195
|
+
const toolCallsByChat = /* @__PURE__ */ new Map();
|
|
196
196
|
const pendingToolCalls = [];
|
|
197
|
-
const
|
|
197
|
+
const currentSkillByChat = /* @__PURE__ */ new Map();
|
|
198
198
|
function rememberToolCall(span) {
|
|
199
199
|
const parentSpanId = span.parentSpanContext?.spanId;
|
|
200
200
|
const toolName = stringAttribute(span, "ai.toolCall.name");
|
|
@@ -208,34 +208,34 @@ function rememberToolCall(span) {
|
|
|
208
208
|
if (parentSpanId) pushToolCall(toolCallsByParentSpan, parentSpanId, toolCall);
|
|
209
209
|
pendingToolCalls.push(toolCall);
|
|
210
210
|
}
|
|
211
|
-
function
|
|
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 =
|
|
216
|
+
const currentSkill = currentSkillByChat.get(durableObjectName);
|
|
217
217
|
const attributedToolCalls = toolCalls.map((toolCall) => {
|
|
218
218
|
const skillName = toolCall.skillName ?? currentSkill;
|
|
219
|
-
if (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
|
-
|
|
225
|
+
toolCallsByChat.set(durableObjectName, [...toolCallsByChat.get(durableObjectName) ?? [], ...attributedToolCalls]);
|
|
226
226
|
}
|
|
227
227
|
function buildAuditLog(span, context) {
|
|
228
|
-
const lastDoStream =
|
|
229
|
-
|
|
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 =
|
|
234
|
-
|
|
233
|
+
const spanToolCalls = toolCallsByChat.get(context.durableObjectName) ?? [];
|
|
234
|
+
toolCallsByChat.delete(context.durableObjectName);
|
|
235
235
|
return {
|
|
236
|
-
id: createAuditLogKey(context.agentName, context.
|
|
236
|
+
id: createAuditLogKey(context.agentName, context.durableObjectName),
|
|
237
237
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
238
|
-
|
|
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
|
-
|
|
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,
|
|
260
|
-
|
|
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.
|
|
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.
|
|
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
|
|
309
|
-
const skillName = extractSkillName(toolName, toolInput) ??
|
|
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.
|
|
312
|
+
indexes: [stringAttribute(span, "ai.telemetry.metadata.actorId") ?? ""],
|
|
313
313
|
blobs: [
|
|
314
314
|
"tool_call",
|
|
315
315
|
stringAttribute(span, "ai.telemetry.metadata.agentName") ?? "",
|
|
316
|
-
|
|
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.
|
|
350
|
-
|
|
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
|
|
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;
|
|
@@ -132,21 +132,21 @@ declare abstract class ChatAgent<RequestContext extends Record<string, unknown>
|
|
|
132
132
|
*/
|
|
133
133
|
rateMessage(messageId: string, rating: number, comment?: string): Promise<void>;
|
|
134
134
|
/**
|
|
135
|
-
* Returns all message ratings for the current
|
|
136
|
-
* @returns All message ratings for the current
|
|
135
|
+
* Returns all message ratings for the current chat.
|
|
136
|
+
* @returns All message ratings for the current chat.
|
|
137
137
|
*/
|
|
138
138
|
getMessageRatings(): Promise<any>;
|
|
139
139
|
}
|
|
140
140
|
//#endregion
|
|
141
|
-
//#region src/server/v2/features/
|
|
142
|
-
type
|
|
141
|
+
//#region src/server/v2/features/chats.d.ts
|
|
142
|
+
type Chat = {
|
|
143
143
|
durable_object_name: string;
|
|
144
144
|
title?: string;
|
|
145
145
|
summary?: string;
|
|
146
146
|
created_at: number;
|
|
147
147
|
updated_at: number;
|
|
148
148
|
};
|
|
149
|
-
declare const
|
|
149
|
+
declare const DELETE_CHAT_CALLBACK: "deleteChatCallback";
|
|
150
150
|
//#endregion
|
|
151
151
|
//#region src/server/v2/agents/Assistant.d.ts
|
|
152
152
|
declare abstract class Assistant extends Agent$1<Cloudflare.Env, AgentConnectionState> {
|
|
@@ -155,13 +155,13 @@ 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>;
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
private [
|
|
164
|
-
private
|
|
158
|
+
onConnect(connection: Connection, ctx: ConnectionContext): Promise<void>;
|
|
159
|
+
createChat(): Promise<string>;
|
|
160
|
+
deleteChat(id: string): Promise<void>;
|
|
161
|
+
getChats(): Promise<Chat[]>;
|
|
162
|
+
recordChatTurn(durableObjectName: string, messages: UIMessage[]): Promise<void>;
|
|
163
|
+
private [DELETE_CHAT_CALLBACK];
|
|
164
|
+
private scheduleChatForAutoDeletion;
|
|
165
165
|
}
|
|
166
166
|
//#endregion
|
|
167
167
|
export { Agent, type AgentConnectionState, type AgentConnectionStatus, type AgentConnectionType, type AgentEnv, Assistant, ChatAgent, type Skill, type Tool, type ToolContext, type ToolSet, getCurrentToolContext, skill, tool };
|
package/dist/v2.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as extractTokenFromConnectRequest, r as verifyJwt, t as createAgentTracer } from "./telemetry-
|
|
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
|
-
|
|
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
|
-
|
|
189
|
-
|
|
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
|
-
|
|
197
|
-
|
|
193
|
+
durableObjectName: this.name,
|
|
194
|
+
actorId: this.getActorIdFromDurableObjectName()
|
|
198
195
|
}
|
|
199
196
|
}
|
|
200
197
|
};
|
|
@@ -277,14 +274,14 @@ var Agent = class extends Think {
|
|
|
277
274
|
_userContext;
|
|
278
275
|
};
|
|
279
276
|
//#endregion
|
|
280
|
-
//#region src/server/v2/features/
|
|
277
|
+
//#region src/server/v2/features/chats.ts
|
|
281
278
|
/**
|
|
282
|
-
* Ensures that the
|
|
279
|
+
* Ensures that the chats table exists.
|
|
283
280
|
* @param sql - The SQL function to use to execute the query.
|
|
284
281
|
*/
|
|
285
|
-
function
|
|
282
|
+
function ensureChatsTableExists(sql) {
|
|
286
283
|
try {
|
|
287
|
-
sql`CREATE TABLE IF NOT EXISTS
|
|
284
|
+
sql`CREATE TABLE IF NOT EXISTS chats (
|
|
288
285
|
durable_object_name TEXT NOT NULL,
|
|
289
286
|
title TEXT,
|
|
290
287
|
summary TEXT,
|
|
@@ -293,80 +290,80 @@ function ensureConversationsTableExists(sql) {
|
|
|
293
290
|
PRIMARY KEY (durable_object_name)
|
|
294
291
|
)`;
|
|
295
292
|
} catch (error) {
|
|
296
|
-
console.error("[Agent] Failed to create
|
|
293
|
+
console.error("[Agent] Failed to create chats table", error);
|
|
297
294
|
}
|
|
298
295
|
}
|
|
299
|
-
function
|
|
300
|
-
sql`INSERT INTO
|
|
296
|
+
function registerChat(sql, durableObjectName, dateTime) {
|
|
297
|
+
sql`INSERT INTO chats (durable_object_name, created_at, updated_at)
|
|
301
298
|
VALUES (${durableObjectName}, ${dateTime}, ${dateTime})`;
|
|
302
299
|
}
|
|
303
|
-
function
|
|
304
|
-
sql`DELETE FROM
|
|
300
|
+
function deleteChat(sql, durableObjectName) {
|
|
301
|
+
sql`DELETE FROM chats WHERE durable_object_name = ${durableObjectName}`;
|
|
305
302
|
}
|
|
306
|
-
function
|
|
307
|
-
return sql`SELECT * FROM
|
|
303
|
+
function getChat(sql, durableObjectName) {
|
|
304
|
+
return sql`SELECT * FROM chats WHERE durable_object_name = ${durableObjectName}`[0] ?? null;
|
|
308
305
|
}
|
|
309
|
-
async function
|
|
310
|
-
return sql`SELECT * FROM
|
|
306
|
+
async function getChats(sql) {
|
|
307
|
+
return sql`SELECT * FROM chats ORDER BY updated_at DESC`;
|
|
311
308
|
}
|
|
312
|
-
function
|
|
313
|
-
return schedules.filter((schedule) => schedule.callback ===
|
|
309
|
+
function getDeleteChatScheduleIds(schedules) {
|
|
310
|
+
return schedules.filter((schedule) => schedule.callback === DELETE_CHAT_CALLBACK).map((schedule) => schedule.id);
|
|
314
311
|
}
|
|
315
312
|
/**
|
|
316
313
|
* Number of recent messages passed to `generateSummary` for rolling
|
|
317
314
|
* summarization. Keeping this bounded prevents the prompt growing
|
|
318
|
-
* unboundedly regardless of
|
|
315
|
+
* unboundedly regardless of chat length.
|
|
319
316
|
*/
|
|
320
|
-
const
|
|
321
|
-
async function
|
|
322
|
-
const
|
|
323
|
-
if (!(!
|
|
317
|
+
const CHAT_RECENT_MESSAGES_COUNT = 20;
|
|
318
|
+
async function summariseChatWithAI(sql, durableObjectName, messages, model) {
|
|
319
|
+
const chat = getChat(sql, durableObjectName);
|
|
320
|
+
if (!(!chat || !chat.title || messages.length % CHAT_RECENT_MESSAGES_COUNT === 0)) return;
|
|
324
321
|
let systemPrompt = `
|
|
325
|
-
You are a helpful assistant that summarises
|
|
326
|
-
You will be given a list of messages and you need to generate a title and summary for the
|
|
327
|
-
The title should be a short title for the
|
|
328
|
-
The summary should be a short 1-2 sentence summary of the
|
|
329
|
-
The summary should reflect the direction of the
|
|
330
|
-
if (
|
|
322
|
+
You are a helpful assistant that summarises chats.
|
|
323
|
+
You will be given a list of messages and you need to generate a title and summary for the chat.
|
|
324
|
+
The title should be a short title for the chat, max 8-10 words.
|
|
325
|
+
The summary should be a short 1-2 sentence summary of the chat.
|
|
326
|
+
The summary should reflect the direction of the chat.`;
|
|
327
|
+
if (chat) systemPrompt += `${systemPrompt}\n\nThe previous summary: ${chat.summary}`;
|
|
331
328
|
try {
|
|
332
329
|
const { output: { title, summary } } = await generateText({
|
|
333
330
|
model,
|
|
334
331
|
system: systemPrompt,
|
|
335
|
-
messages: await convertToModelMessages(messages.slice(-
|
|
332
|
+
messages: await convertToModelMessages(messages.slice(-CHAT_RECENT_MESSAGES_COUNT)),
|
|
336
333
|
output: Output.object({ schema: jsonSchema({
|
|
337
334
|
type: "object",
|
|
338
335
|
properties: {
|
|
339
336
|
title: {
|
|
340
337
|
type: "string",
|
|
341
|
-
description: "Short title for the
|
|
338
|
+
description: "Short title for the chat, max 8-10 words"
|
|
342
339
|
},
|
|
343
340
|
summary: {
|
|
344
341
|
type: "string",
|
|
345
|
-
description: "A short 1-2 sentence summary of the
|
|
342
|
+
description: "A short 1-2 sentence summary of the chat. If the chat direction has changed from the previous summary, reflect the new direction."
|
|
346
343
|
}
|
|
347
344
|
},
|
|
348
345
|
required: ["title", "summary"]
|
|
349
346
|
}) })
|
|
350
347
|
});
|
|
351
348
|
if (!title || !summary) {
|
|
352
|
-
console.error("[Assistant] Failed to generate
|
|
349
|
+
console.error("[Assistant] Failed to generate chat title and summary", { durableObjectName });
|
|
353
350
|
return;
|
|
354
351
|
}
|
|
355
|
-
sql`UPDATE
|
|
352
|
+
sql`UPDATE chats
|
|
356
353
|
SET title = ${title},
|
|
357
354
|
summary = ${summary},
|
|
358
355
|
updated_at = ${Date.now()}
|
|
359
356
|
WHERE durable_object_name = ${durableObjectName}`;
|
|
360
|
-
console.info("[Assistant] Generated
|
|
357
|
+
console.info("[Assistant] Generated chat summary", { durableObjectName });
|
|
361
358
|
} catch (error) {
|
|
362
|
-
console.error("[Assistant] Failed to generate
|
|
359
|
+
console.error("[Assistant] Failed to generate chat title and summary", {
|
|
363
360
|
durableObjectName,
|
|
364
361
|
error
|
|
365
362
|
});
|
|
366
363
|
}
|
|
367
364
|
}
|
|
368
|
-
const
|
|
369
|
-
function
|
|
365
|
+
const DELETE_CHAT_CALLBACK = "deleteChatCallback";
|
|
366
|
+
function getChatRetentionMs(days) {
|
|
370
367
|
if (typeof days !== "number" || !Number.isFinite(days) || days <= 0) return null;
|
|
371
368
|
return Math.floor(days * 24 * 60 * 60 * 1e3);
|
|
372
369
|
}
|
|
@@ -379,53 +376,86 @@ var Assistant = class extends Agent$1 {
|
|
|
379
376
|
};
|
|
380
377
|
onStart() {
|
|
381
378
|
this.setState({
|
|
382
|
-
|
|
379
|
+
...this.initialState,
|
|
383
380
|
status: "connecting",
|
|
384
381
|
subAgentName: this.agent.name
|
|
385
382
|
});
|
|
386
|
-
|
|
383
|
+
ensureChatsTableExists(this.sql.bind(this));
|
|
387
384
|
}
|
|
388
385
|
async onClose() {
|
|
389
386
|
this.setState({
|
|
390
|
-
|
|
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
|
-
|
|
427
|
+
...this.initialState,
|
|
398
428
|
status: "connected",
|
|
399
429
|
subAgentName: this.agent.name
|
|
400
430
|
});
|
|
401
431
|
}
|
|
402
|
-
@callable() async
|
|
432
|
+
@callable() async createChat() {
|
|
403
433
|
const id = nanoid();
|
|
404
434
|
const now = Date.now();
|
|
405
435
|
await this.subAgent(this.agent, id);
|
|
406
|
-
|
|
436
|
+
registerChat(this.sql.bind(this), id, now);
|
|
407
437
|
return id;
|
|
408
438
|
}
|
|
409
|
-
@callable() async
|
|
439
|
+
@callable() async deleteChat(id) {
|
|
410
440
|
await this.deleteSubAgent(this.agent, id);
|
|
411
|
-
|
|
441
|
+
deleteChat(this.sql.bind(this), id);
|
|
412
442
|
}
|
|
413
|
-
@callable() async
|
|
414
|
-
return
|
|
443
|
+
@callable() async getChats() {
|
|
444
|
+
return getChats(this.sql.bind(this));
|
|
415
445
|
}
|
|
416
|
-
async
|
|
417
|
-
|
|
418
|
-
this.
|
|
446
|
+
async recordChatTurn(durableObjectName, messages) {
|
|
447
|
+
summariseChatWithAI(this.sql.bind(this), durableObjectName, messages, this.fastModel);
|
|
448
|
+
this.scheduleChatForAutoDeletion(durableObjectName);
|
|
419
449
|
}
|
|
420
|
-
async [
|
|
421
|
-
await this.
|
|
450
|
+
async [DELETE_CHAT_CALLBACK](durableObjectName) {
|
|
451
|
+
await this.deleteChat(durableObjectName);
|
|
422
452
|
}
|
|
423
|
-
async
|
|
424
|
-
const retentionMs =
|
|
453
|
+
async scheduleChatForAutoDeletion(durableObjectName) {
|
|
454
|
+
const retentionMs = getChatRetentionMs(90);
|
|
425
455
|
if (retentionMs === null) return;
|
|
426
|
-
const scheduleIds =
|
|
456
|
+
const scheduleIds = getDeleteChatScheduleIds(await this.listSchedules());
|
|
427
457
|
await Promise.all(scheduleIds.map((scheduleId) => this.cancelSchedule(scheduleId)));
|
|
428
|
-
await this.schedule(new Date(Date.now() + retentionMs),
|
|
458
|
+
await this.schedule(new Date(Date.now() + retentionMs), DELETE_CHAT_CALLBACK, durableObjectName, { idempotent: true });
|
|
429
459
|
}
|
|
430
460
|
};
|
|
431
461
|
//#endregion
|
|
@@ -507,7 +537,7 @@ var ChatAgent = class extends Agent {
|
|
|
507
537
|
}
|
|
508
538
|
async onChatResponse(_result) {
|
|
509
539
|
const parent = await this.getParentAgent();
|
|
510
|
-
if (parent?.
|
|
540
|
+
if (parent?.recordChatTurn) await parent.recordChatTurn(this.name, this.messages);
|
|
511
541
|
}
|
|
512
542
|
/**
|
|
513
543
|
* Rate a message by its id.
|
|
@@ -519,10 +549,10 @@ var ChatAgent = class extends Agent {
|
|
|
519
549
|
return rateMessage(this.sql.bind(this), messageId, this.name, rating, comment);
|
|
520
550
|
}
|
|
521
551
|
/**
|
|
522
|
-
* Returns all message ratings for the current
|
|
523
|
-
* @returns All message ratings for the current
|
|
552
|
+
* Returns all message ratings for the current chat.
|
|
553
|
+
* @returns All message ratings for the current chat.
|
|
524
554
|
*/
|
|
525
|
-
@callable({ description: "Returns all message ratings for the current
|
|
555
|
+
@callable({ description: "Returns all message ratings for the current chat" }) async getMessageRatings() {
|
|
526
556
|
return getMessageRatings(this.sql.bind(this), this.name);
|
|
527
557
|
}
|
|
528
558
|
};
|