@convex-dev/agent 0.1.18 → 0.2.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/dist/client/createTool.d.ts +30 -11
- package/dist/client/createTool.d.ts.map +1 -1
- package/dist/client/createTool.js +24 -10
- package/dist/client/createTool.js.map +1 -1
- package/dist/client/defaultComponent.d.ts +11 -0
- package/dist/client/defaultComponent.d.ts.map +1 -0
- package/dist/client/defaultComponent.js +7 -0
- package/dist/client/defaultComponent.js.map +1 -0
- package/dist/client/definePlaygroundAPI.d.ts +68 -23
- package/dist/client/definePlaygroundAPI.d.ts.map +1 -1
- package/dist/client/definePlaygroundAPI.js +7 -20
- package/dist/client/definePlaygroundAPI.js.map +1 -1
- package/dist/client/files.d.ts +14 -4
- package/dist/client/files.d.ts.map +1 -1
- package/dist/client/files.js +66 -11
- package/dist/client/files.js.map +1 -1
- package/dist/client/index.d.ts +323 -780
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +445 -543
- package/dist/client/index.js.map +1 -1
- package/dist/client/messages.d.ts +256 -0
- package/dist/client/messages.d.ts.map +1 -0
- package/dist/client/messages.js +97 -0
- package/dist/client/messages.js.map +1 -0
- package/dist/client/search.d.ts +35 -12
- package/dist/client/search.d.ts.map +1 -1
- package/dist/client/search.js +21 -4
- package/dist/client/search.js.map +1 -1
- package/dist/client/streaming.d.ts +21 -21
- package/dist/client/streaming.d.ts.map +1 -1
- package/dist/client/streaming.js +35 -40
- package/dist/client/streaming.js.map +1 -1
- package/dist/client/threads.d.ts +46 -0
- package/dist/client/threads.d.ts.map +1 -0
- package/dist/client/threads.js +49 -0
- package/dist/client/threads.js.map +1 -0
- package/dist/client/types.d.ts +159 -75
- package/dist/client/types.d.ts.map +1 -1
- package/dist/component/_generated/api.d.ts +261 -209
- package/dist/component/messages.d.ts +314 -105
- package/dist/component/messages.d.ts.map +1 -1
- package/dist/component/messages.js +141 -83
- package/dist/component/messages.js.map +1 -1
- package/dist/component/schema.d.ts +631 -870
- package/dist/component/schema.d.ts.map +1 -1
- package/dist/component/schema.js +11 -16
- package/dist/component/schema.js.map +1 -1
- package/dist/component/streams.d.ts +29 -149
- package/dist/component/streams.d.ts.map +1 -1
- package/dist/component/streams.js +104 -60
- package/dist/component/streams.js.map +1 -1
- package/dist/component/threads.d.ts +4 -4
- package/dist/component/users.d.ts +3 -3
- package/dist/mapping.d.ts +15 -16
- package/dist/mapping.d.ts.map +1 -1
- package/dist/mapping.js +208 -62
- package/dist/mapping.js.map +1 -1
- package/dist/parts.d.ts +3 -0
- package/dist/parts.d.ts.map +1 -0
- package/dist/parts.js +34 -0
- package/dist/parts.js.map +1 -0
- package/dist/react/SmoothText.d.ts +5 -0
- package/dist/react/SmoothText.d.ts.map +1 -0
- package/dist/react/SmoothText.js +6 -0
- package/dist/react/SmoothText.js.map +1 -0
- package/dist/react/deltas.d.ts +3 -5
- package/dist/react/deltas.d.ts.map +1 -1
- package/dist/react/deltas.js +89 -53
- package/dist/react/deltas.js.map +1 -1
- package/dist/react/index.d.ts +1 -0
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +31 -11
- package/dist/react/index.js.map +1 -1
- package/dist/react/optimisticallySendMessage.d.ts.map +1 -1
- package/dist/react/optimisticallySendMessage.js +2 -8
- package/dist/react/optimisticallySendMessage.js.map +1 -1
- package/dist/react/toUIMessages.d.ts +5 -4
- package/dist/react/toUIMessages.d.ts.map +1 -1
- package/dist/react/toUIMessages.js +103 -40
- package/dist/react/toUIMessages.js.map +1 -1
- package/dist/react/useSmoothText.d.ts +13 -12
- package/dist/react/useSmoothText.d.ts.map +1 -1
- package/dist/react/useSmoothText.js +1 -1
- package/dist/react/useSmoothText.js.map +1 -1
- package/dist/validators.d.ts +751 -1464
- package/dist/validators.d.ts.map +1 -1
- package/dist/validators.js +39 -80
- package/dist/validators.js.map +1 -1
- package/package.json +34 -30
- package/src/client/createTool.ts +66 -40
- package/src/client/defaultComponent.ts +17 -0
- package/src/client/definePlaygroundAPI.ts +17 -31
- package/src/client/files.ts +94 -17
- package/src/client/index.test.ts +28 -38
- package/src/client/index.ts +785 -977
- package/src/client/messages.ts +205 -0
- package/src/client/search.ts +37 -10
- package/src/client/streaming.ts +53 -56
- package/src/client/threads.ts +78 -0
- package/src/client/types.ts +239 -131
- package/src/component/_generated/api.d.ts +261 -209
- package/src/component/messages.test.ts +182 -40
- package/src/component/messages.ts +165 -108
- package/src/component/schema.ts +11 -17
- package/src/component/streams.ts +180 -69
- package/src/mapping.ts +253 -96
- package/src/parts.ts +39 -0
- package/src/react/SmoothText.tsx +9 -0
- package/src/react/deltas.test.ts +38 -42
- package/src/react/deltas.ts +116 -65
- package/src/react/index.ts +35 -13
- package/src/react/optimisticallySendMessage.ts +2 -8
- package/src/react/toUIMessages.test.ts +154 -36
- package/src/react/toUIMessages.ts +136 -57
- package/src/react/useSmoothText.ts +14 -15
- package/src/validators.test.ts +1 -117
- package/src/validators.ts +57 -107
- package/dist/client/listMessages.d.ts +0 -22
- package/dist/client/listMessages.d.ts.map +0 -1
- package/dist/client/listMessages.js +0 -25
- package/dist/client/listMessages.js.map +0 -1
- package/src/client/listMessages.ts +0 -38
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import { assert, omit } from "convex-helpers";
|
|
1
|
+
import { assert, omit, pick } from "convex-helpers";
|
|
2
2
|
import { mergedStream, stream } from "convex-helpers/server/stream";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
paginationOptsValidator,
|
|
5
|
+
type WithoutSystemFields,
|
|
6
|
+
} from "convex/server";
|
|
4
7
|
import type { ObjectType } from "convex/values";
|
|
5
8
|
import {
|
|
6
9
|
DEFAULT_MESSAGE_RANGE,
|
|
@@ -9,7 +12,7 @@ import {
|
|
|
9
12
|
isTool,
|
|
10
13
|
} from "../shared.js";
|
|
11
14
|
import {
|
|
12
|
-
|
|
15
|
+
vMessageEmbeddingsWithDimension,
|
|
13
16
|
vMessageStatus,
|
|
14
17
|
vMessageWithMetadataInternal,
|
|
15
18
|
vPaginationResult,
|
|
@@ -26,11 +29,6 @@ import {
|
|
|
26
29
|
} from "./_generated/server.js";
|
|
27
30
|
import type { MessageDoc } from "./schema.js";
|
|
28
31
|
import { schema, v, vMessageDoc } from "./schema.js";
|
|
29
|
-
import {
|
|
30
|
-
getThread as _getThread,
|
|
31
|
-
listThreadsByUserId as _listThreadsByUserId,
|
|
32
|
-
updateThread as _updateThread,
|
|
33
|
-
} from "./threads.js";
|
|
34
32
|
import { insertVector, searchVectors } from "./vector/index.js";
|
|
35
33
|
import {
|
|
36
34
|
type VectorDimension,
|
|
@@ -39,6 +37,8 @@ import {
|
|
|
39
37
|
vVectorId,
|
|
40
38
|
} from "./vector/tables.js";
|
|
41
39
|
import { changeRefcount } from "./files.js";
|
|
40
|
+
import { getStreamingMessagesWithMetadata } from "./streams.js";
|
|
41
|
+
import { partial } from "convex-helpers/validators";
|
|
42
42
|
|
|
43
43
|
function publicMessage(message: Doc<"messages">): MessageDoc {
|
|
44
44
|
return omit(message, ["parentMessageId", "stepId", "files"]);
|
|
@@ -58,9 +58,7 @@ export async function deleteMessage(
|
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
export const deleteByIds = mutation({
|
|
61
|
-
args: {
|
|
62
|
-
messageIds: v.array(v.id("messages")),
|
|
63
|
-
},
|
|
61
|
+
args: { messageIds: v.array(v.id("messages")) },
|
|
64
62
|
returns: v.array(v.id("messages")),
|
|
65
63
|
handler: async (ctx, args) => {
|
|
66
64
|
const deletedMessageIds = await Promise.all(
|
|
@@ -115,8 +113,8 @@ export const deleteByOrder = mutation({
|
|
|
115
113
|
await Promise.all(messages.map((m) => deleteMessage(ctx, m)));
|
|
116
114
|
return {
|
|
117
115
|
isDone: messages.length < 64,
|
|
118
|
-
lastOrder: messages
|
|
119
|
-
lastStepOrder: messages
|
|
116
|
+
lastOrder: messages.at(-1)?.order,
|
|
117
|
+
lastStepOrder: messages.at(-1)?.stepOrder,
|
|
120
118
|
};
|
|
121
119
|
},
|
|
122
120
|
});
|
|
@@ -127,16 +125,15 @@ const addMessagesArgs = {
|
|
|
127
125
|
promptMessageId: v.optional(v.id("messages")),
|
|
128
126
|
agentName: v.optional(v.string()),
|
|
129
127
|
messages: v.array(vMessageWithMetadataInternal),
|
|
130
|
-
embeddings: v.optional(
|
|
131
|
-
pending: v.optional(v.boolean()),
|
|
128
|
+
embeddings: v.optional(vMessageEmbeddingsWithDimension),
|
|
132
129
|
failPendingSteps: v.optional(v.boolean()),
|
|
130
|
+
// A pending message to update. If the pending message failed, abort.
|
|
131
|
+
pendingMessageId: v.optional(v.id("messages")),
|
|
133
132
|
};
|
|
134
133
|
export const addMessages = mutation({
|
|
135
134
|
args: addMessagesArgs,
|
|
136
135
|
handler: addMessagesHandler,
|
|
137
|
-
returns: v.object({
|
|
138
|
-
messages: v.array(vMessageDoc),
|
|
139
|
-
}),
|
|
136
|
+
returns: v.object({ messages: v.array(vMessageDoc) }),
|
|
140
137
|
});
|
|
141
138
|
async function addMessagesHandler(
|
|
142
139
|
ctx: MutationCtx,
|
|
@@ -152,12 +149,12 @@ async function addMessagesHandler(
|
|
|
152
149
|
const {
|
|
153
150
|
embeddings,
|
|
154
151
|
failPendingSteps,
|
|
155
|
-
pending,
|
|
156
152
|
messages,
|
|
157
153
|
promptMessageId,
|
|
154
|
+
pendingMessageId,
|
|
158
155
|
...rest
|
|
159
156
|
} = args;
|
|
160
|
-
const
|
|
157
|
+
const promptMessage = promptMessageId && (await ctx.db.get(promptMessageId));
|
|
161
158
|
if (failPendingSteps) {
|
|
162
159
|
assert(args.threadId, "threadId is required to fail pending steps");
|
|
163
160
|
const pendingMessages = await ctx.db
|
|
@@ -165,30 +162,41 @@ async function addMessagesHandler(
|
|
|
165
162
|
.withIndex("threadId_status_tool_order_stepOrder", (q) =>
|
|
166
163
|
q.eq("threadId", threadId).eq("status", "pending"),
|
|
167
164
|
)
|
|
168
|
-
.
|
|
165
|
+
.order("desc")
|
|
166
|
+
.take(100);
|
|
169
167
|
await Promise.all(
|
|
170
168
|
pendingMessages
|
|
171
|
-
.filter((m) => !
|
|
172
|
-
.
|
|
173
|
-
|
|
174
|
-
|
|
169
|
+
.filter((m) => !promptMessage || m.order === promptMessage.order)
|
|
170
|
+
.filter((m) => !pendingMessageId || m._id !== pendingMessageId)
|
|
171
|
+
.map(async (m) => {
|
|
172
|
+
if (m.embeddingId) {
|
|
173
|
+
await ctx.db.delete(m.embeddingId);
|
|
174
|
+
}
|
|
175
|
+
await ctx.db.patch(m._id, {
|
|
176
|
+
status: "failed",
|
|
177
|
+
error: "Restarting",
|
|
178
|
+
embeddingId: undefined,
|
|
179
|
+
});
|
|
180
|
+
}),
|
|
175
181
|
);
|
|
176
182
|
}
|
|
177
183
|
let order, stepOrder;
|
|
178
184
|
let fail = false;
|
|
185
|
+
let error: string | undefined;
|
|
179
186
|
if (promptMessageId) {
|
|
180
|
-
assert(
|
|
181
|
-
if (
|
|
187
|
+
assert(promptMessage, `Parent message ${promptMessageId} not found`);
|
|
188
|
+
if (promptMessage.status === "failed") {
|
|
182
189
|
fail = true;
|
|
190
|
+
error = promptMessage.error ?? error ?? "The prompt message failed";
|
|
183
191
|
}
|
|
184
|
-
order =
|
|
192
|
+
order = promptMessage.order;
|
|
185
193
|
// Defend against there being existing messages with this parent.
|
|
186
194
|
const maxMessage = await getMaxMessage(ctx, threadId, order);
|
|
187
|
-
stepOrder = maxMessage?.stepOrder ??
|
|
195
|
+
stepOrder = maxMessage?.stepOrder ?? promptMessage.stepOrder;
|
|
188
196
|
} else {
|
|
189
197
|
const maxMessage = await getMaxMessage(ctx, threadId);
|
|
190
|
-
order = maxMessage
|
|
191
|
-
stepOrder = -1;
|
|
198
|
+
order = maxMessage?.order ?? -1;
|
|
199
|
+
stepOrder = maxMessage?.stepOrder ?? -1;
|
|
192
200
|
}
|
|
193
201
|
const toReturn: Doc<"messages">[] = [];
|
|
194
202
|
if (embeddings) {
|
|
@@ -200,7 +208,12 @@ async function addMessagesHandler(
|
|
|
200
208
|
for (let i = 0; i < messages.length; i++) {
|
|
201
209
|
const message = messages[i];
|
|
202
210
|
let embeddingId: VectorTableId | undefined;
|
|
203
|
-
if (
|
|
211
|
+
if (
|
|
212
|
+
embeddings &&
|
|
213
|
+
embeddings.vectors[i] &&
|
|
214
|
+
!fail &&
|
|
215
|
+
message.status !== "failed"
|
|
216
|
+
) {
|
|
204
217
|
embeddingId = await insertVector(ctx, embeddings.dimension, {
|
|
205
218
|
vector: embeddings.vectors[i]!,
|
|
206
219
|
model: embeddings.model,
|
|
@@ -209,26 +222,68 @@ async function addMessagesHandler(
|
|
|
209
222
|
threadId,
|
|
210
223
|
});
|
|
211
224
|
}
|
|
212
|
-
|
|
213
|
-
const messageId = await ctx.db.insert("messages", {
|
|
225
|
+
const messageDoc = {
|
|
214
226
|
...rest,
|
|
215
227
|
...message,
|
|
216
228
|
embeddingId,
|
|
217
229
|
parentMessageId: promptMessageId,
|
|
218
230
|
userId,
|
|
219
|
-
order,
|
|
220
231
|
tool: isTool(message.message),
|
|
221
232
|
text: extractText(message.message),
|
|
222
|
-
status: fail ? "failed" :
|
|
223
|
-
error: fail ?
|
|
233
|
+
status: fail ? "failed" : (message.status ?? "success"),
|
|
234
|
+
error: fail ? error : message.error,
|
|
235
|
+
} satisfies Omit<
|
|
236
|
+
WithoutSystemFields<Doc<"messages">>,
|
|
237
|
+
"order" | "stepOrder"
|
|
238
|
+
>;
|
|
239
|
+
// If there is a pending message, we replace that one with the first message
|
|
240
|
+
// and subsequent ones will follow the regular order/subOrder advancement.
|
|
241
|
+
if (i === 0 && pendingMessageId) {
|
|
242
|
+
const pendingMessage = await ctx.db.get(pendingMessageId);
|
|
243
|
+
assert(pendingMessage, `Pending msg ${pendingMessageId} not found`);
|
|
244
|
+
if (pendingMessage.status === "failed") {
|
|
245
|
+
fail = true;
|
|
246
|
+
error =
|
|
247
|
+
`Trying to update a message that failed: ${pendingMessageId}, ` +
|
|
248
|
+
`error: ${pendingMessage.error ?? error}`;
|
|
249
|
+
messageDoc.status = "failed";
|
|
250
|
+
messageDoc.error = error;
|
|
251
|
+
}
|
|
252
|
+
if (message.fileIds) {
|
|
253
|
+
await changeRefcount(
|
|
254
|
+
ctx,
|
|
255
|
+
pendingMessage.fileIds ?? [],
|
|
256
|
+
message.fileIds,
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
await ctx.db.replace(pendingMessage._id, {
|
|
260
|
+
...messageDoc,
|
|
261
|
+
order: pendingMessage.order,
|
|
262
|
+
stepOrder: pendingMessage.stepOrder,
|
|
263
|
+
});
|
|
264
|
+
toReturn.push(pendingMessage);
|
|
265
|
+
continue;
|
|
266
|
+
}
|
|
267
|
+
if (message.message.role === "user") {
|
|
268
|
+
if (promptMessage && promptMessage.order === order) {
|
|
269
|
+
// see if there's a later message than the parent message order
|
|
270
|
+
const maxMessage = await getMaxMessage(ctx, threadId);
|
|
271
|
+
order = (maxMessage?.order ?? order) + 1;
|
|
272
|
+
} else {
|
|
273
|
+
order++;
|
|
274
|
+
}
|
|
275
|
+
stepOrder = 0;
|
|
276
|
+
} else {
|
|
277
|
+
if (order < 0) {
|
|
278
|
+
order = 0;
|
|
279
|
+
}
|
|
280
|
+
stepOrder++;
|
|
281
|
+
}
|
|
282
|
+
const messageId = await ctx.db.insert("messages", {
|
|
283
|
+
...messageDoc,
|
|
284
|
+
order,
|
|
224
285
|
stepOrder,
|
|
225
286
|
});
|
|
226
|
-
// Let's just not set the id field and have it set only in explicit cases.
|
|
227
|
-
// if (!message.id) {
|
|
228
|
-
// await ctx.db.patch(messageId, {
|
|
229
|
-
// id: messageId,
|
|
230
|
-
// });
|
|
231
|
-
// }
|
|
232
287
|
if (message.fileIds) {
|
|
233
288
|
await changeRefcount(ctx, [], message.fileIds);
|
|
234
289
|
}
|
|
@@ -263,7 +318,7 @@ function orderedMessagesStream(
|
|
|
263
318
|
.eq("threadId", threadId)
|
|
264
319
|
.eq("status", status)
|
|
265
320
|
.eq("tool", tool);
|
|
266
|
-
if (order) {
|
|
321
|
+
if (order !== undefined) {
|
|
267
322
|
return qq.eq("order", order);
|
|
268
323
|
}
|
|
269
324
|
return qq;
|
|
@@ -275,51 +330,77 @@ function orderedMessagesStream(
|
|
|
275
330
|
);
|
|
276
331
|
}
|
|
277
332
|
|
|
278
|
-
export const
|
|
333
|
+
export const finalizeMessage = mutation({
|
|
279
334
|
args: {
|
|
280
335
|
messageId: v.id("messages"),
|
|
281
|
-
|
|
336
|
+
result: v.union(
|
|
337
|
+
v.object({ status: v.literal("success") }),
|
|
338
|
+
v.object({ status: v.literal("failed"), error: v.string() }),
|
|
339
|
+
),
|
|
282
340
|
},
|
|
283
341
|
returns: v.null(),
|
|
284
|
-
handler: async (ctx, { messageId,
|
|
342
|
+
handler: async (ctx, { messageId, result }) => {
|
|
285
343
|
const message = await ctx.db.get(messageId);
|
|
286
344
|
assert(message, `Message ${messageId} not found`);
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
345
|
+
if (message.status !== "pending") {
|
|
346
|
+
console.log(
|
|
347
|
+
"Trying to finalize a message that's already",
|
|
348
|
+
message.status,
|
|
349
|
+
);
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
// See if we can add any in-progress data
|
|
353
|
+
if (message.message === undefined) {
|
|
354
|
+
const messages = await getStreamingMessagesWithMetadata(
|
|
355
|
+
ctx,
|
|
356
|
+
message,
|
|
357
|
+
result,
|
|
358
|
+
);
|
|
359
|
+
if (messages.length > 0) {
|
|
360
|
+
await addMessagesHandler(ctx, {
|
|
361
|
+
messages,
|
|
362
|
+
threadId: message.threadId,
|
|
363
|
+
agentName: message.agentName,
|
|
364
|
+
failPendingSteps: false,
|
|
365
|
+
pendingMessageId: messageId,
|
|
366
|
+
userId: message.userId,
|
|
367
|
+
embeddings: undefined,
|
|
368
|
+
});
|
|
369
|
+
return;
|
|
296
370
|
}
|
|
297
371
|
}
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
372
|
+
if (result.status === "failed") {
|
|
373
|
+
if (message.embeddingId) {
|
|
374
|
+
await ctx.db.delete(message.embeddingId);
|
|
375
|
+
}
|
|
376
|
+
await ctx.db.patch(messageId, {
|
|
377
|
+
status: "failed",
|
|
378
|
+
error: result.error,
|
|
379
|
+
embeddingId: undefined,
|
|
380
|
+
});
|
|
381
|
+
} else {
|
|
382
|
+
await ctx.db.patch(messageId, { status: "success" });
|
|
383
|
+
}
|
|
309
384
|
},
|
|
310
|
-
returns: v.null(),
|
|
311
|
-
handler: commitMessageHandler,
|
|
312
385
|
});
|
|
313
386
|
|
|
314
387
|
export const updateMessage = mutation({
|
|
315
388
|
args: {
|
|
316
389
|
messageId: v.id("messages"),
|
|
317
|
-
patch: v.object(
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
390
|
+
patch: v.object(
|
|
391
|
+
partial(
|
|
392
|
+
pick(schema.tables.messages.validator.fields, [
|
|
393
|
+
"message",
|
|
394
|
+
"fileIds",
|
|
395
|
+
"status",
|
|
396
|
+
"error",
|
|
397
|
+
"model",
|
|
398
|
+
"provider",
|
|
399
|
+
"providerOptions",
|
|
400
|
+
"finishReason",
|
|
401
|
+
]),
|
|
402
|
+
),
|
|
403
|
+
),
|
|
323
404
|
},
|
|
324
405
|
returns: vMessageDoc,
|
|
325
406
|
handler: async (ctx, args) => {
|
|
@@ -330,9 +411,7 @@ export const updateMessage = mutation({
|
|
|
330
411
|
await changeRefcount(ctx, message.fileIds ?? [], args.patch.fileIds);
|
|
331
412
|
}
|
|
332
413
|
|
|
333
|
-
const patch: Partial<Doc<"messages">> = {
|
|
334
|
-
...args.patch,
|
|
335
|
-
};
|
|
414
|
+
const patch: Partial<Doc<"messages">> = { ...args.patch };
|
|
336
415
|
|
|
337
416
|
if (args.patch.message !== undefined) {
|
|
338
417
|
patch.message = args.patch.message;
|
|
@@ -340,38 +419,18 @@ export const updateMessage = mutation({
|
|
|
340
419
|
patch.text = extractText(args.patch.message);
|
|
341
420
|
}
|
|
342
421
|
|
|
422
|
+
if (args.patch.status === "failed") {
|
|
423
|
+
if (message.embeddingId) {
|
|
424
|
+
await ctx.db.delete(message.embeddingId);
|
|
425
|
+
}
|
|
426
|
+
patch.embeddingId = undefined;
|
|
427
|
+
}
|
|
428
|
+
|
|
343
429
|
await ctx.db.patch(args.messageId, patch);
|
|
344
430
|
return publicMessage((await ctx.db.get(args.messageId))!);
|
|
345
431
|
},
|
|
346
432
|
});
|
|
347
433
|
|
|
348
|
-
async function commitMessageHandler(
|
|
349
|
-
ctx: MutationCtx,
|
|
350
|
-
{ messageId }: { messageId: Id<"messages"> },
|
|
351
|
-
) {
|
|
352
|
-
const message = await ctx.db.get(messageId);
|
|
353
|
-
assert(message, `Message ${messageId} not found`);
|
|
354
|
-
|
|
355
|
-
const order = message.order!;
|
|
356
|
-
const messages = await mergedStream(
|
|
357
|
-
[true, false].map((tool) =>
|
|
358
|
-
stream(ctx.db, schema)
|
|
359
|
-
.query("messages")
|
|
360
|
-
.withIndex("threadId_status_tool_order_stepOrder", (q) =>
|
|
361
|
-
q
|
|
362
|
-
.eq("threadId", message.threadId)
|
|
363
|
-
.eq("status", "pending")
|
|
364
|
-
.eq("tool", tool)
|
|
365
|
-
.eq("order", order),
|
|
366
|
-
),
|
|
367
|
-
),
|
|
368
|
-
["order", "stepOrder"],
|
|
369
|
-
).collect();
|
|
370
|
-
for (const message of messages) {
|
|
371
|
-
await ctx.db.patch(message._id, { status: "success" });
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
|
|
375
434
|
export const listMessagesByThreadId = query({
|
|
376
435
|
args: {
|
|
377
436
|
threadId: v.id("threads"),
|
|
@@ -431,9 +490,7 @@ export const listMessagesByThreadId = query({
|
|
|
431
490
|
});
|
|
432
491
|
|
|
433
492
|
export const getMessagesByIds = query({
|
|
434
|
-
args: {
|
|
435
|
-
messageIds: v.array(v.id("messages")),
|
|
436
|
-
},
|
|
493
|
+
args: { messageIds: v.array(v.id("messages")) },
|
|
437
494
|
handler: async (ctx, args) => {
|
|
438
495
|
return (await Promise.all(args.messageIds.map((id) => ctx.db.get(id)))).map(
|
|
439
496
|
(m) => (m ? publicMessage(m) : null),
|
package/src/component/schema.ts
CHANGED
|
@@ -6,12 +6,11 @@ import {
|
|
|
6
6
|
vMessageStatus,
|
|
7
7
|
vUsage,
|
|
8
8
|
vSource,
|
|
9
|
-
|
|
9
|
+
vLanguageModelCallWarning,
|
|
10
10
|
vFinishReason,
|
|
11
11
|
vProviderOptions,
|
|
12
12
|
vProviderMetadata,
|
|
13
13
|
vReasoningDetails,
|
|
14
|
-
vTextStreamPart,
|
|
15
14
|
} from "../validators.js";
|
|
16
15
|
import { typedV } from "convex-helpers/validators";
|
|
17
16
|
import vectorTables, { vVectorId } from "./vector/tables.js";
|
|
@@ -29,12 +28,8 @@ export const schema = defineSchema({
|
|
|
29
28
|
order: /*DEPRECATED*/ v.optional(v.number()),
|
|
30
29
|
})
|
|
31
30
|
.index("userId", ["userId"])
|
|
32
|
-
.searchIndex("title", {
|
|
33
|
-
searchField: "title",
|
|
34
|
-
filterFields: ["userId"],
|
|
35
|
-
}),
|
|
31
|
+
.searchIndex("title", { searchField: "title", filterFields: ["userId"] }),
|
|
36
32
|
messages: defineTable({
|
|
37
|
-
id: v.optional(v.string()), // external id, e.g. from Vercel AI SDK
|
|
38
33
|
userId: v.optional(v.string()), // useful for searching across threads
|
|
39
34
|
threadId: v.id("threads"),
|
|
40
35
|
order: v.number(),
|
|
@@ -60,11 +55,13 @@ export const schema = defineSchema({
|
|
|
60
55
|
usage: v.optional(vUsage),
|
|
61
56
|
providerMetadata: v.optional(vProviderMetadata), // Received from model
|
|
62
57
|
sources: v.optional(v.array(vSource)),
|
|
58
|
+
warnings: v.optional(v.array(vLanguageModelCallWarning)),
|
|
59
|
+
finishReason: v.optional(vFinishReason),
|
|
60
|
+
// Likely deprecated soon
|
|
63
61
|
reasoning: v.optional(v.string()),
|
|
64
62
|
reasoningDetails: v.optional(vReasoningDetails),
|
|
65
|
-
warnings: v.optional(v.array(vLanguageModelV1CallWarning)),
|
|
66
|
-
finishReason: v.optional(vFinishReason),
|
|
67
63
|
// DEPRECATED
|
|
64
|
+
id: v.optional(v.string()), // external id, e.g. from Vercel AI SDK
|
|
68
65
|
parentMessageId: v.optional(v.id("messages")),
|
|
69
66
|
stepId: v.optional(v.string()),
|
|
70
67
|
files: v.optional(v.array(v.any())),
|
|
@@ -115,10 +112,7 @@ export const schema = defineSchema({
|
|
|
115
112
|
endedAt: v.number(),
|
|
116
113
|
cleanupFnId: v.optional(v.id("_scheduled_functions")),
|
|
117
114
|
}),
|
|
118
|
-
v.object({
|
|
119
|
-
kind: v.literal("aborted"),
|
|
120
|
-
reason: v.string(),
|
|
121
|
-
}),
|
|
115
|
+
v.object({ kind: v.literal("aborted"), reason: v.string() }),
|
|
122
116
|
),
|
|
123
117
|
})
|
|
124
118
|
// There should only be one per "order" index
|
|
@@ -135,7 +129,7 @@ export const schema = defineSchema({
|
|
|
135
129
|
// the indexes work like: 0 <first> 1 <second> 2 <third> 3 ...
|
|
136
130
|
start: v.number(), // inclusive
|
|
137
131
|
end: v.number(), // exclusive
|
|
138
|
-
parts: v.array(
|
|
132
|
+
parts: v.array(v.any()),
|
|
139
133
|
}).index("streamId_start_end", ["streamId", "start", "end"]),
|
|
140
134
|
|
|
141
135
|
memories: defineTable({
|
|
@@ -162,9 +156,9 @@ export const schema = defineSchema({
|
|
|
162
156
|
// To authenticate playground usage
|
|
163
157
|
// Delete a key to invalidate it
|
|
164
158
|
// Provide a name to easily identify it / invalidate by name
|
|
165
|
-
apiKeys: defineTable({
|
|
166
|
-
name
|
|
167
|
-
|
|
159
|
+
apiKeys: defineTable({ name: v.optional(v.string()) }).index("name", [
|
|
160
|
+
"name",
|
|
161
|
+
]),
|
|
168
162
|
});
|
|
169
163
|
|
|
170
164
|
export const vv = typedV(schema);
|