@convex-dev/agent 0.1.16-alpha.0 → 0.1.16-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) 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 +2 -1
  8. package/dist/client/index.d.ts.map +1 -1
  9. package/dist/client/index.js +47 -29
  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/react/deltas.d.ts.map +1 -1
  27. package/dist/react/deltas.js +6 -5
  28. package/dist/react/deltas.js.map +1 -1
  29. package/dist/validators.js +1 -2
  30. package/dist/validators.js.map +1 -1
  31. package/package.json +1 -1
  32. package/src/client/createTool.ts +9 -6
  33. package/src/client/files.ts +8 -8
  34. package/src/client/index.test.ts +14 -12
  35. package/src/client/index.ts +127 -99
  36. package/src/client/listMessages.ts +1 -1
  37. package/src/client/search.ts +14 -14
  38. package/src/client/streaming.ts +7 -7
  39. package/src/client/types.ts +29 -23
  40. package/src/component/apiKeys.ts +1 -1
  41. package/src/component/files.test.ts +1 -1
  42. package/src/component/files.ts +6 -6
  43. package/src/component/messages.test.ts +6 -6
  44. package/src/component/messages.ts +44 -43
  45. package/src/component/schema.ts +1 -2
  46. package/src/component/streams.ts +27 -27
  47. package/src/component/threads.test.ts +4 -4
  48. package/src/component/threads.ts +4 -4
  49. package/src/component/users.test.ts +2 -2
  50. package/src/component/users.ts +4 -4
  51. package/src/component/vector/index.ts +11 -11
  52. package/src/component/vector/tables.ts +6 -6
  53. package/src/mapping.test.ts +4 -4
  54. package/src/mapping.ts +18 -17
  55. package/src/react/deltas.test.ts +16 -16
  56. package/src/react/deltas.ts +19 -18
  57. package/src/react/index.ts +11 -11
  58. package/src/react/optimisticallySendMessage.ts +2 -2
  59. package/src/react/toUIMessages.test.ts +10 -10
  60. package/src/react/toUIMessages.ts +6 -6
  61. package/src/react/useSmoothText.ts +6 -6
  62. package/src/validators.ts +24 -24
@@ -118,7 +118,7 @@ export const schema = defineSchema({
118
118
  v.object({
119
119
  kind: v.literal("aborted"),
120
120
  reason: v.string(),
121
- })
121
+ }),
122
122
  ),
123
123
  })
124
124
  // There should only be one per "order" index
@@ -197,5 +197,4 @@ export const vMessageDoc = v.object({
197
197
  });
198
198
  export type MessageDoc = Infer<typeof vMessageDoc>;
199
199
 
200
-
201
200
  export default schema;
@@ -51,7 +51,7 @@ export const listDeltas = query({
51
51
  v.object({
52
52
  streamId: v.id("streamingMessages"),
53
53
  cursor: v.number(),
54
- })
54
+ }),
55
55
  ),
56
56
  },
57
57
  returns: v.array(vStreamDelta),
