@convex-dev/agent 0.0.1-alpha.4 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -7
- package/dist/commonjs/client/index.d.ts +800 -84
- package/dist/commonjs/client/index.d.ts.map +1 -1
- package/dist/commonjs/client/index.js +176 -130
- package/dist/commonjs/client/index.js.map +1 -1
- package/dist/commonjs/component/messages.d.ts +124 -105
- package/dist/commonjs/component/messages.d.ts.map +1 -1
- package/dist/commonjs/component/messages.js +145 -247
- package/dist/commonjs/component/messages.js.map +1 -1
- package/dist/commonjs/component/schema.d.ts +822 -746
- package/dist/commonjs/component/schema.d.ts.map +1 -1
- package/dist/commonjs/component/schema.js +13 -3
- package/dist/commonjs/component/schema.js.map +1 -1
- package/dist/commonjs/component/vector/index.d.ts +21 -6
- package/dist/commonjs/component/vector/index.d.ts.map +1 -1
- package/dist/commonjs/component/vector/index.js +32 -20
- package/dist/commonjs/component/vector/index.js.map +1 -1
- package/dist/commonjs/component/vector/tables.d.ts +25 -5
- package/dist/commonjs/component/vector/tables.d.ts.map +1 -1
- package/dist/commonjs/component/vector/tables.js +14 -6
- package/dist/commonjs/component/vector/tables.js.map +1 -1
- package/dist/commonjs/mapping.d.ts +3 -2
- package/dist/commonjs/mapping.d.ts.map +1 -1
- package/dist/commonjs/mapping.js +45 -13
- package/dist/commonjs/mapping.js.map +1 -1
- package/dist/commonjs/validators.d.ts +2817 -145
- package/dist/commonjs/validators.d.ts.map +1 -1
- package/dist/commonjs/validators.js +79 -7
- package/dist/commonjs/validators.js.map +1 -1
- package/dist/esm/client/index.d.ts +800 -84
- package/dist/esm/client/index.d.ts.map +1 -1
- package/dist/esm/client/index.js +176 -130
- package/dist/esm/client/index.js.map +1 -1
- package/dist/esm/component/messages.d.ts +124 -105
- package/dist/esm/component/messages.d.ts.map +1 -1
- package/dist/esm/component/messages.js +145 -247
- package/dist/esm/component/messages.js.map +1 -1
- package/dist/esm/component/schema.d.ts +822 -746
- package/dist/esm/component/schema.d.ts.map +1 -1
- package/dist/esm/component/schema.js +13 -3
- package/dist/esm/component/schema.js.map +1 -1
- package/dist/esm/component/vector/index.d.ts +21 -6
- package/dist/esm/component/vector/index.d.ts.map +1 -1
- package/dist/esm/component/vector/index.js +32 -20
- package/dist/esm/component/vector/index.js.map +1 -1
- package/dist/esm/component/vector/tables.d.ts +25 -5
- package/dist/esm/component/vector/tables.d.ts.map +1 -1
- package/dist/esm/component/vector/tables.js +14 -6
- package/dist/esm/component/vector/tables.js.map +1 -1
- package/dist/esm/mapping.d.ts +3 -2
- package/dist/esm/mapping.d.ts.map +1 -1
- package/dist/esm/mapping.js +45 -13
- package/dist/esm/mapping.js.map +1 -1
- package/dist/esm/validators.d.ts +2817 -145
- package/dist/esm/validators.d.ts.map +1 -1
- package/dist/esm/validators.js +79 -7
- package/dist/esm/validators.js.map +1 -1
- package/package.json +7 -7
- package/src/client/index.ts +347 -170
- package/src/component/_generated/api.d.ts +33 -16
- package/src/component/messages.ts +177 -290
- package/src/component/schema.ts +14 -3
- package/src/component/vector/index.ts +59 -26
- package/src/component/vector/tables.ts +38 -6
- package/src/mapping.ts +60 -19
- package/src/validators.ts +112 -12
package/src/client/index.ts
CHANGED
|
@@ -4,36 +4,48 @@ import type {
|
|
|
4
4
|
DeepPartial,
|
|
5
5
|
GenerateObjectResult,
|
|
6
6
|
GenerateTextResult,
|
|
7
|
+
JSONValue,
|
|
8
|
+
RepairTextFunction,
|
|
7
9
|
StepResult,
|
|
8
10
|
StreamObjectResult,
|
|
9
11
|
StreamTextResult,
|
|
12
|
+
TelemetrySettings,
|
|
10
13
|
Tool,
|
|
11
14
|
ToolChoice,
|
|
12
15
|
ToolExecutionOptions,
|
|
13
16
|
ToolSet,
|
|
17
|
+
Message as UIMessage,
|
|
14
18
|
} from "ai";
|
|
15
19
|
import { generateObject, generateText, streamObject, streamText } from "ai";
|
|
16
|
-
import { api } from "../component/_generated/api";
|
|
17
|
-
import {
|
|
18
|
-
SearchOptions,
|
|
19
|
-
vThreadArgs,
|
|
20
|
-
vContextOptions,
|
|
21
|
-
vObjectArgs,
|
|
22
|
-
vStorageOptions,
|
|
23
|
-
} from "../validators";
|
|
24
|
-
import { RunActionCtx, RunMutationCtx, RunQueryCtx, UseApi } from "./types";
|
|
25
|
-
// TODO: is this the only dependency that needs helpers in client?
|
|
26
20
|
import { assert } from "convex-helpers";
|
|
27
21
|
import { ConvexToZod, convexToZod } from "convex-helpers/server/zod";
|
|
28
22
|
import { internalActionGeneric } from "convex/server";
|
|
29
23
|
import { Infer, v, Validator } from "convex/values";
|
|
24
|
+
import { z } from "zod";
|
|
25
|
+
import { api } from "../component/_generated/api";
|
|
26
|
+
import {
|
|
27
|
+
validateVectorDimension,
|
|
28
|
+
VectorDimension,
|
|
29
|
+
} from "../component/vector/tables";
|
|
30
30
|
import {
|
|
31
31
|
promptOrMessagesToCoreMessages,
|
|
32
32
|
serializeMessageWithId,
|
|
33
33
|
serializeNewMessagesInStep,
|
|
34
|
+
serializeObjectResult,
|
|
34
35
|
serializeStep,
|
|
35
36
|
} from "../mapping";
|
|
36
37
|
import { DEFAULT_MESSAGE_RANGE, extractText } from "../shared";
|
|
38
|
+
import {
|
|
39
|
+
CallSettings,
|
|
40
|
+
ProviderMetadata,
|
|
41
|
+
ProviderOptions,
|
|
42
|
+
SearchOptions,
|
|
43
|
+
vContextOptions,
|
|
44
|
+
vSafeObjectArgs,
|
|
45
|
+
vStorageOptions,
|
|
46
|
+
vTextArgs,
|
|
47
|
+
} from "../validators";
|
|
48
|
+
import { RunActionCtx, RunMutationCtx, RunQueryCtx, UseApi } from "./types";
|
|
37
49
|
|
|
38
50
|
export type ContextOptions = {
|
|
39
51
|
/**
|
|
@@ -80,11 +92,13 @@ export type StorageOptions = {
|
|
|
80
92
|
// be in addition to automatically fetched content.
|
|
81
93
|
// Pass true to have all input messages saved to the thread history.
|
|
82
94
|
saveAllInputMessages?: boolean;
|
|
83
|
-
// Defaults to true
|
|
95
|
+
// Defaults to true, saving the prompt, or last message passed to generateText.
|
|
96
|
+
saveAnyInputMessages?: boolean;
|
|
97
|
+
// Defaults to true.
|
|
84
98
|
saveOutputMessages?: boolean;
|
|
85
99
|
};
|
|
86
100
|
|
|
87
|
-
export type GenerationOutputMetadata = { messageId
|
|
101
|
+
export type GenerationOutputMetadata = { messageId?: string };
|
|
88
102
|
|
|
89
103
|
type CoreMessageMaybeWithId = CoreMessage & { id?: string | undefined };
|
|
90
104
|
|
|
@@ -93,7 +107,7 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
93
107
|
public component: UseApi<typeof api>,
|
|
94
108
|
public options: {
|
|
95
109
|
name?: string;
|
|
96
|
-
|
|
110
|
+
chat: LanguageModelV1;
|
|
97
111
|
textEmbedding?: EmbeddingModelV1<string>;
|
|
98
112
|
instructions?: string;
|
|
99
113
|
tools?: AgentTools;
|
|
@@ -116,7 +130,7 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
116
130
|
*/
|
|
117
131
|
async createThread(
|
|
118
132
|
ctx: RunActionCtx,
|
|
119
|
-
args
|
|
133
|
+
args?: {
|
|
120
134
|
/**
|
|
121
135
|
* The userId to associate with the thread. If not provided, the thread will be
|
|
122
136
|
* anonymous.
|
|
@@ -152,7 +166,7 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
152
166
|
*/
|
|
153
167
|
async createThread(
|
|
154
168
|
ctx: RunMutationCtx,
|
|
155
|
-
args
|
|
169
|
+
args?: {
|
|
156
170
|
userId?: string;
|
|
157
171
|
parentThreadIds?: string[];
|
|
158
172
|
title?: string;
|
|
@@ -163,7 +177,7 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
163
177
|
}>;
|
|
164
178
|
async createThread(
|
|
165
179
|
ctx: RunActionCtx | RunMutationCtx,
|
|
166
|
-
args
|
|
180
|
+
args?: {
|
|
167
181
|
userId: string;
|
|
168
182
|
parentThreadIds?: string[];
|
|
169
183
|
title?: string;
|
|
@@ -177,10 +191,10 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
177
191
|
this.component.messages.createThread,
|
|
178
192
|
{
|
|
179
193
|
defaultSystemPrompt: this.options.instructions,
|
|
180
|
-
userId: args
|
|
181
|
-
title: args
|
|
182
|
-
summary: args
|
|
183
|
-
parentThreadIds: args
|
|
194
|
+
userId: args?.userId,
|
|
195
|
+
title: args?.title,
|
|
196
|
+
summary: args?.summary,
|
|
197
|
+
parentThreadIds: args?.parentThreadIds,
|
|
184
198
|
}
|
|
185
199
|
);
|
|
186
200
|
if (!("runAction" in ctx)) {
|
|
@@ -188,7 +202,7 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
188
202
|
}
|
|
189
203
|
const { thread } = await this.continueThread(ctx, {
|
|
190
204
|
threadId: threadDoc._id,
|
|
191
|
-
userId: args
|
|
205
|
+
userId: args?.userId,
|
|
192
206
|
});
|
|
193
207
|
return {
|
|
194
208
|
threadId: threadDoc._id,
|
|
@@ -215,6 +229,7 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
215
229
|
// return this.component.continueThread(ctx, args);
|
|
216
230
|
return {
|
|
217
231
|
thread: {
|
|
232
|
+
threadId,
|
|
218
233
|
generateText: this.generateText.bind(this, ctx, { userId, threadId }),
|
|
219
234
|
streamText: this.streamText.bind(this, ctx, { userId, threadId }),
|
|
220
235
|
generateObject: this.generateObject.bind(this, ctx, {
|
|
@@ -238,6 +253,7 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
238
253
|
assert(args.userId || args.threadId, "Specify userId or threadId");
|
|
239
254
|
// Fetch the latest messages from the thread
|
|
240
255
|
const contextMessages: CoreMessage[] = [];
|
|
256
|
+
let included: Set<string> | undefined;
|
|
241
257
|
const opts = this.mergedContextOptions(args);
|
|
242
258
|
if (opts.searchOptions?.textSearch || opts.searchOptions?.vectorSearch) {
|
|
243
259
|
if (!("runAction" in ctx)) {
|
|
@@ -253,6 +269,7 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
253
269
|
}
|
|
254
270
|
);
|
|
255
271
|
// TODO: track what messages we used for context
|
|
272
|
+
included = new Set(searchMessages.map((m) => m._id));
|
|
256
273
|
contextMessages.push(...searchMessages.map((m) => m.message!));
|
|
257
274
|
}
|
|
258
275
|
if (args.threadId) {
|
|
@@ -267,15 +284,56 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
267
284
|
statuses: ["success"],
|
|
268
285
|
}
|
|
269
286
|
);
|
|
270
|
-
contextMessages.push(
|
|
287
|
+
contextMessages.push(
|
|
288
|
+
...messages.filter((m) => !included?.has(m._id)).map((m) => m.message!)
|
|
289
|
+
);
|
|
271
290
|
}
|
|
272
291
|
return contextMessages;
|
|
273
292
|
}
|
|
274
293
|
|
|
294
|
+
async getEmbeddings(messages: CoreMessage[]) {
|
|
295
|
+
let embeddings:
|
|
296
|
+
| {
|
|
297
|
+
vectors: (number[] | null)[];
|
|
298
|
+
dimension: VectorDimension;
|
|
299
|
+
model: string;
|
|
300
|
+
}
|
|
301
|
+
| undefined;
|
|
302
|
+
if (this.options.textEmbedding) {
|
|
303
|
+
const messageTexts = messages.map((m) => extractText(m));
|
|
304
|
+
// Find the indexes of the messages that have text.
|
|
305
|
+
const textIndexes = messageTexts
|
|
306
|
+
.map((t, i) => (t ? i : undefined))
|
|
307
|
+
.filter((i) => i !== undefined);
|
|
308
|
+
if (textIndexes.length === 0) {
|
|
309
|
+
return undefined;
|
|
310
|
+
}
|
|
311
|
+
// Then embed those messages.
|
|
312
|
+
const textEmbeddings = await this.options.textEmbedding.doEmbed({
|
|
313
|
+
values: messageTexts.filter((t): t is string => !!t),
|
|
314
|
+
});
|
|
315
|
+
// Then assemble the embeddings into a single array with nulls for the messages without text.
|
|
316
|
+
const embeddingsOrNull = Array(messages.length).fill(null);
|
|
317
|
+
textIndexes.forEach((i, j) => {
|
|
318
|
+
embeddingsOrNull[i] = textEmbeddings.embeddings[j];
|
|
319
|
+
});
|
|
320
|
+
if (textEmbeddings.embeddings.length > 0) {
|
|
321
|
+
const dimension = textEmbeddings.embeddings[0].length;
|
|
322
|
+
validateVectorDimension(dimension);
|
|
323
|
+
embeddings = {
|
|
324
|
+
vectors: embeddingsOrNull,
|
|
325
|
+
dimension,
|
|
326
|
+
model: this.options.textEmbedding.modelId,
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
return embeddings;
|
|
331
|
+
}
|
|
332
|
+
|
|
275
333
|
async saveMessages(
|
|
276
334
|
ctx: RunMutationCtx,
|
|
277
335
|
args: {
|
|
278
|
-
threadId
|
|
336
|
+
threadId: string;
|
|
279
337
|
userId?: string;
|
|
280
338
|
messages: CoreMessageMaybeWithId[];
|
|
281
339
|
pending?: boolean;
|
|
@@ -290,8 +348,9 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
290
348
|
threadId: args.threadId,
|
|
291
349
|
userId: args.userId,
|
|
292
350
|
agentName: this.options.name,
|
|
293
|
-
model: this.options.
|
|
351
|
+
model: this.options.chat.modelId,
|
|
294
352
|
messages: args.messages.map(serializeMessageWithId),
|
|
353
|
+
embeddings: await this.getEmbeddings(args.messages),
|
|
295
354
|
failPendingSteps: args.failPendingSteps ?? true,
|
|
296
355
|
pending: args.pending ?? false,
|
|
297
356
|
parentMessageId: args.parentMessageId,
|
|
@@ -308,11 +367,12 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
308
367
|
): Promise<void> {
|
|
309
368
|
const step = serializeStep(args.step as StepResult<ToolSet>);
|
|
310
369
|
const messages = serializeNewMessagesInStep(args.step);
|
|
311
|
-
await ctx.runMutation(this.component.messages.
|
|
370
|
+
await ctx.runMutation(this.component.messages.addStep, {
|
|
312
371
|
threadId: args.threadId,
|
|
313
372
|
messageId: args.messageId,
|
|
314
|
-
|
|
373
|
+
step: { step, messages },
|
|
315
374
|
failPendingSteps: false,
|
|
375
|
+
embeddings: await this.getEmbeddings(messages.map((m) => m.message)),
|
|
316
376
|
});
|
|
317
377
|
}
|
|
318
378
|
|
|
@@ -333,11 +393,9 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
333
393
|
messageId: args.messageId,
|
|
334
394
|
});
|
|
335
395
|
} else {
|
|
336
|
-
await ctx.runMutation(this.component.messages.
|
|
337
|
-
threadId: args.threadId,
|
|
396
|
+
await ctx.runMutation(this.component.messages.rollbackMessage, {
|
|
338
397
|
messageId: args.messageId,
|
|
339
|
-
|
|
340
|
-
failPendingSteps: true,
|
|
398
|
+
error: result.error,
|
|
341
399
|
});
|
|
342
400
|
}
|
|
343
401
|
}
|
|
@@ -372,36 +430,23 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
372
430
|
): Promise<
|
|
373
431
|
GenerateTextResult<TOOLS & AgentTools, OUTPUT> & GenerationOutputMetadata
|
|
374
432
|
> {
|
|
375
|
-
const {
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
userId,
|
|
380
|
-
threadId,
|
|
381
|
-
messages,
|
|
382
|
-
});
|
|
383
|
-
const { lastMessageId: messageId } = await this.saveMessages(ctx, {
|
|
384
|
-
threadId,
|
|
385
|
-
userId,
|
|
386
|
-
messages: args.saveAllInputMessages ? messages : messages.slice(-1),
|
|
387
|
-
pending: true,
|
|
388
|
-
parentMessageId: args.parentMessageId,
|
|
389
|
-
});
|
|
433
|
+
const { args: aiArgs, messageId } = await this.saveMessagesAndFetchContext(
|
|
434
|
+
ctx,
|
|
435
|
+
{ ...args, userId, threadId }
|
|
436
|
+
);
|
|
390
437
|
const toolCtx = { ...ctx, userId, threadId, messageId };
|
|
391
438
|
const tools = wrapTools(toolCtx, this.options.tools, args.tools) as TOOLS;
|
|
439
|
+
const maxSteps = args.maxSteps ?? this.options.maxSteps;
|
|
392
440
|
try {
|
|
393
441
|
const result = await generateText({
|
|
394
|
-
model: this.options.
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
maxSteps: this.options.maxSteps,
|
|
442
|
+
model: this.options.chat,
|
|
443
|
+
...aiArgs,
|
|
444
|
+
maxSteps,
|
|
398
445
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
399
446
|
toolChoice: args.toolChoice as any,
|
|
400
|
-
...rest,
|
|
401
447
|
tools,
|
|
402
448
|
onStepFinish: async (step) => {
|
|
403
|
-
if (threadId && messageId && args.saveOutputMessages) {
|
|
404
|
-
console.log("onStepFinish", step);
|
|
449
|
+
if (threadId && messageId && args.saveOutputMessages !== false) {
|
|
405
450
|
await this.saveStep(ctx, {
|
|
406
451
|
threadId,
|
|
407
452
|
messageId,
|
|
@@ -439,38 +484,27 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
439
484
|
): Promise<
|
|
440
485
|
StreamTextResult<TOOLS, PARTIAL_OUTPUT> & GenerationOutputMetadata
|
|
441
486
|
> {
|
|
442
|
-
const {
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
userId,
|
|
447
|
-
threadId,
|
|
448
|
-
messages,
|
|
449
|
-
});
|
|
450
|
-
const { lastMessageId: messageId } = await this.saveMessages(ctx, {
|
|
451
|
-
threadId,
|
|
452
|
-
messages: args.saveAllInputMessages ? messages : messages.slice(-1),
|
|
453
|
-
pending: true,
|
|
454
|
-
parentMessageId: args.parentMessageId,
|
|
455
|
-
});
|
|
487
|
+
const { args: aiArgs, messageId } = await this.saveMessagesAndFetchContext(
|
|
488
|
+
ctx,
|
|
489
|
+
{ ...args, userId, threadId }
|
|
490
|
+
);
|
|
456
491
|
const toolCtx = { ...ctx, userId, threadId, messageId };
|
|
457
492
|
const tools = wrapTools(toolCtx, this.options.tools, args.tools) as TOOLS;
|
|
493
|
+
const maxSteps = args.maxSteps ?? this.options.maxSteps;
|
|
458
494
|
const result = streamText({
|
|
459
|
-
model: this.options.
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
maxSteps: this.options.maxSteps,
|
|
495
|
+
model: this.options.chat,
|
|
496
|
+
...aiArgs,
|
|
497
|
+
maxSteps,
|
|
463
498
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
464
499
|
toolChoice: args.toolChoice as any,
|
|
465
|
-
...rest,
|
|
466
500
|
tools,
|
|
467
501
|
onChunk: async (chunk) => {
|
|
468
|
-
console.log("onChunk", chunk);
|
|
502
|
+
// console.log("onChunk", chunk);
|
|
469
503
|
return args.onChunk?.(chunk);
|
|
470
504
|
},
|
|
471
505
|
onError: async (error) => {
|
|
472
506
|
console.error("onError", error);
|
|
473
|
-
if (threadId && messageId) {
|
|
507
|
+
if (threadId && messageId && args.saveOutputMessages !== false) {
|
|
474
508
|
await ctx.runMutation(this.component.messages.rollbackMessage, {
|
|
475
509
|
messageId,
|
|
476
510
|
error: (error.error as Error).message,
|
|
@@ -478,14 +512,9 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
478
512
|
}
|
|
479
513
|
return args.onError?.(error);
|
|
480
514
|
},
|
|
481
|
-
onFinish: async (result) => {
|
|
482
|
-
result.response.messages.forEach((message) => {
|
|
483
|
-
console.log("onFinish", message);
|
|
484
|
-
});
|
|
485
|
-
return args.onFinish?.(result);
|
|
486
|
-
},
|
|
487
515
|
onStepFinish: async (step) => {
|
|
488
|
-
console.log("onStepFinish", step);
|
|
516
|
+
// console.log("onStepFinish", step);
|
|
517
|
+
// TODO: compare delta to the output. internally drop the deltas when committing
|
|
489
518
|
if (threadId && messageId) {
|
|
490
519
|
await this.saveStep(ctx, {
|
|
491
520
|
threadId,
|
|
@@ -499,72 +528,160 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
499
528
|
return { ...result, messageId };
|
|
500
529
|
}
|
|
501
530
|
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
const { prompt, messages: raw, ...rest } = args;
|
|
512
|
-
const messages = promptOrMessagesToCoreMessages({ prompt, messages: raw });
|
|
513
|
-
const contextMessages = await this.fetchContextMessages(ctx, {
|
|
514
|
-
...args,
|
|
531
|
+
async saveMessagesAndFetchContext<
|
|
532
|
+
T extends {
|
|
533
|
+
prompt?: string;
|
|
534
|
+
messages?: CoreMessage[] | Omit<UIMessage, "id">[];
|
|
535
|
+
system?: string;
|
|
536
|
+
},
|
|
537
|
+
>(
|
|
538
|
+
ctx: RunActionCtx | RunMutationCtx,
|
|
539
|
+
{
|
|
515
540
|
userId,
|
|
516
541
|
threadId,
|
|
542
|
+
parentMessageId,
|
|
543
|
+
saveAllInputMessages,
|
|
544
|
+
system,
|
|
545
|
+
...args
|
|
546
|
+
}: {
|
|
547
|
+
userId: string | undefined;
|
|
548
|
+
threadId: string | undefined;
|
|
549
|
+
parentMessageId?: string;
|
|
550
|
+
saveAllInputMessages?: boolean;
|
|
551
|
+
saveAnyInputMessages?: boolean;
|
|
552
|
+
} & ContextOptions &
|
|
553
|
+
T
|
|
554
|
+
): Promise<{
|
|
555
|
+
args: T;
|
|
556
|
+
messageId: string | undefined;
|
|
557
|
+
}> {
|
|
558
|
+
const messages = promptOrMessagesToCoreMessages(args);
|
|
559
|
+
const contextMessages = await this.fetchContextMessages(ctx, {
|
|
517
560
|
messages,
|
|
518
|
-
|
|
519
|
-
|
|
561
|
+
parentMessageId,
|
|
562
|
+
userId,
|
|
520
563
|
threadId,
|
|
521
|
-
|
|
522
|
-
pending: true,
|
|
564
|
+
...args,
|
|
523
565
|
});
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
566
|
+
let messageId: string | undefined;
|
|
567
|
+
if (threadId) {
|
|
568
|
+
const saved = await this.saveMessages(ctx, {
|
|
569
|
+
threadId,
|
|
570
|
+
userId,
|
|
571
|
+
messages: saveAllInputMessages ? messages : messages.slice(-1),
|
|
572
|
+
pending: true,
|
|
573
|
+
// We should just fail if you pass in an ID for the message, fail those children
|
|
574
|
+
// failPendingSteps: true,
|
|
575
|
+
parentMessageId,
|
|
576
|
+
});
|
|
577
|
+
messageId = saved.lastMessageId;
|
|
578
|
+
}
|
|
579
|
+
const { prompt: _, ...rest } = args;
|
|
580
|
+
return {
|
|
581
|
+
args: {
|
|
582
|
+
...rest,
|
|
583
|
+
system: system ?? this.options.instructions,
|
|
584
|
+
messages: [...contextMessages, ...messages],
|
|
585
|
+
} as T,
|
|
586
|
+
messageId,
|
|
587
|
+
};
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
async generateObject<T>(
|
|
591
|
+
ctx: RunActionCtx,
|
|
592
|
+
{ userId, threadId }: { userId?: string; threadId?: string },
|
|
593
|
+
args: OurObjectArgs<T>
|
|
594
|
+
): Promise<GenerateObjectResult<T> & GenerationOutputMetadata> {
|
|
595
|
+
const { args: aiArgs, messageId } = await this.saveMessagesAndFetchContext(
|
|
596
|
+
ctx,
|
|
597
|
+
{ ...args, userId, threadId }
|
|
598
|
+
);
|
|
599
|
+
|
|
600
|
+
try {
|
|
601
|
+
const result = (await generateObject({
|
|
602
|
+
model: this.options.chat,
|
|
603
|
+
...aiArgs,
|
|
604
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
605
|
+
} as any)) as GenerateObjectResult<T>;
|
|
606
|
+
|
|
607
|
+
if (threadId && messageId && args.saveOutputMessages !== false) {
|
|
608
|
+
await this.saveObject(ctx, { threadId, messageId, result });
|
|
609
|
+
}
|
|
610
|
+
return { ...result, messageId };
|
|
611
|
+
} catch (error) {
|
|
612
|
+
if (threadId && messageId) {
|
|
613
|
+
await ctx.runMutation(this.component.messages.rollbackMessage, {
|
|
614
|
+
messageId,
|
|
615
|
+
error: (error as Error).message,
|
|
616
|
+
});
|
|
617
|
+
}
|
|
618
|
+
throw error;
|
|
619
|
+
}
|
|
530
620
|
}
|
|
531
621
|
|
|
532
622
|
async streamObject<T>(
|
|
533
623
|
ctx: RunMutationCtx,
|
|
534
624
|
{ userId, threadId }: { userId?: string; threadId?: string },
|
|
535
|
-
args:
|
|
536
|
-
model?: LanguageModelV1;
|
|
537
|
-
} & { parentMessageId?: string } & ContextOptions &
|
|
538
|
-
StorageOptions
|
|
625
|
+
args: OurStreamObjectArgs<T>
|
|
539
626
|
): Promise<
|
|
540
627
|
StreamObjectResult<DeepPartial<T>, T, never> & GenerationOutputMetadata
|
|
541
628
|
> {
|
|
542
|
-
|
|
543
|
-
const
|
|
544
|
-
|
|
545
|
-
...args,
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
threadId,
|
|
552
|
-
messages: args.saveAllInputMessages ? messages : messages.slice(-1),
|
|
553
|
-
pending: true,
|
|
554
|
-
});
|
|
555
|
-
const result = streamObject<T>({
|
|
556
|
-
model: this.options.thread,
|
|
557
|
-
messages: [...contextMessages, ...messages],
|
|
558
|
-
...rest,
|
|
629
|
+
// TODO: unify all this shared code between all the generate* and stream* functions
|
|
630
|
+
const { args: aiArgs, messageId } = await this.saveMessagesAndFetchContext(
|
|
631
|
+
ctx,
|
|
632
|
+
{ ...args, userId, threadId }
|
|
633
|
+
);
|
|
634
|
+
const stream = streamObject<T>({
|
|
635
|
+
model: this.options.chat,
|
|
636
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
637
|
+
...(aiArgs as any),
|
|
559
638
|
onError: async (error) => {
|
|
560
639
|
console.error("onError", error);
|
|
561
640
|
return args.onError?.(error);
|
|
562
641
|
},
|
|
563
642
|
onFinish: async (result) => {
|
|
564
|
-
|
|
643
|
+
if (threadId && messageId && args.saveOutputMessages !== false) {
|
|
644
|
+
await this.saveObject(ctx, {
|
|
645
|
+
threadId,
|
|
646
|
+
messageId,
|
|
647
|
+
result: {
|
|
648
|
+
object: result.object,
|
|
649
|
+
finishReason: "stop",
|
|
650
|
+
usage: result.usage,
|
|
651
|
+
warnings: result.warnings,
|
|
652
|
+
request: await stream.request,
|
|
653
|
+
response: result.response,
|
|
654
|
+
providerMetadata: result.providerMetadata,
|
|
655
|
+
experimental_providerMetadata:
|
|
656
|
+
result.experimental_providerMetadata,
|
|
657
|
+
logprobs: undefined,
|
|
658
|
+
toJsonResponse: stream.toTextStreamResponse,
|
|
659
|
+
},
|
|
660
|
+
});
|
|
661
|
+
}
|
|
662
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
663
|
+
return args.onFinish?.(result as any);
|
|
565
664
|
},
|
|
566
665
|
}) as StreamObjectResult<DeepPartial<T>, T, never>;
|
|
567
|
-
return { ...
|
|
666
|
+
return { ...stream, messageId };
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
async saveObject(
|
|
670
|
+
ctx: RunMutationCtx,
|
|
671
|
+
args: {
|
|
672
|
+
threadId: string;
|
|
673
|
+
messageId: string;
|
|
674
|
+
result: GenerateObjectResult<unknown>;
|
|
675
|
+
}
|
|
676
|
+
): Promise<void> {
|
|
677
|
+
const step = serializeObjectResult(args.result);
|
|
678
|
+
await ctx.runMutation(this.component.messages.addStep, {
|
|
679
|
+
threadId: args.threadId,
|
|
680
|
+
messageId: args.messageId,
|
|
681
|
+
failPendingSteps: false,
|
|
682
|
+
embeddings: await this.getEmbeddings([step.messages[0].message]),
|
|
683
|
+
step,
|
|
684
|
+
});
|
|
568
685
|
}
|
|
569
686
|
|
|
570
687
|
mergedContextOptions(opts: ContextOptions): ContextOptions {
|
|
@@ -618,7 +735,7 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
618
735
|
/**
|
|
619
736
|
*
|
|
620
737
|
*/
|
|
621
|
-
asAction(spec
|
|
738
|
+
asAction(spec?: { contextOptions?: ContextOptions; maxSteps?: number }) {
|
|
622
739
|
return internalActionGeneric({
|
|
623
740
|
args: {
|
|
624
741
|
userId: v.optional(v.string()),
|
|
@@ -626,6 +743,7 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
626
743
|
contextOptions: v.optional(vContextOptions),
|
|
627
744
|
storageOptions: v.optional(vStorageOptions),
|
|
628
745
|
maxRetries: v.optional(v.number()),
|
|
746
|
+
parentMessageId: v.optional(v.string()),
|
|
629
747
|
|
|
630
748
|
createThread: v.optional(
|
|
631
749
|
v.object({
|
|
@@ -635,67 +753,59 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
635
753
|
summary: v.optional(v.string()),
|
|
636
754
|
})
|
|
637
755
|
),
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
})
|
|
643
|
-
),
|
|
644
|
-
generateText: v.optional(vThreadArgs),
|
|
645
|
-
streamText: v.optional(vThreadArgs),
|
|
646
|
-
generateObject: v.optional(vObjectArgs),
|
|
647
|
-
streamObject: v.optional(
|
|
648
|
-
v.object({ ...vObjectArgs.fields, schema: v.any() })
|
|
649
|
-
),
|
|
756
|
+
generateText: v.optional(vTextArgs),
|
|
757
|
+
streamText: v.optional(vTextArgs),
|
|
758
|
+
generateObject: v.optional(vSafeObjectArgs),
|
|
759
|
+
streamObject: v.optional(vSafeObjectArgs),
|
|
650
760
|
},
|
|
651
761
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
652
762
|
handler: async (ctx, args): Promise<any> => {
|
|
653
763
|
const contextOptions =
|
|
654
|
-
spec
|
|
655
|
-
|
|
656
|
-
const
|
|
764
|
+
spec?.contextOptions &&
|
|
765
|
+
this.mergedContextOptions(spec.contextOptions);
|
|
766
|
+
const maxSteps = spec?.maxSteps ?? this.options.maxSteps;
|
|
657
767
|
const commonArgs = {
|
|
658
768
|
userId: args.userId,
|
|
659
769
|
threadId: args.threadId,
|
|
770
|
+
parentMessageId: args.parentMessageId,
|
|
660
771
|
...contextOptions,
|
|
661
772
|
...args.storageOptions,
|
|
662
773
|
};
|
|
663
774
|
if (args.createThread) {
|
|
664
|
-
|
|
775
|
+
const { threadId } = await this.createThread(ctx, {
|
|
665
776
|
userId: args.createThread.userId,
|
|
666
777
|
parentThreadIds: args.createThread.parentThreadIds,
|
|
667
778
|
title: args.createThread.title,
|
|
668
779
|
summary: args.createThread.summary,
|
|
669
780
|
});
|
|
670
|
-
|
|
671
|
-
return this.continueThread(ctx, {
|
|
672
|
-
threadId: args.continueThread.threadId,
|
|
673
|
-
userId: args.continueThread.userId,
|
|
674
|
-
});
|
|
781
|
+
return threadId;
|
|
675
782
|
} else if (args.generateText) {
|
|
676
|
-
|
|
783
|
+
const value = await this.generateText(ctx, commonArgs, {
|
|
677
784
|
...args.generateText,
|
|
678
785
|
maxSteps: args.generateText.maxSteps ?? maxSteps,
|
|
679
|
-
maxRetries,
|
|
680
786
|
});
|
|
787
|
+
return value.text;
|
|
681
788
|
} else if (args.streamText) {
|
|
682
|
-
|
|
789
|
+
const value = await this.streamText(ctx, commonArgs, {
|
|
683
790
|
...args.streamText,
|
|
684
791
|
maxSteps: args.streamText.maxSteps ?? maxSteps,
|
|
685
|
-
maxRetries,
|
|
686
792
|
});
|
|
793
|
+
return value.text;
|
|
687
794
|
} else if (args.generateObject) {
|
|
688
|
-
|
|
689
|
-
...args.generateObject,
|
|
690
|
-
output: args.generateObject.output ?? "string",
|
|
691
|
-
maxRetries,
|
|
795
|
+
const value = await this.generateObject(ctx, commonArgs, {
|
|
796
|
+
...(args.generateObject as GenerateObjectArgs<unknown>),
|
|
692
797
|
});
|
|
798
|
+
return value.object;
|
|
693
799
|
} else if (args.streamObject) {
|
|
694
|
-
|
|
695
|
-
...args.streamObject,
|
|
696
|
-
output: args.streamObject.output ?? "string",
|
|
697
|
-
maxRetries,
|
|
800
|
+
const value = await this.streamObject(ctx, commonArgs, {
|
|
801
|
+
...(args.streamObject as StreamObjectArgs<unknown>),
|
|
698
802
|
});
|
|
803
|
+
return value.object;
|
|
804
|
+
} else {
|
|
805
|
+
throw new Error(
|
|
806
|
+
"No action specified. Maybe try :" +
|
|
807
|
+
'generateText: { prompt: "Hello world" }'
|
|
808
|
+
);
|
|
699
809
|
}
|
|
700
810
|
},
|
|
701
811
|
});
|
|
@@ -819,16 +929,80 @@ type TextArgs<
|
|
|
819
929
|
} & ContextOptions &
|
|
820
930
|
StorageOptions;
|
|
821
931
|
|
|
822
|
-
type
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
932
|
+
type BaseGenerateObjectOptions = StorageOptions &
|
|
933
|
+
ContextOptions &
|
|
934
|
+
CallSettings & {
|
|
935
|
+
model?: LanguageModelV1;
|
|
936
|
+
parentMessageId?: string;
|
|
937
|
+
system?: string;
|
|
938
|
+
prompt?: string;
|
|
939
|
+
messages?: CoreMessage[];
|
|
940
|
+
experimental_repairText?: RepairTextFunction;
|
|
941
|
+
experimental_telemetry?: TelemetrySettings;
|
|
942
|
+
providerOptions?: ProviderOptions;
|
|
943
|
+
experimental_providerMetadata?: ProviderMetadata;
|
|
944
|
+
};
|
|
945
|
+
|
|
946
|
+
type GenerateObjectObjectOptions<T extends Record<string, unknown>> =
|
|
947
|
+
BaseGenerateObjectOptions & {
|
|
948
|
+
output: "object";
|
|
949
|
+
mode?: "auto" | "json" | "tool";
|
|
950
|
+
schema: z.Schema<T>;
|
|
951
|
+
schemaName?: string;
|
|
952
|
+
schemaDescription?: string;
|
|
953
|
+
};
|
|
954
|
+
|
|
955
|
+
type GenerateObjectArrayOptions<T> = BaseGenerateObjectOptions & {
|
|
956
|
+
output: "array";
|
|
957
|
+
mode?: "auto" | "json" | "tool";
|
|
958
|
+
schema: z.Schema<T>;
|
|
959
|
+
schemaName?: string;
|
|
960
|
+
schemaDescription?: string;
|
|
961
|
+
};
|
|
962
|
+
|
|
963
|
+
type GenerateObjectWithEnumOptions<T extends string> =
|
|
964
|
+
BaseGenerateObjectOptions & {
|
|
965
|
+
output: "enum";
|
|
966
|
+
enum: Array<T>;
|
|
967
|
+
mode?: "auto" | "json" | "tool";
|
|
968
|
+
};
|
|
969
|
+
|
|
970
|
+
type GenerateObjectNoSchemaOptions = BaseGenerateObjectOptions & {
|
|
971
|
+
schema?: undefined;
|
|
972
|
+
mode?: "json";
|
|
973
|
+
};
|
|
974
|
+
|
|
975
|
+
type GenerateObjectArgs<T> =
|
|
976
|
+
T extends Record<string, unknown>
|
|
977
|
+
? GenerateObjectObjectOptions<T>
|
|
978
|
+
: T extends Array<unknown>
|
|
979
|
+
? GenerateObjectArrayOptions<T>
|
|
980
|
+
: T extends string
|
|
981
|
+
? GenerateObjectWithEnumOptions<T>
|
|
982
|
+
: GenerateObjectNoSchemaOptions;
|
|
983
|
+
|
|
984
|
+
type StreamObjectArgs<T> =
|
|
985
|
+
T extends Record<string, unknown>
|
|
986
|
+
? GenerateObjectObjectOptions<T>
|
|
987
|
+
: T extends Array<unknown>
|
|
988
|
+
? GenerateObjectArrayOptions<T>
|
|
989
|
+
: GenerateObjectNoSchemaOptions;
|
|
990
|
+
|
|
991
|
+
type OurObjectArgs<T> = GenerateObjectArgs<T> &
|
|
992
|
+
Pick<
|
|
993
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
994
|
+
Parameters<typeof generateObject<any>>[0],
|
|
995
|
+
"experimental_repairText" | "abortSignal"
|
|
996
|
+
>;
|
|
997
|
+
|
|
998
|
+
type OurStreamObjectArgs<T> = StreamObjectArgs<T> &
|
|
999
|
+
Pick<
|
|
1000
|
+
Parameters<typeof streamObject<T>>[0],
|
|
1001
|
+
"onError" | "onFinish" | "abortSignal"
|
|
1002
|
+
>;
|
|
830
1003
|
|
|
831
1004
|
interface Thread<AgentTools extends ToolSet> {
|
|
1005
|
+
threadId: string;
|
|
832
1006
|
generateText<TOOLS extends ToolSet, OUTPUT = never, OUTPUT_PARTIAL = never>(
|
|
833
1007
|
args: TextArgs<
|
|
834
1008
|
AgentTools,
|
|
@@ -851,10 +1025,13 @@ interface Thread<AgentTools extends ToolSet> {
|
|
|
851
1025
|
>;
|
|
852
1026
|
// TODO: add all the overloads
|
|
853
1027
|
generateObject<T>(
|
|
854
|
-
args:
|
|
1028
|
+
args: OurObjectArgs<T>
|
|
855
1029
|
): Promise<GenerateObjectResult<T> & GenerationOutputMetadata>;
|
|
1030
|
+
generateObject(
|
|
1031
|
+
args: GenerateObjectNoSchemaOptions
|
|
1032
|
+
): Promise<GenerateObjectResult<JSONValue> & GenerationOutputMetadata>;
|
|
856
1033
|
streamObject<T>(
|
|
857
|
-
args:
|
|
1034
|
+
args: OurStreamObjectArgs<T>
|
|
858
1035
|
): Promise<
|
|
859
1036
|
StreamObjectResult<DeepPartial<T>, T, never> & GenerationOutputMetadata
|
|
860
1037
|
>;
|