@convex-dev/agent 0.1.14 → 0.1.15-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/client/index.d.ts +496 -174
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +120 -165
- package/dist/client/index.js.map +1 -1
- package/dist/client/listMessages.d.ts +22 -0
- package/dist/client/listMessages.d.ts.map +1 -0
- package/dist/client/listMessages.js +25 -0
- package/dist/client/listMessages.js.map +1 -0
- package/dist/client/search.d.ts +162 -0
- package/dist/client/search.d.ts.map +1 -0
- package/dist/client/search.js +113 -0
- package/dist/client/search.js.map +1 -0
- package/dist/client/streaming.d.ts +17 -3
- package/dist/client/streaming.d.ts.map +1 -1
- package/dist/client/streaming.js +39 -1
- package/dist/client/streaming.js.map +1 -1
- package/dist/client/types.d.ts +5 -1
- package/dist/client/types.d.ts.map +1 -1
- package/dist/component/_generated/api.d.ts +14 -3
- package/dist/component/messages.d.ts +4 -4
- package/dist/component/messages.d.ts.map +1 -1
- package/dist/component/messages.js +12 -7
- package/dist/component/messages.js.map +1 -1
- package/dist/component/schema.d.ts +38 -28
- package/dist/component/schema.d.ts.map +1 -1
- package/dist/component/schema.js +3 -2
- package/dist/component/schema.js.map +1 -1
- package/dist/component/streams.d.ts +7 -0
- package/dist/component/streams.d.ts.map +1 -1
- package/dist/component/streams.js +49 -22
- package/dist/component/streams.js.map +1 -1
- package/dist/component/vector/index.js +3 -3
- package/dist/component/vector/index.js.map +1 -1
- package/dist/react/deltas.d.ts.map +1 -1
- package/dist/react/deltas.js +2 -2
- package/dist/react/deltas.js.map +1 -1
- package/dist/react/index.d.ts +4 -2
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +22 -9
- package/dist/react/index.js.map +1 -1
- package/dist/react/optimisticallySendMessage.js +1 -1
- package/dist/react/optimisticallySendMessage.js.map +1 -1
- package/dist/validators.d.ts +49 -55
- package/dist/validators.d.ts.map +1 -1
- package/dist/validators.js +3 -8
- package/dist/validators.js.map +1 -1
- package/package.json +4 -3
- package/src/client/index.ts +249 -268
- package/src/client/listMessages.ts +38 -0
- package/src/client/search.ts +172 -0
- package/src/client/streaming.ts +56 -3
- package/src/client/types.ts +5 -1
- package/src/component/_generated/api.d.ts +14 -3
- package/src/component/messages.ts +13 -7
- package/src/component/schema.ts +3 -2
- package/src/component/streams.ts +85 -39
- package/src/component/vector/index.ts +4 -4
- package/src/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
- package/src/react/deltas.ts +4 -2
- package/src/react/index.ts +23 -11
- package/src/react/optimisticallySendMessage.ts +1 -1
- package/src/validators.ts +8 -10
package/src/client/index.ts
CHANGED
|
@@ -34,22 +34,17 @@ import {
|
|
|
34
34
|
serializeNewMessagesInStep,
|
|
35
35
|
serializeObjectResult,
|
|
36
36
|
} from "../mapping.js";
|
|
37
|
-
import {
|
|
38
|
-
DEFAULT_MESSAGE_RANGE,
|
|
39
|
-
DEFAULT_RECENT_MESSAGES,
|
|
40
|
-
extractText,
|
|
41
|
-
isTool,
|
|
42
|
-
} from "../shared.js";
|
|
37
|
+
import { extractText, isTool } from "../shared.js";
|
|
43
38
|
import {
|
|
44
39
|
type MessageWithMetadata,
|
|
45
40
|
type MessageStatus,
|
|
46
41
|
type ProviderMetadata,
|
|
47
|
-
type SearchOptions,
|
|
48
42
|
type StreamArgs,
|
|
49
43
|
type Usage,
|
|
50
44
|
vMessageWithMetadata,
|
|
51
45
|
vSafeObjectArgs,
|
|
52
46
|
vTextArgs,
|
|
47
|
+
type MessageEmbeddings,
|
|
53
48
|
} from "../validators.js";
|
|
54
49
|
import { createTool, wrapTools } from "./createTool.js";
|
|
55
50
|
import {
|
|
@@ -77,6 +72,9 @@ import type {
|
|
|
77
72
|
UsageHandler,
|
|
78
73
|
} from "./types.js";
|
|
79
74
|
import type { threadFieldsSupportingPatch } from "../component/threads.js";
|
|
75
|
+
import { listMessages } from "./listMessages.js";
|
|
76
|
+
import { syncStreams } from "./streaming.js";
|
|
77
|
+
import { fetchContextMessages } from "./search.js";
|
|
80
78
|
|
|
81
79
|
export { storeFile, getFile } from "./files.js";
|
|
82
80
|
export { serializeDataOrUrl } from "../mapping.js";
|
|
@@ -95,12 +93,21 @@ export {
|
|
|
95
93
|
vUserMessage,
|
|
96
94
|
} from "../validators.js";
|
|
97
95
|
export type { ToolCtx } from "./createTool.js";
|
|
98
|
-
export {
|
|
96
|
+
export { filterOutOrphanedToolMessages } from "./search.js";
|
|
97
|
+
export {
|
|
98
|
+
createTool,
|
|
99
|
+
extractText,
|
|
100
|
+
fetchContextMessages,
|
|
101
|
+
isTool,
|
|
102
|
+
listMessages,
|
|
103
|
+
syncStreams,
|
|
104
|
+
};
|
|
99
105
|
export type {
|
|
100
106
|
AgentComponent,
|
|
101
107
|
ContextOptions,
|
|
102
108
|
MessageDoc,
|
|
103
109
|
ProviderMetadata,
|
|
110
|
+
RawRequestResponseHandler,
|
|
104
111
|
StorageOptions,
|
|
105
112
|
StreamArgs,
|
|
106
113
|
SyncStreamsReturnValue,
|
|
@@ -110,7 +117,7 @@ export type {
|
|
|
110
117
|
UsageHandler,
|
|
111
118
|
};
|
|
112
119
|
|
|
113
|
-
export class Agent<AgentTools extends ToolSet> {
|
|
120
|
+
export class Agent<AgentTools extends ToolSet = ToolSet> {
|
|
114
121
|
constructor(
|
|
115
122
|
public component: AgentComponent,
|
|
116
123
|
public options: {
|
|
@@ -276,25 +283,18 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
276
283
|
threadId: string;
|
|
277
284
|
thread?: Thread<ThreadTools extends undefined ? AgentTools : ThreadTools>;
|
|
278
285
|
}> {
|
|
279
|
-
const
|
|
280
|
-
this.component.threads.createThread,
|
|
281
|
-
{
|
|
282
|
-
userId: args?.userId,
|
|
283
|
-
title: args?.title,
|
|
284
|
-
summary: args?.summary,
|
|
285
|
-
}
|
|
286
|
-
);
|
|
286
|
+
const threadId = await createThread(ctx, this.component, args);
|
|
287
287
|
if (!("runAction" in ctx)) {
|
|
288
|
-
return { threadId
|
|
288
|
+
return { threadId };
|
|
289
289
|
}
|
|
290
290
|
const { thread } = await this.continueThread(ctx, {
|
|
291
|
-
threadId
|
|
291
|
+
threadId,
|
|
292
292
|
userId: args?.userId,
|
|
293
293
|
usageHandler: args?.usageHandler,
|
|
294
294
|
tools: args?.tools,
|
|
295
295
|
});
|
|
296
296
|
return {
|
|
297
|
-
threadId
|
|
297
|
+
threadId,
|
|
298
298
|
thread,
|
|
299
299
|
};
|
|
300
300
|
}
|
|
@@ -598,6 +598,7 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
598
598
|
error: (error.error as Error).message,
|
|
599
599
|
});
|
|
600
600
|
}
|
|
601
|
+
// TODO: update the streamer to error state
|
|
601
602
|
return args.onError?.(error);
|
|
602
603
|
},
|
|
603
604
|
onStepFinish: async (step) => {
|
|
@@ -611,7 +612,6 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
611
612
|
promptMessageId: messageId,
|
|
612
613
|
step,
|
|
613
614
|
});
|
|
614
|
-
// TODO: figure out pending/not
|
|
615
615
|
await streamer?.finish(saved.messages);
|
|
616
616
|
}
|
|
617
617
|
if (this.options.rawRequestResponseHandler) {
|
|
@@ -833,14 +833,7 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
833
833
|
*/
|
|
834
834
|
async saveMessage(
|
|
835
835
|
ctx: RunMutationCtx,
|
|
836
|
-
args: {
|
|
837
|
-
threadId: string;
|
|
838
|
-
userId?: string;
|
|
839
|
-
/**
|
|
840
|
-
* Metadata to save with the messages. Each element corresponds to the
|
|
841
|
-
* message at the same index.
|
|
842
|
-
*/
|
|
843
|
-
metadata?: Omit<MessageWithMetadata, "message">;
|
|
836
|
+
args: SaveMessageArgs & {
|
|
844
837
|
/**
|
|
845
838
|
* If true, it will not generate embeddings for the message.
|
|
846
839
|
* Useful if you're saving messages in a mutation where you can't run `fetch`.
|
|
@@ -848,22 +841,7 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
848
841
|
* action later that calls `agent.generateAndSaveEmbeddings`.
|
|
849
842
|
*/
|
|
850
843
|
skipEmbeddings?: boolean;
|
|
851
|
-
}
|
|
852
|
-
| {
|
|
853
|
-
prompt?: undefined;
|
|
854
|
-
/**
|
|
855
|
-
* The message to save.
|
|
856
|
-
*/
|
|
857
|
-
message: CoreMessage;
|
|
858
|
-
}
|
|
859
|
-
| {
|
|
860
|
-
/*
|
|
861
|
-
* The prompt to save with the message.
|
|
862
|
-
*/
|
|
863
|
-
prompt: string;
|
|
864
|
-
message?: undefined;
|
|
865
|
-
}
|
|
866
|
-
)
|
|
844
|
+
}
|
|
867
845
|
) {
|
|
868
846
|
const { lastMessageId, messages } = await this.saveMessages(ctx, {
|
|
869
847
|
threadId: args.threadId,
|
|
@@ -880,40 +858,15 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
880
858
|
|
|
881
859
|
/**
|
|
882
860
|
* Explicitly save messages associated with the thread (& user if provided)
|
|
861
|
+
* If you have an embedding model set, it will also generate embeddings for
|
|
862
|
+
* the messages.
|
|
883
863
|
* @param ctx The ctx parameter to a mutation or action.
|
|
884
864
|
* @param args The messages and context to save
|
|
885
865
|
* @returns
|
|
886
866
|
*/
|
|
887
867
|
async saveMessages(
|
|
888
868
|
ctx: RunMutationCtx | RunActionCtx,
|
|
889
|
-
args: {
|
|
890
|
-
threadId: string;
|
|
891
|
-
userId?: string;
|
|
892
|
-
/**
|
|
893
|
-
* The message that these messages are in response to. They will be
|
|
894
|
-
* the same "order" as this message, at increasing stepOrder(s).
|
|
895
|
-
*/
|
|
896
|
-
promptMessageId?: string;
|
|
897
|
-
/**
|
|
898
|
-
* The messages to save.
|
|
899
|
-
*/
|
|
900
|
-
messages: CoreMessageMaybeWithId[];
|
|
901
|
-
/**
|
|
902
|
-
* Metadata to save with the messages. Each element corresponds to the
|
|
903
|
-
* message at the same index.
|
|
904
|
-
*/
|
|
905
|
-
metadata?: Omit<MessageWithMetadata, "message">[];
|
|
906
|
-
/**
|
|
907
|
-
* If false, it will "commit" the messages immediately.
|
|
908
|
-
* If true, it will mark them as pending until the final step has finished.
|
|
909
|
-
* Defaults to false.
|
|
910
|
-
*/
|
|
911
|
-
pending?: boolean;
|
|
912
|
-
/**
|
|
913
|
-
* If true, it will fail any pending steps.
|
|
914
|
-
* Defaults to false.
|
|
915
|
-
*/
|
|
916
|
-
failPendingSteps?: boolean;
|
|
869
|
+
args: SaveMessagesArgs & {
|
|
917
870
|
/**
|
|
918
871
|
* Skip generating embeddings for the messages. Useful if you're
|
|
919
872
|
* saving messages in a mutation where you can't run `fetch`.
|
|
@@ -933,9 +886,12 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
933
886
|
model: string;
|
|
934
887
|
}
|
|
935
888
|
| undefined;
|
|
936
|
-
|
|
889
|
+
const { skipEmbeddings, ...rest } = args;
|
|
890
|
+
if (args.embeddings) {
|
|
891
|
+
embeddings = args.embeddings;
|
|
892
|
+
} else if (skipEmbeddings || !("runAction" in ctx)) {
|
|
937
893
|
embeddings = undefined;
|
|
938
|
-
if (!
|
|
894
|
+
if (!skipEmbeddings && this.options.textEmbedding) {
|
|
939
895
|
console.warn(
|
|
940
896
|
"You're trying to save messages and generate embeddings, but you're in a mutation. " +
|
|
941
897
|
"Pass `skipEmbeddings: true` to skip generating embeddings in the mutation and skip this warning. " +
|
|
@@ -953,33 +909,11 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
953
909
|
args.messages
|
|
954
910
|
);
|
|
955
911
|
}
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
userId: args.userId,
|
|
912
|
+
return saveMessages(ctx, this.component, {
|
|
913
|
+
...rest,
|
|
959
914
|
agentName: this.options.name,
|
|
960
|
-
promptMessageId: args.promptMessageId,
|
|
961
915
|
embeddings,
|
|
962
|
-
messages: await Promise.all(
|
|
963
|
-
args.messages.map(async (m, i) => {
|
|
964
|
-
const { message, fileIds } = await serializeMessage(
|
|
965
|
-
ctx,
|
|
966
|
-
this.component,
|
|
967
|
-
m
|
|
968
|
-
);
|
|
969
|
-
return {
|
|
970
|
-
...args.metadata?.[i],
|
|
971
|
-
message,
|
|
972
|
-
fileIds,
|
|
973
|
-
} as MessageWithMetadata;
|
|
974
|
-
})
|
|
975
|
-
),
|
|
976
|
-
failPendingSteps: args.failPendingSteps ?? false,
|
|
977
|
-
pending: args.pending ?? false,
|
|
978
916
|
});
|
|
979
|
-
return {
|
|
980
|
-
lastMessageId: result.messages.at(-1)!._id,
|
|
981
|
-
messages: result.messages,
|
|
982
|
-
};
|
|
983
917
|
}
|
|
984
918
|
|
|
985
919
|
/**
|
|
@@ -1001,17 +935,7 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
1001
935
|
statuses?: MessageStatus[];
|
|
1002
936
|
}
|
|
1003
937
|
): Promise<PaginationResult<MessageDoc>> {
|
|
1004
|
-
|
|
1005
|
-
return {
|
|
1006
|
-
page: [],
|
|
1007
|
-
isDone: true,
|
|
1008
|
-
continueCursor: args.paginationOpts.cursor ?? "",
|
|
1009
|
-
};
|
|
1010
|
-
}
|
|
1011
|
-
return ctx.runQuery(this.component.messages.listMessagesByThreadId, {
|
|
1012
|
-
order: "desc",
|
|
1013
|
-
...args,
|
|
1014
|
-
});
|
|
938
|
+
return listMessages(ctx, this.component, args);
|
|
1015
939
|
}
|
|
1016
940
|
|
|
1017
941
|
/**
|
|
@@ -1027,25 +951,11 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
1027
951
|
args: {
|
|
1028
952
|
threadId: string;
|
|
1029
953
|
streamArgs: StreamArgs | undefined;
|
|
954
|
+
// By default, only streaming messages are included.
|
|
955
|
+
includeStatuses?: ("streaming" | "finished" | "aborted")[];
|
|
1030
956
|
}
|
|
1031
957
|
): Promise<SyncStreamsReturnValue | undefined> {
|
|
1032
|
-
|
|
1033
|
-
if (args.streamArgs.kind === "list") {
|
|
1034
|
-
return {
|
|
1035
|
-
kind: "list",
|
|
1036
|
-
messages: await ctx.runQuery(this.component.streams.list, {
|
|
1037
|
-
threadId: args.threadId,
|
|
1038
|
-
}),
|
|
1039
|
-
};
|
|
1040
|
-
} else {
|
|
1041
|
-
return {
|
|
1042
|
-
kind: "deltas",
|
|
1043
|
-
deltas: await ctx.runQuery(this.component.streams.listDeltas, {
|
|
1044
|
-
threadId: args.threadId,
|
|
1045
|
-
cursors: args.streamArgs.cursors,
|
|
1046
|
-
}),
|
|
1047
|
-
};
|
|
1048
|
-
}
|
|
958
|
+
return syncStreams(ctx, this.component, args);
|
|
1049
959
|
}
|
|
1050
960
|
|
|
1051
961
|
/**
|
|
@@ -1072,76 +982,28 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
1072
982
|
}
|
|
1073
983
|
): Promise<MessageDoc[]> {
|
|
1074
984
|
assert(args.userId || args.threadId, "Specify userId or threadId");
|
|
1075
|
-
// Fetch the latest messages from the thread
|
|
1076
|
-
let included: Set<string> | undefined;
|
|
1077
985
|
const opts = this._mergedContextOptions(args.contextOptions);
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
// Reverse since we fetched in descending order
|
|
1100
|
-
...page.reverse()
|
|
1101
|
-
);
|
|
1102
|
-
}
|
|
1103
|
-
if (opts.searchOptions?.textSearch || opts.searchOptions?.vectorSearch) {
|
|
1104
|
-
const targetMessage = contextMessages.find(
|
|
1105
|
-
(m) => m._id === args.upToAndIncludingMessageId
|
|
1106
|
-
)?.message;
|
|
1107
|
-
const messagesToSearch = targetMessage ? [targetMessage] : args.messages;
|
|
1108
|
-
if (!("runAction" in ctx)) {
|
|
1109
|
-
throw new Error("searchUserMessages only works in an action");
|
|
1110
|
-
}
|
|
1111
|
-
const searchMessages = await ctx.runAction(
|
|
1112
|
-
this.component.messages.searchMessages,
|
|
1113
|
-
{
|
|
1114
|
-
searchAllMessagesForUserId: opts?.searchOtherThreads
|
|
1115
|
-
? args.userId ??
|
|
1116
|
-
(args.threadId &&
|
|
1117
|
-
(
|
|
1118
|
-
await ctx.runQuery(this.component.threads.getThread, {
|
|
1119
|
-
threadId: args.threadId,
|
|
1120
|
-
})
|
|
1121
|
-
)?.userId)
|
|
1122
|
-
: undefined,
|
|
1123
|
-
threadId: args.threadId,
|
|
1124
|
-
beforeMessageId: args.upToAndIncludingMessageId,
|
|
1125
|
-
...(await this._searchOptionsWithEmbeddingAndDefaults(
|
|
1126
|
-
ctx,
|
|
1127
|
-
{ userId: args.userId, threadId: args.threadId },
|
|
1128
|
-
opts,
|
|
1129
|
-
messagesToSearch
|
|
1130
|
-
)),
|
|
1131
|
-
}
|
|
1132
|
-
);
|
|
1133
|
-
// TODO: track what messages we used for context
|
|
1134
|
-
contextMessages.unshift(
|
|
1135
|
-
...searchMessages.filter((m) => !included?.has(m._id))
|
|
1136
|
-
);
|
|
1137
|
-
}
|
|
1138
|
-
// Ensure we don't include tool messages without a corresponding tool call
|
|
1139
|
-
return filterOutOrphanedToolMessages(
|
|
1140
|
-
contextMessages.sort((a, b) =>
|
|
1141
|
-
// Sort the raw MessageDocs by order and stepOrder
|
|
1142
|
-
a.order === b.order ? a.stepOrder - b.stepOrder : a.order - b.order
|
|
1143
|
-
)
|
|
1144
|
-
);
|
|
986
|
+
return fetchContextMessages(ctx, this.component, {
|
|
987
|
+
...args,
|
|
988
|
+
contextOptions: opts,
|
|
989
|
+
getEmbedding: async (text) => {
|
|
990
|
+
assert("runAction" in ctx);
|
|
991
|
+
assert(
|
|
992
|
+
this.options.textEmbedding,
|
|
993
|
+
"A textEmbedding model is required to be set on the Agent that you're doing vector search with"
|
|
994
|
+
);
|
|
995
|
+
return {
|
|
996
|
+
vector: (
|
|
997
|
+
await this.doEmbed(ctx, {
|
|
998
|
+
userId: args.userId,
|
|
999
|
+
threadId: args.threadId,
|
|
1000
|
+
values: [text],
|
|
1001
|
+
})
|
|
1002
|
+
).embeddings[0],
|
|
1003
|
+
vectorModel: this.options.textEmbedding.modelId,
|
|
1004
|
+
};
|
|
1005
|
+
},
|
|
1006
|
+
});
|
|
1145
1007
|
}
|
|
1146
1008
|
|
|
1147
1009
|
/**
|
|
@@ -1154,13 +1016,7 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
1154
1016
|
ctx: RunQueryCtx,
|
|
1155
1017
|
args: { threadId: string }
|
|
1156
1018
|
): Promise<ThreadDoc> {
|
|
1157
|
-
|
|
1158
|
-
threadId: args.threadId,
|
|
1159
|
-
});
|
|
1160
|
-
if (!thread) {
|
|
1161
|
-
throw new Error("Thread not found");
|
|
1162
|
-
}
|
|
1163
|
-
return thread;
|
|
1019
|
+
return getThreadMetadata(ctx, this.component, args);
|
|
1164
1020
|
}
|
|
1165
1021
|
|
|
1166
1022
|
/**
|
|
@@ -1765,49 +1621,11 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
1765
1621
|
...this.options.contextOptions,
|
|
1766
1622
|
...opts,
|
|
1767
1623
|
searchOptions: searchOptions.limit
|
|
1768
|
-
? (searchOptions as
|
|
1624
|
+
? (searchOptions as ContextOptions["searchOptions"])
|
|
1769
1625
|
: undefined,
|
|
1770
1626
|
};
|
|
1771
1627
|
}
|
|
1772
1628
|
|
|
1773
|
-
async _searchOptionsWithEmbeddingAndDefaults(
|
|
1774
|
-
ctx: RunActionCtx,
|
|
1775
|
-
{ userId, threadId }: { userId?: string; threadId?: string },
|
|
1776
|
-
contextOptions: ContextOptions,
|
|
1777
|
-
messages: CoreMessage[]
|
|
1778
|
-
): Promise<SearchOptions> {
|
|
1779
|
-
assert(
|
|
1780
|
-
contextOptions.searchOptions?.textSearch ||
|
|
1781
|
-
contextOptions.searchOptions?.vectorSearch,
|
|
1782
|
-
"searchOptions is required"
|
|
1783
|
-
);
|
|
1784
|
-
assert(messages.length > 0, "Core messages cannot be empty");
|
|
1785
|
-
const text = extractText(messages.at(-1)!);
|
|
1786
|
-
const search: SearchOptions = {
|
|
1787
|
-
limit: contextOptions.searchOptions?.limit ?? 10,
|
|
1788
|
-
messageRange: {
|
|
1789
|
-
...DEFAULT_MESSAGE_RANGE,
|
|
1790
|
-
...contextOptions.searchOptions?.messageRange,
|
|
1791
|
-
},
|
|
1792
|
-
text: extractText(messages.at(-1)!),
|
|
1793
|
-
};
|
|
1794
|
-
if (
|
|
1795
|
-
contextOptions.searchOptions?.vectorSearch &&
|
|
1796
|
-
text &&
|
|
1797
|
-
this.options.textEmbedding
|
|
1798
|
-
) {
|
|
1799
|
-
search.vector = (
|
|
1800
|
-
await this.doEmbed(ctx, {
|
|
1801
|
-
threadId,
|
|
1802
|
-
userId,
|
|
1803
|
-
values: [text],
|
|
1804
|
-
})
|
|
1805
|
-
).embeddings[0];
|
|
1806
|
-
search.vectorModel = this.options.textEmbedding.modelId;
|
|
1807
|
-
}
|
|
1808
|
-
return search;
|
|
1809
|
-
}
|
|
1810
|
-
|
|
1811
1629
|
async doEmbed(
|
|
1812
1630
|
ctx: RunActionCtx,
|
|
1813
1631
|
options: {
|
|
@@ -1819,7 +1637,10 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
1819
1637
|
}
|
|
1820
1638
|
): Promise<{ embeddings: number[][] }> {
|
|
1821
1639
|
const embedding = this.options.textEmbedding;
|
|
1822
|
-
assert(
|
|
1640
|
+
assert(
|
|
1641
|
+
embedding,
|
|
1642
|
+
"a textEmbedding model is required to be set on the Agent that you're doing vector search with"
|
|
1643
|
+
);
|
|
1823
1644
|
const result = await embedding.doEmbed({
|
|
1824
1645
|
values: options.values,
|
|
1825
1646
|
abortSignal: options.abortSignal,
|
|
@@ -2120,31 +1941,191 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
2120
1941
|
}
|
|
2121
1942
|
}
|
|
2122
1943
|
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
result.push(doc);
|
|
2140
|
-
} else {
|
|
2141
|
-
console.debug("Filtering out orphaned tool message", doc);
|
|
2142
|
-
}
|
|
2143
|
-
} else {
|
|
2144
|
-
result.push(doc);
|
|
2145
|
-
}
|
|
1944
|
+
type CoreMessageMaybeWithId = CoreMessage & { id?: string | undefined };
|
|
1945
|
+
|
|
1946
|
+
/**
|
|
1947
|
+
* Create a thread to store messages with an Agent.
|
|
1948
|
+
* @param ctx The context from a mutation or action.
|
|
1949
|
+
* @param component The Agent component, usually `components.agent`.
|
|
1950
|
+
* @param args The associated thread metadata.
|
|
1951
|
+
* @returns The id of the created thread.
|
|
1952
|
+
*/
|
|
1953
|
+
export async function createThread(
|
|
1954
|
+
ctx: RunMutationCtx,
|
|
1955
|
+
component: AgentComponent,
|
|
1956
|
+
args?: {
|
|
1957
|
+
userId?: string;
|
|
1958
|
+
title?: string;
|
|
1959
|
+
summary?: string;
|
|
2146
1960
|
}
|
|
2147
|
-
|
|
1961
|
+
) {
|
|
1962
|
+
const { _id: threadId } = await ctx.runMutation(
|
|
1963
|
+
component.threads.createThread,
|
|
1964
|
+
{ userId: args?.userId, title: args?.title, summary: args?.summary }
|
|
1965
|
+
);
|
|
1966
|
+
return threadId;
|
|
2148
1967
|
}
|
|
2149
1968
|
|
|
2150
|
-
|
|
1969
|
+
/**
|
|
1970
|
+
* Get the metadata for a thread.
|
|
1971
|
+
* @param ctx A ctx object from a query, mutation, or action.
|
|
1972
|
+
* @param args.threadId The thread to get the metadata for.
|
|
1973
|
+
* @returns The metadata for the thread.
|
|
1974
|
+
*/
|
|
1975
|
+
export async function getThreadMetadata(
|
|
1976
|
+
ctx: RunQueryCtx,
|
|
1977
|
+
component: AgentComponent,
|
|
1978
|
+
args: { threadId: string }
|
|
1979
|
+
): Promise<ThreadDoc> {
|
|
1980
|
+
const thread = await ctx.runQuery(component.threads.getThread, {
|
|
1981
|
+
threadId: args.threadId,
|
|
1982
|
+
});
|
|
1983
|
+
if (!thread) {
|
|
1984
|
+
throw new Error("Thread not found");
|
|
1985
|
+
}
|
|
1986
|
+
return thread;
|
|
1987
|
+
}
|
|
1988
|
+
|
|
1989
|
+
type SaveMessagesArgs = {
|
|
1990
|
+
threadId: string;
|
|
1991
|
+
userId?: string;
|
|
1992
|
+
/**
|
|
1993
|
+
* The message that these messages are in response to. They will be
|
|
1994
|
+
* the same "order" as this message, at increasing stepOrder(s).
|
|
1995
|
+
*/
|
|
1996
|
+
promptMessageId?: string;
|
|
1997
|
+
/**
|
|
1998
|
+
* The messages to save.
|
|
1999
|
+
*/
|
|
2000
|
+
messages: CoreMessageMaybeWithId[];
|
|
2001
|
+
/**
|
|
2002
|
+
* Metadata to save with the messages. Each element corresponds to the
|
|
2003
|
+
* message at the same index.
|
|
2004
|
+
*/
|
|
2005
|
+
metadata?: Omit<MessageWithMetadata, "message">[];
|
|
2006
|
+
/**
|
|
2007
|
+
* If false, it will "commit" the messages immediately.
|
|
2008
|
+
* If true, it will mark them as pending until the final step has finished.
|
|
2009
|
+
* Defaults to false.
|
|
2010
|
+
*/
|
|
2011
|
+
pending?: boolean;
|
|
2012
|
+
/**
|
|
2013
|
+
* If true, it will fail any pending steps.
|
|
2014
|
+
* Defaults to false.
|
|
2015
|
+
*/
|
|
2016
|
+
failPendingSteps?: boolean;
|
|
2017
|
+
/**
|
|
2018
|
+
* The embeddings to save with the messages.
|
|
2019
|
+
*/
|
|
2020
|
+
embeddings?: MessageEmbeddings;
|
|
2021
|
+
};
|
|
2022
|
+
|
|
2023
|
+
/**
|
|
2024
|
+
* Explicitly save messages associated with the thread (& user if provided)
|
|
2025
|
+
*/
|
|
2026
|
+
export async function saveMessages(
|
|
2027
|
+
ctx: RunMutationCtx,
|
|
2028
|
+
component: AgentComponent,
|
|
2029
|
+
args: SaveMessagesArgs & {
|
|
2030
|
+
/**
|
|
2031
|
+
* The agent name to associate with the messages.
|
|
2032
|
+
*/
|
|
2033
|
+
agentName?: string;
|
|
2034
|
+
}
|
|
2035
|
+
) {
|
|
2036
|
+
const result = await ctx.runMutation(component.messages.addMessages, {
|
|
2037
|
+
threadId: args.threadId,
|
|
2038
|
+
userId: args.userId,
|
|
2039
|
+
agentName: args.agentName,
|
|
2040
|
+
promptMessageId: args.promptMessageId,
|
|
2041
|
+
embeddings: args.embeddings,
|
|
2042
|
+
messages: await Promise.all(
|
|
2043
|
+
args.messages.map(async (m, i) => {
|
|
2044
|
+
const { message, fileIds } = await serializeMessage(ctx, component, m);
|
|
2045
|
+
return {
|
|
2046
|
+
...args.metadata?.[i],
|
|
2047
|
+
message,
|
|
2048
|
+
fileIds,
|
|
2049
|
+
} as MessageWithMetadata;
|
|
2050
|
+
})
|
|
2051
|
+
),
|
|
2052
|
+
failPendingSteps: args.failPendingSteps ?? false,
|
|
2053
|
+
pending: args.pending ?? false,
|
|
2054
|
+
});
|
|
2055
|
+
return {
|
|
2056
|
+
lastMessageId: result.messages.at(-1)!._id,
|
|
2057
|
+
messages: result.messages,
|
|
2058
|
+
};
|
|
2059
|
+
}
|
|
2060
|
+
|
|
2061
|
+
type SaveMessageArgs = {
|
|
2062
|
+
threadId: string;
|
|
2063
|
+
userId?: string;
|
|
2064
|
+
/**
|
|
2065
|
+
* Metadata to save with the messages. Each element corresponds to the
|
|
2066
|
+
* message at the same index.
|
|
2067
|
+
*/
|
|
2068
|
+
metadata?: Omit<MessageWithMetadata, "message">;
|
|
2069
|
+
/**
|
|
2070
|
+
* The embedding to save with the message.
|
|
2071
|
+
*/
|
|
2072
|
+
embedding?: {
|
|
2073
|
+
vector: number[];
|
|
2074
|
+
model: string;
|
|
2075
|
+
};
|
|
2076
|
+
} & (
|
|
2077
|
+
| {
|
|
2078
|
+
prompt?: undefined;
|
|
2079
|
+
/**
|
|
2080
|
+
* The message to save.
|
|
2081
|
+
*/
|
|
2082
|
+
message: CoreMessage;
|
|
2083
|
+
}
|
|
2084
|
+
| {
|
|
2085
|
+
/*
|
|
2086
|
+
* The prompt to save with the message.
|
|
2087
|
+
*/
|
|
2088
|
+
prompt: string;
|
|
2089
|
+
message?: undefined;
|
|
2090
|
+
}
|
|
2091
|
+
);
|
|
2092
|
+
|
|
2093
|
+
/**
|
|
2094
|
+
* Save a message to the thread.
|
|
2095
|
+
* @param ctx A ctx object from a mutation or action.
|
|
2096
|
+
* @param args The message and what to associate it with (user / thread)
|
|
2097
|
+
* You can pass extra metadata alongside the message, e.g. associated fileIds.
|
|
2098
|
+
* @returns The messageId of the saved message.
|
|
2099
|
+
*/
|
|
2100
|
+
export async function saveMessage(
|
|
2101
|
+
ctx: RunMutationCtx,
|
|
2102
|
+
component: AgentComponent,
|
|
2103
|
+
args: SaveMessageArgs & {
|
|
2104
|
+
/**
|
|
2105
|
+
* The agent name to associate with the message.
|
|
2106
|
+
*/
|
|
2107
|
+
agentName?: string;
|
|
2108
|
+
}
|
|
2109
|
+
) {
|
|
2110
|
+
let embeddings: MessageEmbeddings | undefined;
|
|
2111
|
+
if (args.embedding) {
|
|
2112
|
+
const dimension = args.embedding.vector.length;
|
|
2113
|
+
validateVectorDimension(dimension);
|
|
2114
|
+
embeddings = {
|
|
2115
|
+
model: args.embedding.model,
|
|
2116
|
+
dimension,
|
|
2117
|
+
vectors: [args.embedding.vector],
|
|
2118
|
+
};
|
|
2119
|
+
}
|
|
2120
|
+
const { lastMessageId, messages } = await saveMessages(ctx, component, {
|
|
2121
|
+
threadId: args.threadId,
|
|
2122
|
+
userId: args.userId,
|
|
2123
|
+
messages:
|
|
2124
|
+
args.prompt !== undefined
|
|
2125
|
+
? [{ role: "user", content: args.prompt }]
|
|
2126
|
+
: [args.message],
|
|
2127
|
+
metadata: args.metadata ? [args.metadata] : undefined,
|
|
2128
|
+
embeddings,
|
|
2129
|
+
});
|
|
2130
|
+
return { messageId: lastMessageId, message: messages.at(-1)! };
|
|
2131
|
+
}
|