@convex-dev/agent 0.0.1 → 0.0.3-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.
Files changed (64) hide show
  1. package/README.md +27 -0
  2. package/dist/commonjs/client/index.d.ts +792 -83
  3. package/dist/commonjs/client/index.d.ts.map +1 -1
  4. package/dist/commonjs/client/index.js +119 -155
  5. package/dist/commonjs/client/index.js.map +1 -1
  6. package/dist/commonjs/component/messages.d.ts +11 -3
  7. package/dist/commonjs/component/messages.d.ts.map +1 -1
  8. package/dist/commonjs/component/messages.js +2 -1
  9. package/dist/commonjs/component/messages.js.map +1 -1
  10. package/dist/commonjs/component/schema.d.ts +18 -12
  11. package/dist/commonjs/component/schema.d.ts.map +1 -1
  12. package/dist/commonjs/component/schema.js +1 -0
  13. package/dist/commonjs/component/schema.js.map +1 -1
  14. package/dist/commonjs/component/vector/index.d.ts.map +1 -1
  15. package/dist/commonjs/component/vector/index.js +1 -1
  16. package/dist/commonjs/component/vector/index.js.map +1 -1
  17. package/dist/commonjs/logging.d.ts +18 -0
  18. package/dist/commonjs/logging.d.ts.map +1 -0
  19. package/dist/commonjs/logging.js +78 -0
  20. package/dist/commonjs/logging.js.map +1 -0
  21. package/dist/commonjs/mapping.d.ts +3 -6
  22. package/dist/commonjs/mapping.d.ts.map +1 -1
  23. package/dist/commonjs/mapping.js +46 -20
  24. package/dist/commonjs/mapping.js.map +1 -1
  25. package/dist/commonjs/validators.d.ts +2736 -76
  26. package/dist/commonjs/validators.d.ts.map +1 -1
  27. package/dist/commonjs/validators.js +72 -7
  28. package/dist/commonjs/validators.js.map +1 -1
  29. package/dist/esm/client/index.d.ts +792 -83
  30. package/dist/esm/client/index.d.ts.map +1 -1
  31. package/dist/esm/client/index.js +119 -155
  32. package/dist/esm/client/index.js.map +1 -1
  33. package/dist/esm/component/messages.d.ts +11 -3
  34. package/dist/esm/component/messages.d.ts.map +1 -1
  35. package/dist/esm/component/messages.js +2 -1
  36. package/dist/esm/component/messages.js.map +1 -1
  37. package/dist/esm/component/schema.d.ts +18 -12
  38. package/dist/esm/component/schema.d.ts.map +1 -1
  39. package/dist/esm/component/schema.js +1 -0
  40. package/dist/esm/component/schema.js.map +1 -1
  41. package/dist/esm/component/vector/index.d.ts.map +1 -1
  42. package/dist/esm/component/vector/index.js +1 -1
  43. package/dist/esm/component/vector/index.js.map +1 -1
  44. package/dist/esm/logging.d.ts +18 -0
  45. package/dist/esm/logging.d.ts.map +1 -0
  46. package/dist/esm/logging.js +78 -0
  47. package/dist/esm/logging.js.map +1 -0
  48. package/dist/esm/mapping.d.ts +3 -6
  49. package/dist/esm/mapping.d.ts.map +1 -1
  50. package/dist/esm/mapping.js +46 -20
  51. package/dist/esm/mapping.js.map +1 -1
  52. package/dist/esm/validators.d.ts +2736 -76
  53. package/dist/esm/validators.d.ts.map +1 -1
  54. package/dist/esm/validators.js +72 -7
  55. package/dist/esm/validators.js.map +1 -1
  56. package/package.json +7 -7
  57. package/src/client/index.ts +277 -193
  58. package/src/component/_generated/api.d.ts +5 -0
  59. package/src/component/messages.ts +2 -1
  60. package/src/component/schema.ts +1 -0
  61. package/src/component/vector/index.ts +1 -7
  62. package/src/logging.ts +103 -0
  63. package/src/mapping.ts +61 -29
  64. package/src/validators.ts +102 -9
@@ -4,28 +4,29 @@ 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
- vContextOptions,
20
- vObjectArgs,
21
- vStorageOptions,
22
- vThreadArgs,
23
- } from "../validators";
24
- import { RunActionCtx, RunMutationCtx, RunQueryCtx, UseApi } from "./types";
25
20
  import { assert } from "convex-helpers";