@@ -62,16 +62,16 @@ export const listDeltas = query({
62
62
  const streamDeltas = await ctx.db
63
63
  .query("streamDeltas")
64
64
  .withIndex("streamId_start_end", (q) =>
65
- q.eq("streamId", cursor.streamId).gte("start", cursor.cursor)
65
+ q.eq("streamId", cursor.streamId).gte("start", cursor.cursor),
66
66
  )
67
67
  .take(
68
- Math.min(MAX_DELTAS_PER_STREAM, MAX_DELTAS_PER_REQUEST - totalDeltas)
68
+ Math.min(MAX_DELTAS_PER_STREAM, MAX_DELTAS_PER_REQUEST - totalDeltas),
69
69
  );
70
70
  totalDeltas += streamDeltas.length;
71
71
  deltas.push(
72
72
  ...streamDeltas.map((d) =>
73
- pick(d, ["streamId", "start", "end", "parts"])
74
- )
73
+ pick(d, ["streamId", "start", "end", "parts"]),
74
+ ),
75
75
  );
76
76
  if (totalDeltas >= MAX_DELTAS_PER_REQUEST) {
77
77
  break;
@@ -96,7 +96,7 @@ export const create = mutation({
96
96
  const timeoutFnId = await ctx.scheduler.runAfter(
97
97
  TIMEOUT_INTERVAL,
98
98
  internal.streams.timeoutStream,
99
- { streamId }
99
+ { streamId },
100
100
  );
101
101
  await ctx.db.patch(streamId, { state: { ...state, timeoutFnId } });
102
102
  return streamId;
@@ -112,9 +112,9 @@ export const list = query({
112
112
  v.union(
113
113
  v.literal("streaming"),
114
114
  v.literal("finished"),
115
- v.literal("aborted")
116
- )
117
- )
115
+ v.literal("aborted"),
116
+ ),
117
+ ),
118
118
  ),
119
119
  },
120
120
  returns: v.array(vStreamMessage),
@@ -128,11 +128,11 @@ export const list = query({
128
128
  q
129
129
  .eq("threadId", args.threadId)
130
130
  .eq("state.kind", status)
131
- .gte("order", args.startOrder ?? 0)
131
+ .gte("order", args.startOrder ?? 0),
132
132
  )
133
- .order("desc")
133
+ .order("desc"),
134
134
  ),
135
- ["order", "stepOrder"]
135
+ ["order", "stepOrder"],
136
136
  ).take(100);
137
137
 
