@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.
Files changed (66) hide show
  1. package/README.md +35 -7
  2. package/dist/commonjs/client/index.d.ts +800 -84
  3. package/dist/commonjs/client/index.d.ts.map +1 -1
  4. package/dist/commonjs/client/index.js +176 -130
  5. package/dist/commonjs/client/index.js.map +1 -1
  6. package/dist/commonjs/component/messages.d.ts +124 -105
  7. package/dist/commonjs/component/messages.d.ts.map +1 -1
  8. package/dist/commonjs/component/messages.js +145 -247
  9. package/dist/commonjs/component/messages.js.map +1 -1
  10. package/dist/commonjs/component/schema.d.ts +822 -746
  11. package/dist/commonjs/component/schema.d.ts.map +1 -1
  12. package/dist/commonjs/component/schema.js +13 -3
  13. package/dist/commonjs/component/schema.js.map +1 -1
  14. package/dist/commonjs/component/vector/index.d.ts +21 -6
  15. package/dist/commonjs/component/vector/index.d.ts.map +1 -1
  16. package/dist/commonjs/component/vector/index.js +32 -20
  17. package/dist/commonjs/component/vector/index.js.map +1 -1
  18. package/dist/commonjs/component/vector/tables.d.ts +25 -5
  19. package/dist/commonjs/component/vector/tables.d.ts.map +1 -1
  20. package/dist/commonjs/component/vector/tables.js +14 -6
  21. package/dist/commonjs/component/vector/tables.js.map +1 -1
  22. package/dist/commonjs/mapping.d.ts +3 -2
  23. package/dist/commonjs/mapping.d.ts.map +1 -1
  24. package/dist/commonjs/mapping.js +45 -13
  25. package/dist/commonjs/mapping.js.map +1 -1
  26. package/dist/commonjs/validators.d.ts +2817 -145
  27. package/dist/commonjs/validators.d.ts.map +1 -1
  28. package/dist/commonjs/validators.js +79 -7
  29. package/dist/commonjs/validators.js.map +1 -1
  30. package/dist/esm/client/index.d.ts +800 -84
  31. package/dist/esm/client/index.d.ts.map +1 -1
  32. package/dist/esm/client/index.js +176 -130
  33. package/dist/esm/client/index.js.map +1 -1
  34. package/dist/esm/component/messages.d.ts +124 -105
  35. package/dist/esm/component/messages.d.ts.map +1 -1
  36. package/dist/esm/component/messages.js +145 -247
  37. package/dist/esm/component/messages.js.map +1 -1
  38. package/dist/esm/component/schema.d.ts +822 -746
  39. package/dist/esm/component/schema.d.ts.map +1 -1
  40. package/dist/esm/component/schema.js +13 -3
  41. package/dist/esm/component/schema.js.map +1 -1
  42. package/dist/esm/component/vector/index.d.ts +21 -6
  43. package/dist/esm/component/vector/index.d.ts.map +1 -1
  44. package/dist/esm/component/vector/index.js +32 -20
  45. package/dist/esm/component/vector/index.js.map +1 -1
  46. package/dist/esm/component/vector/tables.d.ts +25 -5
  47. package/dist/esm/component/vector/tables.d.ts.map +1 -1
  48. package/dist/esm/component/vector/tables.js +14 -6
  49. package/dist/esm/component/vector/tables.js.map +1 -1
  50. package/dist/esm/mapping.d.ts +3 -2
  51. package/dist/esm/mapping.d.ts.map +1 -1
  52. package/dist/esm/mapping.js +45 -13
  53. package/dist/esm/mapping.js.map +1 -1
  54. package/dist/esm/validators.d.ts +2817 -145
  55. package/dist/esm/validators.d.ts.map +1 -1
  56. package/dist/esm/validators.js +79 -7
  57. package/dist/esm/validators.js.map +1 -1
  58. package/package.json +7 -7
  59. package/src/client/index.ts +347 -170
  60. package/src/component/_generated/api.d.ts +33 -16
  61. package/src/component/messages.ts +177 -290
  62. package/src/component/schema.ts +14 -3
  63. package/src/component/vector/index.ts +59 -26
  64. package/src/component/vector/tables.ts +38 -6
  65. package/src/mapping.ts +60 -19
  66. package/src/validators.ts +112 -12
