@convex-dev/agent 0.1.18-alpha.1 → 0.2.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/createTool.d.ts +31 -10
- package/dist/client/createTool.d.ts.map +1 -1
- package/dist/client/createTool.js +25 -10
- 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 +174 -199
- package/dist/client/definePlaygroundAPI.d.ts.map +1 -1
- package/dist/client/definePlaygroundAPI.js +17 -35
- package/dist/client/definePlaygroundAPI.js.map +1 -1
- package/dist/client/files.d.ts +6 -3
- package/dist/client/files.d.ts.map +1 -1
- package/dist/client/files.js +7 -7
- package/dist/client/files.js.map +1 -1
- package/dist/client/index.d.ts +152 -589
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +138 -222
- package/dist/client/index.js.map +1 -1
- package/dist/client/messages.d.ts +538 -0
- package/dist/client/messages.d.ts.map +1 -0
- package/dist/client/messages.js +91 -0
- package/dist/client/messages.js.map +1 -0
- package/dist/client/search.d.ts +30 -7
- package/dist/client/search.d.ts.map +1 -1
- package/dist/client/search.js +20 -3
- package/dist/client/search.js.map +1 -1
- package/dist/client/streaming.d.ts +3 -2
- package/dist/client/streaming.d.ts.map +1 -1
- 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 +39 -42
- package/dist/client/types.d.ts.map +1 -1
- package/dist/component/_generated/api.d.ts +437 -75
- package/dist/component/messages.d.ts +254 -55
- package/dist/component/messages.d.ts.map +1 -1
- package/dist/component/messages.js +29 -25
- package/dist/component/messages.js.map +1 -1
- package/dist/component/schema.d.ts +1459 -158
- package/dist/component/schema.d.ts.map +1 -1
- package/dist/component/schema.js +8 -14
- package/dist/component/schema.js.map +1 -1
- package/dist/component/streams.d.ts +180 -6
- package/dist/component/streams.d.ts.map +1 -1
- package/dist/mapping.d.ts +11 -15
- package/dist/mapping.d.ts.map +1 -1
- package/dist/mapping.js +191 -61
- package/dist/mapping.js.map +1 -1
- package/dist/react/deltas.d.ts +0 -3
- package/dist/react/deltas.d.ts.map +1 -1
- package/dist/react/deltas.js +140 -44
- package/dist/react/deltas.js.map +1 -1
- package/dist/react/optimisticallySendMessage.d.ts.map +1 -1
- package/dist/react/optimisticallySendMessage.js +2 -1
- package/dist/react/optimisticallySendMessage.js.map +1 -1
- package/dist/react/toUIMessages.d.ts +5 -4
- package/dist/react/toUIMessages.d.ts.map +1 -1
- package/dist/react/toUIMessages.js +103 -40
- package/dist/react/toUIMessages.js.map +1 -1
- package/dist/validators.d.ts +1978 -1210
- package/dist/validators.d.ts.map +1 -1
- package/dist/validators.js +90 -54
- package/dist/validators.js.map +1 -1
- package/package.json +32 -28
- package/src/client/createTool.ts +69 -38
- package/src/client/defaultComponent.ts +17 -0
- package/src/client/definePlaygroundAPI.ts +29 -43
- package/src/client/files.ts +7 -8
- package/src/client/index.test.ts +20 -18
- package/src/client/index.ts +228 -434
- package/src/client/messages.ts +191 -0
- package/src/client/search.ts +30 -6
- package/src/client/streaming.ts +4 -3
- package/src/client/threads.ts +78 -0
- package/src/client/types.ts +50 -72
- package/src/component/_generated/api.d.ts +437 -75
- package/src/component/messages.test.ts +182 -40
- package/src/component/messages.ts +30 -32
- package/src/component/schema.ts +8 -14
- package/src/mapping.ts +230 -94
- package/src/react/deltas.ts +165 -52
- package/src/react/optimisticallySendMessage.ts +4 -1
- package/src/react/toUIMessages.test.ts +154 -36
- package/src/react/toUIMessages.ts +136 -57
- package/src/validators.test.ts +2 -101
- package/src/validators.ts +111 -68
- 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/src/client/listMessages.ts +0 -38
- package/src/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
package/dist/client/index.js
CHANGED
|
@@ -1,24 +1,28 @@
|
|
|
1
|
-
import { embedMany, generateObject, generateText, streamObject, streamText, } from "ai";
|
|
1
|
+
import { embedMany, generateObject, generateText, stepCountIs, streamObject, streamText, } from "ai";
|
|
2
2
|
import { assert, omit, pick } from "convex-helpers";
|
|
3
3
|
import { internalActionGeneric, internalMutationGeneric, } from "convex/server";
|
|
4
4
|
import { v } from "convex/values";
|
|
5
5
|
import { validateVectorDimension, } from "../component/vector/tables.js";
|
|
6
|
-
import { deserializeMessage,
|
|
6
|
+
import { deserializeMessage, serializeMessage, serializeNewMessagesInStep, serializeObjectResult, } from "../mapping.js";
|
|
7
7
|
import { extractText, isTool } from "../shared.js";
|
|
8
|
-
import { vMessageWithMetadata, vSafeObjectArgs, vTextArgs, } from "../validators.js";
|
|
8
|
+
import { vMessageEmbeddings, vMessageWithMetadata, vSafeObjectArgs, vTextArgs, } from "../validators.js";
|
|
9
9
|
import { createTool, wrapTools } from "./createTool.js";
|
|
10
|
-
import { listMessages } from "./
|
|
11
|
-
import {
|
|
10
|
+
import { listMessages, saveMessages, } from "./messages.js";
|
|
11
|
+
import { createThread, getThreadMetadata } from "./threads.js";
|
|
12
|
+
import { fetchContextMessages, getModelName, getProviderName, } from "./search.js";
|
|
12
13
|
import { DeltaStreamer, mergeTransforms, syncStreams, } from "./streaming.js";
|
|
14
|
+
export { stepCountIs } from "ai";
|
|
13
15
|
export { vMessageDoc, vThreadDoc } from "../component/schema.js";
|
|
14
|
-
export { serializeDataOrUrl } from "../mapping.js";
|
|
16
|
+
export { serializeDataOrUrl, deserializeMessage, serializeMessage, } from "../mapping.js";
|
|
15
17
|
// NOTE: these are also exported via @convex-dev/agent/validators
|
|
16
18
|
// a future version may put them all here or move these over there
|
|
17
19
|
export { vAssistantMessage, vContextOptions, vMessage, vPaginationResult, vProviderMetadata, vStorageOptions, vStreamArgs, vSystemMessage, vToolMessage, vUsage, vUserMessage, } from "../validators.js";
|
|
18
20
|
export { getFile, storeFile } from "./files.js";
|
|
19
|
-
export { filterOutOrphanedToolMessages } from "./search.js";
|
|
20
|
-
export { abortStream, listStreams } from "./streaming.js";
|
|
21
|
-
export {
|
|
21
|
+
export { filterOutOrphanedToolMessages, fetchContextMessages, } from "./search.js";
|
|
22
|
+
export { abortStream, listStreams, syncStreams } from "./streaming.js";
|
|
23
|
+
export { listMessages, saveMessage, saveMessages, } from "./messages.js";
|
|
24
|
+
export { createThread, getThreadMetadata } from "./threads.js";
|
|
25
|
+
export { createTool, extractText, isTool };
|
|
22
26
|
export { definePlaygroundAPI, } from "./definePlaygroundAPI.js";
|
|
23
27
|
export class Agent {
|
|
24
28
|
component;
|
|
@@ -38,10 +42,7 @@ export class Agent {
|
|
|
38
42
|
usageHandler: args?.usageHandler,
|
|
39
43
|
tools: args?.tools,
|
|
40
44
|
});
|
|
41
|
-
return {
|
|
42
|
-
threadId,
|
|
43
|
-
thread,
|
|
44
|
-
};
|
|
45
|
+
return { threadId, thread };
|
|
45
46
|
}
|
|
46
47
|
/**
|
|
47
48
|
* Continues a thread using this agent. Note: threads can be continued
|
|
@@ -69,18 +70,6 @@ export class Agent {
|
|
|
69
70
|
},
|
|
70
71
|
};
|
|
71
72
|
}
|
|
72
|
-
/**
|
|
73
|
-
* Search for threads by title, paginated.
|
|
74
|
-
* @param ctx The context passed from the query/mutation/action.
|
|
75
|
-
* @returns The threads matching the search, paginated.
|
|
76
|
-
*/
|
|
77
|
-
async searchThreadTitles(ctx, { userId, query, limit, }) {
|
|
78
|
-
return ctx.runQuery(this.component.threads.searchThreadTitles, {
|
|
79
|
-
userId,
|
|
80
|
-
query,
|
|
81
|
-
limit: limit ?? 10,
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
73
|
/**
|
|
85
74
|
* This behaves like {@link generateText} from the "ai" package except that
|
|
86
75
|
* it add context based on the userId and threadId and saves the input and
|
|
@@ -93,14 +82,15 @@ export class Agent {
|
|
|
93
82
|
* for the {@link ContextOptions} and {@link StorageOptions}.
|
|
94
83
|
* @returns The result of the generateText function.
|
|
95
84
|
*/
|
|
96
|
-
async generateText(ctx, { userId: argsUserId, threadId,
|
|
97
|
-
const opts = { ...this.options, ...options, usageHandler };
|
|
85
|
+
async generateText(ctx, { userId: argsUserId, threadId, tools: threadTools, ...usageHandler }, args, options) {
|
|
86
|
+
const opts = { ...this.options, ...options, ...usageHandler };
|
|
98
87
|
const context = await this._saveMessagesAndFetchContext(ctx, args, {
|
|
99
88
|
userId: argsUserId ?? undefined,
|
|
100
89
|
threadId,
|
|
101
90
|
...opts,
|
|
102
91
|
});
|
|
103
92
|
const { args: aiArgs, messageId, order, userId } = context;
|
|
93
|
+
const messages = context.savedMessages ?? [];
|
|
104
94
|
const toolCtx = {
|
|
105
95
|
...ctx,
|
|
106
96
|
userId,
|
|
@@ -113,12 +103,12 @@ export class Agent {
|
|
|
113
103
|
try {
|
|
114
104
|
const result = (await generateText({
|
|
115
105
|
// Can be overridden
|
|
116
|
-
|
|
106
|
+
stopWhen: this.options.stopWhen,
|
|
117
107
|
...aiArgs,
|
|
118
108
|
tools,
|
|
119
109
|
onStepFinish: async (step) => {
|
|
120
110
|
if (threadId && messageId && saveOutput) {
|
|
121
|
-
await this.saveStep(ctx, {
|
|
111
|
+
const saved = await this.saveStep(ctx, {
|
|
122
112
|
userId,
|
|
123
113
|
threadId,
|
|
124
114
|
promptMessageId: messageId,
|
|
@@ -126,6 +116,7 @@ export class Agent {
|
|
|
126
116
|
provider: aiArgs.model.provider,
|
|
127
117
|
step,
|
|
128
118
|
});
|
|
119
|
+
messages.push(...saved.messages);
|
|
129
120
|
}
|
|
130
121
|
if (this.options.rawRequestResponseHandler) {
|
|
131
122
|
await this.options.rawRequestResponseHandler(ctx, {
|
|
@@ -152,6 +143,7 @@ export class Agent {
|
|
|
152
143
|
}));
|
|
153
144
|
result.messageId = messageId;
|
|
154
145
|
result.order = order;
|
|
146
|
+
result.messages = messages;
|
|
155
147
|
return result;
|
|
156
148
|
}
|
|
157
149
|
catch (error) {
|
|
@@ -172,9 +164,9 @@ export class Agent {
|
|
|
172
164
|
* Use {@link continueThread} to get a version of this function already scoped
|
|
173
165
|
* to a thread (and optionally userId).
|
|
174
166
|
*/
|
|
175
|
-
async streamText(ctx, { userId: argsUserId, threadId,
|
|
167
|
+
async streamText(ctx, { userId: argsUserId, threadId,
|
|
176
168
|
/** Note: to get better type inference, pass tools in the next arg */
|
|
177
|
-
tools: threadTools, },
|
|
169
|
+
tools: threadTools, ...usageHandler },
|
|
178
170
|
/**
|
|
179
171
|
* The arguments to the streamText function, similar to the ai `streamText` function.
|
|
180
172
|
*/
|
|
@@ -184,13 +176,14 @@ export class Agent {
|
|
|
184
176
|
* options to use for fetching contextual messages and saving input/output messages.
|
|
185
177
|
*/
|
|
186
178
|
options) {
|
|
187
|
-
const opts = { ...this.options, ...options, usageHandler };
|
|
179
|
+
const opts = { ...this.options, ...options, ...usageHandler };
|
|
188
180
|
const context = await this._saveMessagesAndFetchContext(ctx, args, {
|
|
189
181
|
userId: argsUserId ?? undefined,
|
|
190
182
|
threadId,
|
|
191
183
|
...opts,
|
|
192
184
|
});
|
|
193
185
|
const { args: aiArgs, messageId, order, stepOrder, userId } = context;
|
|
186
|
+
const messages = context.savedMessages ?? [];
|
|
194
187
|
const toolCtx = {
|
|
195
188
|
...ctx,
|
|
196
189
|
userId,
|
|
@@ -214,8 +207,8 @@ export class Agent {
|
|
|
214
207
|
})
|
|
215
208
|
: undefined;
|
|
216
209
|
const result = streamText({
|
|
217
|
-
//
|
|
218
|
-
|
|
210
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
211
|
+
stopWhen: this.options.stopWhen, // Can be overridden
|
|
219
212
|
...aiArgs,
|
|
220
213
|
tools,
|
|
221
214
|
abortSignal: streamer?.abortController.signal ?? aiArgs.abortSignal,
|
|
@@ -248,6 +241,7 @@ export class Agent {
|
|
|
248
241
|
step,
|
|
249
242
|
});
|
|
250
243
|
await streamer?.finish(saved.messages);
|
|
244
|
+
messages.push(...saved.messages);
|
|
251
245
|
}
|
|
252
246
|
if (this.options.rawRequestResponseHandler) {
|
|
253
247
|
await this.options.rawRequestResponseHandler(ctx, {
|
|
@@ -274,6 +268,7 @@ export class Agent {
|
|
|
274
268
|
});
|
|
275
269
|
result.messageId = messageId;
|
|
276
270
|
result.order = order;
|
|
271
|
+
result.messages = messages;
|
|
277
272
|
return result;
|
|
278
273
|
}
|
|
279
274
|
/**
|
|
@@ -283,7 +278,7 @@ export class Agent {
|
|
|
283
278
|
* Use {@link continueThread} to get a version of this function already scoped
|
|
284
279
|
* to a thread (and optionally userId).
|
|
285
280
|
*/
|
|
286
|
-
async generateObject(ctx, { userId: argsUserId, threadId, usageHandler
|
|
281
|
+
async generateObject(ctx, { userId: argsUserId, threadId, ...usageHandler },
|
|
287
282
|
/**
|
|
288
283
|
* The arguments to the generateObject function, similar to the ai.generateObject function.
|
|
289
284
|
*/
|
|
@@ -293,20 +288,21 @@ export class Agent {
|
|
|
293
288
|
* options to use for fetching contextual messages and saving input/output messages.
|
|
294
289
|
*/
|
|
295
290
|
options) {
|
|
296
|
-
const opts = { ...this.options, ...options, usageHandler };
|
|
291
|
+
const opts = { ...this.options, ...options, ...usageHandler };
|
|
297
292
|
const context = await this._saveMessagesAndFetchContext(ctx, args, {
|
|
298
293
|
userId: argsUserId ?? undefined,
|
|
299
294
|
threadId,
|
|
300
295
|
...opts,
|
|
301
296
|
});
|
|
302
297
|
const { args: aiArgs, messageId, order, userId } = context;
|
|
298
|
+
const messages = context.savedMessages ?? [];
|
|
303
299
|
const saveOutput = opts.storageOptions?.saveMessages !== "none";
|
|
304
300
|
try {
|
|
305
301
|
const result = (await generateObject(
|
|
306
302
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
307
303
|
aiArgs));
|
|
308
304
|
if (threadId && messageId && saveOutput) {
|
|
309
|
-
await this.saveObject(ctx, {
|
|
305
|
+
const saved = await this.saveObject(ctx, {
|
|
310
306
|
threadId,
|
|
311
307
|
promptMessageId: messageId,
|
|
312
308
|
result,
|
|
@@ -314,9 +310,11 @@ export class Agent {
|
|
|
314
310
|
model: aiArgs.model.modelId,
|
|
315
311
|
provider: aiArgs.model.provider,
|
|
316
312
|
});
|
|
313
|
+
messages.push(...saved.messages);
|
|
317
314
|
}
|
|
318
315
|
result.messageId = messageId;
|
|
319
316
|
result.order = order;
|
|
317
|
+
result.messages = messages;
|
|
320
318
|
if (this.options.rawRequestResponseHandler) {
|
|
321
319
|
await this.options.rawRequestResponseHandler(ctx, {
|
|
322
320
|
userId,
|
|
@@ -356,7 +354,7 @@ export class Agent {
|
|
|
356
354
|
* Use {@link continueThread} to get a version of this function already scoped
|
|
357
355
|
* to a thread (and optionally userId).
|
|
358
356
|
*/
|
|
359
|
-
async streamObject(ctx, { userId: argsUserId, threadId, usageHandler
|
|
357
|
+
async streamObject(ctx, { userId: argsUserId, threadId, ...usageHandler },
|
|
360
358
|
/**
|
|
361
359
|
* The arguments to the streamObject function, similar to the ai `streamObject` function.
|
|
362
360
|
*/
|
|
@@ -367,14 +365,16 @@ export class Agent {
|
|
|
367
365
|
*/
|
|
368
366
|
options) {
|
|
369
367
|
// TODO: unify all this shared code between all the generate* and stream* functions
|
|
370
|
-
const opts = { ...this.options, ...options, usageHandler };
|
|
368
|
+
const opts = { ...this.options, ...options, ...usageHandler };
|
|
371
369
|
const context = await this._saveMessagesAndFetchContext(ctx, args, {
|
|
372
370
|
userId: argsUserId ?? undefined,
|
|
373
371
|
threadId,
|
|
374
372
|
...opts,
|
|
375
373
|
});
|
|
376
374
|
const { args: aiArgs, messageId, order, userId } = context;
|
|
375
|
+
const messages = context.savedMessages ?? [];
|
|
377
376
|
const saveOutput = opts.storageOptions?.saveMessages !== "none";
|
|
377
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
378
378
|
const stream = streamObject({
|
|
379
379
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
380
380
|
...aiArgs,
|
|
@@ -384,7 +384,7 @@ export class Agent {
|
|
|
384
384
|
},
|
|
385
385
|
onFinish: async (result) => {
|
|
386
386
|
if (threadId && messageId && saveOutput) {
|
|
387
|
-
await this.saveObject(ctx, {
|
|
387
|
+
const saved = await this.saveObject(ctx, {
|
|
388
388
|
userId,
|
|
389
389
|
threadId,
|
|
390
390
|
promptMessageId: messageId,
|
|
@@ -396,13 +396,12 @@ export class Agent {
|
|
|
396
396
|
request: await stream.request,
|
|
397
397
|
response: result.response,
|
|
398
398
|
providerMetadata: result.providerMetadata,
|
|
399
|
-
experimental_providerMetadata: result.experimental_providerMetadata,
|
|
400
|
-
logprobs: undefined,
|
|
401
399
|
toJsonResponse: stream.toTextStreamResponse,
|
|
402
400
|
},
|
|
403
401
|
model: aiArgs.model.modelId,
|
|
404
402
|
provider: aiArgs.model.provider,
|
|
405
403
|
});
|
|
404
|
+
messages.push(...saved.messages);
|
|
406
405
|
}
|
|
407
406
|
if (opts.usageHandler && result.usage) {
|
|
408
407
|
await opts.usageHandler(ctx, {
|
|
@@ -430,6 +429,7 @@ export class Agent {
|
|
|
430
429
|
});
|
|
431
430
|
stream.messageId = messageId;
|
|
432
431
|
stream.order = order;
|
|
432
|
+
stream.messages = messages;
|
|
433
433
|
return stream;
|
|
434
434
|
}
|
|
435
435
|
/**
|
|
@@ -440,14 +440,11 @@ export class Agent {
|
|
|
440
440
|
* @returns The messageId of the saved message.
|
|
441
441
|
*/
|
|
442
442
|
async saveMessage(ctx, args) {
|
|
443
|
-
const {
|
|
443
|
+
const { messages } = await this.saveMessages(ctx, {
|
|
444
444
|
threadId: args.threadId,
|
|
445
445
|
userId: args.userId,
|
|
446
446
|
embeddings: args.embedding
|
|
447
|
-
? {
|
|
448
|
-
model: args.embedding.model,
|
|
449
|
-
vectors: [args.embedding.vector],
|
|
450
|
-
}
|
|
447
|
+
? { model: args.embedding.model, vectors: [args.embedding.vector] }
|
|
451
448
|
: undefined,
|
|
452
449
|
messages: args.prompt !== undefined
|
|
453
450
|
? [{ role: "user", content: args.prompt }]
|
|
@@ -455,7 +452,8 @@ export class Agent {
|
|
|
455
452
|
metadata: args.metadata ? [args.metadata] : undefined,
|
|
456
453
|
skipEmbeddings: args.skipEmbeddings,
|
|
457
454
|
});
|
|
458
|
-
|
|
455
|
+
const message = messages.at(-1);
|
|
456
|
+
return { messageId: message._id, message };
|
|
459
457
|
}
|
|
460
458
|
/**
|
|
461
459
|
* Explicitly save messages associated with the thread (& user if provided)
|
|
@@ -485,10 +483,7 @@ export class Agent {
|
|
|
485
483
|
"You can explicitly generate them asynchronously by using the scheduler to run an action later that calls `agent.generateAndSaveEmbeddings`.");
|
|
486
484
|
}
|
|
487
485
|
else {
|
|
488
|
-
embeddings = await this.generateEmbeddings(ctx, {
|
|
489
|
-
userId: args.userId ?? undefined,
|
|
490
|
-
threadId: args.threadId,
|
|
491
|
-
}, args.messages);
|
|
486
|
+
embeddings = await this.generateEmbeddings(ctx, { userId: args.userId ?? undefined, threadId: args.threadId }, args.messages);
|
|
492
487
|
}
|
|
493
488
|
}
|
|
494
489
|
return saveMessages(ctx, this.component, {
|
|
@@ -547,7 +542,7 @@ export class Agent {
|
|
|
547
542
|
threadId: args.threadId,
|
|
548
543
|
values: [text],
|
|
549
544
|
})).embeddings[0],
|
|
550
|
-
embeddingModel: this.options.textEmbedding
|
|
545
|
+
embeddingModel: this.options.textEmbedding,
|
|
551
546
|
};
|
|
552
547
|
},
|
|
553
548
|
});
|
|
@@ -596,7 +591,6 @@ export class Agent {
|
|
|
596
591
|
threadId,
|
|
597
592
|
values: messageTexts,
|
|
598
593
|
});
|
|
599
|
-
// TODO: record usage of embeddings
|
|
600
594
|
// Then assemble the embeddings into a single array with nulls for the messages without text.
|
|
601
595
|
const embeddingsOrNull = Array(messages.length).fill(null);
|
|
602
596
|
textIndexes.forEach((i, j) => {
|
|
@@ -605,11 +599,8 @@ export class Agent {
|
|
|
605
599
|
if (textEmbeddings.embeddings.length > 0) {
|
|
606
600
|
const dimension = textEmbeddings.embeddings[0].length;
|
|
607
601
|
validateVectorDimension(dimension);
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
dimension,
|
|
611
|
-
model: this.options.textEmbedding.modelId,
|
|
612
|
-
};
|
|
602
|
+
const model = getModelName(this.options.textEmbedding);
|
|
603
|
+
embeddings = { vectors: embeddingsOrNull, dimension, model };
|
|
613
604
|
}
|
|
614
605
|
return embeddings;
|
|
615
606
|
}
|
|
@@ -647,7 +638,7 @@ export class Agent {
|
|
|
647
638
|
const embeddings = await this.generateEmbeddings(ctx, {
|
|
648
639
|
userId: messagesMissingEmbeddings[0].userId,
|
|
649
640
|
threadId: messagesMissingEmbeddings[0].threadId,
|
|
650
|
-
}, messagesMissingEmbeddings.map((m) => m.message));
|
|
641
|
+
}, messagesMissingEmbeddings.map((m) => deserializeMessage(m.message)));
|
|
651
642
|
if (!embeddings) {
|
|
652
643
|
if (!this.options.textEmbedding) {
|
|
653
644
|
throw new Error("No embeddings were generated for the messages. You must pass a textEmbedding model to the agent constructor.");
|
|
@@ -676,11 +667,11 @@ export class Agent {
|
|
|
676
667
|
*/
|
|
677
668
|
async saveStep(ctx, args) {
|
|
678
669
|
const messages = await serializeNewMessagesInStep(ctx, this.component, args.step, {
|
|
679
|
-
provider: args.provider ?? this.options.chat
|
|
680
|
-
model: args.model ?? this.options.chat
|
|
670
|
+
provider: args.provider ?? getProviderName(this.options.chat),
|
|
671
|
+
model: args.model ?? getModelName(this.options.chat),
|
|
681
672
|
});
|
|
682
673
|
const embeddings = await this.generateEmbeddings(ctx, { userId: args.userId, threadId: args.threadId }, messages.map((m) => m.message));
|
|
683
|
-
|
|
674
|
+
return ctx.runMutation(this.component.messages.addMessages, {
|
|
684
675
|
userId: args.userId,
|
|
685
676
|
threadId: args.threadId,
|
|
686
677
|
agentName: this.options.name,
|
|
@@ -689,7 +680,6 @@ export class Agent {
|
|
|
689
680
|
embeddings,
|
|
690
681
|
failPendingSteps: false,
|
|
691
682
|
});
|
|
692
|
-
return saved;
|
|
693
683
|
}
|
|
694
684
|
/**
|
|
695
685
|
* Manually save the result of a generateObject call to the thread.
|
|
@@ -700,11 +690,11 @@ export class Agent {
|
|
|
700
690
|
*/
|
|
701
691
|
async saveObject(ctx, args) {
|
|
702
692
|
const { messages } = await serializeObjectResult(ctx, this.component, args.result, {
|
|
703
|
-
model: args.model ?? this.options.chat
|
|
704
|
-
provider: args.provider ?? this.options.chat
|
|
693
|
+
model: args.model ?? getModelName(this.options.chat),
|
|
694
|
+
provider: args.provider ?? getProviderName(this.options.chat),
|
|
705
695
|
});
|
|
706
|
-
const embeddings = await this.generateEmbeddings(ctx, { userId: args.userId, threadId: args.threadId }, messages.map((m) => m.message));
|
|
707
|
-
|
|
696
|
+
const embeddings = await this.generateEmbeddings(ctx, { userId: args.userId, threadId: args.threadId }, messages.map((m) => deserializeMessage(m.message)));
|
|
697
|
+
return ctx.runMutation(this.component.messages.addMessages, {
|
|
708
698
|
userId: args.userId,
|
|
709
699
|
threadId: args.threadId,
|
|
710
700
|
promptMessageId: args.promptMessageId,
|
|
@@ -712,7 +702,6 @@ export class Agent {
|
|
|
712
702
|
messages,
|
|
713
703
|
embeddings,
|
|
714
704
|
agentName: this.options.name,
|
|
715
|
-
pending: false,
|
|
716
705
|
});
|
|
717
706
|
}
|
|
718
707
|
/**
|
|
@@ -814,7 +803,7 @@ export class Agent {
|
|
|
814
803
|
* @param args The range of messages to delete.
|
|
815
804
|
*/
|
|
816
805
|
async deleteMessageRange(ctx, args) {
|
|
817
|
-
|
|
806
|
+
return ctx.runMutation(this.component.messages.deleteByOrder, {
|
|
818
807
|
threadId: args.threadId,
|
|
819
808
|
startOrder: args.startOrder,
|
|
820
809
|
startStepOrder: args.startStepOrder,
|
|
@@ -850,7 +839,12 @@ export class Agent {
|
|
|
850
839
|
}
|
|
851
840
|
async _saveMessagesAndFetchContext(ctx, args, { userId: argsUserId, threadId, contextOptions, storageOptions, }) {
|
|
852
841
|
// If only a promptMessageId is provided, this will be empty.
|
|
853
|
-
const messages =
|
|
842
|
+
const messages = args.messages ?? [];
|
|
843
|
+
const prompt = !args.prompt
|
|
844
|
+
? []
|
|
845
|
+
: Array.isArray(args.prompt)
|
|
846
|
+
? args.prompt
|
|
847
|
+
: [{ role: "user", content: args.prompt }];
|
|
854
848
|
const userId = argsUserId ??
|
|
855
849
|
(threadId &&
|
|
856
850
|
(await ctx.runQuery(this.component.threads.getThread, { threadId }))
|
|
@@ -865,40 +859,42 @@ export class Agent {
|
|
|
865
859
|
});
|
|
866
860
|
// If it was a promptMessageId, pop it off context messages
|
|
867
861
|
// and add to the end of messages.
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
862
|
+
const promptMessageIndex = args.promptMessageId
|
|
863
|
+
? contextMessages.findIndex((m) => m._id === args.promptMessageId)
|
|
864
|
+
: -1;
|
|
865
|
+
const promptMessage = promptMessageIndex !== -1
|
|
866
|
+
? contextMessages.splice(promptMessageIndex, 1)[0]
|
|
872
867
|
: undefined;
|
|
873
|
-
if (promptMessage && args.prompt) {
|
|
874
|
-
// If they specify both a promptMessageId and a prompt, we prefer
|
|
875
|
-
// the prompt to stand in for the promptMessageId message.
|
|
876
|
-
promptMessage.message = { role: "user", content: args.prompt };
|
|
877
|
-
}
|
|
878
868
|
let messageId = promptMessage?._id;
|
|
879
869
|
let order = promptMessage?.order;
|
|
880
870
|
let stepOrder = promptMessage?.stepOrder;
|
|
871
|
+
let savedMessages = undefined;
|
|
881
872
|
if (threadId &&
|
|
882
|
-
messages.length &&
|
|
873
|
+
messages.length + prompt.length &&
|
|
883
874
|
storageOptions?.saveMessages !== "none" &&
|
|
884
875
|
// If it was a promptMessageId, we don't want to save it again.
|
|
885
876
|
(!args.promptMessageId || storageOptions?.saveMessages === "all")) {
|
|
886
877
|
const saveAll = storageOptions?.saveMessages === "all";
|
|
887
|
-
const coreMessages =
|
|
878
|
+
const coreMessages = [...messages, ...prompt];
|
|
879
|
+
const toSave = saveAll ? coreMessages : coreMessages.slice(-1);
|
|
880
|
+
const metadata = Array.from({ length: toSave.length }, () => ({}));
|
|
888
881
|
const saved = await this.saveMessages(ctx, {
|
|
889
882
|
threadId,
|
|
890
883
|
userId,
|
|
891
|
-
messages:
|
|
892
|
-
metadata
|
|
884
|
+
messages: toSave,
|
|
885
|
+
metadata,
|
|
893
886
|
failPendingSteps: true,
|
|
894
887
|
});
|
|
895
|
-
messageId = saved.
|
|
896
|
-
order = saved.messages.at(-1)
|
|
897
|
-
stepOrder = saved.messages.at(-1)
|
|
888
|
+
messageId = saved.messages.at(-1)._id;
|
|
889
|
+
order = saved.messages.at(-1).order;
|
|
890
|
+
stepOrder = saved.messages.at(-1).stepOrder;
|
|
891
|
+
savedMessages = saved.messages;
|
|
898
892
|
}
|
|
899
893
|
if (promptMessage?.message) {
|
|
900
|
-
|
|
901
|
-
|
|
894
|
+
if (!args.prompt) {
|
|
895
|
+
// If they override the prompt, we skip the existing prompt message.
|
|
896
|
+
messages.push(deserializeMessage(promptMessage.message));
|
|
897
|
+
}
|
|
902
898
|
// Lazily generate embeddings for the prompt message, if it doesn't have
|
|
903
899
|
// embeddings yet. This can happen if the message was saved in a mutation
|
|
904
900
|
// where the LLM is not available.
|
|
@@ -906,10 +902,26 @@ export class Agent {
|
|
|
906
902
|
await this._generateAndSaveEmbeddings(ctx, [promptMessage]);
|
|
907
903
|
}
|
|
908
904
|
}
|
|
905
|
+
const prePrompt = contextMessages.map((m) => deserializeMessage(m.message));
|
|
906
|
+
let existingResponses = [];
|
|
907
|
+
if (promptMessageIndex !== -1) {
|
|
908
|
+
// pull any messages that already responded to the prompt off
|
|
909
|
+
// and add them after the prompt
|
|
910
|
+
existingResponses = prePrompt.splice(promptMessageIndex);
|
|
911
|
+
}
|
|
909
912
|
let processedMessages = [
|
|
910
|
-
...
|
|
913
|
+
...prePrompt,
|
|
911
914
|
...messages,
|
|
915
|
+
...prompt,
|
|
916
|
+
...existingResponses,
|
|
912
917
|
];
|
|
918
|
+
if (promptMessageIndex === -1) {
|
|
919
|
+
processedMessages.push(...prompt);
|
|
920
|
+
}
|
|
921
|
+
else {
|
|
922
|
+
// We add the prompt where the prompt message was
|
|
923
|
+
processedMessages.splice(promptMessageIndex, 0, ...prompt);
|
|
924
|
+
}
|
|
913
925
|
// Process messages to inline localhost files (if not, file urls pointing to localhost will be sent to LLM providers)
|
|
914
926
|
if (process.env.CONVEX_CLOUD_URL?.startsWith("http://127.0.0.1")) {
|
|
915
927
|
processedMessages = await this._inlineMessagesFiles(processedMessages);
|
|
@@ -917,14 +929,15 @@ export class Agent {
|
|
|
917
929
|
const { prompt: _, model, ...rest } = args;
|
|
918
930
|
return {
|
|
919
931
|
args: {
|
|
932
|
+
...this.options.callSettings,
|
|
920
933
|
...rest,
|
|
921
|
-
maxRetries: args.maxRetries ?? this.options.maxRetries,
|
|
922
934
|
model: model ?? this.options.chat,
|
|
923
935
|
system: args.system ?? this.options.instructions,
|
|
924
936
|
messages: processedMessages,
|
|
925
937
|
},
|
|
926
938
|
userId,
|
|
927
939
|
messageId,
|
|
940
|
+
savedMessages,
|
|
928
941
|
order,
|
|
929
942
|
stepOrder,
|
|
930
943
|
};
|
|
@@ -933,23 +946,23 @@ export class Agent {
|
|
|
933
946
|
const embeddingModel = this.options.textEmbedding;
|
|
934
947
|
assert(embeddingModel, "a textEmbedding model is required to be set on the Agent that you're doing vector search with");
|
|
935
948
|
const result = await embedMany({
|
|
949
|
+
...this.options.callSettings,
|
|
936
950
|
model: embeddingModel,
|
|
937
951
|
values: options.values,
|
|
938
952
|
abortSignal: options.abortSignal,
|
|
939
953
|
headers: options.headers,
|
|
940
|
-
maxRetries: this.options.maxRetries,
|
|
941
954
|
});
|
|
942
955
|
if (this.options.usageHandler && result.usage) {
|
|
943
956
|
await this.options.usageHandler(ctx, {
|
|
944
957
|
userId: options.userId,
|
|
945
958
|
threadId: options.threadId,
|
|
946
959
|
agentName: this.options.name,
|
|
947
|
-
model: embeddingModel
|
|
948
|
-
provider: embeddingModel
|
|
960
|
+
model: getModelName(embeddingModel),
|
|
961
|
+
provider: getProviderName(embeddingModel),
|
|
949
962
|
providerMetadata: undefined,
|
|
950
963
|
usage: {
|
|
951
|
-
|
|
952
|
-
|
|
964
|
+
inputTokens: result.usage.tokens,
|
|
965
|
+
outputTokens: 0,
|
|
953
966
|
totalTokens: result.usage.tokens,
|
|
954
967
|
},
|
|
955
968
|
});
|
|
@@ -974,35 +987,23 @@ export class Agent {
|
|
|
974
987
|
assert(message.role === "user", "Images can only be in user messages");
|
|
975
988
|
if (this._isLocalhostUrl(part.image)) {
|
|
976
989
|
const imageData = await this._downloadFile(part.image);
|
|
977
|
-
return {
|
|
978
|
-
...part,
|
|
979
|
-
image: imageData,
|
|
980
|
-
};
|
|
990
|
+
return { ...part, image: imageData };
|
|
981
991
|
}
|
|
982
992
|
}
|
|
983
993
|
// Handle file parts
|
|
984
994
|
if (part.type === "file" && part.data instanceof URL) {
|
|
985
995
|
if (this._isLocalhostUrl(part.data)) {
|
|
986
996
|
const fileData = await this._downloadFile(part.data);
|
|
987
|
-
return {
|
|
988
|
-
...part,
|
|
989
|
-
data: fileData,
|
|
990
|
-
};
|
|
997
|
+
return { ...part, data: fileData };
|
|
991
998
|
}
|
|
992
999
|
}
|
|
993
1000
|
return part;
|
|
994
1001
|
}));
|
|
995
1002
|
if (message.role === "user") {
|
|
996
|
-
return {
|
|
997
|
-
...message,
|
|
998
|
-
content: processedContent,
|
|
999
|
-
};
|
|
1003
|
+
return { ...message, content: processedContent };
|
|
1000
1004
|
}
|
|
1001
1005
|
else {
|
|
1002
|
-
return {
|
|
1003
|
-
...message,
|
|
1004
|
-
content: processedContent,
|
|
1005
|
-
};
|
|
1006
|
+
return { ...message, content: processedContent };
|
|
1006
1007
|
}
|
|
1007
1008
|
}));
|
|
1008
1009
|
}
|
|
@@ -1064,19 +1065,27 @@ export class Agent {
|
|
|
1064
1065
|
* Create an action out of this agent so you can call it from workflows or other actions
|
|
1065
1066
|
* without a wrapping function.
|
|
1066
1067
|
* @param spec Configuration for the agent acting as an action, including
|
|
1067
|
-
* {@link ContextOptions}, {@link StorageOptions}, and
|
|
1068
|
+
* {@link ContextOptions}, {@link StorageOptions}, and {@link stopWhen}.
|
|
1068
1069
|
*/
|
|
1069
1070
|
asTextAction(spec) {
|
|
1070
|
-
const
|
|
1071
|
+
const stopWhen = spec?.stopWhen ?? this.options.stopWhen;
|
|
1071
1072
|
return internalActionGeneric({
|
|
1072
1073
|
args: vTextArgs,
|
|
1073
1074
|
handler: async (ctx_, args) => {
|
|
1074
|
-
const stream = args.stream === true ? spec?.stream || true : spec?.stream ?? false;
|
|
1075
|
+
const stream = args.stream === true ? spec?.stream || true : (spec?.stream ?? false);
|
|
1075
1076
|
const targetArgs = { userId: args.userId, threadId: args.threadId };
|
|
1076
1077
|
const llmArgs = {
|
|
1077
|
-
|
|
1078
|
+
stopWhen,
|
|
1078
1079
|
...omit(args, ["storageOptions", "contextOptions"]),
|
|
1080
|
+
messages: args.messages?.map(deserializeMessage),
|
|
1081
|
+
prompt: Array.isArray(args.prompt)
|
|
1082
|
+
? args.prompt.map(deserializeMessage)
|
|
1083
|
+
: args.prompt,
|
|
1084
|
+
toolChoice: args.toolChoice,
|
|
1079
1085
|
};
|
|
1086
|
+
if (args.maxSteps) {
|
|
1087
|
+
llmArgs.stopWhen = stepCountIs(args.maxSteps);
|
|
1088
|
+
}
|
|
1080
1089
|
const opts = {
|
|
1081
1090
|
...this.options,
|
|
1082
1091
|
...(spec && pick(spec, ["contextOptions", "storageOptions"])),
|
|
@@ -1087,6 +1096,7 @@ export class Agent {
|
|
|
1087
1096
|
? { ...ctx_, ...spec.customCtx(ctx_, targetArgs, llmArgs) }
|
|
1088
1097
|
: ctx_);
|
|
1089
1098
|
if (stream) {
|
|
1099
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1090
1100
|
const result = await this.streamText(ctx, targetArgs, llmArgs, opts);
|
|
1091
1101
|
await result.consumeStream();
|
|
1092
1102
|
return {
|
|
@@ -1098,6 +1108,7 @@ export class Agent {
|
|
|
1098
1108
|
};
|
|
1099
1109
|
}
|
|
1100
1110
|
else {
|
|
1111
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1101
1112
|
const res = await this.generateText(ctx, targetArgs, llmArgs, opts);
|
|
1102
1113
|
return {
|
|
1103
1114
|
text: res.text,
|
|
@@ -1115,18 +1126,17 @@ export class Agent {
|
|
|
1115
1126
|
* it from workflows or other actions without a wrapping function.
|
|
1116
1127
|
* @param spec Configuration for the agent acting as an action, including
|
|
1117
1128
|
* the normal parameters to {@link generateObject}, plus {@link ContextOptions}
|
|
1118
|
-
* and
|
|
1129
|
+
* and stopWhen.
|
|
1119
1130
|
*/
|
|
1120
1131
|
asObjectAction(spec, options) {
|
|
1121
|
-
const maxSteps = spec?.maxSteps ?? this.options.maxSteps;
|
|
1122
1132
|
return internalActionGeneric({
|
|
1123
1133
|
args: vSafeObjectArgs,
|
|
1124
1134
|
handler: async (ctx, args) => {
|
|
1125
|
-
const
|
|
1126
|
-
const
|
|
1135
|
+
const { userId, threadId, ...rest } = args;
|
|
1136
|
+
const overrides = pick(rest, ["contextOptions", "storageOptions"]);
|
|
1137
|
+
const value = await this.generateObject(ctx, { userId, threadId }, {
|
|
1127
1138
|
...spec,
|
|
1128
|
-
|
|
1129
|
-
...omit(args, ["userId", "threadId"]),
|
|
1139
|
+
...omit(rest, ["contextOptions", "storageOptions"]),
|
|
1130
1140
|
}, { ...this.options, ...options, ...overrides });
|
|
1131
1141
|
return {
|
|
1132
1142
|
object: value.object,
|
|
@@ -1165,116 +1175,22 @@ export class Agent {
|
|
|
1165
1175
|
userId: v.optional(v.string()),
|
|
1166
1176
|
promptMessageId: v.optional(v.string()),
|
|
1167
1177
|
messages: v.array(vMessageWithMetadata),
|
|
1168
|
-
pending: v.optional(v.boolean()),
|
|
1169
1178
|
failPendingSteps: v.optional(v.boolean()),
|
|
1179
|
+
embeddings: v.optional(vMessageEmbeddings),
|
|
1170
1180
|
},
|
|
1171
1181
|
handler: async (ctx, args) => {
|
|
1172
|
-
const {
|
|
1182
|
+
const { messages } = await this.saveMessages(ctx, {
|
|
1173
1183
|
...args,
|
|
1174
|
-
messages: args.messages.map((m) => m.message),
|
|
1184
|
+
messages: args.messages.map((m) => deserializeMessage(m.message)),
|
|
1175
1185
|
metadata: args.messages.map(({ message: _, ...m }) => m),
|
|
1186
|
+
skipEmbeddings: true,
|
|
1176
1187
|
});
|
|
1177
1188
|
return {
|
|
1178
|
-
lastMessageId,
|
|
1179
|
-
|
|
1189
|
+
lastMessageId: messages.at(-1)._id,
|
|
1190
|
+
messages: messages.map((m) => pick(m, ["_id", "order", "stepOrder"])),
|
|
1180
1191
|
};
|
|
1181
1192
|
},
|
|
1182
1193
|
});
|
|
1183
1194
|
}
|
|
1184
1195
|
}
|
|
1185
|
-
/**
|
|
1186
|
-
* Create a thread to store messages with an Agent.
|
|
1187
|
-
* @param ctx The context from a mutation or action.
|
|
1188
|
-
* @param component The Agent component, usually `components.agent`.
|
|
1189
|
-
* @param args The associated thread metadata.
|
|
1190
|
-
* @returns The id of the created thread.
|
|
1191
|
-
*/
|
|
1192
|
-
export async function createThread(ctx, component, args) {
|
|
1193
|
-
const { _id: threadId } = await ctx.runMutation(component.threads.createThread, {
|
|
1194
|
-
userId: args?.userId ?? undefined,
|
|
1195
|
-
title: args?.title,
|
|
1196
|
-
summary: args?.summary,
|
|
1197
|
-
});
|
|
1198
|
-
return threadId;
|
|
1199
|
-
}
|
|
1200
|
-
/**
|
|
1201
|
-
* Get the metadata for a thread.
|
|
1202
|
-
* @param ctx A ctx object from a query, mutation, or action.
|
|
1203
|
-
* @param args.threadId The thread to get the metadata for.
|
|
1204
|
-
* @returns The metadata for the thread.
|
|
1205
|
-
*/
|
|
1206
|
-
export async function getThreadMetadata(ctx, component, args) {
|
|
1207
|
-
const thread = await ctx.runQuery(component.threads.getThread, {
|
|
1208
|
-
threadId: args.threadId,
|
|
1209
|
-
});
|
|
1210
|
-
if (!thread) {
|
|
1211
|
-
throw new Error("Thread not found");
|
|
1212
|
-
}
|
|
1213
|
-
return thread;
|
|
1214
|
-
}
|
|
1215
|
-
/**
|
|
1216
|
-
* Explicitly save messages associated with the thread (& user if provided)
|
|
1217
|
-
*/
|
|
1218
|
-
export async function saveMessages(ctx, component, args) {
|
|
1219
|
-
let embeddings;
|
|
1220
|
-
if (args.embeddings) {
|
|
1221
|
-
const dimension = args.embeddings.vectors.find((v) => v !== null)?.length;
|
|
1222
|
-
if (dimension) {
|
|
1223
|
-
validateVectorDimension(dimension);
|
|
1224
|
-
embeddings = {
|
|
1225
|
-
model: args.embeddings.model,
|
|
1226
|
-
dimension,
|
|
1227
|
-
vectors: args.embeddings.vectors,
|
|
1228
|
-
};
|
|
1229
|
-
}
|
|
1230
|
-
}
|
|
1231
|
-
const result = await ctx.runMutation(component.messages.addMessages, {
|
|
1232
|
-
threadId: args.threadId,
|
|
1233
|
-
userId: args.userId ?? undefined,
|
|
1234
|
-
agentName: args.agentName,
|
|
1235
|
-
promptMessageId: args.promptMessageId,
|
|
1236
|
-
embeddings,
|
|
1237
|
-
messages: await Promise.all(args.messages.map(async (m, i) => {
|
|
1238
|
-
const { message, fileIds } = await serializeMessage(ctx, component, m);
|
|
1239
|
-
return {
|
|
1240
|
-
...args.metadata?.[i],
|
|
1241
|
-
message,
|
|
1242
|
-
fileIds,
|
|
1243
|
-
};
|
|
1244
|
-
})),
|
|
1245
|
-
failPendingSteps: args.failPendingSteps ?? false,
|
|
1246
|
-
pending: args.pending ?? false,
|
|
1247
|
-
});
|
|
1248
|
-
return {
|
|
1249
|
-
lastMessageId: result.messages.at(-1)._id,
|
|
1250
|
-
messages: result.messages,
|
|
1251
|
-
};
|
|
1252
|
-
}
|
|
1253
|
-
/**
|
|
1254
|
-
* Save a message to the thread.
|
|
1255
|
-
* @param ctx A ctx object from a mutation or action.
|
|
1256
|
-
* @param args The message and what to associate it with (user / thread)
|
|
1257
|
-
* You can pass extra metadata alongside the message, e.g. associated fileIds.
|
|
1258
|
-
* @returns The messageId of the saved message.
|
|
1259
|
-
*/
|
|
1260
|
-
export async function saveMessage(ctx, component, args) {
|
|
1261
|
-
let embeddings;
|
|
1262
|
-
if (args.embedding && args.embedding.vector) {
|
|
1263
|
-
embeddings = {
|
|
1264
|
-
model: args.embedding.model,
|
|
1265
|
-
vectors: [args.embedding.vector],
|
|
1266
|
-
};
|
|
1267
|
-
}
|
|
1268
|
-
const { lastMessageId, messages } = await saveMessages(ctx, component, {
|
|
1269
|
-
threadId: args.threadId,
|
|
1270
|
-
userId: args.userId ?? undefined,
|
|
1271
|
-
agentName: args.agentName,
|
|
1272
|
-
messages: args.prompt !== undefined
|
|
1273
|
-
? [{ role: "user", content: args.prompt }]
|
|
1274
|
-
: [args.message],
|
|
1275
|
-
metadata: args.metadata ? [args.metadata] : undefined,
|
|
1276
|
-
embeddings,
|
|
1277
|
-
});
|
|
1278
|
-
return { messageId: lastMessageId, message: messages.at(-1) };
|
|
1279
|
-
}
|
|
1280
1196
|
//# sourceMappingURL=index.js.map
|