@convex-dev/agent 0.1.16-alpha.1 → 0.1.16-alpha.3

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 (59) hide show
  1. package/README.md +26 -15
  2. package/dist/client/createTool.d.ts +2 -2
  3. package/dist/client/createTool.d.ts.map +1 -1
  4. package/dist/client/createTool.js.map +1 -1
  5. package/dist/client/files.js +2 -2
  6. package/dist/client/files.js.map +1 -1
  7. package/dist/client/index.d.ts +12 -11
  8. package/dist/client/index.d.ts.map +1 -1
  9. package/dist/client/index.js +58 -36
  10. package/dist/client/index.js.map +1 -1
  11. package/dist/client/search.d.ts +2 -3
  12. package/dist/client/search.d.ts.map +1 -1
  13. package/dist/client/search.js +2 -1
  14. package/dist/client/search.js.map +1 -1
  15. package/dist/client/types.d.ts +7 -9
  16. package/dist/client/types.d.ts.map +1 -1
  17. package/dist/component/messages.d.ts +1 -1
  18. package/dist/component/messages.d.ts.map +1 -1
  19. package/dist/component/messages.js +5 -5
  20. package/dist/component/messages.js.map +1 -1
  21. package/dist/component/schema.d.ts.map +1 -1
  22. package/dist/component/schema.js.map +1 -1
  23. package/dist/mapping.d.ts.map +1 -1
  24. package/dist/mapping.js +3 -1
  25. package/dist/mapping.js.map +1 -1
  26. package/dist/validators.js +1 -2
  27. package/dist/validators.js.map +1 -1
  28. package/package.json +1 -1
  29. package/src/client/createTool.ts +9 -6
  30. package/src/client/files.ts +8 -8
  31. package/src/client/index.test.ts +14 -12
  32. package/src/client/index.ts +156 -116
  33. package/src/client/listMessages.ts +1 -1
  34. package/src/client/search.ts +14 -14
  35. package/src/client/streaming.ts +7 -7
  36. package/src/client/types.ts +29 -23
  37. package/src/component/apiKeys.ts +1 -1
  38. package/src/component/files.test.ts +1 -1
  39. package/src/component/files.ts +6 -6
  40. package/src/component/messages.test.ts +6 -6
  41. package/src/component/messages.ts +44 -43
  42. package/src/component/schema.ts +1 -2
  43. package/src/component/streams.ts +27 -27
  44. package/src/component/threads.test.ts +4 -4
  45. package/src/component/threads.ts +4 -4
  46. package/src/component/users.test.ts +2 -2
  47. package/src/component/users.ts +4 -4
  48. package/src/component/vector/index.ts +11 -11
  49. package/src/component/vector/tables.ts +6 -6
  50. package/src/mapping.test.ts +4 -4
  51. package/src/mapping.ts +18 -17
  52. package/src/react/deltas.test.ts +16 -16
  53. package/src/react/deltas.ts +13 -13
  54. package/src/react/index.ts +11 -11
  55. package/src/react/optimisticallySendMessage.ts +2 -2
  56. package/src/react/toUIMessages.test.ts +10 -10
  57. package/src/react/toUIMessages.ts +6 -6
  58. package/src/react/useSmoothText.ts +6 -6
  59. package/src/validators.ts +24 -24
