@convex-dev/agent 0.0.16 → 0.0.17-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/README.md +159 -98
- package/dist/commonjs/client/index.d.ts +806 -189
- package/dist/commonjs/client/index.d.ts.map +1 -1
- package/dist/commonjs/client/index.js +178 -28
- package/dist/commonjs/client/index.js.map +1 -1
- package/dist/commonjs/client/playground.d.ts +609 -0
- package/dist/commonjs/client/playground.d.ts.map +1 -0
- package/dist/commonjs/client/playground.js +200 -0
- package/dist/commonjs/client/playground.js.map +1 -0
- package/dist/commonjs/component/apiKeys.d.ts +11 -0
- package/dist/commonjs/component/apiKeys.d.ts.map +1 -0
- package/dist/commonjs/component/apiKeys.js +69 -0
- package/dist/commonjs/component/apiKeys.js.map +1 -0
- package/dist/commonjs/component/files.d.ts +31 -0
- package/dist/commonjs/component/files.d.ts.map +1 -0
- package/dist/commonjs/component/files.js +61 -0
- package/dist/commonjs/component/files.js.map +1 -0
- package/dist/commonjs/component/messages.d.ts +720 -676
- package/dist/commonjs/component/messages.d.ts.map +1 -1
- package/dist/commonjs/component/messages.js +99 -287
- package/dist/commonjs/component/messages.js.map +1 -1
- package/dist/commonjs/component/schema.d.ts +1124 -1324
- package/dist/commonjs/component/schema.d.ts.map +1 -1
- package/dist/commonjs/component/schema.js +26 -14
- package/dist/commonjs/component/schema.js.map +1 -1
- package/dist/commonjs/component/threads.d.ts +95 -0
- package/dist/commonjs/component/threads.d.ts.map +1 -0
- package/dist/commonjs/component/threads.js +151 -0
- package/dist/commonjs/component/threads.js.map +1 -0
- package/dist/commonjs/component/users.d.ts +37 -0
- package/dist/commonjs/component/users.d.ts.map +1 -0
- package/dist/commonjs/component/users.js +118 -0
- package/dist/commonjs/component/users.js.map +1 -0
- package/dist/commonjs/component/vector/index.d.ts.map +1 -1
- package/dist/commonjs/component/vector/index.js +4 -6
- package/dist/commonjs/component/vector/index.js.map +1 -1
- package/dist/commonjs/component/vector/tables.d.ts +10 -10
- package/dist/commonjs/component/vector/tables.d.ts.map +1 -1
- package/dist/commonjs/component/vector/tables.js.map +1 -1
- package/dist/commonjs/mapping.d.ts +7 -1
- package/dist/commonjs/mapping.d.ts.map +1 -1
- package/dist/commonjs/mapping.js +39 -18
- package/dist/commonjs/mapping.js.map +1 -1
- package/dist/commonjs/validators.d.ts +1669 -2340
- package/dist/commonjs/validators.d.ts.map +1 -1
- package/dist/commonjs/validators.js +35 -26
- package/dist/commonjs/validators.js.map +1 -1
- package/dist/esm/client/index.d.ts +806 -189
- package/dist/esm/client/index.d.ts.map +1 -1
- package/dist/esm/client/index.js +178 -28
- package/dist/esm/client/index.js.map +1 -1
- package/dist/esm/client/playground.d.ts +609 -0
- package/dist/esm/client/playground.d.ts.map +1 -0
- package/dist/esm/client/playground.js +200 -0
- package/dist/esm/client/playground.js.map +1 -0
- package/dist/esm/component/apiKeys.d.ts +11 -0
- package/dist/esm/component/apiKeys.d.ts.map +1 -0
- package/dist/esm/component/apiKeys.js +69 -0
- package/dist/esm/component/apiKeys.js.map +1 -0
- package/dist/esm/component/files.d.ts +31 -0
- package/dist/esm/component/files.d.ts.map +1 -0
- package/dist/esm/component/files.js +61 -0
- package/dist/esm/component/files.js.map +1 -0
- package/dist/esm/component/messages.d.ts +720 -676
- package/dist/esm/component/messages.d.ts.map +1 -1
- package/dist/esm/component/messages.js +99 -287
- package/dist/esm/component/messages.js.map +1 -1
- package/dist/esm/component/schema.d.ts +1124 -1324
- package/dist/esm/component/schema.d.ts.map +1 -1
- package/dist/esm/component/schema.js +26 -14
- package/dist/esm/component/schema.js.map +1 -1
- package/dist/esm/component/threads.d.ts +95 -0
- package/dist/esm/component/threads.d.ts.map +1 -0
- package/dist/esm/component/threads.js +151 -0
- package/dist/esm/component/threads.js.map +1 -0
- package/dist/esm/component/users.d.ts +37 -0
- package/dist/esm/component/users.d.ts.map +1 -0
- package/dist/esm/component/users.js +118 -0
- package/dist/esm/component/users.js.map +1 -0
- package/dist/esm/component/vector/index.d.ts.map +1 -1
- package/dist/esm/component/vector/index.js +4 -6
- package/dist/esm/component/vector/index.js.map +1 -1
- package/dist/esm/component/vector/tables.d.ts +10 -10
- package/dist/esm/component/vector/tables.d.ts.map +1 -1
- package/dist/esm/component/vector/tables.js.map +1 -1
- package/dist/esm/mapping.d.ts +7 -1
- package/dist/esm/mapping.d.ts.map +1 -1
- package/dist/esm/mapping.js +39 -18
- package/dist/esm/mapping.js.map +1 -1
- package/dist/esm/validators.d.ts +1669 -2340
- package/dist/esm/validators.d.ts.map +1 -1
- package/dist/esm/validators.js +35 -26
- package/dist/esm/validators.js.map +1 -1
- package/package.json +8 -1
- package/src/client/index.ts +220 -59
- package/src/client/playground.ts +257 -0
- package/src/component/_generated/api.d.ts +601 -400
- package/src/component/apiKeys.ts +74 -0
- package/src/component/files.ts +72 -0
- package/src/component/messages.test.ts +23 -0
- package/src/component/messages.ts +127 -341
- package/src/component/schema.ts +32 -13
- package/src/component/threads.ts +184 -0
- package/src/component/users.ts +145 -0
- package/src/component/vector/index.ts +5 -6
- package/src/component/vector/tables.ts +15 -15
- package/src/mapping.ts +65 -32
- package/src/validators.ts +47 -28
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import { assert
|
|
2
|
-
import { paginator } from "convex-helpers/server/pagination";
|
|
1
|
+
import { assert } from "convex-helpers";
|
|
3
2
|
import { mergedStream, stream } from "convex-helpers/server/stream";
|
|
4
|
-
import { nullable, partial } from "convex-helpers/validators";
|
|
5
3
|
import { ObjectType } from "convex/values";
|
|
6
4
|
import {
|
|
7
5
|
DEFAULT_MESSAGE_RANGE,
|
|
@@ -20,7 +18,6 @@ import { api, internal } from "./_generated/api.js";
|
|
|
20
18
|
import { Doc, Id } from "./_generated/dataModel.js";
|
|
21
19
|
import {
|
|
22
20
|
action,
|
|
23
|
-
internalMutation,
|
|
24
21
|
internalQuery,
|
|
25
22
|
mutation,
|
|
26
23
|
MutationCtx,
|
|
@@ -35,293 +32,40 @@ import {
|
|
|
35
32
|
VectorTableId,
|
|
36
33
|
vVectorId,
|
|
37
34
|
} from "./vector/tables.js";
|
|
35
|
+
import {
|
|
36
|
+
listThreadsByUserId as _listThreadsByUserId,
|
|
37
|
+
getThread as _getThread,
|
|
38
|
+
updateThread as _updateThread,
|
|
39
|
+
} from "./threads.js";
|
|
38
40
|
import { paginationOptsValidator } from "convex/server";
|
|
39
41
|
|
|
40
|
-
export const getThread = query({
|
|
41
|
-
args: { threadId: v.id("threads") },
|
|
42
|
-
handler: async (ctx, args) => {
|
|
43
|
-
return ctx.db.get(args.threadId);
|
|
44
|
-
},
|
|
45
|
-
returns: v.union(v.doc("threads"), v.null()),
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
export const getThreadsByUserId = query({
|
|
49
|
-
args: {
|
|
50
|
-
userId: v.string(),
|
|
51
|
-
order: v.optional(v.union(v.literal("asc"), v.literal("desc"))),
|
|
52
|
-
paginationOpts: v.optional(paginationOptsValidator),
|
|
53
|
-
},
|
|
54
|
-
handler: async (ctx, args) => {
|
|
55
|
-
const threads = await paginator(ctx.db, schema)
|
|
56
|
-
.query("threads")
|
|
57
|
-
.withIndex("userId", (q) => q.eq("userId", args.userId))
|
|
58
|
-
.order(args.order ?? "desc")
|
|
59
|
-
.paginate(args.paginationOpts ?? { cursor: null, numItems: 100 });
|
|
60
|
-
return threads;
|
|
61
|
-
},
|
|
62
|
-
returns: paginationResultValidator(v.doc("threads")),
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
const vThread = schema.tables.threads.validator;
|
|
66
|
-
|
|
67
|
-
export const createThread = mutation({
|
|
68
|
-
args: omit(vThread.fields, ["order", "status"]),
|
|
69
|
-
handler: async (ctx, args) => {
|
|
70
|
-
const threadId = await ctx.db.insert("threads", {
|
|
71
|
-
...args,
|
|
72
|
-
status: "active",
|
|
73
|
-
});
|
|
74
|
-
return (await ctx.db.get(threadId))!;
|
|
75
|
-
},
|
|
76
|
-
returns: v.doc("threads"),
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
export const updateThread = mutation({
|
|
80
|
-
args: {
|
|
81
|
-
threadId: v.id("threads"),
|
|
82
|
-
patch: v.object(
|
|
83
|
-
partial(pick(vThread.fields, ["title", "summary", "status"]))
|
|
84
|
-
),
|
|
85
|
-
},
|
|
86
|
-
handler: async (ctx, args) => {
|
|
87
|
-
const thread = await ctx.db.get(args.threadId);
|
|
88
|
-
assert(thread, `Thread ${args.threadId} not found`);
|
|
89
|
-
await ctx.db.patch(args.threadId, args.patch);
|
|
90
|
-
return (await ctx.db.get(args.threadId))!;
|
|
91
|
-
},
|
|
92
|
-
returns: v.doc("threads"),
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
// When we expose this, we need to also hide all the messages and steps
|
|
96
|
-
// export const archiveThread = mutation({
|
|
97
|
-
// args: { threadId: v.id("threads") },
|
|
98
|
-
// handler: async (ctx, args) => {
|
|
99
|
-
// const thread = await ctx.db.get(args.threadId);
|
|
100
|
-
// assert(thread, `Thread ${args.threadId} not found`);
|
|
101
|
-
// await ctx.db.patch(args.threadId, { status: "archived" });
|
|
102
|
-
// return (await ctx.db.get(args.threadId))!;
|
|
103
|
-
// },
|
|
104
|
-
// returns: v.doc("threads"),
|
|
105
|
-
// });
|
|
106
|
-
|
|
107
|
-
export const deleteAllForUserId = action({
|
|
108
|
-
args: { userId: v.string() },
|
|
109
|
-
handler: async (ctx, args) => {
|
|
110
|
-
let messagesCursor = null;
|
|
111
|
-
let threadsCursor = null;
|
|
112
|
-
let isDone = false;
|
|
113
|
-
while (!isDone) {
|
|
114
|
-
const result: {
|
|
115
|
-
messagesCursor: string;
|
|
116
|
-
threadsCursor: string | null;
|
|
117
|
-
isDone: boolean;
|
|
118
|
-
} = await ctx.runMutation(internal.messages._deletePageForUserId, {
|
|
119
|
-
userId: args.userId,
|
|
120
|
-
messagesCursor,
|
|
121
|
-
threadsCursor,
|
|
122
|
-
});
|
|
123
|
-
messagesCursor = result.messagesCursor;
|
|
124
|
-
threadsCursor = result.threadsCursor;
|
|
125
|
-
isDone = result.isDone;
|
|
126
|
-
}
|
|
127
|
-
},
|
|
128
|
-
returns: v.null(),
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
export const deleteAllForUserIdAsync = mutation({
|
|
132
|
-
args: {
|
|
133
|
-
userId: v.string(),
|
|
134
|
-
},
|
|
135
|
-
handler: async (ctx, args) => {
|
|
136
|
-
const isDone = await deleteAllForUserIdAsyncHandler(ctx, {
|
|
137
|
-
userId: args.userId,
|
|
138
|
-
messagesCursor: null,
|
|
139
|
-
threadsCursor: null,
|
|
140
|
-
});
|
|
141
|
-
return isDone;
|
|
142
|
-
},
|
|
143
|
-
returns: v.boolean(),
|
|
144
|
-
});
|
|
145
42
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
messagesCursor: nullable(v.string()),
|
|
149
|
-
threadsCursor: nullable(v.string()),
|
|
150
|
-
};
|
|
151
|
-
type DeleteAllArgs = ObjectType<typeof deleteAllArgs>;
|
|
152
|
-
const deleteAllReturns = {
|
|
153
|
-
messagesCursor: v.string(),
|
|
154
|
-
threadsCursor: nullable(v.string()),
|
|
155
|
-
isDone: v.boolean(),
|
|
156
|
-
};
|
|
157
|
-
type DeleteAllReturns = ObjectType<typeof deleteAllReturns>;
|
|
43
|
+
/** @deprecated Use *.threads.listMessagesByThreadId instead. */
|
|
44
|
+
export const listThreadsByUserId= _listThreadsByUserId
|
|
158
45
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
handler: deleteAllForUserIdAsyncHandler,
|
|
162
|
-
returns: v.boolean(),
|
|
163
|
-
});
|
|
46
|
+
/** @deprecated Use *.threads.getThread */
|
|
47
|
+
export const getThread = _getThread;
|
|
164
48
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
args: DeleteAllArgs
|
|
168
|
-
): Promise<boolean> {
|
|
169
|
-
const result = await deletePageForUserId(ctx, args);
|
|
170
|
-
if (!result.isDone) {
|
|
171
|
-
await ctx.scheduler.runAfter(
|
|
172
|
-
0,
|
|
173
|
-
internal.messages._deleteAllForUserIdAsync,
|
|
174
|
-
{
|
|
175
|
-
userId: args.userId,
|
|
176
|
-
messagesCursor: result.messagesCursor,
|
|
177
|
-
threadsCursor: result.threadsCursor,
|
|
178
|
-
}
|
|
179
|
-
);
|
|
180
|
-
}
|
|
181
|
-
return result.isDone;
|
|
182
|
-
}
|
|
49
|
+
/** @deprecated Use *.threads.updateThread instead */
|
|
50
|
+
export const updateThread= _updateThread;
|
|
183
51
|
|
|
184
|
-
export
|
|
185
|
-
args: deleteAllArgs,
|
|
186
|
-
handler: deletePageForUserId,
|
|
187
|
-
returns: deleteAllReturns,
|
|
188
|
-
});
|
|
189
|
-
async function deletePageForUserId(
|
|
52
|
+
export async function deleteMessage(
|
|
190
53
|
ctx: MutationCtx,
|
|
191
|
-
|
|
192
|
-
)
|
|
193
|
-
const threads = await paginator(ctx.db, schema)
|
|
194
|
-
.query("threads")
|
|
195
|
-
.withIndex("userId", (q) => q.eq("userId", args.userId))
|
|
196
|
-
.order("desc")
|
|
197
|
-
.paginate({
|
|
198
|
-
numItems: 100,
|
|
199
|
-
cursor: args.threadsCursor ?? null,
|
|
200
|
-
});
|
|
201
|
-
await Promise.all(threads.page.map((c) => ctx.db.delete(c._id)));
|
|
202
|
-
const messages = await paginator(ctx.db, schema)
|
|
203
|
-
.query("messages")
|
|
204
|
-
.withIndex("userId_status_tool_order_stepOrder", (q) =>
|
|
205
|
-
q.eq("userId", args.userId)
|
|
206
|
-
)
|
|
207
|
-
.order("desc")
|
|
208
|
-
.paginate({
|
|
209
|
-
numItems: 100,
|
|
210
|
-
cursor: args.messagesCursor ?? null,
|
|
211
|
-
});
|
|
212
|
-
await Promise.all(messages.page.map((m) => deleteMessage(ctx, m)));
|
|
213
|
-
return {
|
|
214
|
-
messagesCursor: messages.continueCursor,
|
|
215
|
-
threadsCursor: threads.continueCursor,
|
|
216
|
-
isDone: messages.isDone,
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
async function deleteMessage(ctx: MutationCtx, messageDoc: Doc<"messages">) {
|
|
54
|
+
messageDoc: Doc<"messages">
|
|
55
|
+
) {
|
|
221
56
|
await ctx.db.delete(messageDoc._id);
|
|
222
57
|
if (messageDoc.embeddingId) {
|
|
223
58
|
await ctx.db.delete(messageDoc.embeddingId);
|
|
224
59
|
}
|
|
225
|
-
|
|
226
|
-
|
|
60
|
+
for (const { fileId } of messageDoc.files ?? []) {
|
|
61
|
+
if (!fileId) continue;
|
|
62
|
+
const file = await ctx.db.get(fileId);
|
|
227
63
|
if (file) {
|
|
228
|
-
await ctx.db.patch(
|
|
64
|
+
await ctx.db.patch(fileId, { refcount: file.refcount - 1 });
|
|
229
65
|
}
|
|
230
66
|
}
|
|
231
67
|
}
|
|
232
68
|
|
|
233
|
-
const deleteThreadArgs = {
|
|
234
|
-
threadId: v.id("threads"),
|
|
235
|
-
cursor: v.optional(v.string()),
|
|
236
|
-
limit: v.optional(v.number()),
|
|
237
|
-
};
|
|
238
|
-
type DeleteThreadArgs = ObjectType<typeof deleteThreadArgs>;
|
|
239
|
-
const deleteThreadReturns = {
|
|
240
|
-
cursor: v.string(),
|
|
241
|
-
isDone: v.boolean(),
|
|
242
|
-
};
|
|
243
|
-
type DeleteThreadReturns = ObjectType<typeof deleteThreadReturns>;
|
|
244
|
-
|
|
245
|
-
export const deleteAllForThreadIdSync = action({
|
|
246
|
-
args: deleteThreadArgs,
|
|
247
|
-
handler: async (ctx, args) => {
|
|
248
|
-
const result: DeleteThreadReturns = await ctx.runMutation(
|
|
249
|
-
internal.messages._deletePageForThreadId,
|
|
250
|
-
{ threadId: args.threadId, cursor: args.cursor, limit: args.limit }
|
|
251
|
-
);
|
|
252
|
-
return result;
|
|
253
|
-
},
|
|
254
|
-
returns: deleteThreadReturns,
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
export const deleteAllForThreadIdAsync = mutation({
|
|
258
|
-
args: deleteThreadArgs,
|
|
259
|
-
handler: async (ctx, args) => {
|
|
260
|
-
const result = await deletePageForThreadIdHandler(ctx, args);
|
|
261
|
-
if (!result.isDone) {
|
|
262
|
-
await ctx.scheduler.runAfter(0, api.messages.deleteAllForThreadIdAsync, {
|
|
263
|
-
threadId: args.threadId,
|
|
264
|
-
cursor: result.cursor,
|
|
265
|
-
});
|
|
266
|
-
}
|
|
267
|
-
return result;
|
|
268
|
-
},
|
|
269
|
-
returns: deleteThreadReturns,
|
|
270
|
-
});
|
|
271
|
-
|
|
272
|
-
export const _deletePageForThreadId = internalMutation({
|
|
273
|
-
args: deleteThreadArgs,
|
|
274
|
-
handler: deletePageForThreadIdHandler,
|
|
275
|
-
returns: deleteThreadReturns,
|
|
276
|
-
});
|
|
277
|
-
|
|
278
|
-
async function deletePageForThreadIdHandler(
|
|
279
|
-
ctx: MutationCtx,
|
|
280
|
-
args: DeleteThreadArgs
|
|
281
|
-
): Promise<DeleteThreadReturns> {
|
|
282
|
-
const messages = await paginator(ctx.db, schema)
|
|
283
|
-
.query("messages")
|
|
284
|
-
.withIndex("threadId_status_tool_order_stepOrder", (q) =>
|
|
285
|
-
q.eq("threadId", args.threadId)
|
|
286
|
-
)
|
|
287
|
-
.paginate({
|
|
288
|
-
numItems: args.limit ?? 100,
|
|
289
|
-
cursor: args.cursor ?? null,
|
|
290
|
-
});
|
|
291
|
-
await Promise.all(messages.page.map((m) => deleteMessage(ctx, m)));
|
|
292
|
-
await ctx.db.delete(args.threadId);
|
|
293
|
-
return {
|
|
294
|
-
cursor: messages.continueCursor,
|
|
295
|
-
isDone: messages.isDone,
|
|
296
|
-
};
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
export const getFilesToDelete = query({
|
|
300
|
-
args: {
|
|
301
|
-
cursor: v.optional(v.string()),
|
|
302
|
-
limit: v.optional(v.number()),
|
|
303
|
-
},
|
|
304
|
-
handler: async (ctx, args) => {
|
|
305
|
-
const files = await paginator(ctx.db, schema)
|
|
306
|
-
.query("files")
|
|
307
|
-
.withIndex("refcount", (q) => q.eq("refcount", 0))
|
|
308
|
-
.paginate({
|
|
309
|
-
numItems: args.limit ?? 100,
|
|
310
|
-
cursor: args.cursor ?? null,
|
|
311
|
-
});
|
|
312
|
-
return {
|
|
313
|
-
files: files.page,
|
|
314
|
-
continueCursor: files.continueCursor,
|
|
315
|
-
isDone: files.isDone,
|
|
316
|
-
};
|
|
317
|
-
},
|
|
318
|
-
returns: v.object({
|
|
319
|
-
files: v.array(v.doc("files")),
|
|
320
|
-
continueCursor: v.string(),
|
|
321
|
-
isDone: v.boolean(),
|
|
322
|
-
}),
|
|
323
|
-
});
|
|
324
|
-
|
|
325
69
|
export const vMessageDoc = schema.tables.messages.validator;
|
|
326
70
|
export const messageStatuses = vMessageDoc.fields.status.members.map(
|
|
327
71
|
(m) => m.value
|
|
@@ -358,9 +102,7 @@ async function addMessagesHandler(
|
|
|
358
102
|
}
|
|
359
103
|
const { failPendingSteps, pending, messages, parentMessageId, ...rest } =
|
|
360
104
|
args;
|
|
361
|
-
|
|
362
|
-
// TODO: I think this is a bug - parent will be pending always?
|
|
363
|
-
if (failPendingSteps && parent?.status !== "pending") {
|
|
105
|
+
if (failPendingSteps) {
|
|
364
106
|
assert(args.threadId, "threadId is required to fail pending steps");
|
|
365
107
|
const pendingMessages = await ctx.db
|
|
366
108
|
.query("messages")
|
|
@@ -376,9 +118,11 @@ async function addMessagesHandler(
|
|
|
376
118
|
}
|
|
377
119
|
const maxMessage = await getMaxMessage(ctx, threadId, userId);
|
|
378
120
|
let order = maxMessage?.order ?? -1;
|
|
121
|
+
let stepOrder = maxMessage?.stepOrder ?? 0;
|
|
122
|
+
let lastMessageIsTool = maxMessage?.tool ?? false;
|
|
379
123
|
const toReturn: Doc<"messages">[] = [];
|
|
380
124
|
if (messages.length > 0) {
|
|
381
|
-
for (const { message,
|
|
125
|
+
for (const { message, files, embedding, ...fields } of messages) {
|
|
382
126
|
let embeddingId: VectorTableId | undefined;
|
|
383
127
|
if (embedding) {
|
|
384
128
|
embeddingId = await insertVector(ctx, embedding.dimension, {
|
|
@@ -390,9 +134,13 @@ async function addMessagesHandler(
|
|
|
390
134
|
});
|
|
391
135
|
}
|
|
392
136
|
const tool = isTool(message);
|
|
393
|
-
if (
|
|
137
|
+
if (lastMessageIsTool) {
|
|
138
|
+
stepOrder++;
|
|
139
|
+
} else {
|
|
394
140
|
order++;
|
|
141
|
+
stepOrder = 0;
|
|
395
142
|
}
|
|
143
|
+
lastMessageIsTool = tool;
|
|
396
144
|
const text = extractText(message);
|
|
397
145
|
const messageId = await ctx.db.insert("messages", {
|
|
398
146
|
...rest,
|
|
@@ -404,11 +152,17 @@ async function addMessagesHandler(
|
|
|
404
152
|
order,
|
|
405
153
|
tool,
|
|
406
154
|
text,
|
|
407
|
-
|
|
155
|
+
files,
|
|
408
156
|
status: pending ? "pending" : "success",
|
|
409
|
-
stepOrder
|
|
157
|
+
stepOrder,
|
|
410
158
|
});
|
|
411
|
-
if (
|
|
159
|
+
if (!fields.id) {
|
|
160
|
+
await ctx.db.patch(messageId, {
|
|
161
|
+
id: messageId,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
for (const { fileId } of files ?? []) {
|
|
165
|
+
if (!fileId) continue;
|
|
412
166
|
await ctx.db.patch(fileId, {
|
|
413
167
|
refcount: (await ctx.db.get(fileId))!.refcount + 1,
|
|
414
168
|
});
|
|
@@ -419,7 +173,8 @@ async function addMessagesHandler(
|
|
|
419
173
|
return { messages: toReturn };
|
|
420
174
|
}
|
|
421
175
|
|
|
422
|
-
|
|
176
|
+
// exported for tests
|
|
177
|
+
export async function getMaxMessage(
|
|
423
178
|
ctx: QueryCtx,
|
|
424
179
|
threadId: Id<"threads"> | undefined,
|
|
425
180
|
userId: string | undefined
|
|
@@ -427,46 +182,39 @@ async function getMaxMessage(
|
|
|
427
182
|
assert(threadId || userId, "One of threadId or userId is required");
|
|
428
183
|
if (threadId) {
|
|
429
184
|
return mergedStream(
|
|
430
|
-
[
|
|
431
|
-
|
|
432
|
-
.
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
185
|
+
[true, false].flatMap((tool) =>
|
|
186
|
+
["success" as const, "pending" as const].map((status) =>
|
|
187
|
+
stream(ctx.db, schema)
|
|
188
|
+
.query("messages")
|
|
189
|
+
.withIndex("threadId_status_tool_order_stepOrder", (q) =>
|
|
190
|
+
q.eq("threadId", threadId).eq("status", status).eq("tool", tool)
|
|
191
|
+
)
|
|
192
|
+
.order("desc")
|
|
193
|
+
)
|
|
437
194
|
),
|
|
438
195
|
["order", "stepOrder"]
|
|
439
196
|
).first();
|
|
440
197
|
} else {
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
.order("desc")
|
|
455
|
-
.first();
|
|
456
|
-
return maxPending
|
|
457
|
-
? maxSuccess
|
|
458
|
-
? maxPending.order > maxSuccess.order
|
|
459
|
-
? maxPending
|
|
460
|
-
: maxSuccess
|
|
461
|
-
: maxPending
|
|
462
|
-
: maxSuccess ?? null;
|
|
198
|
+
return mergedStream(
|
|
199
|
+
[true, false].flatMap((tool) =>
|
|
200
|
+
["success" as const, "pending" as const].map((status) =>
|
|
201
|
+
stream(ctx.db, schema)
|
|
202
|
+
.query("messages")
|
|
203
|
+
.withIndex("userId_status_tool_order_stepOrder", (q) =>
|
|
204
|
+
q.eq("userId", userId).eq("status", status).eq("tool", tool)
|
|
205
|
+
)
|
|
206
|
+
.order("desc")
|
|
207
|
+
)
|
|
208
|
+
),
|
|
209
|
+
["order", "stepOrder"]
|
|
210
|
+
).first();
|
|
463
211
|
}
|
|
464
212
|
}
|
|
465
213
|
|
|
466
214
|
const addStepArgs = {
|
|
467
215
|
userId: v.optional(v.string()),
|
|
468
216
|
threadId: v.id("threads"),
|
|
469
|
-
|
|
217
|
+
parentMessageId: v.id("messages"),
|
|
470
218
|
step: vStepWithMessages,
|
|
471
219
|
failPendingSteps: v.optional(v.boolean()),
|
|
472
220
|
};
|
|
@@ -480,15 +228,16 @@ async function addStepHandler(
|
|
|
480
228
|
ctx: MutationCtx,
|
|
481
229
|
args: ObjectType<typeof addStepArgs>
|
|
482
230
|
) {
|
|
483
|
-
const parentMessage = await ctx.db.get(args.
|
|
484
|
-
assert(parentMessage, `Message ${args.
|
|
231
|
+
const parentMessage = await ctx.db.get(args.parentMessageId);
|
|
232
|
+
assert(parentMessage, `Message ${args.parentMessageId} not found`);
|
|
485
233
|
const order = parentMessage.order;
|
|
486
|
-
assert(order !== undefined, `${args.
|
|
234
|
+
assert(order !== undefined, `${args.parentMessageId} has no order`);
|
|
235
|
+
// TODO: only fetch the last one if we aren't failing pending steps
|
|
487
236
|
let steps = await ctx.db
|
|
488
237
|
.query("steps")
|
|
489
238
|
.withIndex("parentMessageId_order_stepOrder", (q) =>
|
|
490
239
|
// TODO: fetch pending, and commit later
|
|
491
|
-
q.eq("parentMessageId", args.
|
|
240
|
+
q.eq("parentMessageId", args.parentMessageId)
|
|
492
241
|
)
|
|
493
242
|
.collect();
|
|
494
243
|
if (args.failPendingSteps) {
|
|
@@ -502,7 +251,7 @@ async function addStepHandler(
|
|
|
502
251
|
const { step, messages } = args.step;
|
|
503
252
|
const stepId = await ctx.db.insert("steps", {
|
|
504
253
|
threadId: args.threadId,
|
|
505
|
-
parentMessageId: args.
|
|
254
|
+
parentMessageId: args.parentMessageId,
|
|
506
255
|
order,
|
|
507
256
|
stepOrder: (steps.at(-1)?.stepOrder ?? -1) + 1,
|
|
508
257
|
status: step.finishReason === "stop" ? "success" : "pending",
|
|
@@ -512,7 +261,7 @@ async function addStepHandler(
|
|
|
512
261
|
userId: args.userId,
|
|
513
262
|
threadId: args.threadId,
|
|
514
263
|
stepId,
|
|
515
|
-
parentMessageId: args.
|
|
264
|
+
parentMessageId: args.parentMessageId,
|
|
516
265
|
agentName: parentMessage.agentName,
|
|
517
266
|
messages,
|
|
518
267
|
pending: step.finishReason === "stop" ? false : true,
|
|
@@ -520,7 +269,7 @@ async function addStepHandler(
|
|
|
520
269
|
});
|
|
521
270
|
// We don't commit if the parent is still pending.
|
|
522
271
|
if (step.finishReason === "stop") {
|
|
523
|
-
await commitMessageHandler(ctx, { messageId: args.
|
|
272
|
+
await commitMessageHandler(ctx, { messageId: args.parentMessageId });
|
|
524
273
|
}
|
|
525
274
|
steps.push((await ctx.db.get(stepId))!);
|
|
526
275
|
return steps;
|
|
@@ -602,21 +351,23 @@ async function commitMessageHandler(
|
|
|
602
351
|
}
|
|
603
352
|
}
|
|
604
353
|
|
|
605
|
-
export const
|
|
354
|
+
export const listMessagesByThreadId = query({
|
|
606
355
|
args: {
|
|
607
356
|
threadId: v.id("threads"),
|
|
608
|
-
|
|
357
|
+
excludeToolMessages: v.optional(v.boolean()),
|
|
358
|
+
/** @deprecated Use excludeToolMessages instead. */
|
|
359
|
+
isTool: v.optional(v.literal("use excludeToolMessages instead of this")),
|
|
609
360
|
order: v.optional(v.union(v.literal("asc"), v.literal("desc"))),
|
|
610
361
|
paginationOpts: v.optional(paginationOptsValidator),
|
|
611
362
|
statuses: v.optional(v.array(vMessageStatus)),
|
|
612
|
-
|
|
363
|
+
beforeMessageId: v.optional(v.id("messages")),
|
|
613
364
|
},
|
|
614
365
|
handler: async (ctx, args) => {
|
|
615
|
-
const statuses =
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
366
|
+
const statuses =
|
|
367
|
+
args.statuses ?? vMessageStatus.members.map((m) => m.value);
|
|
368
|
+
const before =
|
|
369
|
+
args.beforeMessageId && (await ctx.db.get(args.beforeMessageId));
|
|
370
|
+
const toolOptions = args.excludeToolMessages ? [false] : [true, false];
|
|
620
371
|
const order = args.order ?? "desc";
|
|
621
372
|
const streams = toolOptions.flatMap((tool) =>
|
|
622
373
|
statuses.map((status) =>
|
|
@@ -627,12 +378,18 @@ export const getThreadMessages = query({
|
|
|
627
378
|
.eq("threadId", args.threadId)
|
|
628
379
|
.eq("status", status)
|
|
629
380
|
.eq("tool", tool);
|
|
630
|
-
if (
|
|
631
|
-
return qq.lte("order",
|
|
381
|
+
if (before) {
|
|
382
|
+
return qq.lte("order", before.order);
|
|
632
383
|
}
|
|
633
384
|
return qq;
|
|
634
385
|
})
|
|
635
386
|
.order(order)
|
|
387
|
+
.filterWith(
|
|
388
|
+
async (m) =>
|
|
389
|
+
!before ||
|
|
390
|
+
m.order < before.order ||
|
|
391
|
+
(m.order === before.order && m.stepOrder < before.stepOrder)
|
|
392
|
+
)
|
|
636
393
|
)
|
|
637
394
|
);
|
|
638
395
|
const messages = await mergedStream(streams, [
|
|
@@ -649,11 +406,20 @@ export const getThreadMessages = query({
|
|
|
649
406
|
returns: paginationResultValidator(v.doc("messages")),
|
|
650
407
|
});
|
|
651
408
|
|
|
409
|
+
/** @deprecated Use listMessagesByThreadId instead. */
|
|
410
|
+
export const getThreadMessages = query({
|
|
411
|
+
args: { deprecated: v.literal("Use listMessagesByThreadId instead") },
|
|
412
|
+
handler: async () => {
|
|
413
|
+
throw new Error("Use listMessagesByThreadId instead of getThreadMessages");
|
|
414
|
+
},
|
|
415
|
+
returns: paginationResultValidator(v.doc("messages")),
|
|
416
|
+
});
|
|
417
|
+
|
|
652
418
|
export const searchMessages = action({
|
|
653
419
|
args: {
|
|
654
420
|
userId: v.optional(v.string()),
|
|
655
421
|
threadId: v.optional(v.id("threads")),
|
|
656
|
-
|
|
422
|
+
beforeMessageId: v.optional(v.id("messages")),
|
|
657
423
|
...vSearchOptions.fields,
|
|
658
424
|
},
|
|
659
425
|
returns: v.array(v.doc("messages")),
|
|
@@ -667,6 +433,7 @@ export const searchMessages = action({
|
|
|
667
433
|
threadId: args.threadId,
|
|
668
434
|
text: args.text,
|
|
669
435
|
limit,
|
|
436
|
+
beforeMessageId: args.beforeMessageId,
|
|
670
437
|
});
|
|
671
438
|
}
|
|
672
439
|
if (args.vector) {
|
|
@@ -697,7 +464,7 @@ export const searchMessages = action({
|
|
|
697
464
|
.sort((a, b) => b.score - a.score);
|
|
698
465
|
const vectorIds = vectorScores.slice(0, limit).map((v) => v.id);
|
|
699
466
|
const messages: Doc<"messages">[] = await ctx.runQuery(
|
|
700
|
-
internal.messages.
|
|
467
|
+
internal.messages._fetchSearchMessages,
|
|
701
468
|
{
|
|
702
469
|
userId: args.userId,
|
|
703
470
|
threadId: args.threadId,
|
|
@@ -706,7 +473,7 @@ export const searchMessages = action({
|
|
|
706
473
|
(m) => !vectorIds.includes(m.embeddingId!)
|
|
707
474
|
),
|
|
708
475
|
messageRange: args.messageRange ?? DEFAULT_MESSAGE_RANGE,
|
|
709
|
-
|
|
476
|
+
beforeMessageId: args.beforeMessageId,
|
|
710
477
|
limit,
|
|
711
478
|
}
|
|
712
479
|
);
|
|
@@ -716,20 +483,20 @@ export const searchMessages = action({
|
|
|
716
483
|
},
|
|
717
484
|
});
|
|
718
485
|
|
|
719
|
-
export const
|
|
486
|
+
export const _fetchSearchMessages = internalQuery({
|
|
720
487
|
args: {
|
|
721
488
|
userId: v.optional(v.string()),
|
|
722
489
|
threadId: v.optional(v.id("threads")),
|
|
723
490
|
vectorIds: v.array(vVectorId),
|
|
724
491
|
textSearchMessages: v.optional(v.array(v.doc("messages"))),
|
|
725
492
|
messageRange: v.object({ before: v.number(), after: v.number() }),
|
|
726
|
-
|
|
493
|
+
beforeMessageId: v.optional(v.id("messages")),
|
|
727
494
|
limit: v.number(),
|
|
728
495
|
},
|
|
729
496
|
returns: v.array(v.doc("messages")),
|
|
730
497
|
handler: async (ctx, args): Promise<Doc<"messages">[]> => {
|
|
731
|
-
const
|
|
732
|
-
args.
|
|
498
|
+
const beforeMessage =
|
|
499
|
+
args.beforeMessageId && (await ctx.db.get(args.beforeMessageId));
|
|
733
500
|
const { userId, threadId } = args;
|
|
734
501
|
assert(userId || threadId, "Specify userId or threadId to search");
|
|
735
502
|
let messages = (
|
|
@@ -753,7 +520,10 @@ export const _fetchVectorMessages = internalQuery({
|
|
|
753
520
|
m !== undefined &&
|
|
754
521
|
m !== null &&
|
|
755
522
|
!m.tool &&
|
|
756
|
-
(!
|
|
523
|
+
(!beforeMessage ||
|
|
524
|
+
m.order < beforeMessage.order ||
|
|
525
|
+
(m.order === beforeMessage.order &&
|
|
526
|
+
m.stepOrder < beforeMessage.stepOrder))
|
|
757
527
|
);
|
|
758
528
|
messages.push(...(args.textSearchMessages ?? []));
|
|
759
529
|
// TODO: prioritize more recent messages
|
|
@@ -844,9 +614,13 @@ export const textSearch = query({
|
|
|
844
614
|
userId: v.optional(v.string()),
|
|
845
615
|
text: v.string(),
|
|
846
616
|
limit: v.number(),
|
|
617
|
+
beforeMessageId: v.optional(v.id("messages")),
|
|
847
618
|
},
|
|
848
619
|
handler: async (ctx, args) => {
|
|
849
620
|
assert(args.userId || args.threadId, "Specify userId or threadId");
|
|
621
|
+
const beforeMessage =
|
|
622
|
+
args.beforeMessageId && (await ctx.db.get(args.beforeMessageId));
|
|
623
|
+
const order = beforeMessage?.order;
|
|
850
624
|
const messages = await ctx.db
|
|
851
625
|
.query("messages")
|
|
852
626
|
.withSearchIndex("text_search", (q) =>
|
|
@@ -855,9 +629,21 @@ export const textSearch = query({
|
|
|
855
629
|
: q.search("text", args.text).eq("threadId", args.threadId!)
|
|
856
630
|
)
|
|
857
631
|
// Just in case tool messages slip through
|
|
858
|
-
.filter((q) =>
|
|
632
|
+
.filter((q) => {
|
|
633
|
+
const qq = q.eq(q.field("tool"), false);
|
|
634
|
+
if (order) {
|
|
635
|
+
return q.and(qq, q.lte(q.field("order"), order));
|
|
636
|
+
}
|
|
637
|
+
return qq;
|
|
638
|
+
})
|
|
859
639
|
.take(args.limit);
|
|
860
|
-
return messages
|
|
640
|
+
return messages.filter(
|
|
641
|
+
(m) =>
|
|
642
|
+
!beforeMessage ||
|
|
643
|
+
m.order < beforeMessage.order ||
|
|
644
|
+
(m.order === beforeMessage.order &&
|
|
645
|
+
m.stepOrder < beforeMessage.stepOrder)
|
|
646
|
+
);
|
|
861
647
|
},
|
|
862
648
|
returns: v.array(v.doc("messages")),
|
|
863
649
|
});
|