@convex-dev/agent 0.5.0-alpha.1 → 0.6.0-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 +32 -27
- package/dist/UIMessages.d.ts +46 -0
- package/dist/UIMessages.d.ts.map +1 -0
- package/dist/UIMessages.js +546 -0
- package/dist/UIMessages.js.map +1 -0
- package/dist/client/createTool.d.ts +129 -27
- package/dist/client/createTool.d.ts.map +1 -1
- package/dist/client/createTool.js +66 -12
- package/dist/client/createTool.js.map +1 -1
- package/dist/client/defaultComponent.d.ts +11 -0
- package/dist/client/defaultComponent.d.ts.map +1 -0
- package/dist/client/defaultComponent.js +7 -0
- package/dist/client/defaultComponent.js.map +1 -0
- package/dist/client/definePlaygroundAPI.d.ts +1323 -192
- package/dist/client/definePlaygroundAPI.d.ts.map +1 -1
- package/dist/client/definePlaygroundAPI.js +52 -28
- package/dist/client/definePlaygroundAPI.js.map +1 -1
- package/dist/client/files.d.ts +20 -7
- package/dist/client/files.d.ts.map +1 -1
- package/dist/client/files.js +68 -11
- package/dist/client/files.js.map +1 -1
- package/dist/client/index.d.ts +1056 -965
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +242 -748
- package/dist/client/index.js.map +1 -1
- package/dist/client/messages.d.ts +461 -0
- package/dist/client/messages.d.ts.map +1 -0
- package/dist/client/messages.js +106 -0
- package/dist/client/messages.js.map +1 -0
- package/dist/client/mockModel.d.ts +42 -0
- package/dist/client/mockModel.d.ts.map +1 -0
- package/dist/client/mockModel.js +175 -0
- package/dist/client/mockModel.js.map +1 -0
- package/dist/client/saveInputMessages.d.ts +20 -0
- package/dist/client/saveInputMessages.d.ts.map +1 -0
- package/dist/client/saveInputMessages.js +58 -0
- package/dist/client/saveInputMessages.js.map +1 -0
- package/dist/client/search.d.ts +346 -35
- package/dist/client/search.d.ts.map +1 -1
- package/dist/client/search.js +350 -39
- package/dist/client/search.js.map +1 -1
- package/dist/client/start.d.ts +84 -0
- package/dist/client/start.d.ts.map +1 -0
- package/dist/client/start.js +171 -0
- package/dist/client/start.js.map +1 -0
- package/dist/client/streamText.d.ts +46 -0
- package/dist/client/streamText.d.ts.map +1 -0
- package/dist/client/streamText.js +93 -0
- package/dist/client/streamText.js.map +1 -0
- package/dist/client/streaming.d.ts +3705 -32
- package/dist/client/streaming.d.ts.map +1 -1
- package/dist/client/streaming.js +141 -59
- package/dist/client/streaming.js.map +1 -1
- package/dist/client/threads.d.ts +46 -0
- package/dist/client/threads.d.ts.map +1 -0
- package/dist/client/threads.js +49 -0
- package/dist/client/threads.js.map +1 -0
- package/dist/client/types.d.ts +265 -128
- package/dist/client/types.d.ts.map +1 -1
- package/dist/client/utils.d.ts +4 -0
- package/dist/client/utils.d.ts.map +1 -0
- package/dist/client/utils.js +21 -0
- package/dist/client/utils.js.map +1 -0
- package/dist/component/_generated/api.d.ts +24 -2178
- package/dist/component/_generated/api.d.ts.map +1 -1
- package/dist/component/_generated/api.js +10 -1
- package/dist/component/_generated/api.js.map +1 -1
- package/dist/component/_generated/component.d.ts +3119 -0
- package/dist/component/_generated/component.d.ts.map +1 -0
- package/dist/component/_generated/component.js +11 -0
- package/dist/component/_generated/component.js.map +1 -0
- package/dist/component/_generated/dataModel.d.ts +4 -18
- package/dist/component/_generated/dataModel.d.ts.map +1 -0
- package/dist/component/_generated/dataModel.js +11 -0
- package/dist/component/_generated/dataModel.js.map +1 -0
- package/dist/component/_generated/server.d.ts +10 -38
- package/dist/component/_generated/server.d.ts.map +1 -1
- package/dist/component/_generated/server.js +9 -5
- package/dist/component/_generated/server.js.map +1 -1
- package/dist/component/files.d.ts +16 -10
- package/dist/component/files.d.ts.map +1 -1
- package/dist/component/files.js +10 -2
- package/dist/component/files.js.map +1 -1
- package/dist/component/messages.d.ts +2553 -342
- package/dist/component/messages.d.ts.map +1 -1
- package/dist/component/messages.js +387 -154
- package/dist/component/messages.js.map +1 -1
- package/dist/component/schema.d.ts +5697 -3584
- package/dist/component/schema.d.ts.map +1 -1
- package/dist/component/schema.js +18 -41
- package/dist/component/schema.js.map +1 -1
- package/dist/component/streams.d.ts +35 -335
- package/dist/component/streams.d.ts.map +1 -1
- package/dist/component/streams.js +114 -73
- package/dist/component/streams.js.map +1 -1
- package/dist/component/threads.d.ts +16 -16
- package/dist/component/users.d.ts +4 -4
- package/dist/component/vector/index.d.ts +1 -1
- package/dist/component/vector/index.d.ts.map +1 -1
- package/dist/component/vector/index.js +1 -3
- package/dist/component/vector/index.js.map +1 -1
- package/dist/deltas.d.ts +43 -0
- package/dist/deltas.d.ts.map +1 -0
- package/dist/deltas.js +447 -0
- package/dist/deltas.js.map +1 -0
- package/dist/mapping.d.ts +20 -20
- package/dist/mapping.d.ts.map +1 -1
- package/dist/mapping.js +313 -96
- package/dist/mapping.js.map +1 -1
- package/dist/react/SmoothText.d.ts +5 -0
- package/dist/react/SmoothText.d.ts.map +1 -0
- package/dist/react/SmoothText.js +6 -0
- package/dist/react/SmoothText.js.map +1 -0
- package/dist/react/index.d.ts +5 -77
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +6 -160
- package/dist/react/index.js.map +1 -1
- package/dist/react/optimisticallySendMessage.d.ts +36 -3
- package/dist/react/optimisticallySendMessage.d.ts.map +1 -1
- package/dist/react/optimisticallySendMessage.js +35 -9
- package/dist/react/optimisticallySendMessage.js.map +1 -1
- package/dist/react/types.d.ts +4 -18
- package/dist/react/types.d.ts.map +1 -1
- package/dist/react/useDeltaStreams.d.ts +10 -0
- package/dist/react/useDeltaStreams.d.ts.map +1 -0
- package/dist/react/useDeltaStreams.js +101 -0
- package/dist/react/useDeltaStreams.js.map +1 -0
- package/dist/react/useSmoothText.d.ts +13 -12
- package/dist/react/useSmoothText.d.ts.map +1 -1
- package/dist/react/useSmoothText.js +32 -15
- package/dist/react/useSmoothText.js.map +1 -1
- package/dist/react/useStreamingUIMessages.d.ts +22 -0
- package/dist/react/useStreamingUIMessages.d.ts.map +1 -0
- package/dist/react/useStreamingUIMessages.js +92 -0
- package/dist/react/useStreamingUIMessages.js.map +1 -0
- package/dist/react/useThreadMessages.d.ts +104 -0
- package/dist/react/useThreadMessages.d.ts.map +1 -0
- package/dist/react/useThreadMessages.js +148 -0
- package/dist/react/useThreadMessages.js.map +1 -0
- package/dist/react/useUIMessages.d.ts +96 -0
- package/dist/react/useUIMessages.d.ts.map +1 -0
- package/dist/react/useUIMessages.js +108 -0
- package/dist/react/useUIMessages.js.map +1 -0
- package/dist/shared.d.ts +20 -4
- package/dist/shared.d.ts.map +1 -1
- package/dist/shared.js +45 -8
- package/dist/shared.js.map +1 -1
- package/dist/validators.d.ts +22981 -5666
- package/dist/validators.d.ts.map +1 -1
- package/dist/validators.js +245 -137
- package/dist/validators.js.map +1 -1
- package/package.json +98 -50
- package/src/UIMessages.combineUIMessages.test.ts +239 -0
- package/src/UIMessages.test.ts +273 -0
- package/src/UIMessages.ts +739 -0
- package/src/client/createTool.ts +293 -76
- package/src/client/defaultComponent.ts +17 -0
- package/src/client/definePlaygroundAPI.ts +67 -31
- package/src/client/files.ts +100 -20
- package/src/client/index.test.ts +40 -85
- package/src/client/index.ts +520 -1290
- package/src/client/messages.ts +237 -0
- package/src/client/mockModel.ts +245 -0
- package/src/client/saveInputMessages.test.ts +583 -0
- package/src/client/saveInputMessages.ts +101 -0
- package/src/client/search.test.ts +1207 -0
- package/src/client/search.ts +577 -70
- package/src/client/start.ts +310 -0
- package/src/client/streamText.ts +163 -0
- package/src/client/streaming.test.ts +186 -0
- package/src/client/streaming.ts +219 -97
- package/src/client/threads.ts +83 -0
- package/src/client/types.ts +368 -219
- package/src/client/utils.ts +27 -0
- package/src/component/_generated/api.ts +64 -0
- package/src/component/_generated/component.ts +4913 -0
- package/src/component/_generated/{server.d.ts → server.ts} +33 -21
- package/src/component/files.ts +11 -2
- package/src/component/messages.test.ts +195 -51
- package/src/component/messages.ts +490 -201
- package/src/component/schema.ts +20 -46
- package/src/component/setup.test.ts +7 -0
- package/src/component/streams.ts +184 -83
- package/src/component/users.test.ts +0 -1
- package/src/component/vector/index.ts +1 -3
- package/src/deltas.test.ts +626 -0
- package/src/deltas.ts +570 -0
- package/src/fromUIMessages.test.ts +497 -0
- package/src/mapping.test.ts +103 -6
- package/src/mapping.ts +422 -161
- package/src/react/SmoothText.tsx +9 -0
- package/src/react/index.ts +10 -230
- package/src/react/optimisticallySendMessage.ts +55 -12
- package/src/react/types.ts +6 -39
- package/src/react/useDeltaStreams.ts +154 -0
- package/src/react/useSmoothText.ts +56 -36
- package/src/react/useStreamingUIMessages.ts +143 -0
- package/src/react/useThreadMessages.ts +262 -0
- package/src/react/useUIMessages.test.ts +255 -0
- package/src/react/useUIMessages.ts +195 -0
- package/src/shared.ts +88 -12
- package/src/test.ts +18 -0
- package/src/toUIMessages.test.ts +1269 -0
- package/src/validators.test.ts +18 -19
- package/src/validators.ts +325 -185
- package/dist/client/_generated/_ignore.d.ts +0 -1
- package/dist/client/_generated/_ignore.d.ts.map +0 -1
- package/dist/client/_generated/_ignore.js +0 -3
- package/dist/client/_generated/_ignore.js.map +0 -1
- package/dist/client/listMessages.d.ts +0 -22
- package/dist/client/listMessages.d.ts.map +0 -1
- package/dist/client/listMessages.js +0 -25
- package/dist/client/listMessages.js.map +0 -1
- package/dist/package.json +0 -3
- package/dist/react/deltas.d.ts +0 -26
- package/dist/react/deltas.d.ts.map +0 -1
- package/dist/react/deltas.js +0 -384
- package/dist/react/deltas.js.map +0 -1
- package/dist/react/toUIMessages.d.ts +0 -15
- package/dist/react/toUIMessages.d.ts.map +0 -1
- package/dist/react/toUIMessages.js +0 -211
- package/dist/react/toUIMessages.js.map +0 -1
- package/src/client/listMessages.ts +0 -38
- package/src/component/_generated/api.d.ts +0 -2202
- package/src/component/_generated/api.js +0 -23
- package/src/component/_generated/server.js +0 -90
- package/src/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
- package/src/react/deltas.test.ts +0 -315
- package/src/react/deltas.ts +0 -478
- package/src/react/toUIMessages.test.ts +0 -420
- package/src/react/toUIMessages.ts +0 -253
- package/src/vitest.config.ts +0 -7
- /package/src/component/_generated/{dataModel.d.ts → dataModel.ts} +0 -0
package/src/client/index.ts
CHANGED
|
@@ -1,29 +1,32 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { JSONValue } from "@ai-sdk/provider";
|
|
2
2
|
import type {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
FlexibleSchema,
|
|
4
|
+
IdGenerator,
|
|
5
|
+
InferSchema,
|
|
6
|
+
} from "@ai-sdk/provider-utils";
|
|
7
|
+
import type {
|
|
8
|
+
CallSettings,
|
|
9
|
+
EmbeddingModel,
|
|
7
10
|
GenerateObjectResult,
|
|
8
11
|
GenerateTextResult,
|
|
9
|
-
|
|
12
|
+
LanguageModel,
|
|
13
|
+
ModelMessage,
|
|
10
14
|
StepResult,
|
|
11
|
-
StreamObjectResult,
|
|
12
|
-
StreamTextResult,
|
|
13
|
-
ToolSet,
|
|
14
|
-
UserContent,
|
|
15
15
|
StopCondition,
|
|
16
|
-
|
|
16
|
+
StreamTextResult,
|
|
17
17
|
ToolChoice,
|
|
18
|
+
ToolSet,
|
|
18
19
|
} from "ai";
|
|
19
|
-
import {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
20
|
+
import { generateObject, generateText, stepCountIs, streamObject } from "ai";
|
|
21
|
+
|
|
22
|
+
const MIGRATION_URL = "https://github.com/get-convex/agent/blob/main/MIGRATION.md";
|
|
23
|
+
const warnedDeprecations = new Set<string>();
|
|
24
|
+
function warnDeprecation(key: string, message: string) {
|
|
25
|
+
if (!warnedDeprecations.has(key)) {
|
|
26
|
+
warnedDeprecations.add(key);
|
|
27
|
+
console.warn(`[@convex-dev/agent] ${message}\n See: ${MIGRATION_URL}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
27
30
|
import { assert, omit, pick } from "convex-helpers";
|
|
28
31
|
import {
|
|
29
32
|
internalActionGeneric,
|
|
@@ -34,110 +37,159 @@ import {
|
|
|
34
37
|
type PaginationResult,
|
|
35
38
|
type WithoutSystemFields,
|
|
36
39
|
} from "convex/server";
|
|
37
|
-
import { v } from "convex/values";
|
|
38
|
-
import type { MessageDoc, ThreadDoc } from "../component/schema.js";
|
|
40
|
+
import { convexToJson, v, type Value } from "convex/values";
|
|
39
41
|
import type { threadFieldsSupportingPatch } from "../component/threads.js";
|
|
42
|
+
import { type VectorDimension } from "../component/vector/tables.js";
|
|
40
43
|
import {
|
|
41
|
-
|
|
42
|
-
type VectorDimension,
|
|
43
|
-
} from "../component/vector/tables.js";
|
|
44
|
-
import {
|
|
45
|
-
deserializeMessage,
|
|
44
|
+
toModelMessage,
|
|
46
45
|
serializeMessage,
|
|
47
46
|
serializeNewMessagesInStep,
|
|
48
47
|
serializeObjectResult,
|
|
49
48
|
} from "../mapping.js";
|
|
50
|
-
import {
|
|
49
|
+
import { getModelName, getProviderName } from "../shared.js";
|
|
51
50
|
import {
|
|
51
|
+
vMessageEmbeddings,
|
|
52
|
+
vMessageWithMetadata,
|
|
53
|
+
vSafeObjectArgs,
|
|
54
|
+
vTextArgs,
|
|
52
55
|
type Message,
|
|
53
|
-
type
|
|
56
|
+
type MessageDoc,
|
|
54
57
|
type MessageStatus,
|
|
55
58
|
type MessageWithMetadata,
|
|
56
59
|
type ProviderMetadata,
|
|
57
60
|
type StreamArgs,
|
|
58
|
-
type
|
|
59
|
-
vMessageWithMetadata,
|
|
60
|
-
vSafeObjectArgs,
|
|
61
|
-
vTextArgs,
|
|
61
|
+
type ThreadDoc,
|
|
62
62
|
} from "../validators.js";
|
|
63
|
-
import { createTool, wrapTools, type ToolCtx } from "./createTool.js";
|
|
64
|
-
import { listMessages } from "./listMessages.js";
|
|
65
|
-
import { fetchContextMessages } from "./search.js";
|
|
66
63
|
import {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
type
|
|
70
|
-
|
|
71
|
-
} from "./
|
|
64
|
+
listMessages,
|
|
65
|
+
saveMessages,
|
|
66
|
+
type SaveMessageArgs,
|
|
67
|
+
type SaveMessagesArgs,
|
|
68
|
+
} from "./messages.js";
|
|
69
|
+
import {
|
|
70
|
+
embedMany,
|
|
71
|
+
embedMessages,
|
|
72
|
+
fetchContextMessages,
|
|
73
|
+
generateAndSaveEmbeddings,
|
|
74
|
+
} from "./search.js";
|
|
75
|
+
import { startGeneration } from "./start.js";
|
|
76
|
+
import { syncStreams, type StreamingOptions } from "./streaming.js";
|
|
77
|
+
import { createThread, getThreadMetadata } from "./threads.js";
|
|
72
78
|
import type {
|
|
73
79
|
ActionCtx,
|
|
74
80
|
AgentComponent,
|
|
81
|
+
Config,
|
|
75
82
|
ContextOptions,
|
|
83
|
+
GenerateObjectArgs,
|
|
76
84
|
GenerationOutputMetadata,
|
|
85
|
+
MaybeCustomCtx,
|
|
86
|
+
ObjectMode,
|
|
77
87
|
Options,
|
|
78
|
-
OurObjectArgs,
|
|
79
|
-
OurStreamObjectArgs,
|
|
80
88
|
RawRequestResponseHandler,
|
|
81
|
-
|
|
82
|
-
RunMutationCtx,
|
|
83
|
-
RunQueryCtx,
|
|
89
|
+
MutationCtx,
|
|
84
90
|
StorageOptions,
|
|
85
91
|
StreamingTextArgs,
|
|
92
|
+
StreamObjectArgs,
|
|
86
93
|
SyncStreamsReturnValue,
|
|
87
94
|
TextArgs,
|
|
88
95
|
Thread,
|
|
89
96
|
UsageHandler,
|
|
90
|
-
|
|
97
|
+
QueryCtx,
|
|
98
|
+
AgentPrompt,
|
|
99
|
+
Output,
|
|
91
100
|
} from "./types.js";
|
|
92
|
-
import
|
|
101
|
+
import { streamText } from "./streamText.js";
|
|
102
|
+
import { errorToString, willContinue } from "./utils.js";
|
|
93
103
|
|
|
94
104
|
export { stepCountIs } from "ai";
|
|
95
|
-
export { vMessageDoc, vThreadDoc } from "../component/schema.js";
|
|
96
105
|
export {
|
|
106
|
+
docsToModelMessages,
|
|
107
|
+
toModelMessage,
|
|
108
|
+
//** @deprecated use toModelMessage instead */
|
|
109
|
+
toModelMessage as deserializeMessage,
|
|
110
|
+
guessMimeType,
|
|
97
111
|
serializeDataOrUrl,
|
|
98
|
-
deserializeMessage,
|
|
99
112
|
serializeMessage,
|
|
113
|
+
toUIFilePart,
|
|
100
114
|
} from "../mapping.js";
|
|
101
115
|
// NOTE: these are also exported via @convex-dev/agent/validators
|
|
102
116
|
// a future version may put them all here or move these over there
|
|
117
|
+
export { extractText, isTool, sorted } from "../shared.js";
|
|
103
118
|
export {
|
|
104
119
|
vAssistantMessage,
|
|
120
|
+
vContent,
|
|
105
121
|
vContextOptions,
|
|
106
122
|
vMessage,
|
|
123
|
+
vMessageDoc,
|
|
107
124
|
vPaginationResult,
|
|
108
125
|
vProviderMetadata,
|
|
126
|
+
vSource,
|
|
109
127
|
vStorageOptions,
|
|
110
128
|
vStreamArgs,
|
|
111
129
|
vSystemMessage,
|
|
130
|
+
vThreadDoc,
|
|
112
131
|
vToolMessage,
|
|
113
132
|
vUsage,
|
|
114
133
|
vUserMessage,
|
|
134
|
+
type Message,
|
|
135
|
+
type MessageDoc,
|
|
136
|
+
type SourcePart,
|
|
137
|
+
type ThreadDoc,
|
|
138
|
+
type Usage,
|
|
115
139
|
} from "../validators.js";
|
|
116
|
-
export type
|
|
140
|
+
export { createTool, type ToolCtx } from "./createTool.js";
|
|
141
|
+
export {
|
|
142
|
+
definePlaygroundAPI,
|
|
143
|
+
type AgentsFn,
|
|
144
|
+
type PlaygroundAPI,
|
|
145
|
+
} from "./definePlaygroundAPI.js";
|
|
117
146
|
export { getFile, storeFile } from "./files.js";
|
|
118
147
|
export {
|
|
119
|
-
|
|
148
|
+
listMessages,
|
|
149
|
+
listUIMessages,
|
|
150
|
+
saveMessage,
|
|
151
|
+
saveMessages,
|
|
152
|
+
type SaveMessageArgs,
|
|
153
|
+
type SaveMessagesArgs,
|
|
154
|
+
} from "./messages.js";
|
|
155
|
+
export { mockModel } from "./mockModel.js";
|
|
156
|
+
export {
|
|
120
157
|
fetchContextMessages,
|
|
158
|
+
filterOutOrphanedToolMessages,
|
|
159
|
+
fetchContextWithPrompt,
|
|
160
|
+
generateAndSaveEmbeddings,
|
|
161
|
+
embedMessages,
|
|
162
|
+
embedMany,
|
|
121
163
|
} from "./search.js";
|
|
122
|
-
export {
|
|
123
|
-
export { createTool, extractText, isTool, listMessages };
|
|
164
|
+
export { startGeneration } from "./start.js";
|
|
124
165
|
export {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
166
|
+
DEFAULT_STREAMING_OPTIONS,
|
|
167
|
+
DeltaStreamer,
|
|
168
|
+
abortStream,
|
|
169
|
+
compressUIMessageChunks,
|
|
170
|
+
listStreams,
|
|
171
|
+
syncStreams,
|
|
172
|
+
vStreamMessagesReturnValue,
|
|
173
|
+
} from "./streaming.js";
|
|
174
|
+
export {
|
|
175
|
+
createThread,
|
|
176
|
+
getThreadMetadata,
|
|
177
|
+
searchThreadTitles,
|
|
178
|
+
updateThreadMetadata,
|
|
179
|
+
} from "./threads.js";
|
|
180
|
+
export type { ContextHandler } from "./types.js";
|
|
181
|
+
export { toUIMessages, fromUIMessages, type UIMessage } from "../UIMessages.js";
|
|
182
|
+
|
|
129
183
|
export type {
|
|
130
184
|
AgentComponent,
|
|
185
|
+
Config,
|
|
131
186
|
ContextOptions,
|
|
132
|
-
MessageDoc,
|
|
133
187
|
ProviderMetadata,
|
|
134
188
|
RawRequestResponseHandler,
|
|
135
189
|
StorageOptions,
|
|
136
190
|
StreamArgs,
|
|
137
191
|
SyncStreamsReturnValue,
|
|
138
192
|
Thread,
|
|
139
|
-
ThreadDoc,
|
|
140
|
-
Usage,
|
|
141
193
|
UsageHandler,
|
|
142
194
|
};
|
|
143
195
|
|
|
@@ -162,36 +214,24 @@ export class Agent<
|
|
|
162
214
|
* });
|
|
163
215
|
*/
|
|
164
216
|
CustomCtx extends object = object,
|
|
165
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
166
217
|
AgentTools extends ToolSet = any,
|
|
167
218
|
> {
|
|
168
219
|
constructor(
|
|
169
220
|
public component: AgentComponent,
|
|
170
|
-
public options: {
|
|
221
|
+
public options: Config & {
|
|
171
222
|
/**
|
|
172
223
|
* The name for the agent. This will be attributed on each message
|
|
173
224
|
* created by this agent.
|
|
174
225
|
*/
|
|
175
|
-
name
|
|
226
|
+
name: string;
|
|
176
227
|
/**
|
|
177
228
|
* The LLM model to use for generating / streaming text and objects.
|
|
178
229
|
* e.g.
|
|
179
230
|
* import { openai } from "@ai-sdk/openai"
|
|
180
231
|
* const myAgent = new Agent(components.agent, {
|
|
181
|
-
*
|
|
232
|
+
* languageModel: openai.chat("gpt-4o-mini"),
|
|
182
233
|
*/
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* The model to use for text embeddings. Optional.
|
|
186
|
-
* If specified, it will use this for generating vector embeddings
|
|
187
|
-
* of chats, and can opt-in to doing vector search for automatic context
|
|
188
|
-
* on generateText, etc.
|
|
189
|
-
* e.g.
|
|
190
|
-
* import { openai } from "@ai-sdk/openai"
|
|
191
|
-
* const myAgent = new Agent(components.agent, {
|
|
192
|
-
* textEmbedding: openai.embedding("text-embedding-3-small")
|
|
193
|
-
*/
|
|
194
|
-
textEmbedding?: EmbeddingModelV2<string>;
|
|
234
|
+
languageModel: LanguageModel;
|
|
195
235
|
/**
|
|
196
236
|
* The default system prompt to put in each request.
|
|
197
237
|
* Override per-prompt by passing the "system" parameter.
|
|
@@ -204,38 +244,30 @@ export class Agent<
|
|
|
204
244
|
* (import { createTool } from "@convex-dev/agent")
|
|
205
245
|
*/
|
|
206
246
|
tools?: AgentTools;
|
|
207
|
-
/**
|
|
208
|
-
* Options to determine what messages are included as context in message
|
|
209
|
-
* generation. To disable any messages automatically being added, pass:
|
|
210
|
-
* { recentMessages: 0 }
|
|
211
|
-
*/
|
|
212
|
-
contextOptions?: ContextOptions;
|
|
213
|
-
/**
|
|
214
|
-
* Determines whether messages are automatically stored when passed as
|
|
215
|
-
* arguments or generated.
|
|
216
|
-
*/
|
|
217
|
-
storageOptions?: StorageOptions;
|
|
218
247
|
/**
|
|
219
248
|
* When generating or streaming text with tools available, this
|
|
220
|
-
* determines when to stop. Defaults to
|
|
221
|
-
*/
|
|
222
|
-
stopWhen?: StopCondition<AgentTools> | Array<StopCondition<AgentTools>>;
|
|
223
|
-
/**
|
|
224
|
-
* The maximum number of calls to make to an LLM in case it fails.
|
|
225
|
-
* This can be overridden at each generate/stream callsite.
|
|
226
|
-
*/
|
|
227
|
-
maxRetries?: number;
|
|
228
|
-
/**
|
|
229
|
-
* The usage handler to use for this agent.
|
|
249
|
+
* determines when to stop. Defaults to the AI SDK default.
|
|
230
250
|
*/
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
* log the raw request body or response headers to a table, or logs.
|
|
235
|
-
*/
|
|
236
|
-
rawRequestResponseHandler?: RawRequestResponseHandler;
|
|
251
|
+
stopWhen?:
|
|
252
|
+
| StopCondition<NoInfer<AgentTools>>
|
|
253
|
+
| Array<StopCondition<NoInfer<AgentTools>>>;
|
|
237
254
|
},
|
|
238
|
-
) {
|
|
255
|
+
) {
|
|
256
|
+
if (this.options.textEmbeddingModel && !this.options.embeddingModel) {
|
|
257
|
+
warnDeprecation(
|
|
258
|
+
"textEmbeddingModel",
|
|
259
|
+
"textEmbeddingModel is deprecated. Use embeddingModel instead.",
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Get the embedding model, prioritizing embeddingModel over textEmbeddingModel.
|
|
266
|
+
* @private
|
|
267
|
+
*/
|
|
268
|
+
private getEmbeddingModel(): EmbeddingModel | undefined {
|
|
269
|
+
return this.options.embeddingModel ?? this.options.textEmbeddingModel;
|
|
270
|
+
}
|
|
239
271
|
|
|
240
272
|
/**
|
|
241
273
|
* Start a new thread with the agent. This will have a fresh history, though if
|
|
@@ -247,8 +279,8 @@ export class Agent<
|
|
|
247
279
|
* @param args The thread metadata.
|
|
248
280
|
* @returns The threadId of the new thread and the thread object.
|
|
249
281
|
*/
|
|
250
|
-
async createThread
|
|
251
|
-
ctx:
|
|
282
|
+
async createThread(
|
|
283
|
+
ctx: ActionCtx & CustomCtx,
|
|
252
284
|
args?: {
|
|
253
285
|
/**
|
|
254
286
|
* The userId to associate with the thread. If not provided, the thread will be
|
|
@@ -263,21 +295,8 @@ export class Agent<
|
|
|
263
295
|
* The summary of the thread. Not currently used for anything.
|
|
264
296
|
*/
|
|
265
297
|
summary?: string;
|
|
266
|
-
/**
|
|
267
|
-
* The usage handler to use for this thread. Overrides any handler
|
|
268
|
-
* set in the agent constructor.
|
|
269
|
-
*/
|
|
270
|
-
usageHandler?: UsageHandler;
|
|
271
|
-
/**
|
|
272
|
-
* The tools to use for this thread.
|
|
273
|
-
* Overrides any tools passed in the agent constructor.
|
|
274
|
-
*/
|
|
275
|
-
tools?: ThreadTools;
|
|
276
298
|
},
|
|
277
|
-
): Promise<{
|
|
278
|
-
threadId: string;
|
|
279
|
-
thread: Thread<ThreadTools extends undefined ? AgentTools : ThreadTools>;
|
|
280
|
-
}>;
|
|
299
|
+
): Promise<{ threadId: string; thread: Thread<AgentTools> }>;
|
|
281
300
|
/**
|
|
282
301
|
* Start a new thread with the agent. This will have a fresh history, though if
|
|
283
302
|
* you pass in a userId you can have it search across other threads for relevant
|
|
@@ -287,8 +306,8 @@ export class Agent<
|
|
|
287
306
|
* @param args The thread metadata.
|
|
288
307
|
* @returns The threadId of the new thread.
|
|
289
308
|
*/
|
|
290
|
-
async createThread
|
|
291
|
-
ctx:
|
|
309
|
+
async createThread(
|
|
310
|
+
ctx: MutationCtx,
|
|
292
311
|
args?: {
|
|
293
312
|
/**
|
|
294
313
|
* The userId to associate with the thread. If not provided, the thread will be
|
|
@@ -303,33 +322,12 @@ export class Agent<
|
|
|
303
322
|
* The summary of the thread. Not currently used for anything.
|
|
304
323
|
*/
|
|
305
324
|
summary?: string;
|
|
306
|
-
/**
|
|
307
|
-
* The usage handler to use for this thread. Overrides any handler
|
|
308
|
-
* set in the agent constructor.
|
|
309
|
-
*/
|
|
310
|
-
usageHandler?: UsageHandler;
|
|
311
|
-
/**
|
|
312
|
-
* The tools to use for this thread.
|
|
313
|
-
* Overrides any tools passed in the agent constructor.
|
|
314
|
-
*/
|
|
315
|
-
tools?: ThreadTools;
|
|
316
325
|
},
|
|
317
|
-
): Promise<{
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
args?: {
|
|
323
|
-
userId: string | null;
|
|
324
|
-
title?: string;
|
|
325
|
-
summary?: string;
|
|
326
|
-
usageHandler?: UsageHandler;
|
|
327
|
-
tools?: ThreadTools;
|
|
328
|
-
},
|
|
329
|
-
): Promise<{
|
|
330
|
-
threadId: string;
|
|
331
|
-
thread?: Thread<ThreadTools extends undefined ? AgentTools : ThreadTools>;
|
|
332
|
-
}> {
|
|
326
|
+
): Promise<{ threadId: string }>;
|
|
327
|
+
async createThread(
|
|
328
|
+
ctx: (ActionCtx & CustomCtx) | MutationCtx,
|
|
329
|
+
args?: { userId: string | null; title?: string; summary?: string },
|
|
330
|
+
): Promise<{ threadId: string; thread?: Thread<AgentTools> }> {
|
|
333
331
|
const threadId = await createThread(ctx, this.component, args);
|
|
334
332
|
if (!("runAction" in ctx) || "workflowId" in ctx) {
|
|
335
333
|
return { threadId };
|
|
@@ -337,13 +335,8 @@ export class Agent<
|
|
|
337
335
|
const { thread } = await this.continueThread(ctx, {
|
|
338
336
|
threadId,
|
|
339
337
|
userId: args?.userId,
|
|
340
|
-
usageHandler: args?.usageHandler,
|
|
341
|
-
tools: args?.tools,
|
|
342
338
|
});
|
|
343
|
-
return {
|
|
344
|
-
threadId,
|
|
345
|
-
thread,
|
|
346
|
-
};
|
|
339
|
+
return { threadId, thread };
|
|
347
340
|
}
|
|
348
341
|
|
|
349
342
|
/**
|
|
@@ -354,7 +347,7 @@ export class Agent<
|
|
|
354
347
|
* @param { threadId, userId }: the thread and user to associate the messages with.
|
|
355
348
|
* @returns Functions bound to the userId and threadId on a `{thread}` object.
|
|
356
349
|
*/
|
|
357
|
-
async continueThread
|
|
350
|
+
async continueThread(
|
|
358
351
|
ctx: ActionCtx & CustomCtx,
|
|
359
352
|
args: {
|
|
360
353
|
/**
|
|
@@ -366,20 +359,8 @@ export class Agent<
|
|
|
366
359
|
* relevant messages from the same user as context for the LLM calls.
|
|
367
360
|
*/
|
|
368
361
|
userId?: string | null;
|
|
369
|
-
/**
|
|
370
|
-
* The usage handler to use for this thread. Overrides any handler
|
|
371
|
-
* set in the agent constructor.
|
|
372
|
-
*/
|
|
373
|
-
usageHandler?: UsageHandler;
|
|
374
|
-
/**
|
|
375
|
-
* The tools to use for this thread.
|
|
376
|
-
* Overrides any tools passed in the agent constructor.
|
|
377
|
-
*/
|
|
378
|
-
tools?: ThreadTools;
|
|
379
362
|
},
|
|
380
|
-
): Promise<{
|
|
381
|
-
thread: Thread<ThreadTools extends undefined ? AgentTools : ThreadTools>;
|
|
382
|
-
}> {
|
|
363
|
+
): Promise<{ thread: Thread<AgentTools> }> {
|
|
383
364
|
return {
|
|
384
365
|
thread: {
|
|
385
366
|
threadId: args.threadId,
|
|
@@ -395,32 +376,81 @@ export class Agent<
|
|
|
395
376
|
streamText: this.streamText.bind(this, ctx, args),
|
|
396
377
|
generateObject: this.generateObject.bind(this, ctx, args),
|
|
397
378
|
streamObject: this.streamObject.bind(this, ctx, args),
|
|
398
|
-
} as Thread<
|
|
379
|
+
} as Thread<AgentTools>,
|
|
399
380
|
};
|
|
400
381
|
}
|
|
401
382
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
*/
|
|
407
|
-
async searchThreadTitles(
|
|
408
|
-
ctx: RunQueryCtx,
|
|
409
|
-
{
|
|
410
|
-
userId,
|
|
411
|
-
query,
|
|
412
|
-
limit,
|
|
413
|
-
}: {
|
|
414
|
-
userId?: string | undefined;
|
|
415
|
-
query: string;
|
|
416
|
-
limit?: number;
|
|
383
|
+
async start<
|
|
384
|
+
TOOLS extends ToolSet | undefined,
|
|
385
|
+
T extends {
|
|
386
|
+
_internal?: { generateId?: IdGenerator };
|
|
417
387
|
},
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
388
|
+
>(
|
|
389
|
+
ctx: ActionCtx & CustomCtx,
|
|
390
|
+
/**
|
|
391
|
+
* These are the arguments you'll pass to the LLM call such as
|
|
392
|
+
* `generateText` or `streamText`. This function will look up the context
|
|
393
|
+
* and provide functions to save the steps, abort the generation, and more.
|
|
394
|
+
* The type of the arguments returned infers from the type of the arguments
|
|
395
|
+
* you pass here.
|
|
396
|
+
*/
|
|
397
|
+
args: T &
|
|
398
|
+
AgentPrompt & {
|
|
399
|
+
/**
|
|
400
|
+
* The tools to use for the tool calls. This will override tools specified
|
|
401
|
+
* in the Agent constructor or createThread / continueThread.
|
|
402
|
+
*/
|
|
403
|
+
tools?: TOOLS;
|
|
404
|
+
/**
|
|
405
|
+
* The abort signal to be passed to the LLM call. If triggered, it will
|
|
406
|
+
* mark the pending message as failed. If the generation is asynchronously
|
|
407
|
+
* aborted, it will trigger this signal when detected.
|
|
408
|
+
*/
|
|
409
|
+
abortSignal?: AbortSignal;
|
|
410
|
+
stopWhen?:
|
|
411
|
+
| StopCondition<TOOLS extends undefined ? AgentTools : TOOLS>
|
|
412
|
+
| Array<StopCondition<TOOLS extends undefined ? AgentTools : TOOLS>>;
|
|
413
|
+
},
|
|
414
|
+
options?: Options & { userId?: string | null; threadId?: string },
|
|
415
|
+
): Promise<{
|
|
416
|
+
args: T & {
|
|
417
|
+
system?: string;
|
|
418
|
+
model: LanguageModel;
|
|
419
|
+
prompt?: never;
|
|
420
|
+
messages: ModelMessage[];
|
|
421
|
+
tools?: TOOLS extends undefined ? AgentTools : TOOLS;
|
|
422
|
+
} & CallSettings;
|
|
423
|
+
order: number;
|
|
424
|
+
stepOrder: number;
|
|
425
|
+
userId: string | undefined;
|
|
426
|
+
promptMessageId: string | undefined;
|
|
427
|
+
updateModel: (model: LanguageModel | undefined) => void;
|
|
428
|
+
save: <TOOLS extends ToolSet>(
|
|
429
|
+
toSave:
|
|
430
|
+
| { step: StepResult<TOOLS> }
|
|
431
|
+
| { object: GenerateObjectResult<unknown> },
|
|
432
|
+
createPendingMessage?: boolean,
|
|
433
|
+
) => Promise<void>;
|
|
434
|
+
fail: (reason: string) => Promise<void>;
|
|
435
|
+
getSavedMessages: () => MessageDoc[];
|
|
436
|
+
}> {
|
|
437
|
+
type Tools = TOOLS extends undefined ? AgentTools : TOOLS;
|
|
438
|
+
return startGeneration<T, Tools, CustomCtx>(
|
|
439
|
+
ctx,
|
|
440
|
+
this.component,
|
|
441
|
+
{
|
|
442
|
+
...args,
|
|
443
|
+
tools: (args.tools ?? this.options.tools) as Tools,
|
|
444
|
+
system: args.system ?? this.options.instructions,
|
|
445
|
+
stopWhen: (args.stopWhen ?? this.options.stopWhen) as any,
|
|
446
|
+
},
|
|
447
|
+
{
|
|
448
|
+
...this.options,
|
|
449
|
+
...options,
|
|
450
|
+
agentName: this.options.name,
|
|
451
|
+
agentForToolCtx: this,
|
|
452
|
+
},
|
|
453
|
+
);
|
|
424
454
|
}
|
|
425
455
|
|
|
426
456
|
/**
|
|
@@ -430,110 +460,60 @@ export class Agent<
|
|
|
430
460
|
* Use {@link continueThread} to get a version of this function already scoped
|
|
431
461
|
* to a thread (and optionally userId).
|
|
432
462
|
* @param ctx The context passed from the action function calling this.
|
|
433
|
-
* @param
|
|
434
|
-
* @param
|
|
435
|
-
*
|
|
463
|
+
* @param scope: The user and thread to associate the message with
|
|
464
|
+
* @param generateTextArgs The arguments to the generateText function, along
|
|
465
|
+
* with {@link AgentPrompt} options, such as promptMessageId.
|
|
466
|
+
* @param options Extra controls for the {@link ContextOptions} and {@link StorageOptions}.
|
|
436
467
|
* @returns The result of the generateText function.
|
|
437
468
|
*/
|
|
438
469
|
async generateText<
|
|
439
470
|
TOOLS extends ToolSet | undefined = undefined,
|
|
440
|
-
OUTPUT = never,
|
|
441
|
-
OUTPUT_PARTIAL = never,
|
|
471
|
+
OUTPUT extends Output<any, any, any> = never,
|
|
442
472
|
>(
|
|
443
473
|
ctx: ActionCtx & CustomCtx,
|
|
444
|
-
{
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
threadId?: string;
|
|
452
|
-
/**
|
|
453
|
-
* The usage handler to use for this thread. Overrides any handler
|
|
454
|
-
* set in the agent constructor.
|
|
455
|
-
*/
|
|
456
|
-
usageHandler?: UsageHandler;
|
|
457
|
-
/** Note: to get better type inference, pass tools in the next arg */
|
|
458
|
-
tools?: ToolSet;
|
|
459
|
-
},
|
|
460
|
-
args: TextArgs<AgentTools, TOOLS, OUTPUT, OUTPUT_PARTIAL>,
|
|
474
|
+
threadOpts: { userId?: string | null; threadId?: string },
|
|
475
|
+
/**
|
|
476
|
+
* The arguments to the generateText function, similar to the ai sdk's
|
|
477
|
+
* {@link generateText} function, along with Agent prompt options.
|
|
478
|
+
*/
|
|
479
|
+
generateTextArgs: AgentPrompt &
|
|
480
|
+
TextArgs<AgentTools, TOOLS, OUTPUT>,
|
|
461
481
|
options?: Options,
|
|
462
482
|
): Promise<
|
|
463
483
|
GenerateTextResult<TOOLS extends undefined ? AgentTools : TOOLS, OUTPUT> &
|
|
464
484
|
GenerationOutputMetadata
|
|
465
485
|
> {
|
|
466
|
-
const
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
const { args: aiArgs, messageId, order, userId } = context;
|
|
473
|
-
const toolCtx = {
|
|
474
|
-
...(ctx as UserActionCtx & CustomCtx),
|
|
475
|
-
userId,
|
|
476
|
-
threadId,
|
|
477
|
-
messageId,
|
|
478
|
-
agent: this,
|
|
479
|
-
} satisfies ToolCtx;
|
|
486
|
+
const { args, promptMessageId, order, ...call } = await this.start(
|
|
487
|
+
ctx,
|
|
488
|
+
generateTextArgs,
|
|
489
|
+
{ ...threadOpts, ...options },
|
|
490
|
+
);
|
|
491
|
+
|
|
480
492
|
type Tools = TOOLS extends undefined ? AgentTools : TOOLS;
|
|
481
|
-
const
|
|
482
|
-
toolCtx,
|
|
483
|
-
args.tools ?? threadTools ?? this.options.tools,
|
|
484
|
-
) as Tools;
|
|
485
|
-
const saveOutput = opts.storageOptions?.saveMessages !== "none";
|
|
493
|
+
const steps: StepResult<Tools>[] = [];
|
|
486
494
|
try {
|
|
487
|
-
const result = (await generateText<Tools, OUTPUT
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
495
|
+
const result = (await generateText<Tools, OUTPUT>({
|
|
496
|
+
...args,
|
|
497
|
+
prepareStep: async (options) => {
|
|
498
|
+
const result = await generateTextArgs.prepareStep?.(options);
|
|
499
|
+
call.updateModel(result?.model ?? options.model);
|
|
500
|
+
return result;
|
|
501
|
+
},
|
|
492
502
|
onStepFinish: async (step) => {
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
threadId,
|
|
497
|
-
promptMessageId: messageId,
|
|
498
|
-
model: aiArgs.model.modelId,
|
|
499
|
-
provider: aiArgs.model.provider,
|
|
500
|
-
step,
|
|
501
|
-
});
|
|
502
|
-
}
|
|
503
|
-
if (this.options.rawRequestResponseHandler) {
|
|
504
|
-
await this.options.rawRequestResponseHandler(ctx, {
|
|
505
|
-
userId,
|
|
506
|
-
threadId,
|
|
507
|
-
agentName: this.options.name,
|
|
508
|
-
request: step.request,
|
|
509
|
-
response: step.response,
|
|
510
|
-
});
|
|
511
|
-
}
|
|
512
|
-
if (opts.usageHandler && step.usage) {
|
|
513
|
-
await opts.usageHandler(ctx, {
|
|
514
|
-
userId,
|
|
515
|
-
threadId,
|
|
516
|
-
agentName: this.options.name,
|
|
517
|
-
model: aiArgs.model.modelId,
|
|
518
|
-
provider: aiArgs.model.provider,
|
|
519
|
-
usage: step.usage,
|
|
520
|
-
providerMetadata: step.providerMetadata,
|
|
521
|
-
});
|
|
522
|
-
}
|
|
523
|
-
return args.onStepFinish?.(step);
|
|
503
|
+
steps.push(step);
|
|
504
|
+
await call.save({ step }, await willContinue(steps, args.stopWhen));
|
|
505
|
+
return generateTextArgs.onStepFinish?.(step);
|
|
524
506
|
},
|
|
525
|
-
})) as GenerateTextResult<Tools, OUTPUT
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
507
|
+
})) as GenerateTextResult<Tools, OUTPUT>;
|
|
508
|
+
const metadata: GenerationOutputMetadata = {
|
|
509
|
+
promptMessageId,
|
|
510
|
+
order,
|
|
511
|
+
savedMessages: call.getSavedMessages(),
|
|
512
|
+
messageId: promptMessageId,
|
|
513
|
+
};
|
|
514
|
+
return Object.assign(result, metadata);
|
|
529
515
|
} catch (error) {
|
|
530
|
-
|
|
531
|
-
console.error("RollbackMessage", messageId);
|
|
532
|
-
await ctx.runMutation(this.component.messages.rollbackMessage, {
|
|
533
|
-
messageId,
|
|
534
|
-
error: (error as Error).message,
|
|
535
|
-
});
|
|
536
|
-
}
|
|
516
|
+
await call.fail(errorToString(error));
|
|
537
517
|
throw error;
|
|
538
518
|
}
|
|
539
519
|
}
|
|
@@ -547,26 +527,16 @@ export class Agent<
|
|
|
547
527
|
*/
|
|
548
528
|
async streamText<
|
|
549
529
|
TOOLS extends ToolSet | undefined = undefined,
|
|
550
|
-
OUTPUT = never,
|
|
551
|
-
PARTIAL_OUTPUT = never,
|
|
530
|
+
OUTPUT extends Output<any, any, any> = never,
|
|
552
531
|
>(
|
|
553
532
|
ctx: ActionCtx & CustomCtx,
|
|
554
|
-
{
|
|
555
|
-
userId: argsUserId,
|
|
556
|
-
threadId,
|
|
557
|
-
usageHandler,
|
|
558
|
-
/** Note: to get better type inference, pass tools in the next arg */
|
|
559
|
-
tools: threadTools,
|
|
560
|
-
}: {
|
|
561
|
-
userId?: string | null;
|
|
562
|
-
threadId?: string;
|
|
563
|
-
usageHandler?: UsageHandler;
|
|
564
|
-
tools?: ToolSet;
|
|
565
|
-
},
|
|
533
|
+
threadOpts: { userId?: string | null; threadId?: string },
|
|
566
534
|
/**
|
|
567
|
-
* The arguments to the streamText function, similar to the ai
|
|
535
|
+
* The arguments to the streamText function, similar to the ai sdk's
|
|
536
|
+
* {@link streamText} function, along with Agent prompt options.
|
|
568
537
|
*/
|
|
569
|
-
|
|
538
|
+
streamTextArgs: AgentPrompt &
|
|
539
|
+
StreamingTextArgs<AgentTools, TOOLS, OUTPUT>,
|
|
570
540
|
/**
|
|
571
541
|
* The {@link ContextOptions} and {@link StorageOptions}
|
|
572
542
|
* options to use for fetching contextual messages and saving input/output messages.
|
|
@@ -587,113 +557,29 @@ export class Agent<
|
|
|
587
557
|
): Promise<
|
|
588
558
|
StreamTextResult<
|
|
589
559
|
TOOLS extends undefined ? AgentTools : TOOLS,
|
|
590
|
-
|
|
560
|
+
OUTPUT
|
|
591
561
|
> &
|
|
592
562
|
GenerationOutputMetadata
|
|
593
563
|
> {
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
threadId,
|
|
605
|
-
messageId,
|
|
606
|
-
agent: this,
|
|
607
|
-
};
|
|
608
|
-
const tools = wrapTools(
|
|
609
|
-
toolCtx,
|
|
610
|
-
args.tools ?? threadTools ?? this.options.tools,
|
|
611
|
-
) as TOOLS extends undefined ? AgentTools : TOOLS;
|
|
612
|
-
const saveOutput = opts.storageOptions?.saveMessages !== "none";
|
|
613
|
-
const streamer =
|
|
614
|
-
threadId && opts.saveStreamDeltas
|
|
615
|
-
? new DeltaStreamer(this.component, ctx, opts.saveStreamDeltas, {
|
|
616
|
-
threadId,
|
|
617
|
-
userId,
|
|
618
|
-
agentName: this.options.name,
|
|
619
|
-
model: aiArgs.model.modelId,
|
|
620
|
-
provider: aiArgs.model.provider,
|
|
621
|
-
providerOptions: aiArgs.providerOptions,
|
|
622
|
-
order,
|
|
623
|
-
stepOrder,
|
|
624
|
-
abortSignal: aiArgs.abortSignal,
|
|
625
|
-
})
|
|
626
|
-
: undefined;
|
|
627
|
-
|
|
628
|
-
const result = streamText({
|
|
629
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
630
|
-
stopWhen: this.options.stopWhen as any, // Can be overridden
|
|
631
|
-
...aiArgs,
|
|
632
|
-
tools,
|
|
633
|
-
abortSignal: streamer?.abortController.signal ?? aiArgs.abortSignal,
|
|
634
|
-
experimental_transform: mergeTransforms(
|
|
635
|
-
options?.saveStreamDeltas,
|
|
636
|
-
args.experimental_transform,
|
|
637
|
-
),
|
|
638
|
-
onChunk: async (event) => {
|
|
639
|
-
await streamer?.addParts([event.chunk]);
|
|
640
|
-
// console.log("onChunk", chunk);
|
|
641
|
-
return args.onChunk?.(event);
|
|
642
|
-
},
|
|
643
|
-
onError: async (error) => {
|
|
644
|
-
console.error("onError", error);
|
|
645
|
-
if (threadId && messageId && saveOutput) {
|
|
646
|
-
await ctx.runMutation(this.component.messages.rollbackMessage, {
|
|
647
|
-
messageId,
|
|
648
|
-
error: (error.error as Error).message,
|
|
649
|
-
});
|
|
650
|
-
}
|
|
651
|
-
// TODO: update the streamer to error state
|
|
652
|
-
return args.onError?.(error);
|
|
564
|
+
type Tools = TOOLS extends undefined ? AgentTools : TOOLS;
|
|
565
|
+
return streamText<Tools, OUTPUT>(
|
|
566
|
+
ctx,
|
|
567
|
+
this.component,
|
|
568
|
+
{
|
|
569
|
+
...streamTextArgs,
|
|
570
|
+
model: streamTextArgs.model ?? this.options.languageModel,
|
|
571
|
+
tools: (streamTextArgs.tools ?? this.options.tools) as Tools,
|
|
572
|
+
system: streamTextArgs.system ?? this.options.instructions,
|
|
573
|
+
stopWhen: (streamTextArgs.stopWhen ?? this.options.stopWhen) as any,
|
|
653
574
|
},
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
model: aiArgs.model.modelId,
|
|
661
|
-
provider: aiArgs.model.provider,
|
|
662
|
-
promptMessageId: messageId,
|
|
663
|
-
step,
|
|
664
|
-
});
|
|
665
|
-
await streamer?.finish(saved.messages);
|
|
666
|
-
}
|
|
667
|
-
if (this.options.rawRequestResponseHandler) {
|
|
668
|
-
await this.options.rawRequestResponseHandler(ctx, {
|
|
669
|
-
userId,
|
|
670
|
-
threadId,
|
|
671
|
-
agentName: this.options.name,
|
|
672
|
-
request: step.request,
|
|
673
|
-
response: step.response,
|
|
674
|
-
});
|
|
675
|
-
}
|
|
676
|
-
if (opts.usageHandler && step.usage) {
|
|
677
|
-
await opts.usageHandler(ctx, {
|
|
678
|
-
userId,
|
|
679
|
-
threadId,
|
|
680
|
-
agentName: this.options.name,
|
|
681
|
-
model: aiArgs.model.modelId,
|
|
682
|
-
provider: aiArgs.model.provider,
|
|
683
|
-
usage: step.usage,
|
|
684
|
-
providerMetadata: step.providerMetadata,
|
|
685
|
-
});
|
|
686
|
-
}
|
|
687
|
-
return args.onStepFinish?.(step);
|
|
575
|
+
{
|
|
576
|
+
...threadOpts,
|
|
577
|
+
...this.options,
|
|
578
|
+
agentName: this.options.name,
|
|
579
|
+
agentForToolCtx: this,
|
|
580
|
+
...options,
|
|
688
581
|
},
|
|
689
|
-
|
|
690
|
-
TOOLS extends undefined ? AgentTools : TOOLS,
|
|
691
|
-
PARTIAL_OUTPUT
|
|
692
|
-
> &
|
|
693
|
-
GenerationOutputMetadata;
|
|
694
|
-
result.messageId = messageId;
|
|
695
|
-
result.order = order;
|
|
696
|
-
return result;
|
|
582
|
+
);
|
|
697
583
|
}
|
|
698
584
|
|
|
699
585
|
/**
|
|
@@ -703,81 +589,47 @@ export class Agent<
|
|
|
703
589
|
* Use {@link continueThread} to get a version of this function already scoped
|
|
704
590
|
* to a thread (and optionally userId).
|
|
705
591
|
*/
|
|
706
|
-
async generateObject<
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
},
|
|
592
|
+
async generateObject<
|
|
593
|
+
SCHEMA extends FlexibleSchema<unknown> = FlexibleSchema<JSONValue>,
|
|
594
|
+
OUTPUT extends ObjectMode = InferSchema<SCHEMA> extends string
|
|
595
|
+
? "enum"
|
|
596
|
+
: "object",
|
|
597
|
+
RESULT = OUTPUT extends "array"
|
|
598
|
+
? Array<InferSchema<SCHEMA>>
|
|
599
|
+
: InferSchema<SCHEMA>,
|
|
600
|
+
>(
|
|
601
|
+
ctx: ActionCtx & CustomCtx,
|
|
602
|
+
threadOpts: { userId?: string | null; threadId?: string },
|
|
717
603
|
/**
|
|
718
|
-
* The arguments to the generateObject function, similar to the ai
|
|
604
|
+
* The arguments to the generateObject function, similar to the ai sdk's
|
|
605
|
+
* {@link generateObject} function, along with Agent prompt options.
|
|
719
606
|
*/
|
|
720
|
-
|
|
607
|
+
generateObjectArgs: AgentPrompt &
|
|
608
|
+
GenerateObjectArgs<SCHEMA, OUTPUT, RESULT>,
|
|
721
609
|
/**
|
|
722
610
|
* The {@link ContextOptions} and {@link StorageOptions}
|
|
723
611
|
* options to use for fetching contextual messages and saving input/output messages.
|
|
724
612
|
*/
|
|
725
613
|
options?: Options,
|
|
726
|
-
): Promise<GenerateObjectResult<
|
|
727
|
-
const
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
threadId,
|
|
731
|
-
...opts,
|
|
732
|
-
});
|
|
733
|
-
const { args: aiArgs, messageId, order, userId } = context;
|
|
734
|
-
const saveOutput = opts.storageOptions?.saveMessages !== "none";
|
|
614
|
+
): Promise<GenerateObjectResult<RESULT> & GenerationOutputMetadata> {
|
|
615
|
+
const { args, promptMessageId, order, fail, save, getSavedMessages } =
|
|
616
|
+
await this.start(ctx, generateObjectArgs, { ...threadOpts, ...options });
|
|
617
|
+
|
|
735
618
|
try {
|
|
736
619
|
const result = (await generateObject(
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
)) as GenerateObjectResult<T> & GenerationOutputMetadata;
|
|
620
|
+
args,
|
|
621
|
+
)) as GenerateObjectResult<RESULT>;
|
|
740
622
|
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
});
|
|
750
|
-
}
|
|
751
|
-
result.messageId = messageId;
|
|
752
|
-
result.order = order;
|
|
753
|
-
if (this.options.rawRequestResponseHandler) {
|
|
754
|
-
await this.options.rawRequestResponseHandler(ctx, {
|
|
755
|
-
userId,
|
|
756
|
-
threadId,
|
|
757
|
-
agentName: this.options.name,
|
|
758
|
-
request: result.request,
|
|
759
|
-
response: result.response,
|
|
760
|
-
});
|
|
761
|
-
}
|
|
762
|
-
if (opts.usageHandler && result.usage) {
|
|
763
|
-
await opts.usageHandler(ctx, {
|
|
764
|
-
userId,
|
|
765
|
-
threadId,
|
|
766
|
-
agentName: this.options.name,
|
|
767
|
-
model: aiArgs.model.modelId,
|
|
768
|
-
provider: aiArgs.model.provider,
|
|
769
|
-
usage: result.usage,
|
|
770
|
-
providerMetadata: result.providerMetadata,
|
|
771
|
-
});
|
|
772
|
-
}
|
|
773
|
-
return result;
|
|
623
|
+
await save({ object: result });
|
|
624
|
+
const metadata: GenerationOutputMetadata = {
|
|
625
|
+
promptMessageId,
|
|
626
|
+
order,
|
|
627
|
+
savedMessages: getSavedMessages(),
|
|
628
|
+
messageId: promptMessageId,
|
|
629
|
+
};
|
|
630
|
+
return Object.assign(result, metadata);
|
|
774
631
|
} catch (error) {
|
|
775
|
-
|
|
776
|
-
await ctx.runMutation(this.component.messages.rollbackMessage, {
|
|
777
|
-
messageId,
|
|
778
|
-
error: (error as Error).message,
|
|
779
|
-
});
|
|
780
|
-
}
|
|
632
|
+
await fail(errorToString(error));
|
|
781
633
|
throw error;
|
|
782
634
|
}
|
|
783
635
|
}
|
|
@@ -789,94 +641,67 @@ export class Agent<
|
|
|
789
641
|
* Use {@link continueThread} to get a version of this function already scoped
|
|
790
642
|
* to a thread (and optionally userId).
|
|
791
643
|
*/
|
|
792
|
-
async streamObject<
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
},
|
|
644
|
+
async streamObject<
|
|
645
|
+
SCHEMA extends FlexibleSchema<unknown> = FlexibleSchema<JSONValue>,
|
|
646
|
+
OUTPUT extends ObjectMode = InferSchema<SCHEMA> extends string
|
|
647
|
+
? "enum"
|
|
648
|
+
: "object",
|
|
649
|
+
RESULT = OUTPUT extends "array"
|
|
650
|
+
? Array<InferSchema<SCHEMA>>
|
|
651
|
+
: InferSchema<SCHEMA>,
|
|
652
|
+
>(
|
|
653
|
+
ctx: ActionCtx & CustomCtx,
|
|
654
|
+
threadOpts: { userId?: string | null; threadId?: string },
|
|
803
655
|
/**
|
|
804
|
-
* The arguments to the streamObject function, similar to the ai
|
|
656
|
+
* The arguments to the streamObject function, similar to the ai sdk's
|
|
657
|
+
* {@link streamObject} function, along with Agent prompt options.
|
|
805
658
|
*/
|
|
806
|
-
|
|
659
|
+
streamObjectArgs: AgentPrompt & StreamObjectArgs<SCHEMA, OUTPUT, RESULT>,
|
|
807
660
|
/**
|
|
808
661
|
* The {@link ContextOptions} and {@link StorageOptions}
|
|
809
662
|
* options to use for fetching contextual messages and saving input/output messages.
|
|
810
663
|
*/
|
|
811
664
|
options?: Options,
|
|
812
665
|
): Promise<
|
|
813
|
-
|
|
666
|
+
ReturnType<typeof streamObject<SCHEMA, OUTPUT, RESULT>> &
|
|
667
|
+
GenerationOutputMetadata
|
|
814
668
|
> {
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
...opts,
|
|
821
|
-
});
|
|
822
|
-
const { args: aiArgs, messageId, order, userId } = context;
|
|
823
|
-
const saveOutput = opts.storageOptions?.saveMessages !== "none";
|
|
824
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
825
|
-
const stream = streamObject<any>({
|
|
826
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
827
|
-
...(aiArgs as any),
|
|
669
|
+
const { args, promptMessageId, order, fail, save, getSavedMessages } =
|
|
670
|
+
await this.start(ctx, streamObjectArgs, { ...threadOpts, ...options });
|
|
671
|
+
|
|
672
|
+
const stream = streamObject<SCHEMA, OUTPUT, RESULT>({
|
|
673
|
+
...(args as any),
|
|
828
674
|
onError: async (error) => {
|
|
829
|
-
console.error("onError", error);
|
|
675
|
+
console.error(" streamObject onError", error);
|
|
676
|
+
// TODO: content that we have so far
|
|
677
|
+
// content: stream.fullStream.
|
|
678
|
+
await fail(errorToString(error.error));
|
|
830
679
|
return args.onError?.(error);
|
|
831
680
|
},
|
|
832
681
|
onFinish: async (result) => {
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
promptMessageId: messageId,
|
|
838
|
-
result: {
|
|
839
|
-
object: result.object,
|
|
840
|
-
finishReason: "stop",
|
|
841
|
-
usage: result.usage,
|
|
842
|
-
warnings: result.warnings,
|
|
843
|
-
request: await stream.request,
|
|
844
|
-
response: result.response,
|
|
845
|
-
providerMetadata: result.providerMetadata,
|
|
846
|
-
toJsonResponse: stream.toTextStreamResponse,
|
|
847
|
-
},
|
|
848
|
-
model: aiArgs.model.modelId,
|
|
849
|
-
provider: aiArgs.model.provider,
|
|
850
|
-
});
|
|
851
|
-
}
|
|
852
|
-
if (opts.usageHandler && result.usage) {
|
|
853
|
-
await opts.usageHandler(ctx, {
|
|
854
|
-
userId,
|
|
855
|
-
threadId,
|
|
856
|
-
agentName: this.options.name,
|
|
857
|
-
model: aiArgs.model.modelId,
|
|
858
|
-
provider: aiArgs.model.provider,
|
|
682
|
+
await save({
|
|
683
|
+
object: {
|
|
684
|
+
object: result.object,
|
|
685
|
+
finishReason: result.error ? "error" : "stop",
|
|
859
686
|
usage: result.usage,
|
|
860
|
-
|
|
861
|
-
});
|
|
862
|
-
}
|
|
863
|
-
if (this.options.rawRequestResponseHandler) {
|
|
864
|
-
await this.options.rawRequestResponseHandler(ctx, {
|
|
865
|
-
userId,
|
|
866
|
-
threadId,
|
|
867
|
-
agentName: this.options.name,
|
|
687
|
+
warnings: result.warnings,
|
|
868
688
|
request: await stream.request,
|
|
869
689
|
response: result.response,
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
690
|
+
providerMetadata: result.providerMetadata,
|
|
691
|
+
toJsonResponse: stream.toTextStreamResponse,
|
|
692
|
+
reasoning: undefined,
|
|
693
|
+
},
|
|
694
|
+
});
|
|
695
|
+
return args.onFinish?.(result);
|
|
874
696
|
},
|
|
875
|
-
})
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
697
|
+
});
|
|
698
|
+
const metadata: GenerationOutputMetadata = {
|
|
699
|
+
promptMessageId,
|
|
700
|
+
order,
|
|
701
|
+
savedMessages: getSavedMessages(),
|
|
702
|
+
messageId: promptMessageId,
|
|
703
|
+
};
|
|
704
|
+
return Object.assign(stream, metadata);
|
|
880
705
|
}
|
|
881
706
|
|
|
882
707
|
/**
|
|
@@ -887,7 +712,7 @@ export class Agent<
|
|
|
887
712
|
* @returns The messageId of the saved message.
|
|
888
713
|
*/
|
|
889
714
|
async saveMessage(
|
|
890
|
-
ctx:
|
|
715
|
+
ctx: MutationCtx | ActionCtx,
|
|
891
716
|
args: SaveMessageArgs & {
|
|
892
717
|
/**
|
|
893
718
|
* If true, it will not generate embeddings for the message.
|
|
@@ -898,14 +723,11 @@ export class Agent<
|
|
|
898
723
|
skipEmbeddings?: boolean;
|
|
899
724
|
},
|
|
900
725
|
) {
|
|
901
|
-
const {
|
|
726
|
+
const { messages } = await this.saveMessages(ctx, {
|
|
902
727
|
threadId: args.threadId,
|
|
903
728
|
userId: args.userId,
|
|
904
729
|
embeddings: args.embedding
|
|
905
|
-
? {
|
|
906
|
-
model: args.embedding.model,
|
|
907
|
-
vectors: [args.embedding.vector],
|
|
908
|
-
}
|
|
730
|
+
? { model: args.embedding.model, vectors: [args.embedding.vector] }
|
|
909
731
|
: undefined,
|
|
910
732
|
messages:
|
|
911
733
|
args.prompt !== undefined
|
|
@@ -913,8 +735,11 @@ export class Agent<
|
|
|
913
735
|
: [args.message],
|
|
914
736
|
metadata: args.metadata ? [args.metadata] : undefined,
|
|
915
737
|
skipEmbeddings: args.skipEmbeddings,
|
|
738
|
+
promptMessageId: args.promptMessageId,
|
|
739
|
+
pendingMessageId: args.pendingMessageId,
|
|
916
740
|
});
|
|
917
|
-
|
|
741
|
+
const message = messages.at(-1)!;
|
|
742
|
+
return { messageId: message._id, message };
|
|
918
743
|
}
|
|
919
744
|
|
|
920
745
|
/**
|
|
@@ -926,7 +751,7 @@ export class Agent<
|
|
|
926
751
|
* @returns
|
|
927
752
|
*/
|
|
928
753
|
async saveMessages(
|
|
929
|
-
ctx:
|
|
754
|
+
ctx: MutationCtx | ActionCtx,
|
|
930
755
|
args: SaveMessagesArgs & {
|
|
931
756
|
/**
|
|
932
757
|
* Skip generating embeddings for the messages. Useful if you're
|
|
@@ -936,20 +761,12 @@ export class Agent<
|
|
|
936
761
|
*/
|
|
937
762
|
skipEmbeddings?: boolean;
|
|
938
763
|
},
|
|
939
|
-
): Promise<{
|
|
940
|
-
|
|
941
|
-
messages: MessageDoc[];
|
|
942
|
-
}> {
|
|
943
|
-
let embeddings:
|
|
944
|
-
| {
|
|
945
|
-
vectors: (number[] | null)[];
|
|
946
|
-
model: string;
|
|
947
|
-
}
|
|
948
|
-
| undefined;
|
|
764
|
+
): Promise<{ messages: MessageDoc[] }> {
|
|
765
|
+
let embeddings: { vectors: (number[] | null)[]; model: string } | undefined;
|
|
949
766
|
const { skipEmbeddings, ...rest } = args;
|
|
950
767
|
if (args.embeddings) {
|
|
951
768
|
embeddings = args.embeddings;
|
|
952
|
-
} else if (!skipEmbeddings && this.
|
|
769
|
+
} else if (!skipEmbeddings && this.getEmbeddingModel()) {
|
|
953
770
|
if (!("runAction" in ctx)) {
|
|
954
771
|
console.warn(
|
|
955
772
|
"You're trying to save messages and generate embeddings, but you're in a mutation. " +
|
|
@@ -967,10 +784,7 @@ export class Agent<
|
|
|
967
784
|
} else {
|
|
968
785
|
embeddings = await this.generateEmbeddings(
|
|
969
786
|
ctx,
|
|
970
|
-
{
|
|
971
|
-
userId: args.userId ?? undefined,
|
|
972
|
-
threadId: args.threadId,
|
|
973
|
-
},
|
|
787
|
+
{ userId: args.userId ?? undefined, threadId: args.threadId },
|
|
974
788
|
args.messages,
|
|
975
789
|
);
|
|
976
790
|
}
|
|
@@ -993,7 +807,7 @@ export class Agent<
|
|
|
993
807
|
* @returns The MessageDoc's in a format compatible with usePaginatedQuery.
|
|
994
808
|
*/
|
|
995
809
|
async listMessages(
|
|
996
|
-
ctx:
|
|
810
|
+
ctx: QueryCtx | MutationCtx | ActionCtx,
|
|
997
811
|
args: {
|
|
998
812
|
threadId: string;
|
|
999
813
|
paginationOpts: PaginationOptions;
|
|
@@ -1013,7 +827,7 @@ export class Agent<
|
|
|
1013
827
|
* @returns The deltas for each stream from their existing cursor.
|
|
1014
828
|
*/
|
|
1015
829
|
async syncStreams(
|
|
1016
|
-
ctx:
|
|
830
|
+
ctx: QueryCtx | MutationCtx | ActionCtx,
|
|
1017
831
|
args: {
|
|
1018
832
|
threadId: string;
|
|
1019
833
|
streamArgs: StreamArgs | undefined;
|
|
@@ -1033,15 +847,26 @@ export class Agent<
|
|
|
1033
847
|
* @returns
|
|
1034
848
|
*/
|
|
1035
849
|
async fetchContextMessages(
|
|
1036
|
-
ctx:
|
|
850
|
+
ctx: QueryCtx | MutationCtx | ActionCtx,
|
|
1037
851
|
args: {
|
|
1038
852
|
userId: string | undefined;
|
|
1039
853
|
threadId: string | undefined;
|
|
1040
|
-
messages: (ModelMessage | Message)[];
|
|
1041
854
|
/**
|
|
1042
|
-
* If
|
|
1043
|
-
*
|
|
1044
|
-
|
|
855
|
+
* If targetMessageId is not provided, this text will be used
|
|
856
|
+
* for text and vector search
|
|
857
|
+
*/
|
|
858
|
+
searchText?: string;
|
|
859
|
+
/**
|
|
860
|
+
* If provided, it will use this message for text/vector search (if enabled)
|
|
861
|
+
* and will only fetch messages up to (and including) this message's "order"
|
|
862
|
+
*/
|
|
863
|
+
targetMessageId?: string;
|
|
864
|
+
/**
|
|
865
|
+
* @deprecated use searchText and targetMessageId instead
|
|
866
|
+
*/
|
|
867
|
+
messages?: (ModelMessage | Message)[];
|
|
868
|
+
/**
|
|
869
|
+
* @deprecated use targetMessageId instead
|
|
1045
870
|
*/
|
|
1046
871
|
upToAndIncludingMessageId?: string;
|
|
1047
872
|
contextOptions: ContextOptions | undefined;
|
|
@@ -1057,19 +882,22 @@ export class Agent<
|
|
|
1057
882
|
contextOptions,
|
|
1058
883
|
getEmbedding: async (text) => {
|
|
1059
884
|
assert("runAction" in ctx);
|
|
885
|
+
const embeddingModel = this.getEmbeddingModel();
|
|
1060
886
|
assert(
|
|
1061
|
-
|
|
1062
|
-
"
|
|
887
|
+
embeddingModel,
|
|
888
|
+
"An embeddingModel (or textEmbeddingModel) is required to be set on the Agent that you're doing vector search with",
|
|
1063
889
|
);
|
|
1064
890
|
return {
|
|
1065
891
|
embedding: (
|
|
1066
|
-
await
|
|
892
|
+
await embedMany(ctx, {
|
|
893
|
+
...this.options,
|
|
894
|
+
agentName: this.options.name,
|
|
1067
895
|
userId: args.userId,
|
|
1068
896
|
threadId: args.threadId,
|
|
1069
897
|
values: [text],
|
|
1070
898
|
})
|
|
1071
899
|
).embeddings[0],
|
|
1072
|
-
embeddingModel:
|
|
900
|
+
embeddingModel: embeddingModel,
|
|
1073
901
|
};
|
|
1074
902
|
},
|
|
1075
903
|
});
|
|
@@ -1082,7 +910,7 @@ export class Agent<
|
|
|
1082
910
|
* @returns The metadata for the thread.
|
|
1083
911
|
*/
|
|
1084
912
|
async getThreadMetadata(
|
|
1085
|
-
ctx:
|
|
913
|
+
ctx: QueryCtx | MutationCtx | ActionCtx,
|
|
1086
914
|
args: { threadId: string },
|
|
1087
915
|
): Promise<ThreadDoc> {
|
|
1088
916
|
return getThreadMetadata(ctx, this.component, args);
|
|
@@ -1096,7 +924,7 @@ export class Agent<
|
|
|
1096
924
|
* @returns The updated thread metadata.
|
|
1097
925
|
*/
|
|
1098
926
|
async updateThreadMetadata(
|
|
1099
|
-
ctx:
|
|
927
|
+
ctx: MutationCtx | ActionCtx,
|
|
1100
928
|
args: {
|
|
1101
929
|
threadId: string;
|
|
1102
930
|
patch: Partial<
|
|
@@ -1117,55 +945,22 @@ export class Agent<
|
|
|
1117
945
|
* @returns The embeddings for the messages.
|
|
1118
946
|
*/
|
|
1119
947
|
async generateEmbeddings(
|
|
1120
|
-
ctx:
|
|
1121
|
-
{
|
|
1122
|
-
userId,
|
|
1123
|
-
threadId,
|
|
1124
|
-
}: {
|
|
1125
|
-
userId: string | undefined;
|
|
1126
|
-
threadId: string | undefined;
|
|
1127
|
-
},
|
|
948
|
+
ctx: ActionCtx,
|
|
949
|
+
args: { userId: string | undefined; threadId: string | undefined },
|
|
1128
950
|
messages: (ModelMessage | Message)[],
|
|
1129
|
-
)
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
const textIndexes = messageTexts
|
|
1143
|
-
.map((t, i) => (t ? i : undefined))
|
|
1144
|
-
.filter((i) => i !== undefined);
|
|
1145
|
-
if (textIndexes.length === 0) {
|
|
1146
|
-
return undefined;
|
|
1147
|
-
}
|
|
1148
|
-
// Then embed those messages.
|
|
1149
|
-
const textEmbeddings = await this.doEmbed(ctx, {
|
|
1150
|
-
userId,
|
|
1151
|
-
threadId,
|
|
1152
|
-
values: messageTexts as string[],
|
|
1153
|
-
});
|
|
1154
|
-
// Then assemble the embeddings into a single array with nulls for the messages without text.
|
|
1155
|
-
const embeddingsOrNull = Array(messages.length).fill(null);
|
|
1156
|
-
textIndexes.forEach((i, j) => {
|
|
1157
|
-
embeddingsOrNull[i] = textEmbeddings.embeddings[j];
|
|
1158
|
-
});
|
|
1159
|
-
if (textEmbeddings.embeddings.length > 0) {
|
|
1160
|
-
const dimension = textEmbeddings.embeddings[0].length;
|
|
1161
|
-
validateVectorDimension(dimension);
|
|
1162
|
-
embeddings = {
|
|
1163
|
-
vectors: embeddingsOrNull,
|
|
1164
|
-
dimension,
|
|
1165
|
-
model: this.options.textEmbedding.modelId,
|
|
1166
|
-
};
|
|
1167
|
-
}
|
|
1168
|
-
return embeddings;
|
|
951
|
+
): Promise<
|
|
952
|
+
| {
|
|
953
|
+
vectors: (number[] | null)[];
|
|
954
|
+
dimension: VectorDimension;
|
|
955
|
+
model: string;
|
|
956
|
+
}
|
|
957
|
+
| undefined
|
|
958
|
+
> {
|
|
959
|
+
return embedMessages(
|
|
960
|
+
ctx,
|
|
961
|
+
{ ...args, ...this.options, agentName: this.options.name },
|
|
962
|
+
messages,
|
|
963
|
+
);
|
|
1169
964
|
}
|
|
1170
965
|
|
|
1171
966
|
/**
|
|
@@ -1176,10 +971,8 @@ export class Agent<
|
|
|
1176
971
|
* @param args The messageIds to generate embeddings for.
|
|
1177
972
|
*/
|
|
1178
973
|
async generateAndSaveEmbeddings(
|
|
1179
|
-
ctx:
|
|
1180
|
-
args: {
|
|
1181
|
-
messageIds: string[];
|
|
1182
|
-
},
|
|
974
|
+
ctx: ActionCtx,
|
|
975
|
+
args: { messageIds: string[] },
|
|
1183
976
|
) {
|
|
1184
977
|
const messages = (
|
|
1185
978
|
await ctx.runQuery(this.component.messages.getMessagesByIds, {
|
|
@@ -1194,10 +987,6 @@ export class Agent<
|
|
|
1194
987
|
.join(", "),
|
|
1195
988
|
);
|
|
1196
989
|
}
|
|
1197
|
-
await this._generateAndSaveEmbeddings(ctx, messages);
|
|
1198
|
-
}
|
|
1199
|
-
|
|
1200
|
-
async _generateAndSaveEmbeddings(ctx: RunActionCtx, messages: MessageDoc[]) {
|
|
1201
990
|
if (messages.some((m) => !m.message)) {
|
|
1202
991
|
throw new Error(
|
|
1203
992
|
"Some messages don't have a message: " +
|
|
@@ -1207,45 +996,24 @@ export class Agent<
|
|
|
1207
996
|
.join(", "),
|
|
1208
997
|
);
|
|
1209
998
|
}
|
|
1210
|
-
const
|
|
1211
|
-
if (
|
|
1212
|
-
|
|
999
|
+
const embeddingModel = this.getEmbeddingModel();
|
|
1000
|
+
if (!embeddingModel) {
|
|
1001
|
+
throw new Error(
|
|
1002
|
+
"No embeddings were generated for the messages. You must pass an embeddingModel (or textEmbeddingModel) to the agent constructor.",
|
|
1003
|
+
);
|
|
1213
1004
|
}
|
|
1214
|
-
|
|
1005
|
+
await generateAndSaveEmbeddings(
|
|
1215
1006
|
ctx,
|
|
1007
|
+
this.component,
|
|
1216
1008
|
{
|
|
1217
|
-
|
|
1218
|
-
|
|
1009
|
+
...this.options,
|
|
1010
|
+
agentName: this.options.name,
|
|
1011
|
+
threadId: messages[0].threadId,
|
|
1012
|
+
userId: messages[0].userId,
|
|
1013
|
+
embeddingModel,
|
|
1219
1014
|
},
|
|
1220
|
-
|
|
1015
|
+
messages,
|
|
1221
1016
|
);
|
|
1222
|
-
if (!embeddings) {
|
|
1223
|
-
if (!this.options.textEmbedding) {
|
|
1224
|
-
throw new Error(
|
|
1225
|
-
"No embeddings were generated for the messages. You must pass a textEmbedding model to the agent constructor.",
|
|
1226
|
-
);
|
|
1227
|
-
}
|
|
1228
|
-
throw new Error(
|
|
1229
|
-
"No embeddings were generated for these messages: " +
|
|
1230
|
-
messagesMissingEmbeddings.map((m) => m!._id).join(", "),
|
|
1231
|
-
);
|
|
1232
|
-
}
|
|
1233
|
-
await ctx.runMutation(this.component.vector.index.insertBatch, {
|
|
1234
|
-
vectorDimension: embeddings.dimension,
|
|
1235
|
-
vectors: messagesMissingEmbeddings
|
|
1236
|
-
.map((m, i) => ({
|
|
1237
|
-
messageId: m!._id,
|
|
1238
|
-
model: embeddings.model,
|
|
1239
|
-
table: "messages",
|
|
1240
|
-
userId: m.userId,
|
|
1241
|
-
threadId: m.threadId,
|
|
1242
|
-
vector: embeddings.vectors[i],
|
|
1243
|
-
}))
|
|
1244
|
-
.filter(
|
|
1245
|
-
(v): v is Extract<typeof v, { vector: number[] }> =>
|
|
1246
|
-
v.vector !== null,
|
|
1247
|
-
),
|
|
1248
|
-
});
|
|
1249
1017
|
}
|
|
1250
1018
|
|
|
1251
1019
|
/**
|
|
@@ -1277,22 +1045,22 @@ export class Agent<
|
|
|
1277
1045
|
*/
|
|
1278
1046
|
provider?: string;
|
|
1279
1047
|
},
|
|
1280
|
-
): Promise<{ messages: MessageDoc[]
|
|
1281
|
-
const messages = await serializeNewMessagesInStep(
|
|
1048
|
+
): Promise<{ messages: MessageDoc[] }> {
|
|
1049
|
+
const { messages } = await serializeNewMessagesInStep(
|
|
1282
1050
|
ctx,
|
|
1283
1051
|
this.component,
|
|
1284
1052
|
args.step,
|
|
1285
1053
|
{
|
|
1286
|
-
provider: args.provider ?? this.options.
|
|
1287
|
-
model: args.model ?? this.options.
|
|
1054
|
+
provider: args.provider ?? getProviderName(this.options.languageModel),
|
|
1055
|
+
model: args.model ?? getModelName(this.options.languageModel),
|
|
1288
1056
|
},
|
|
1289
1057
|
);
|
|
1290
1058
|
const embeddings = await this.generateEmbeddings(
|
|
1291
1059
|
ctx,
|
|
1292
1060
|
{ userId: args.userId, threadId: args.threadId },
|
|
1293
|
-
messages.map((m) =>
|
|
1061
|
+
messages.map((m) => m.message),
|
|
1294
1062
|
);
|
|
1295
|
-
|
|
1063
|
+
return ctx.runMutation(this.component.messages.addMessages, {
|
|
1296
1064
|
userId: args.userId,
|
|
1297
1065
|
threadId: args.threadId,
|
|
1298
1066
|
agentName: this.options.name,
|
|
@@ -1301,7 +1069,6 @@ export class Agent<
|
|
|
1301
1069
|
embeddings,
|
|
1302
1070
|
failPendingSteps: false,
|
|
1303
1071
|
});
|
|
1304
|
-
return saved;
|
|
1305
1072
|
}
|
|
1306
1073
|
|
|
1307
1074
|
/**
|
|
@@ -1322,23 +1089,29 @@ export class Agent<
|
|
|
1322
1089
|
result: GenerateObjectResult<unknown>;
|
|
1323
1090
|
metadata?: Omit<MessageWithMetadata, "message">;
|
|
1324
1091
|
},
|
|
1325
|
-
): Promise<
|
|
1092
|
+
): Promise<{ messages: MessageDoc[] }> {
|
|
1326
1093
|
const { messages } = await serializeObjectResult(
|
|
1327
1094
|
ctx,
|
|
1328
1095
|
this.component,
|
|
1329
1096
|
args.result,
|
|
1330
1097
|
{
|
|
1331
|
-
model:
|
|
1332
|
-
|
|
1098
|
+
model:
|
|
1099
|
+
args.model ??
|
|
1100
|
+
args.metadata?.model ??
|
|
1101
|
+
getModelName(this.options.languageModel),
|
|
1102
|
+
provider:
|
|
1103
|
+
args.provider ??
|
|
1104
|
+
args.metadata?.provider ??
|
|
1105
|
+
getProviderName(this.options.languageModel),
|
|
1333
1106
|
},
|
|
1334
1107
|
);
|
|
1335
1108
|
const embeddings = await this.generateEmbeddings(
|
|
1336
1109
|
ctx,
|
|
1337
1110
|
{ userId: args.userId, threadId: args.threadId },
|
|
1338
|
-
messages.map((m) =>
|
|
1111
|
+
messages.map((m) => m.message),
|
|
1339
1112
|
);
|
|
1340
1113
|
|
|
1341
|
-
|
|
1114
|
+
return ctx.runMutation(this.component.messages.addMessages, {
|
|
1342
1115
|
userId: args.userId,
|
|
1343
1116
|
threadId: args.threadId,
|
|
1344
1117
|
promptMessageId: args.promptMessageId,
|
|
@@ -1346,7 +1119,6 @@ export class Agent<
|
|
|
1346
1119
|
messages,
|
|
1347
1120
|
embeddings,
|
|
1348
1121
|
agentName: this.options.name,
|
|
1349
|
-
pending: false,
|
|
1350
1122
|
});
|
|
1351
1123
|
}
|
|
1352
1124
|
|
|
@@ -1358,25 +1130,17 @@ export class Agent<
|
|
|
1358
1130
|
* @param args What message to save. Generally the parent message sent into
|
|
1359
1131
|
* the generateText call.
|
|
1360
1132
|
*/
|
|
1361
|
-
async
|
|
1362
|
-
ctx:
|
|
1133
|
+
async finalizeMessage(
|
|
1134
|
+
ctx: MutationCtx | ActionCtx,
|
|
1363
1135
|
args: {
|
|
1364
|
-
threadId: string;
|
|
1365
1136
|
messageId: string;
|
|
1366
|
-
result: {
|
|
1137
|
+
result: { status: "failed"; error: string } | { status: "success" };
|
|
1367
1138
|
},
|
|
1368
1139
|
): Promise<void> {
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
});
|
|
1374
|
-
} else {
|
|
1375
|
-
await ctx.runMutation(this.component.messages.rollbackMessage, {
|
|
1376
|
-
messageId: args.messageId,
|
|
1377
|
-
error: result.error,
|
|
1378
|
-
});
|
|
1379
|
-
}
|
|
1140
|
+
await ctx.runMutation(this.component.messages.finalizeMessage, {
|
|
1141
|
+
messageId: args.messageId,
|
|
1142
|
+
result: args.result,
|
|
1143
|
+
});
|
|
1380
1144
|
}
|
|
1381
1145
|
|
|
1382
1146
|
/**
|
|
@@ -1385,13 +1149,13 @@ export class Agent<
|
|
|
1385
1149
|
* @param args The message fields to update.
|
|
1386
1150
|
*/
|
|
1387
1151
|
async updateMessage(
|
|
1388
|
-
ctx:
|
|
1152
|
+
ctx: MutationCtx | ActionCtx,
|
|
1389
1153
|
args: {
|
|
1390
1154
|
/** The id of the message to update. */
|
|
1391
1155
|
messageId: string;
|
|
1392
1156
|
patch: {
|
|
1393
1157
|
/** The message to replace the existing message. */
|
|
1394
|
-
message:
|
|
1158
|
+
message: ModelMessage | Message;
|
|
1395
1159
|
/** The status to set on the message. */
|
|
1396
1160
|
status: "success" | "error";
|
|
1397
1161
|
/** The error message to set on the message. */
|
|
@@ -1435,10 +1199,8 @@ export class Agent<
|
|
|
1435
1199
|
* @param args The ids of the messages to delete.
|
|
1436
1200
|
*/
|
|
1437
1201
|
async deleteMessages(
|
|
1438
|
-
ctx:
|
|
1439
|
-
args: {
|
|
1440
|
-
messageIds: string[];
|
|
1441
|
-
},
|
|
1202
|
+
ctx: MutationCtx | ActionCtx,
|
|
1203
|
+
args: { messageIds: string[] },
|
|
1442
1204
|
): Promise<void> {
|
|
1443
1205
|
await ctx.runMutation(this.component.messages.deleteByIds, args);
|
|
1444
1206
|
}
|
|
@@ -1450,10 +1212,8 @@ export class Agent<
|
|
|
1450
1212
|
* @param args The id of the message to delete.
|
|
1451
1213
|
*/
|
|
1452
1214
|
async deleteMessage(
|
|
1453
|
-
ctx:
|
|
1454
|
-
args: {
|
|
1455
|
-
messageId: string;
|
|
1456
|
-
},
|
|
1215
|
+
ctx: MutationCtx | ActionCtx,
|
|
1216
|
+
args: { messageId: string },
|
|
1457
1217
|
): Promise<void> {
|
|
1458
1218
|
await ctx.runMutation(this.component.messages.deleteByIds, {
|
|
1459
1219
|
messageIds: [args.messageId],
|
|
@@ -1498,7 +1258,7 @@ export class Agent<
|
|
|
1498
1258
|
* @param args The range of messages to delete.
|
|
1499
1259
|
*/
|
|
1500
1260
|
async deleteMessageRange(
|
|
1501
|
-
ctx:
|
|
1261
|
+
ctx: MutationCtx | ActionCtx,
|
|
1502
1262
|
args: {
|
|
1503
1263
|
threadId: string;
|
|
1504
1264
|
startOrder: number;
|
|
@@ -1524,11 +1284,8 @@ export class Agent<
|
|
|
1524
1284
|
* @param args The id of the thread to delete and optionally the page size to use for the delete.
|
|
1525
1285
|
*/
|
|
1526
1286
|
async deleteThreadAsync(
|
|
1527
|
-
ctx:
|
|
1528
|
-
args: {
|
|
1529
|
-
threadId: string;
|
|
1530
|
-
pageSize?: number;
|
|
1531
|
-
},
|
|
1287
|
+
ctx: MutationCtx | ActionCtx,
|
|
1288
|
+
args: { threadId: string; pageSize?: number },
|
|
1532
1289
|
): Promise<void> {
|
|
1533
1290
|
await ctx.runMutation(this.component.threads.deleteAllForThreadIdAsync, {
|
|
1534
1291
|
threadId: args.threadId,
|
|
@@ -1544,11 +1301,8 @@ export class Agent<
|
|
|
1544
1301
|
* @param args The id of the thread to delete and optionally the page size to use for the delete.
|
|
1545
1302
|
*/
|
|
1546
1303
|
async deleteThreadSync(
|
|
1547
|
-
ctx:
|
|
1548
|
-
args: {
|
|
1549
|
-
threadId: string;
|
|
1550
|
-
pageSize?: number;
|
|
1551
|
-
},
|
|
1304
|
+
ctx: ActionCtx,
|
|
1305
|
+
args: { threadId: string; pageSize?: number },
|
|
1552
1306
|
): Promise<void> {
|
|
1553
1307
|
await ctx.runAction(this.component.threads.deleteAllForThreadIdSync, {
|
|
1554
1308
|
threadId: args.threadId,
|
|
@@ -1556,278 +1310,6 @@ export class Agent<
|
|
|
1556
1310
|
});
|
|
1557
1311
|
}
|
|
1558
1312
|
|
|
1559
|
-
async _saveMessagesAndFetchContext<
|
|
1560
|
-
T extends {
|
|
1561
|
-
id?: string;
|
|
1562
|
-
prompt?: string | (ModelMessage | Message)[];
|
|
1563
|
-
messages?: (ModelMessage | Message)[];
|
|
1564
|
-
system?: string;
|
|
1565
|
-
promptMessageId?: string;
|
|
1566
|
-
model?: LanguageModelV2;
|
|
1567
|
-
maxRetries?: number;
|
|
1568
|
-
},
|
|
1569
|
-
>(
|
|
1570
|
-
ctx: RunActionCtx,
|
|
1571
|
-
args: T,
|
|
1572
|
-
{
|
|
1573
|
-
userId: argsUserId,
|
|
1574
|
-
threadId,
|
|
1575
|
-
contextOptions,
|
|
1576
|
-
storageOptions,
|
|
1577
|
-
}: {
|
|
1578
|
-
userId: string | undefined;
|
|
1579
|
-
threadId: string | undefined;
|
|
1580
|
-
} & Options,
|
|
1581
|
-
): Promise<{
|
|
1582
|
-
args: T & { model: LanguageModelV2 };
|
|
1583
|
-
userId: string | undefined;
|
|
1584
|
-
messageId: string | undefined;
|
|
1585
|
-
order: number | undefined;
|
|
1586
|
-
stepOrder: number | undefined;
|
|
1587
|
-
}> {
|
|
1588
|
-
// If only a promptMessageId is provided, this will be empty.
|
|
1589
|
-
const messages = args.messages ?? [];
|
|
1590
|
-
const prompt: (ModelMessage | Message)[] = !args.prompt
|
|
1591
|
-
? []
|
|
1592
|
-
: Array.isArray(args.prompt)
|
|
1593
|
-
? args.prompt
|
|
1594
|
-
: [{ role: "user", content: args.prompt }];
|
|
1595
|
-
const userId =
|
|
1596
|
-
argsUserId ??
|
|
1597
|
-
(threadId &&
|
|
1598
|
-
(await ctx.runQuery(this.component.threads.getThread, { threadId }))
|
|
1599
|
-
?.userId);
|
|
1600
|
-
// If only a messageId is provided, this will add that message to the end.
|
|
1601
|
-
const contextMessages = await this.fetchContextMessages(ctx, {
|
|
1602
|
-
userId,
|
|
1603
|
-
threadId,
|
|
1604
|
-
upToAndIncludingMessageId: args.promptMessageId,
|
|
1605
|
-
messages,
|
|
1606
|
-
contextOptions,
|
|
1607
|
-
});
|
|
1608
|
-
// If it was a promptMessageId, pop it off context messages
|
|
1609
|
-
// and add to the end of messages.
|
|
1610
|
-
const promptMessageIndex = args.promptMessageId
|
|
1611
|
-
? contextMessages.findIndex((m) => m._id === args.promptMessageId)
|
|
1612
|
-
: -1;
|
|
1613
|
-
const promptMessage =
|
|
1614
|
-
promptMessageIndex !== -1
|
|
1615
|
-
? contextMessages.splice(promptMessageIndex, 1)[0]
|
|
1616
|
-
: undefined;
|
|
1617
|
-
|
|
1618
|
-
let messageId = promptMessage?._id;
|
|
1619
|
-
let order = promptMessage?.order;
|
|
1620
|
-
let stepOrder = promptMessage?.stepOrder;
|
|
1621
|
-
if (
|
|
1622
|
-
threadId &&
|
|
1623
|
-
messages.length + prompt.length &&
|
|
1624
|
-
storageOptions?.saveMessages !== "none" &&
|
|
1625
|
-
// If it was a promptMessageId, we don't want to save it again.
|
|
1626
|
-
(!args.promptMessageId || storageOptions?.saveMessages === "all")
|
|
1627
|
-
) {
|
|
1628
|
-
const saveAll = storageOptions?.saveMessages === "all";
|
|
1629
|
-
const coreMessages = [...messages, ...prompt];
|
|
1630
|
-
const toSave = saveAll ? coreMessages : coreMessages.slice(-1);
|
|
1631
|
-
const metadata = Array.from({ length: toSave.length }, () => ({}));
|
|
1632
|
-
metadata[metadata.length - 1] = { id: args.id };
|
|
1633
|
-
const saved = await this.saveMessages(ctx, {
|
|
1634
|
-
threadId,
|
|
1635
|
-
userId,
|
|
1636
|
-
messages: toSave,
|
|
1637
|
-
metadata,
|
|
1638
|
-
failPendingSteps: true,
|
|
1639
|
-
});
|
|
1640
|
-
messageId = saved.lastMessageId;
|
|
1641
|
-
order = saved.messages.at(-1)?.order;
|
|
1642
|
-
stepOrder = saved.messages.at(-1)?.stepOrder;
|
|
1643
|
-
}
|
|
1644
|
-
|
|
1645
|
-
if (promptMessage?.message) {
|
|
1646
|
-
if (!args.prompt) {
|
|
1647
|
-
// If they override the prompt, we skip the existing prompt message.
|
|
1648
|
-
messages.push(deserializeMessage(promptMessage.message));
|
|
1649
|
-
}
|
|
1650
|
-
// Lazily generate embeddings for the prompt message, if it doesn't have
|
|
1651
|
-
// embeddings yet. This can happen if the message was saved in a mutation
|
|
1652
|
-
// where the LLM is not available.
|
|
1653
|
-
if (!promptMessage.embeddingId && this.options.textEmbedding) {
|
|
1654
|
-
await this._generateAndSaveEmbeddings(ctx, [promptMessage]);
|
|
1655
|
-
}
|
|
1656
|
-
}
|
|
1657
|
-
|
|
1658
|
-
const prePrompt = contextMessages.map((m) =>
|
|
1659
|
-
deserializeMessage(m.message!),
|
|
1660
|
-
);
|
|
1661
|
-
let existingResponses: ModelMessage[] = [];
|
|
1662
|
-
if (promptMessageIndex !== -1) {
|
|
1663
|
-
// pull any messages that already responded to the prompt off
|
|
1664
|
-
// and add them after the prompt
|
|
1665
|
-
existingResponses = prePrompt.splice(promptMessageIndex);
|
|
1666
|
-
}
|
|
1667
|
-
|
|
1668
|
-
let processedMessages = [
|
|
1669
|
-
...prePrompt,
|
|
1670
|
-
...messages,
|
|
1671
|
-
...prompt,
|
|
1672
|
-
...existingResponses,
|
|
1673
|
-
];
|
|
1674
|
-
if (promptMessageIndex === -1) {
|
|
1675
|
-
processedMessages.push(...prompt);
|
|
1676
|
-
} else {
|
|
1677
|
-
// We add the prompt where the prompt message was
|
|
1678
|
-
processedMessages.splice(promptMessageIndex, 0, ...prompt);
|
|
1679
|
-
}
|
|
1680
|
-
|
|
1681
|
-
// Process messages to inline localhost files (if not, file urls pointing to localhost will be sent to LLM providers)
|
|
1682
|
-
if (process.env.CONVEX_CLOUD_URL?.startsWith("http://127.0.0.1")) {
|
|
1683
|
-
processedMessages = await this._inlineMessagesFiles(processedMessages);
|
|
1684
|
-
}
|
|
1685
|
-
|
|
1686
|
-
const { prompt: _, model, ...rest } = args;
|
|
1687
|
-
return {
|
|
1688
|
-
args: {
|
|
1689
|
-
...rest,
|
|
1690
|
-
maxRetries: args.maxRetries ?? this.options.maxRetries,
|
|
1691
|
-
model: model ?? this.options.chat,
|
|
1692
|
-
system: args.system ?? this.options.instructions,
|
|
1693
|
-
messages: processedMessages,
|
|
1694
|
-
} as T & { model: LanguageModelV2 },
|
|
1695
|
-
userId,
|
|
1696
|
-
messageId,
|
|
1697
|
-
order,
|
|
1698
|
-
stepOrder,
|
|
1699
|
-
};
|
|
1700
|
-
}
|
|
1701
|
-
|
|
1702
|
-
async doEmbed(
|
|
1703
|
-
ctx: RunActionCtx,
|
|
1704
|
-
options: {
|
|
1705
|
-
userId: string | undefined;
|
|
1706
|
-
threadId: string | undefined;
|
|
1707
|
-
values: string[];
|
|
1708
|
-
abortSignal?: AbortSignal;
|
|
1709
|
-
headers?: Record<string, string>;
|
|
1710
|
-
},
|
|
1711
|
-
): Promise<{ embeddings: number[][] }> {
|
|
1712
|
-
const embeddingModel = this.options.textEmbedding;
|
|
1713
|
-
assert(
|
|
1714
|
-
embeddingModel,
|
|
1715
|
-
"a textEmbedding model is required to be set on the Agent that you're doing vector search with",
|
|
1716
|
-
);
|
|
1717
|
-
const result = await embedMany({
|
|
1718
|
-
model: embeddingModel,
|
|
1719
|
-
values: options.values,
|
|
1720
|
-
abortSignal: options.abortSignal,
|
|
1721
|
-
headers: options.headers,
|
|
1722
|
-
maxRetries: this.options.maxRetries,
|
|
1723
|
-
});
|
|
1724
|
-
if (this.options.usageHandler && result.usage) {
|
|
1725
|
-
await this.options.usageHandler(ctx, {
|
|
1726
|
-
userId: options.userId,
|
|
1727
|
-
threadId: options.threadId,
|
|
1728
|
-
agentName: this.options.name,
|
|
1729
|
-
model: embeddingModel.modelId,
|
|
1730
|
-
provider: embeddingModel.provider,
|
|
1731
|
-
providerMetadata: undefined,
|
|
1732
|
-
usage: {
|
|
1733
|
-
inputTokens: result.usage.tokens,
|
|
1734
|
-
outputTokens: 0,
|
|
1735
|
-
totalTokens: result.usage.tokens,
|
|
1736
|
-
},
|
|
1737
|
-
});
|
|
1738
|
-
}
|
|
1739
|
-
return { embeddings: result.embeddings };
|
|
1740
|
-
}
|
|
1741
|
-
|
|
1742
|
-
/**
|
|
1743
|
-
* Process messages to inline file and image URLs that point to localhost
|
|
1744
|
-
* by converting them to base64. This solves the problem of LLMs not being
|
|
1745
|
-
* able to access localhost URLs.
|
|
1746
|
-
*/
|
|
1747
|
-
private async _inlineMessagesFiles(
|
|
1748
|
-
messages: (ModelMessage | Message)[],
|
|
1749
|
-
): Promise<(ModelMessage | Message)[]> {
|
|
1750
|
-
// Process each message to convert localhost URLs to base64
|
|
1751
|
-
return Promise.all(
|
|
1752
|
-
messages.map(async (message): Promise<ModelMessage | Message> => {
|
|
1753
|
-
if (
|
|
1754
|
-
(message.role !== "user" && message.role !== "assistant") ||
|
|
1755
|
-
typeof message.content === "string" ||
|
|
1756
|
-
!Array.isArray(message.content)
|
|
1757
|
-
) {
|
|
1758
|
-
return message;
|
|
1759
|
-
}
|
|
1760
|
-
|
|
1761
|
-
const processedContent = await Promise.all(
|
|
1762
|
-
message.content.map(async (part) => {
|
|
1763
|
-
if (part.type === "image" && part.image instanceof URL) {
|
|
1764
|
-
assert(
|
|
1765
|
-
message.role === "user",
|
|
1766
|
-
"Images can only be in user messages",
|
|
1767
|
-
);
|
|
1768
|
-
if (this._isLocalhostUrl(part.image)) {
|
|
1769
|
-
const imageData = await this._downloadFile(part.image);
|
|
1770
|
-
return {
|
|
1771
|
-
...part,
|
|
1772
|
-
image: imageData,
|
|
1773
|
-
} as ImagePart;
|
|
1774
|
-
}
|
|
1775
|
-
}
|
|
1776
|
-
|
|
1777
|
-
// Handle file parts
|
|
1778
|
-
if (part.type === "file" && part.data instanceof URL) {
|
|
1779
|
-
if (this._isLocalhostUrl(part.data)) {
|
|
1780
|
-
const fileData = await this._downloadFile(part.data);
|
|
1781
|
-
return {
|
|
1782
|
-
...part,
|
|
1783
|
-
data: fileData,
|
|
1784
|
-
} as FilePart;
|
|
1785
|
-
}
|
|
1786
|
-
}
|
|
1787
|
-
|
|
1788
|
-
return part;
|
|
1789
|
-
}),
|
|
1790
|
-
);
|
|
1791
|
-
if (message.role === "user") {
|
|
1792
|
-
return {
|
|
1793
|
-
...message,
|
|
1794
|
-
content: processedContent as UserContent,
|
|
1795
|
-
};
|
|
1796
|
-
} else {
|
|
1797
|
-
return {
|
|
1798
|
-
...message,
|
|
1799
|
-
content: processedContent as AssistantContent,
|
|
1800
|
-
};
|
|
1801
|
-
}
|
|
1802
|
-
}),
|
|
1803
|
-
);
|
|
1804
|
-
}
|
|
1805
|
-
|
|
1806
|
-
/**
|
|
1807
|
-
* Check if a URL points to localhost
|
|
1808
|
-
*/
|
|
1809
|
-
private _isLocalhostUrl(url: URL): boolean {
|
|
1810
|
-
return (
|
|
1811
|
-
url.hostname === "localhost" ||
|
|
1812
|
-
url.hostname === "127.0.0.1" ||
|
|
1813
|
-
url.hostname === "::1" ||
|
|
1814
|
-
url.hostname === "0.0.0.0"
|
|
1815
|
-
);
|
|
1816
|
-
}
|
|
1817
|
-
|
|
1818
|
-
/**
|
|
1819
|
-
* Download a file from a URL
|
|
1820
|
-
*/
|
|
1821
|
-
private async _downloadFile(url: URL): Promise<ArrayBuffer> {
|
|
1822
|
-
// Fetch the file
|
|
1823
|
-
const response = await fetch(url);
|
|
1824
|
-
if (!response.ok) {
|
|
1825
|
-
throw new Error(`Failed to fetch ${url}: ${response.statusText}`);
|
|
1826
|
-
}
|
|
1827
|
-
|
|
1828
|
-
return await response.arrayBuffer();
|
|
1829
|
-
}
|
|
1830
|
-
|
|
1831
1313
|
/**
|
|
1832
1314
|
* WORKFLOW UTILITIES
|
|
1833
1315
|
*/
|
|
@@ -1871,23 +1353,7 @@ export class Agent<
|
|
|
1871
1353
|
* {@link ContextOptions}, {@link StorageOptions}, and {@link stopWhen}.
|
|
1872
1354
|
*/
|
|
1873
1355
|
asTextAction<DataModel extends GenericDataModel>(
|
|
1874
|
-
spec
|
|
1875
|
-
/**
|
|
1876
|
-
* When to stop generating text.
|
|
1877
|
-
* Defaults to the {@link Agent["options"].stopWhen} option.
|
|
1878
|
-
*/
|
|
1879
|
-
stopWhen?: StopCondition<AgentTools> | Array<StopCondition<AgentTools>>;
|
|
1880
|
-
/**
|
|
1881
|
-
* The {@link ContextOptions} to use for fetching contextual messages and
|
|
1882
|
-
* saving input/output messages.
|
|
1883
|
-
* Defaults to the {@link Agent.contextOptions} option.
|
|
1884
|
-
*/
|
|
1885
|
-
contextOptions?: ContextOptions;
|
|
1886
|
-
/**
|
|
1887
|
-
* The {@link StorageOptions} to use for saving input/output messages.
|
|
1888
|
-
* Defaults to the {@link Agent.storageOptions} option.
|
|
1889
|
-
*/
|
|
1890
|
-
storageOptions?: StorageOptions;
|
|
1356
|
+
spec: MaybeCustomCtx<CustomCtx, DataModel, AgentTools> & {
|
|
1891
1357
|
/**
|
|
1892
1358
|
* Whether to stream the text.
|
|
1893
1359
|
* If false, it will generate the text in a single call. (default)
|
|
@@ -1896,57 +1362,34 @@ export class Agent<
|
|
|
1896
1362
|
* defaults if you pass true.
|
|
1897
1363
|
*/
|
|
1898
1364
|
stream?: boolean | StreamingOptions;
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
* ```ts
|
|
1907
|
-
* const myAgent = new Agent<{ orgId: string }>(...);
|
|
1908
|
-
* const myAction = myAgent.asTextAction({
|
|
1909
|
-
* customCtx: (ctx: ActionCtx, target, llmArgs) => {
|
|
1910
|
-
* const orgId = await lookupOrgId(ctx, target.threadId);
|
|
1911
|
-
* return { orgId };
|
|
1912
|
-
* },
|
|
1913
|
-
* });
|
|
1914
|
-
* ```
|
|
1915
|
-
* Then, in your tools, you can
|
|
1916
|
-
*/
|
|
1917
|
-
customCtx: (
|
|
1918
|
-
ctx: GenericActionCtx<DataModel>,
|
|
1919
|
-
target: {
|
|
1920
|
-
userId?: string | undefined;
|
|
1921
|
-
threadId?: string | undefined;
|
|
1922
|
-
},
|
|
1923
|
-
llmArgs: TextArgs<AgentTools>,
|
|
1924
|
-
) => CustomCtx;
|
|
1925
|
-
}
|
|
1926
|
-
: { customCtx?: never }),
|
|
1365
|
+
/**
|
|
1366
|
+
* When to stop generating text.
|
|
1367
|
+
* Defaults to the {@link Agent["options"].stopWhen} option.
|
|
1368
|
+
*/
|
|
1369
|
+
stopWhen?: StopCondition<AgentTools> | Array<StopCondition<AgentTools>>;
|
|
1370
|
+
} & Options,
|
|
1371
|
+
overrides?: CallSettings,
|
|
1927
1372
|
) {
|
|
1928
|
-
const stopWhen = spec?.stopWhen ?? this.options.stopWhen;
|
|
1929
1373
|
return internalActionGeneric({
|
|
1930
1374
|
args: vTextArgs,
|
|
1931
1375
|
handler: async (ctx_, args) => {
|
|
1932
1376
|
const stream =
|
|
1933
|
-
args.stream === true ? spec?.stream || true : spec?.stream ?? false;
|
|
1934
|
-
const
|
|
1377
|
+
args.stream === true ? spec?.stream || true : (spec?.stream ?? false);
|
|
1378
|
+
const { userId, threadId, prompt, messages, maxSteps, ...rest } = args;
|
|
1379
|
+
const targetArgs = { userId, threadId };
|
|
1935
1380
|
const llmArgs = {
|
|
1936
|
-
stopWhen,
|
|
1937
|
-
...
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
: args.prompt,
|
|
1381
|
+
stopWhen: spec?.stopWhen,
|
|
1382
|
+
...overrides,
|
|
1383
|
+
...omit(rest, ["storageOptions", "contextOptions", "stream"]),
|
|
1384
|
+
messages: messages?.map(toModelMessage),
|
|
1385
|
+
prompt: Array.isArray(prompt) ? prompt.map(toModelMessage) : prompt,
|
|
1942
1386
|
toolChoice: args.toolChoice as ToolChoice<AgentTools>,
|
|
1943
1387
|
} satisfies StreamingTextArgs<AgentTools>;
|
|
1944
|
-
if (
|
|
1945
|
-
llmArgs.stopWhen = stepCountIs(
|
|
1388
|
+
if (maxSteps) {
|
|
1389
|
+
llmArgs.stopWhen = stepCountIs(maxSteps);
|
|
1946
1390
|
}
|
|
1947
1391
|
const opts = {
|
|
1948
|
-
...
|
|
1949
|
-
...(spec && pick(spec, ["contextOptions", "storageOptions"])),
|
|
1392
|
+
...pick(spec, ["contextOptions", "storageOptions"]),
|
|
1950
1393
|
...pick(args, ["contextOptions", "storageOptions"]),
|
|
1951
1394
|
saveStreamDeltas: stream,
|
|
1952
1395
|
};
|
|
@@ -1954,9 +1397,8 @@ export class Agent<
|
|
|
1954
1397
|
spec?.customCtx
|
|
1955
1398
|
? { ...ctx_, ...spec.customCtx(ctx_, targetArgs, llmArgs) }
|
|
1956
1399
|
: ctx_
|
|
1957
|
-
) as
|
|
1400
|
+
) as GenericActionCtx<GenericDataModel> & CustomCtx;
|
|
1958
1401
|
if (stream) {
|
|
1959
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1960
1402
|
const result = await this.streamText<any>(
|
|
1961
1403
|
ctx,
|
|
1962
1404
|
targetArgs,
|
|
@@ -1966,13 +1408,13 @@ export class Agent<
|
|
|
1966
1408
|
await result.consumeStream();
|
|
1967
1409
|
return {
|
|
1968
1410
|
text: await result.text,
|
|
1969
|
-
|
|
1411
|
+
promptMessageId: result.promptMessageId,
|
|
1970
1412
|
order: result.order,
|
|
1971
1413
|
finishReason: await result.finishReason,
|
|
1972
|
-
warnings: result.warnings,
|
|
1414
|
+
warnings: await result.warnings,
|
|
1415
|
+
savedMessageIds: result.savedMessages?.map((m) => m._id) ?? [],
|
|
1973
1416
|
};
|
|
1974
1417
|
} else {
|
|
1975
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1976
1418
|
const res = await this.generateText<any>(
|
|
1977
1419
|
ctx,
|
|
1978
1420
|
targetArgs,
|
|
@@ -1981,10 +1423,11 @@ export class Agent<
|
|
|
1981
1423
|
);
|
|
1982
1424
|
return {
|
|
1983
1425
|
text: res.text,
|
|
1984
|
-
|
|
1426
|
+
promptMessageId: res.promptMessageId,
|
|
1985
1427
|
order: res.order,
|
|
1986
1428
|
finishReason: res.finishReason,
|
|
1987
1429
|
warnings: res.warnings,
|
|
1430
|
+
savedMessageIds: res.savedMessages?.map((m) => m._id) ?? [],
|
|
1988
1431
|
};
|
|
1989
1432
|
}
|
|
1990
1433
|
},
|
|
@@ -1997,57 +1440,49 @@ export class Agent<
|
|
|
1997
1440
|
* the normal parameters to {@link generateObject}, plus {@link ContextOptions}
|
|
1998
1441
|
* and stopWhen.
|
|
1999
1442
|
*/
|
|
2000
|
-
asObjectAction<T>(
|
|
2001
|
-
|
|
2002
|
-
options?:
|
|
2003
|
-
contextOptions?: ContextOptions;
|
|
2004
|
-
storageOptions?: StorageOptions;
|
|
2005
|
-
},
|
|
1443
|
+
asObjectAction<T, DataModel extends GenericDataModel>(
|
|
1444
|
+
objectArgs: GenerateObjectArgs<FlexibleSchema<T>> & Partial<AgentPrompt>,
|
|
1445
|
+
options?: Options & MaybeCustomCtx<CustomCtx, DataModel, AgentTools>,
|
|
2006
1446
|
) {
|
|
2007
1447
|
return internalActionGeneric({
|
|
2008
1448
|
args: vSafeObjectArgs,
|
|
2009
|
-
handler: async (
|
|
2010
|
-
const { userId, threadId, ...rest } = args;
|
|
1449
|
+
handler: async (ctx_, args) => {
|
|
1450
|
+
const { userId, threadId, callSettings, ...rest } = args;
|
|
2011
1451
|
const overrides = pick(rest, ["contextOptions", "storageOptions"]);
|
|
2012
|
-
const
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
1452
|
+
const targetArgs = { userId, threadId };
|
|
1453
|
+
const llmArgs = {
|
|
1454
|
+
...objectArgs,
|
|
1455
|
+
...callSettings,
|
|
1456
|
+
...omit(rest, ["storageOptions", "contextOptions"]),
|
|
1457
|
+
messages: args.messages?.map(toModelMessage),
|
|
1458
|
+
prompt: Array.isArray(args.prompt)
|
|
1459
|
+
? args.prompt.map(toModelMessage)
|
|
1460
|
+
: args.prompt,
|
|
1461
|
+
} as GenerateObjectArgs<FlexibleSchema<T>>;
|
|
1462
|
+
const ctx = (
|
|
1463
|
+
options?.customCtx
|
|
1464
|
+
? { ...ctx_, ...options.customCtx(ctx_, targetArgs, llmArgs as any) }
|
|
1465
|
+
: ctx_
|
|
1466
|
+
) as GenericActionCtx<GenericDataModel> & CustomCtx;
|
|
1467
|
+
const value = await this.generateObject(ctx, targetArgs, llmArgs, {
|
|
1468
|
+
...this.options,
|
|
1469
|
+
...options,
|
|
1470
|
+
...overrides,
|
|
1471
|
+
});
|
|
2021
1472
|
return {
|
|
2022
|
-
object: value.object as T,
|
|
2023
|
-
|
|
1473
|
+
object: convexToJson(value.object as Value) as T,
|
|
1474
|
+
promptMessageId: value.promptMessageId,
|
|
2024
1475
|
order: value.order,
|
|
2025
1476
|
finishReason: value.finishReason,
|
|
2026
1477
|
warnings: value.warnings,
|
|
1478
|
+
savedMessageIds: value.savedMessages?.map((m) => m._id) ?? [],
|
|
2027
1479
|
};
|
|
2028
1480
|
},
|
|
2029
1481
|
});
|
|
2030
1482
|
}
|
|
2031
1483
|
|
|
2032
1484
|
/**
|
|
2033
|
-
*
|
|
2034
|
-
* Useful as a step in Workflows, e.g.
|
|
2035
|
-
* ```ts
|
|
2036
|
-
* const saveMessages = agent.asSaveMessagesMutation();
|
|
2037
|
-
*
|
|
2038
|
-
* const myWorkflow = workflow.define({
|
|
2039
|
-
* args: {...},
|
|
2040
|
-
* handler: async (step, args) => {
|
|
2041
|
-
* // do things to create (but not save)messages
|
|
2042
|
-
* const { messageIds } = await step.runMutation(internal.foo.saveMessages, {
|
|
2043
|
-
* threadId: args.threadId,
|
|
2044
|
-
* messages: args.messages,
|
|
2045
|
-
* });
|
|
2046
|
-
* // ...
|
|
2047
|
-
* },
|
|
2048
|
-
* })
|
|
2049
|
-
* ```
|
|
2050
|
-
* @returns A mutation that can be used to save messages to the thread.
|
|
1485
|
+
* @deprecated Use {@link saveMessages} directly instead.
|
|
2051
1486
|
*/
|
|
2052
1487
|
asSaveMessagesMutation() {
|
|
2053
1488
|
return internalMutationGeneric({
|
|
@@ -2056,226 +1491,21 @@ export class Agent<
|
|
|
2056
1491
|
userId: v.optional(v.string()),
|
|
2057
1492
|
promptMessageId: v.optional(v.string()),
|
|
2058
1493
|
messages: v.array(vMessageWithMetadata),
|
|
2059
|
-
pending: v.optional(v.boolean()),
|
|
2060
1494
|
failPendingSteps: v.optional(v.boolean()),
|
|
1495
|
+
embeddings: v.optional(vMessageEmbeddings),
|
|
2061
1496
|
},
|
|
2062
1497
|
handler: async (ctx, args) => {
|
|
2063
|
-
const {
|
|
1498
|
+
const { messages } = await this.saveMessages(ctx, {
|
|
2064
1499
|
...args,
|
|
2065
|
-
messages: args.messages.map((m) =>
|
|
1500
|
+
messages: args.messages.map((m) => toModelMessage(m.message)),
|
|
2066
1501
|
metadata: args.messages.map(({ message: _, ...m }) => m),
|
|
1502
|
+
skipEmbeddings: true,
|
|
2067
1503
|
});
|
|
2068
1504
|
return {
|
|
2069
|
-
lastMessageId,
|
|
2070
|
-
|
|
1505
|
+
lastMessageId: messages.at(-1)!._id,
|
|
1506
|
+
messages: messages.map((m) => pick(m, ["_id", "order", "stepOrder"])),
|
|
2071
1507
|
};
|
|
2072
1508
|
},
|
|
2073
1509
|
});
|
|
2074
1510
|
}
|
|
2075
1511
|
}
|
|
2076
|
-
|
|
2077
|
-
/**
|
|
2078
|
-
* Create a thread to store messages with an Agent.
|
|
2079
|
-
* @param ctx The context from a mutation or action.
|
|
2080
|
-
* @param component The Agent component, usually `components.agent`.
|
|
2081
|
-
* @param args The associated thread metadata.
|
|
2082
|
-
* @returns The id of the created thread.
|
|
2083
|
-
*/
|
|
2084
|
-
export async function createThread(
|
|
2085
|
-
ctx: RunMutationCtx,
|
|
2086
|
-
component: AgentComponent,
|
|
2087
|
-
args?: {
|
|
2088
|
-
userId?: string | null;
|
|
2089
|
-
title?: string;
|
|
2090
|
-
summary?: string;
|
|
2091
|
-
},
|
|
2092
|
-
) {
|
|
2093
|
-
const { _id: threadId } = await ctx.runMutation(
|
|
2094
|
-
component.threads.createThread,
|
|
2095
|
-
{
|
|
2096
|
-
userId: args?.userId ?? undefined,
|
|
2097
|
-
title: args?.title,
|
|
2098
|
-
summary: args?.summary,
|
|
2099
|
-
},
|
|
2100
|
-
);
|
|
2101
|
-
return threadId;
|
|
2102
|
-
}
|
|
2103
|
-
|
|
2104
|
-
/**
|
|
2105
|
-
* Get the metadata for a thread.
|
|
2106
|
-
* @param ctx A ctx object from a query, mutation, or action.
|
|
2107
|
-
* @param args.threadId The thread to get the metadata for.
|
|
2108
|
-
* @returns The metadata for the thread.
|
|
2109
|
-
*/
|
|
2110
|
-
export async function getThreadMetadata(
|
|
2111
|
-
ctx: RunQueryCtx,
|
|
2112
|
-
component: AgentComponent,
|
|
2113
|
-
args: { threadId: string },
|
|
2114
|
-
): Promise<ThreadDoc> {
|
|
2115
|
-
const thread = await ctx.runQuery(component.threads.getThread, {
|
|
2116
|
-
threadId: args.threadId,
|
|
2117
|
-
});
|
|
2118
|
-
if (!thread) {
|
|
2119
|
-
throw new Error("Thread not found");
|
|
2120
|
-
}
|
|
2121
|
-
return thread;
|
|
2122
|
-
}
|
|
2123
|
-
|
|
2124
|
-
type SaveMessagesArgs = {
|
|
2125
|
-
threadId: string;
|
|
2126
|
-
userId?: string | null;
|
|
2127
|
-
/**
|
|
2128
|
-
* The message that these messages are in response to. They will be
|
|
2129
|
-
* the same "order" as this message, at increasing stepOrder(s).
|
|
2130
|
-
*/
|
|
2131
|
-
promptMessageId?: string;
|
|
2132
|
-
/**
|
|
2133
|
-
* The messages to save.
|
|
2134
|
-
*/
|
|
2135
|
-
messages: ((ModelMessage & { id?: string | undefined }) | Message)[];
|
|
2136
|
-
/**
|
|
2137
|
-
* Metadata to save with the messages. Each element corresponds to the
|
|
2138
|
-
* message at the same index.
|
|
2139
|
-
*/
|
|
2140
|
-
metadata?: Omit<MessageWithMetadata, "message">[];
|
|
2141
|
-
/**
|
|
2142
|
-
* If false, it will "commit" the messages immediately.
|
|
2143
|
-
* If true, it will mark them as pending until the final step has finished.
|
|
2144
|
-
* Defaults to false.
|
|
2145
|
-
*/
|
|
2146
|
-
pending?: boolean;
|
|
2147
|
-
/**
|
|
2148
|
-
* If true, it will fail any pending steps.
|
|
2149
|
-
* Defaults to false.
|
|
2150
|
-
*/
|
|
2151
|
-
failPendingSteps?: boolean;
|
|
2152
|
-
/**
|
|
2153
|
-
* The embeddings to save with the messages.
|
|
2154
|
-
*/
|
|
2155
|
-
embeddings?: Omit<MessageEmbeddings, "dimension">;
|
|
2156
|
-
};
|
|
2157
|
-
|
|
2158
|
-
/**
|
|
2159
|
-
* Explicitly save messages associated with the thread (& user if provided)
|
|
2160
|
-
*/
|
|
2161
|
-
export async function saveMessages(
|
|
2162
|
-
ctx: RunMutationCtx,
|
|
2163
|
-
component: AgentComponent,
|
|
2164
|
-
args: SaveMessagesArgs & {
|
|
2165
|
-
/**
|
|
2166
|
-
* The agent name to associate with the messages.
|
|
2167
|
-
*/
|
|
2168
|
-
agentName?: string;
|
|
2169
|
-
},
|
|
2170
|
-
) {
|
|
2171
|
-
let embeddings: MessageEmbeddings | undefined;
|
|
2172
|
-
if (args.embeddings) {
|
|
2173
|
-
const dimension = args.embeddings.vectors.find((v) => v !== null)?.length;
|
|
2174
|
-
if (dimension) {
|
|
2175
|
-
validateVectorDimension(dimension);
|
|
2176
|
-
embeddings = {
|
|
2177
|
-
model: args.embeddings.model,
|
|
2178
|
-
dimension,
|
|
2179
|
-
vectors: args.embeddings.vectors,
|
|
2180
|
-
};
|
|
2181
|
-
}
|
|
2182
|
-
}
|
|
2183
|
-
const result = await ctx.runMutation(component.messages.addMessages, {
|
|
2184
|
-
threadId: args.threadId,
|
|
2185
|
-
userId: args.userId ?? undefined,
|
|
2186
|
-
agentName: args.agentName,
|
|
2187
|
-
promptMessageId: args.promptMessageId,
|
|
2188
|
-
embeddings,
|
|
2189
|
-
messages: await Promise.all(
|
|
2190
|
-
args.messages.map(async (m, i) => {
|
|
2191
|
-
const { message, fileIds } = await serializeMessage(ctx, component, m);
|
|
2192
|
-
return {
|
|
2193
|
-
...args.metadata?.[i],
|
|
2194
|
-
message,
|
|
2195
|
-
fileIds,
|
|
2196
|
-
} as MessageWithMetadata;
|
|
2197
|
-
}),
|
|
2198
|
-
),
|
|
2199
|
-
failPendingSteps: args.failPendingSteps ?? false,
|
|
2200
|
-
pending: args.pending ?? false,
|
|
2201
|
-
});
|
|
2202
|
-
return {
|
|
2203
|
-
lastMessageId: result.messages.at(-1)!._id,
|
|
2204
|
-
messages: result.messages,
|
|
2205
|
-
};
|
|
2206
|
-
}
|
|
2207
|
-
|
|
2208
|
-
type SaveMessageArgs = {
|
|
2209
|
-
threadId: string;
|
|
2210
|
-
userId?: string | null;
|
|
2211
|
-
/**
|
|
2212
|
-
* Metadata to save with the messages. Each element corresponds to the
|
|
2213
|
-
* message at the same index.
|
|
2214
|
-
*/
|
|
2215
|
-
metadata?: Omit<MessageWithMetadata, "message">;
|
|
2216
|
-
/**
|
|
2217
|
-
* The embedding to save with the message.
|
|
2218
|
-
*/
|
|
2219
|
-
embedding?: {
|
|
2220
|
-
vector: number[];
|
|
2221
|
-
model: string;
|
|
2222
|
-
};
|
|
2223
|
-
} & (
|
|
2224
|
-
| {
|
|
2225
|
-
prompt?: undefined;
|
|
2226
|
-
/**
|
|
2227
|
-
* The message to save.
|
|
2228
|
-
*/
|
|
2229
|
-
message: ModelMessage | Message;
|
|
2230
|
-
}
|
|
2231
|
-
| {
|
|
2232
|
-
/*
|
|
2233
|
-
* The prompt to save with the message.
|
|
2234
|
-
*/
|
|
2235
|
-
prompt: string;
|
|
2236
|
-
message?: undefined;
|
|
2237
|
-
}
|
|
2238
|
-
);
|
|
2239
|
-
|
|
2240
|
-
/**
|
|
2241
|
-
* Save a message to the thread.
|
|
2242
|
-
* @param ctx A ctx object from a mutation or action.
|
|
2243
|
-
* @param args The message and what to associate it with (user / thread)
|
|
2244
|
-
* You can pass extra metadata alongside the message, e.g. associated fileIds.
|
|
2245
|
-
* @returns The messageId of the saved message.
|
|
2246
|
-
*/
|
|
2247
|
-
export async function saveMessage(
|
|
2248
|
-
ctx: RunMutationCtx,
|
|
2249
|
-
component: AgentComponent,
|
|
2250
|
-
args: SaveMessageArgs & {
|
|
2251
|
-
/**
|
|
2252
|
-
* The agent name to associate with the message.
|
|
2253
|
-
*/
|
|
2254
|
-
agentName?: string;
|
|
2255
|
-
},
|
|
2256
|
-
) {
|
|
2257
|
-
let embeddings:
|
|
2258
|
-
| {
|
|
2259
|
-
vectors: number[][];
|
|
2260
|
-
model: string;
|
|
2261
|
-
}
|
|
2262
|
-
| undefined;
|
|
2263
|
-
if (args.embedding && args.embedding.vector) {
|
|
2264
|
-
embeddings = {
|
|
2265
|
-
model: args.embedding.model,
|
|
2266
|
-
vectors: [args.embedding.vector],
|
|
2267
|
-
};
|
|
2268
|
-
}
|
|
2269
|
-
const { lastMessageId, messages } = await saveMessages(ctx, component, {
|
|
2270
|
-
threadId: args.threadId,
|
|
2271
|
-
userId: args.userId ?? undefined,
|
|
2272
|
-
agentName: args.agentName,
|
|
2273
|
-
messages:
|
|
2274
|
-
args.prompt !== undefined
|
|
2275
|
-
? [{ role: "user", content: args.prompt }]
|
|
2276
|
-
: [args.message],
|
|
2277
|
-
metadata: args.metadata ? [args.metadata] : undefined,
|
|
2278
|
-
embeddings,
|
|
2279
|
-
});
|
|
2280
|
-
return { messageId: lastMessageId, message: messages.at(-1)! };
|
|
2281
|
-
}
|