@convex-dev/agent 0.0.1-alpha.0 → 0.0.1-alpha.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/README.md +297 -6
- package/dist/commonjs/client/index.d.ts +521 -62
- package/dist/commonjs/client/index.d.ts.map +1 -1
- package/dist/commonjs/client/index.js +230 -118
- package/dist/commonjs/client/index.js.map +1 -1
- package/dist/commonjs/client/types.d.ts +3 -0
- package/dist/commonjs/client/types.d.ts.map +1 -1
- package/dist/commonjs/component/messages.d.ts +22 -17
- package/dist/commonjs/component/messages.d.ts.map +1 -1
- package/dist/commonjs/component/messages.js +107 -47
- package/dist/commonjs/component/messages.js.map +1 -1
- package/dist/commonjs/component/schema.d.ts +16 -12
- package/dist/commonjs/component/schema.d.ts.map +1 -1
- package/dist/commonjs/component/schema.js +10 -3
- package/dist/commonjs/component/schema.js.map +1 -1
- package/dist/commonjs/component/vector/index.d.ts +41 -0
- package/dist/commonjs/component/vector/index.d.ts.map +1 -0
- package/dist/commonjs/component/vector/index.js +120 -0
- package/dist/commonjs/component/vector/index.js.map +1 -0
- package/dist/commonjs/component/vector/tables.d.ts.map +1 -1
- package/dist/commonjs/component/vector/tables.js +4 -2
- package/dist/commonjs/component/vector/tables.js.map +1 -1
- package/dist/commonjs/mapping.d.ts +6 -1
- package/dist/commonjs/mapping.d.ts.map +1 -1
- package/dist/commonjs/mapping.js +25 -0
- package/dist/commonjs/mapping.js.map +1 -1
- package/dist/commonjs/validators.d.ts +1375 -0
- package/dist/commonjs/validators.d.ts.map +1 -1
- package/dist/commonjs/validators.js +27 -0
- package/dist/commonjs/validators.js.map +1 -1
- package/dist/esm/client/index.d.ts +521 -62
- package/dist/esm/client/index.d.ts.map +1 -1
- package/dist/esm/client/index.js +230 -118
- package/dist/esm/client/index.js.map +1 -1
- package/dist/esm/client/types.d.ts +3 -0
- package/dist/esm/client/types.d.ts.map +1 -1
- package/dist/esm/component/messages.d.ts +22 -17
- package/dist/esm/component/messages.d.ts.map +1 -1
- package/dist/esm/component/messages.js +107 -47
- package/dist/esm/component/messages.js.map +1 -1
- package/dist/esm/component/schema.d.ts +16 -12
- package/dist/esm/component/schema.d.ts.map +1 -1
- package/dist/esm/component/schema.js +10 -3
- package/dist/esm/component/schema.js.map +1 -1
- package/dist/esm/component/vector/index.d.ts +41 -0
- package/dist/esm/component/vector/index.d.ts.map +1 -0
- package/dist/esm/component/vector/index.js +120 -0
- package/dist/esm/component/vector/index.js.map +1 -0
- package/dist/esm/component/vector/tables.d.ts.map +1 -1
- package/dist/esm/component/vector/tables.js +4 -2
- package/dist/esm/component/vector/tables.js.map +1 -1
- package/dist/esm/mapping.d.ts +6 -1
- package/dist/esm/mapping.d.ts.map +1 -1
- package/dist/esm/mapping.js +25 -0
- package/dist/esm/mapping.js.map +1 -1
- package/dist/esm/validators.d.ts +1375 -0
- package/dist/esm/validators.d.ts.map +1 -1
- package/dist/esm/validators.js +27 -0
- package/dist/esm/validators.js.map +1 -1
- package/package.json +2 -2
- package/src/client/index.ts +428 -232
- package/src/client/types.ts +4 -0
- package/src/component/_generated/api.d.ts +138 -11
- package/src/component/messages.ts +136 -66
- package/src/component/schema.ts +10 -3
- package/src/component/vector/index.ts +144 -0
- package/src/component/vector/tables.ts +7 -5
- package/src/mapping.ts +46 -11
- package/src/validators.test.ts +9 -0
- package/src/validators.ts +32 -0
package/src/client/types.ts
CHANGED
|
@@ -7,6 +7,10 @@ import {
|
|
|
7
7
|
GenericActionCtx,
|
|
8
8
|
} from "convex/server";
|
|
9
9
|
import { GenericId } from "convex/values";
|
|
10
|
+
import type { Doc } from "../component/_generated/dataModel";
|
|
11
|
+
|
|
12
|
+
export type ChatDoc = OpaqueIds<Doc<"chats">>;
|
|
13
|
+
export type MessageDoc = OpaqueIds<Doc<"messages">>;
|
|
10
14
|
|
|
11
15
|
/* Type utils follow */
|
|
12
16
|
export type RunQueryCtx = {
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
|
|
11
11
|
import type * as lib from "../lib.js";
|
|
12
12
|
import type * as messages from "../messages.js";
|
|
13
|
+
import type * as vector_index from "../vector/index.js";
|
|
13
14
|
import type * as vector_tables from "../vector/tables.js";
|
|
14
15
|
|
|
15
16
|
import type {
|
|
@@ -29,6 +30,7 @@ import type {
|
|
|
29
30
|
declare const fullApi: ApiFromModules<{
|
|
30
31
|
lib: typeof lib;
|
|
31
32
|
messages: typeof messages;
|
|
33
|
+
"vector/index": typeof vector_index;
|
|
32
34
|
"vector/tables": typeof vector_tables;
|
|
33
35
|
}>;
|
|
34
36
|
export type Mounts = {
|
|
@@ -38,7 +40,7 @@ export type Mounts = {
|
|
|
38
40
|
"public",
|
|
39
41
|
{
|
|
40
42
|
agentName?: string;
|
|
41
|
-
chatId
|
|
43
|
+
chatId?: string;
|
|
42
44
|
failPendingSteps?: boolean;
|
|
43
45
|
messages: Array<{
|
|
44
46
|
fileId?: string;
|
|
@@ -145,13 +147,14 @@ export type Mounts = {
|
|
|
145
147
|
parentMessageId?: string;
|
|
146
148
|
pending?: boolean;
|
|
147
149
|
stepId?: string;
|
|
150
|
+
userId?: string;
|
|
148
151
|
},
|
|
149
152
|
{
|
|
150
153
|
messages: Array<{
|
|
151
154
|
_creationTime: number;
|
|
152
155
|
_id: string;
|
|
153
156
|
agentName?: string;
|
|
154
|
-
chatId
|
|
157
|
+
chatId?: string;
|
|
155
158
|
embeddingId?:
|
|
156
159
|
| string
|
|
157
160
|
| string
|
|
@@ -262,7 +265,7 @@ export type Mounts = {
|
|
|
262
265
|
role: "system";
|
|
263
266
|
};
|
|
264
267
|
model?: string;
|
|
265
|
-
order
|
|
268
|
+
order: number;
|
|
266
269
|
status: "pending" | "success" | "failed";
|
|
267
270
|
stepId?: string;
|
|
268
271
|
stepOrder?: number;
|
|
@@ -275,7 +278,7 @@ export type Mounts = {
|
|
|
275
278
|
_creationTime: number;
|
|
276
279
|
_id: string;
|
|
277
280
|
agentName?: string;
|
|
278
|
-
chatId
|
|
281
|
+
chatId?: string;
|
|
279
282
|
embeddingId?:
|
|
280
283
|
| string
|
|
281
284
|
| string
|
|
@@ -386,7 +389,7 @@ export type Mounts = {
|
|
|
386
389
|
role: "system";
|
|
387
390
|
};
|
|
388
391
|
model?: string;
|
|
389
|
-
order
|
|
392
|
+
order: number;
|
|
390
393
|
status: "pending" | "success" | "failed";
|
|
391
394
|
stepId?: string;
|
|
392
395
|
stepOrder?: number;
|
|
@@ -1009,6 +1012,7 @@ export type Mounts = {
|
|
|
1009
1012
|
isTool?: boolean;
|
|
1010
1013
|
limit?: number;
|
|
1011
1014
|
order?: "asc" | "desc";
|
|
1015
|
+
parentMessageId?: string;
|
|
1012
1016
|
statuses?: Array<"pending" | "success" | "failed">;
|
|
1013
1017
|
},
|
|
1014
1018
|
{
|
|
@@ -1018,7 +1022,7 @@ export type Mounts = {
|
|
|
1018
1022
|
_creationTime: number;
|
|
1019
1023
|
_id: string;
|
|
1020
1024
|
agentName?: string;
|
|
1021
|
-
chatId
|
|
1025
|
+
chatId?: string;
|
|
1022
1026
|
embeddingId?:
|
|
1023
1027
|
| string
|
|
1024
1028
|
| string
|
|
@@ -1129,7 +1133,7 @@ export type Mounts = {
|
|
|
1129
1133
|
role: "system";
|
|
1130
1134
|
};
|
|
1131
1135
|
model?: string;
|
|
1132
|
-
order
|
|
1136
|
+
order: number;
|
|
1133
1137
|
status: "pending" | "success" | "failed";
|
|
1134
1138
|
stepId?: string;
|
|
1135
1139
|
stepOrder?: number;
|
|
@@ -1195,6 +1199,7 @@ export type Mounts = {
|
|
|
1195
1199
|
chatId?: string;
|
|
1196
1200
|
limit: number;
|
|
1197
1201
|
messageRange?: { after: number; before: number };
|
|
1202
|
+
parentMessageId?: string;
|
|
1198
1203
|
text?: string;
|
|
1199
1204
|
userId?: string;
|
|
1200
1205
|
vector?: Array<number>;
|
|
@@ -1204,7 +1209,7 @@ export type Mounts = {
|
|
|
1204
1209
|
_creationTime: number;
|
|
1205
1210
|
_id: string;
|
|
1206
1211
|
agentName?: string;
|
|
1207
|
-
chatId
|
|
1212
|
+
chatId?: string;
|
|
1208
1213
|
embeddingId?:
|
|
1209
1214
|
| string
|
|
1210
1215
|
| string
|
|
@@ -1315,7 +1320,7 @@ export type Mounts = {
|
|
|
1315
1320
|
role: "system";
|
|
1316
1321
|
};
|
|
1317
1322
|
model?: string;
|
|
1318
|
-
order
|
|
1323
|
+
order: number;
|
|
1319
1324
|
status: "pending" | "success" | "failed";
|
|
1320
1325
|
stepId?: string;
|
|
1321
1326
|
stepOrder?: number;
|
|
@@ -1333,7 +1338,7 @@ export type Mounts = {
|
|
|
1333
1338
|
_creationTime: number;
|
|
1334
1339
|
_id: string;
|
|
1335
1340
|
agentName?: string;
|
|
1336
|
-
chatId
|
|
1341
|
+
chatId?: string;
|
|
1337
1342
|
embeddingId?:
|
|
1338
1343
|
| string
|
|
1339
1344
|
| string
|
|
@@ -1444,7 +1449,7 @@ export type Mounts = {
|
|
|
1444
1449
|
role: "system";
|
|
1445
1450
|
};
|
|
1446
1451
|
model?: string;
|
|
1447
|
-
order
|
|
1452
|
+
order: number;
|
|
1448
1453
|
status: "pending" | "success" | "failed";
|
|
1449
1454
|
stepId?: string;
|
|
1450
1455
|
stepOrder?: number;
|
|
@@ -1479,6 +1484,128 @@ export type Mounts = {
|
|
|
1479
1484
|
}
|
|
1480
1485
|
>;
|
|
1481
1486
|
};
|
|
1487
|
+
vector: {
|
|
1488
|
+
index: {
|
|
1489
|
+
deleteBatch: FunctionReference<
|
|
1490
|
+
"mutation",
|
|
1491
|
+
"public",
|
|
1492
|
+
{
|
|
1493
|
+
ids: Array<
|
|
1494
|
+
| string
|
|
1495
|
+
| string
|
|
1496
|
+
| string
|
|
1497
|
+
| string
|
|
1498
|
+
| string
|
|
1499
|
+
| string
|
|
1500
|
+
| string
|
|
1501
|
+
| string
|
|
1502
|
+
| string
|
|
1503
|
+
>;
|
|
1504
|
+
},
|
|
1505
|
+
null
|
|
1506
|
+
>;
|
|
1507
|
+
deleteBatchForChat: FunctionReference<
|
|
1508
|
+
"mutation",
|
|
1509
|
+
"public",
|
|
1510
|
+
{
|
|
1511
|
+
chatId: string;
|
|
1512
|
+
cursor?: string;
|
|
1513
|
+
limit: number;
|
|
1514
|
+
model: string;
|
|
1515
|
+
vectorDimension:
|
|
1516
|
+
| 128
|
|
1517
|
+
| 256
|
|
1518
|
+
| 512
|
|
1519
|
+
| 768
|
|
1520
|
+
| 1024
|
|
1521
|
+
| 1536
|
|
1522
|
+
| 2048
|
|
1523
|
+
| 3072
|
|
1524
|
+
| 4096;
|
|
1525
|
+
},
|
|
1526
|
+
{ continueCursor: string; isDone: boolean }
|
|
1527
|
+
>;
|
|
1528
|
+
insertBatch: FunctionReference<
|
|
1529
|
+
"mutation",
|
|
1530
|
+
"public",
|
|
1531
|
+
{
|
|
1532
|
+
vectorDimension:
|
|
1533
|
+
| 128
|
|
1534
|
+
| 256
|
|
1535
|
+
| 512
|
|
1536
|
+
| 768
|
|
1537
|
+
| 1024
|
|
1538
|
+
| 1536
|
|
1539
|
+
| 2048
|
|
1540
|
+
| 3072
|
|
1541
|
+
| 4096;
|
|
1542
|
+
vectors: Array<{
|
|
1543
|
+
chatId?: string;
|
|
1544
|
+
kind: "chat" | "memory";
|
|
1545
|
+
model: string;
|
|
1546
|
+
userId?: string;
|
|
1547
|
+
vector: Array<number>;
|
|
1548
|
+
}>;
|
|
1549
|
+
},
|
|
1550
|
+
null
|
|
1551
|
+
>;
|
|
1552
|
+
paginate: FunctionReference<
|
|
1553
|
+
"query",
|
|
1554
|
+
"public",
|
|
1555
|
+
{
|
|
1556
|
+
cursor?: string;
|
|
1557
|
+
limit: number;
|
|
1558
|
+
targetModel: string;
|
|
1559
|
+
vectorDimension:
|
|
1560
|
+
| 128
|
|
1561
|
+
| 256
|
|
1562
|
+
| 512
|
|
1563
|
+
| 768
|
|
1564
|
+
| 1024
|
|
1565
|
+
| 1536
|
|
1566
|
+
| 2048
|
|
1567
|
+
| 3072
|
|
1568
|
+
| 4096;
|
|
1569
|
+
},
|
|
1570
|
+
{
|
|
1571
|
+
continueCursor: string;
|
|
1572
|
+
ids: Array<
|
|
1573
|
+
| string
|
|
1574
|
+
| string
|
|
1575
|
+
| string
|
|
1576
|
+
| string
|
|
1577
|
+
| string
|
|
1578
|
+
| string
|
|
1579
|
+
| string
|
|
1580
|
+
| string
|
|
1581
|
+
| string
|
|
1582
|
+
>;
|
|
1583
|
+
isDone: boolean;
|
|
1584
|
+
}
|
|
1585
|
+
>;
|
|
1586
|
+
updateBatch: FunctionReference<
|
|
1587
|
+
"mutation",
|
|
1588
|
+
"public",
|
|
1589
|
+
{
|
|
1590
|
+
vectors: Array<{
|
|
1591
|
+
id:
|
|
1592
|
+
| string
|
|
1593
|
+
| string
|
|
1594
|
+
| string
|
|
1595
|
+
| string
|
|
1596
|
+
| string
|
|
1597
|
+
| string
|
|
1598
|
+
| string
|
|
1599
|
+
| string
|
|
1600
|
+
| string;
|
|
1601
|
+
model: string;
|
|
1602
|
+
vector: Array<number>;
|
|
1603
|
+
}>;
|
|
1604
|
+
},
|
|
1605
|
+
null
|
|
1606
|
+
>;
|
|
1607
|
+
};
|
|
1608
|
+
};
|
|
1482
1609
|
};
|
|
1483
1610
|
// For now fullApiWithMounts is only fullApi which provides
|
|
1484
1611
|
// jump-to-definition in component client code.
|
|
@@ -2,19 +2,14 @@ import { assert, omit, pick } from "convex-helpers";
|
|
|
2
2
|
import { paginator } from "convex-helpers/server/pagination";
|
|
3
3
|
import { mergedStream, stream } from "convex-helpers/server/stream";
|
|
4
4
|
import { nullable, partial } from "convex-helpers/validators";
|
|
5
|
-
import {
|
|
5
|
+
import { ObjectType } from "convex/values";
|
|
6
6
|
import { DEFAULT_MESSAGE_RANGE, extractText, isTool } from "../shared.js";
|
|
7
7
|
import {
|
|
8
|
-
Message,
|
|
9
|
-
MessageWithFileAndId,
|
|
10
|
-
vAssistantMessage,
|
|
11
8
|
vChatStatus,
|
|
12
9
|
vMessageStatus,
|
|
13
10
|
vMessageWithFileAndId,
|
|
14
11
|
vSearchOptions,
|
|
15
|
-
vStep,
|
|
16
12
|
vStepWithMessagesWithFileAndId,
|
|
17
|
-
vToolMessage,
|
|
18
13
|
} from "../validators.js";
|
|
19
14
|
import { api, internal } from "./_generated/api.js";
|
|
20
15
|
import { Doc, Id } from "./_generated/dataModel.js";
|
|
@@ -63,7 +58,7 @@ export const getChatsByUserId = query({
|
|
|
63
58
|
.gte("order", args.offset ?? 0)
|
|
64
59
|
)
|
|
65
60
|
);
|
|
66
|
-
const chats = await mergedStream(streams, ["order"
|
|
61
|
+
const chats = await mergedStream(streams, ["order"]).paginate({
|
|
67
62
|
numItems: args.limit ?? 100,
|
|
68
63
|
cursor: args.cursor ?? null,
|
|
69
64
|
});
|
|
@@ -377,7 +372,8 @@ export const messageStatuses = vMessageDoc.fields.status.members.map(
|
|
|
377
372
|
);
|
|
378
373
|
|
|
379
374
|
const addMessagesArgs = {
|
|
380
|
-
|
|
375
|
+
userId: v.optional(v.string()),
|
|
376
|
+
chatId: v.optional(v.id("chats")),
|
|
381
377
|
stepId: v.optional(v.id("steps")),
|
|
382
378
|
parentMessageId: v.optional(v.id("messages")),
|
|
383
379
|
messages: v.array(vMessageWithFileAndId),
|
|
@@ -398,15 +394,22 @@ async function addMessagesHandler(
|
|
|
398
394
|
ctx: MutationCtx,
|
|
399
395
|
args: ObjectType<typeof addMessagesArgs>
|
|
400
396
|
) {
|
|
401
|
-
|
|
402
|
-
|
|
397
|
+
let userId = args.userId;
|
|
398
|
+
const chatId = args.chatId;
|
|
399
|
+
if (!userId && args.chatId) {
|
|
400
|
+
const chat = await ctx.db.get(args.chatId);
|
|
401
|
+
assert(chat, `Chat ${args.chatId} not found`);
|
|
402
|
+
userId = chat._id;
|
|
403
|
+
}
|
|
403
404
|
const { failPendingSteps, pending, messages, parentMessageId, ...rest } =
|
|
404
405
|
args;
|
|
405
|
-
|
|
406
|
+
const parent = parentMessageId && (await ctx.db.get(parentMessageId));
|
|
407
|
+
if (failPendingSteps && parent?.status !== "pending") {
|
|
408
|
+
assert(args.chatId, "chatId is required to fail pending steps");
|
|
406
409
|
const pendingMessages = await ctx.db
|
|
407
410
|
.query("messages")
|
|
408
411
|
.withIndex("chatId_status_tool_order_stepOrder", (q) =>
|
|
409
|
-
q.eq("chatId",
|
|
412
|
+
q.eq("chatId", chatId).eq("status", "pending")
|
|
410
413
|
)
|
|
411
414
|
.collect();
|
|
412
415
|
await Promise.all(
|
|
@@ -415,14 +418,14 @@ async function addMessagesHandler(
|
|
|
415
418
|
)
|
|
416
419
|
);
|
|
417
420
|
}
|
|
418
|
-
let
|
|
419
|
-
const maxMessage = await getMaxMessage(ctx,
|
|
421
|
+
let threadId = parentMessageId;
|
|
422
|
+
const maxMessage = await getMaxMessage(ctx, chatId, userId);
|
|
420
423
|
// If the previous message isn't our parent, we make a new thread.
|
|
421
|
-
|
|
424
|
+
threadId =
|
|
422
425
|
parentMessageId && maxMessage?._id === parentMessageId
|
|
423
426
|
? maxMessage.threadId ?? parentMessageId
|
|
424
427
|
: parentMessageId;
|
|
425
|
-
order = maxMessage?.order ?? -1;
|
|
428
|
+
let order = maxMessage?.order ?? -1;
|
|
426
429
|
const toReturn: Doc<"messages">[] = [];
|
|
427
430
|
if (messages.length > 0) {
|
|
428
431
|
for (const { message, fileId, id } of messages) {
|
|
@@ -434,7 +437,7 @@ async function addMessagesHandler(
|
|
|
434
437
|
const messageId = await ctx.db.insert("messages", {
|
|
435
438
|
...rest,
|
|
436
439
|
threadId,
|
|
437
|
-
userId
|
|
440
|
+
userId,
|
|
438
441
|
message,
|
|
439
442
|
id,
|
|
440
443
|
order,
|
|
@@ -449,18 +452,37 @@ async function addMessagesHandler(
|
|
|
449
452
|
return { messages: toReturn };
|
|
450
453
|
}
|
|
451
454
|
|
|
452
|
-
async function getMaxMessage(
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
455
|
+
async function getMaxMessage(
|
|
456
|
+
ctx: QueryCtx,
|
|
457
|
+
chatId: Id<"chats"> | undefined,
|
|
458
|
+
userId: string | undefined
|
|
459
|
+
) {
|
|
460
|
+
assert(chatId || userId, "One of chatId or userId is required");
|
|
461
|
+
if (chatId) {
|
|
462
|
+
return mergedStream(
|
|
463
|
+
["success" as const, "pending" as const].map((status) =>
|
|
464
|
+
stream(ctx.db, schema)
|
|
465
|
+
.query("messages")
|
|
466
|
+
.withIndex("chatId_status_tool_order_stepOrder", (q) =>
|
|
467
|
+
q.eq("chatId", chatId).eq("status", status).eq("tool", false)
|
|
468
|
+
)
|
|
469
|
+
.order("desc")
|
|
470
|
+
),
|
|
471
|
+
["order", "stepOrder"]
|
|
472
|
+
).first();
|
|
473
|
+
} else {
|
|
474
|
+
return mergedStream(
|
|
475
|
+
["success" as const, "pending" as const].map((status) =>
|
|
476
|
+
stream(ctx.db, schema)
|
|
477
|
+
.query("messages")
|
|
478
|
+
.withIndex("userId_status_tool_order_stepOrder", (q) =>
|
|
479
|
+
q.eq("userId", userId).eq("status", status).eq("tool", false)
|
|
480
|
+
)
|
|
481
|
+
.order("desc")
|
|
482
|
+
),
|
|
483
|
+
["order", "stepOrder"]
|
|
484
|
+
).first();
|
|
485
|
+
}
|
|
464
486
|
}
|
|
465
487
|
|
|
466
488
|
const addStepsArgs = {
|
|
@@ -518,7 +540,8 @@ async function addStepsHandler(
|
|
|
518
540
|
pending: step.finishReason === "stop" ? false : true,
|
|
519
541
|
failPendingSteps: false,
|
|
520
542
|
});
|
|
521
|
-
if
|
|
543
|
+
// We don't commit if the parent is still pending.
|
|
544
|
+
if (step.finishReason === "stop" && parentMessage.status === "success") {
|
|
522
545
|
await commitMessageHandler(ctx, { messageId: args.messageId });
|
|
523
546
|
}
|
|
524
547
|
steps.push((await ctx.db.get(stepId))!);
|
|
@@ -585,6 +608,7 @@ async function commitMessageHandler(
|
|
|
585
608
|
).collect();
|
|
586
609
|
for (const message of messages) {
|
|
587
610
|
await ctx.db.patch(message._id, { status: "success" });
|
|
611
|
+
// TODO: recursively commit steps & messages that might depend on this one.
|
|
588
612
|
}
|
|
589
613
|
}
|
|
590
614
|
|
|
@@ -597,9 +621,12 @@ export const getChatMessages = query({
|
|
|
597
621
|
// Note: the other arguments cannot change from when the cursor was created.
|
|
598
622
|
cursor: v.optional(v.string()),
|
|
599
623
|
statuses: v.optional(v.array(vMessageStatus)),
|
|
624
|
+
parentMessageId: v.optional(v.id("messages")),
|
|
600
625
|
},
|
|
601
626
|
handler: async (ctx, args) => {
|
|
602
627
|
const statuses = args.statuses ?? ["success"];
|
|
628
|
+
const parent =
|
|
629
|
+
args.parentMessageId && (await ctx.db.get(args.parentMessageId));
|
|
603
630
|
const toolOptions =
|
|
604
631
|
args.isTool === undefined ? [true, false] : [args.isTool];
|
|
605
632
|
const order = args.order ?? "desc";
|
|
@@ -607,9 +634,16 @@ export const getChatMessages = query({
|
|
|
607
634
|
statuses.map((status) =>
|
|
608
635
|
stream(ctx.db, schema)
|
|
609
636
|
.query("messages")
|
|
610
|
-
.withIndex("chatId_status_tool_order_stepOrder", (q) =>
|
|
611
|
-
|
|
612
|
-
|
|
637
|
+
.withIndex("chatId_status_tool_order_stepOrder", (q) => {
|
|
638
|
+
const qq = q
|
|
639
|
+
.eq("chatId", args.chatId)
|
|
640
|
+
.eq("status", status)
|
|
641
|
+
.eq("tool", tool);
|
|
642
|
+
if (parent) {
|
|
643
|
+
return qq.lte("order", parent.order);
|
|
644
|
+
}
|
|
645
|
+
return qq;
|
|
646
|
+
})
|
|
613
647
|
.order(order)
|
|
614
648
|
)
|
|
615
649
|
);
|
|
@@ -637,6 +671,7 @@ export const searchMessages = action({
|
|
|
637
671
|
args: {
|
|
638
672
|
userId: v.optional(v.string()),
|
|
639
673
|
chatId: v.optional(v.id("chats")),
|
|
674
|
+
parentMessageId: v.optional(v.id("messages")),
|
|
640
675
|
...vSearchOptions.fields,
|
|
641
676
|
},
|
|
642
677
|
returns: v.array(v.doc("messages")),
|
|
@@ -688,10 +723,12 @@ export const searchMessages = action({
|
|
|
688
723
|
userId: args.userId,
|
|
689
724
|
chatId: args.chatId,
|
|
690
725
|
vectorIds,
|
|
691
|
-
textSearchMessages: textSearchMessages
|
|
692
|
-
|
|
693
|
-
|
|
726
|
+
textSearchMessages: textSearchMessages?.filter(
|
|
727
|
+
(m) => !vectorIds.includes(m.embeddingId!)
|
|
728
|
+
),
|
|
694
729
|
messageRange: args.messageRange ?? DEFAULT_MESSAGE_RANGE,
|
|
730
|
+
parentMessageId: args.parentMessageId,
|
|
731
|
+
limit,
|
|
695
732
|
}
|
|
696
733
|
);
|
|
697
734
|
return messages;
|
|
@@ -707,71 +744,104 @@ export const _fetchVectorMessages = internalQuery({
|
|
|
707
744
|
vectorIds: v.array(vVectorId),
|
|
708
745
|
textSearchMessages: v.optional(v.array(v.doc("messages"))),
|
|
709
746
|
messageRange: v.object({ before: v.number(), after: v.number() }),
|
|
747
|
+
parentMessageId: v.optional(v.id("messages")),
|
|
748
|
+
limit: v.number(),
|
|
710
749
|
},
|
|
711
750
|
returns: v.array(v.doc("messages")),
|
|
712
751
|
handler: async (ctx, args): Promise<Doc<"messages">[]> => {
|
|
713
|
-
const
|
|
752
|
+
const parent =
|
|
753
|
+
args.parentMessageId && (await ctx.db.get(args.parentMessageId));
|
|
754
|
+
const { userId, chatId } = args;
|
|
755
|
+
assert(userId || chatId, "Specify userId or chatId to search");
|
|
756
|
+
let messages = (
|
|
714
757
|
await Promise.all(
|
|
715
758
|
args.vectorIds.map((embeddingId) =>
|
|
716
759
|
ctx.db
|
|
717
760
|
.query("messages")
|
|
718
761
|
.withIndex("embeddingId", (q) => q.eq("embeddingId", embeddingId))
|
|
719
|
-
.filter(
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
q.eq("chatId", args.chatId as any) // not sure why it's failing...
|
|
762
|
+
.filter((q) =>
|
|
763
|
+
userId
|
|
764
|
+
? q.eq("userId", userId)
|
|
765
|
+
: // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
766
|
+
q.eq("chatId", chatId as any)
|
|
725
767
|
)
|
|
726
768
|
.first()
|
|
727
769
|
)
|
|
728
770
|
)
|
|
729
|
-
).filter(
|
|
771
|
+
).filter(
|
|
772
|
+
(m): m is Doc<"messages"> =>
|
|
773
|
+
m !== undefined && m !== null && (!parent || m.order <= parent.order)
|
|
774
|
+
);
|
|
730
775
|
messages.push(...(args.textSearchMessages ?? []));
|
|
776
|
+
// TODO: prioritize more recent messages
|
|
731
777
|
messages.sort((a, b) => a.order! - b.order!);
|
|
778
|
+
messages = messages.slice(0, args.limit);
|
|
732
779
|
// Fetch the surrounding messages
|
|
733
|
-
|
|
780
|
+
if (!chatId) {
|
|
781
|
+
return messages.sort((a, b) => a.order - b.order);
|
|
782
|
+
}
|
|
783
|
+
const included: Record<string, Set<number>> = {};
|
|
734
784
|
for (const m of messages) {
|
|
735
|
-
|
|
736
|
-
|
|
785
|
+
const searchId = m.chatId ?? m.userId!;
|
|
786
|
+
if (!included[searchId]) {
|
|
787
|
+
included[searchId] = new Set();
|
|
737
788
|
}
|
|
738
|
-
included[
|
|
789
|
+
included[searchId].add(m.order!);
|
|
739
790
|
}
|
|
740
|
-
const ranges: Record<
|
|
791
|
+
const ranges: Record<string, Doc<"messages">[]> = {};
|
|
741
792
|
const { before, after } = args.messageRange;
|
|
742
793
|
for (const m of messages) {
|
|
794
|
+
const searchId = m.chatId ?? m.userId!;
|
|
743
795
|
const order = m.order!;
|
|
744
796
|
let earliest = order - before;
|
|
745
797
|
let latest = order + after;
|
|
746
798
|
for (; earliest <= latest; earliest++) {
|
|
747
|
-
if (!included[
|
|
799
|
+
if (!included[searchId].has(earliest)) {
|
|
748
800
|
break;
|
|
749
801
|
}
|
|
750
802
|
}
|
|
751
803
|
for (; latest >= earliest; latest--) {
|
|
752
|
-
if (!included[
|
|
804
|
+
if (!included[searchId].has(latest)) {
|
|
753
805
|
break;
|
|
754
806
|
}
|
|
755
807
|
}
|
|
756
808
|
for (let i = earliest; i <= latest; i++) {
|
|
757
|
-
included[
|
|
809
|
+
included[searchId].add(i);
|
|
758
810
|
}
|
|
759
811
|
if (earliest !== latest) {
|
|
760
|
-
|
|
761
|
-
.
|
|
762
|
-
|
|
763
|
-
q
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
ranges[
|
|
812
|
+
if (m.chatId) {
|
|
813
|
+
const surrounding = await ctx.db
|
|
814
|
+
.query("messages")
|
|
815
|
+
.withIndex("chatId_status_tool_order_stepOrder", (q) =>
|
|
816
|
+
q
|
|
817
|
+
.eq("chatId", m.chatId)
|
|
818
|
+
.eq("status", "success")
|
|
819
|
+
.eq("tool", false)
|
|
820
|
+
.gt("order", earliest)
|
|
821
|
+
.lt("order", latest)
|
|
822
|
+
)
|
|
823
|
+
.collect();
|
|
824
|
+
if (!ranges[searchId]) {
|
|
825
|
+
ranges[searchId] = [];
|
|
826
|
+
}
|
|
827
|
+
ranges[searchId].push(...surrounding);
|
|
828
|
+
} else {
|
|
829
|
+
const surrounding = await ctx.db
|
|
830
|
+
.query("messages")
|
|
831
|
+
.withIndex("userId_status_tool_order_stepOrder", (q) =>
|
|
832
|
+
q
|
|
833
|
+
.eq("userId", m.userId!)
|
|
834
|
+
.eq("status", "success")
|
|
835
|
+
.eq("tool", false)
|
|
836
|
+
.gt("order", earliest)
|
|
837
|
+
.lt("order", latest)
|
|
838
|
+
)
|
|
839
|
+
.collect();
|
|
840
|
+
if (!ranges[searchId]) {
|
|
841
|
+
ranges[searchId] = [];
|
|
842
|
+
}
|
|
843
|
+
ranges[searchId].push(...surrounding);
|
|
773
844
|
}
|
|
774
|
-
ranges[m.chatId].push(...surrounding);
|
|
775
845
|
}
|
|
776
846
|
}
|
|
777
847
|
return Object.values(ranges)
|
package/src/component/schema.ts
CHANGED
|
@@ -22,7 +22,7 @@ export const schema = defineSchema({
|
|
|
22
22
|
messages: defineTable({
|
|
23
23
|
id: v.optional(v.string()), // external id, e.g. from Vercel AI SDK
|
|
24
24
|
userId: v.optional(v.string()), // useful for future indexes (text search)
|
|
25
|
-
chatId: v.id("chats"),
|
|
25
|
+
chatId: v.optional(v.id("chats")),
|
|
26
26
|
threadId: v.optional(v.id("messages")),
|
|
27
27
|
stepId: v.optional(v.id("steps")),
|
|
28
28
|
agentName: v.optional(v.string()),
|
|
@@ -33,8 +33,8 @@ export const schema = defineSchema({
|
|
|
33
33
|
// TODO: add sub-messages back in? or be able to skip them?
|
|
34
34
|
tool: v.boolean(),
|
|
35
35
|
// Repeats until a non-tool message.
|
|
36
|
-
//
|
|
37
|
-
order: v.
|
|
36
|
+
// Unset if it's not in a chat.
|
|
37
|
+
order: v.number(),
|
|
38
38
|
stepOrder: v.optional(v.number()),
|
|
39
39
|
fileId: v.optional(v.id("files")),
|
|
40
40
|
status: vMessageStatus,
|
|
@@ -48,6 +48,13 @@ export const schema = defineSchema({
|
|
|
48
48
|
"order",
|
|
49
49
|
"stepOrder",
|
|
50
50
|
])
|
|
51
|
+
.index("userId_status_tool_order_stepOrder", [
|
|
52
|
+
"userId",
|
|
53
|
+
"status",
|
|
54
|
+
"tool",
|
|
55
|
+
"order",
|
|
56
|
+
"stepOrder",
|
|
57
|
+
])
|
|
51
58
|
// Allows finding all threaded messages in order
|
|
52
59
|
// Allows finding all failed messages to evaluate
|
|
53
60
|
// .index("status_threadId_order_stepOrder", [
|