@@ -17,16 +17,17 @@ export const schema = defineSchema({
17
17
  // the parent thread(s). There are multiple if the thread is a merging of
18
18
  // multiple threads.
19
19
  parentThreadIds: v.optional(v.array(v.id("threads"))),
20
- }).index("status_userId_order", ["status", "userId", "order"]),
20
+ }).index("userId_status_order", ["userId", "status", "order"]),
21
21
  // TODO: text search on title/ summary
22
22
  messages: defineTable({
23
23
  id: v.optional(v.string()), // external id, e.g. from Vercel AI SDK
24
24
  userId: v.optional(v.string()), // useful for future indexes (text search)
25
- threadId: v.optional(v.id("threads")),
25
+ threadId: v.id("threads"),
26
26
  parentMessageId: v.optional(v.id("messages")),
27
27
  stepId: v.optional(v.id("steps")),
28
28
  agentName: v.optional(v.string()),
29
29
  message: v.optional(vMessage),
30
+ error: v.optional(v.string()),
30
31
  model: v.optional(v.string()),
31
32
  text: v.optional(v.string()),
32
33
  embeddingId: v.optional(vVectorId),
@@ -35,7 +36,7 @@ export const schema = defineSchema({
35
36
  // Repeats until a non-tool message.
36
37
  // Unset if it's not in a thread.
37
38
  order: v.number(),
38
- stepOrder: v.optional(v.number()),
39
+ stepOrder: v.number(),
39
40
  fileId: v.optional(v.id("files")),
40
41
  status: vMessageStatus,
41
42
  })
@@ -92,6 +93,16 @@ export const schema = defineSchema({
92
93
  "stepOrder",
93
94
  ]),
94
95
 
96
+ memories: defineTable({
97
+ threadId: v.optional(v.id("threads")),
98
+ userId: v.optional(v.string()),
99
+ memory: v.string(),
100
+ embeddingId: v.optional(vVectorId),
101
+ })
102
+ .index("threadId", ["threadId"])
103
+ .index("userId", ["userId"])
104
+ .index("embeddingId", ["embeddingId"]),
105
+
95
106
  files: defineTable({
96
107
  storageId: v.string(),
97
108
  hash: v.string(),
@@ -1,7 +1,14 @@
1
1
  import { paginator } from "convex-helpers/server/pagination";
2
2
  import { v } from "convex/values";
3
- import { mutation, query } from "../_generated/server";
4
- import { getVectorTableName, vVectorDimension, vVectorId } from "./tables";
3
+ import { ActionCtx, mutation, MutationCtx, query } from "../_generated/server";
4
+ import {
5
+ EmbeddingsWithoutDenormalizedFields,
6
+ getVectorTableName,
7
+ VectorDimension,
8
+ vEmbeddingsWithoutDenormalizedFields,
9
+ vVectorDimension,
10
+ vVectorId,
11
+ } from "./tables";
5
12
  import schema from "../schema";
6
13
  import { mergedStream } from "convex-helpers/server/stream";
7
14
  import { stream } from "convex-helpers/server/stream";
@@ -10,6 +17,7 @@ export const paginate = query({
10
17
  args: {
11
18
  vectorDimension: vVectorDimension,
12
19
  targetModel: v.string(),
20
+ table: v.optional(v.string()),
13
21
  cursor: v.optional(v.string()),
14
22
  limit: v.number(),
15
23
  },
@@ -23,8 +31,11 @@ export const paginate = query({
23
31
  const vectors = await paginator(ctx.db, schema)
24
32
  .query(tableName)
25
33
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
26
- .withIndex("model_kind_threadId" as any, (q) =>
27
- q.eq("model", args.targetModel)
34
+ .withIndex("model_table_threadId" as any, (q) =>
35
+ args.table
36
+ ? // eslint-disable-next-line @typescript-eslint/no-explicit-any
37
+ (q.eq("model", args.targetModel) as any).eq("table", args.table)
38
+ : q.eq("model", args.targetModel)
28
39
  )
29
40
  .paginate({
30
41
  cursor: args.cursor ?? null,
@@ -82,36 +93,58 @@ export const deleteBatchForThread = mutation({
82
93
  export const insertBatch = mutation({
83
94
  args: {
84
95
  vectorDimension: vVectorDimension,
85
- vectors: v.array(
86
- v.object({
87
- model: v.string(),
88
- kind: v.union(v.literal("thread"), v.literal("memory")),
89
- userId: v.optional(v.string()),
90
- threadId: v.optional(v.string()),
91
- vector: v.array(v.number()),
92
- })
93
- ),
96
+ vectors: v.array(vEmbeddingsWithoutDenormalizedFields),
94
97
  },
95
98
  returns: v.null(),
96
99
  handler: async (ctx, args) => {
97
100
  await Promise.all(
98
- args.vectors.map((v) =>
99
- ctx.db.insert(getVectorTableName(args.vectorDimension), {
100
- model: v.model,
101
- kind: v.kind,
102
- userId: v.userId,
103
- threadId: v.threadId,
104
- vector: v.vector,
105
- model_kind_userId: v.userId ? [v.model, v.kind, v.userId] : undefined,
106
- model_kind_threadId: v.threadId
107
- ? [v.model, v.kind, v.threadId]
108
- : undefined,
109
- })
110
- )
101
+ args.vectors.map((v) => insertVector(ctx, args.vectorDimension, v))
111
102
  );
112
103
  },
113
104
  });
114
105
 
106
+ export async function insertVector(
107
+ ctx: MutationCtx,
108
+ dimension: VectorDimension,
109
+ v: EmbeddingsWithoutDenormalizedFields
110
+ ) {
111
+ return ctx.db.insert(getVectorTableName(dimension), {
112
+ ...v,
113
+ model_table_userId: v.userId ? [v.model, v.table, v.userId] : undefined,
114
+ model_table_threadId: v.threadId
115
+ ? [v.model, v.table, v.threadId]
116
+ : undefined,
117
+ });
118
+ }
119
+
120
+ export function searchVectors(
121
+ ctx: ActionCtx,
122
+ vector: number[],
123
+ args: {
124
+ dimension: VectorDimension;
125
+ model: string;
126
+ table: string;
127
+ userId?: string;
128
+ threadId?: string;
129
+ limit?: number;
130
+ }
131
+ ) {
132
+ const tableName = getVectorTableName(args.dimension);
133
+ return ctx.vectorSearch(tableName, "vector", {
134
+ vector,
135
+ // TODO: to support more tables, add more "OR" clauses for each.
136
+ filter: (q) =>
137
+ args.userId
138
+ ? q.eq("model_table_userId", [args.model, args.table, args.userId])
139
+ : q.eq("model_table_threadId", [
140
+ args.model,
141
+ args.table,
142
+ args.threadId!,
143
+ ]),
144
+ limit: args.limit,
145
+ });
146
+ }
147
+
115
148
  export const updateBatch = mutation({
116
149
  args: {
117
150
  vectors: v.array(
@@ -1,37 +1,69 @@
1
+ import { omit } from "convex-helpers";
1
2
  import { literals } from "convex-helpers/validators";
2
3
  import {
3
4
  defineTable,
4
5
  GenericTableSearchIndexes,
6
+ SchemaDefinition,
5
7
  TableDefinition,
6
8
  } from "convex/server";
7
- import { GenericId, ObjectType, v, VId, VObject, VUnion } from "convex/values";
9
+ import {
10
+ GenericId,
11
+ Infer,
12
+ ObjectType,
13
+ v,
14
+ VId,
15
+ VObject,
16
+ VUnion,
17
+ } from "convex/values";
8
18
  import { QueryCtx } from "../_generated/server";
9
19
 
10
20
  // We only generate embeddings for non-tool, non-system messages
11
21
  const embeddings = {
12
22
  model: v.string(),
13
- kind: v.union(v.literal("thread"), v.literal("memory")),
23
+ // What table it's stored in. (usually messages or memories)
24
+ table: v.string(),
14
25
  userId: v.optional(v.string()),
15
26
  threadId: v.optional(v.string()),
16
27
  // not set for private threads
17
- model_kind_userId: v.optional(v.array(v.string())),
18
- model_kind_threadId: v.optional(v.array(v.string())),
28
+ model_table_userId: v.optional(v.array(v.string())),
29
+ model_table_threadId: v.optional(v.array(v.string())),
19
30
  vector: v.array(v.number()),
20
31
  };
21
32
 
33
+ export const vEmbeddingsWithoutDenormalizedFields = v.object(
34
+ omit(embeddings, ["model_table_userId", "model_table_threadId"])
35
+ );
36
+ export type EmbeddingsWithoutDenormalizedFields = Infer<
37
+ typeof vEmbeddingsWithoutDenormalizedFields
38
+ >;
39
+
22
40
  function table<D extends number>(dimensions: D): Table<D> {
23
41
  return defineTable(embeddings)
24
42
  .vectorIndex("vector", {
25
43
  vectorField: "vector",
26
44
  dimensions,
27
- filterFields: ["model_kind_userId", "model_kind_threadId"],
45
+ filterFields: ["model_table_userId", "model_table_threadId"],
28
46
  })
29
- .index("model_kind_threadId", ["model", "kind", "threadId"]);
47
+ .index("model_table_threadId", ["model", "table", "threadId"]);
30
48
  }
31
49
 
50
+ export type VectorSchema = SchemaDefinition<
51
+ { [key in VectorTableName]: Table<128> },
52
+ true
53
+ >;
54
+
32
55
  export const VectorDimensions = [
33
56
  128, 256, 512, 768, 1024, 1536, 2048, 3072, 4096,
34
57
  ] as const;
58
+ export function validateVectorDimension(
59
+ dimension: number
60
+ ): asserts dimension is VectorDimension {
61
+ if (!VectorDimensions.includes(dimension as VectorDimension)) {
62
+ throw new Error(
63
+ `Unsupported vector dimension${dimension}. Supported: ${VectorDimensions.join(", ")}`
64
+ );
65
+ }
66
+ }
35
67
  export type VectorDimension = (typeof VectorDimensions)[number];
36
68
  export const VectorTableNames = VectorDimensions.map(
37
69
  (d) => `embeddings_${d}`
package/src/mapping.ts CHANGED
@@ -1,10 +1,9 @@
1
1
  import {
2
2
  convertToCoreMessages,
3
3
  coreMessageSchema,
4
+ GenerateObjectResult,
4
5
  type AssistantContent,
5
- type CoreAssistantMessage,
6
6
  type CoreMessage,
7
- type CoreToolMessage,
8
7
  type DataContent,
9
8
  type GenerateTextResult,
10
9
  type StepResult,
@@ -13,8 +12,12 @@ import {
13
12
  type Message as UIMessage,
14
13
  type UserContent,
15
14
  } from "ai";
16
- import { MessageWithFileAndId, Step } from "./validators";
17
15
  import { assert } from "convex-helpers";
16
+ import {
17
+ MessageWithFileAndId,
18
+ Step,
19
+ StepWithMessagesWithFileAndId,
20
+ } from "./validators";
18
21
 
19
22
  export type SerializeUrlsAndUint8Arrays<T> = T extends URL
20
23
  ? string
@@ -115,6 +118,41 @@ export function serializeNewMessagesInStep<TOOLS extends ToolSet>(
115
118
  return messages;
116
119
  }
117
120
 
121
+ export function serializeObjectResult(
122
+ result: GenerateObjectResult<unknown>
123
+ ): StepWithMessagesWithFileAndId {
124
+ const text = JSON.stringify(result.object);
125
+ const serializedMessage = serializeMessageWithId({
126
+ role: "assistant" as const,
127
+ content: text,
128
+ id: result.response.id,
129
+ });
130
+
131
+ const messages = [serializedMessage];
132
+
133
+ return {
134
+ messages,
135
+ step: {
136
+ text,
137
+ isContinued: false,
138
+ stepType: "initial",
139
+ toolCalls: [],
140
+ toolResults: [],
141
+ usage: result.usage,
142
+ warnings: result.warnings,
143
+ finishReason: result.finishReason,
144
+ request: result.request,
145
+ response: {
146
+ ...result.response,
147
+ timestamp: result.response.timestamp.getTime(),
148
+ messages,
149
+ },
150
+ providerMetadata: result.providerMetadata,
151
+ experimental_providerMetadata: result.experimental_providerMetadata,
152
+ },
153
+ };
154
+ }
155
+
118
156
  export function deserializeContent(content: SerializedContent): Content {
119
157
  if (typeof content === "string") {
120
158
  return content;
@@ -172,23 +210,26 @@ export function promptOrMessagesToCoreMessages(args: {
172
210
  if (args.system) {
173
211
  messages.push({ role: "system", content: args.system });
174
212
  }
175
- if (!args.messages) {
176
- assert(args.prompt, "messages or prompt is required");
213
+ assert(args.prompt || args.messages, "messages or prompt is required");
214
+ if (args.messages) {
215
+ if (
216
+ args.messages.some(
217
+ (m) =>
218
+ typeof m === "object" &&
219
+ m !== null &&
220
+ (m.role === "data" || // UI-only role
221
+ "toolInvocations" in m || // UI-specific field
222
+ "parts" in m || // UI-specific field
223
+ "experimental_attachments" in m)
224
+ )
225
+ ) {
226
+ messages.push(...convertToCoreMessages(args.messages as UIMessage[]));
227
+ } else {
228
+ messages.push(...coreMessageSchema.array().parse(args.messages));
229
+ }
230
+ }
231
+ if (args.prompt) {
177
232
  messages.push({ role: "user", content: args.prompt });
178
- } else if (
179
- args.messages.some(
180
- (m) =>
181
- typeof m === "object" &&
182
- m !== null &&
183
- (m.role === "data" || // UI-only role
184
- "toolInvocations" in m || // UI-specific field
185
- "parts" in m || // UI-specific field
186
- "experimental_attachments" in m)
187
- )
188
- ) {
189
- messages.push(...convertToCoreMessages(args.messages as UIMessage[]));
190
- } else {
191
- messages.push(...coreMessageSchema.array().parse(args.messages));
192
233
  }
193
234
  assert(messages.length > 0, "Messages must contain at least one message");
194
235
  return messages;
package/src/validators.ts CHANGED
@@ -1,9 +1,12 @@
1
- import { Infer, v } from "convex/values";
1
+ import { Infer, ObjectType, v } from "convex/values";
2
+ import { vVectorDimension } from "./component/vector/tables";
2
3
 
3
4
  // const deprecated = v.optional(v.any()) as unknown as VNull<unknown, "optional">;
4
5
 
5
6
  const providerOptions = v.optional(v.record(v.string(), v.any()));
7
+ export type ProviderOptions = Infer<typeof providerOptions>;
6
8
  const experimental_providerMetadata = providerOptions;
9
+ export type ProviderMetadata = Infer<typeof experimental_providerMetadata>;
7
10
 
8
11
  export const vThreadStatus = v.union(
9
12
  v.literal("active"),
@@ -185,6 +188,14 @@ export const vResponse = v.object({
185
188
  body: v.optional(v.any()),
186
189
  });
187
190
 
191
+ export const vResponseWithoutMessages = v.object({
192
+ id: v.string(),
193
+ timestamp: v.number(),
194
+ modelId: v.string(),
195
+ headers: v.optional(v.record(v.string(), v.string())), // clear these?
196
+ body: v.optional(v.any()),
197
+ });
198
+
188
199
  export const vFinishReason = v.union(
189
200
  v.literal("stop"),
190
201
  v.literal("length"),
@@ -243,19 +254,30 @@ export const vStep = v.object({
243
254
  });
244
255
  export type Step = Infer<typeof vStep>;
245
256
 
246
- export const vStepWithMessagesWithFileAndId = v.object({
257
+ export const vStepWithMessages = v.object({
247
258
  step: vStep,
248
259
  messages: v.array(vMessageWithFileAndId),
249
260
  });
250
- export type StepWithMessagesWithFileAndId = Infer<
251
- typeof vStepWithMessagesWithFileAndId
252
- >;
261
+ export type StepWithMessagesWithFileAndId = Infer<typeof vStepWithMessages>;
253
262
 
263
+ export const vObjectResult = v.object({
264
+ request: vRequest,
265
+ response: vResponseWithoutMessages,
266
+ finishReason: vFinishReason,
267
+ usage: v.optional(v.any()),
268
+ object: v.any(),
269
+ error: v.optional(v.string()),
270
+ warnings: v.optional(v.array(vLanguageModelV1CallWarning)),
271
+ providerMetadata: providerOptions,
272
+ experimental_providerMetadata,
273
+ });
274
+ export type ObjectResult = Infer<typeof vObjectResult>;
254
275
  export const vSearchOptions = v.object({
255
276
  vector: v.optional(v.array(v.number())),
256
277
  vectorModel: v.optional(v.string()),
257
278
  text: v.optional(v.string()),
258
279
  limit: v.number(),
280
+ vectorScoreThreshold: v.optional(v.number()),
259
281
  messageRange: v.optional(v.object({ before: v.number(), after: v.number() })),
260
282
  });
261
283
  export type SearchOptions = Infer<typeof vSearchOptions>;
@@ -279,15 +301,93 @@ export const vStorageOptions = v.object({
279
301
  saveAllOutputMessages: v.optional(v.boolean()),
280
302
  });
281
303
 
282
- export const vThreadArgs = v.object({
283
- maxSteps: v.optional(v.number()),
304
+ const vPromptFields = {
305
+ system: v.optional(v.string()),
284
306
  prompt: v.optional(v.string()),
285
307
  messages: v.optional(v.array(vMessage)),
308
+ };
309
+
310
+ export const vCallSettingsFields = {
311
+ maxTokens: v.optional(v.number()),
312
+ temperature: v.optional(v.number()),
313
+ topP: v.optional(v.number()),
314
+ topK: v.optional(v.number()),
315
+ presencePenalty: v.optional(v.number()),
316
+ frequencyPenalty: v.optional(v.number()),
317
+ seed: v.optional(v.number()),
318
+ maxRetries: v.optional(v.number()),
319
+ headers: v.optional(v.record(v.string(), v.string())),
320
+ };
321
+ export type CallSettings = ObjectType<typeof vCallSettingsFields>;
322
+
323
+ export const vTextArgs = v.object({
324
+ ...vCallSettingsFields,
325
+ ...vPromptFields,
326
+ toolChoice: v.optional(
327
+ v.union(
328
+ v.literal("auto"),
329
+ v.literal("none"),
330
+ v.literal("required"),
331
+ v.object({
332
+ type: v.literal("tool"),
333
+ toolName: v.string(),
334
+ })
335
+ )
336
+ ),
337
+ maxSteps: v.optional(v.number()),
338
+ experimental_continueSteps: v.optional(v.boolean()),
339
+ providerOptions,
340
+ experimental_providerMetadata,
286
341
  });
342
+ export type TextArgs = Infer<typeof vTextArgs>;
287
343
 
288
- export const vObjectArgs = v.object({
289
- output: v.optional(v.any()),
290
- mode: v.optional(v.literal("json")),
291
- prompt: v.optional(v.string()),
292
- messages: v.optional(v.array(vMessage)),
344
+ const objectArgsCommonFields = {
345
+ ...vCallSettingsFields,
346
+ ...vPromptFields,
347
+ providerOptions,
348
+ experimental_providerMetadata,
349
+ };
350
+
351
+ export const vSafeObjectArgs = v.union(
352
+ v.object({
353
+ ...objectArgsCommonFields,
354
+ output: v.optional(v.literal("object")),
355
+ schema: v.any(), // JSON schema
356
+ schemaName: v.optional(v.string()),
357
+ schemaDescription: v.optional(v.string()),
358
+ mode: v.optional(
359
+ v.union(v.literal("auto"), v.literal("json"), v.literal("tool"))
360
+ ),
361
+ }),
362
+ v.object({
363
+ ...objectArgsCommonFields,
364
+ output: v.optional(v.literal("array")),
365
+ schema: v.any(), // JSON schema
366
+ schemaName: v.optional(v.string()),
367
+ schemaDescription: v.optional(v.string()),
368
+ mode: v.optional(
369
+ v.union(v.literal("auto"), v.literal("json"), v.literal("tool"))
370
+ ),
371
+ }),
372
+ v.object({
373
+ ...objectArgsCommonFields,
374
+ output: v.optional(v.literal("enum")),
375
+ enum: v.array(v.string()),
376
+ mode: v.optional(
377
+ v.union(v.literal("auto"), v.literal("json"), v.literal("tool"))
378
+ ),
379
+ }),
380
+ v.object({
381
+ ...objectArgsCommonFields,
382
+ output: v.literal("no-schema"),
383
+ mode: v.optional(v.literal("json")),
384
+ })
385
+ );
386
+ export type SafeObjectArgs = Infer<typeof vSafeObjectArgs>;
387
+
388
+ export const vEmbeddingsWithMetadata = v.object({
389
+ vectors: v.array(v.union(v.array(v.number()), v.null())),
390
+ dimension: vVectorDimension,
391
+ model: v.string(),
293
392
  });
393
+ export type EmbeddingsWithMetadata = Infer<typeof vEmbeddingsWithMetadata>;