@convex-dev/agent 0.2.10 → 0.2.11-alpha.1
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/UIMessages.d.ts.map +1 -1
- package/dist/UIMessages.js +2 -7
- package/dist/UIMessages.js.map +1 -1
- package/dist/client/files.d.ts +2 -2
- package/dist/client/files.d.ts.map +1 -1
- package/dist/client/files.js.map +1 -1
- package/dist/client/index.d.ts +20 -20
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +1 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/messages.d.ts +5 -5
- package/dist/client/messages.d.ts.map +1 -1
- package/dist/client/messages.js.map +1 -1
- package/dist/client/saveInputMessages.d.ts +2 -2
- package/dist/client/saveInputMessages.d.ts.map +1 -1
- package/dist/client/saveInputMessages.js.map +1 -1
- package/dist/client/search.d.ts +7 -7
- package/dist/client/search.d.ts.map +1 -1
- package/dist/client/search.js +33 -21
- package/dist/client/search.js.map +1 -1
- package/dist/client/streaming.d.ts +6 -6
- package/dist/client/streaming.d.ts.map +1 -1
- package/dist/client/streaming.js.map +1 -1
- package/dist/client/threads.d.ts +5 -5
- package/dist/client/threads.d.ts.map +1 -1
- package/dist/client/threads.js.map +1 -1
- package/dist/client/types.d.ts +6 -8
- package/dist/client/types.d.ts.map +1 -1
- package/dist/deltas.d.ts.map +1 -1
- package/dist/deltas.js +7 -18
- package/dist/deltas.js.map +1 -1
- package/dist/mapping.d.ts +5 -4
- package/dist/mapping.d.ts.map +1 -1
- package/dist/mapping.js +7 -0
- package/dist/mapping.js.map +1 -1
- package/dist/shared.d.ts +4 -2
- package/dist/shared.d.ts.map +1 -1
- package/dist/shared.js +10 -10
- package/dist/shared.js.map +1 -1
- package/dist/validators.d.ts +1 -0
- package/dist/validators.d.ts.map +1 -1
- package/dist/validators.js.map +1 -1
- package/package.json +1 -1
- package/src/UIMessages.ts +8 -8
- package/src/client/files.ts +2 -2
- package/src/client/index.ts +22 -22
- package/src/client/messages.ts +10 -5
- package/src/client/saveInputMessages.test.ts +13 -5
- package/src/client/saveInputMessages.ts +3 -3
- package/src/client/search.test.ts +44 -19
- package/src/client/search.ts +54 -37
- package/src/client/streaming.ts +7 -6
- package/src/client/threads.ts +10 -5
- package/src/client/types.ts +6 -8
- package/src/deltas.test.ts +24 -14
- package/src/deltas.ts +7 -18
- package/src/mapping.ts +12 -3
- package/src/shared.ts +37 -12
- package/src/toUIMessages.test.ts +77 -2
- package/src/validators.ts +10 -0
package/src/client/index.ts
CHANGED
|
@@ -89,9 +89,7 @@ import type {
|
|
|
89
89
|
ObjectSchema,
|
|
90
90
|
Options,
|
|
91
91
|
RawRequestResponseHandler,
|
|
92
|
-
|
|
93
|
-
RunMutationCtx,
|
|
94
|
-
RunQueryCtx,
|
|
92
|
+
MutationCtx,
|
|
95
93
|
StorageOptions,
|
|
96
94
|
StreamingTextArgs,
|
|
97
95
|
StreamObjectArgs,
|
|
@@ -100,10 +98,12 @@ import type {
|
|
|
100
98
|
Thread,
|
|
101
99
|
UsageHandler,
|
|
102
100
|
UserActionCtx,
|
|
101
|
+
QueryCtx,
|
|
103
102
|
} from "./types.js";
|
|
104
103
|
|
|
105
104
|
export { stepCountIs } from "ai";
|
|
106
105
|
export {
|
|
106
|
+
docsToModelMessages,
|
|
107
107
|
toModelMessage,
|
|
108
108
|
//** @deprecated use toModelMessage instead */
|
|
109
109
|
toModelMessage as deserializeMessage,
|
|
@@ -268,7 +268,7 @@ export class Agent<
|
|
|
268
268
|
* @returns The threadId of the new thread and the thread object.
|
|
269
269
|
*/
|
|
270
270
|
async createThread(
|
|
271
|
-
ctx:
|
|
271
|
+
ctx: ActionCtx & CustomCtx,
|
|
272
272
|
args?: {
|
|
273
273
|
/**
|
|
274
274
|
* The userId to associate with the thread. If not provided, the thread will be
|
|
@@ -295,7 +295,7 @@ export class Agent<
|
|
|
295
295
|
* @returns The threadId of the new thread.
|
|
296
296
|
*/
|
|
297
297
|
async createThread(
|
|
298
|
-
ctx:
|
|
298
|
+
ctx: MutationCtx,
|
|
299
299
|
args?: {
|
|
300
300
|
/**
|
|
301
301
|
* The userId to associate with the thread. If not provided, the thread will be
|
|
@@ -313,7 +313,7 @@ export class Agent<
|
|
|
313
313
|
},
|
|
314
314
|
): Promise<{ threadId: string }>;
|
|
315
315
|
async createThread(
|
|
316
|
-
ctx: (ActionCtx & CustomCtx) |
|
|
316
|
+
ctx: (ActionCtx & CustomCtx) | MutationCtx,
|
|
317
317
|
args?: { userId: string | null; title?: string; summary?: string },
|
|
318
318
|
): Promise<{ threadId: string; thread?: Thread<AgentTools> }> {
|
|
319
319
|
const threadId = await createThread(ctx, this.component, args);
|
|
@@ -834,7 +834,7 @@ export class Agent<
|
|
|
834
834
|
* @returns The messageId of the saved message.
|
|
835
835
|
*/
|
|
836
836
|
async saveMessage(
|
|
837
|
-
ctx:
|
|
837
|
+
ctx: MutationCtx | ActionCtx,
|
|
838
838
|
args: SaveMessageArgs & {
|
|
839
839
|
/**
|
|
840
840
|
* If true, it will not generate embeddings for the message.
|
|
@@ -872,7 +872,7 @@ export class Agent<
|
|
|
872
872
|
* @returns
|
|
873
873
|
*/
|
|
874
874
|
async saveMessages(
|
|
875
|
-
ctx:
|
|
875
|
+
ctx: MutationCtx | ActionCtx,
|
|
876
876
|
args: SaveMessagesArgs & {
|
|
877
877
|
/**
|
|
878
878
|
* Skip generating embeddings for the messages. Useful if you're
|
|
@@ -928,7 +928,7 @@ export class Agent<
|
|
|
928
928
|
* @returns The MessageDoc's in a format compatible with usePaginatedQuery.
|
|
929
929
|
*/
|
|
930
930
|
async listMessages(
|
|
931
|
-
ctx:
|
|
931
|
+
ctx: QueryCtx | MutationCtx | ActionCtx,
|
|
932
932
|
args: {
|
|
933
933
|
threadId: string;
|
|
934
934
|
paginationOpts: PaginationOptions;
|
|
@@ -948,7 +948,7 @@ export class Agent<
|
|
|
948
948
|
* @returns The deltas for each stream from their existing cursor.
|
|
949
949
|
*/
|
|
950
950
|
async syncStreams(
|
|
951
|
-
ctx:
|
|
951
|
+
ctx: QueryCtx | MutationCtx | ActionCtx,
|
|
952
952
|
args: {
|
|
953
953
|
threadId: string;
|
|
954
954
|
streamArgs: StreamArgs | undefined;
|
|
@@ -968,7 +968,7 @@ export class Agent<
|
|
|
968
968
|
* @returns
|
|
969
969
|
*/
|
|
970
970
|
async fetchContextMessages(
|
|
971
|
-
ctx:
|
|
971
|
+
ctx: QueryCtx | MutationCtx | ActionCtx,
|
|
972
972
|
args: {
|
|
973
973
|
userId: string | undefined;
|
|
974
974
|
threadId: string | undefined;
|
|
@@ -1030,7 +1030,7 @@ export class Agent<
|
|
|
1030
1030
|
* @returns The metadata for the thread.
|
|
1031
1031
|
*/
|
|
1032
1032
|
async getThreadMetadata(
|
|
1033
|
-
ctx:
|
|
1033
|
+
ctx: QueryCtx | MutationCtx | ActionCtx,
|
|
1034
1034
|
args: { threadId: string },
|
|
1035
1035
|
): Promise<ThreadDoc> {
|
|
1036
1036
|
return getThreadMetadata(ctx, this.component, args);
|
|
@@ -1044,7 +1044,7 @@ export class Agent<
|
|
|
1044
1044
|
* @returns The updated thread metadata.
|
|
1045
1045
|
*/
|
|
1046
1046
|
async updateThreadMetadata(
|
|
1047
|
-
ctx:
|
|
1047
|
+
ctx: MutationCtx | ActionCtx,
|
|
1048
1048
|
args: {
|
|
1049
1049
|
threadId: string;
|
|
1050
1050
|
patch: Partial<
|
|
@@ -1065,7 +1065,7 @@ export class Agent<
|
|
|
1065
1065
|
* @returns The embeddings for the messages.
|
|
1066
1066
|
*/
|
|
1067
1067
|
async generateEmbeddings(
|
|
1068
|
-
ctx:
|
|
1068
|
+
ctx: ActionCtx,
|
|
1069
1069
|
args: { userId: string | undefined; threadId: string | undefined },
|
|
1070
1070
|
messages: (ModelMessage | Message)[],
|
|
1071
1071
|
): Promise<
|
|
@@ -1091,7 +1091,7 @@ export class Agent<
|
|
|
1091
1091
|
* @param args The messageIds to generate embeddings for.
|
|
1092
1092
|
*/
|
|
1093
1093
|
async generateAndSaveEmbeddings(
|
|
1094
|
-
ctx:
|
|
1094
|
+
ctx: ActionCtx,
|
|
1095
1095
|
args: { messageIds: string[] },
|
|
1096
1096
|
) {
|
|
1097
1097
|
const messages = (
|
|
@@ -1251,7 +1251,7 @@ export class Agent<
|
|
|
1251
1251
|
* the generateText call.
|
|
1252
1252
|
*/
|
|
1253
1253
|
async finalizeMessage(
|
|
1254
|
-
ctx:
|
|
1254
|
+
ctx: MutationCtx | ActionCtx,
|
|
1255
1255
|
args: {
|
|
1256
1256
|
messageId: string;
|
|
1257
1257
|
result: { status: "failed"; error: string } | { status: "success" };
|
|
@@ -1269,7 +1269,7 @@ export class Agent<
|
|
|
1269
1269
|
* @param args The message fields to update.
|
|
1270
1270
|
*/
|
|
1271
1271
|
async updateMessage(
|
|
1272
|
-
ctx:
|
|
1272
|
+
ctx: MutationCtx | ActionCtx,
|
|
1273
1273
|
args: {
|
|
1274
1274
|
/** The id of the message to update. */
|
|
1275
1275
|
messageId: string;
|
|
@@ -1319,7 +1319,7 @@ export class Agent<
|
|
|
1319
1319
|
* @param args The ids of the messages to delete.
|
|
1320
1320
|
*/
|
|
1321
1321
|
async deleteMessages(
|
|
1322
|
-
ctx:
|
|
1322
|
+
ctx: MutationCtx | ActionCtx,
|
|
1323
1323
|
args: { messageIds: string[] },
|
|
1324
1324
|
): Promise<void> {
|
|
1325
1325
|
await ctx.runMutation(this.component.messages.deleteByIds, args);
|
|
@@ -1332,7 +1332,7 @@ export class Agent<
|
|
|
1332
1332
|
* @param args The id of the message to delete.
|
|
1333
1333
|
*/
|
|
1334
1334
|
async deleteMessage(
|
|
1335
|
-
ctx:
|
|
1335
|
+
ctx: MutationCtx | ActionCtx,
|
|
1336
1336
|
args: { messageId: string },
|
|
1337
1337
|
): Promise<void> {
|
|
1338
1338
|
await ctx.runMutation(this.component.messages.deleteByIds, {
|
|
@@ -1378,7 +1378,7 @@ export class Agent<
|
|
|
1378
1378
|
* @param args The range of messages to delete.
|
|
1379
1379
|
*/
|
|
1380
1380
|
async deleteMessageRange(
|
|
1381
|
-
ctx:
|
|
1381
|
+
ctx: MutationCtx | ActionCtx,
|
|
1382
1382
|
args: {
|
|
1383
1383
|
threadId: string;
|
|
1384
1384
|
startOrder: number;
|
|
@@ -1404,7 +1404,7 @@ export class Agent<
|
|
|
1404
1404
|
* @param args The id of the thread to delete and optionally the page size to use for the delete.
|
|
1405
1405
|
*/
|
|
1406
1406
|
async deleteThreadAsync(
|
|
1407
|
-
ctx:
|
|
1407
|
+
ctx: MutationCtx | ActionCtx,
|
|
1408
1408
|
args: { threadId: string; pageSize?: number },
|
|
1409
1409
|
): Promise<void> {
|
|
1410
1410
|
await ctx.runMutation(this.component.threads.deleteAllForThreadIdAsync, {
|
|
@@ -1421,7 +1421,7 @@ export class Agent<
|
|
|
1421
1421
|
* @param args The id of the thread to delete and optionally the page size to use for the delete.
|
|
1422
1422
|
*/
|
|
1423
1423
|
async deleteThreadSync(
|
|
1424
|
-
ctx:
|
|
1424
|
+
ctx: ActionCtx,
|
|
1425
1425
|
args: { threadId: string; pageSize?: number },
|
|
1426
1426
|
): Promise<void> {
|
|
1427
1427
|
await ctx.runAction(this.component.threads.deleteAllForThreadIdSync, {
|
package/src/client/messages.ts
CHANGED
|
@@ -12,7 +12,12 @@ import {
|
|
|
12
12
|
} from "../validators.js";
|
|
13
13
|
import { serializeMessage } from "../mapping.js";
|
|
14
14
|
import { toUIMessages, type UIMessage } from "../UIMessages.js";
|
|
15
|
-
import type {
|
|
15
|
+
import type {
|
|
16
|
+
AgentComponent,
|
|
17
|
+
MutationCtx,
|
|
18
|
+
QueryCtx,
|
|
19
|
+
ActionCtx,
|
|
20
|
+
} from "./types.js";
|
|
16
21
|
import { parse } from "convex-helpers/validators";
|
|
17
22
|
|
|
18
23
|
/**
|
|
@@ -27,7 +32,7 @@ import { parse } from "convex-helpers/validators";
|
|
|
27
32
|
* @returns The MessageDoc's in a format compatible with usePaginatedQuery.
|
|
28
33
|
*/
|
|
29
34
|
export async function listMessages(
|
|
30
|
-
ctx:
|
|
35
|
+
ctx: QueryCtx | MutationCtx | ActionCtx,
|
|
31
36
|
component: AgentComponent,
|
|
32
37
|
{
|
|
33
38
|
threadId,
|
|
@@ -58,7 +63,7 @@ export async function listMessages(
|
|
|
58
63
|
}
|
|
59
64
|
|
|
60
65
|
export async function listUIMessages(
|
|
61
|
-
ctx:
|
|
66
|
+
ctx: QueryCtx | MutationCtx | ActionCtx,
|
|
62
67
|
component: AgentComponent,
|
|
63
68
|
args: {
|
|
64
69
|
threadId: string;
|
|
@@ -105,7 +110,7 @@ export type SaveMessagesArgs = {
|
|
|
105
110
|
* Explicitly save messages associated with the thread (& user if provided)
|
|
106
111
|
*/
|
|
107
112
|
export async function saveMessages(
|
|
108
|
-
ctx:
|
|
113
|
+
ctx: MutationCtx,
|
|
109
114
|
component: AgentComponent,
|
|
110
115
|
args: SaveMessagesArgs & {
|
|
111
116
|
/**
|
|
@@ -193,7 +198,7 @@ export type SaveMessageArgs = {
|
|
|
193
198
|
* @returns The messageId of the saved message.
|
|
194
199
|
*/
|
|
195
200
|
export async function saveMessage(
|
|
196
|
-
ctx:
|
|
201
|
+
ctx: MutationCtx,
|
|
197
202
|
component: AgentComponent,
|
|
198
203
|
args: SaveMessageArgs & {
|
|
199
204
|
/**
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import { beforeEach, describe, expect, test, vi } from "vitest";
|
|
2
2
|
import { saveInputMessages } from "./saveInputMessages.js";
|
|
3
3
|
import type { MessageDoc } from "../validators.js";
|
|
4
|
-
import type {
|
|
5
|
-
import {
|
|
4
|
+
import type { ActionCtx } from "./types.js";
|
|
5
|
+
import {
|
|
6
|
+
defineSchema,
|
|
7
|
+
type Auth,
|
|
8
|
+
type StorageActionWriter,
|
|
9
|
+
} from "convex/server";
|
|
6
10
|
import { initConvexTest } from "./setup.test.js";
|
|
7
11
|
import { components } from "./setup.test.js";
|
|
8
12
|
|
|
@@ -59,7 +63,7 @@ describe("saveInputMessages", () => {
|
|
|
59
63
|
const mockComponent = components.agent;
|
|
60
64
|
|
|
61
65
|
let t = initConvexTest(schema);
|
|
62
|
-
let ctx:
|
|
66
|
+
let ctx: ActionCtx;
|
|
63
67
|
|
|
64
68
|
beforeEach(() => {
|
|
65
69
|
vi.clearAllMocks();
|
|
@@ -68,7 +72,9 @@ describe("saveInputMessages", () => {
|
|
|
68
72
|
runQuery: t.query,
|
|
69
73
|
runAction: t.action,
|
|
70
74
|
runMutation: t.mutation,
|
|
71
|
-
|
|
75
|
+
auth: {} as Auth,
|
|
76
|
+
storage: {} as StorageActionWriter,
|
|
77
|
+
} as ActionCtx;
|
|
72
78
|
|
|
73
79
|
mockSaveMessages.mockResolvedValue({
|
|
74
80
|
messages: [
|
|
@@ -358,7 +364,9 @@ describe("saveInputMessages", () => {
|
|
|
358
364
|
runQuery: vi.fn(),
|
|
359
365
|
runMutation: vi.fn(),
|
|
360
366
|
runAction: vi.fn(),
|
|
361
|
-
|
|
367
|
+
auth: {} as Auth,
|
|
368
|
+
storage: {} as StorageActionWriter,
|
|
369
|
+
} as ActionCtx;
|
|
362
370
|
|
|
363
371
|
await saveInputMessages(actionCtx, mockComponent, {
|
|
364
372
|
...defaultArgs,
|
|
@@ -2,10 +2,10 @@ import { type ModelMessage } from "ai";
|
|
|
2
2
|
import type { MessageDoc } from "../validators.js";
|
|
3
3
|
import { embedMessages, getPromptArray } from "./search.js";
|
|
4
4
|
import type {
|
|
5
|
+
ActionCtx,
|
|
5
6
|
AgentComponent,
|
|
6
7
|
Config,
|
|
7
|
-
|
|
8
|
-
RunMutationCtx,
|
|
8
|
+
MutationCtx,
|
|
9
9
|
} from "./types.js";
|
|
10
10
|
import { saveMessages } from "./messages.js";
|
|
11
11
|
import type { Message } from "../validators.js";
|
|
@@ -13,7 +13,7 @@ import { assert } from "convex-helpers";
|
|
|
13
13
|
import type { VectorDimension } from "../component/vector/tables.js";
|
|
14
14
|
|
|
15
15
|
export async function saveInputMessages(
|
|
16
|
-
ctx:
|
|
16
|
+
ctx: MutationCtx | ActionCtx,
|
|
17
17
|
component: AgentComponent,
|
|
18
18
|
{
|
|
19
19
|
threadId,
|
|
@@ -7,9 +7,14 @@ import {
|
|
|
7
7
|
type MockedFunction,
|
|
8
8
|
} from "vitest";
|
|
9
9
|
import type { ModelMessage } from "ai";
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
defineSchema,
|
|
12
|
+
type Auth,
|
|
13
|
+
type StorageActionWriter,
|
|
14
|
+
type StorageReader,
|
|
15
|
+
} from "convex/server";
|
|
11
16
|
import type { MessageDoc } from "../validators.js";
|
|
12
|
-
import type {
|
|
17
|
+
import type { ActionCtx, QueryCtx } from "./types.js";
|
|
13
18
|
import {
|
|
14
19
|
fetchContextWithPrompt,
|
|
15
20
|
fetchContextMessages,
|
|
@@ -43,8 +48,8 @@ const schema = defineSchema({});
|
|
|
43
48
|
|
|
44
49
|
describe("search.ts", () => {
|
|
45
50
|
let t = initConvexTest(schema);
|
|
46
|
-
let mockCtx:
|
|
47
|
-
let ctx:
|
|
51
|
+
let mockCtx: ActionCtx;
|
|
52
|
+
let ctx: ActionCtx;
|
|
48
53
|
|
|
49
54
|
// Shared helper functions
|
|
50
55
|
async function createTestThread(userId: string) {
|
|
@@ -88,13 +93,15 @@ describe("search.ts", () => {
|
|
|
88
93
|
runQuery: t.query,
|
|
89
94
|
runAction: t.action,
|
|
90
95
|
runMutation: t.mutation,
|
|
91
|
-
} as
|
|
96
|
+
} as ActionCtx;
|
|
92
97
|
|
|
93
98
|
mockCtx = {
|
|
94
99
|
runQuery: vi.fn(),
|
|
95
100
|
runAction: vi.fn(),
|
|
96
101
|
runMutation: vi.fn(),
|
|
97
|
-
|
|
102
|
+
auth: {} as Auth,
|
|
103
|
+
storage: {} as StorageActionWriter,
|
|
104
|
+
} satisfies ActionCtx;
|
|
98
105
|
|
|
99
106
|
// Mock process.env to avoid file inlining in tests
|
|
100
107
|
process.env.CONVEX_CLOUD_URL = "https://example.convex.cloud";
|
|
@@ -183,10 +190,25 @@ describe("search.ts", () => {
|
|
|
183
190
|
it("should filter out orphaned tool messages", () => {
|
|
184
191
|
const messages: MessageDoc[] = [
|
|
185
192
|
{
|
|
186
|
-
_id: "
|
|
193
|
+
_id: "0",
|
|
187
194
|
message: { role: "user", content: "Hello" },
|
|
188
195
|
order: 1,
|
|
189
196
|
} as MessageDoc,
|
|
197
|
+
{
|
|
198
|
+
_id: "1",
|
|
199
|
+
message: {
|
|
200
|
+
role: "assistant",
|
|
201
|
+
content: [
|
|
202
|
+
{
|
|
203
|
+
type: "tool-call",
|
|
204
|
+
toolCallId: "call_orphaned",
|
|
205
|
+
toolName: "test",
|
|
206
|
+
args: {},
|
|
207
|
+
},
|
|
208
|
+
],
|
|
209
|
+
},
|
|
210
|
+
order: 1,
|
|
211
|
+
} as MessageDoc,
|
|
190
212
|
{
|
|
191
213
|
_id: "2",
|
|
192
214
|
message: {
|
|
@@ -194,18 +216,24 @@ describe("search.ts", () => {
|
|
|
194
216
|
content: [
|
|
195
217
|
{
|
|
196
218
|
type: "tool-result",
|
|
197
|
-
toolCallId: "
|
|
219
|
+
toolCallId: "result_orphaned",
|
|
198
220
|
result: "orphaned",
|
|
199
221
|
},
|
|
200
222
|
],
|
|
201
223
|
},
|
|
202
224
|
order: 2,
|
|
203
225
|
} as MessageDoc,
|
|
226
|
+
{
|
|
227
|
+
_id: "3",
|
|
228
|
+
message: { role: "assistant", content: "I'll help you with that" },
|
|
229
|
+
order: 1,
|
|
230
|
+
} as MessageDoc,
|
|
204
231
|
];
|
|
205
232
|
|
|
206
233
|
const result = filterOutOrphanedToolMessages(messages);
|
|
207
|
-
expect(result).toHaveLength(
|
|
208
|
-
expect(result[0]._id).toBe("
|
|
234
|
+
expect(result).toHaveLength(2);
|
|
235
|
+
expect(result[0]._id).toBe("0");
|
|
236
|
+
expect(result[1]._id).toBe("3");
|
|
209
237
|
});
|
|
210
238
|
});
|
|
211
239
|
|
|
@@ -227,7 +255,7 @@ describe("search.ts", () => {
|
|
|
227
255
|
];
|
|
228
256
|
|
|
229
257
|
(
|
|
230
|
-
mockCtx.runQuery as MockedFunction<
|
|
258
|
+
mockCtx.runQuery as MockedFunction<ActionCtx["runQuery"]>
|
|
231
259
|
).mockResolvedValue({
|
|
232
260
|
page: mockPage,
|
|
233
261
|
});
|
|
@@ -269,7 +297,7 @@ describe("search.ts", () => {
|
|
|
269
297
|
];
|
|
270
298
|
|
|
271
299
|
(
|
|
272
|
-
mockCtx.runAction as MockedFunction<
|
|
300
|
+
mockCtx.runAction as MockedFunction<ActionCtx["runAction"]>
|
|
273
301
|
).mockResolvedValue(searchResults);
|
|
274
302
|
|
|
275
303
|
const result = await fetchContextMessages(mockCtx, components.agent, {
|
|
@@ -293,7 +321,8 @@ describe("search.ts", () => {
|
|
|
293
321
|
const mockQueryCtx = {
|
|
294
322
|
runQuery: vi.fn().mockResolvedValue({ page: [] }),
|
|
295
323
|
// No runAction method
|
|
296
|
-
|
|
324
|
+
storage: {} as StorageReader,
|
|
325
|
+
} as QueryCtx;
|
|
297
326
|
|
|
298
327
|
await expect(
|
|
299
328
|
fetchContextMessages(mockQueryCtx, components.agent, {
|
|
@@ -948,11 +977,7 @@ describe("search.ts", () => {
|
|
|
948
977
|
|
|
949
978
|
const contextHandler = vi.fn(async (ctx, args) => {
|
|
950
979
|
// Put existing responses first to test they're properly identified
|
|
951
|
-
return [
|
|
952
|
-
...args.recent,
|
|
953
|
-
...args.existingResponses,
|
|
954
|
-
...args.inputPrompt,
|
|
955
|
-
];
|
|
980
|
+
return [...args.recent, ...args.existingResponses, ...args.inputPrompt];
|
|
956
981
|
});
|
|
957
982
|
|
|
958
983
|
const result = await fetchContextWithPrompt(ctx, components.agent, {
|
|
@@ -979,7 +1004,7 @@ describe("search.ts", () => {
|
|
|
979
1004
|
inputPrompt: expect.arrayContaining([
|
|
980
1005
|
expect.objectContaining({ content: "New replacement prompt" }),
|
|
981
1006
|
]),
|
|
982
|
-
})
|
|
1007
|
+
}),
|
|
983
1008
|
);
|
|
984
1009
|
|
|
985
1010
|
expect(result.messages).toHaveLength(4);
|
package/src/client/search.ts
CHANGED
|
@@ -20,15 +20,16 @@ import {
|
|
|
20
20
|
} from "../shared.js";
|
|
21
21
|
import type { Message } from "../validators.js";
|
|
22
22
|
import type {
|
|
23
|
+
ActionCtx,
|
|
23
24
|
AgentComponent,
|
|
24
25
|
Config,
|
|
25
26
|
ContextOptions,
|
|
26
27
|
Options,
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
QueryCtx,
|
|
29
|
+
MutationCtx,
|
|
29
30
|
} from "./types.js";
|
|
30
31
|
import { inlineMessagesFiles } from "./files.js";
|
|
31
|
-
import { toModelMessage } from "../mapping.js";
|
|
32
|
+
import { docsToModelMessages, toModelMessage } from "../mapping.js";
|
|
32
33
|
|
|
33
34
|
const DEFAULT_VECTOR_SCORE_THRESHOLD = 0.0;
|
|
34
35
|
// 10k characters should be more than enough for most cases, and stays under
|
|
@@ -49,7 +50,7 @@ export type GetEmbedding = (text: string) => Promise<{
|
|
|
49
50
|
* @returns
|
|
50
51
|
*/
|
|
51
52
|
export async function fetchContextMessages(
|
|
52
|
-
ctx:
|
|
53
|
+
ctx: QueryCtx | MutationCtx | ActionCtx,
|
|
53
54
|
component: AgentComponent,
|
|
54
55
|
args: {
|
|
55
56
|
userId: string | undefined;
|
|
@@ -85,7 +86,7 @@ export async function fetchContextMessages(
|
|
|
85
86
|
}
|
|
86
87
|
|
|
87
88
|
export async function fetchRecentAndSearchMessages(
|
|
88
|
-
ctx:
|
|
89
|
+
ctx: QueryCtx | MutationCtx | ActionCtx,
|
|
89
90
|
component: AgentComponent,
|
|
90
91
|
args: {
|
|
91
92
|
userId: string | undefined;
|
|
@@ -229,23 +230,48 @@ export async function fetchRecentAndSearchMessages(
|
|
|
229
230
|
*/
|
|
230
231
|
export function filterOutOrphanedToolMessages(docs: MessageDoc[]) {
|
|
231
232
|
const toolCallIds = new Set<string>();
|
|
233
|
+
const toolResultIds = new Set<string>();
|
|
232
234
|
const result: MessageDoc[] = [];
|
|
233
235
|
for (const doc of docs) {
|
|
234
|
-
if (
|
|
235
|
-
doc.message?.role === "assistant" &&
|
|
236
|
-
Array.isArray(doc.message.content)
|
|
237
|
-
) {
|
|
236
|
+
if (doc.message && Array.isArray(doc.message.content)) {
|
|
238
237
|
for (const content of doc.message.content) {
|
|
239
238
|
if (content.type === "tool-call") {
|
|
240
239
|
toolCallIds.add(content.toolCallId);
|
|
240
|
+
} else if (content.type === "tool-result") {
|
|
241
|
+
toolResultIds.add(content.toolCallId);
|
|
241
242
|
}
|
|
242
243
|
}
|
|
243
|
-
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
for (const doc of docs) {
|
|
247
|
+
if (
|
|
248
|
+
doc.message?.role === "assistant" &&
|
|
249
|
+
Array.isArray(doc.message.content)
|
|
250
|
+
) {
|
|
251
|
+
const content = doc.message.content.filter(
|
|
252
|
+
(p) => p.type !== "tool-call" || toolResultIds.has(p.toolCallId),
|
|
253
|
+
);
|
|
254
|
+
if (content.length) {
|
|
255
|
+
result.push({
|
|
256
|
+
...doc,
|
|
257
|
+
message: {
|
|
258
|
+
...doc.message,
|
|
259
|
+
content,
|
|
260
|
+
},
|
|
261
|
+
});
|
|
262
|
+
}
|
|
244
263
|
} else if (doc.message?.role === "tool") {
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
264
|
+
const content = doc.message.content.filter((c) =>
|
|
265
|
+
toolCallIds.has(c.toolCallId),
|
|
266
|
+
);
|
|
267
|
+
if (content.length) {
|
|
268
|
+
result.push({
|
|
269
|
+
...doc,
|
|
270
|
+
message: {
|
|
271
|
+
...doc.message,
|
|
272
|
+
content,
|
|
273
|
+
},
|
|
274
|
+
});
|
|
249
275
|
}
|
|
250
276
|
} else {
|
|
251
277
|
result.push(doc);
|
|
@@ -259,7 +285,7 @@ export function filterOutOrphanedToolMessages(docs: MessageDoc[]) {
|
|
|
259
285
|
* This will not save the embeddings to the database.
|
|
260
286
|
*/
|
|
261
287
|
export async function embedMessages(
|
|
262
|
-
ctx:
|
|
288
|
+
ctx: ActionCtx,
|
|
263
289
|
{
|
|
264
290
|
userId,
|
|
265
291
|
threadId,
|
|
@@ -328,7 +354,7 @@ export async function embedMessages(
|
|
|
328
354
|
* @returns The embeddings for the strings, matching the order of the values.
|
|
329
355
|
*/
|
|
330
356
|
export async function embedMany(
|
|
331
|
-
ctx:
|
|
357
|
+
ctx: ActionCtx,
|
|
332
358
|
{
|
|
333
359
|
userId,
|
|
334
360
|
threadId,
|
|
@@ -386,7 +412,7 @@ export async function embedMany(
|
|
|
386
412
|
* @param messages The messages to embed, in the Agent MessageDoc format.
|
|
387
413
|
*/
|
|
388
414
|
export async function generateAndSaveEmbeddings(
|
|
389
|
-
ctx:
|
|
415
|
+
ctx: ActionCtx,
|
|
390
416
|
component: AgentComponent,
|
|
391
417
|
args: {
|
|
392
418
|
threadId: string | undefined;
|
|
@@ -431,7 +457,7 @@ export async function generateAndSaveEmbeddings(
|
|
|
431
457
|
* promptMessageId message.
|
|
432
458
|
*/
|
|
433
459
|
export async function fetchContextWithPrompt(
|
|
434
|
-
ctx:
|
|
460
|
+
ctx: ActionCtx,
|
|
435
461
|
component: AgentComponent,
|
|
436
462
|
args: {
|
|
437
463
|
prompt: string | (ModelMessage | Message)[] | undefined;
|
|
@@ -522,28 +548,19 @@ export async function fetchContextWithPrompt(
|
|
|
522
548
|
}
|
|
523
549
|
}
|
|
524
550
|
|
|
525
|
-
const search = searchMessages
|
|
526
|
-
|
|
527
|
-
.filter((m) => !!m)
|
|
528
|
-
.map(toModelMessage);
|
|
529
|
-
const recent = prePromptDocs
|
|
530
|
-
.map((m) => m.message)
|
|
531
|
-
.filter((m) => !!m)
|
|
532
|
-
.map(toModelMessage);
|
|
551
|
+
const search = docsToModelMessages(searchMessages);
|
|
552
|
+
const recent = docsToModelMessages(prePromptDocs);
|
|
533
553
|
const inputMessages = messages.map(toModelMessage);
|
|
534
554
|
const inputPrompt = promptArray.map(toModelMessage);
|
|
535
|
-
const existingResponses = existingResponseDocs
|
|
536
|
-
.map((m) => m.message)
|
|
537
|
-
.filter((m) => !!m)
|
|
538
|
-
.map(toModelMessage);
|
|
555
|
+
const existingResponses = docsToModelMessages(existingResponseDocs);
|
|
539
556
|
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
557
|
+
const allMessages = [
|
|
558
|
+
...search,
|
|
559
|
+
...recent,
|
|
560
|
+
...inputMessages,
|
|
561
|
+
...inputPrompt,
|
|
562
|
+
...existingResponses,
|
|
563
|
+
];
|
|
547
564
|
let processedMessages = args.contextHandler
|
|
548
565
|
? await args.contextHandler(ctx, {
|
|
549
566
|
allMessages,
|
package/src/client/streaming.ts
CHANGED
|
@@ -19,9 +19,10 @@ import {
|
|
|
19
19
|
type StreamMessage,
|
|
20
20
|
} from "../validators.js";
|
|
21
21
|
import type {
|
|
22
|
+
ActionCtx,
|
|
22
23
|
AgentComponent,
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
MutationCtx,
|
|
25
|
+
QueryCtx,
|
|
25
26
|
SyncStreamsReturnValue,
|
|
26
27
|
} from "./types.js";
|
|
27
28
|
|
|
@@ -45,7 +46,7 @@ export const vStreamMessagesReturnValue = v.object({
|
|
|
45
46
|
* @returns The deltas for each stream from their existing cursor.
|
|
46
47
|
*/
|
|
47
48
|
export async function syncStreams(
|
|
48
|
-
ctx:
|
|
49
|
+
ctx: QueryCtx | MutationCtx | ActionCtx,
|
|
49
50
|
component: AgentComponent,
|
|
50
51
|
{
|
|
51
52
|
threadId,
|
|
@@ -80,7 +81,7 @@ export async function syncStreams(
|
|
|
80
81
|
}
|
|
81
82
|
|
|
82
83
|
export async function abortStream(
|
|
83
|
-
ctx:
|
|
84
|
+
ctx: MutationCtx,
|
|
84
85
|
component: AgentComponent,
|
|
85
86
|
args: { reason: string } & (
|
|
86
87
|
| { streamId: string }
|
|
@@ -111,7 +112,7 @@ export async function abortStream(
|
|
|
111
112
|
* @returns The streams for the thread.
|
|
112
113
|
*/
|
|
113
114
|
export async function listStreams(
|
|
114
|
-
ctx:
|
|
115
|
+
ctx: QueryCtx | MutationCtx | ActionCtx,
|
|
115
116
|
component: AgentComponent,
|
|
116
117
|
{
|
|
117
118
|
threadId,
|
|
@@ -212,7 +213,7 @@ export class DeltaStreamer<T> {
|
|
|
212
213
|
|
|
213
214
|
constructor(
|
|
214
215
|
public readonly component: AgentComponent,
|
|
215
|
-
public readonly ctx:
|
|
216
|
+
public readonly ctx: MutationCtx,
|
|
216
217
|
config: {
|
|
217
218
|
throttleMs: number | undefined;
|
|
218
219
|
onAsyncAbort: (reason: string) => Promise<void>;
|