@economic/agents 3.1.0 → 3.2.1
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 +19 -0
- package/dist/index.d.mts +23 -1
- package/dist/index.mjs +170 -89
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -675,6 +675,24 @@ export class SupportAgent extends Agent<RequestContext, UserContext> {
|
|
|
675
675
|
- **Requests without the caller's token,** such as an OAuth callback or a signed webhook, are refused unless `acceptsWithoutToken(request)` returns `true` for them. Check them another way.
|
|
676
676
|
- **Any authenticator works:** `getAuthenticator(env)` can return your own `Authenticator`, such as one for a different identity provider.
|
|
677
677
|
|
|
678
|
+
### Reading without chatting
|
|
679
|
+
|
|
680
|
+
Return `false` from `canChat(userContext)` to let a user read their chats but not chat in them.
|
|
681
|
+
|
|
682
|
+
- **Refused:** messages, approval answers, a client tool's result that would start another turn, and `run`. Nothing they send is kept.
|
|
683
|
+
- **Still allowed:** reading the chat, rating messages, stopping a turn, and a client tool's result for the turn that's running. A running turn finishes.
|
|
684
|
+
- **The client** is told in the `connected` frame (`canChat: false`), which `useChat` returns as `canChat`.
|
|
685
|
+
- **When it's asked:** once per connection, when the user connects, so a change reaches them when they reconnect. An error counts as `false`. An override of `onConnect` must call `super.onConnect`.
|
|
686
|
+
- **The connection** is marked readonly, so it can't change the agent's state either.
|
|
687
|
+
|
|
688
|
+
```ts
|
|
689
|
+
export class SupportChat extends ChatAgent<RequestContext, UserContext> {
|
|
690
|
+
canChat(userContext: UserContext | undefined) {
|
|
691
|
+
return userContext?.hasSupportAgent === true;
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
```
|
|
695
|
+
|
|
678
696
|
## Memory
|
|
679
697
|
|
|
680
698
|
Return `memory: true` from `getAgentConfig()` to give each user a private memory with the agent, kept across all their chats in their `UserStore` (`AGENTS_USERS`). It's a writable block of the system prompt, which the model updates itself with `set_context`.
|
|
@@ -792,6 +810,7 @@ Imported from `@economic/agents` unless noted.
|
|
|
792
810
|
| `configureContext()` | `Agent` | Think's system prompt blocks. An override must include `...(await super.configureContext())`, or the agent's own prompt and rules are lost. |
|
|
793
811
|
| `getTracingHandlers()` | `Agent` | Destinations for completed turns and message feedback (default: `[]`). |
|
|
794
812
|
| `static getAuthenticator(env)` | `Agent` | Optional caller authentication, credentials and user context. |
|
|
813
|
+
| `canChat(userContext)` | `Agent` | Whether the user can send messages and answer approvals (default `true`). See [Reading without chatting](#reading-without-chatting). |
|
|
795
814
|
| `submitMessageFeedback` / `getMessageFeedback` | `ChatAgent` | Callable message feedback. |
|
|
796
815
|
| `getAgentConfig(ctx?)` | `Agent` | Settings for a turn (default `{}`): `maxSteps`, `temperature`, `maxOutputTokens`, `topP`, `toolChoice`, `maxRetries`, `timeout`, `sendReasoning`, `providerOptions`; `toolCallLimits`, how often each user may call each tool by name, per day (`dailyCalls`) and per minute (`burst`), which needs `AGENTS_USERS`; for a chat, `memory`, a private memory per user, and `deleteMessagesAfterMs`, after which its messages are deleted. |
|
|
797
816
|
| `agent` | `Assistant` | Required. Your `ChatAgent` subclass. |
|
package/dist/index.d.mts
CHANGED
|
@@ -12873,6 +12873,24 @@ export declare abstract class Agent<RequestContext extends Record<string, unknow
|
|
|
12873
12873
|
*/
|
|
12874
12874
|
protected acceptsWithoutToken(_request: Request): boolean;
|
|
12875
12875
|
onConnect(connection: Connection, ctx: ConnectionContext): Promise<void>;
|
|
12876
|
+
/**
|
|
12877
|
+
* Whether the user can send messages and answer approvals. When it's
|
|
12878
|
+
* `false` they can still read the chat. Asked for each connection in
|
|
12879
|
+
* `onConnect`, so an override of `onConnect` must call `super`. An error
|
|
12880
|
+
* counts as `false`. `true` by default.
|
|
12881
|
+
*/
|
|
12882
|
+
canChat(_userContext: UserContext | undefined): boolean | Promise<boolean>;
|
|
12883
|
+
/** Answers still being asked, by connection, so messages sent meanwhile wait for them. */
|
|
12884
|
+
private _canChatAnswers;
|
|
12885
|
+
/**
|
|
12886
|
+
* Asks `canChat` for a connection. A no marks it readonly, which outlives
|
|
12887
|
+
* hibernation and the user's token.
|
|
12888
|
+
*/
|
|
12889
|
+
private _askCanChat;
|
|
12890
|
+
/** Whether the connection can chat. Calls from the server, without one, can. */
|
|
12891
|
+
protected _canChat(connection?: Connection | undefined): Promise<boolean>;
|
|
12892
|
+
/** Think stores a message before any hook runs, so it's refused before Think sees it. */
|
|
12893
|
+
private _refuseChatMessages;
|
|
12876
12894
|
protected _turn: CurrentTurnState<RequestContext, UserContext>;
|
|
12877
12895
|
protected createToolContextForCurrentTurn(requestContext?: RequestContext): ToolContext<RequestContext, UserContext>;
|
|
12878
12896
|
protected getToolContextForCurrentTurn(): ToolContext<RequestContext, UserContext> | undefined;
|
|
@@ -13090,7 +13108,11 @@ export declare abstract class Agent<RequestContext extends Record<string, unknow
|
|
|
13090
13108
|
* as a server error.
|
|
13091
13109
|
*/
|
|
13092
13110
|
protected authenticate(request: Request): Promise<void>;
|
|
13093
|
-
|
|
13111
|
+
protected _logContext(): {
|
|
13112
|
+
agentName: string;
|
|
13113
|
+
agentClass: string;
|
|
13114
|
+
durableObjectName: string;
|
|
13115
|
+
};
|
|
13094
13116
|
/**
|
|
13095
13117
|
* Self-registers this DO in the global `agent_registry`. Only top-level DOs
|
|
13096
13118
|
* are registered — facets are enumerable via their parent's own index, so
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as aiSdk from "ai";
|
|
2
|
-
import { Output, asSchema, convertToModelMessages, generateId, generateText, getToolName, hasToolCall, isToolUIPart, jsonSchema, pruneMessages, stepCountIs, tool as tool$1 } from "ai";
|
|
2
|
+
import { AISDKError, APICallError, Output, asSchema, convertToModelMessages, generateId, generateText, getToolName, hasToolCall, isToolUIPart, jsonSchema, pruneMessages, stepCountIs, tool as tool$1 } from "ai";
|
|
3
3
|
import { isPrivateOrLocalHost } from "agents/webfetch";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
import { truncateResult } from "@cloudflare/codemode";
|
|
@@ -28166,7 +28166,7 @@ const symbol$16 = Symbol.for(marker$16);
|
|
|
28166
28166
|
* Custom error class for AI SDK related errors.
|
|
28167
28167
|
* @extends Error
|
|
28168
28168
|
*/
|
|
28169
|
-
var AISDKError = class AISDKError extends Error {
|
|
28169
|
+
var AISDKError$1 = class AISDKError extends Error {
|
|
28170
28170
|
/**
|
|
28171
28171
|
* Creates an AI SDK Error.
|
|
28172
28172
|
*
|
|
@@ -28197,7 +28197,7 @@ var AISDKError = class AISDKError extends Error {
|
|
|
28197
28197
|
const name$14 = "AI_APICallError";
|
|
28198
28198
|
const marker$14 = `vercel.ai.error.${name$14}`;
|
|
28199
28199
|
const symbol$14 = Symbol.for(marker$14);
|
|
28200
|
-
var APICallError = class extends AISDKError {
|
|
28200
|
+
var APICallError$1 = class extends AISDKError$1 {
|
|
28201
28201
|
constructor({ message, url, requestBodyValues, statusCode, responseHeaders, responseBody, cause, isRetryable = statusCode != null && (statusCode === 408 || statusCode === 409 || statusCode === 429 || statusCode >= 500), data }) {
|
|
28202
28202
|
super({
|
|
28203
28203
|
name: name$14,
|
|
@@ -28214,13 +28214,13 @@ var APICallError = class extends AISDKError {
|
|
|
28214
28214
|
this.data = data;
|
|
28215
28215
|
}
|
|
28216
28216
|
static isInstance(error) {
|
|
28217
|
-
return AISDKError.hasMarker(error, marker$14);
|
|
28217
|
+
return AISDKError$1.hasMarker(error, marker$14);
|
|
28218
28218
|
}
|
|
28219
28219
|
};
|
|
28220
28220
|
const name$13 = "AI_EmptyResponseBodyError";
|
|
28221
28221
|
const marker$13 = `vercel.ai.error.${name$13}`;
|
|
28222
28222
|
const symbol$13 = Symbol.for(marker$13);
|
|
28223
|
-
var EmptyResponseBodyError = class extends AISDKError {
|
|
28223
|
+
var EmptyResponseBodyError = class extends AISDKError$1 {
|
|
28224
28224
|
constructor({ message = "Empty response body" } = {}) {
|
|
28225
28225
|
super({
|
|
28226
28226
|
name: name$13,
|
|
@@ -28229,7 +28229,7 @@ var EmptyResponseBodyError = class extends AISDKError {
|
|
|
28229
28229
|
this[symbol$13] = true;
|
|
28230
28230
|
}
|
|
28231
28231
|
static isInstance(error) {
|
|
28232
|
-
return AISDKError.hasMarker(error, marker$13);
|
|
28232
|
+
return AISDKError$1.hasMarker(error, marker$13);
|
|
28233
28233
|
}
|
|
28234
28234
|
};
|
|
28235
28235
|
function getErrorMessage(error) {
|
|
@@ -28244,7 +28244,7 @@ const symbol$11 = Symbol.for(marker$11);
|
|
|
28244
28244
|
/**
|
|
28245
28245
|
* A function argument is invalid.
|
|
28246
28246
|
*/
|
|
28247
|
-
var InvalidArgumentError = class extends AISDKError {
|
|
28247
|
+
var InvalidArgumentError = class extends AISDKError$1 {
|
|
28248
28248
|
constructor({ message, cause, argument }) {
|
|
28249
28249
|
super({
|
|
28250
28250
|
name: name$11,
|
|
@@ -28255,7 +28255,7 @@ var InvalidArgumentError = class extends AISDKError {
|
|
|
28255
28255
|
this.argument = argument;
|
|
28256
28256
|
}
|
|
28257
28257
|
static isInstance(error) {
|
|
28258
|
-
return AISDKError.hasMarker(error, marker$11);
|
|
28258
|
+
return AISDKError$1.hasMarker(error, marker$11);
|
|
28259
28259
|
}
|
|
28260
28260
|
};
|
|
28261
28261
|
const name$10 = "AI_InvalidPromptError";
|
|
@@ -28265,7 +28265,7 @@ const symbol$10 = Symbol.for(marker$10);
|
|
|
28265
28265
|
* A prompt is invalid. This error should be thrown by providers when they cannot
|
|
28266
28266
|
* process a prompt.
|
|
28267
28267
|
*/
|
|
28268
|
-
var InvalidPromptError = class extends AISDKError {
|
|
28268
|
+
var InvalidPromptError = class extends AISDKError$1 {
|
|
28269
28269
|
constructor({ prompt, message, cause }) {
|
|
28270
28270
|
super({
|
|
28271
28271
|
name: name$10,
|
|
@@ -28276,7 +28276,7 @@ var InvalidPromptError = class extends AISDKError {
|
|
|
28276
28276
|
this.prompt = prompt;
|
|
28277
28277
|
}
|
|
28278
28278
|
static isInstance(error) {
|
|
28279
|
-
return AISDKError.hasMarker(error, marker$10);
|
|
28279
|
+
return AISDKError$1.hasMarker(error, marker$10);
|
|
28280
28280
|
}
|
|
28281
28281
|
};
|
|
28282
28282
|
const name$9 = "AI_InvalidResponseDataError";
|
|
@@ -28286,7 +28286,7 @@ const symbol$9 = Symbol.for(marker$9);
|
|
|
28286
28286
|
* Server returned a response with invalid data content.
|
|
28287
28287
|
* This should be thrown by providers when they cannot parse the response from the API.
|
|
28288
28288
|
*/
|
|
28289
|
-
var InvalidResponseDataError = class extends AISDKError {
|
|
28289
|
+
var InvalidResponseDataError = class extends AISDKError$1 {
|
|
28290
28290
|
constructor({ data, message = `Invalid response data: ${JSON.stringify(data)}.` }) {
|
|
28291
28291
|
super({
|
|
28292
28292
|
name: name$9,
|
|
@@ -28296,13 +28296,13 @@ var InvalidResponseDataError = class extends AISDKError {
|
|
|
28296
28296
|
this.data = data;
|
|
28297
28297
|
}
|
|
28298
28298
|
static isInstance(error) {
|
|
28299
|
-
return AISDKError.hasMarker(error, marker$9);
|
|
28299
|
+
return AISDKError$1.hasMarker(error, marker$9);
|
|
28300
28300
|
}
|
|
28301
28301
|
};
|
|
28302
28302
|
const name$8 = "AI_JSONParseError";
|
|
28303
28303
|
const marker$8 = `vercel.ai.error.${name$8}`;
|
|
28304
28304
|
const symbol$8 = Symbol.for(marker$8);
|
|
28305
|
-
var JSONParseError = class extends AISDKError {
|
|
28305
|
+
var JSONParseError = class extends AISDKError$1 {
|
|
28306
28306
|
constructor({ text, cause }) {
|
|
28307
28307
|
super({
|
|
28308
28308
|
name: name$8,
|
|
@@ -28313,13 +28313,13 @@ var JSONParseError = class extends AISDKError {
|
|
|
28313
28313
|
this.text = text;
|
|
28314
28314
|
}
|
|
28315
28315
|
static isInstance(error) {
|
|
28316
|
-
return AISDKError.hasMarker(error, marker$8);
|
|
28316
|
+
return AISDKError$1.hasMarker(error, marker$8);
|
|
28317
28317
|
}
|
|
28318
28318
|
};
|
|
28319
28319
|
const name$7 = "AI_LoadAPIKeyError";
|
|
28320
28320
|
const marker$7 = `vercel.ai.error.${name$7}`;
|
|
28321
28321
|
const symbol$7 = Symbol.for(marker$7);
|
|
28322
|
-
var LoadAPIKeyError = class extends AISDKError {
|
|
28322
|
+
var LoadAPIKeyError = class extends AISDKError$1 {
|
|
28323
28323
|
constructor({ message }) {
|
|
28324
28324
|
super({
|
|
28325
28325
|
name: name$7,
|
|
@@ -28328,7 +28328,7 @@ var LoadAPIKeyError = class extends AISDKError {
|
|
|
28328
28328
|
this[symbol$7] = true;
|
|
28329
28329
|
}
|
|
28330
28330
|
static isInstance(error) {
|
|
28331
|
-
return AISDKError.hasMarker(error, marker$7);
|
|
28331
|
+
return AISDKError$1.hasMarker(error, marker$7);
|
|
28332
28332
|
}
|
|
28333
28333
|
};
|
|
28334
28334
|
const name$3 = "AI_NoSuchProviderReferenceError";
|
|
@@ -28338,7 +28338,7 @@ const symbol$3 = Symbol.for(marker$3);
|
|
|
28338
28338
|
* Thrown when a provider reference cannot be resolved because the specified
|
|
28339
28339
|
* provider is not found in the provider reference mapping.
|
|
28340
28340
|
*/
|
|
28341
|
-
var NoSuchProviderReferenceError = class extends AISDKError {
|
|
28341
|
+
var NoSuchProviderReferenceError = class extends AISDKError$1 {
|
|
28342
28342
|
constructor({ provider, reference, message = `No provider reference found for provider '${provider}'. Available providers: ${Object.keys(reference).join(", ")}` }) {
|
|
28343
28343
|
super({
|
|
28344
28344
|
name: name$3,
|
|
@@ -28349,13 +28349,13 @@ var NoSuchProviderReferenceError = class extends AISDKError {
|
|
|
28349
28349
|
this.reference = reference;
|
|
28350
28350
|
}
|
|
28351
28351
|
static isInstance(error) {
|
|
28352
|
-
return AISDKError.hasMarker(error, marker$3);
|
|
28352
|
+
return AISDKError$1.hasMarker(error, marker$3);
|
|
28353
28353
|
}
|
|
28354
28354
|
};
|
|
28355
28355
|
const name$2 = "AI_TooManyEmbeddingValuesForCallError";
|
|
28356
28356
|
const marker$2$1 = `vercel.ai.error.${name$2}`;
|
|
28357
28357
|
const symbol$2 = Symbol.for(marker$2$1);
|
|
28358
|
-
var TooManyEmbeddingValuesForCallError = class extends AISDKError {
|
|
28358
|
+
var TooManyEmbeddingValuesForCallError = class extends AISDKError$1 {
|
|
28359
28359
|
constructor(options) {
|
|
28360
28360
|
super({
|
|
28361
28361
|
name: name$2,
|
|
@@ -28368,13 +28368,13 @@ var TooManyEmbeddingValuesForCallError = class extends AISDKError {
|
|
|
28368
28368
|
this.values = options.values;
|
|
28369
28369
|
}
|
|
28370
28370
|
static isInstance(error) {
|
|
28371
|
-
return AISDKError.hasMarker(error, marker$2$1);
|
|
28371
|
+
return AISDKError$1.hasMarker(error, marker$2$1);
|
|
28372
28372
|
}
|
|
28373
28373
|
};
|
|
28374
28374
|
const name$1$1 = "AI_TypeValidationError";
|
|
28375
28375
|
const marker$1$1 = `vercel.ai.error.${name$1$1}`;
|
|
28376
28376
|
const symbol$1$1 = Symbol.for(marker$1$1);
|
|
28377
|
-
var TypeValidationError = class TypeValidationError extends AISDKError {
|
|
28377
|
+
var TypeValidationError = class TypeValidationError extends AISDKError$1 {
|
|
28378
28378
|
constructor({ value, cause, context }) {
|
|
28379
28379
|
let contextPrefix = "Type validation failed";
|
|
28380
28380
|
if (context?.field) contextPrefix += ` for ${context.field}`;
|
|
@@ -28396,7 +28396,7 @@ var TypeValidationError = class TypeValidationError extends AISDKError {
|
|
|
28396
28396
|
this.context = context;
|
|
28397
28397
|
}
|
|
28398
28398
|
static isInstance(error) {
|
|
28399
|
-
return AISDKError.hasMarker(error, marker$1$1);
|
|
28399
|
+
return AISDKError$1.hasMarker(error, marker$1$1);
|
|
28400
28400
|
}
|
|
28401
28401
|
/**
|
|
28402
28402
|
* Wraps an error into a TypeValidationError.
|
|
@@ -28421,7 +28421,7 @@ var TypeValidationError = class TypeValidationError extends AISDKError {
|
|
|
28421
28421
|
const name$16 = "AI_UnsupportedFunctionalityError";
|
|
28422
28422
|
const marker$17 = `vercel.ai.error.${name$16}`;
|
|
28423
28423
|
const symbol$17 = Symbol.for(marker$17);
|
|
28424
|
-
var UnsupportedFunctionalityError = class extends AISDKError {
|
|
28424
|
+
var UnsupportedFunctionalityError = class extends AISDKError$1 {
|
|
28425
28425
|
constructor({ functionality, message = `'${functionality}' functionality not supported.` }) {
|
|
28426
28426
|
super({
|
|
28427
28427
|
name: name$16,
|
|
@@ -28431,7 +28431,7 @@ var UnsupportedFunctionalityError = class extends AISDKError {
|
|
|
28431
28431
|
this.functionality = functionality;
|
|
28432
28432
|
}
|
|
28433
28433
|
static isInstance(error) {
|
|
28434
|
-
return AISDKError.hasMarker(error, marker$17);
|
|
28434
|
+
return AISDKError$1.hasMarker(error, marker$17);
|
|
28435
28435
|
}
|
|
28436
28436
|
};
|
|
28437
28437
|
function isJSONValue(value) {
|
|
@@ -28457,11 +28457,11 @@ function isJSONObject(value) {
|
|
|
28457
28457
|
* prior behavior).
|
|
28458
28458
|
*/
|
|
28459
28459
|
function normalizeBindingError(error, context) {
|
|
28460
|
-
if (APICallError.isInstance(error) || isAbortError$1(error)) return error;
|
|
28460
|
+
if (APICallError$1.isInstance(error) || isAbortError$1(error)) return error;
|
|
28461
28461
|
const code = parseWorkersAIErrorCode(error);
|
|
28462
28462
|
const statusCode = code != null ? WORKERS_AI_ERROR_CODE_TO_STATUS[code] : void 0;
|
|
28463
28463
|
const message = messageOf(error);
|
|
28464
|
-
return new APICallError({
|
|
28464
|
+
return new APICallError$1({
|
|
28465
28465
|
message,
|
|
28466
28466
|
url: `workers-ai:binding/run/${context.model}`,
|
|
28467
28467
|
requestBodyValues: context.requestBodyValues,
|
|
@@ -28479,7 +28479,7 @@ function normalizeBindingError(error, context) {
|
|
|
28479
28479
|
* `"Workers AI API error (<status> <statusText>): <body>"` shape.
|
|
28480
28480
|
*/
|
|
28481
28481
|
function apiCallErrorFromResponse(response, errorBody, context) {
|
|
28482
|
-
return new APICallError({
|
|
28482
|
+
return new APICallError$1({
|
|
28483
28483
|
message: `Workers AI API error (${response.status} ${response.statusText}): ${errorBody}`,
|
|
28484
28484
|
url: context.url,
|
|
28485
28485
|
requestBodyValues: context.requestBodyValues,
|
|
@@ -31347,7 +31347,7 @@ function handleFetchError({ error, url, requestBodyValues }) {
|
|
|
31347
31347
|
if (isAbortError(error)) return error;
|
|
31348
31348
|
if (error instanceof TypeError && FETCH_FAILED_ERROR_MESSAGES.includes(error.message.toLowerCase())) {
|
|
31349
31349
|
const cause = error.cause;
|
|
31350
|
-
if (cause != null) return new APICallError({
|
|
31350
|
+
if (cause != null) return new APICallError$1({
|
|
31351
31351
|
message: `Cannot connect to API: ${cause.message}`,
|
|
31352
31352
|
cause,
|
|
31353
31353
|
url,
|
|
@@ -31357,7 +31357,7 @@ function handleFetchError({ error, url, requestBodyValues }) {
|
|
|
31357
31357
|
}
|
|
31358
31358
|
const networkError = findNetworkError(error);
|
|
31359
31359
|
if (networkError != null) {
|
|
31360
|
-
if (APICallError.isInstance(error)) return new APICallError({
|
|
31360
|
+
if (APICallError$1.isInstance(error)) return new APICallError$1({
|
|
31361
31361
|
message: error.message,
|
|
31362
31362
|
cause: error.cause,
|
|
31363
31363
|
url: error.url,
|
|
@@ -31368,7 +31368,7 @@ function handleFetchError({ error, url, requestBodyValues }) {
|
|
|
31368
31368
|
data: error.data,
|
|
31369
31369
|
isRetryable: true
|
|
31370
31370
|
});
|
|
31371
|
-
return new APICallError({
|
|
31371
|
+
return new APICallError$1({
|
|
31372
31372
|
message: `Cannot connect to API: ${error instanceof Error ? error.message : networkError.message}`,
|
|
31373
31373
|
cause: error,
|
|
31374
31374
|
url,
|
|
@@ -31437,8 +31437,8 @@ const deleteFromApi = async ({ url, headers = {}, failedResponseHandler, success
|
|
|
31437
31437
|
requestBodyValues: {}
|
|
31438
31438
|
});
|
|
31439
31439
|
} catch (error) {
|
|
31440
|
-
if (isAbortError(error) || APICallError.isInstance(error)) throw error;
|
|
31441
|
-
throw new APICallError({
|
|
31440
|
+
if (isAbortError(error) || APICallError$1.isInstance(error)) throw error;
|
|
31441
|
+
throw new APICallError$1({
|
|
31442
31442
|
message: "Failed to process error response",
|
|
31443
31443
|
cause: error,
|
|
31444
31444
|
statusCode: response.status,
|
|
@@ -31457,9 +31457,9 @@ const deleteFromApi = async ({ url, headers = {}, failedResponseHandler, success
|
|
|
31457
31457
|
});
|
|
31458
31458
|
} catch (error) {
|
|
31459
31459
|
if (error instanceof Error) {
|
|
31460
|
-
if (isAbortError(error) || APICallError.isInstance(error)) throw error;
|
|
31460
|
+
if (isAbortError(error) || APICallError$1.isInstance(error)) throw error;
|
|
31461
31461
|
}
|
|
31462
|
-
throw new APICallError({
|
|
31462
|
+
throw new APICallError$1({
|
|
31463
31463
|
message: "Failed to process successful response",
|
|
31464
31464
|
cause: error,
|
|
31465
31465
|
statusCode: response.status,
|
|
@@ -31868,7 +31868,7 @@ async function cancelResponseBody(response) {
|
|
|
31868
31868
|
const name$1 = "AI_DownloadError";
|
|
31869
31869
|
const marker$1 = `vercel.ai.error.${name$1}`;
|
|
31870
31870
|
const symbol$1 = Symbol.for(marker$1);
|
|
31871
|
-
var DownloadError = class extends AISDKError {
|
|
31871
|
+
var DownloadError = class extends AISDKError$1 {
|
|
31872
31872
|
constructor({ url, statusCode, statusText, cause, message = cause == null ? `Failed to download ${url}: ${statusCode} ${statusText}` : `Failed to download ${url}: ${cause}` }) {
|
|
31873
31873
|
super({
|
|
31874
31874
|
name: name$1,
|
|
@@ -31881,7 +31881,7 @@ var DownloadError = class extends AISDKError {
|
|
|
31881
31881
|
this.statusText = statusText;
|
|
31882
31882
|
}
|
|
31883
31883
|
static isInstance(error) {
|
|
31884
|
-
return AISDKError.hasMarker(error, marker$1);
|
|
31884
|
+
return AISDKError$1.hasMarker(error, marker$1);
|
|
31885
31885
|
}
|
|
31886
31886
|
};
|
|
31887
31887
|
/**
|
|
@@ -32499,8 +32499,8 @@ const getFromApi = async ({ url, headers = {}, successfulResponseHandler, failed
|
|
|
32499
32499
|
requestBodyValues: {}
|
|
32500
32500
|
});
|
|
32501
32501
|
} catch (error) {
|
|
32502
|
-
if (isAbortError(error) || APICallError.isInstance(error)) throw error;
|
|
32503
|
-
throw new APICallError({
|
|
32502
|
+
if (isAbortError(error) || APICallError$1.isInstance(error)) throw error;
|
|
32503
|
+
throw new APICallError$1({
|
|
32504
32504
|
message: "Failed to process error response",
|
|
32505
32505
|
cause: error,
|
|
32506
32506
|
statusCode: response.status,
|
|
@@ -32519,9 +32519,9 @@ const getFromApi = async ({ url, headers = {}, successfulResponseHandler, failed
|
|
|
32519
32519
|
});
|
|
32520
32520
|
} catch (error) {
|
|
32521
32521
|
if (error instanceof Error) {
|
|
32522
|
-
if (isAbortError(error) || APICallError.isInstance(error)) throw error;
|
|
32522
|
+
if (isAbortError(error) || APICallError$1.isInstance(error)) throw error;
|
|
32523
32523
|
}
|
|
32524
|
-
throw new APICallError({
|
|
32524
|
+
throw new APICallError$1({
|
|
32525
32525
|
message: "Failed to process successful response",
|
|
32526
32526
|
cause: error,
|
|
32527
32527
|
statusCode: response.status,
|
|
@@ -33867,8 +33867,8 @@ const postMultipartStreamToApi = async ({ url, headers = {}, parts, failedRespon
|
|
|
33867
33867
|
requestBodyValues
|
|
33868
33868
|
});
|
|
33869
33869
|
} catch (error) {
|
|
33870
|
-
if (isAbortError(error) || APICallError.isInstance(error)) throw error;
|
|
33871
|
-
throw new APICallError({
|
|
33870
|
+
if (isAbortError(error) || APICallError$1.isInstance(error)) throw error;
|
|
33871
|
+
throw new APICallError$1({
|
|
33872
33872
|
message: "Failed to process error response",
|
|
33873
33873
|
cause: error,
|
|
33874
33874
|
statusCode: response.status,
|
|
@@ -33887,9 +33887,9 @@ const postMultipartStreamToApi = async ({ url, headers = {}, parts, failedRespon
|
|
|
33887
33887
|
});
|
|
33888
33888
|
} catch (error) {
|
|
33889
33889
|
if (error instanceof Error) {
|
|
33890
|
-
if (isAbortError(error) || APICallError.isInstance(error)) throw error;
|
|
33890
|
+
if (isAbortError(error) || APICallError$1.isInstance(error)) throw error;
|
|
33891
33891
|
}
|
|
33892
|
-
throw new APICallError({
|
|
33892
|
+
throw new APICallError$1({
|
|
33893
33893
|
message: "Failed to process successful response",
|
|
33894
33894
|
cause: error,
|
|
33895
33895
|
statusCode: response.status,
|
|
@@ -33953,8 +33953,8 @@ const postToApi = async ({ url, headers = {}, body, successfulResponseHandler, f
|
|
|
33953
33953
|
requestBodyValues: body.values
|
|
33954
33954
|
});
|
|
33955
33955
|
} catch (error) {
|
|
33956
|
-
if (isAbortError(error) || APICallError.isInstance(error)) throw error;
|
|
33957
|
-
throw new APICallError({
|
|
33956
|
+
if (isAbortError(error) || APICallError$1.isInstance(error)) throw error;
|
|
33957
|
+
throw new APICallError$1({
|
|
33958
33958
|
message: "Failed to process error response",
|
|
33959
33959
|
cause: error,
|
|
33960
33960
|
statusCode: response.status,
|
|
@@ -33973,9 +33973,9 @@ const postToApi = async ({ url, headers = {}, body, successfulResponseHandler, f
|
|
|
33973
33973
|
});
|
|
33974
33974
|
} catch (error) {
|
|
33975
33975
|
if (error instanceof Error) {
|
|
33976
|
-
if (isAbortError(error) || APICallError.isInstance(error)) throw error;
|
|
33976
|
+
if (isAbortError(error) || APICallError$1.isInstance(error)) throw error;
|
|
33977
33977
|
}
|
|
33978
|
-
throw new APICallError({
|
|
33978
|
+
throw new APICallError$1({
|
|
33979
33979
|
message: "Failed to process successful response",
|
|
33980
33980
|
cause: error,
|
|
33981
33981
|
statusCode: response.status,
|
|
@@ -34104,7 +34104,7 @@ function wrapResponseBodyStream({ stream, url, requestBodyValues, statusCode, re
|
|
|
34104
34104
|
return;
|
|
34105
34105
|
}
|
|
34106
34106
|
controller.error(handleFetchError({
|
|
34107
|
-
error: new APICallError({
|
|
34107
|
+
error: new APICallError$1({
|
|
34108
34108
|
message: "Failed to process successful response",
|
|
34109
34109
|
cause: error,
|
|
34110
34110
|
statusCode,
|
|
@@ -34140,7 +34140,7 @@ const createJsonErrorResponseHandler = ({ errorSchema, errorToMessage, isRetryab
|
|
|
34140
34140
|
const responseHeaders = extractResponseHeaders(response);
|
|
34141
34141
|
if (responseBody.trim() === "") return {
|
|
34142
34142
|
responseHeaders,
|
|
34143
|
-
value: new APICallError({
|
|
34143
|
+
value: new APICallError$1({
|
|
34144
34144
|
message: response.statusText,
|
|
34145
34145
|
url,
|
|
34146
34146
|
requestBodyValues,
|
|
@@ -34157,7 +34157,7 @@ const createJsonErrorResponseHandler = ({ errorSchema, errorToMessage, isRetryab
|
|
|
34157
34157
|
});
|
|
34158
34158
|
return {
|
|
34159
34159
|
responseHeaders,
|
|
34160
|
-
value: new APICallError({
|
|
34160
|
+
value: new APICallError$1({
|
|
34161
34161
|
message: errorToMessage(parsedError),
|
|
34162
34162
|
url,
|
|
34163
34163
|
requestBodyValues,
|
|
@@ -34171,7 +34171,7 @@ const createJsonErrorResponseHandler = ({ errorSchema, errorToMessage, isRetryab
|
|
|
34171
34171
|
} catch {
|
|
34172
34172
|
return {
|
|
34173
34173
|
responseHeaders,
|
|
34174
|
-
value: new APICallError({
|
|
34174
|
+
value: new APICallError$1({
|
|
34175
34175
|
message: response.statusText,
|
|
34176
34176
|
url,
|
|
34177
34177
|
requestBodyValues,
|
|
@@ -34210,7 +34210,7 @@ const createJsonResponseHandler = (responseSchema) => async ({ response, url, re
|
|
|
34210
34210
|
schema: responseSchema
|
|
34211
34211
|
});
|
|
34212
34212
|
const responseHeaders = extractResponseHeaders(response);
|
|
34213
|
-
if (!parsedResult.success) throw new APICallError({
|
|
34213
|
+
if (!parsedResult.success) throw new APICallError$1({
|
|
34214
34214
|
message: "Invalid JSON response",
|
|
34215
34215
|
cause: parsedResult.error,
|
|
34216
34216
|
statusCode: response.status,
|
|
@@ -34292,7 +34292,7 @@ async function* parseJsonLines({ stream, schema, url, maxLineBytes }) {
|
|
|
34292
34292
|
}
|
|
34293
34293
|
const createBinaryResponseHandler = () => async ({ response, url, requestBodyValues }) => {
|
|
34294
34294
|
const responseHeaders = extractResponseHeaders(response);
|
|
34295
|
-
if (!response.body) throw new APICallError({
|
|
34295
|
+
if (!response.body) throw new APICallError$1({
|
|
34296
34296
|
message: "Response body is empty",
|
|
34297
34297
|
url,
|
|
34298
34298
|
requestBodyValues,
|
|
@@ -34307,7 +34307,7 @@ const createBinaryResponseHandler = () => async ({ response, url, requestBodyVal
|
|
|
34307
34307
|
value: new Uint8Array(buffer)
|
|
34308
34308
|
};
|
|
34309
34309
|
} catch (error) {
|
|
34310
|
-
throw new APICallError({
|
|
34310
|
+
throw new APICallError$1({
|
|
34311
34311
|
message: "Failed to read response as array buffer",
|
|
34312
34312
|
url,
|
|
34313
34313
|
requestBodyValues,
|
|
@@ -34356,7 +34356,7 @@ function isJSONSerializable(value) {
|
|
|
34356
34356
|
const name = "AI_SerializationError";
|
|
34357
34357
|
const marker = `vercel.ai.error.${name}`;
|
|
34358
34358
|
const symbol = Symbol.for(marker);
|
|
34359
|
-
var SerializationError = class extends AISDKError {
|
|
34359
|
+
var SerializationError = class extends AISDKError$1 {
|
|
34360
34360
|
constructor({ message = "Failed to serialize value.", cause } = {}) {
|
|
34361
34361
|
super({
|
|
34362
34362
|
name,
|
|
@@ -34366,7 +34366,7 @@ var SerializationError = class extends AISDKError {
|
|
|
34366
34366
|
this[symbol] = true;
|
|
34367
34367
|
}
|
|
34368
34368
|
static isInstance(error) {
|
|
34369
|
-
return AISDKError.hasMarker(error, marker);
|
|
34369
|
+
return AISDKError$1.hasMarker(error, marker);
|
|
34370
34370
|
}
|
|
34371
34371
|
};
|
|
34372
34372
|
/**
|
|
@@ -35098,7 +35098,7 @@ async function raceWithTimeout(promise, timeoutMs) {
|
|
|
35098
35098
|
}
|
|
35099
35099
|
function createOpenAIStreamError({ frame, url, requestBodyValues, responseHeaders }) {
|
|
35100
35100
|
const streamError = createOpenAIProviderStreamError(frame);
|
|
35101
|
-
return new APICallError({
|
|
35101
|
+
return new APICallError$1({
|
|
35102
35102
|
message: streamError?.message ?? "OpenAI stream failed before any output was generated",
|
|
35103
35103
|
url,
|
|
35104
35104
|
requestBodyValues,
|
|
@@ -41160,7 +41160,7 @@ var OpenAIResponsesLanguageModel = class OpenAIResponsesLanguageModel {
|
|
|
41160
41160
|
abortSignal: options.abortSignal,
|
|
41161
41161
|
fetch: this.config.fetch
|
|
41162
41162
|
});
|
|
41163
|
-
if (response.error) throw new APICallError({
|
|
41163
|
+
if (response.error) throw new APICallError$1({
|
|
41164
41164
|
message: response.error.message,
|
|
41165
41165
|
url,
|
|
41166
41166
|
requestBodyValues: body,
|
|
@@ -41171,7 +41171,7 @@ var OpenAIResponsesLanguageModel = class OpenAIResponsesLanguageModel {
|
|
|
41171
41171
|
});
|
|
41172
41172
|
if (response.output == null) {
|
|
41173
41173
|
const detail = response.incomplete_details?.reason;
|
|
41174
|
-
throw new APICallError({
|
|
41174
|
+
throw new APICallError$1({
|
|
41175
41175
|
message: detail ? `Responses API returned no output (${detail})` : "Responses API returned no output",
|
|
41176
41176
|
url,
|
|
41177
41177
|
requestBodyValues: body,
|
|
@@ -42566,7 +42566,7 @@ function isOpenAIChatCompletionChunk(value) {
|
|
|
42566
42566
|
return chunk != null && Array.isArray(chunk.choices) && typeof chunk.type !== "string";
|
|
42567
42567
|
}
|
|
42568
42568
|
function createOpenAIResponsesChatCompletionsMismatchError({ value, cause, url, requestBodyValues, responseHeaders }) {
|
|
42569
|
-
return new APICallError({
|
|
42569
|
+
return new APICallError$1({
|
|
42570
42570
|
message: "Received a Chat Completions stream while using the OpenAI Responses API. The default OpenAI provider model uses the Responses API. If your custom baseURL targets a Chat Completions-compatible endpoint, use openai.chat('model-id') or createOpenAI(...).chat('model-id') instead. You can also use @ai-sdk/openai-compatible for OpenAI-compatible providers.",
|
|
42571
42571
|
url,
|
|
42572
42572
|
requestBodyValues,
|
|
@@ -69941,18 +69941,38 @@ function writeOperationalLog(record, logger = console) {
|
|
|
69941
69941
|
else logger.log(message);
|
|
69942
69942
|
} catch {}
|
|
69943
69943
|
}
|
|
69944
|
+
/**
|
|
69945
|
+
* What's safe to log of an error. An AI SDK error's message can quote what
|
|
69946
|
+
* the model was sent or returned, such as a value that failed validation, so
|
|
69947
|
+
* only its name is kept, and an API call's message, which is the provider's.
|
|
69948
|
+
*/
|
|
69949
|
+
function describeError(error) {
|
|
69950
|
+
if (!AISDKError.isInstance(error)) return {
|
|
69951
|
+
name: error.name,
|
|
69952
|
+
message: error.message,
|
|
69953
|
+
stack: error.stack
|
|
69954
|
+
};
|
|
69955
|
+
return APICallError.isInstance(error) ? {
|
|
69956
|
+
name: error.name,
|
|
69957
|
+
message: error.message
|
|
69958
|
+
} : { name: error.name };
|
|
69959
|
+
}
|
|
69944
69960
|
function errorAttributes(error) {
|
|
69945
69961
|
if (!(error instanceof Error)) return { error: String(error) };
|
|
69962
|
+
const { name, message, stack } = describeError(error);
|
|
69946
69963
|
const causes = [];
|
|
69947
69964
|
let cause = error.cause;
|
|
69948
69965
|
while (cause !== void 0 && causes.length < 5) {
|
|
69949
|
-
|
|
69966
|
+
if (cause instanceof Error) {
|
|
69967
|
+
const described = describeError(cause);
|
|
69968
|
+
causes.push(described.message ? `${described.name}: ${described.message}` : described.name);
|
|
69969
|
+
} else causes.push(String(cause));
|
|
69950
69970
|
cause = cause instanceof Error ? cause.cause : void 0;
|
|
69951
69971
|
}
|
|
69952
69972
|
return {
|
|
69953
|
-
error:
|
|
69954
|
-
errorType:
|
|
69955
|
-
stack
|
|
69973
|
+
error: message,
|
|
69974
|
+
errorType: name,
|
|
69975
|
+
stack,
|
|
69956
69976
|
...causes.length ? { causes } : {}
|
|
69957
69977
|
};
|
|
69958
69978
|
}
|
|
@@ -71011,11 +71031,12 @@ var ToolApprovals = class {
|
|
|
71011
71031
|
}
|
|
71012
71032
|
};
|
|
71013
71033
|
// src/server/util/agent.ts
|
|
71014
|
-
function sendConnectionStatus(connection, status, reason) {
|
|
71034
|
+
function sendConnectionStatus(connection, status, reason, details) {
|
|
71015
71035
|
connection.send(JSON.stringify({
|
|
71016
71036
|
type: "connection_status",
|
|
71017
71037
|
status,
|
|
71018
|
-
reason
|
|
71038
|
+
reason,
|
|
71039
|
+
...details
|
|
71019
71040
|
}));
|
|
71020
71041
|
}
|
|
71021
71042
|
function sendAgentType(connection, agentType) {
|
|
@@ -71204,6 +71225,7 @@ const THINK_SKILLS_CONTEXT_LABEL = "think_skills";
|
|
|
71204
71225
|
const SESSION_CONTEXT_SEPARATOR = "═".repeat(46);
|
|
71205
71226
|
const TOOL_CONTINUATION_PREFIX = "economic:tool-continuation:";
|
|
71206
71227
|
const TOOL_CONTINUATION_REQUEST_PREFIX = "economic:tool-continuation-request:";
|
|
71228
|
+
const CHAT_REFUSED = "You can read this chat, but you can't chat in it.";
|
|
71207
71229
|
/** Whether a tool call's output is the paused or running output of an execution. */
|
|
71208
71230
|
function showsExecution(part, executionId) {
|
|
71209
71231
|
return "output" in part && part.output?.executionId === executionId;
|
|
@@ -71277,6 +71299,7 @@ var Agent = class Agent extends Think {
|
|
|
71277
71299
|
this._tracingHandlers = this.getTracingHandlers();
|
|
71278
71300
|
if (this.context.removeBlock(THINK_SKILLS_CONTEXT_LABEL)) await this.context.refreshSystemPrompt();
|
|
71279
71301
|
this._unfinishedToolCalls = await this._toolTaskSettlements.unfinishedToolCalls();
|
|
71302
|
+
this._refuseChatMessages();
|
|
71280
71303
|
this.registerInstance();
|
|
71281
71304
|
}
|
|
71282
71305
|
/**
|
|
@@ -71336,7 +71359,57 @@ var Agent = class Agent extends Think {
|
|
|
71336
71359
|
connection.close(closeCode, message);
|
|
71337
71360
|
return;
|
|
71338
71361
|
}
|
|
71339
|
-
sendConnectionStatus(connection, "connected");
|
|
71362
|
+
sendConnectionStatus(connection, "connected", void 0, { canChat: await this._askCanChat(connection) });
|
|
71363
|
+
}
|
|
71364
|
+
/**
|
|
71365
|
+
* Whether the user can send messages and answer approvals. When it's
|
|
71366
|
+
* `false` they can still read the chat. Asked for each connection in
|
|
71367
|
+
* `onConnect`, so an override of `onConnect` must call `super`. An error
|
|
71368
|
+
* counts as `false`. `true` by default.
|
|
71369
|
+
*/
|
|
71370
|
+
canChat(_userContext) {
|
|
71371
|
+
return true;
|
|
71372
|
+
}
|
|
71373
|
+
/** Answers still being asked, by connection, so messages sent meanwhile wait for them. */
|
|
71374
|
+
_canChatAnswers = /* @__PURE__ */ new Map();
|
|
71375
|
+
/**
|
|
71376
|
+
* Asks `canChat` for a connection. A no marks it readonly, which outlives
|
|
71377
|
+
* hibernation and the user's token.
|
|
71378
|
+
*/
|
|
71379
|
+
async _askCanChat(connection) {
|
|
71380
|
+
const answer = Promise.resolve().then(() => this.canChat(this.identity.userContext())).catch((error) => {
|
|
71381
|
+
logOperationalError("agent.can-chat.failed", error, this._logContext());
|
|
71382
|
+
return false;
|
|
71383
|
+
});
|
|
71384
|
+
this._canChatAnswers.set(connection.id, answer);
|
|
71385
|
+
const canChat = await answer;
|
|
71386
|
+
if (!canChat) this.setConnectionReadonly(connection, true);
|
|
71387
|
+
this._canChatAnswers.delete(connection.id);
|
|
71388
|
+
return canChat;
|
|
71389
|
+
}
|
|
71390
|
+
/** Whether the connection can chat. Calls from the server, without one, can. */
|
|
71391
|
+
async _canChat(connection = getCurrentAgent$1().connection) {
|
|
71392
|
+
if (!connection) return true;
|
|
71393
|
+
return await this._canChatAnswers.get(connection.id) ?? !this.isConnectionReadonly(connection);
|
|
71394
|
+
}
|
|
71395
|
+
/** Think stores a message before any hook runs, so it's refused before Think sees it. */
|
|
71396
|
+
_refuseChatMessages() {
|
|
71397
|
+
const onMessage = this.onMessage.bind(this);
|
|
71398
|
+
this.onMessage = async (connection, message) => {
|
|
71399
|
+
const event = typeof message === "string" ? parseProtocolMessage(message) : null;
|
|
71400
|
+
if (!((event?.type === "chat-request" || event?.type === "tool-approval" || event?.type === "tool-result" && event.autoContinue === true) && !this._cf_connectionTargetsSubAgent(connection) && !await this._canChat(connection))) return onMessage(connection, message);
|
|
71401
|
+
connection.send(JSON.stringify({
|
|
71402
|
+
type: CHAT_MESSAGE_TYPES.CHAT_MESSAGES,
|
|
71403
|
+
messages: this.messages
|
|
71404
|
+
}));
|
|
71405
|
+
if (event.type === "chat-request") connection.send(JSON.stringify({
|
|
71406
|
+
type: CHAT_MESSAGE_TYPES.USE_CHAT_RESPONSE,
|
|
71407
|
+
id: event.id,
|
|
71408
|
+
body: CHAT_REFUSED,
|
|
71409
|
+
done: true,
|
|
71410
|
+
error: true
|
|
71411
|
+
}));
|
|
71412
|
+
};
|
|
71340
71413
|
}
|
|
71341
71414
|
_turn = {
|
|
71342
71415
|
inputTools: {},
|
|
@@ -71518,11 +71591,13 @@ var Agent = class Agent extends Think {
|
|
|
71518
71591
|
}
|
|
71519
71592
|
/** `all` also approves the tool call's later approvals, so it doesn't stop again. */
|
|
71520
71593
|
async approveExecution(executionId, options) {
|
|
71594
|
+
if (!await this._canChat()) throw new Error(CHAT_REFUSED);
|
|
71521
71595
|
const answer = await this._toolApprovals.answer(executionId, true, { all: options?.all });
|
|
71522
71596
|
if (answer) return answer;
|
|
71523
71597
|
return super.approveExecution(executionId);
|
|
71524
71598
|
}
|
|
71525
71599
|
async rejectExecution(executionId, reason, options) {
|
|
71600
|
+
if (!await this._canChat()) throw new Error(CHAT_REFUSED);
|
|
71526
71601
|
const answer = await this._toolApprovals.answer(executionId, false, { autoContinue: options?.autoContinue });
|
|
71527
71602
|
if (answer) return answer;
|
|
71528
71603
|
return super.rejectExecution(executionId, reason, options);
|
|
@@ -72072,7 +72147,10 @@ var Agent = class Agent extends Think {
|
|
|
72072
72147
|
for (const source of sources) try {
|
|
72073
72148
|
for (const descriptor of await source.list()) if (!byName.has(descriptor.name)) byName.set(descriptor.name, source);
|
|
72074
72149
|
} catch (error) {
|
|
72075
|
-
|
|
72150
|
+
logOperationalError("agent.skills.source.failed", error, {
|
|
72151
|
+
...this._logContext(),
|
|
72152
|
+
attributes: { skillSource: source.id }
|
|
72153
|
+
});
|
|
72076
72154
|
break;
|
|
72077
72155
|
}
|
|
72078
72156
|
return byName;
|
|
@@ -72352,7 +72430,7 @@ function ensureChatsTableExists(sql) {
|
|
|
72352
72430
|
ensureChatsTitleSetByUserColumnExists(sql);
|
|
72353
72431
|
ensureChatMessageFeedbackTableExists(sql);
|
|
72354
72432
|
} catch (error) {
|
|
72355
|
-
|
|
72433
|
+
logOperationalError("agent.chats.table.failed", error);
|
|
72356
72434
|
}
|
|
72357
72435
|
}
|
|
72358
72436
|
function ensureChatsFeedbackColumnsExist(sql) {
|
|
@@ -72446,8 +72524,12 @@ function chatSummaryInput(messages) {
|
|
|
72446
72524
|
recentMessages: messages.slice(-20)
|
|
72447
72525
|
};
|
|
72448
72526
|
}
|
|
72449
|
-
async function summariseChatWithAI(sql, durableObjectName, { completedTurns, recentMessages }, model) {
|
|
72527
|
+
async function summariseChatWithAI(sql, durableObjectName, { completedTurns, recentMessages }, model, logContext = {}) {
|
|
72450
72528
|
const chat = getChat(sql, durableObjectName);
|
|
72529
|
+
const failureContext = {
|
|
72530
|
+
...logContext,
|
|
72531
|
+
attributes: { chatName: durableObjectName }
|
|
72532
|
+
};
|
|
72451
72533
|
if (!(!chat || !chat.title || isChatSummaryDue(completedTurns))) return;
|
|
72452
72534
|
let systemPrompt = `
|
|
72453
72535
|
You are a helpful assistant that summarises chats.
|
|
@@ -72480,7 +72562,7 @@ async function summariseChatWithAI(sql, durableObjectName, { completedTurns, rec
|
|
|
72480
72562
|
}) })
|
|
72481
72563
|
});
|
|
72482
72564
|
if (!title || !summary) {
|
|
72483
|
-
|
|
72565
|
+
logOperationalError("assistant.chat.summary.failed", /* @__PURE__ */ new Error("The model gave no title or summary."), failureContext);
|
|
72484
72566
|
return;
|
|
72485
72567
|
}
|
|
72486
72568
|
sql`UPDATE chats
|
|
@@ -72490,10 +72572,7 @@ async function summariseChatWithAI(sql, durableObjectName, { completedTurns, rec
|
|
|
72490
72572
|
WHERE durable_object_name = ${durableObjectName}`;
|
|
72491
72573
|
console.info("[Assistant] Generated chat summary", { durableObjectName });
|
|
72492
72574
|
} catch (error) {
|
|
72493
|
-
|
|
72494
|
-
durableObjectName,
|
|
72495
|
-
error
|
|
72496
|
-
});
|
|
72575
|
+
logOperationalError("assistant.chat.summary.failed", error, failureContext);
|
|
72497
72576
|
}
|
|
72498
72577
|
}
|
|
72499
72578
|
const DELETE_CHAT_CALLBACK = "deleteChatCallback";
|
|
@@ -72778,7 +72857,7 @@ var Assistant = class extends Agent$1 {
|
|
|
72778
72857
|
async recordChatTurn(durableObjectName, summaryInput) {
|
|
72779
72858
|
touchChat(this.sql.bind(this), durableObjectName);
|
|
72780
72859
|
this.keepAliveWhile(async () => {
|
|
72781
|
-
await Promise.all([summaryInput && summariseChatWithAI(this.sql.bind(this), durableObjectName, summaryInput, this.fastModel), this.scheduleChatForAutoDeletion(durableObjectName).catch((error) => {
|
|
72860
|
+
await Promise.all([summaryInput && summariseChatWithAI(this.sql.bind(this), durableObjectName, summaryInput, this.fastModel, this._logContext()), this.scheduleChatForAutoDeletion(durableObjectName).catch((error) => {
|
|
72782
72861
|
logOperationalError("assistant.chat.reschedule.failed", error, {
|
|
72783
72862
|
agentName: this.constructor.name,
|
|
72784
72863
|
agentClass: this.constructor.name,
|
|
@@ -72878,9 +72957,9 @@ var Assistant = class extends Agent$1 {
|
|
|
72878
72957
|
negativeFeedbackCount: chat.negative_feedback_count
|
|
72879
72958
|
});
|
|
72880
72959
|
} catch (error) {
|
|
72881
|
-
|
|
72882
|
-
|
|
72883
|
-
|
|
72960
|
+
logOperationalError("assistant.chat.sync.failed", error, {
|
|
72961
|
+
...this._logContext(),
|
|
72962
|
+
attributes: { chatName: durableObjectName }
|
|
72884
72963
|
});
|
|
72885
72964
|
}
|
|
72886
72965
|
}
|
|
@@ -72888,9 +72967,9 @@ var Assistant = class extends Agent$1 {
|
|
|
72888
72967
|
try {
|
|
72889
72968
|
await deleteGlobalChat(this.env.AGENTS_DB, this.constructor.name, this.name, durableObjectName);
|
|
72890
72969
|
} catch (error) {
|
|
72891
|
-
|
|
72892
|
-
|
|
72893
|
-
|
|
72970
|
+
logOperationalError("assistant.chat.unlist.failed", error, {
|
|
72971
|
+
...this._logContext(),
|
|
72972
|
+
attributes: { chatName: durableObjectName }
|
|
72894
72973
|
});
|
|
72895
72974
|
}
|
|
72896
72975
|
}
|
|
@@ -73154,7 +73233,7 @@ function ensureFeedbackTableExists(sql) {
|
|
|
73154
73233
|
PRIMARY KEY (message_id)
|
|
73155
73234
|
)`;
|
|
73156
73235
|
} catch (error) {
|
|
73157
|
-
|
|
73236
|
+
logOperationalError("agent.feedback.table.failed", error);
|
|
73158
73237
|
}
|
|
73159
73238
|
}
|
|
73160
73239
|
const MESSAGE_FEEDBACK_COMMENT_LIMIT = 2e3;
|
|
@@ -73185,7 +73264,7 @@ function submitMessageFeedback(sql, messageId, rating, comment, now = /* @__PURE
|
|
|
73185
73264
|
comment = excluded.comment,
|
|
73186
73265
|
updated_at = excluded.updated_at`;
|
|
73187
73266
|
} catch (error) {
|
|
73188
|
-
|
|
73267
|
+
logOperationalError("agent.feedback.submit.failed", error, { attributes: { messageId } });
|
|
73189
73268
|
}
|
|
73190
73269
|
}
|
|
73191
73270
|
function clearMessageFeedback(sql) {
|
|
@@ -73432,7 +73511,7 @@ var ChatAgent = class extends Agent {
|
|
|
73432
73511
|
};
|
|
73433
73512
|
}
|
|
73434
73513
|
} catch (error) {
|
|
73435
|
-
|
|
73514
|
+
logOperationalError("agent.compaction.failed", error, this._logContext());
|
|
73436
73515
|
}
|
|
73437
73516
|
return config;
|
|
73438
73517
|
}
|
|
@@ -73499,6 +73578,10 @@ var ChatAgent = class extends Agent {
|
|
|
73499
73578
|
* The answer is the reply's text, or its JSON with `outputSchema`.
|
|
73500
73579
|
*/
|
|
73501
73580
|
async run(input, body) {
|
|
73581
|
+
if (!await this._canChat()) return {
|
|
73582
|
+
status: "error",
|
|
73583
|
+
error: CHAT_REFUSED
|
|
73584
|
+
};
|
|
73502
73585
|
const { inputSchema = z.string() } = await this.getAgentConfig(this.createToolContextForCurrentTurn(body));
|
|
73503
73586
|
const check = checkInputValue(inputSchema, input);
|
|
73504
73587
|
if (!check.success) return {
|
|
@@ -73580,9 +73663,7 @@ var ChatAgent = class extends Agent {
|
|
|
73580
73663
|
await parent.recordChatFeedback(this.name, messageId, rating);
|
|
73581
73664
|
} catch (error) {
|
|
73582
73665
|
logOperationalError("agent.feedback.summary.failed", error, {
|
|
73583
|
-
|
|
73584
|
-
agentClass: this.constructor.name,
|
|
73585
|
-
durableObjectName: this.name,
|
|
73666
|
+
...this._logContext(),
|
|
73586
73667
|
attributes: { messageId }
|
|
73587
73668
|
});
|
|
73588
73669
|
}
|