@@ -22,7 +22,7 @@ export async function listMessages(
22
22
  paginationOpts: PaginationOptions;
23
23
  excludeToolMessages?: boolean;
24
24
  statuses?: MessageStatus[];
25
- }
25
+ },
26
26
  ): Promise<PaginationResult<MessageDoc>> {
27
27
  if (args.paginationOpts.numItems === 0) {
28
28
  return {
@@ -16,9 +16,8 @@ import {
16
16
  const DEFAULT_VECTOR_SCORE_THRESHOLD = 0.0;
17
17
 
18
18
  export type GetEmbedding = (text: string) => Promise<{
19
- vector: number[];
20
- vectorModel: string;
21
- vectorScoreThreshold?: number;
19
+ embedding: number[];
20
+ embeddingModel: string;
22
21
  }>;
23
22
 
24
23
  /**
@@ -44,7 +43,7 @@ export async function fetchContextMessages(
44
43
  upToAndIncludingMessageId?: string;
45
44
  contextOptions: ContextOptions;
46
45
  getEmbedding?: GetEmbedding;
47
- }
46
+ },
48
47
  ): Promise<MessageDoc[]> {
49
48
  assert(args.userId || args.threadId, "Specify userId or threadId");
50
49
  const opts = args.contextOptions;
@@ -67,17 +66,17 @@ export async function fetchContextMessages(
67
66
  upToAndIncludingMessageId: args.upToAndIncludingMessageId,
68
67
  order: "desc",
69
68
  statuses: ["success"],
70
- }
69
+ },
71
70
  );
72
71
  included = new Set(page.map((m) => m._id));
73
72
  contextMessages.push(
74
73
  // Reverse since we fetched in descending order
75
- ...page.reverse()
74
+ ...page.reverse(),
76
75
  );
77
76
  }
78
77
  if (opts.searchOptions?.textSearch || opts.searchOptions?.vectorSearch) {
79
78
  const targetMessage = contextMessages.find(
80
- (m) => m._id === args.upToAndIncludingMessageId
79
+ (m) => m._id === args.upToAndIncludingMessageId,
81
80
  )?.message;
82
81
  const messagesToSearch = targetMessage ? [targetMessage] : args.messages;
83
82
  if (!("runAction" in ctx)) {
@@ -89,11 +88,11 @@ export async function fetchContextMessages(
89
88
  assert(text, `No text to search in message ${JSON.stringify(lastMessage)}`);
90
89
  assert(
91
90
  !args.contextOptions?.searchOptions?.vectorSearch || "runAction" in ctx,
92
- "You must do vector search from an action"
91
+ "You must do vector search from an action",
93
92
  );
94
93
  if (opts.searchOptions?.vectorSearch && !args.getEmbedding) {
95
94
  throw new Error(
96
- "You must provide an embedding and embeddingModel to use vector search"
95
+ "You must provide an embedding and embeddingModel to use vector search",
97
96
  );
98
97
  }
99
98
  const embeddingFields = opts.searchOptions?.vectorSearch
@@ -122,20 +121,21 @@ export async function fetchContextMessages(
122
121
  vectorScoreThreshold:
123
122
  opts.searchOptions?.vectorScoreThreshold ??
124
123
  DEFAULT_VECTOR_SCORE_THRESHOLD,
125
- ...embeddingFields,
126
- }
124
+ embedding: embeddingFields?.embedding,
125
+ embeddingModel: embeddingFields?.embeddingModel,
126
+ },
127
127
  );
128
128
  // TODO: track what messages we used for context
129
129
  contextMessages.unshift(
130
- ...searchMessages.filter((m) => !included?.has(m._id))
130
+ ...searchMessages.filter((m) => !included?.has(m._id)),
131
131
  );
132
132
  }
133
133
  // Ensure we don't include tool messages without a corresponding tool call
134
134
  return filterOutOrphanedToolMessages(
135
135
  contextMessages.sort((a, b) =>
136
136
  // Sort the raw MessageDocs by order and stepOrder
137
- a.order === b.order ? a.stepOrder - b.stepOrder : a.order - b.order
138
- )
137
+ a.order === b.order ? a.stepOrder - b.stepOrder : a.order - b.order,
138
+ ),
139
139
  );
140
140
  }
141
141
 
@@ -38,7 +38,7 @@ export async function syncStreams(
38
38
  streamArgs: StreamArgs | undefined;
39
39
  // By default, only streaming messages are included.
40
40
  includeStatuses?: ("streaming" | "finished" | "aborted")[];
41
- }
41
+ },
42
42
  ): Promise<SyncStreamsReturnValue | undefined> {
43
43
  if (!args.streamArgs) return undefined;
44
44
  if (args.streamArgs.kind === "list") {
@@ -66,7 +66,7 @@ export async function abortStream(
66
66
  component: AgentComponent,
67
67
  args: {
68
68
  reason: string;
69
- } & ({ streamId: string } | { threadId: string; order: number })
69
+ } & ({ streamId: string } | { threadId: string; order: number }),
70
70
  ): Promise<boolean> {
71
71
  if ("streamId" in args) {
72
72
  return await ctx.runMutation(component.streams.abort, {
@@ -102,7 +102,7 @@ export async function listStreams(
102
102
  threadId: string;
103
103
  startOrder?: number;
104
104
  includeStatuses?: ("streaming" | "finished" | "aborted")[];
105
- }
105
+ },
106
106
  ): Promise<StreamMessage[]> {
107
107
  return ctx.runQuery(component.streams.list, {
108
108
  threadId,
@@ -137,7 +137,7 @@ export function mergeTransforms<TOOLS extends ToolSet>(
137
137
  existing:
138
138
  | StreamTextTransform<TOOLS>
139
139
  | Array<StreamTextTransform<TOOLS>>
140
- | undefined
140
+ | undefined,
141
141
  ) {
142
142
  if (!options) {
143
143
  return existing;
@@ -180,7 +180,7 @@ export class DeltaStreamer {
180
180
  order: number | undefined;
181
181
  stepOrder: number | undefined;
182
182
  abortSignal: AbortSignal | undefined;
183
- }
183
+ },
184
184
  ) {
185
185
  this.options =
186
186
  typeof options === "boolean"
@@ -216,7 +216,7 @@ export class DeltaStreamer {
216
216
  ...omit(this.metadata, ["abortSignal"]),
217
217
  order: this.#nextOrder,
218
218
  stepOrder: this.#nextStepOrder,
219
- }
219
+ },
220
220
  );
221
221
  }
222
222
  this.#nextParts.push(...parts);
@@ -237,7 +237,7 @@ export class DeltaStreamer {
237
237
  try {
238
238
  const success = await this.ctx.runMutation(
239
239
  this.component.streams.addDelta,
240
- delta
240
+ delta,
241
241
  );
242
242
  if (!success) {
243
243
  this.abortController.abort();
@@ -22,13 +22,14 @@ import type {
22
22
  Auth,
23
23
  Expand,
24
24
  FunctionReference,
25
- GenericActionCtx,
26
- GenericDataModel,
27
- GenericMutationCtx,
28
- GenericQueryCtx,
29
25
  StorageActionWriter,
30
26
  StorageReader,
31
27
  WithoutSystemFields,
28
+ FunctionArgs,
29
+ FunctionReturnType,
30
+ GenericActionCtx,
31
+ GenericDataModel,
32
+ OptionalRestArgs,
32
33
  } from "convex/server";
33
34
  import type { GenericId } from "convex/values";
34
35
  import type { Schema } from "zod";
@@ -127,7 +128,7 @@ export type UsageHandler = (
127
128
  providerMetadata: ProviderMetadata | undefined;
128
129
  model: string;
129
130
  provider: string;
130
- }
131
+ },
131
132
  ) => void | Promise<void>;
132
133
 
133
134
  export type RawRequestResponseHandler = (
@@ -138,7 +139,7 @@ export type RawRequestResponseHandler = (
138
139
  agentName: string | undefined;
139
140
  request: LanguageModelRequestMetadata;
140
141
  response: LanguageModelResponseMetadata;
141
- }
142
+ },
142
143
  ) => void | Promise<void>;
143
144
 
144
145
  export type AgentComponent = UseApi<Mounts>;
@@ -335,7 +336,7 @@ export interface Thread<DefaultTools extends ToolSet> {
335
336
  * Update the metadata for the thread.
336
337
  */
337
338
  updateMetadata: (
338
- patch: Partial<WithoutSystemFields<ThreadDoc>>
339
+ patch: Partial<WithoutSystemFields<ThreadDoc>>,
339
340
  ) => Promise<ThreadDoc>;
340
341
  /**
341
342
  * This behaves like {@link generateText} from the "ai" package except that
@@ -358,7 +359,7 @@ export interface Thread<DefaultTools extends ToolSet> {
358
359
  OUTPUT,
359
360
  OUTPUT_PARTIAL
360
361
  >,
361
- options?: Options
362
+ options?: Options,
362
363
  ): Promise<
363
364
  GenerateTextResult<TOOLS extends undefined ? DefaultTools : TOOLS, OUTPUT> &
364
365
  ThreadOutputMetadata
@@ -397,7 +398,7 @@ export interface Thread<DefaultTools extends ToolSet> {
397
398
  * iterating over the text, streaming it over HTTP, etc.
398
399
  */
399
400
  saveStreamDeltas?: boolean | StreamingOptions;
400
- }
401
+ },
401
402
  ): Promise<
402
403
  StreamTextResult<
403
404
  TOOLS extends undefined ? DefaultTools : TOOLS,
@@ -417,7 +418,7 @@ export interface Thread<DefaultTools extends ToolSet> {
417
418
  */
418
419
  generateObject<T>(
419
420
  args: OurObjectArgs<T>,
420
- options?: Options
421
+ options?: Options,
421
422
  ): Promise<GenerateObjectResult<T> & ThreadOutputMetadata>;
422
423
  /**
423
424
  * This behaves like {@link generateObject} from the "ai" package except that
@@ -431,7 +432,7 @@ export interface Thread<DefaultTools extends ToolSet> {
431
432
  */
432
433
  generateObject(
433
434
  args: GenerateObjectNoSchemaOptions,
434
- options?: Options
435
+ options?: Options,
435
436
  ): Promise<GenerateObjectResult<JSONValue> & ThreadOutputMetadata>;
436
437
  /**
437
438
  * This behaves like {@link streamObject} from the "ai" package except that
@@ -445,7 +446,7 @@ export interface Thread<DefaultTools extends ToolSet> {
445
446
  */
446
447
  streamObject<T>(
447
448
  args: OurStreamObjectArgs<T>,
448
- options?: Options
449
+ options?: Options,
449
450
  ): Promise<
450
451
  StreamObjectResult<DeepPartial<T>, T, never> & ThreadOutputMetadata
451
452
  >;
@@ -469,17 +470,24 @@ export type SyncStreamsReturnValue =
469
470
 
470
471
  /* Type utils follow */
471
472
  export type RunQueryCtx = {
472
- runQuery: GenericQueryCtx<GenericDataModel>["runQuery"];
473
+ runQuery: <Query extends FunctionReference<"query", "internal">>(
474
+ query: Query,
475
+ args: FunctionArgs<Query>,
476
+ ) => Promise<FunctionReturnType<Query>>;
473
477
  };
474
- export type RunMutationCtx = {
475
- runQuery: GenericMutationCtx<GenericDataModel>["runQuery"];
476
- runMutation: GenericMutationCtx<GenericDataModel>["runMutation"];
478
+ export type RunMutationCtx = RunQueryCtx & {
479
+ runMutation: <Mutation extends FunctionReference<"mutation", "internal">>(
480
+ mutation: Mutation,
481
+ args: FunctionArgs<Mutation>,
482
+ ) => Promise<FunctionReturnType<Mutation>>;
477
483
  };
478
- export type RunActionCtx = {
479
- runQuery: GenericActionCtx<GenericDataModel>["runQuery"];
480
- runMutation: GenericActionCtx<GenericDataModel>["runMutation"];
481
- runAction: GenericActionCtx<GenericDataModel>["runAction"];
484
+ export type RunActionCtx = RunMutationCtx & {
485
+ runAction<Action extends FunctionReference<"action", "internal">>(
486
+ action: Action,
487
+ args: FunctionArgs<Action>,
488
+ ): Promise<FunctionReturnType<Action>>;
482
489
  };
490
+ export type UserActionCtx = GenericActionCtx<GenericDataModel>;
483
491
  export type ActionCtx = RunActionCtx & {
484
492
  auth: Auth;
485
493
  storage: StorageActionWriter;
@@ -496,9 +504,7 @@ export type OpaqueIds<T> =
496
504
  : T extends ArrayBuffer
497
505
  ? ArrayBuffer
498
506
  : T extends object
499
- ? {
500
- [K in keyof T]: OpaqueIds<T[K]>;
501
- }
507
+ ? { [K in keyof T]: OpaqueIds<T[K]> }
502
508
  : T;
503
509
 
504
510
  export type UseApi<API> = Expand<{
@@ -69,6 +69,6 @@ export const destroy = mutation({
69
69
  v.literal("missing"),
70
70
  v.literal("deleted"),
71
71
  v.literal("name mismatch"),
72
- v.literal("must provide either apiKey or name")
72
+ v.literal("must provide either apiKey or name"),
73
73
  ),
74
74
  });
@@ -22,7 +22,7 @@ describe("files", () => {
22
22
  hash,
23
23
  filename,
24
24
  mimeType: "text/plain",
25
- }
25
+ },
26
26
  );
27
27
  expect(fileId).toBeTruthy();
28
28
  expect(returnedStorageId).toBe(storageId);
@@ -23,7 +23,7 @@ export const addFile = mutation({
23
23
 
24
24
  export async function addFileHandler(
25
25
  ctx: MutationCtx,
26
- args: Infer<typeof addFileArgs>
26
+ args: Infer<typeof addFileArgs>,
27
27
  ) {
28
28
  const existingFile = await ctx.db
29
29
  .query("files")
@@ -93,14 +93,14 @@ export const useExistingFile = mutation({
93
93
  v.object({
94
94
  fileId: v.id("files"),
95
95
  storageId: v.string(),
96
- })
96
+ }),
97
97
  ),
98
98
  });
99
99
 
100
100
  export async function changeRefcount(
101
101
  ctx: MutationCtx,
102
102
  prev: Id<"files">[],
103
- next: Id<"files">[]
103
+ next: Id<"files">[],
104
104
  ) {
105
105
  const prevSet = new Set(prev);
106
106
  const nextSet = new Set(next);
@@ -140,7 +140,7 @@ export const copyFile = mutation({
140
140
 
141
141
  export async function copyFileHandler(
142
142
  ctx: MutationCtx,
143
- args: { fileId: Id<"files"> }
143
+ args: { fileId: Id<"files"> },
144
144
  ) {
145
145
  const file = await ctx.db.get(args.fileId);
146
146
  if (!file) {
@@ -194,14 +194,14 @@ export const deleteFiles = mutation({
194
194
  if (file.refcount && file.refcount > 0) {
195
195
  if (!args.force) {
196
196
  console.error(
197
- `File ${fileId} has refcount ${file.refcount} > 0, skipping...`
197
+ `File ${fileId} has refcount ${file.refcount} > 0, skipping...`,
198
198
  );
199
199
  return null;
200
200
  }
201
201
  }
202
202
  await ctx.db.delete(fileId);
203
203
  return fileId;
204
- })
204
+ }),
205
205
  );
206
206
  return deletedFileIds.filter((fileId) => fileId !== null);
207
207
  },
@@ -280,7 +280,7 @@ describe("agent", () => {
280
280
  patch: {
281
281
  message: { role: "user", content: "test" },
282
282
  },
283
- })
283
+ }),
284
284
  ).rejects.toThrow();
285
285
  });