138
138
  return messages.map((m) => ({
@@ -165,7 +165,7 @@ export const abortByOrder = mutation({
165
165
  q
166
166
  .eq("threadId", args.threadId)
167
167
  .eq("state.kind", "streaming")
168
- .eq("order", args.order)
168
+ .eq("order", args.order),
169
169
  )
170
170
  .take(100);
171
171
  for (const stream of streams) {
@@ -189,7 +189,7 @@ export const abort = mutation({
189
189
 
190
190
  async function abortById(
191
191
  ctx: MutationCtx,
192
- args: { streamId: Id<"streamingMessages">; reason: string }
192
+ args: { streamId: Id<"streamingMessages">; reason: string },
193
193
  ) {
194
194
  const stream = await ctx.db.get(args.streamId);
195
195
  if (!stream) {
@@ -197,7 +197,7 @@ async function abortById(
197
197
  }
198
198
  if (stream.state.kind !== "streaming") {
199
199
  console.warn(
200
- `Stream trying to abort but not currently streaming (${stream.state.kind}): ${args.streamId}`
200
+ `Stream trying to abort but not currently streaming (${stream.state.kind}): ${args.streamId}`,
201
201
  );
202
202
  return false;
203
203
  }
@@ -210,7 +210,7 @@ async function abortById(
210
210
 
211
211
  async function cleanupTimeoutFn(
212
212
  ctx: MutationCtx,
213
- stream: Doc<"streamingMessages">
213
+ stream: Doc<"streamingMessages">,
214
214
  ) {
215
215
  if (stream.state.kind === "streaming" && stream.state.timeoutFnId) {
216
216
  const timeoutFn = await ctx.db.system.get(stream.state.timeoutFnId);
@@ -236,7 +236,7 @@ export const finish = mutation({
236
236
  }
237
237
  if (stream.state.kind !== "streaming") {
238
238
  console.warn(
239
- `Stream trying to finish but not currently streaming: ${args.streamId}`
239
+ `Stream trying to finish but not currently streaming: ${args.streamId}`,
240
240
  );
241
241
  return;
242
242
  }
@@ -244,7 +244,7 @@ export const finish = mutation({
244
244
  const cleanupFnId = await ctx.scheduler.runAfter(
245
245
  DELETE_STREAM_DELAY,
246
246
  api.streams.deleteStreamAsync,
247
- { streamId: args.streamId }
247
+ { streamId: args.streamId },
248
248
  );
249
249
  await ctx.db.patch(args.streamId, {
250
250
  state: { kind: "finished", endedAt: Date.now(), cleanupFnId },
@@ -254,7 +254,7 @@ export const finish = mutation({
254
254
 
255
255
  async function heartbeatStream(
256
256
  ctx: MutationCtx,
257
- args: { streamId: Id<"streamingMessages"> }
257
+ args: { streamId: Id<"streamingMessages"> },
258
258
  ) {
259
259
  const stream = await ctx.db.get(args.streamId);
260
260
  if (!stream) {
@@ -283,7 +283,7 @@ async function heartbeatStream(
283
283
  const timeoutFnId = await ctx.scheduler.runAfter(
284
284
  TIMEOUT_INTERVAL,
285
285
  internal.streams.timeoutStream,
286
- { streamId: args.streamId }
286
+ { streamId: args.streamId },
287
287
  );
288
288
  await ctx.db.patch(args.streamId, {
289
289
  state: {
@@ -314,7 +314,7 @@ export const timeoutStream = internalMutation({
314
314
 
315
315
  async function deletePageForStreamId(
316
316
  ctx: MutationCtx,
317
- args: { streamId: Id<"streamingMessages">; cursor?: string }
317
+ args: { streamId: Id<"streamingMessages">; cursor?: string },
318
318
  ) {
319
319
  const deltas = await paginator(ctx.db, schema)
320
320
  .query("streamDeltas")
@@ -339,7 +339,7 @@ async function deletePageForStreamId(
339
339
 
340
340
  export async function deleteStreamsPageForThreadId(
341
341
  ctx: MutationCtx,
342
- args: { threadId: Id<"threads">; streamOrder?: number; deltaCursor?: string }
342
+ args: { threadId: Id<"threads">; streamOrder?: number; deltaCursor?: string },
343
343
  ) {
344
344
  const allStreamMessages =
345
345
  schema.tables.streamingMessages.validator.fields.state.members
@@ -351,8 +351,8 @@ export async function deleteStreamsPageForThreadId(
351
351
  q
352
352
  .eq("threadId", args.threadId)
353
353
  .eq("state.kind", stateKind)
354
- .gte("order", args.streamOrder ?? 0)
355
- )
354
+ .gte("order", args.streamOrder ?? 0),
355
+ ),
356
356
  );
357
357
  let deltaCursor = args.deltaCursor;
358
358
  const streamMessage = await mergedStream(allStreamMessages, [
@@ -417,7 +417,7 @@ export const deleteAllStreamsForThreadIdAsync = mutation({
417
417
  threadId: args.threadId,
418
418
  streamOrder: result.streamOrder,
419
419
  deltaCursor: result.deltaCursor,
420
- }
420
+ },
421
421
  );
422
422
  } else {
423
423
  await ctx.db.delete(args.threadId);
@@ -460,7 +460,7 @@ export const deleteAllStreamsForThreadIdSync = action({
460
460
  handler: async (ctx, args) => {
461
461
  let result = await ctx.runMutation(
462
462
  internal.streams.deleteStreamsPageForThreadIdMutation,
463
- args
463
+ args,
464
464
  );
465
465
  while (!result.isDone) {
466
466
  result = await ctx.runMutation(
@@ -469,7 +469,7 @@ export const deleteAllStreamsForThreadIdSync = action({
469
469
  ...args,
470
470
  streamOrder: result.streamOrder,
471
471
  deltaCursor: result.deltaCursor,
472
- }
472
+ },
473
473
  );
474
474
  }
475
475
  },
@@ -225,7 +225,7 @@ describe("threads", () => {
225
225
  t.mutation(api.threads.updateThread, {
226
226
  threadId: thread._id as Id<"threads">,
227
227
  patch: { title: "New Title" },
228
- })
228
+ }),
229
229
  ).rejects.toThrow();
230
230
  });
231
231
 
@@ -368,7 +368,7 @@ describe("threads", () => {
368
368
  {
369
369
  threadId: thread._id as Id<"threads">,
370
370
  cursor: currentResult.cursor,
371
- }
371
+ },
372
372
  );
373
373
  iterations++;
374
374
  }
@@ -471,7 +471,7 @@ describe("threads", () => {
471
471
  await expect(
472
472
  t.action(api.threads.deleteAllForThreadIdSync, {
473
473
  threadId: thread._id as Id<"threads">,
474
- })
474
+ }),
475
475
  ).resolves.not.toThrow();
476
476
 
477
477
  // Thread should be deleted
@@ -499,7 +499,7 @@ describe("threads", () => {
499
499
  await expect(
500
500
  t.action(api.threads.deleteAllForThreadIdSync, {
501
501
  threadId: thread._id as Id<"threads">,
502
- })
502
+ }),
503
503
  ).resolves.not.toThrow();
504
504
  });
505
505
 
@@ -104,7 +104,7 @@ export const searchThreadTitles = query({
104
104
  .withSearchIndex("title", (q) =>
105
105
  args.userId
106
106
  ? q.search("title", args.query).eq("userId", args.userId ?? undefined)
107
- : q.search("title", args.query)
107
+ : q.search("title", args.query),
108
108
  )
109
109
  .take(args.limit);
110
110
  return threads.map(publicThread);
@@ -138,7 +138,7 @@ export const deleteAllForThreadIdSync = action({
138
138
  while (true) {
139
139
  const result: DeleteThreadReturns = await ctx.runMutation(
140
140
  internal.threads._deletePageForThreadId,
141
- { threadId: args.threadId, cursor, limit: args.limit }
141
+ { threadId: args.threadId, cursor, limit: args.limit },
142
142
  );
143
143
  if (result.isDone) {
144
144
  break;
@@ -218,12 +218,12 @@ export const deleteAllForThreadIdAsync = mutation({
218
218
 
219
219
  async function deletePageForThreadIdHandler(
220
220
  ctx: MutationCtx,
221
- args: DeleteThreadArgs
221
+ args: DeleteThreadArgs,
222
222
  ): Promise<DeleteThreadReturns> {
223
223
  const messages = await paginator(ctx.db, schema)
224
224
  .query("messages")
225
225
  .withIndex("threadId_status_tool_order_stepOrder", (q) =>
226
- q.eq("threadId", args.threadId)
226
+ q.eq("threadId", args.threadId),
227
227
  )
228
228
  .paginate({
229
229
  numItems: args.limit ?? 100,
@@ -60,7 +60,7 @@ describe("users", () => {
60
60
  // Should not have duplicate users
61
61
  console.log(firstPage.page, secondPage.page);
62
62
  expect(
63
- firstPage.page.every((user) => !secondPage.page.includes(user))
63
+ firstPage.page.every((user) => !secondPage.page.includes(user)),
64
64
  ).toBe(true);
65
65
  });
66
66
 
@@ -470,7 +470,7 @@ describe("users", () => {
470
470
 
471
471
  // Try to delete for a user that doesn't exist
472
472
  await expect(
473
- t.action(api.users.deleteAllForUserId, { userId: "nonexistentUser" })
473
+ t.action(api.users.deleteAllForUserId, { userId: "nonexistentUser" }),
474
474
  ).resolves.not.toThrow();
475
475
 
476
476
  // Should complete successfully without errors
@@ -59,7 +59,7 @@ export const deleteAllForUserId = action({
59
59
  streamsInProgress,
60
60
  streamOrder,
61
61
  deltaCursor,
62
- }
62
+ },
63
63
  );
64
64
  messagesCursor = result.messagesCursor;
65
65
  threadInProgress = result.threadInProgress;
@@ -121,7 +121,7 @@ export const _deleteAllForUserIdAsync = internalMutation({
121
121
 
122
122
  async function deleteAllForUserIdAsyncHandler(
123
123
  ctx: MutationCtx,
124
- args: DeleteAllArgs
124
+ args: DeleteAllArgs,
125
125
  ): Promise<boolean> {
126
126
  const result = await deletePageForUserId(ctx, args);
127
127
  if (!result.isDone) {
@@ -145,7 +145,7 @@ export const _deletePageForUserId = internalMutation({
145
145
  });
146
146
  async function deletePageForUserId(
147
147
  ctx: MutationCtx,
148
- args: DeleteAllArgs
148
+ args: DeleteAllArgs,
149
149
  ): Promise<DeleteAllReturns> {
150
150
  let threadInProgress: Id<"threads"> | null = args.threadInProgress;
151
151
  let threadsCursor: string | null = args.threadsCursor;
@@ -189,7 +189,7 @@ async function deletePageForUserId(
189
189
  const messages = await paginator(ctx.db, schema)
190
190
  .query("messages")
191
191
  .withIndex("threadId_status_tool_order_stepOrder", (q) =>
192
- q.eq("threadId", threadInProgress!)
192
+ q.eq("threadId", threadInProgress!),
193
193
  )
194
194
  .order("desc")
195
195
  .paginate({
@@ -40,7 +40,7 @@ export const paginate = query({
40
40
  args.table
41
41
  ? // eslint-disable-next-line @typescript-eslint/no-explicit-any
42
42
  (q.eq("model", args.targetModel) as any).eq("table", args.table)
43
- : q.eq("model", args.targetModel)
43
+ : q.eq("model", args.targetModel),
44
44
  )
45
45
  .paginate({
46
46
  cursor: args.cursor ?? null,
@@ -77,10 +77,10 @@ export const deleteBatchForThread = mutation({
77
77
  q
78
78
  .eq("model", args.model)
79
79
  .eq("table", table)
80
- .eq("threadId", args.threadId)
81
- )
80
+ .eq("threadId", args.threadId),
81
+ ),
82
82
  ),
83
- ["threadId"]
83
+ ["threadId"],
84
84
  ).paginate({
85
85
  cursor: args.cursor ?? null,
86
86
  numItems: args.limit,
@@ -101,7 +101,7 @@ export const insertBatch = mutation({
101
101
  v.object({
102
102
  ...vEmbeddingsWithoutDenormalizedFields.fields,
103
103
  messageId: v.optional(v.id("messages")),
104
- })
104
+ }),
105
105
  ),
106
106
  },
107
107
  returns: v.array(vVectorId),
@@ -113,7 +113,7 @@ export const insertBatch = mutation({
113
113
  await ctx.db.patch(messageId, { embeddingId });
114
114
  }
115
115
  return embeddingId;
116
- })
116
+ }),
117
117
  );
118
118
  },
119
119
  });
@@ -121,7 +121,7 @@ export const insertBatch = mutation({
121
121
  export async function insertVector(
122
122
  ctx: MutationCtx,
123
123
  dimension: VectorDimension,
124
- v: EmbeddingsWithoutDenormalizedFields
124
+ v: EmbeddingsWithoutDenormalizedFields,
125
125
  ) {
126
126
  return ctx.db.insert(getVectorTableName(dimension), {
127
127
  ...v,
@@ -143,7 +143,7 @@ export function searchVectors(
143
143
  threadId?: Id<"threads">;
144
144
  searchAllMessagesForUserId?: string;
145
145
  limit?: number;
146
- }
146
+ },
147
147
  ) {
148
148
  const tableName = getVectorTableName(args.dimension);
149
149
  return ctx.vectorSearch(tableName, "vector", {
@@ -176,7 +176,7 @@ export const updateBatch = mutation({
176
176
  // deleting from one table and inserting into another.
177
177
  // However this requires updating all the messages that reference
178
178
  // the vector.
179
- })
179
+ }),
180
180
  ),
181
181
  },
182
182
  returns: v.null(),
@@ -186,8 +186,8 @@ export const updateBatch = mutation({
186
186
  ctx.db.patch(embedding.id, {
187
187
  model: embedding.model,
188
188
  vector: embedding.vector,
189
- })
190
- )
189
+ }),
190
+ ),
191
191
  );
192
192
  },
193
193
  });
@@ -31,7 +31,7 @@ const embeddings = {
31
31
  };
32
32
 
33
33
  export const vEmbeddingsWithoutDenormalizedFields = v.object(
34
- omit(embeddings, ["model_table_userId", "model_table_threadId"])
34
+ omit(embeddings, ["model_table_userId", "model_table_threadId"]),
35
35
  );
36
36
  export type EmbeddingsWithoutDenormalizedFields = Infer<
37
37
  typeof vEmbeddingsWithoutDenormalizedFields
@@ -71,17 +71,17 @@ export const VectorDimensions = [
71
71
  128, 256, 512, 768, 1024, 1408, 1536, 2048, 3072, 4096,
72
72
  ] as const;
73
73
  export function validateVectorDimension(
74
- dimension: number
74
+ dimension: number,
75
75
  ): asserts dimension is VectorDimension {
76
76
  if (!VectorDimensions.includes(dimension as VectorDimension)) {
77
77
  throw new Error(
78
- `Unsupported vector dimension${dimension}. Supported: ${VectorDimensions.join(", ")}`
78
+ `Unsupported vector dimension${dimension}. Supported: ${VectorDimensions.join(", ")}`,
79
79
  );
80
80
  }
81
81
  }
82
82
  export type VectorDimension = (typeof VectorDimensions)[number];
83
83
  export const VectorTableNames = VectorDimensions.map(
84
- (d) => `embeddings_${d}`
84
+ (d) => `embeddings_${d}`,
85
85
  ) as `embeddings_${(typeof VectorDimensions)[number]}`[];
86
86
  export type VectorTableName = (typeof VectorTableNames)[number];
87
87
  export type VectorTableId = GenericId<(typeof VectorTableNames)[number]>;
@@ -89,7 +89,7 @@ export type VectorTableId = GenericId<(typeof VectorTableNames)[number]>;
89
89
  export const vVectorDimension = literals(...VectorDimensions);
90
90
  export const vVectorTableName = literals(...VectorTableNames);
91
91
  export const vVectorId = v.union(
92
- ...VectorTableNames.map((name) => v.id(name))
92
+ ...VectorTableNames.map((name) => v.id(name)),
93
93
  ) as VUnion<
94
94
  GenericId<(typeof VectorTableNames)[number]>,
95
95
  VId<(typeof VectorTableNames)[number]>[]
@@ -117,7 +117,7 @@ const tables: {
117
117
  VectorDimensions.map((dimensions) => [
118
118
  `embeddings_${dimensions}`,
119
119
  table(dimensions),
120
- ])
120
+ ]),
121
121
  ) as Record<
122
122
  `embeddings_${(typeof VectorDimensions)[number]}`,
123
123
  VectorTable<(typeof VectorDimensions)[number]>
@@ -89,7 +89,7 @@ describe("mapping", () => {
89
89
  const bigArr = new Uint8Array(1024 * 65).fill(1);
90
90
  const ab = bigArr.buffer.slice(
91
91
  bigArr.byteOffset,
92
- bigArr.byteOffset + bigArr.byteLength
92
+ bigArr.byteOffset + bigArr.byteLength,
93
93
  );
94
94
  let called = false;
95
95
  const ctx = {
@@ -117,7 +117,7 @@ describe("mapping", () => {
117
117
  const { content: ser, fileIds } = await serializeContent(
118
118
  ctx,
119
119
  component,
120
- content
120
+ content,
121
121
  );
122
122
  expect(called).toBe(true);
123
123
  expect(fileIds).toEqual(["file-123"]);
@@ -125,7 +125,7 @@ describe("mapping", () => {
125
125
  const serArr = ser as SerializedContent;
126
126
  expect(typeof (serArr as { data: unknown }[])[0].data).toBe("string");
127
127
  expect((serArr as { data: unknown }[])[0].data as string).toMatch(
128
- /^https?:\/\//
128
+ /^https?:\/\//,
129
129
  );
130
130
  });
131
131
 
@@ -133,7 +133,7 @@ describe("mapping", () => {
133
133
  const arr = new Uint8Array([1, 2, 3, 4, 5]);
134
134
  const ab = arr.buffer.slice(
135
135
  arr.byteOffset,
136
- arr.byteOffset + arr.byteLength
136
+ arr.byteOffset + arr.byteLength,
137
137
  );
138
138
  const ctx = {
139
139
  runAction: async () => undefined,
package/src/mapping.ts CHANGED
@@ -20,7 +20,6 @@ import type { ActionCtx, AgentComponent } from "./client/types.js";
20
20
  import type { RunMutationCtx } from "./client/types.js";
21
21
  import { MAX_FILE_SIZE, storeFile } from "./client/files.js";
22
22
 
23
-
24
23
  export type AIMessageWithoutId = Omit<AIMessage, "id">;
25
24
 
26
25
  export type SerializeUrlsAndUint8Arrays<T> = T extends URL
@@ -42,13 +41,13 @@ export type SerializedMessage = SerializeUrlsAndUint8Arrays<CoreMessage>;
42
41
  export async function serializeMessage(
43
42
  ctx: ActionCtx | RunMutationCtx,
44
43
  component: AgentComponent,
45
- messageWithId: CoreMessage & { id?: string }
44
+ messageWithId: CoreMessage & { id?: string },
46
45
  ): Promise<{ message: SerializedMessage; fileIds?: string[] }> {
47
46
  const { id: _, experimental_providerMetadata, ...message } = messageWithId;
48
47
  const { content, fileIds } = await serializeContent(
49
48
  ctx,
50
49
  component,
51
- message.content
50
+ message.content,
52
51
  );
53
52
  return {
54
53
  message: {
@@ -72,7 +71,7 @@ export async function serializeNewMessagesInStep<TOOLS extends ToolSet>(
72
71
  ctx: ActionCtx,
73
72
  component: AgentComponent,
74
73
  step: StepResult<TOOLS>,
75
- metadata: { model: string; provider: string }
74
+ metadata: { model: string; provider: string },
76
75
  ): Promise<MessageWithMetadata[]> {
77
76
  // If there are tool results, there's another message with the tool results
78
77
  // ref: https://github.com/vercel/ai/blob/main/packages/ai/core/generate-text/to-response-messages.ts
@@ -98,7 +97,7 @@ export async function serializeNewMessagesInStep<TOOLS extends ToolSet>(
98
97
  const { message, fileIds } = await serializeMessage(
99
98
  ctx,
100
99
  component,
101
- messageWithId
100
+ messageWithId,
102
101
  );
103
102
  return {
104
103
  message,
@@ -109,7 +108,7 @@ export async function serializeNewMessagesInStep<TOOLS extends ToolSet>(
109
108
  text: step.text,
110
109
  fileIds,
111
110
  };
112
- })
111
+ }),
113
112
  );
114
113
  return messages;
115
114
  }
@@ -118,7 +117,7 @@ export async function serializeObjectResult(
118
117
  ctx: ActionCtx,
119
118
  component: AgentComponent,
120
119
  result: GenerateObjectResult<unknown>,
121
- metadata: { model: string; provider: string }
120
+ metadata: { model: string; provider: string },
122
121
  ): Promise<{ messages: MessageWithMetadata[] }> {
123
122
  const text = JSON.stringify(result.object);
124
123
 
@@ -147,7 +146,7 @@ export async function serializeObjectResult(
147
146
  export async function serializeContent(
148
147
  ctx: ActionCtx | RunMutationCtx,
149
148
  component: AgentComponent,
150
- content: Content
149
+ content: Content,
151
150
  ): Promise<{ content: SerializedContent; fileIds?: string[] }> {
152
151
  if (typeof content === "string") {
153
152
  return { content };
@@ -166,7 +165,9 @@ export async function serializeContent(
166
165
  const { file } = await storeFile(
167
166
  ctx,
168
167
  component,
169
- new Blob([image], { type: part.mimeType || guessMimeType(image) })
168
+ new Blob([image], {
169
+ type: part.mimeType || guessMimeType(image),
170
+ }),
170
171
  );
171
172
  image = file.url;
172
173
  fileIds.push(file.fileId);
@@ -179,7 +180,7 @@ export async function serializeContent(
179
180
  const { file } = await storeFile(
180
181
  ctx,
181
182
  component,
182
- new Blob([data], { type: part.mimeType })
183
+ new Blob([data], { type: part.mimeType }),
183
184
  );
184
185
  data = file.url;
185
186
  fileIds.push(file.fileId);
@@ -192,7 +193,7 @@ export async function serializeContent(
192
193
  default:
193
194
  return part;
194
195
  }
195
- })
196
+ }),
196
197
  );
197
198
  return {
198
199
  content: serialized as SerializedContent,
@@ -289,7 +290,7 @@ export function guessMimeType(buf: ArrayBuffer | string): string {
289
290
  * @returns The serialized data as an ArrayBuffer or the URL as a string.
290
291
  */
291
292
  export function serializeDataOrUrl(
292
- dataOrUrl: DataContent | URL
293
+ dataOrUrl: DataContent | URL,
293
294
  ): ArrayBuffer | string {
294
295
  if (typeof dataOrUrl === "string") {
295
296
  return dataOrUrl;
@@ -302,12 +303,12 @@ export function serializeDataOrUrl(
302
303
  }
303
304
  return dataOrUrl.buffer.slice(
304
305
  dataOrUrl.byteOffset,
305
- dataOrUrl.byteOffset + dataOrUrl.byteLength
306
+ dataOrUrl.byteOffset + dataOrUrl.byteLength,
306
307
  ) as ArrayBuffer;
307
308
  }
308
309
 
309
310
  export function deserializeUrl(
310
- urlOrString: string | ArrayBuffer
311
+ urlOrString: string | ArrayBuffer,
311
312
  ): URL | DataContent {
312
313
  if (typeof urlOrString === "string") {
313
314
  if (
@@ -323,7 +324,7 @@ export function deserializeUrl(
323
324
 
324
325
  export function toUIFilePart(part: ImagePart | FilePart): FileUIPart {
325
326
  const dataOrUrl = serializeDataOrUrl(
326
- part.type === "image" ? part.image : part.data
327
+ part.type === "image" ? part.image : part.data,
327
328
  );
328
329
 
329
330
  return {
@@ -346,7 +347,7 @@ export function promptOrMessagesToCoreMessages(args: {
346
347
  const messages: CoreMessage[] = [];
347
348
  assert(
348
349
  args.prompt || args.messages || args.promptMessageId,
349
- "messages or prompt or promptMessageId is required"
350
+ "messages or prompt or promptMessageId is required",
350
351
  );
351
352
  if (args.messages) {
352
353
  if (
@@ -357,7 +358,7 @@ export function promptOrMessagesToCoreMessages(args: {
357
358
  (m.role === "data" || // UI-only role
358
359
  "toolInvocations" in m || // UI-specific field
359
360
  "parts" in m || // UI-specific field
360
- "experimental_attachments" in m)
361
+ "experimental_attachments" in m),
361
362
  )
362
363
  ) {
363
364
  messages.push(...convertToCoreMessages(args.messages as AIMessage[]));