26
- import { ConvexToZod, convexToZod } from "convex-helpers/server/zod";
21
+ import {
22
+ ConvexToZod,
23
+ convexToZod,
24
+ zodToConvex,
25
+ } from "convex-helpers/server/zod";
27
26
  import { internalActionGeneric } from "convex/server";
28
27
  import { Infer, v, Validator } from "convex/values";
28
+ import { z } from "zod";
29
+ import { api, Mounts } from "../component/_generated/api";
29
30
  import {
30
31
  validateVectorDimension,
31
32
  VectorDimension,
@@ -34,9 +35,23 @@ import {
34
35
  promptOrMessagesToCoreMessages,
35
36
  serializeMessageWithId,
36
37
  serializeNewMessagesInStep,
38
+ serializeObjectResult,
37
39
  serializeStep,
38
40
  } from "../mapping";
39
41
  import { DEFAULT_MESSAGE_RANGE, extractText } from "../shared";
42
+ import {
43
+ CallSettings,
44
+ ProviderMetadata,
45
+ ProviderOptions,
46
+ SearchOptions,
47
+ vContextOptions,
48
+ vSafeObjectArgs,
49
+ vStorageOptions,
50
+ vTextArgs,
51
+ } from "../validators";
52
+ import { RunActionCtx, RunMutationCtx, RunQueryCtx, UseApi } from "./types";
53
+
54
+ export { convexToZod, zodToConvex };
40
55
 
41
56
  export type ContextOptions = {
42
57
  /**
@@ -95,10 +110,10 @@ type CoreMessageMaybeWithId = CoreMessage & { id?: string | undefined };
95
110
 
96
111
  export class Agent<AgentTools extends ToolSet> {
97
112
  constructor(
98
- public component: UseApi<typeof api>,
113
+ public component: UseApi<Mounts>,
99
114
  public options: {
100
115
  name?: string;
101
- thread: LanguageModelV1;
116
+ chat: LanguageModelV1;
102
117
  textEmbedding?: EmbeddingModelV1<string>;
103
118
  instructions?: string;
104
119
  tools?: AgentTools;
@@ -220,6 +235,7 @@ export class Agent<AgentTools extends ToolSet> {
220
235
  // return this.component.continueThread(ctx, args);
221
236
  return {
222
237
  thread: {
238
+ threadId,
223
239
  generateText: this.generateText.bind(this, ctx, { userId, threadId }),
224
240
  streamText: this.streamText.bind(this, ctx, { userId, threadId }),
225
241
  generateObject: this.generateObject.bind(this, ctx, {
@@ -295,6 +311,9 @@ export class Agent<AgentTools extends ToolSet> {
295
311
  const textIndexes = messageTexts
296
312
  .map((t, i) => (t ? i : undefined))
297
313
  .filter((i) => i !== undefined);
314
+ if (textIndexes.length === 0) {
315
+ return undefined;
316
+ }
298
317
  // Then embed those messages.
299
318
  const textEmbeddings = await this.options.textEmbedding.doEmbed({
300
319
  values: messageTexts.filter((t): t is string => !!t),
@@ -335,7 +354,7 @@ export class Agent<AgentTools extends ToolSet> {
335
354
  threadId: args.threadId,
336
355
  userId: args.userId,
337
356
  agentName: this.options.name,
338
- model: this.options.thread.modelId,
357
+ model: this.options.chat.modelId,
339
358
  messages: args.messages.map(serializeMessageWithId),
340
359
  embeddings: await this.getEmbeddings(args.messages),
341
360
  failPendingSteps: args.failPendingSteps ?? true,
@@ -417,36 +436,20 @@ export class Agent<AgentTools extends ToolSet> {
417
436
  ): Promise<
418
437
  GenerateTextResult<TOOLS & AgentTools, OUTPUT> & GenerationOutputMetadata
419
438
  > {
420
- const { prompt, messages: raw, ...rest } = args;
421
- const messages = promptOrMessagesToCoreMessages({ prompt, messages: raw });
422
- const contextMessages = await this.fetchContextMessages(ctx, {
423
- ...args,
424
- userId,
425
- threadId,
426
- messages,
427
- });
428
- let messageId: string | undefined;
429
- if (threadId) {
430
- const saved = await this.saveMessages(ctx, {
431
- threadId,
432
- userId,
433
- messages: args.saveAllInputMessages ? messages : messages.slice(-1),
434
- pending: true,
435
- parentMessageId: args.parentMessageId,
436
- });
437
- messageId = saved.lastMessageId;
438
- }
439
+ const { args: aiArgs, messageId } = await this.saveMessagesAndFetchContext(
440
+ ctx,
441
+ { ...args, userId, threadId }
442
+ );
439
443
  const toolCtx = { ...ctx, userId, threadId, messageId };
440
444
  const tools = wrapTools(toolCtx, this.options.tools, args.tools) as TOOLS;
445
+ const maxSteps = args.maxSteps ?? this.options.maxSteps;
441
446
  try {
442
447
  const result = await generateText({
443
- model: this.options.thread,
444
- messages: [...contextMessages, ...messages],
445
- system: this.options.instructions,
446
- maxSteps: this.options.maxSteps,
448
+ model: this.options.chat,
449
+ ...aiArgs,
450
+ maxSteps,
447
451
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
448
452
  toolChoice: args.toolChoice as any,
449
- ...rest,
450
453
  tools,
451
454
  onStepFinish: async (step) => {
452
455
  if (threadId && messageId && args.saveOutputMessages !== false) {
@@ -487,35 +490,19 @@ export class Agent<AgentTools extends ToolSet> {
487
490
  ): Promise<
488
491
  StreamTextResult<TOOLS, PARTIAL_OUTPUT> & GenerationOutputMetadata
489
492
  > {
490
- const { prompt, messages: raw, ...rest } = args;
491
- const messages = promptOrMessagesToCoreMessages({ prompt, messages: raw });
492
- const contextMessages = await this.fetchContextMessages(ctx, {
493
- ...args,
494
- userId,
495
- threadId,
496
- messages,
497
- });
498
- let messageId: string | undefined;
499
- if (threadId) {
500
- const saved = await this.saveMessages(ctx, {
501
- threadId,
502
- userId,
503
- messages: args.saveAllInputMessages ? messages : messages.slice(-1),
504
- pending: true,
505
- parentMessageId: args.parentMessageId,
506
- });
507
- messageId = saved.lastMessageId;
508
- }
493
+ const { args: aiArgs, messageId } = await this.saveMessagesAndFetchContext(
494
+ ctx,
495
+ { ...args, userId, threadId }
496
+ );
509
497
  const toolCtx = { ...ctx, userId, threadId, messageId };
510
498
  const tools = wrapTools(toolCtx, this.options.tools, args.tools) as TOOLS;
499
+ const maxSteps = args.maxSteps ?? this.options.maxSteps;
511
500
  const result = streamText({
512
- model: this.options.thread,
513
- messages: [...contextMessages, ...messages],
514
- system: this.options.instructions,
515
- maxSteps: this.options.maxSteps,
501
+ model: this.options.chat,
502
+ ...aiArgs,
503
+ maxSteps,
516
504
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
517
505
  toolChoice: args.toolChoice as any,
518
- ...rest,
519
506
  tools,
520
507
  onChunk: async (chunk) => {
521
508
  // console.log("onChunk", chunk);
@@ -531,14 +518,9 @@ export class Agent<AgentTools extends ToolSet> {
531
518
  }
532
519
  return args.onError?.(error);
533
520
  },
534
- onFinish: async (result) => {
535
- result.response.messages.forEach((message) => {
536
- // console.log("onFinish", message);
537
- });
538
- return args.onFinish?.(result);
539
- },
540
521
  onStepFinish: async (step) => {
541
522
  // console.log("onStepFinish", step);
523
+ // TODO: compare delta to the output. internally drop the deltas when committing
542
524
  if (threadId && messageId) {
543
525
  await this.saveStep(ctx, {
544
526
  threadId,
@@ -552,118 +534,160 @@ export class Agent<AgentTools extends ToolSet> {
552
534
  return { ...result, messageId };
553
535
  }
554
536
 
555
- // TODO: add the crazy number of overloads to get types through
556
- async generateObject<T>(
557
- ctx: RunActionCtx,
558
- { userId, threadId }: { userId?: string; threadId?: string },
559
- args: Omit<Parameters<typeof generateObject>[0], "model"> & {
560
- model?: LanguageModelV1;
561
- } & { parentMessageId?: string } & ContextOptions &
562
- StorageOptions
563
- ): Promise<GenerateObjectResult<T> & GenerationOutputMetadata> {
564
- const { prompt, messages: raw, ...rest } = args;
565
- const messages = promptOrMessagesToCoreMessages({ prompt, messages: raw });
566
- const contextMessages = await this.fetchContextMessages(ctx, {
567
- ...args,
537
+ async saveMessagesAndFetchContext<
538
+ T extends {
539
+ prompt?: string;
540
+ messages?: CoreMessage[] | Omit<UIMessage, "id">[];
541
+ system?: string;
542
+ },
543
+ >(
544
+ ctx: RunActionCtx | RunMutationCtx,
545
+ {
568
546
  userId,
569
547
  threadId,
548
+ parentMessageId,
549
+ saveAllInputMessages,
550
+ system,
551
+ ...args
552
+ }: {
553
+ userId: string | undefined;
554
+ threadId: string | undefined;
555
+ parentMessageId?: string;
556
+ saveAllInputMessages?: boolean;
557
+ saveAnyInputMessages?: boolean;
558
+ } & ContextOptions &
559
+ T
560
+ ): Promise<{
561
+ args: T;
562
+ messageId: string | undefined;
563
+ }> {
564
+ const messages = promptOrMessagesToCoreMessages(args);
565
+ const contextMessages = await this.fetchContextMessages(ctx, {
570
566
  messages,
567
+ parentMessageId,
568
+ userId,
569
+ threadId,
570
+ ...args,
571
571
  });
572
572
  let messageId: string | undefined;
573
573
  if (threadId) {
574
574
  const saved = await this.saveMessages(ctx, {
575
575
  threadId,
576
576
  userId,
577
- messages: args.saveAllInputMessages ? messages : messages.slice(-1),
577
+ messages: saveAllInputMessages ? messages : messages.slice(-1),
578
578
  pending: true,
579
- parentMessageId: args.parentMessageId,
579
+ // We should just fail if you pass in an ID for the message, fail those children
580
+ // failPendingSteps: true,
581
+ parentMessageId,
580
582
  });
581
583
  messageId = saved.lastMessageId;
582
584
  }
583
- const result = (await generateObject({
584
- model: this.options.thread,
585
- messages: [...contextMessages, ...messages],
586
- ...rest,
587
- })) as GenerateObjectResult<T>;
588
- if (threadId && messageId && args.saveOutputMessages !== false) {
589
- // await this.saveObject(ctx, { threadId, messageId, result });
590
- }
591
- return { ...result, messageId };
585
+ const { prompt: _, ...rest } = args;
586
+ return {
587
+ args: {
588
+ ...rest,
589
+ system: system ?? this.options.instructions,
590
+ messages: [...contextMessages, ...messages],
591
+ } as T,
592
+ messageId,
593
+ };
592
594
  }
593
595
 
594
- // async saveObject<T>(
595
- // ctx: RunMutationCtx,
596
- // args: {
597
- // threadId: string;
598
- // messageId: string;
599
- // result: GenerateObjectResult<T>;
600
- // }
601
- // ): Promise<void> {
602
- // await ctx.runMutation(this.component.messages.addObject, {
603
- // threadId: args.threadId,
604
- // step: {
605
- // request: result.request,
606
- // response: {
607
- // ...result.response,
608
- // messages: [
609
- // {
610
- // role: "assistant",
611
-
612
- // content: result.object,
613
- // },
614
- // ],
615
- // },
616
- // finishReason: result.finishReason,
617
- // providerMetadata: result.providerMetadata,
618
- // usage: result.usage,
619
- // warnings: result.warnings,
620
- // },
621
- // });
622
- // }
596
+ async generateObject<T>(
597
+ ctx: RunActionCtx,
598
+ { userId, threadId }: { userId?: string; threadId?: string },
599
+ args: OurObjectArgs<T>
600
+ ): Promise<GenerateObjectResult<T> & GenerationOutputMetadata> {
601
+ const { args: aiArgs, messageId } = await this.saveMessagesAndFetchContext(
602
+ ctx,
603
+ { ...args, userId, threadId }
604
+ );
605
+
606
+ try {
607
+ const result = (await generateObject({
608
+ model: this.options.chat,
609
+ ...aiArgs,
610
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
611
+ } as any)) as GenerateObjectResult<T>;
612
+
613
+ if (threadId && messageId && args.saveOutputMessages !== false) {
614
+ await this.saveObject(ctx, { threadId, messageId, result });
615
+ }
616
+ return { ...result, messageId };
617
+ } catch (error) {
618
+ if (threadId && messageId) {
619
+ await ctx.runMutation(this.component.messages.rollbackMessage, {
620
+ messageId,
621
+ error: (error as Error).message,
622
+ });
623
+ }
624
+ throw error;
625
+ }
626
+ }
623
627
 
624
628
  async streamObject<T>(
625
629
  ctx: RunMutationCtx,
626
630
  { userId, threadId }: { userId?: string; threadId?: string },
627
- args: Omit<Parameters<typeof streamObject<T>>[0], "model"> & {
628
- model?: LanguageModelV1;
629
- } & { parentMessageId?: string } & ContextOptions &
630
- StorageOptions
631
+ args: OurStreamObjectArgs<T>
631
632
  ): Promise<
632
633
  StreamObjectResult<DeepPartial<T>, T, never> & GenerationOutputMetadata
633
634
  > {
634
635
  // TODO: unify all this shared code between all the generate* and stream* functions
635
- const { prompt, messages: raw, ...rest } = args;
636
- const messages = promptOrMessagesToCoreMessages({ prompt, messages: raw });
637
- const contextMessages = await this.fetchContextMessages(ctx, {
638
- ...args,
639
- userId,
640
- threadId,
641
- messages,
642
- });
643
- let messageId: string | undefined;
644
- if (threadId) {
645
- const saved = await this.saveMessages(ctx, {
646
- threadId,
647
- userId,
648
- messages: args.saveAllInputMessages ? messages : messages.slice(-1),
649
- pending: true,
650
- parentMessageId: args.parentMessageId,
651
- });
652
- messageId = saved.lastMessageId;
653
- }
654
- const result = streamObject<T>({
655
- model: this.options.thread,
656
- messages: [...contextMessages, ...messages],
657
- ...rest,
636
+ const { args: aiArgs, messageId } = await this.saveMessagesAndFetchContext(
637
+ ctx,
638
+ { ...args, userId, threadId }
639
+ );
640
+ const stream = streamObject<T>({
641
+ model: this.options.chat,
642
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
643
+ ...(aiArgs as any),
658
644
  onError: async (error) => {
659
645
  console.error("onError", error);
660
646
  return args.onError?.(error);
661
647
  },
662
648
  onFinish: async (result) => {
663
- // console.log("onFinish", result);
649
+ if (threadId && messageId && args.saveOutputMessages !== false) {
650
+ await this.saveObject(ctx, {
651
+ threadId,
652
+ messageId,
653
+ result: {
654
+ object: result.object,
655
+ finishReason: "stop",
656
+ usage: result.usage,
657
+ warnings: result.warnings,
658
+ request: await stream.request,
659
+ response: result.response,
660
+ providerMetadata: result.providerMetadata,
661
+ experimental_providerMetadata:
662
+ result.experimental_providerMetadata,
663
+ logprobs: undefined,
664
+ toJsonResponse: stream.toTextStreamResponse,
665
+ },
666
+ });
667
+ }
668
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
669
+ return args.onFinish?.(result as any);
664
670
  },
665
671
  }) as StreamObjectResult<DeepPartial<T>, T, never>;
666
- return { ...result, messageId };
672
+ return { ...stream, messageId };
673
+ }
674
+
675
+ async saveObject(
676
+ ctx: RunMutationCtx,
677
+ args: {
678
+ threadId: string;
679
+ messageId: string;
680
+ result: GenerateObjectResult<unknown>;
681
+ }
682
+ ): Promise<void> {
683
+ const step = serializeObjectResult(args.result);
684
+ await ctx.runMutation(this.component.messages.addStep, {
685
+ threadId: args.threadId,
686
+ messageId: args.messageId,
687
+ failPendingSteps: false,
688
+ embeddings: await this.getEmbeddings([step.messages[0].message]),
689
+ step,
690
+ });
667
691
  }
668
692
 
669
693
  mergedContextOptions(opts: ContextOptions): ContextOptions {
@@ -717,7 +741,7 @@ export class Agent<AgentTools extends ToolSet> {
717
741
  /**
718
742
  *
719
743
  */
720
- asAction(spec: { contextOptions?: ContextOptions; maxSteps?: number }) {
744
+ asAction(spec?: { contextOptions?: ContextOptions; maxSteps?: number }) {
721
745
  return internalActionGeneric({
722
746
  args: {
723
747
  userId: v.optional(v.string()),
@@ -725,6 +749,7 @@ export class Agent<AgentTools extends ToolSet> {
725
749
  contextOptions: v.optional(vContextOptions),
726
750
  storageOptions: v.optional(vStorageOptions),
727
751
  maxRetries: v.optional(v.number()),
752
+ parentMessageId: v.optional(v.string()),
728
753
 
729
754
  createThread: v.optional(
730
755
  v.object({
@@ -734,67 +759,59 @@ export class Agent<AgentTools extends ToolSet> {
734
759
  summary: v.optional(v.string()),
735
760
  })
736
761
  ),
737
- continueThread: v.optional(
738
- v.object({
739
- threadId: v.string(),
740
- userId: v.optional(v.string()),
741
- })
742
- ),
743
- generateText: v.optional(vThreadArgs),
744
- streamText: v.optional(vThreadArgs),
745
- generateObject: v.optional(vObjectArgs),
746
- streamObject: v.optional(
747
- v.object({ ...vObjectArgs.fields, schema: v.any() })
748
- ),
762
+ generateText: v.optional(vTextArgs),
763
+ streamText: v.optional(vTextArgs),
764
+ generateObject: v.optional(vSafeObjectArgs),
765
+ streamObject: v.optional(vSafeObjectArgs),
749
766
  },
750
767
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
751
768
  handler: async (ctx, args): Promise<any> => {
752
769
  const contextOptions =
753
- spec.contextOptions && this.mergedContextOptions(spec.contextOptions);
754
- const maxSteps = spec.maxSteps ?? this.options.maxSteps;
755
- const maxRetries = args.maxRetries;
770
+ spec?.contextOptions &&
771
+ this.mergedContextOptions(spec.contextOptions);
772
+ const maxSteps = spec?.maxSteps ?? this.options.maxSteps;
756
773
  const commonArgs = {
757
774
  userId: args.userId,
758
775
  threadId: args.threadId,
776
+ parentMessageId: args.parentMessageId,
759
777
  ...contextOptions,
760
778
  ...args.storageOptions,
761
779
  };
762
780
  if (args.createThread) {
763
- return this.createThread(ctx, {
781
+ const { threadId } = await this.createThread(ctx, {
764
782
  userId: args.createThread.userId,
765
783
  parentThreadIds: args.createThread.parentThreadIds,
766
784
  title: args.createThread.title,
767
785
  summary: args.createThread.summary,
768
786
  });
769
- } else if (args.continueThread) {
770
- return this.continueThread(ctx, {
771
- threadId: args.continueThread.threadId,
772
- userId: args.continueThread.userId,
773
- });
787
+ return threadId;
774
788
  } else if (args.generateText) {
775
- return this.generateText(ctx, commonArgs, {
789
+ const value = await this.generateText(ctx, commonArgs, {
776
790
  ...args.generateText,
777
791
  maxSteps: args.generateText.maxSteps ?? maxSteps,
778
- maxRetries,
779
792
  });
793
+ return value.text;
780
794
  } else if (args.streamText) {
781
- return this.streamText(ctx, commonArgs, {
795
+ const value = await this.streamText(ctx, commonArgs, {
782
796
  ...args.streamText,
783
797
  maxSteps: args.streamText.maxSteps ?? maxSteps,
784
- maxRetries,
785
798
  });
799
+ return value.text;
786
800
  } else if (args.generateObject) {
787
- return this.generateObject(ctx, commonArgs, {
788
- ...args.generateObject,
789
- output: args.generateObject.output ?? "string",
790
- maxRetries,
801
+ const value = await this.generateObject(ctx, commonArgs, {
802
+ ...(args.generateObject as GenerateObjectArgs<unknown>),
791
803
  });
804
+ return value.object;
792
805
  } else if (args.streamObject) {
793
- return this.streamObject(ctx, commonArgs, {
794
- ...args.streamObject,
795
- output: args.streamObject.output ?? "string",
796
- maxRetries,
806
+ const value = await this.streamObject(ctx, commonArgs, {
807
+ ...(args.streamObject as StreamObjectArgs<unknown>),
797
808
  });
809
+ return value.object;
810
+ } else {
811
+ throw new Error(
812
+ "No action specified. Maybe try :" +
813
+ 'generateText: { prompt: "Hello world" }'
814
+ );
798
815
  }
799
816
  },
800
817
  });
@@ -918,16 +935,80 @@ type TextArgs<
918
935
  } & ContextOptions &
919
936
  StorageOptions;
920
937
 
921
- type ObjectArgs<
922
- T extends {
923
- model: LanguageModelV1;
924
- },
925
- > = Omit<T, "model"> & {
926
- model?: LanguageModelV1;
927
- } & ContextOptions &
928
- StorageOptions;
938
+ type BaseGenerateObjectOptions = StorageOptions &
939
+ ContextOptions &
940
+ CallSettings & {
941
+ model?: LanguageModelV1;
942
+ parentMessageId?: string;
943
+ system?: string;
944
+ prompt?: string;
945
+ messages?: CoreMessage[];
946
+ experimental_repairText?: RepairTextFunction;
947
+ experimental_telemetry?: TelemetrySettings;
948
+ providerOptions?: ProviderOptions;
949
+ experimental_providerMetadata?: ProviderMetadata;
950
+ };
951
+
952
+ type GenerateObjectObjectOptions<T extends Record<string, unknown>> =
953
+ BaseGenerateObjectOptions & {
954
+ output: "object";
955
+ mode?: "auto" | "json" | "tool";
956
+ schema: z.Schema<T>;
957
+ schemaName?: string;
958
+ schemaDescription?: string;
959
+ };
960
+
961
+ type GenerateObjectArrayOptions<T> = BaseGenerateObjectOptions & {
962
+ output: "array";
963
+ mode?: "auto" | "json" | "tool";
964
+ schema: z.Schema<T>;
965
+ schemaName?: string;
966
+ schemaDescription?: string;
967
+ };
968
+
969
+ type GenerateObjectWithEnumOptions<T extends string> =
970
+ BaseGenerateObjectOptions & {
971
+ output: "enum";
972
+ enum: Array<T>;
973
+ mode?: "auto" | "json" | "tool";
974
+ };
975
+
976
+ type GenerateObjectNoSchemaOptions = BaseGenerateObjectOptions & {
977
+ schema?: undefined;
978
+ mode?: "json";
979
+ };
980
+
981
+ type GenerateObjectArgs<T> =
982
+ T extends Record<string, unknown>
983
+ ? GenerateObjectObjectOptions<T>
984
+ : T extends Array<unknown>
985
+ ? GenerateObjectArrayOptions<T>
986
+ : T extends string
987
+ ? GenerateObjectWithEnumOptions<T>
988
+ : GenerateObjectNoSchemaOptions;
989
+
990
+ type StreamObjectArgs<T> =
991
+ T extends Record<string, unknown>
992
+ ? GenerateObjectObjectOptions<T>
993
+ : T extends Array<unknown>
994
+ ? GenerateObjectArrayOptions<T>
995
+ : GenerateObjectNoSchemaOptions;
996
+
997
+ type OurObjectArgs<T> = GenerateObjectArgs<T> &
998
+ Pick<
999
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1000
+ Parameters<typeof generateObject<any>>[0],
1001
+ "experimental_repairText" | "abortSignal"
1002
+ >;
1003
+
1004
+ type OurStreamObjectArgs<T> = StreamObjectArgs<T> &
1005
+ Pick<
1006
+ Parameters<typeof streamObject<T>>[0],
1007
+ "onError" | "onFinish" | "abortSignal"
1008
+ >;
929
1009
 
930
1010
  interface Thread<AgentTools extends ToolSet> {
1011
+ threadId: string;
931
1012
  generateText<TOOLS extends ToolSet, OUTPUT = never, OUTPUT_PARTIAL = never>(
932
1013
  args: TextArgs<
933
1014
  AgentTools,
@@ -950,10 +1031,13 @@ interface Thread<AgentTools extends ToolSet> {
950
1031
  >;
951
1032
  // TODO: add all the overloads
952
1033
  generateObject<T>(
953
- args: ObjectArgs<Parameters<typeof generateObject>[0]>
1034
+ args: OurObjectArgs<T>
954
1035
  ): Promise<GenerateObjectResult<T> & GenerationOutputMetadata>;
1036
+ generateObject(
1037
+ args: GenerateObjectNoSchemaOptions
1038
+ ): Promise<GenerateObjectResult<JSONValue> & GenerationOutputMetadata>;
955
1039
  streamObject<T>(
956
- args: ObjectArgs<Parameters<typeof streamObject<T>>[0]>
1040
+ args: OurStreamObjectArgs<T>
957
1041
  ): Promise<
958
1042
  StreamObjectResult<DeepPartial<T>, T, never> & GenerationOutputMetadata
959
1043
  >;