@convex-dev/agent 0.1.16-alpha.0 → 0.1.16-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -15
- package/dist/client/createTool.d.ts +2 -2
- package/dist/client/createTool.d.ts.map +1 -1
- package/dist/client/createTool.js.map +1 -1
- package/dist/client/files.js +2 -2
- package/dist/client/files.js.map +1 -1
- package/dist/client/index.d.ts +2 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +47 -29
- package/dist/client/index.js.map +1 -1
- package/dist/client/search.d.ts +2 -3
- package/dist/client/search.d.ts.map +1 -1
- package/dist/client/search.js +2 -1
- package/dist/client/search.js.map +1 -1
- package/dist/client/types.d.ts +7 -9
- package/dist/client/types.d.ts.map +1 -1
- package/dist/component/messages.d.ts +1 -1
- package/dist/component/messages.d.ts.map +1 -1
- package/dist/component/messages.js +5 -5
- package/dist/component/messages.js.map +1 -1
- package/dist/component/schema.d.ts.map +1 -1
- package/dist/component/schema.js.map +1 -1
- package/dist/mapping.d.ts.map +1 -1
- package/dist/mapping.js +3 -1
- package/dist/mapping.js.map +1 -1
- package/dist/react/deltas.d.ts.map +1 -1
- package/dist/react/deltas.js +6 -5
- package/dist/react/deltas.js.map +1 -1
- package/dist/validators.js +1 -2
- package/dist/validators.js.map +1 -1
- package/package.json +1 -1
- package/src/client/createTool.ts +9 -6
- package/src/client/files.ts +8 -8
- package/src/client/index.test.ts +14 -12
- package/src/client/index.ts +127 -99
- package/src/client/listMessages.ts +1 -1
- package/src/client/search.ts +14 -14
- package/src/client/streaming.ts +7 -7
- package/src/client/types.ts +29 -23
- package/src/component/apiKeys.ts +1 -1
- package/src/component/files.test.ts +1 -1
- package/src/component/files.ts +6 -6
- package/src/component/messages.test.ts +6 -6
- package/src/component/messages.ts +44 -43
- package/src/component/schema.ts +1 -2
- package/src/component/streams.ts +27 -27
- package/src/component/threads.test.ts +4 -4
- package/src/component/threads.ts +4 -4
- package/src/component/users.test.ts +2 -2
- package/src/component/users.ts +4 -4
- package/src/component/vector/index.ts +11 -11
- package/src/component/vector/tables.ts +6 -6
- package/src/mapping.test.ts +4 -4
- package/src/mapping.ts +18 -17
- package/src/react/deltas.test.ts +16 -16
- package/src/react/deltas.ts +19 -18
- package/src/react/index.ts +11 -11
- package/src/react/optimisticallySendMessage.ts +2 -2
- package/src/react/toUIMessages.test.ts +10 -10
- package/src/react/toUIMessages.ts +6 -6
- package/src/react/useSmoothText.ts +6 -6
- package/src/validators.ts +24 -24
package/src/client/search.ts
CHANGED
|
@@ -16,9 +16,8 @@ import {
|
|
|
16
16
|
const DEFAULT_VECTOR_SCORE_THRESHOLD = 0.0;
|
|
17
17
|
|
|
18
18
|
export type GetEmbedding = (text: string) => Promise<{
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
vectorScoreThreshold?: number;
|
|
19
|
+
embedding: number[];
|
|
20
|
+
embeddingModel: string;
|
|
22
21
|
}>;
|
|
23
22
|
|
|
24
23
|
/**
|
|
@@ -44,7 +43,7 @@ export async function fetchContextMessages(
|
|
|
44
43
|
upToAndIncludingMessageId?: string;
|
|
45
44
|
contextOptions: ContextOptions;
|
|
46
45
|
getEmbedding?: GetEmbedding;
|
|
47
|
-
}
|
|
46
|
+
},
|
|
48
47
|
): Promise<MessageDoc[]> {
|
|
49
48
|
assert(args.userId || args.threadId, "Specify userId or threadId");
|
|
50
49
|
const opts = args.contextOptions;
|
|
@@ -67,17 +66,17 @@ export async function fetchContextMessages(
|
|
|
67
66
|
upToAndIncludingMessageId: args.upToAndIncludingMessageId,
|
|
68
67
|
order: "desc",
|
|
69
68
|
statuses: ["success"],
|
|
70
|
-
}
|
|
69
|
+
},
|
|
71
70
|
);
|
|
72
71
|
included = new Set(page.map((m) => m._id));
|
|
73
72
|
contextMessages.push(
|
|
74
73
|
// Reverse since we fetched in descending order
|
|
75
|
-
...page.reverse()
|
|
74
|
+
...page.reverse(),
|
|
76
75
|
);
|
|
77
76
|
}
|
|
78
77
|
if (opts.searchOptions?.textSearch || opts.searchOptions?.vectorSearch) {
|
|
79
78
|
const targetMessage = contextMessages.find(
|
|
80
|
-
(m) => m._id === args.upToAndIncludingMessageId
|
|
79
|
+
(m) => m._id === args.upToAndIncludingMessageId,
|
|
81
80
|
)?.message;
|
|
82
81
|
const messagesToSearch = targetMessage ? [targetMessage] : args.messages;
|
|
83
82
|
if (!("runAction" in ctx)) {
|
|
@@ -89,11 +88,11 @@ export async function fetchContextMessages(
|
|
|
89
88
|
assert(text, `No text to search in message ${JSON.stringify(lastMessage)}`);
|
|
90
89
|
assert(
|
|
91
90
|
!args.contextOptions?.searchOptions?.vectorSearch || "runAction" in ctx,
|
|
92
|
-
"You must do vector search from an action"
|
|
91
|
+
"You must do vector search from an action",
|
|
93
92
|
);
|
|
94
93
|
if (opts.searchOptions?.vectorSearch && !args.getEmbedding) {
|
|
95
94
|
throw new Error(
|
|
96
|
-
"You must provide an embedding and embeddingModel to use vector search"
|
|
95
|
+
"You must provide an embedding and embeddingModel to use vector search",
|
|
97
96
|
);
|
|
98
97
|
}
|
|
99
98
|
const embeddingFields = opts.searchOptions?.vectorSearch
|
|
@@ -122,20 +121,21 @@ export async function fetchContextMessages(
|
|
|
122
121
|
vectorScoreThreshold:
|
|
123
122
|
opts.searchOptions?.vectorScoreThreshold ??
|
|
124
123
|
DEFAULT_VECTOR_SCORE_THRESHOLD,
|
|
125
|
-
|
|
126
|
-
|
|
124
|
+
embedding: embeddingFields?.embedding,
|
|
125
|
+
embeddingModel: embeddingFields?.embeddingModel,
|
|
126
|
+
},
|
|
127
127
|
);
|
|
128
128
|
// TODO: track what messages we used for context
|
|
129
129
|
contextMessages.unshift(
|
|
130
|
-
...searchMessages.filter((m) => !included?.has(m._id))
|
|
130
|
+
...searchMessages.filter((m) => !included?.has(m._id)),
|
|
131
131
|
);
|
|
132
132
|
}
|
|
133
133
|
// Ensure we don't include tool messages without a corresponding tool call
|
|
134
134
|
return filterOutOrphanedToolMessages(
|
|
135
135
|
contextMessages.sort((a, b) =>
|
|
136
136
|
// Sort the raw MessageDocs by order and stepOrder
|
|
137
|
-
a.order === b.order ? a.stepOrder - b.stepOrder : a.order - b.order
|
|
138
|
-
)
|
|
137
|
+
a.order === b.order ? a.stepOrder - b.stepOrder : a.order - b.order,
|
|
138
|
+
),
|
|
139
139
|
);
|
|
140
140
|
}
|
|
141
141
|
|
package/src/client/streaming.ts
CHANGED
|
@@ -38,7 +38,7 @@ export async function syncStreams(
|
|
|
38
38
|
streamArgs: StreamArgs | undefined;
|
|
39
39
|
// By default, only streaming messages are included.
|
|
40
40
|
includeStatuses?: ("streaming" | "finished" | "aborted")[];
|
|
41
|
-
}
|
|
41
|
+
},
|
|
42
42
|
): Promise<SyncStreamsReturnValue | undefined> {
|
|
43
43
|
if (!args.streamArgs) return undefined;
|
|
44
44
|
if (args.streamArgs.kind === "list") {
|
|
@@ -66,7 +66,7 @@ export async function abortStream(
|
|
|
66
66
|
component: AgentComponent,
|
|
67
67
|
args: {
|
|
68
68
|
reason: string;
|
|
69
|
-
} & ({ streamId: string } | { threadId: string; order: number })
|
|
69
|
+
} & ({ streamId: string } | { threadId: string; order: number }),
|
|
70
70
|
): Promise<boolean> {
|
|
71
71
|
if ("streamId" in args) {
|
|
72
72
|
return await ctx.runMutation(component.streams.abort, {
|
|
@@ -102,7 +102,7 @@ export async function listStreams(
|
|
|
102
102
|
threadId: string;
|
|
103
103
|
startOrder?: number;
|
|
104
104
|
includeStatuses?: ("streaming" | "finished" | "aborted")[];
|
|
105
|
-
}
|
|
105
|
+
},
|
|
106
106
|
): Promise<StreamMessage[]> {
|
|
107
107
|
return ctx.runQuery(component.streams.list, {
|
|
108
108
|
threadId,
|
|
@@ -137,7 +137,7 @@ export function mergeTransforms<TOOLS extends ToolSet>(
|
|
|
137
137
|
existing:
|
|
138
138
|
| StreamTextTransform<TOOLS>
|
|
139
139
|
| Array<StreamTextTransform<TOOLS>>
|
|
140
|
-
| undefined
|
|
140
|
+
| undefined,
|
|
141
141
|
) {
|
|
142
142
|
if (!options) {
|
|
143
143
|
return existing;
|
|
@@ -180,7 +180,7 @@ export class DeltaStreamer {
|
|
|
180
180
|
order: number | undefined;
|
|
181
181
|
stepOrder: number | undefined;
|
|
182
182
|
abortSignal: AbortSignal | undefined;
|
|
183
|
-
}
|
|
183
|
+
},
|
|
184
184
|
) {
|
|
185
185
|
this.options =
|
|
186
186
|
typeof options === "boolean"
|
|
@@ -216,7 +216,7 @@ export class DeltaStreamer {
|
|
|
216
216
|
...omit(this.metadata, ["abortSignal"]),
|
|
217
217
|
order: this.#nextOrder,
|
|
218
218
|
stepOrder: this.#nextStepOrder,
|
|
219
|
-
}
|
|
219
|
+
},
|
|
220
220
|
);
|
|
221
221
|
}
|
|
222
222
|
this.#nextParts.push(...parts);
|
|
@@ -237,7 +237,7 @@ export class DeltaStreamer {
|
|
|
237
237
|
try {
|
|
238
238
|
const success = await this.ctx.runMutation(
|
|
239
239
|
this.component.streams.addDelta,
|
|
240
|
-
delta
|
|
240
|
+
delta,
|
|
241
241
|
);
|
|
242
242
|
if (!success) {
|
|
243
243
|
this.abortController.abort();
|
package/src/client/types.ts
CHANGED
|
@@ -22,13 +22,14 @@ import type {
|
|
|
22
22
|
Auth,
|
|
23
23
|
Expand,
|
|
24
24
|
FunctionReference,
|
|
25
|
-
GenericActionCtx,
|
|
26
|
-
GenericDataModel,
|
|
27
|
-
GenericMutationCtx,
|
|
28
|
-
GenericQueryCtx,
|
|
29
25
|
StorageActionWriter,
|
|
30
26
|
StorageReader,
|
|
31
27
|
WithoutSystemFields,
|
|
28
|
+
FunctionArgs,
|
|
29
|
+
FunctionReturnType,
|
|
30
|
+
GenericActionCtx,
|
|
31
|
+
GenericDataModel,
|
|
32
|
+
OptionalRestArgs,
|
|
32
33
|
} from "convex/server";
|
|
33
34
|
import type { GenericId } from "convex/values";
|
|
34
35
|
import type { Schema } from "zod";
|
|
@@ -127,7 +128,7 @@ export type UsageHandler = (
|
|
|
127
128
|
providerMetadata: ProviderMetadata | undefined;
|
|
128
129
|
model: string;
|
|
129
130
|
provider: string;
|
|
130
|
-
}
|
|
131
|
+
},
|
|
131
132
|
) => void | Promise<void>;
|
|
132
133
|
|
|
133
134
|
export type RawRequestResponseHandler = (
|
|
@@ -138,7 +139,7 @@ export type RawRequestResponseHandler = (
|
|
|
138
139
|
agentName: string | undefined;
|
|
139
140
|
request: LanguageModelRequestMetadata;
|
|
140
141
|
response: LanguageModelResponseMetadata;
|
|
141
|
-
}
|
|
142
|
+
},
|
|
142
143
|
) => void | Promise<void>;
|
|
143
144
|
|
|
144
145
|
export type AgentComponent = UseApi<Mounts>;
|
|
@@ -335,7 +336,7 @@ export interface Thread<DefaultTools extends ToolSet> {
|
|
|
335
336
|
* Update the metadata for the thread.
|
|
336
337
|
*/
|
|
337
338
|
updateMetadata: (
|
|
338
|
-
patch: Partial<WithoutSystemFields<ThreadDoc
|
|
339
|
+
patch: Partial<WithoutSystemFields<ThreadDoc>>,
|
|
339
340
|
) => Promise<ThreadDoc>;
|
|
340
341
|
/**
|
|
341
342
|
* This behaves like {@link generateText} from the "ai" package except that
|
|
@@ -358,7 +359,7 @@ export interface Thread<DefaultTools extends ToolSet> {
|
|
|
358
359
|
OUTPUT,
|
|
359
360
|
OUTPUT_PARTIAL
|
|
360
361
|
>,
|
|
361
|
-
options?: Options
|
|
362
|
+
options?: Options,
|
|
362
363
|
): Promise<
|
|
363
364
|
GenerateTextResult<TOOLS extends undefined ? DefaultTools : TOOLS, OUTPUT> &
|
|
364
365
|
ThreadOutputMetadata
|
|
@@ -397,7 +398,7 @@ export interface Thread<DefaultTools extends ToolSet> {
|
|
|
397
398
|
* iterating over the text, streaming it over HTTP, etc.
|
|
398
399
|
*/
|
|
399
400
|
saveStreamDeltas?: boolean | StreamingOptions;
|
|
400
|
-
}
|
|
401
|
+
},
|
|
401
402
|
): Promise<
|
|
402
403
|
StreamTextResult<
|
|
403
404
|
TOOLS extends undefined ? DefaultTools : TOOLS,
|
|
@@ -417,7 +418,7 @@ export interface Thread<DefaultTools extends ToolSet> {
|
|
|
417
418
|
*/
|
|
418
419
|
generateObject<T>(
|
|
419
420
|
args: OurObjectArgs<T>,
|
|
420
|
-
options?: Options
|
|
421
|
+
options?: Options,
|
|
421
422
|
): Promise<GenerateObjectResult<T> & ThreadOutputMetadata>;
|
|
422
423
|
/**
|
|
423
424
|
* This behaves like {@link generateObject} from the "ai" package except that
|
|
@@ -431,7 +432,7 @@ export interface Thread<DefaultTools extends ToolSet> {
|
|
|
431
432
|
*/
|
|
432
433
|
generateObject(
|
|
433
434
|
args: GenerateObjectNoSchemaOptions,
|
|
434
|
-
options?: Options
|
|
435
|
+
options?: Options,
|
|
435
436
|
): Promise<GenerateObjectResult<JSONValue> & ThreadOutputMetadata>;
|
|
436
437
|
/**
|
|
437
438
|
* This behaves like {@link streamObject} from the "ai" package except that
|
|
@@ -445,7 +446,7 @@ export interface Thread<DefaultTools extends ToolSet> {
|
|
|
445
446
|
*/
|
|
446
447
|
streamObject<T>(
|
|
447
448
|
args: OurStreamObjectArgs<T>,
|
|
448
|
-
options?: Options
|
|
449
|
+
options?: Options,
|
|
449
450
|
): Promise<
|
|
450
451
|
StreamObjectResult<DeepPartial<T>, T, never> & ThreadOutputMetadata
|
|
451
452
|
>;
|
|
@@ -469,17 +470,24 @@ export type SyncStreamsReturnValue =
|
|
|
469
470
|
|
|
470
471
|
/* Type utils follow */
|
|
471
472
|
export type RunQueryCtx = {
|
|
472
|
-
runQuery:
|
|
473
|
+
runQuery: <Query extends FunctionReference<"query", "internal">>(
|
|
474
|
+
query: Query,
|
|
475
|
+
args: FunctionArgs<Query>,
|
|
476
|
+
) => Promise<FunctionReturnType<Query>>;
|
|
473
477
|
};
|
|
474
|
-
export type RunMutationCtx = {
|
|
475
|
-
|
|
476
|
-
|
|
478
|
+
export type RunMutationCtx = RunQueryCtx & {
|
|
479
|
+
runMutation: <Mutation extends FunctionReference<"mutation", "internal">>(
|
|
480
|
+
mutation: Mutation,
|
|
481
|
+
args: FunctionArgs<Mutation>,
|
|
482
|
+
) => Promise<FunctionReturnType<Mutation>>;
|
|
477
483
|
};
|
|
478
|
-
export type RunActionCtx = {
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
484
|
+
export type RunActionCtx = RunMutationCtx & {
|
|
485
|
+
runAction<Action extends FunctionReference<"action", "internal">>(
|
|
486
|
+
action: Action,
|
|
487
|
+
args: FunctionArgs<Action>,
|
|
488
|
+
): Promise<FunctionReturnType<Action>>;
|
|
482
489
|
};
|
|
490
|
+
export type UserActionCtx = GenericActionCtx<GenericDataModel>;
|
|
483
491
|
export type ActionCtx = RunActionCtx & {
|
|
484
492
|
auth: Auth;
|
|
485
493
|
storage: StorageActionWriter;
|
|
@@ -496,9 +504,7 @@ export type OpaqueIds<T> =
|
|
|
496
504
|
: T extends ArrayBuffer
|
|
497
505
|
? ArrayBuffer
|
|
498
506
|
: T extends object
|
|
499
|
-
? {
|
|
500
|
-
[K in keyof T]: OpaqueIds<T[K]>;
|
|
501
|
-
}
|
|
507
|
+
? { [K in keyof T]: OpaqueIds<T[K]> }
|
|
502
508
|
: T;
|
|
503
509
|
|
|
504
510
|
export type UseApi<API> = Expand<{
|
package/src/component/apiKeys.ts
CHANGED
package/src/component/files.ts
CHANGED
|
@@ -23,7 +23,7 @@ export const addFile = mutation({
|
|
|
23
23
|
|
|
24
24
|
export async function addFileHandler(
|
|
25
25
|
ctx: MutationCtx,
|
|
26
|
-
args: Infer<typeof addFileArgs
|
|
26
|
+
args: Infer<typeof addFileArgs>,
|
|
27
27
|
) {
|
|
28
28
|
const existingFile = await ctx.db
|
|
29
29
|
.query("files")
|
|
@@ -93,14 +93,14 @@ export const useExistingFile = mutation({
|
|
|
93
93
|
v.object({
|
|
94
94
|
fileId: v.id("files"),
|
|
95
95
|
storageId: v.string(),
|
|
96
|
-
})
|
|
96
|
+
}),
|
|
97
97
|
),
|
|
98
98
|
});
|
|
99
99
|
|
|
100
100
|
export async function changeRefcount(
|
|
101
101
|
ctx: MutationCtx,
|
|
102
102
|
prev: Id<"files">[],
|
|
103
|
-
next: Id<"files">[]
|
|
103
|
+
next: Id<"files">[],
|
|
104
104
|
) {
|
|
105
105
|
const prevSet = new Set(prev);
|
|
106
106
|
const nextSet = new Set(next);
|
|
@@ -140,7 +140,7 @@ export const copyFile = mutation({
|
|
|
140
140
|
|
|
141
141
|
export async function copyFileHandler(
|
|
142
142
|
ctx: MutationCtx,
|
|
143
|
-
args: { fileId: Id<"files"> }
|
|
143
|
+
args: { fileId: Id<"files"> },
|
|
144
144
|
) {
|
|
145
145
|
const file = await ctx.db.get(args.fileId);
|
|
146
146
|
if (!file) {
|
|
@@ -194,14 +194,14 @@ export const deleteFiles = mutation({
|
|
|
194
194
|
if (file.refcount && file.refcount > 0) {
|
|
195
195
|
if (!args.force) {
|
|
196
196
|
console.error(
|
|
197
|
-
`File ${fileId} has refcount ${file.refcount} > 0, skipping
|
|
197
|
+
`File ${fileId} has refcount ${file.refcount} > 0, skipping...`,
|
|
198
198
|
);
|
|
199
199
|
return null;
|
|
200
200
|
}
|
|
201
201
|
}
|
|
202
202
|
await ctx.db.delete(fileId);
|
|
203
203
|
return fileId;
|
|
204
|
-
})
|
|
204
|
+
}),
|
|
205
205
|
);
|
|
206
206
|
return deletedFileIds.filter((fileId) => fileId !== null);
|
|
207
207
|
},
|
|
@@ -280,7 +280,7 @@ describe("agent", () => {
|
|
|
280
280
|
patch: {
|
|
281
281
|
message: { role: "user", content: "test" },
|
|
282
282
|
},
|
|
283
|
-
})
|
|
283
|
+
}),
|
|
284
284
|
).rejects.toThrow();
|
|
285
285
|
});
|
|
286
286
|
|
|
@@ -311,7 +311,7 @@ describe("agent", () => {
|
|
|
311
311
|
{
|
|
312
312
|
threadId: thread._id as Id<"threads">,
|
|
313
313
|
order: "asc",
|
|
314
|
-
}
|
|
314
|
+
},
|
|
315
315
|
);
|
|
316
316
|
expect(remainingMessages.page).toHaveLength(1);
|
|
317
317
|
expect(remainingMessages.page[0]._id).toBe(messageIds[1]);
|
|
@@ -346,7 +346,7 @@ describe("agent", () => {
|
|
|
346
346
|
{
|
|
347
347
|
threadId: thread._id as Id<"threads">,
|
|
348
348
|
order: "asc",
|
|
349
|
-
}
|
|
349
|
+
},
|
|
350
350
|
);
|
|
351
351
|
expect(remainingMessages.page).toHaveLength(0);
|
|
352
352
|
});
|
|
@@ -398,7 +398,7 @@ describe("agent", () => {
|
|
|
398
398
|
{
|
|
399
399
|
threadId: thread._id as Id<"threads">,
|
|
400
400
|
order: "asc",
|
|
401
|
-
}
|
|
401
|
+
},
|
|
402
402
|
);
|
|
403
403
|
|
|
404
404
|
expect(remainingMessages.page).toHaveLength(3); // Should have messages from order 1 and 2
|
|
@@ -441,7 +441,7 @@ describe("agent", () => {
|
|
|
441
441
|
{
|
|
442
442
|
threadId: thread._id as Id<"threads">,
|
|
443
443
|
order: "asc",
|
|
444
|
-
}
|
|
444
|
+
},
|
|
445
445
|
);
|
|
446
446
|
|
|
447
447
|
expect(remainingMessages.page).toHaveLength(2);
|
|
@@ -504,7 +504,7 @@ describe("agent", () => {
|
|
|
504
504
|
{
|
|
505
505
|
threadId: thread._id as Id<"threads">,
|
|
506
506
|
order: "asc",
|
|
507
|
-
}
|
|
507
|
+
},
|
|
508
508
|
);
|
|
509
509
|
expect(remainingMessages.page).toHaveLength(1);
|
|
510
510
|
});
|
|
@@ -46,7 +46,7 @@ function publicMessage(message: Doc<"messages">): MessageDoc {
|
|
|
46
46
|
|
|
47
47
|
export async function deleteMessage(
|
|
48
48
|
ctx: MutationCtx,
|
|
49
|
-
messageDoc: Doc<"messages"
|
|
49
|
+
messageDoc: Doc<"messages">,
|
|
50
50
|
) {
|
|
51
51
|
await ctx.db.delete(messageDoc._id);
|
|
52
52
|
if (messageDoc.embeddingId) {
|
|
@@ -71,14 +71,14 @@ export const deleteByIds = mutation({
|
|
|
71
71
|
return id;
|
|
72
72
|
}
|
|
73
73
|
return null;
|
|
74
|
-
})
|
|
74
|
+
}),
|
|
75
75
|
);
|
|
76
76
|
return deletedMessageIds.filter((id) => id !== null);
|
|
77
77
|
},
|
|
78
78
|
});
|
|
79
79
|
|
|
80
80
|
export const messageStatuses = vMessageDoc.fields.status.members.map(
|
|
81
|
-
(m) => m.value
|
|
81
|
+
(m) => m.value,
|
|
82
82
|
);
|
|
83
83
|
|
|
84
84
|
export const deleteByOrder = mutation({
|
|
@@ -99,7 +99,7 @@ export const deleteByOrder = mutation({
|
|
|
99
99
|
ctx,
|
|
100
100
|
args.threadId,
|
|
101
101
|
"asc",
|
|
102
|
-
args.startOrder
|
|
102
|
+
args.startOrder,
|
|
103
103
|
)
|
|
104
104
|
.narrow({
|
|
105
105
|
lowerBound: args.startStepOrder
|
|
@@ -140,7 +140,7 @@ export const addMessages = mutation({
|
|
|
140
140
|
});
|
|
141
141
|
async function addMessagesHandler(
|
|
142
142
|
ctx: MutationCtx,
|
|
143
|
-
args: ObjectType<typeof addMessagesArgs
|
|
143
|
+
args: ObjectType<typeof addMessagesArgs>,
|
|
144
144
|
) {
|
|
145
145
|
let userId = args.userId;
|
|
146
146
|
const threadId = args.threadId;
|
|
@@ -163,15 +163,15 @@ async function addMessagesHandler(
|
|
|
163
163
|
const pendingMessages = await ctx.db
|
|
164
164
|
.query("messages")
|
|
165
165
|
.withIndex("threadId_status_tool_order_stepOrder", (q) =>
|
|
166
|
-
q.eq("threadId", threadId).eq("status", "pending")
|
|
166
|
+
q.eq("threadId", threadId).eq("status", "pending"),
|
|
167
167
|
)
|
|
168
168
|
.collect();
|
|
169
169
|
await Promise.all(
|
|
170
170
|
pendingMessages
|
|
171
171
|
.filter((m) => !parentMessage || m.order === parentMessage.order)
|
|
172
172
|
.map((m) =>
|
|
173
|
-
ctx.db.patch(m._id, { status: "failed", error: "Restarting" })
|
|
174
|
-
)
|
|
173
|
+
ctx.db.patch(m._id, { status: "failed", error: "Restarting" }),
|
|
174
|
+
),
|
|
175
175
|
);
|
|
176
176
|
}
|
|
177
177
|
let order, stepOrder;
|
|
@@ -194,7 +194,7 @@ async function addMessagesHandler(
|
|
|
194
194
|
if (embeddings) {
|
|
195
195
|
assert(
|
|
196
196
|
embeddings.vectors.length === messages.length,
|
|
197
|
-
"embeddings.vectors.length must match messages.length"
|
|
197
|
+
"embeddings.vectors.length must match messages.length",
|
|
198
198
|
);
|
|
199
199
|
}
|
|
200
200
|
for (let i = 0; i < messages.length; i++) {
|
|
@@ -242,7 +242,7 @@ async function addMessagesHandler(
|
|
|
242
242
|
export async function getMaxMessage(
|
|
243
243
|
ctx: QueryCtx,
|
|
244
244
|
threadId: Id<"threads">,
|
|
245
|
-
order?: number
|
|
245
|
+
order?: number,
|
|
246
246
|
) {
|
|
247
247
|
return orderedMessagesStream(ctx, threadId, "desc", order).first();
|
|
248
248
|
}
|
|
@@ -251,7 +251,7 @@ function orderedMessagesStream(
|
|
|
251
251
|
ctx: QueryCtx,
|
|
252
252
|
threadId: Id<"threads">,
|
|
253
253
|
sortOrder: "asc" | "desc",
|
|
254
|
-
order?: number
|
|
254
|
+
order?: number,
|
|
255
255
|
) {
|
|
256
256
|
return mergedStream(
|
|
257
257
|
[true, false].flatMap((tool) =>
|
|
@@ -268,10 +268,10 @@ function orderedMessagesStream(
|
|
|
268
268
|
}
|
|
269
269
|
return qq;
|
|
270
270
|
})
|
|
271
|
-
.order(sortOrder)
|
|
272
|
-
)
|
|
271
|
+
.order(sortOrder),
|
|
272
|
+
),
|
|
273
273
|
),
|
|
274
|
-
["order", "stepOrder"]
|
|
274
|
+
["order", "stepOrder"],
|
|
275
275
|
);
|
|
276
276
|
}
|
|
277
277
|
|
|
@@ -288,7 +288,7 @@ export const rollbackMessage = mutation({
|
|
|
288
288
|
ctx,
|
|
289
289
|
message.threadId,
|
|
290
290
|
"asc",
|
|
291
|
-
message.order
|
|
291
|
+
message.order,
|
|
292
292
|
).collect();
|
|
293
293
|
for (const m of messages) {
|
|
294
294
|
if (m.status === "pending") {
|
|
@@ -347,7 +347,7 @@ export const updateMessage = mutation({
|
|
|
347
347
|
|
|
348
348
|
async function commitMessageHandler(
|
|
349
349
|
ctx: MutationCtx,
|
|
350
|
-
{ messageId }: { messageId: Id<"messages"> }
|
|
350
|
+
{ messageId }: { messageId: Id<"messages"> },
|
|
351
351
|
) {
|
|
352
352
|
const message = await ctx.db.get(messageId);
|
|
353
353
|
assert(message, `Message ${messageId} not found`);
|
|
@@ -362,10 +362,10 @@ async function commitMessageHandler(
|
|
|
362
362
|
.eq("threadId", message.threadId)
|
|
363
363
|
.eq("status", "pending")
|
|
364
364
|
.eq("tool", tool)
|
|
365
|
-
.eq("order", order)
|
|
366
|
-
)
|
|
365
|
+
.eq("order", order),
|
|
366
|
+
),
|
|
367
367
|
),
|
|
368
|
-
["order", "stepOrder"]
|
|
368
|
+
["order", "stepOrder"],
|
|
369
369
|
).collect();
|
|
370
370
|
for (const message of messages) {
|
|
371
371
|
await ctx.db.patch(message._id, { status: "success" });
|
|
@@ -390,7 +390,7 @@ export const listMessagesByThreadId = query({
|
|
|
390
390
|
(await ctx.db.get(args.upToAndIncludingMessageId));
|
|
391
391
|
assert(
|
|
392
392
|
!last || last.threadId === args.threadId,
|
|
393
|
-
"upToAndIncludingMessageId must be a message in the thread"
|
|
393
|
+
"upToAndIncludingMessageId must be a message in the thread",
|
|
394
394
|
);
|
|
395
395
|
const toolOptions = args.excludeToolMessages ? [false] : [true, false];
|
|
396
396
|
const order = args.order ?? "desc";
|
|
@@ -411,9 +411,10 @@ export const listMessagesByThreadId = query({
|
|
|
411
411
|
.order(order)
|
|
412
412
|
.filterWith(
|
|
413
413
|
// We allow all messages on the same order.
|
|
414
|
-
async (m) =>
|
|
415
|
-
|
|
416
|
-
|
|
414
|
+
async (m) =>
|
|
415
|
+
!last || m.order < last.order || m.order === last.order,
|
|
416
|
+
),
|
|
417
|
+
),
|
|
417
418
|
);
|
|
418
419
|
const messages = await mergedStream(streams, [
|
|
419
420
|
"order",
|
|
@@ -422,7 +423,7 @@ export const listMessagesByThreadId = query({
|
|
|
422
423
|
args.paginationOpts ?? {
|
|
423
424
|
numItems: DEFAULT_RECENT_MESSAGES,
|
|
424
425
|
cursor: null,
|
|
425
|
-
}
|
|
426
|
+
},
|
|
426
427
|
);
|
|
427
428
|
return { ...messages, page: messages.page.map(publicMessage) };
|
|
428
429
|
},
|
|
@@ -450,14 +451,14 @@ export const searchMessages = action({
|
|
|
450
451
|
limit: v.number(),
|
|
451
452
|
vectorScoreThreshold: v.optional(v.number()),
|
|
452
453
|
messageRange: v.optional(
|
|
453
|
-
v.object({ before: v.number(), after: v.number() })
|
|
454
|
+
v.object({ before: v.number(), after: v.number() }),
|
|
454
455
|
),
|
|
455
456
|
},
|
|
456
457
|
returns: v.array(vMessageDoc),
|
|
457
458
|
handler: async (ctx, args): Promise<MessageDoc[]> => {
|
|
458
459
|
assert(
|
|
459
460
|
args.searchAllMessagesForUserId || args.threadId,
|
|
460
|
-
"Specify userId or threadId"
|
|
461
|
+
"Specify userId or threadId",
|
|
461
462
|
);
|
|
462
463
|
const limit = args.limit;
|
|
463
464
|
let textSearchMessages: MessageDoc[] | undefined;
|
|
@@ -496,20 +497,20 @@ export const searchMessages = action({
|
|
|
496
497
|
1 / ((textEmbeddingIds?.indexOf(v._id) ?? Infinity) + k),
|
|
497
498
|
}))
|
|
498
499
|
.sort((a, b) => b.score - a.score);
|
|
499
|
-
const
|
|
500
|
+
const embeddingIds = vectorScores.slice(0, limit).map((v) => v.id);
|
|
500
501
|
const messages: MessageDoc[] = await ctx.runQuery(
|
|
501
502
|
internal.messages._fetchSearchMessages,
|
|
502
503
|
{
|
|
503
504
|
searchAllMessagesForUserId: args.searchAllMessagesForUserId,
|
|
504
505
|
threadId: args.threadId,
|
|
505
|
-
|
|
506
|
+
embeddingIds,
|
|
506
507
|
textSearchMessages: textSearchMessages?.filter(
|
|
507
|
-
(m) => !
|
|
508
|
+
(m) => !embeddingIds.includes(m.embeddingId! as VectorTableId),
|
|
508
509
|
),
|
|
509
510
|
messageRange: args.messageRange ?? DEFAULT_MESSAGE_RANGE,
|
|
510
511
|
beforeMessageId: args.beforeMessageId,
|
|
511
512
|
limit,
|
|
512
|
-
}
|
|
513
|
+
},
|
|
513
514
|
);
|
|
514
515
|
return messages;
|
|
515
516
|
}
|
|
@@ -520,7 +521,7 @@ export const searchMessages = action({
|
|
|
520
521
|
export const _fetchSearchMessages = internalQuery({
|
|
521
522
|
args: {
|
|
522
523
|
threadId: v.optional(v.id("threads")),
|
|
523
|
-
|
|
524
|
+
embeddingIds: v.array(vVectorId),
|
|
524
525
|
searchAllMessagesForUserId: v.optional(v.string()),
|
|
525
526
|
textSearchMessages: v.optional(v.array(vMessageDoc)),
|
|
526
527
|
messageRange: v.object({ before: v.number(), after: v.number() }),
|
|
@@ -534,28 +535,28 @@ export const _fetchSearchMessages = internalQuery({
|
|
|
534
535
|
const { searchAllMessagesForUserId, threadId } = args;
|
|
535
536
|
assert(
|
|
536
537
|
searchAllMessagesForUserId || threadId,
|
|
537
|
-
"Specify searchAllMessagesForUserId or threadId to search"
|
|
538
|
+
"Specify searchAllMessagesForUserId or threadId to search",
|
|
538
539
|
);
|
|
539
540
|
let messages: MessageDoc[] = (
|
|
540
541
|
await Promise.all(
|
|
541
|
-
args.
|
|
542
|
+
args.embeddingIds.map((embeddingId) =>
|
|
542
543
|
ctx.db
|
|
543
544
|
.query("messages")
|
|
544
545
|
.withIndex("embeddingId_threadId", (q) =>
|
|
545
546
|
searchAllMessagesForUserId
|
|
546
547
|
? q.eq("embeddingId", embeddingId)
|
|
547
|
-
: q.eq("embeddingId", embeddingId).eq("threadId", threadId!)
|
|
548
|
+
: q.eq("embeddingId", embeddingId).eq("threadId", threadId!),
|
|
548
549
|
)
|
|
549
550
|
.filter((q) =>
|
|
550
551
|
q.and(
|
|
551
552
|
q.eq(q.field("status"), "success"),
|
|
552
553
|
searchAllMessagesForUserId
|
|
553
554
|
? q.eq(q.field("userId"), searchAllMessagesForUserId)
|
|
554
|
-
: q.eq(q.field("threadId"), threadId)
|
|
555
|
-
)
|
|
555
|
+
: q.eq(q.field("threadId"), threadId),
|
|
556
|
+
),
|
|
556
557
|
)
|
|
557
|
-
.first()
|
|
558
|
-
)
|
|
558
|
+
.first(),
|
|
559
|
+
),
|
|
559
560
|
)
|
|
560
561
|
)
|
|
561
562
|
.filter(
|
|
@@ -566,7 +567,7 @@ export const _fetchSearchMessages = internalQuery({
|
|
|
566
567
|
(!beforeMessage ||
|
|
567
568
|
m.order < beforeMessage.order ||
|
|
568
569
|
(m.order === beforeMessage.order &&
|
|
569
|
-
m.stepOrder < beforeMessage.stepOrder))
|
|
570
|
+
m.stepOrder < beforeMessage.stepOrder)),
|
|
570
571
|
)
|
|
571
572
|
.map(publicMessage);
|
|
572
573
|
messages.push(...(args.textSearchMessages ?? []));
|
|
@@ -614,7 +615,7 @@ export const _fetchSearchMessages = internalQuery({
|
|
|
614
615
|
.eq("status", "success")
|
|
615
616
|
.eq("tool", false)
|
|
616
617
|
.gte("order", earliest)
|
|
617
|
-
.lte("order", latest)
|
|
618
|
+
.lte("order", latest),
|
|
618
619
|
)
|
|
619
620
|
.collect();
|
|
620
621
|
if (!ranges[searchId]) {
|
|
@@ -645,7 +646,7 @@ export const textSearch = query({
|
|
|
645
646
|
handler: async (ctx, args) => {
|
|
646
647
|
assert(
|
|
647
648
|
args.searchAllMessagesForUserId || args.threadId,
|
|
648
|
-
"Specify userId or threadId"
|
|
649
|
+
"Specify userId or threadId",
|
|
649
650
|
);
|
|
650
651
|
const beforeMessage =
|
|
651
652
|
args.beforeMessageId && (await ctx.db.get(args.beforeMessageId));
|
|
@@ -657,7 +658,7 @@ export const textSearch = query({
|
|
|
657
658
|
? q
|
|
658
659
|
.search("text", args.text)
|
|
659
660
|
.eq("userId", args.searchAllMessagesForUserId)
|
|
660
|
-
: q.search("text", args.text).eq("threadId", args.threadId!)
|
|
661
|
+
: q.search("text", args.text).eq("threadId", args.threadId!),
|
|
661
662
|
)
|
|
662
663
|
// Just in case tool messages slip through
|
|
663
664
|
.filter((q) => {
|
|
@@ -674,7 +675,7 @@ export const textSearch = query({
|
|
|
674
675
|
!beforeMessage ||
|
|
675
676
|
m.order < beforeMessage.order ||
|
|
676
677
|
(m.order === beforeMessage.order &&
|
|
677
|
-
m.stepOrder < beforeMessage.stepOrder)
|
|
678
|
+
m.stepOrder < beforeMessage.stepOrder),
|
|
678
679
|
)
|
|
679
680
|
.map(publicMessage);
|
|
680
681
|
},
|