@convex-dev/agent 0.6.3 → 0.7.0-alpha.0
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/MIGRATION.md +60 -116
- package/dist/client/messages.d.ts +1 -398
- package/dist/client/messages.d.ts.map +1 -1
- package/dist/client/messages.js +3 -47
- package/dist/client/messages.js.map +1 -1
- package/dist/client/types.d.ts +1 -455
- package/dist/client/types.d.ts.map +1 -1
- package/dist/component/_generated/component.d.ts +805 -45
- package/dist/component/_generated/component.d.ts.map +1 -1
- package/dist/component/apiKeys.js +5 -5
- package/dist/component/apiKeys.js.map +1 -1
- package/dist/component/files.d.ts.map +1 -1
- package/dist/component/files.js +13 -11
- package/dist/component/files.js.map +1 -1
- package/dist/component/messages.d.ts +1252 -201
- package/dist/component/messages.d.ts.map +1 -1
- package/dist/component/messages.js +83 -47
- package/dist/component/messages.js.map +1 -1
- package/dist/component/schema.d.ts +2593 -332
- package/dist/component/schema.d.ts.map +1 -1
- package/dist/component/streams.d.ts +7 -1
- package/dist/component/streams.d.ts.map +1 -1
- package/dist/component/streams.js +46 -47
- package/dist/component/streams.js.map +1 -1
- package/dist/component/threads.d.ts.map +1 -1
- package/dist/component/threads.js +8 -9
- package/dist/component/threads.js.map +1 -1
- package/dist/component/users.js +2 -2
- package/dist/component/users.js.map +1 -1
- package/dist/component/vector/index.d.ts.map +1 -1
- package/dist/component/vector/index.js +14 -8
- package/dist/component/vector/index.js.map +1 -1
- package/dist/react/index.d.ts +5 -5
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +5 -5
- package/dist/react/index.js.map +1 -1
- package/dist/shared.d.ts +19 -7
- package/dist/shared.d.ts.map +1 -1
- package/dist/shared.js +4 -4
- package/dist/shared.js.map +1 -1
- package/dist/streaming/materializePersistedUIMessageChunks.d.ts +16 -0
- package/dist/streaming/materializePersistedUIMessageChunks.d.ts.map +1 -0
- package/dist/streaming/materializePersistedUIMessageChunks.js +302 -0
- package/dist/streaming/materializePersistedUIMessageChunks.js.map +1 -0
- package/dist/streaming/persistedUIMessageChunks.d.ts +106 -0
- package/dist/streaming/persistedUIMessageChunks.d.ts.map +1 -0
- package/dist/streaming/persistedUIMessageChunks.js +475 -0
- package/dist/streaming/persistedUIMessageChunks.js.map +1 -0
- package/dist/validators.d.ts +10026 -1055
- package/dist/validators.d.ts.map +1 -1
- package/dist/validators.js +71 -9
- package/dist/validators.js.map +1 -1
- package/dist/{UIMessages.d.ts → vercel/UIMessages.d.ts} +1 -1
- package/dist/vercel/UIMessages.d.ts.map +1 -0
- package/dist/{UIMessages.js → vercel/UIMessages.js} +63 -1
- package/dist/vercel/UIMessages.js.map +1 -0
- package/dist/{client → vercel/client}/createTool.d.ts +23 -16
- package/dist/vercel/client/createTool.d.ts.map +1 -0
- package/dist/{client → vercel/client}/createTool.js +2 -0
- package/dist/vercel/client/createTool.js.map +1 -0
- package/dist/{client → vercel/client}/definePlaygroundAPI.d.ts +593 -134
- package/dist/{client → vercel/client}/definePlaygroundAPI.d.ts.map +1 -1
- package/dist/{client → vercel/client}/definePlaygroundAPI.js +13 -9
- package/dist/vercel/client/definePlaygroundAPI.js.map +1 -0
- package/dist/{client → vercel/client}/files.d.ts +2 -2
- package/dist/vercel/client/files.d.ts.map +1 -0
- package/dist/vercel/client/files.js.map +1 -0
- package/dist/vercel/client/messages.d.ts +542 -0
- package/dist/vercel/client/messages.d.ts.map +1 -0
- package/dist/vercel/client/messages.js +66 -0
- package/dist/vercel/client/messages.js.map +1 -0
- package/dist/{client → vercel/client}/mockModel.d.ts +17 -17
- package/dist/vercel/client/mockModel.d.ts.map +1 -0
- package/dist/{client → vercel/client}/mockModel.js +12 -13
- package/dist/vercel/client/mockModel.js.map +1 -0
- package/dist/{client → vercel/client}/saveInputMessages.d.ts +2 -2
- package/dist/vercel/client/saveInputMessages.d.ts.map +1 -0
- package/dist/vercel/client/saveInputMessages.js.map +1 -0
- package/dist/{client → vercel/client}/search.d.ts +119 -22
- package/dist/vercel/client/search.d.ts.map +1 -0
- package/dist/{client → vercel/client}/search.js +2 -2
- package/dist/vercel/client/search.js.map +1 -0
- package/dist/{client → vercel/client}/start.d.ts +26 -11
- package/dist/vercel/client/start.d.ts.map +1 -0
- package/dist/{client → vercel/client}/start.js +64 -22
- package/dist/vercel/client/start.js.map +1 -0
- package/dist/{client → vercel/client}/streamText.d.ts +13 -12
- package/dist/vercel/client/streamText.d.ts.map +1 -0
- package/dist/{client → vercel/client}/streamText.js +43 -9
- package/dist/vercel/client/streamText.js.map +1 -0
- package/dist/{client → vercel/client}/streaming.d.ts +1410 -183
- package/dist/vercel/client/streaming.d.ts.map +1 -0
- package/dist/{client → vercel/client}/streaming.js +120 -52
- package/dist/vercel/client/streaming.js.map +1 -0
- package/dist/vercel/client/types.d.ts +456 -0
- package/dist/vercel/client/types.d.ts.map +1 -0
- package/dist/vercel/client/types.js +3 -0
- package/dist/vercel/client/types.js.map +1 -0
- package/dist/{client → vercel/client}/utils.d.ts +3 -2
- package/dist/vercel/client/utils.d.ts.map +1 -0
- package/dist/{client → vercel/client}/utils.js +2 -2
- package/dist/vercel/client/utils.js.map +1 -0
- package/dist/vercel/deltas.d.ts +31 -0
- package/dist/vercel/deltas.d.ts.map +1 -0
- package/dist/vercel/deltas.js +525 -0
- package/dist/vercel/deltas.js.map +1 -0
- package/dist/{client → vercel}/index.d.ts +484 -97
- package/dist/vercel/index.d.ts.map +1 -0
- package/dist/{client → vercel}/index.js +65 -38
- package/dist/vercel/index.js.map +1 -0
- package/dist/{mapping.d.ts → vercel/mapping.d.ts} +5 -13
- package/dist/vercel/mapping.d.ts.map +1 -0
- package/dist/{mapping.js → vercel/mapping.js} +411 -112
- package/dist/vercel/mapping.js.map +1 -0
- package/dist/{react → vercel/react}/optimisticallySendMessage.d.ts +2 -2
- package/dist/vercel/react/optimisticallySendMessage.d.ts.map +1 -0
- package/dist/vercel/react/optimisticallySendMessage.js.map +1 -0
- package/dist/{react → vercel/react}/types.d.ts +1 -1
- package/dist/vercel/react/types.d.ts.map +1 -0
- package/dist/{react → vercel/react}/types.js.map +1 -1
- package/dist/{react → vercel/react}/useDeltaStreams.d.ts +1 -1
- package/dist/vercel/react/useDeltaStreams.d.ts.map +1 -0
- package/dist/{react → vercel/react}/useDeltaStreams.js +1 -1
- package/dist/vercel/react/useDeltaStreams.js.map +1 -0
- package/dist/{react → vercel/react}/useStreamingUIMessages.d.ts +1 -1
- package/dist/vercel/react/useStreamingUIMessages.d.ts.map +1 -0
- package/dist/vercel/react/useStreamingUIMessages.js +112 -0
- package/dist/vercel/react/useStreamingUIMessages.js.map +1 -0
- package/dist/{react → vercel/react}/useThreadMessages.d.ts +1 -1
- package/dist/vercel/react/useThreadMessages.d.ts.map +1 -0
- package/dist/{react → vercel/react}/useThreadMessages.js +1 -1
- package/dist/vercel/react/useThreadMessages.js.map +1 -0
- package/dist/{react → vercel/react}/useUIMessages.d.ts +2 -1
- package/dist/vercel/react/useUIMessages.d.ts.map +1 -0
- package/dist/{react → vercel/react}/useUIMessages.js +8 -4
- package/dist/vercel/react/useUIMessages.js.map +1 -0
- package/package.json +30 -22
- package/src/client/messages.ts +5 -107
- package/src/client/types.ts +0 -621
- package/src/component/_generated/component.ts +1089 -48
- package/src/component/apiKeys.ts +5 -5
- package/src/component/files.test.ts +1 -1
- package/src/component/files.ts +14 -12
- package/src/component/messages.test.ts +273 -1
- package/src/component/messages.ts +99 -57
- package/src/component/streams.ts +80 -64
- package/src/component/threads.ts +12 -9
- package/src/component/users.ts +2 -2
- package/src/component/vector/index.ts +14 -7
- package/src/eslintConfig.test.ts +44 -0
- package/src/react/index.ts +8 -5
- package/src/shared.ts +26 -36
- package/src/streaming/materializePersistedUIMessageChunks.test.ts +513 -0
- package/src/streaming/materializePersistedUIMessageChunks.ts +398 -0
- package/src/streaming/persistedUIMessageChunks.test.ts +205 -0
- package/src/streaming/persistedUIMessageChunks.ts +658 -0
- package/src/validators.test.ts +4 -1
- package/src/validators.ts +89 -8
- package/src/{UIMessages.combineUIMessages.test.ts → vercel/UIMessages.combineUIMessages.test.ts} +4 -1
- package/src/{UIMessages.ts → vercel/UIMessages.ts} +96 -5
- package/src/{client → vercel/client}/approval.test.ts +48 -19
- package/src/{client → vercel/client}/createTool.ts +63 -23
- package/src/{client → vercel/client}/definePlaygroundAPI.ts +44 -29
- package/src/{client → vercel/client}/files.ts +2 -2
- package/src/{client → vercel/client}/index.test.ts +162 -3
- package/src/vercel/client/messages.ts +182 -0
- package/src/{client → vercel/client}/mockModel.ts +38 -39
- package/src/{client → vercel/client}/saveInputMessages.test.ts +1 -1
- package/src/{client → vercel/client}/saveInputMessages.ts +7 -4
- package/src/{client → vercel/client}/search.test.ts +3 -3
- package/src/{client → vercel/client}/search.ts +4 -4
- package/src/{client → vercel/client}/setup.test.ts +6 -3
- package/src/vercel/client/start.test.ts +14 -0
- package/src/{client → vercel/client}/start.ts +147 -36
- package/src/vercel/client/streamText.test.ts +223 -0
- package/src/{client → vercel/client}/streamText.ts +102 -31
- package/src/{client → vercel/client}/streaming.integration.test.ts +40 -115
- package/src/{client → vercel/client}/streaming.test.ts +178 -4
- package/src/{client → vercel/client}/streaming.ts +114 -52
- package/src/vercel/client/types.test.ts +13 -0
- package/src/vercel/client/types.ts +679 -0
- package/src/{client → vercel/client}/utils.ts +13 -7
- package/src/vercel/deltas.test.ts +898 -0
- package/src/vercel/deltas.ts +633 -0
- package/src/{fromUIMessages.test.ts → vercel/fromUIMessages.test.ts} +17 -1
- package/src/{client → vercel}/index.ts +169 -62
- package/src/vercel/mapping.test.ts +965 -0
- package/src/{mapping.ts → vercel/mapping.ts} +501 -131
- package/src/{react → vercel/react}/optimisticallySendMessage.ts +2 -2
- package/src/{react → vercel/react}/types.ts +1 -1
- package/src/{react → vercel/react}/useDeltaStreams.ts +6 -2
- package/src/{react → vercel/react}/useStreamingUIMessages.ts +67 -35
- package/src/{react → vercel/react}/useThreadMessages.ts +2 -2
- package/src/{react → vercel/react}/useUIMessages.test.ts +80 -1
- package/src/{react → vercel/react}/useUIMessages.ts +13 -5
- package/src/{toUIMessages.test.ts → vercel/toUIMessages.test.ts} +49 -2
- package/dist/UIMessages.d.ts.map +0 -1
- package/dist/UIMessages.js.map +0 -1
- package/dist/client/createTool.d.ts.map +0 -1
- package/dist/client/createTool.js.map +0 -1
- package/dist/client/definePlaygroundAPI.js.map +0 -1
- package/dist/client/files.d.ts.map +0 -1
- package/dist/client/files.js.map +0 -1
- package/dist/client/index.d.ts.map +0 -1
- package/dist/client/index.js.map +0 -1
- package/dist/client/mockModel.d.ts.map +0 -1
- package/dist/client/mockModel.js.map +0 -1
- package/dist/client/saveInputMessages.d.ts.map +0 -1
- package/dist/client/saveInputMessages.js.map +0 -1
- package/dist/client/search.d.ts.map +0 -1
- package/dist/client/search.js.map +0 -1
- package/dist/client/start.d.ts.map +0 -1
- package/dist/client/start.js.map +0 -1
- package/dist/client/streamText.d.ts.map +0 -1
- package/dist/client/streamText.js.map +0 -1
- package/dist/client/streaming.d.ts.map +0 -1
- package/dist/client/streaming.js.map +0 -1
- package/dist/client/utils.d.ts.map +0 -1
- package/dist/client/utils.js.map +0 -1
- package/dist/deltas.d.ts +0 -43
- package/dist/deltas.d.ts.map +0 -1
- package/dist/deltas.js +0 -446
- package/dist/deltas.js.map +0 -1
- package/dist/mapping.d.ts.map +0 -1
- package/dist/mapping.js.map +0 -1
- package/dist/react/optimisticallySendMessage.d.ts.map +0 -1
- package/dist/react/optimisticallySendMessage.js.map +0 -1
- package/dist/react/types.d.ts.map +0 -1
- package/dist/react/useDeltaStreams.d.ts.map +0 -1
- package/dist/react/useDeltaStreams.js.map +0 -1
- package/dist/react/useStreamingUIMessages.d.ts.map +0 -1
- package/dist/react/useStreamingUIMessages.js +0 -92
- package/dist/react/useStreamingUIMessages.js.map +0 -1
- package/dist/react/useThreadMessages.d.ts.map +0 -1
- package/dist/react/useThreadMessages.js.map +0 -1
- package/dist/react/useUIMessages.d.ts.map +0 -1
- package/dist/react/useUIMessages.js.map +0 -1
- package/src/client/streamText.test.ts +0 -102
- package/src/deltas.test.ts +0 -626
- package/src/deltas.ts +0 -569
- package/src/mapping.test.ts +0 -402
- /package/dist/{client → vercel/client}/files.js +0 -0
- /package/dist/{client → vercel/client}/saveInputMessages.js +0 -0
- /package/dist/{react → vercel/react}/optimisticallySendMessage.js +0 -0
- /package/dist/{react → vercel/react}/types.js +0 -0
- /package/src/{UIMessages.test.ts → vercel/UIMessages.test.ts} +0 -0
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
import { schema, v } from "./schema.js";
|
|
35
35
|
import { insertVector, searchVectors } from "./vector/index.js";
|
|
36
36
|
import {
|
|
37
|
+
getVectorIdInfo,
|
|
37
38
|
validateVectorDimension,
|
|
38
39
|
type VectorTableId,
|
|
39
40
|
vVectorId,
|
|
@@ -50,9 +51,10 @@ export async function deleteMessage(
|
|
|
50
51
|
ctx: MutationCtx,
|
|
51
52
|
messageDoc: Doc<"messages">,
|
|
52
53
|
) {
|
|
53
|
-
await ctx.db.delete(messageDoc._id);
|
|
54
|
+
await ctx.db.delete("messages", messageDoc._id);
|
|
54
55
|
if (messageDoc.embeddingId) {
|
|
55
|
-
|
|
56
|
+
const { tableName } = getVectorIdInfo(ctx, messageDoc.embeddingId);
|
|
57
|
+
await ctx.db.delete(tableName, messageDoc.embeddingId);
|
|
56
58
|
}
|
|
57
59
|
if (messageDoc.fileIds) {
|
|
58
60
|
await changeRefcount(ctx, messageDoc.fileIds, []);
|
|
@@ -65,7 +67,7 @@ export const deleteByIds = mutation({
|
|
|
65
67
|
handler: async (ctx, args) => {
|
|
66
68
|
const deletedMessageIds = await Promise.all(
|
|
67
69
|
args.messageIds.map(async (id) => {
|
|
68
|
-
const message = await ctx.db.get(id);
|
|
70
|
+
const message = await ctx.db.get("messages", id);
|
|
69
71
|
if (message) {
|
|
70
72
|
await deleteMessage(ctx, message);
|
|
71
73
|
return id;
|
|
@@ -81,6 +83,25 @@ export const messageStatuses = vMessageDoc.fields.status.members.map(
|
|
|
81
83
|
(m) => m.value,
|
|
82
84
|
);
|
|
83
85
|
|
|
86
|
+
const STREAM_RECOVERY_FAILURE =
|
|
87
|
+
"Failed to recover persisted assistant stream output";
|
|
88
|
+
|
|
89
|
+
async function markPendingMessageFailed(
|
|
90
|
+
ctx: MutationCtx,
|
|
91
|
+
message: Doc<"messages">,
|
|
92
|
+
error: string,
|
|
93
|
+
) {
|
|
94
|
+
if (message.embeddingId) {
|
|
95
|
+
const { tableName } = getVectorIdInfo(ctx, message.embeddingId);
|
|
96
|
+
await ctx.db.delete(tableName, message.embeddingId);
|
|
97
|
+
}
|
|
98
|
+
await ctx.db.patch("messages", message._id, {
|
|
99
|
+
status: "failed",
|
|
100
|
+
error,
|
|
101
|
+
embeddingId: undefined,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
84
105
|
export const deleteByOrder = mutation({
|
|
85
106
|
args: {
|
|
86
107
|
threadId: v.id("threads"),
|
|
@@ -157,7 +178,7 @@ async function addMessagesHandler(
|
|
|
157
178
|
let userId = args.userId;
|
|
158
179
|
const threadId = args.threadId;
|
|
159
180
|
if (!userId && args.threadId) {
|
|
160
|
-
const thread = await ctx.db.get(args.threadId);
|
|
181
|
+
const thread = await ctx.db.get("threads", args.threadId);
|
|
161
182
|
assert(thread, `Thread ${args.threadId} not found`);
|
|
162
183
|
userId = thread.userId;
|
|
163
184
|
}
|
|
@@ -172,7 +193,8 @@ async function addMessagesHandler(
|
|
|
172
193
|
hideFromUserIdSearch,
|
|
173
194
|
...rest
|
|
174
195
|
} = args;
|
|
175
|
-
const promptMessage =
|
|
196
|
+
const promptMessage =
|
|
197
|
+
promptMessageId && (await ctx.db.get("messages", promptMessageId));
|
|
176
198
|
if (failPendingSteps) {
|
|
177
199
|
assert(args.threadId, "threadId is required to fail pending steps");
|
|
178
200
|
const pendingMessages = await ctx.db
|
|
@@ -188,9 +210,10 @@ async function addMessagesHandler(
|
|
|
188
210
|
.filter((m) => !pendingMessageId || m._id !== pendingMessageId)
|
|
189
211
|
.map(async (m) => {
|
|
190
212
|
if (m.embeddingId) {
|
|
191
|
-
|
|
213
|
+
const { tableName } = getVectorIdInfo(ctx, m.embeddingId);
|
|
214
|
+
await ctx.db.delete(tableName, m.embeddingId);
|
|
192
215
|
}
|
|
193
|
-
await ctx.db.patch(m._id, {
|
|
216
|
+
await ctx.db.patch("messages", m._id, {
|
|
194
217
|
status: "failed",
|
|
195
218
|
error: "Restarting",
|
|
196
219
|
embeddingId: undefined,
|
|
@@ -257,7 +280,7 @@ async function addMessagesHandler(
|
|
|
257
280
|
// If there is a pending message, we replace that one with the first message
|
|
258
281
|
// and subsequent ones will follow the regular order/subOrder advancement.
|
|
259
282
|
if (i === 0 && pendingMessageId) {
|
|
260
|
-
const pendingMessage = await ctx.db.get(pendingMessageId);
|
|
283
|
+
const pendingMessage = await ctx.db.get("messages", pendingMessageId);
|
|
261
284
|
assert(pendingMessage, `Pending msg ${pendingMessageId} not found`);
|
|
262
285
|
if (pendingMessage.status === "failed") {
|
|
263
286
|
fail = true;
|
|
@@ -274,12 +297,12 @@ async function addMessagesHandler(
|
|
|
274
297
|
message.fileIds,
|
|
275
298
|
);
|
|
276
299
|
}
|
|
277
|
-
await ctx.db.replace(pendingMessage._id, {
|
|
300
|
+
await ctx.db.replace("messages", pendingMessage._id, {
|
|
278
301
|
...messageDoc,
|
|
279
302
|
order: pendingMessage.order,
|
|
280
303
|
stepOrder: pendingMessage.stepOrder,
|
|
281
304
|
});
|
|
282
|
-
toReturn.push((await ctx.db.get(pendingMessage._id))!);
|
|
305
|
+
toReturn.push((await ctx.db.get("messages", pendingMessage._id))!);
|
|
283
306
|
continue;
|
|
284
307
|
}
|
|
285
308
|
if (message.message.role === "user") {
|
|
@@ -306,7 +329,7 @@ async function addMessagesHandler(
|
|
|
306
329
|
await changeRefcount(ctx, [], message.fileIds);
|
|
307
330
|
}
|
|
308
331
|
// TODO: delete the associated stream data for the order/stepOrder
|
|
309
|
-
toReturn.push((await ctx.db.get(messageId))!);
|
|
332
|
+
toReturn.push((await ctx.db.get("messages", messageId))!);
|
|
310
333
|
}
|
|
311
334
|
// Atomically finish the stream if requested, preventing UI flickering
|
|
312
335
|
// from separate mutations for message save and stream finish (issue #181).
|
|
@@ -375,7 +398,7 @@ export const finalizeMessage = mutation({
|
|
|
375
398
|
},
|
|
376
399
|
returns: v.null(),
|
|
377
400
|
handler: async (ctx, { messageId, result }) => {
|
|
378
|
-
const message = await ctx.db.get(messageId);
|
|
401
|
+
const message = await ctx.db.get("messages", messageId);
|
|
379
402
|
assert(message, `Message ${messageId} not found`);
|
|
380
403
|
if (message.status !== "pending") {
|
|
381
404
|
console.debug(
|
|
@@ -386,11 +409,20 @@ export const finalizeMessage = mutation({
|
|
|
386
409
|
}
|
|
387
410
|
// See if we can add any in-progress data
|
|
388
411
|
if (!message.message?.content.length) {
|
|
389
|
-
const messages
|
|
390
|
-
ctx,
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
412
|
+
const { messages, materializationFailures } =
|
|
413
|
+
await getStreamingMessagesWithMetadata(ctx, message, result);
|
|
414
|
+
if (materializationFailures.length > 0) {
|
|
415
|
+
console.error(
|
|
416
|
+
"Failed to materialize persisted assistant streams",
|
|
417
|
+
materializationFailures,
|
|
418
|
+
);
|
|
419
|
+
await markPendingMessageFailed(
|
|
420
|
+
ctx,
|
|
421
|
+
message,
|
|
422
|
+
result.status === "failed" ? result.error : STREAM_RECOVERY_FAILURE,
|
|
423
|
+
);
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
394
426
|
if (messages.length > 0) {
|
|
395
427
|
await addMessagesHandler(ctx, {
|
|
396
428
|
messages,
|
|
@@ -405,16 +437,9 @@ export const finalizeMessage = mutation({
|
|
|
405
437
|
}
|
|
406
438
|
}
|
|
407
439
|
if (result.status === "failed") {
|
|
408
|
-
|
|
409
|
-
await ctx.db.delete(message.embeddingId);
|
|
410
|
-
}
|
|
411
|
-
await ctx.db.patch(messageId, {
|
|
412
|
-
status: "failed",
|
|
413
|
-
error: result.error,
|
|
414
|
-
embeddingId: undefined,
|
|
415
|
-
});
|
|
440
|
+
await markPendingMessageFailed(ctx, message, result.error);
|
|
416
441
|
} else {
|
|
417
|
-
await ctx.db.patch(messageId, { status: "success" });
|
|
442
|
+
await ctx.db.patch("messages", messageId, { status: "success" });
|
|
418
443
|
}
|
|
419
444
|
},
|
|
420
445
|
});
|
|
@@ -439,7 +464,7 @@ export const updateMessage = mutation({
|
|
|
439
464
|
},
|
|
440
465
|
returns: vMessageDoc,
|
|
441
466
|
handler: async (ctx, args) => {
|
|
442
|
-
const message = await ctx.db.get(args.messageId);
|
|
467
|
+
const message = await ctx.db.get("messages", args.messageId);
|
|
443
468
|
assert(message, `Message ${args.messageId} not found`);
|
|
444
469
|
|
|
445
470
|
if (args.patch.fileIds) {
|
|
@@ -456,13 +481,14 @@ export const updateMessage = mutation({
|
|
|
456
481
|
|
|
457
482
|
if (args.patch.status === "failed") {
|
|
458
483
|
if (message.embeddingId) {
|
|
459
|
-
|
|
484
|
+
const { tableName } = getVectorIdInfo(ctx, message.embeddingId);
|
|
485
|
+
await ctx.db.delete(tableName, message.embeddingId);
|
|
460
486
|
}
|
|
461
487
|
patch.embeddingId = undefined;
|
|
462
488
|
}
|
|
463
489
|
|
|
464
|
-
await ctx.db.patch(args.messageId, patch);
|
|
465
|
-
return publicMessage((await ctx.db.get(args.messageId))!);
|
|
490
|
+
await ctx.db.patch("messages", args.messageId, patch);
|
|
491
|
+
return publicMessage((await ctx.db.get("messages", args.messageId))!);
|
|
466
492
|
},
|
|
467
493
|
});
|
|
468
494
|
|
|
@@ -540,7 +566,8 @@ export const cloneMessageBatch = internalMutation({
|
|
|
540
566
|
}
|
|
541
567
|
let embeddingId: VectorTableId | undefined = undefined;
|
|
542
568
|
if (m.embeddingId) {
|
|
543
|
-
const
|
|
569
|
+
const { tableName } = getVectorIdInfo(ctx, m.embeddingId);
|
|
570
|
+
const vector = await ctx.db.get(tableName, m.embeddingId);
|
|
544
571
|
assert(vector, `Vector ${m.embeddingId} not found`);
|
|
545
572
|
const dimension = vector.vector.length;
|
|
546
573
|
validateVectorDimension(dimension);
|
|
@@ -636,7 +663,7 @@ async function listMessagesByThreadIdHandler(
|
|
|
636
663
|
const statuses = args.statuses ?? vMessageStatus.members.map((m) => m.value);
|
|
637
664
|
const last =
|
|
638
665
|
args.upToAndIncludingMessageId &&
|
|
639
|
-
(await ctx.db.get(args.upToAndIncludingMessageId));
|
|
666
|
+
(await ctx.db.get("messages", args.upToAndIncludingMessageId));
|
|
640
667
|
assert(
|
|
641
668
|
!last || last.threadId === args.threadId,
|
|
642
669
|
"upToAndIncludingMessageId must be a message in the thread",
|
|
@@ -679,9 +706,9 @@ async function listMessagesByThreadIdHandler(
|
|
|
679
706
|
export const getMessagesByIds = query({
|
|
680
707
|
args: { messageIds: v.array(v.id("messages")) },
|
|
681
708
|
handler: async (ctx, args) => {
|
|
682
|
-
return (
|
|
683
|
-
(
|
|
684
|
-
);
|
|
709
|
+
return (
|
|
710
|
+
await Promise.all(args.messageIds.map((id) => ctx.db.get("messages", id)))
|
|
711
|
+
).map((m) => (m ? publicMessage(m) : null));
|
|
685
712
|
},
|
|
686
713
|
returns: v.array(v.union(v.null(), vMessageDoc)),
|
|
687
714
|
});
|
|
@@ -793,7 +820,8 @@ export const _fetchSearchMessages = internalQuery({
|
|
|
793
820
|
returns: v.array(vMessageDoc),
|
|
794
821
|
handler: async (ctx, args): Promise<MessageDoc[]> => {
|
|
795
822
|
const beforeMessage =
|
|
796
|
-
args.beforeMessageId &&
|
|
823
|
+
args.beforeMessageId &&
|
|
824
|
+
(await ctx.db.get("messages", args.beforeMessageId));
|
|
797
825
|
const { searchAllMessagesForUserId, threadId } = args;
|
|
798
826
|
assert(
|
|
799
827
|
searchAllMessagesForUserId || threadId,
|
|
@@ -809,6 +837,7 @@ export const _fetchSearchMessages = internalQuery({
|
|
|
809
837
|
? q.eq("embeddingId", embeddingId)
|
|
810
838
|
: q.eq("embeddingId", embeddingId).eq("threadId", threadId!),
|
|
811
839
|
)
|
|
840
|
+
// eslint-disable-next-line @convex-dev/no-filter-in-query -- We do not expect many messages with the same embeddingId for different users / threads
|
|
812
841
|
.filter((q) =>
|
|
813
842
|
q.and(
|
|
814
843
|
q.eq(q.field("status"), "success"),
|
|
@@ -821,16 +850,18 @@ export const _fetchSearchMessages = internalQuery({
|
|
|
821
850
|
),
|
|
822
851
|
)
|
|
823
852
|
)
|
|
824
|
-
.filter(
|
|
825
|
-
(m
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
853
|
+
.filter((m): m is Doc<"messages"> => {
|
|
854
|
+
if (m === undefined || m === null || m.tool) return false;
|
|
855
|
+
if (!beforeMessage) return true;
|
|
856
|
+
// The order filter is only meaningful within the same thread.
|
|
857
|
+
// Messages from other threads have independent order sequences.
|
|
858
|
+
if (m.threadId !== beforeMessage.threadId) return true;
|
|
859
|
+
return (
|
|
860
|
+
m.order < beforeMessage.order ||
|
|
861
|
+
(m.order === beforeMessage.order &&
|
|
862
|
+
m.stepOrder < beforeMessage.stepOrder)
|
|
863
|
+
);
|
|
864
|
+
})
|
|
834
865
|
.map(publicMessage);
|
|
835
866
|
messages.push(...(args.textSearchMessages ?? []));
|
|
836
867
|
// TODO: prioritize more recent messages
|
|
@@ -911,13 +942,18 @@ export const textSearch = query({
|
|
|
911
942
|
"Specify userId or threadId",
|
|
912
943
|
);
|
|
913
944
|
const targetMessage =
|
|
914
|
-
args.targetMessageId &&
|
|
915
|
-
|
|
945
|
+
args.targetMessageId &&
|
|
946
|
+
(await ctx.db.get("messages", args.targetMessageId));
|
|
916
947
|
const text = args.text || targetMessage?.text;
|
|
917
948
|
if (!text) {
|
|
918
949
|
console.warn("No text to search", targetMessage, args.text);
|
|
919
950
|
return [];
|
|
920
951
|
}
|
|
952
|
+
// When searching across threads (searchAllMessagesForUserId), the
|
|
953
|
+
// targetMessage's order is only meaningful within its own thread, so we
|
|
954
|
+
// can't apply it as a database-level filter. We still apply it post-fetch
|
|
955
|
+
// for same-thread results below.
|
|
956
|
+
const restrictOrderInDb = !args.searchAllMessagesForUserId && targetMessage;
|
|
921
957
|
const messages = await ctx.db
|
|
922
958
|
.query("messages")
|
|
923
959
|
.withSearchIndex("text_search", (q) =>
|
|
@@ -926,22 +962,27 @@ export const textSearch = query({
|
|
|
926
962
|
: q.search("text", text).eq("threadId", args.threadId!),
|
|
927
963
|
)
|
|
928
964
|
// Just in case tool messages slip through
|
|
965
|
+
// eslint-disable-next-line @convex-dev/no-filter-in-query -- we can't do this in the search index, but text search ideally isn't for really old orders
|
|
929
966
|
.filter((q) => {
|
|
930
967
|
const qq = q.eq(q.field("tool"), false);
|
|
931
|
-
if (
|
|
932
|
-
return q.and(qq, q.lte(q.field("order"), order));
|
|
968
|
+
if (restrictOrderInDb) {
|
|
969
|
+
return q.and(qq, q.lte(q.field("order"), targetMessage.order));
|
|
933
970
|
}
|
|
934
971
|
return qq;
|
|
935
972
|
})
|
|
936
973
|
.take(args.limit);
|
|
937
974
|
return messages
|
|
938
|
-
.filter(
|
|
939
|
-
(
|
|
940
|
-
|
|
975
|
+
.filter((m) => {
|
|
976
|
+
if (!targetMessage) return true;
|
|
977
|
+
// Order is only meaningful within the same thread; cross-thread
|
|
978
|
+
// results have independent order sequences and should pass through.
|
|
979
|
+
if (m.threadId !== targetMessage.threadId) return true;
|
|
980
|
+
return (
|
|
941
981
|
m.order < targetMessage.order ||
|
|
942
982
|
(m.order === targetMessage.order &&
|
|
943
|
-
m.stepOrder < targetMessage.stepOrder)
|
|
944
|
-
|
|
983
|
+
m.stepOrder < targetMessage.stepOrder)
|
|
984
|
+
);
|
|
985
|
+
})
|
|
945
986
|
.map(publicMessage);
|
|
946
987
|
},
|
|
947
988
|
returns: v.array(vMessageDoc),
|
|
@@ -964,12 +1005,13 @@ export const getMessageSearchFields = query({
|
|
|
964
1005
|
embedding?: number[] | undefined;
|
|
965
1006
|
embeddingModel?: string | undefined;
|
|
966
1007
|
}> => {
|
|
967
|
-
const message = await ctx.db.get(args.messageId);
|
|
1008
|
+
const message = await ctx.db.get("messages", args.messageId);
|
|
968
1009
|
const text = message?.text;
|
|
969
1010
|
let embedding = undefined;
|
|
970
1011
|
let embeddingModel = undefined;
|
|
971
1012
|
if (message?.embeddingId) {
|
|
972
|
-
const
|
|
1013
|
+
const { tableName } = getVectorIdInfo(ctx, message.embeddingId);
|
|
1014
|
+
const target = await ctx.db.get(tableName, message.embeddingId);
|
|
973
1015
|
embedding = target?.vector;
|
|
974
1016
|
embeddingModel = target?.model;
|
|
975
1017
|
}
|
package/src/component/streams.ts
CHANGED
|
@@ -21,8 +21,10 @@ import { stream } from "convex-helpers/server/stream";
|
|
|
21
21
|
import { mergedStream } from "convex-helpers/server/stream";
|
|
22
22
|
import { paginator } from "convex-helpers/server/pagination";
|
|
23
23
|
import type { WithoutSystemFields } from "convex/server";
|
|
24
|
-
import {
|
|
25
|
-
|
|
24
|
+
import {
|
|
25
|
+
getPersistedUIMessageChunkParts,
|
|
26
|
+
projectPersistedUIMessageChunks,
|
|
27
|
+
} from "../streaming/materializePersistedUIMessageChunks.js";
|
|
26
28
|
|
|
27
29
|
const SECOND = 1000;
|
|
28
30
|
const MINUTE = 60 * SECOND;
|
|
@@ -38,7 +40,7 @@ export const addDelta = mutation({
|
|
|
38
40
|
args: deltaValidator,
|
|
39
41
|
returns: v.boolean(),
|
|
40
42
|
handler: async (ctx, args) => {
|
|
41
|
-
const stream = await ctx.db.get(args.streamId);
|
|
43
|
+
const stream = await ctx.db.get("streamingMessages", args.streamId);
|
|
42
44
|
if (!stream) {
|
|
43
45
|
console.warn("Stream not found", args.streamId);
|
|
44
46
|
return false;
|
|
@@ -101,7 +103,9 @@ export const create = mutation({
|
|
|
101
103
|
internal.streams.timeoutStream,
|
|
102
104
|
{ streamId },
|
|
103
105
|
);
|
|
104
|
-
await ctx.db.patch(streamId, {
|
|
106
|
+
await ctx.db.patch("streamingMessages", streamId, {
|
|
107
|
+
state: { ...state, timeoutFnId },
|
|
108
|
+
});
|
|
105
109
|
return streamId;
|
|
106
110
|
},
|
|
107
111
|
});
|
|
@@ -197,7 +201,7 @@ async function abortById(
|
|
|
197
201
|
finalDelta?: WithoutSystemFields<Doc<"streamDeltas">>;
|
|
198
202
|
},
|
|
199
203
|
) {
|
|
200
|
-
const stream = await ctx.db.get(args.streamId);
|
|
204
|
+
const stream = await ctx.db.get("streamingMessages", args.streamId);
|
|
201
205
|
if (!stream) {
|
|
202
206
|
throw new Error(`Stream not found: ${args.streamId}`);
|
|
203
207
|
}
|
|
@@ -208,7 +212,7 @@ async function abortById(
|
|
|
208
212
|
return false;
|
|
209
213
|
}
|
|
210
214
|
await cleanupTimeoutFn(ctx, stream);
|
|
211
|
-
await ctx.db.patch(args.streamId, {
|
|
215
|
+
await ctx.db.patch("streamingMessages", args.streamId, {
|
|
212
216
|
state: { kind: "aborted", reason: args.reason },
|
|
213
217
|
});
|
|
214
218
|
return true;
|
|
@@ -219,7 +223,10 @@ async function cleanupTimeoutFn(
|
|
|
219
223
|
stream: Doc<"streamingMessages">,
|
|
220
224
|
) {
|
|
221
225
|
if (stream.state.kind === "streaming" && stream.state.timeoutFnId) {
|
|
222
|
-
const timeoutFn = await ctx.db.system.get(
|
|
226
|
+
const timeoutFn = await ctx.db.system.get(
|
|
227
|
+
"_scheduled_functions",
|
|
228
|
+
stream.state.timeoutFnId,
|
|
229
|
+
);
|
|
223
230
|
if (timeoutFn?.state.kind === "pending") {
|
|
224
231
|
await ctx.scheduler.cancel(stream.state.timeoutFnId);
|
|
225
232
|
}
|
|
@@ -246,7 +253,7 @@ export async function finishHandler(
|
|
|
246
253
|
if (args.finalDelta) {
|
|
247
254
|
await ctx.db.insert("streamDeltas", args.finalDelta);
|
|
248
255
|
}
|
|
249
|
-
const stream = await ctx.db.get(args.streamId);
|
|
256
|
+
const stream = await ctx.db.get("streamingMessages", args.streamId);
|
|
250
257
|
if (!stream) {
|
|
251
258
|
throw new Error(`Stream not found: ${args.streamId}`);
|
|
252
259
|
}
|
|
@@ -262,7 +269,7 @@ export async function finishHandler(
|
|
|
262
269
|
api.streams.deleteStreamAsync,
|
|
263
270
|
{ streamId: args.streamId },
|
|
264
271
|
);
|
|
265
|
-
await ctx.db.patch(args.streamId, {
|
|
272
|
+
await ctx.db.patch("streamingMessages", args.streamId, {
|
|
266
273
|
state: { kind: "finished", endedAt: Date.now(), cleanupFnId },
|
|
267
274
|
});
|
|
268
275
|
}
|
|
@@ -279,7 +286,7 @@ async function heartbeatStream(
|
|
|
279
286
|
ctx: MutationCtx,
|
|
280
287
|
args: { streamId: Id<"streamingMessages"> },
|
|
281
288
|
): Promise<void> {
|
|
282
|
-
const stream = await ctx.db.get(args.streamId);
|
|
289
|
+
const stream = await ctx.db.get("streamingMessages", args.streamId);
|
|
283
290
|
if (!stream) {
|
|
284
291
|
console.warn("Stream not found", args.streamId);
|
|
285
292
|
return;
|
|
@@ -294,7 +301,10 @@ async function heartbeatStream(
|
|
|
294
301
|
if (!stream.state.timeoutFnId) {
|
|
295
302
|
throw new Error("Stream has no timeout function");
|
|
296
303
|
}
|
|
297
|
-
const timeoutFn = await ctx.db.system.get(
|
|
304
|
+
const timeoutFn = await ctx.db.system.get(
|
|
305
|
+
"_scheduled_functions",
|
|
306
|
+
stream.state.timeoutFnId,
|
|
307
|
+
);
|
|
298
308
|
if (!timeoutFn) {
|
|
299
309
|
throw new Error("Timeout function not found");
|
|
300
310
|
}
|
|
@@ -307,7 +317,7 @@ async function heartbeatStream(
|
|
|
307
317
|
internal.streams.timeoutStream,
|
|
308
318
|
{ streamId: args.streamId },
|
|
309
319
|
);
|
|
310
|
-
await ctx.db.patch(args.streamId, {
|
|
320
|
+
await ctx.db.patch("streamingMessages", args.streamId, {
|
|
311
321
|
state: { kind: "streaming", lastHeartbeat: Date.now(), timeoutFnId },
|
|
312
322
|
});
|
|
313
323
|
}
|
|
@@ -316,12 +326,12 @@ export const timeoutStream = internalMutation({
|
|
|
316
326
|
args: { streamId: v.id("streamingMessages") },
|
|
317
327
|
returns: v.null(),
|
|
318
328
|
handler: async (ctx, args) => {
|
|
319
|
-
const stream = await ctx.db.get(args.streamId);
|
|
329
|
+
const stream = await ctx.db.get("streamingMessages", args.streamId);
|
|
320
330
|
if (!stream || stream.state.kind !== "streaming") {
|
|
321
331
|
console.warn("Stream not found", args.streamId);
|
|
322
332
|
return;
|
|
323
333
|
}
|
|
324
|
-
await ctx.db.patch(args.streamId, {
|
|
334
|
+
await ctx.db.patch("streamingMessages", args.streamId, {
|
|
325
335
|
state: { kind: "aborted", reason: "timeout" },
|
|
326
336
|
});
|
|
327
337
|
},
|
|
@@ -338,15 +348,23 @@ async function deletePageForStreamId(
|
|
|
338
348
|
numItems: MAX_DELTAS_PER_REQUEST,
|
|
339
349
|
cursor: args.cursor ?? null,
|
|
340
350
|
});
|
|
341
|
-
await Promise.all(
|
|
351
|
+
await Promise.all(
|
|
352
|
+
deltas.page.map((d) => ctx.db.delete("streamDeltas", d._id)),
|
|
353
|
+
);
|
|
342
354
|
if (deltas.isDone) {
|
|
343
|
-
const stream = await ctx.db.get(args.streamId);
|
|
355
|
+
const stream = await ctx.db.get("streamingMessages", args.streamId);
|
|
344
356
|
if (stream) {
|
|
345
357
|
await cleanupTimeoutFn(ctx, stream);
|
|
346
358
|
if (stream.state.kind === "finished" && stream.state.cleanupFnId) {
|
|
347
|
-
await ctx.
|
|
359
|
+
const scheduledFunction = await ctx.db.system.get(
|
|
360
|
+
"_scheduled_functions",
|
|
361
|
+
stream.state.cleanupFnId,
|
|
362
|
+
);
|
|
363
|
+
if (scheduledFunction?.state.kind === "pending") {
|
|
364
|
+
await ctx.scheduler.cancel(stream.state.cleanupFnId);
|
|
365
|
+
}
|
|
348
366
|
}
|
|
349
|
-
await ctx.db.delete(args.streamId);
|
|
367
|
+
await ctx.db.delete("streamingMessages", args.streamId);
|
|
350
368
|
}
|
|
351
369
|
}
|
|
352
370
|
return deltas;
|
|
@@ -434,7 +452,7 @@ export const deleteAllStreamsForThreadIdAsync = mutation({
|
|
|
434
452
|
},
|
|
435
453
|
);
|
|
436
454
|
} else {
|
|
437
|
-
await ctx.db.delete(args.threadId);
|
|
455
|
+
await ctx.db.delete("threads", args.threadId);
|
|
438
456
|
}
|
|
439
457
|
return result;
|
|
440
458
|
},
|
|
@@ -520,7 +538,13 @@ export async function getStreamingMessagesWithMetadata(
|
|
|
520
538
|
stepOrder,
|
|
521
539
|
}: { threadId: Id<"threads">; order: number; stepOrder: number },
|
|
522
540
|
metadata: { status: "success" | "failed"; error?: string },
|
|
523
|
-
): Promise<
|
|
541
|
+
): Promise<{
|
|
542
|
+
messages: MessageWithMetadataInternal[];
|
|
543
|
+
materializationFailures: Array<{
|
|
544
|
+
streamId: Id<"streamingMessages">;
|
|
545
|
+
reason: string;
|
|
546
|
+
}>;
|
|
547
|
+
}> {
|
|
524
548
|
// See if there are any streaming messages for this order
|
|
525
549
|
const streamingMessages = await getStreamingMessages(
|
|
526
550
|
ctx,
|
|
@@ -528,50 +552,42 @@ export async function getStreamingMessagesWithMetadata(
|
|
|
528
552
|
order,
|
|
529
553
|
stepOrder,
|
|
530
554
|
);
|
|
531
|
-
const
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
.
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
const
|
|
541
|
-
|
|
542
|
-
[publicStreamMessage(streamingMessage)],
|
|
543
|
-
deltas,
|
|
544
|
-
);
|
|
555
|
+
const materializedStreams = await Promise.all(
|
|
556
|
+
streamingMessages.map(async (streamingMessage) => {
|
|
557
|
+
const deltas = await ctx.db
|
|
558
|
+
.query("streamDeltas")
|
|
559
|
+
.withIndex("streamId_start_end", (q) =>
|
|
560
|
+
q.eq("streamId", streamingMessage._id),
|
|
561
|
+
)
|
|
562
|
+
.take(1000);
|
|
563
|
+
try {
|
|
564
|
+
const streamMessage = publicStreamMessage(streamingMessage);
|
|
565
|
+
const { parts } = getPersistedUIMessageChunkParts(deltas);
|
|
545
566
|
// We don't save messages that have already been saved
|
|
546
567
|
const numToSkip = stepOrder - streamingMessage.stepOrder;
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
return messages;
|
|
573
|
-
}),
|
|
574
|
-
)
|
|
575
|
-
).flat();
|
|
576
|
-
return messages;
|
|
568
|
+
return {
|
|
569
|
+
messages: projectPersistedUIMessageChunks(
|
|
570
|
+
streamMessage,
|
|
571
|
+
parts,
|
|
572
|
+
metadata,
|
|
573
|
+
).slice(numToSkip),
|
|
574
|
+
failure: undefined,
|
|
575
|
+
};
|
|
576
|
+
} catch (error) {
|
|
577
|
+
return {
|
|
578
|
+
messages: [],
|
|
579
|
+
failure: {
|
|
580
|
+
streamId: streamingMessage._id,
|
|
581
|
+
reason: error instanceof Error ? error.message : String(error),
|
|
582
|
+
},
|
|
583
|
+
};
|
|
584
|
+
}
|
|
585
|
+
}),
|
|
586
|
+
);
|
|
587
|
+
return {
|
|
588
|
+
messages: materializedStreams.flatMap(({ messages }) => messages),
|
|
589
|
+
materializationFailures: materializedStreams.flatMap(({ failure }) =>
|
|
590
|
+
failure ? [failure] : [],
|
|
591
|
+
),
|
|
592
|
+
};
|
|
577
593
|
}
|
package/src/component/threads.ts
CHANGED
|
@@ -3,8 +3,11 @@ import { paginator } from "convex-helpers/server/pagination";
|
|
|
3
3
|
import { partial } from "convex-helpers/validators";
|
|
4
4
|
import { paginationOptsValidator } from "convex/server";
|
|
5
5
|
import type { ObjectType } from "convex/values";
|
|
6
|
-
import {
|
|
7
|
-
|
|
6
|
+
import {
|
|
7
|
+
type ThreadDoc,
|
|
8
|
+
vPaginationResult,
|
|
9
|
+
vThreadDoc,
|
|
10
|
+
} from "../validators.js";
|
|
8
11
|
import { api, internal } from "./_generated/api.js";
|
|
9
12
|
import type { Doc } from "./_generated/dataModel.js";
|
|
10
13
|
import {
|
|
@@ -32,7 +35,7 @@ function publicThread(thread: Doc<"threads">): ThreadDoc {
|
|
|
32
35
|
export const getThread = query({
|
|
33
36
|
args: { threadId: v.id("threads") },
|
|
34
37
|
handler: async (ctx, args) => {
|
|
35
|
-
return publicThreadOrNull(await ctx.db.get(args.threadId));
|
|
38
|
+
return publicThreadOrNull(await ctx.db.get("threads", args.threadId));
|
|
36
39
|
},
|
|
37
40
|
returns: v.union(vThreadDoc, v.null()),
|
|
38
41
|
});
|
|
@@ -66,7 +69,7 @@ export const createThread = mutation({
|
|
|
66
69
|
...args,
|
|
67
70
|
status: "active",
|
|
68
71
|
});
|
|
69
|
-
return publicThread((await ctx.db.get(threadId))!);
|
|
72
|
+
return publicThread((await ctx.db.get("threads", threadId))!);
|
|
70
73
|
},
|
|
71
74
|
returns: vThreadDoc,
|
|
72
75
|
});
|
|
@@ -84,10 +87,10 @@ export const updateThread = mutation({
|
|
|
84
87
|
patch: v.object(partial(pick(vThread.fields, threadFieldsSupportingPatch))),
|
|
85
88
|
},
|
|
86
89
|
handler: async (ctx, args) => {
|
|
87
|
-
const thread = await ctx.db.get(args.threadId);
|
|
90
|
+
const thread = await ctx.db.get("threads", args.threadId);
|
|
88
91
|
assert(thread, `Thread ${args.threadId} not found`);
|
|
89
|
-
await ctx.db.patch(args.threadId, args.patch);
|
|
90
|
-
return publicThread((await ctx.db.get(args.threadId))!);
|
|
92
|
+
await ctx.db.patch("threads", args.threadId, args.patch);
|
|
93
|
+
return publicThread((await ctx.db.get("threads", args.threadId))!);
|
|
91
94
|
},
|
|
92
95
|
returns: vThreadDoc,
|
|
93
96
|
});
|
|
@@ -231,9 +234,9 @@ async function deletePageForThreadIdHandler(
|
|
|
231
234
|
});
|
|
232
235
|
await Promise.all(messages.page.map((m) => deleteMessage(ctx, m)));
|
|
233
236
|
if (messages.isDone) {
|
|
234
|
-
const thread = await ctx.db.get(args.threadId);
|
|
237
|
+
const thread = await ctx.db.get("threads", args.threadId);
|
|
235
238
|
if (thread) {
|
|
236
|
-
await ctx.db.delete(args.threadId);
|
|
239
|
+
await ctx.db.delete("threads", args.threadId);
|
|
237
240
|
}
|
|
238
241
|
}
|
|
239
242
|
return {
|
package/src/component/users.ts
CHANGED
|
@@ -227,7 +227,7 @@ async function deletePageForUserId(
|
|
|
227
227
|
|
|
228
228
|
if (streamResult.isDone) {
|
|
229
229
|
// Streams are done, delete the thread and reset for next thread
|
|
230
|
-
await ctx.db.delete(threadInProgress);
|
|
230
|
+
await ctx.db.delete("threads", threadInProgress);
|
|
231
231
|
threadInProgress = null;
|
|
232
232
|
messagesCursor = null;
|
|
233
233
|
streamsInProgress = false;
|
|
@@ -256,7 +256,7 @@ export const getThreadUserId = internalQuery({
|
|
|
256
256
|
},
|
|
257
257
|
returns: v.union(v.string(), v.null()),
|
|
258
258
|
handler: async (ctx, args) => {
|
|
259
|
-
const thread = await ctx.db.get(args.threadId);
|
|
259
|
+
const thread = await ctx.db.get("threads", args.threadId);
|
|
260
260
|
return thread?.userId ?? null;
|
|
261
261
|
},
|
|
262
262
|
});
|