@convex-dev/agent 0.1.8-alpha.0 → 0.1.8-alpha.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 +2 -0
- package/dist/commonjs/client/index.d.ts +65 -51
- package/dist/commonjs/client/index.d.ts.map +1 -1
- package/dist/commonjs/client/index.js +70 -4
- package/dist/commonjs/client/index.js.map +1 -1
- package/dist/commonjs/component/_generated/api.d.ts +235 -0
- package/dist/commonjs/component/messages.d.ts +361 -155
- package/dist/commonjs/component/messages.d.ts.map +1 -1
- package/dist/commonjs/component/messages.js +25 -0
- package/dist/commonjs/component/messages.js.map +1 -1
- package/dist/commonjs/component/schema.d.ts +670 -670
- package/dist/commonjs/component/streams.d.ts +18 -18
- package/dist/commonjs/component/threads.d.ts +6 -6
- package/dist/commonjs/component/vector/index.d.ts +12 -12
- package/dist/commonjs/component/vector/index.d.ts.map +1 -1
- package/dist/commonjs/component/vector/index.js +4 -0
- package/dist/commonjs/component/vector/index.js.map +1 -1
- package/dist/commonjs/component/vector/tables.d.ts +6 -6
- package/dist/commonjs/react/index.d.ts.map +1 -1
- package/dist/commonjs/react/index.js +1 -1
- package/dist/commonjs/react/index.js.map +1 -1
- package/dist/commonjs/validators.d.ts +161 -161
- package/dist/commonjs.tsbuildinfo +1 -1
- package/dist/esm/client/index.d.ts +31 -17
- package/dist/esm/client/index.d.ts.map +1 -1
- package/dist/esm/client/index.js +70 -4
- package/dist/esm/client/index.js.map +1 -1
- package/dist/esm/component/_generated/api.d.ts +235 -0
- package/dist/esm/component/messages.d.ts +233 -27
- package/dist/esm/component/messages.d.ts.map +1 -1
- package/dist/esm/component/messages.js +25 -0
- package/dist/esm/component/messages.js.map +1 -1
- package/dist/esm/component/schema.d.ts +48 -48
- package/dist/esm/component/threads.d.ts +8 -8
- package/dist/esm/component/vector/index.d.ts.map +1 -1
- package/dist/esm/component/vector/index.js +4 -0
- package/dist/esm/component/vector/index.js.map +1 -1
- package/dist/esm/react/index.d.ts.map +1 -1
- package/dist/esm/react/index.js +1 -1
- package/dist/esm/react/index.js.map +1 -1
- package/dist/esm/validators.d.ts +19 -19
- package/dist/esm.tsbuildinfo +1 -1
- package/package.json +4 -5
- package/src/client/index.ts +94 -4
- package/src/client/setup.test.ts +2 -2
- package/src/component/_generated/api.d.ts +235 -0
- package/src/component/messages.test.ts +140 -0
- package/src/component/messages.ts +30 -0
- package/src/component/vector/index.ts +4 -0
- package/src/react/index.ts +1 -2
- package/dist/commonjs/react/usePaginatedQuery.d.ts +0 -241
- package/dist/commonjs/react/usePaginatedQuery.d.ts.map +0 -1
- package/dist/commonjs/react/usePaginatedQuery.js +0 -627
- package/dist/commonjs/react/usePaginatedQuery.js.map +0 -1
- package/dist/esm/react/usePaginatedQuery.d.ts +0 -241
- package/dist/esm/react/usePaginatedQuery.d.ts.map +0 -1
- package/dist/esm/react/usePaginatedQuery.js +0 -627
- package/dist/esm/react/usePaginatedQuery.js.map +0 -1
- package/react/package.json +0 -5
- package/src/react/usePaginatedQuery.ts +0 -901
package/package.json
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"email": "support@convex.dev",
|
|
8
8
|
"url": "https://github.com/get-convex/agent/issues"
|
|
9
9
|
},
|
|
10
|
-
"version": "0.1.8-alpha.
|
|
10
|
+
"version": "0.1.8-alpha.1",
|
|
11
11
|
"license": "Apache-2.0",
|
|
12
12
|
"keywords": [
|
|
13
13
|
"convex",
|
|
@@ -39,8 +39,7 @@
|
|
|
39
39
|
},
|
|
40
40
|
"files": [
|
|
41
41
|
"dist",
|
|
42
|
-
"src"
|
|
43
|
-
"react"
|
|
42
|
+
"src"
|
|
44
43
|
],
|
|
45
44
|
"exports": {
|
|
46
45
|
"./package.json": "./package.json",
|
|
@@ -91,7 +90,7 @@
|
|
|
91
90
|
"peerDependencies": {
|
|
92
91
|
"ai": "^4.3.16",
|
|
93
92
|
"convex": "^1.23.0",
|
|
94
|
-
"convex-helpers": "^0.1.
|
|
93
|
+
"convex-helpers": "^0.1.93",
|
|
95
94
|
"react": "^18.3.1 || ^19.0.0"
|
|
96
95
|
},
|
|
97
96
|
"peerDependenciesMeta": {
|
|
@@ -106,7 +105,7 @@
|
|
|
106
105
|
"@types/react": "^19.1.1",
|
|
107
106
|
"chokidar-cli": "^3.0.0",
|
|
108
107
|
"convex": "^1.24.8",
|
|
109
|
-
"convex-helpers": "^0.1.
|
|
108
|
+
"convex-helpers": "^0.1.93",
|
|
110
109
|
"convex-test": "^0.0.37",
|
|
111
110
|
"cpy-cli": "^5.0.0",
|
|
112
111
|
"eslint": "^9.24.0",
|
package/src/client/index.ts
CHANGED
|
@@ -2,11 +2,14 @@ import type { EmbeddingModelV1, LanguageModelV1 } from "@ai-sdk/provider";
|
|
|
2
2
|
import type {
|
|
3
3
|
CoreMessage,
|
|
4
4
|
DeepPartial,
|
|
5
|
+
FilePart,
|
|
5
6
|
GenerateObjectResult,
|
|
6
7
|
GenerateTextResult,
|
|
8
|
+
ImagePart,
|
|
7
9
|
StepResult,
|
|
8
10
|
StreamObjectResult,
|
|
9
11
|
StreamTextResult,
|
|
12
|
+
TextPart,
|
|
10
13
|
ToolSet,
|
|
11
14
|
} from "ai";
|
|
12
15
|
import { generateObject, generateText, streamObject, streamText } from "ai";
|
|
@@ -1495,6 +1498,17 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
1495
1498
|
order = saved.messages.at(-1)?.order;
|
|
1496
1499
|
stepOrder = saved.messages.at(-1)?.stepOrder;
|
|
1497
1500
|
}
|
|
1501
|
+
|
|
1502
|
+
let processedMessages = [
|
|
1503
|
+
...contextMessages.map((m) => deserializeMessage(m.message!)),
|
|
1504
|
+
...messages,
|
|
1505
|
+
];
|
|
1506
|
+
|
|
1507
|
+
// Process messages to inline localhost files (if not, file urls pointing to localhost will be sent to LLM providers)
|
|
1508
|
+
if (process.env.CONVEX_CLOUD_URL?.startsWith("http://127.0.0.1")) {
|
|
1509
|
+
processedMessages = await this._inlineMessagesFiles(processedMessages);
|
|
1510
|
+
}
|
|
1511
|
+
|
|
1498
1512
|
const { prompt: _, model, ...rest } = args;
|
|
1499
1513
|
return {
|
|
1500
1514
|
args: {
|
|
@@ -1502,10 +1516,7 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
1502
1516
|
maxRetries: args.maxRetries ?? this.options.maxRetries,
|
|
1503
1517
|
model: model ?? this.options.chat,
|
|
1504
1518
|
system: args.system ?? this.options.instructions,
|
|
1505
|
-
messages:
|
|
1506
|
-
...contextMessages.map((m) => deserializeMessage(m.message!)),
|
|
1507
|
-
...messages,
|
|
1508
|
-
],
|
|
1519
|
+
messages: processedMessages,
|
|
1509
1520
|
} as T & { model: LanguageModelV1 },
|
|
1510
1521
|
userId,
|
|
1511
1522
|
messageId,
|
|
@@ -1608,6 +1619,85 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
1608
1619
|
return { embeddings: result.embeddings };
|
|
1609
1620
|
}
|
|
1610
1621
|
|
|
1622
|
+
/**
|
|
1623
|
+
* Process messages to inline file and image URLs that point to localhost
|
|
1624
|
+
* by converting them to base64. This solves the problem of LLMs not being
|
|
1625
|
+
* able to access localhost URLs.
|
|
1626
|
+
*/
|
|
1627
|
+
private async _inlineMessagesFiles(
|
|
1628
|
+
messages: CoreMessage[]
|
|
1629
|
+
): Promise<CoreMessage[]> {
|
|
1630
|
+
// Process each message to convert localhost URLs to base64
|
|
1631
|
+
return Promise.all(
|
|
1632
|
+
messages.map(async (message): Promise<CoreMessage> => {
|
|
1633
|
+
if (
|
|
1634
|
+
message.role !== "user" ||
|
|
1635
|
+
typeof message.content === "string" ||
|
|
1636
|
+
!Array.isArray(message.content)
|
|
1637
|
+
) {
|
|
1638
|
+
return message;
|
|
1639
|
+
}
|
|
1640
|
+
|
|
1641
|
+
const processedContent = await Promise.all(
|
|
1642
|
+
message.content.map(async (part) => {
|
|
1643
|
+
if (part.type === "image" && part.image instanceof URL) {
|
|
1644
|
+
if (this._isLocalhostUrl(part.image)) {
|
|
1645
|
+
const imageData = await this._downloadFile(part.image);
|
|
1646
|
+
return {
|
|
1647
|
+
...part,
|
|
1648
|
+
image: imageData,
|
|
1649
|
+
} as ImagePart;
|
|
1650
|
+
}
|
|
1651
|
+
}
|
|
1652
|
+
|
|
1653
|
+
// Handle file parts
|
|
1654
|
+
if (part.type === "file" && part.data instanceof URL) {
|
|
1655
|
+
if (this._isLocalhostUrl(part.data)) {
|
|
1656
|
+
const fileData = await this._downloadFile(part.data);
|
|
1657
|
+
return {
|
|
1658
|
+
...part,
|
|
1659
|
+
data: fileData,
|
|
1660
|
+
} as FilePart;
|
|
1661
|
+
}
|
|
1662
|
+
}
|
|
1663
|
+
|
|
1664
|
+
return part;
|
|
1665
|
+
})
|
|
1666
|
+
);
|
|
1667
|
+
|
|
1668
|
+
return {
|
|
1669
|
+
...message,
|
|
1670
|
+
content: processedContent,
|
|
1671
|
+
};
|
|
1672
|
+
})
|
|
1673
|
+
);
|
|
1674
|
+
}
|
|
1675
|
+
|
|
1676
|
+
/**
|
|
1677
|
+
* Check if a URL points to localhost
|
|
1678
|
+
*/
|
|
1679
|
+
private _isLocalhostUrl(url: URL): boolean {
|
|
1680
|
+
return (
|
|
1681
|
+
url.hostname === "localhost" ||
|
|
1682
|
+
url.hostname === "127.0.0.1" ||
|
|
1683
|
+
url.hostname === "::1" ||
|
|
1684
|
+
url.hostname === "0.0.0.0"
|
|
1685
|
+
);
|
|
1686
|
+
}
|
|
1687
|
+
|
|
1688
|
+
/**
|
|
1689
|
+
* Download a file from a URL
|
|
1690
|
+
*/
|
|
1691
|
+
private async _downloadFile(url: URL): Promise<ArrayBuffer> {
|
|
1692
|
+
// Fetch the file
|
|
1693
|
+
const response = await fetch(url);
|
|
1694
|
+
if (!response.ok) {
|
|
1695
|
+
throw new Error(`Failed to fetch ${url}: ${response.statusText}`);
|
|
1696
|
+
}
|
|
1697
|
+
|
|
1698
|
+
return await response.arrayBuffer();
|
|
1699
|
+
}
|
|
1700
|
+
|
|
1611
1701
|
/**
|
|
1612
1702
|
* WORKFLOW UTILITIES
|
|
1613
1703
|
*/
|
package/src/client/setup.test.ts
CHANGED
|
@@ -3,13 +3,13 @@ import { test } from "vitest";
|
|
|
3
3
|
import { convexTest } from "convex-test";
|
|
4
4
|
export const modules = import.meta.glob("./**/*.*s");
|
|
5
5
|
|
|
6
|
-
import componentSchema from "../component/schema";
|
|
6
|
+
import componentSchema from "../component/schema.js";
|
|
7
7
|
import {
|
|
8
8
|
defineSchema,
|
|
9
9
|
type GenericSchema,
|
|
10
10
|
type SchemaDefinition,
|
|
11
11
|
} from "convex/server";
|
|
12
|
-
import { type AgentComponent } from ".";
|
|
12
|
+
import { type AgentComponent } from "./index.js";
|
|
13
13
|
import { componentsGeneric } from "convex/server";
|
|
14
14
|
export { componentSchema };
|
|
15
15
|
export const componentModules = import.meta.glob("../component/**/*.ts");
|
|
@@ -1177,6 +1177,241 @@ export type Mounts = {
|
|
|
1177
1177
|
>;
|
|
1178
1178
|
}>
|
|
1179
1179
|
>;
|
|
1180
|
+
updateMessage: FunctionReference<
|
|
1181
|
+
"mutation",
|
|
1182
|
+
"public",
|
|
1183
|
+
{
|
|
1184
|
+
messageId: string;
|
|
1185
|
+
patch: {
|
|
1186
|
+
error?: string;
|
|
1187
|
+
message?:
|
|
1188
|
+
| {
|
|
1189
|
+
content:
|
|
1190
|
+
| string
|
|
1191
|
+
| Array<
|
|
1192
|
+
| {
|
|
1193
|
+
providerOptions?: Record<string, Record<string, any>>;
|
|
1194
|
+
text: string;
|
|
1195
|
+
type: "text";
|
|
1196
|
+
}
|
|
1197
|
+
| {
|
|
1198
|
+
image: string | ArrayBuffer;
|
|
1199
|
+
mimeType?: string;
|
|
1200
|
+
providerOptions?: Record<string, Record<string, any>>;
|
|
1201
|
+
type: "image";
|
|
1202
|
+
}
|
|
1203
|
+
| {
|
|
1204
|
+
data: string | ArrayBuffer;
|
|
1205
|
+
filename?: string;
|
|
1206
|
+
mimeType: string;
|
|
1207
|
+
providerOptions?: Record<string, Record<string, any>>;
|
|
1208
|
+
type: "file";
|
|
1209
|
+
}
|
|
1210
|
+
>;
|
|
1211
|
+
providerOptions?: Record<string, Record<string, any>>;
|
|
1212
|
+
role: "user";
|
|
1213
|
+
}
|
|
1214
|
+
| {
|
|
1215
|
+
content:
|
|
1216
|
+
| string
|
|
1217
|
+
| Array<
|
|
1218
|
+
| {
|
|
1219
|
+
providerOptions?: Record<string, Record<string, any>>;
|
|
1220
|
+
text: string;
|
|
1221
|
+
type: "text";
|
|
1222
|
+
}
|
|
1223
|
+
| {
|
|
1224
|
+
data: string | ArrayBuffer;
|
|
1225
|
+
filename?: string;
|
|
1226
|
+
mimeType: string;
|
|
1227
|
+
providerOptions?: Record<string, Record<string, any>>;
|
|
1228
|
+
type: "file";
|
|
1229
|
+
}
|
|
1230
|
+
| {
|
|
1231
|
+
providerOptions?: Record<string, Record<string, any>>;
|
|
1232
|
+
signature?: string;
|
|
1233
|
+
text: string;
|
|
1234
|
+
type: "reasoning";
|
|
1235
|
+
}
|
|
1236
|
+
| {
|
|
1237
|
+
data: string;
|
|
1238
|
+
providerOptions?: Record<string, Record<string, any>>;
|
|
1239
|
+
type: "redacted-reasoning";
|
|
1240
|
+
}
|
|
1241
|
+
| {
|
|
1242
|
+
args: any;
|
|
1243
|
+
providerOptions?: Record<string, Record<string, any>>;
|
|
1244
|
+
toolCallId: string;
|
|
1245
|
+
toolName: string;
|
|
1246
|
+
type: "tool-call";
|
|
1247
|
+
}
|
|
1248
|
+
>;
|
|
1249
|
+
providerOptions?: Record<string, Record<string, any>>;
|
|
1250
|
+
role: "assistant";
|
|
1251
|
+
}
|
|
1252
|
+
| {
|
|
1253
|
+
content: Array<{
|
|
1254
|
+
args?: any;
|
|
1255
|
+
experimental_content?: Array<
|
|
1256
|
+
| { text: string; type: "text" }
|
|
1257
|
+
| { data: string; mimeType?: string; type: "image" }
|
|
1258
|
+
>;
|
|
1259
|
+
isError?: boolean;
|
|
1260
|
+
providerOptions?: Record<string, Record<string, any>>;
|
|
1261
|
+
result: any;
|
|
1262
|
+
toolCallId: string;
|
|
1263
|
+
toolName: string;
|
|
1264
|
+
type: "tool-result";
|
|
1265
|
+
}>;
|
|
1266
|
+
providerOptions?: Record<string, Record<string, any>>;
|
|
1267
|
+
role: "tool";
|
|
1268
|
+
}
|
|
1269
|
+
| {
|
|
1270
|
+
content: string;
|
|
1271
|
+
providerOptions?: Record<string, Record<string, any>>;
|
|
1272
|
+
role: "system";
|
|
1273
|
+
};
|
|
1274
|
+
status?: "pending" | "success" | "failed";
|
|
1275
|
+
};
|
|
1276
|
+
},
|
|
1277
|
+
{
|
|
1278
|
+
_creationTime: number;
|
|
1279
|
+
_id: string;
|
|
1280
|
+
agentName?: string;
|
|
1281
|
+
embeddingId?: string;
|
|
1282
|
+
error?: string;
|
|
1283
|
+
fileIds?: Array<string>;
|
|
1284
|
+
finishReason?:
|
|
1285
|
+
| "stop"
|
|
1286
|
+
| "length"
|
|
1287
|
+
| "content-filter"
|
|
1288
|
+
| "tool-calls"
|
|
1289
|
+
| "error"
|
|
1290
|
+
| "other"
|
|
1291
|
+
| "unknown";
|
|
1292
|
+
id?: string;
|
|
1293
|
+
message?:
|
|
1294
|
+
| {
|
|
1295
|
+
content:
|
|
1296
|
+
| string
|
|
1297
|
+
| Array<
|
|
1298
|
+
| {
|
|
1299
|
+
providerOptions?: Record<string, Record<string, any>>;
|
|
1300
|
+
text: string;
|
|
1301
|
+
type: "text";
|
|
1302
|
+
}
|
|
1303
|
+
| {
|
|
1304
|
+
image: string | ArrayBuffer;
|
|
1305
|
+
mimeType?: string;
|
|
1306
|
+
providerOptions?: Record<string, Record<string, any>>;
|
|
1307
|
+
type: "image";
|
|
1308
|
+
}
|
|
1309
|
+
| {
|
|
1310
|
+
data: string | ArrayBuffer;
|
|
1311
|
+
filename?: string;
|
|
1312
|
+
mimeType: string;
|
|
1313
|
+
providerOptions?: Record<string, Record<string, any>>;
|
|
1314
|
+
type: "file";
|
|
1315
|
+
}
|
|
1316
|
+
>;
|
|
1317
|
+
providerOptions?: Record<string, Record<string, any>>;
|
|
1318
|
+
role: "user";
|
|
1319
|
+
}
|
|
1320
|
+
| {
|
|
1321
|
+
content:
|
|
1322
|
+
| string
|
|
1323
|
+
| Array<
|
|
1324
|
+
| {
|
|
1325
|
+
providerOptions?: Record<string, Record<string, any>>;
|
|
1326
|
+
text: string;
|
|
1327
|
+
type: "text";
|
|
1328
|
+
}
|
|
1329
|
+
| {
|
|
1330
|
+
data: string | ArrayBuffer;
|
|
1331
|
+
filename?: string;
|
|
1332
|
+
mimeType: string;
|
|
1333
|
+
providerOptions?: Record<string, Record<string, any>>;
|
|
1334
|
+
type: "file";
|
|
1335
|
+
}
|
|
1336
|
+
| {
|
|
1337
|
+
providerOptions?: Record<string, Record<string, any>>;
|
|
1338
|
+
signature?: string;
|
|
1339
|
+
text: string;
|
|
1340
|
+
type: "reasoning";
|
|
1341
|
+
}
|
|
1342
|
+
| {
|
|
1343
|
+
data: string;
|
|
1344
|
+
providerOptions?: Record<string, Record<string, any>>;
|
|
1345
|
+
type: "redacted-reasoning";
|
|
1346
|
+
}
|
|
1347
|
+
| {
|
|
1348
|
+
args: any;
|
|
1349
|
+
providerOptions?: Record<string, Record<string, any>>;
|
|
1350
|
+
toolCallId: string;
|
|
1351
|
+
toolName: string;
|
|
1352
|
+
type: "tool-call";
|
|
1353
|
+
}
|
|
1354
|
+
>;
|
|
1355
|
+
providerOptions?: Record<string, Record<string, any>>;
|
|
1356
|
+
role: "assistant";
|
|
1357
|
+
}
|
|
1358
|
+
| {
|
|
1359
|
+
content: Array<{
|
|
1360
|
+
args?: any;
|
|
1361
|
+
experimental_content?: Array<
|
|
1362
|
+
| { text: string; type: "text" }
|
|
1363
|
+
| { data: string; mimeType?: string; type: "image" }
|
|
1364
|
+
>;
|
|
1365
|
+
isError?: boolean;
|
|
1366
|
+
providerOptions?: Record<string, Record<string, any>>;
|
|
1367
|
+
result: any;
|
|
1368
|
+
toolCallId: string;
|
|
1369
|
+
toolName: string;
|
|
1370
|
+
type: "tool-result";
|
|
1371
|
+
}>;
|
|
1372
|
+
providerOptions?: Record<string, Record<string, any>>;
|
|
1373
|
+
role: "tool";
|
|
1374
|
+
}
|
|
1375
|
+
| {
|
|
1376
|
+
content: string;
|
|
1377
|
+
providerOptions?: Record<string, Record<string, any>>;
|
|
1378
|
+
role: "system";
|
|
1379
|
+
};
|
|
1380
|
+
model?: string;
|
|
1381
|
+
order: number;
|
|
1382
|
+
provider?: string;
|
|
1383
|
+
providerMetadata?: Record<string, Record<string, any>>;
|
|
1384
|
+
providerOptions?: Record<string, Record<string, any>>;
|
|
1385
|
+
reasoning?: string;
|
|
1386
|
+
reasoningDetails?: Array<
|
|
1387
|
+
| { signature?: string; text: string; type: "text" }
|
|
1388
|
+
| { data: string; type: "redacted" }
|
|
1389
|
+
>;
|
|
1390
|
+
sources?: Array<{
|
|
1391
|
+
id: string;
|
|
1392
|
+
providerOptions?: Record<string, Record<string, any>>;
|
|
1393
|
+
sourceType: "url";
|
|
1394
|
+
title?: string;
|
|
1395
|
+
url: string;
|
|
1396
|
+
}>;
|
|
1397
|
+
status: "pending" | "success" | "failed";
|
|
1398
|
+
stepOrder: number;
|
|
1399
|
+
text?: string;
|
|
1400
|
+
threadId: string;
|
|
1401
|
+
tool: boolean;
|
|
1402
|
+
usage?: {
|
|
1403
|
+
completionTokens: number;
|
|
1404
|
+
promptTokens: number;
|
|
1405
|
+
totalTokens: number;
|
|
1406
|
+
};
|
|
1407
|
+
userId?: string;
|
|
1408
|
+
warnings?: Array<
|
|
1409
|
+
| { details?: string; setting: string; type: "unsupported-setting" }
|
|
1410
|
+
| { details?: string; tool: any; type: "unsupported-tool" }
|
|
1411
|
+
| { message: string; type: "other" }
|
|
1412
|
+
>;
|
|
1413
|
+
}
|
|
1414
|
+
>;
|
|
1180
1415
|
};
|
|
1181
1416
|
streams: {
|
|
1182
1417
|
addDelta: FunctionReference<
|
|
@@ -141,4 +141,144 @@ describe("agent", () => {
|
|
|
141
141
|
stepOrder: 1,
|
|
142
142
|
});
|
|
143
143
|
});
|
|
144
|
+
|
|
145
|
+
test("updateMessage updates message content", async () => {
|
|
146
|
+
const t = convexTest(schema, modules);
|
|
147
|
+
const thread = await t.mutation(api.threads.createThread, {
|
|
148
|
+
userId: "test",
|
|
149
|
+
});
|
|
150
|
+
const { messages } = await t.mutation(api.messages.addMessages, {
|
|
151
|
+
threadId: thread._id as Id<"threads">,
|
|
152
|
+
messages: [{ message: { role: "user", content: "hello" } }],
|
|
153
|
+
});
|
|
154
|
+
const messageId = messages[0]._id as Id<"messages">;
|
|
155
|
+
|
|
156
|
+
const updatedMessage = await t.mutation(api.messages.updateMessage, {
|
|
157
|
+
messageId,
|
|
158
|
+
patch: {
|
|
159
|
+
message: { role: "user", content: "updated content" },
|
|
160
|
+
},
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
expect(updatedMessage.message).toEqual({
|
|
164
|
+
role: "user",
|
|
165
|
+
content: "updated content",
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
test("updateMessage updates message status", async () => {
|
|
170
|
+
const t = convexTest(schema, modules);
|
|
171
|
+
const thread = await t.mutation(api.threads.createThread, {
|
|
172
|
+
userId: "test",
|
|
173
|
+
});
|
|
174
|
+
const { messages } = await t.mutation(api.messages.addMessages, {
|
|
175
|
+
threadId: thread._id as Id<"threads">,
|
|
176
|
+
messages: [{ message: { role: "assistant", content: "hello" } }],
|
|
177
|
+
pending: true,
|
|
178
|
+
});
|
|
179
|
+
const messageId = messages[0]._id as Id<"messages">;
|
|
180
|
+
|
|
181
|
+
// Initial status should be pending
|
|
182
|
+
expect(messages[0].status).toBe("pending");
|
|
183
|
+
|
|
184
|
+
// Update to success
|
|
185
|
+
const updatedMessage = await t.mutation(api.messages.updateMessage, {
|
|
186
|
+
messageId,
|
|
187
|
+
patch: {
|
|
188
|
+
status: "success",
|
|
189
|
+
},
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
expect(updatedMessage.status).toBe("success");
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
test("updateMessage updates error field", async () => {
|
|
196
|
+
const t = convexTest(schema, modules);
|
|
197
|
+
const thread = await t.mutation(api.threads.createThread, {
|
|
198
|
+
userId: "test",
|
|
199
|
+
});
|
|
200
|
+
const { messages } = await t.mutation(api.messages.addMessages, {
|
|
201
|
+
threadId: thread._id as Id<"threads">,
|
|
202
|
+
messages: [{ message: { role: "assistant", content: "hello" } }],
|
|
203
|
+
pending: true,
|
|
204
|
+
});
|
|
205
|
+
const messageId = messages[0]._id as Id<"messages">;
|
|
206
|
+
|
|
207
|
+
const updatedMessage = await t.mutation(api.messages.updateMessage, {
|
|
208
|
+
messageId,
|
|
209
|
+
patch: {
|
|
210
|
+
status: "failed",
|
|
211
|
+
error: "Something went wrong",
|
|
212
|
+
},
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
expect(updatedMessage.status).toBe("failed");
|
|
216
|
+
expect(updatedMessage.error).toBe("Something went wrong");
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
test("updateMessage correctly updates tool messages", async () => {
|
|
220
|
+
const t = convexTest(schema, modules);
|
|
221
|
+
const thread = await t.mutation(api.threads.createThread, {
|
|
222
|
+
userId: "test",
|
|
223
|
+
});
|
|
224
|
+
const { messages } = await t.mutation(api.messages.addMessages, {
|
|
225
|
+
threadId: thread._id as Id<"threads">,
|
|
226
|
+
messages: [{
|
|
227
|
+
message: {
|
|
228
|
+
role: "assistant",
|
|
229
|
+
content: [
|
|
230
|
+
{
|
|
231
|
+
type: "tool-call",
|
|
232
|
+
args: { a: 1 },
|
|
233
|
+
toolCallId: "1",
|
|
234
|
+
toolName: "tool",
|
|
235
|
+
},
|
|
236
|
+
],
|
|
237
|
+
},
|
|
238
|
+
}],
|
|
239
|
+
});
|
|
240
|
+
const messageId = messages[0]._id as Id<"messages">;
|
|
241
|
+
|
|
242
|
+
const updatedMessage = await t.mutation(api.messages.updateMessage, {
|
|
243
|
+
messageId,
|
|
244
|
+
patch: {
|
|
245
|
+
message: {
|
|
246
|
+
role: "assistant",
|
|
247
|
+
content: [
|
|
248
|
+
{
|
|
249
|
+
type: "tool-call",
|
|
250
|
+
args: { a: 2, b: 3 },
|
|
251
|
+
toolCallId: "1",
|
|
252
|
+
toolName: "tool",
|
|
253
|
+
},
|
|
254
|
+
],
|
|
255
|
+
},
|
|
256
|
+
},
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
expect(updatedMessage.message).toEqual({
|
|
260
|
+
role: "assistant",
|
|
261
|
+
content: [
|
|
262
|
+
{
|
|
263
|
+
type: "tool-call",
|
|
264
|
+
args: { a: 2, b: 3 },
|
|
265
|
+
toolCallId: "1",
|
|
266
|
+
toolName: "tool",
|
|
267
|
+
},
|
|
268
|
+
],
|
|
269
|
+
});
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
test("updateMessage throws error for non-existent message", async () => {
|
|
273
|
+
const t = convexTest(schema, modules);
|
|
274
|
+
|
|
275
|
+
await expect(
|
|
276
|
+
t.mutation(api.messages.updateMessage, {
|
|
277
|
+
messageId: "invalidId" as Id<"messages">,
|
|
278
|
+
patch: {
|
|
279
|
+
message: { role: "user", content: "test" },
|
|
280
|
+
},
|
|
281
|
+
})
|
|
282
|
+
).rejects.toThrow();
|
|
283
|
+
});
|
|
144
284
|
});
|
|
@@ -265,6 +265,36 @@ export const commitMessage = mutation({
|
|
|
265
265
|
returns: v.null(),
|
|
266
266
|
handler: commitMessageHandler,
|
|
267
267
|
});
|
|
268
|
+
|
|
269
|
+
export const updateMessage = mutation({
|
|
270
|
+
args: {
|
|
271
|
+
messageId: v.id("messages"),
|
|
272
|
+
patch: v.object({
|
|
273
|
+
message: v.optional(vMessageDoc.fields.message),
|
|
274
|
+
status: v.optional(vMessageStatus),
|
|
275
|
+
error: v.optional(v.string()),
|
|
276
|
+
}),
|
|
277
|
+
},
|
|
278
|
+
returns: vMessageDoc,
|
|
279
|
+
handler: async (ctx, args) => {
|
|
280
|
+
const message = await ctx.db.get(args.messageId);
|
|
281
|
+
assert(message, `Message ${args.messageId} not found`);
|
|
282
|
+
|
|
283
|
+
const patch: Partial<Doc<"messages">> = {
|
|
284
|
+
...args.patch,
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
if (args.patch.message !== undefined) {
|
|
288
|
+
patch.message = args.patch.message;
|
|
289
|
+
patch.tool = isTool(args.patch.message);
|
|
290
|
+
patch.text = extractText(args.patch.message);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
await ctx.db.patch(args.messageId, patch);
|
|
294
|
+
return publicMessage((await ctx.db.get(args.messageId))!);
|
|
295
|
+
},
|
|
296
|
+
});
|
|
297
|
+
|
|
268
298
|
async function commitMessageHandler(
|
|
269
299
|
ctx: MutationCtx,
|
|
270
300
|
{ messageId }: { messageId: Id<"messages"> }
|
|
@@ -172,6 +172,10 @@ export const updateBatch = mutation({
|
|
|
172
172
|
model: v.string(),
|
|
173
173
|
id: vVectorId,
|
|
174
174
|
vector: v.array(v.number()),
|
|
175
|
+
// TODO: support changing the vector length by
|
|
176
|
+
// deleting from one table and inserting into another.
|
|
177
|
+
// However this requires updating all the messages that reference
|
|
178
|
+
// the vector.
|
|
175
179
|
})
|
|
176
180
|
),
|
|
177
181
|
},
|
package/src/react/index.ts
CHANGED
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
import type { ErrorMessage } from "convex-helpers";
|
|
3
3
|
import {
|
|
4
4
|
type PaginatedQueryArgs,
|
|
5
|
-
// usePaginatedQuery,
|
|
6
5
|
type UsePaginatedQueryResult,
|
|
7
6
|
useQuery,
|
|
8
7
|
} from "convex/react";
|
|
9
|
-
import { usePaginatedQuery } from "
|
|
8
|
+
import { usePaginatedQuery } from "convex-helpers/react";
|
|
10
9
|
import type { FunctionArgs } from "convex/server";
|
|
11
10
|
import { useMemo, useState } from "react";
|
|
12
11
|
import type { MessageDoc } from "../client/index.js";
|