286
286
 
@@ -311,7 +311,7 @@ describe("agent", () => {
311
311
  {
312
312
  threadId: thread._id as Id<"threads">,
313
313
  order: "asc",
314
- }
314
+ },
315
315
  );
316
316
  expect(remainingMessages.page).toHaveLength(1);
317
317
  expect(remainingMessages.page[0]._id).toBe(messageIds[1]);
@@ -346,7 +346,7 @@ describe("agent", () => {
346
346
  {
347
347
  threadId: thread._id as Id<"threads">,
348
348
  order: "asc",
349
- }
349
+ },
350
350
  );
351
351
  expect(remainingMessages.page).toHaveLength(0);
352
352
  });
@@ -398,7 +398,7 @@ describe("agent", () => {
398
398
  {
399
399
  threadId: thread._id as Id<"threads">,
400
400
  order: "asc",
401
- }
401
+ },
402
402
  );
403
403
 
404
404
  expect(remainingMessages.page).toHaveLength(3); // Should have messages from order 1 and 2
@@ -441,7 +441,7 @@ describe("agent", () => {
441
441
  {
442
442
  threadId: thread._id as Id<"threads">,
443
443
  order: "asc",
444
- }
444
+ },
445
445
  );
446
446
 
447
447
  expect(remainingMessages.page).toHaveLength(2);
@@ -504,7 +504,7 @@ describe("agent", () => {
504
504
  {
505
505
  threadId: thread._id as Id<"threads">,
506
506
  order: "asc",
507
- }
507
+ },
508
508
  );
509
509
  expect(remainingMessages.page).toHaveLength(1);
510
510
  });