@convex-dev/agent 0.2.2 → 0.2.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.
- package/dist/client/definePlaygroundAPI.d.ts +144 -13
- package/dist/client/definePlaygroundAPI.d.ts.map +1 -1
- package/dist/client/files.d.ts +1 -1
- package/dist/client/files.d.ts.map +1 -1
- package/dist/client/files.js.map +1 -1
- package/dist/client/index.d.ts +130 -10
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +17 -7
- package/dist/client/index.js.map +1 -1
- package/dist/client/messages.d.ts +32 -5
- package/dist/client/messages.d.ts.map +1 -1
- package/dist/client/messages.js +7 -4
- package/dist/client/messages.js.map +1 -1
- package/dist/client/search.d.ts +31 -4
- package/dist/client/search.d.ts.map +1 -1
- package/dist/client/search.js +2 -4
- package/dist/client/search.js.map +1 -1
- package/dist/client/streaming.d.ts +322 -39
- package/dist/client/streaming.d.ts.map +1 -1
- package/dist/component/_generated/api.d.ts +301 -15
- package/dist/component/messages.d.ts +336 -41
- package/dist/component/messages.d.ts.map +1 -1
- package/dist/component/messages.js +4 -4
- package/dist/component/messages.js.map +1 -1
- package/dist/component/schema.d.ts +874 -133
- package/dist/component/schema.d.ts.map +1 -1
- package/dist/mapping.d.ts +4 -4
- package/dist/mapping.d.ts.map +1 -1
- package/dist/mapping.js +68 -38
- package/dist/mapping.js.map +1 -1
- package/dist/react/deltas.d.ts +3 -3
- package/dist/react/deltas.d.ts.map +1 -1
- package/dist/react/deltas.js +321 -28
- package/dist/react/deltas.js.map +1 -1
- package/dist/react/toUIMessages.d.ts.map +1 -1
- package/dist/react/toUIMessages.js +289 -180
- package/dist/react/toUIMessages.js.map +1 -1
- package/dist/react/useSmoothText.d.ts.map +1 -1
- package/dist/react/useSmoothText.js +15 -6
- package/dist/react/useSmoothText.js.map +1 -1
- package/dist/shared.d.ts +4 -0
- package/dist/shared.d.ts.map +1 -1
- package/dist/shared.js +8 -0
- package/dist/shared.js.map +1 -1
- package/dist/validators.d.ts +1887 -249
- package/dist/validators.d.ts.map +1 -1
- package/dist/validators.js +10 -3
- package/dist/validators.js.map +1 -1
- package/package.json +1 -1
- package/src/client/files.ts +4 -4
- package/src/client/index.ts +41 -15
- package/src/client/messages.ts +12 -4
- package/src/client/search.ts +2 -6
- package/src/component/_generated/api.d.ts +301 -15
- package/src/component/messages.ts +4 -3
- package/src/mapping.ts +105 -56
- package/src/react/deltas.ts +391 -46
- package/src/react/toUIMessages.test.ts +234 -4
- package/src/react/toUIMessages.ts +366 -192
- package/src/react/useSmoothText.ts +25 -13
- package/src/shared.ts +14 -0
- package/src/validators.ts +23 -15
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
DEFAULT_RECENT_MESSAGES,
|
|
11
11
|
extractText,
|
|
12
12
|
isTool,
|
|
13
|
+
sorted,
|
|
13
14
|
} from "../shared.js";
|
|
14
15
|
import {
|
|
15
16
|
vMessageEmbeddingsWithDimension,
|
|
@@ -631,11 +632,11 @@ export const _fetchSearchMessages = internalQuery({
|
|
|
631
632
|
.map(publicMessage);
|
|
632
633
|
messages.push(...(args.textSearchMessages ?? []));
|
|
633
634
|
// TODO: prioritize more recent messages
|
|
634
|
-
messages
|
|
635
|
+
messages = sorted(messages);
|
|
635
636
|
messages = messages.slice(0, args.limit);
|
|
636
637
|
// Fetch the surrounding messages
|
|
637
638
|
if (!threadId) {
|
|
638
|
-
return messages
|
|
639
|
+
return messages;
|
|
639
640
|
}
|
|
640
641
|
const included: Record<string, Set<number>> = {};
|
|
641
642
|
for (const m of messages) {
|
|
@@ -688,7 +689,7 @@ export const _fetchSearchMessages = internalQuery({
|
|
|
688
689
|
messages.push(publicMessage(r));
|
|
689
690
|
}
|
|
690
691
|
}
|
|
691
|
-
return messages
|
|
692
|
+
return sorted(messages);
|
|
692
693
|
},
|
|
693
694
|
});
|
|
694
695
|
|
package/src/mapping.ts
CHANGED
|
@@ -16,26 +16,32 @@ import {
|
|
|
16
16
|
type TextPart,
|
|
17
17
|
type ToolCallPart,
|
|
18
18
|
type ToolResultPart,
|
|
19
|
-
type
|
|
19
|
+
type ProviderMetadata,
|
|
20
20
|
} from "ai";
|
|
21
|
-
import
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
21
|
+
import {
|
|
22
|
+
vMessageWithMetadata,
|
|
23
|
+
type Message,
|
|
24
|
+
type MessageWithMetadata,
|
|
25
|
+
type Usage,
|
|
26
|
+
type vContent,
|
|
27
|
+
type vFilePart,
|
|
28
|
+
type vImagePart,
|
|
29
|
+
type vReasoningPart,
|
|
30
|
+
type vRedactedReasoningPart,
|
|
31
|
+
type vTextPart,
|
|
32
|
+
type vToolCallPart,
|
|
33
|
+
type vToolResultPart,
|
|
33
34
|
} from "./validators.js";
|
|
34
35
|
import type { ActionCtx, AgentComponent } from "./client/types.js";
|
|
35
36
|
import type { RunMutationCtx } from "./client/types.js";
|
|
36
37
|
import { MAX_FILE_SIZE, storeFile } from "./client/files.js";
|
|
37
38
|
import type { Infer } from "convex/values";
|
|
38
|
-
import {
|
|
39
|
+
import {
|
|
40
|
+
convertUint8ArrayToBase64,
|
|
41
|
+
type ProviderOptions,
|
|
42
|
+
type ReasoningPart,
|
|
43
|
+
} from "@ai-sdk/provider-utils";
|
|
44
|
+
import { parse } from "convex-helpers/validators";
|
|
39
45
|
export type AIMessageWithoutId = Omit<AIMessage, "id">;
|
|
40
46
|
|
|
41
47
|
export type SerializeUrlsAndUint8Arrays<T> = T extends URL
|
|
@@ -95,7 +101,9 @@ export async function serializeOrThrow(
|
|
|
95
101
|
} as SerializedMessage;
|
|
96
102
|
}
|
|
97
103
|
|
|
98
|
-
export function deserializeMessage(
|
|
104
|
+
export function deserializeMessage(
|
|
105
|
+
message: SerializedMessage | ModelMessage,
|
|
106
|
+
): ModelMessage {
|
|
99
107
|
return {
|
|
100
108
|
...message,
|
|
101
109
|
content: deserializeContent(message.content),
|
|
@@ -169,12 +177,12 @@ export async function serializeNewMessagesInStep<TOOLS extends ToolSet>(
|
|
|
169
177
|
: step.response.messages.slice(-1)
|
|
170
178
|
).map(async (msg): Promise<MessageWithMetadata> => {
|
|
171
179
|
const { message, fileIds } = await serializeMessage(ctx, component, msg);
|
|
172
|
-
return {
|
|
180
|
+
return parse(vMessageWithMetadata, {
|
|
173
181
|
message,
|
|
174
182
|
...(message.role === "tool" ? toolFields : assistantFields),
|
|
175
183
|
text: step.text,
|
|
176
184
|
fileIds,
|
|
177
|
-
};
|
|
185
|
+
});
|
|
178
186
|
}),
|
|
179
187
|
);
|
|
180
188
|
// TODO: capture step.files separately?
|
|
@@ -210,6 +218,16 @@ export async function serializeObjectResult(
|
|
|
210
218
|
};
|
|
211
219
|
}
|
|
212
220
|
|
|
221
|
+
function getMimeOrMediaType(part: { mediaType?: string; mimeType?: string }) {
|
|
222
|
+
if ("mediaType" in part) {
|
|
223
|
+
return part.mediaType;
|
|
224
|
+
}
|
|
225
|
+
if ("mimeType" in part) {
|
|
226
|
+
return part.mimeType;
|
|
227
|
+
}
|
|
228
|
+
return undefined;
|
|
229
|
+
}
|
|
230
|
+
|
|
213
231
|
export async function serializeContent(
|
|
214
232
|
ctx: ActionCtx | RunMutationCtx,
|
|
215
233
|
component: AgentComponent,
|
|
@@ -219,14 +237,15 @@ export async function serializeContent(
|
|
|
219
237
|
return { content };
|
|
220
238
|
}
|
|
221
239
|
const fileIds: string[] = [];
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
240
|
+
const metadata: {
|
|
241
|
+
providerOptions?: ProviderOptions;
|
|
242
|
+
providerMetadata?: ProviderMetadata;
|
|
243
|
+
} = {};
|
|
244
|
+
if ("providerOptions" in content) {
|
|
245
|
+
metadata.providerOptions = content.providerOptions as ProviderOptions;
|
|
246
|
+
}
|
|
247
|
+
if ("providerMetadata" in content) {
|
|
248
|
+
metadata.providerMetadata = content.providerMetadata as ProviderMetadata;
|
|
230
249
|
}
|
|
231
250
|
const serialized = await Promise.all(
|
|
232
251
|
content.map(async (part) => {
|
|
@@ -235,7 +254,7 @@ export async function serializeContent(
|
|
|
235
254
|
return {
|
|
236
255
|
type: part.type,
|
|
237
256
|
text: part.text,
|
|
238
|
-
|
|
257
|
+
...metadata,
|
|
239
258
|
} satisfies Infer<typeof vTextPart>;
|
|
240
259
|
}
|
|
241
260
|
case "image": {
|
|
@@ -248,7 +267,7 @@ export async function serializeContent(
|
|
|
248
267
|
ctx,
|
|
249
268
|
component,
|
|
250
269
|
new Blob([image], {
|
|
251
|
-
type:
|
|
270
|
+
type: getMimeOrMediaType(part) || guessMimeType(image),
|
|
252
271
|
}),
|
|
253
272
|
);
|
|
254
273
|
image = file.url;
|
|
@@ -256,8 +275,8 @@ export async function serializeContent(
|
|
|
256
275
|
}
|
|
257
276
|
return {
|
|
258
277
|
type: part.type,
|
|
259
|
-
mimeType:
|
|
260
|
-
|
|
278
|
+
mimeType: getMimeOrMediaType(part),
|
|
279
|
+
...metadata,
|
|
261
280
|
image,
|
|
262
281
|
} satisfies Infer<typeof vImagePart>;
|
|
263
282
|
}
|
|
@@ -267,7 +286,7 @@ export async function serializeContent(
|
|
|
267
286
|
const { file } = await storeFile(
|
|
268
287
|
ctx,
|
|
269
288
|
component,
|
|
270
|
-
new Blob([data], { type:
|
|
289
|
+
new Blob([data], { type: getMimeOrMediaType(part) }),
|
|
271
290
|
);
|
|
272
291
|
data = file.url;
|
|
273
292
|
fileIds.push(file.fileId);
|
|
@@ -276,8 +295,8 @@ export async function serializeContent(
|
|
|
276
295
|
type: part.type,
|
|
277
296
|
data,
|
|
278
297
|
filename: part.filename,
|
|
279
|
-
mimeType:
|
|
280
|
-
|
|
298
|
+
mimeType: getMimeOrMediaType(part)!,
|
|
299
|
+
...metadata,
|
|
281
300
|
} satisfies Infer<typeof vFilePart>;
|
|
282
301
|
}
|
|
283
302
|
case "tool-call": {
|
|
@@ -287,8 +306,8 @@ export async function serializeContent(
|
|
|
287
306
|
args: args ?? null,
|
|
288
307
|
toolCallId: part.toolCallId,
|
|
289
308
|
toolName: part.toolName,
|
|
290
|
-
providerOptions: part.providerOptions,
|
|
291
309
|
providerExecuted: part.providerExecuted,
|
|
310
|
+
...metadata,
|
|
292
311
|
} satisfies Infer<typeof vToolCallPart>;
|
|
293
312
|
}
|
|
294
313
|
case "tool-result": {
|
|
@@ -298,14 +317,14 @@ export async function serializeContent(
|
|
|
298
317
|
result: result ?? null,
|
|
299
318
|
toolCallId: part.toolCallId,
|
|
300
319
|
toolName: part.toolName,
|
|
301
|
-
|
|
320
|
+
...metadata,
|
|
302
321
|
} satisfies Infer<typeof vToolResultPart>;
|
|
303
322
|
}
|
|
304
323
|
case "reasoning": {
|
|
305
324
|
return {
|
|
306
325
|
type: part.type,
|
|
307
326
|
text: part.text,
|
|
308
|
-
|
|
327
|
+
...metadata,
|
|
309
328
|
} satisfies Infer<typeof vReasoningPart>;
|
|
310
329
|
}
|
|
311
330
|
// Not in current generation output, but could be in historical messages
|
|
@@ -313,7 +332,7 @@ export async function serializeContent(
|
|
|
313
332
|
return {
|
|
314
333
|
type: part.type,
|
|
315
334
|
data: part.data,
|
|
316
|
-
|
|
335
|
+
...metadata,
|
|
317
336
|
} satisfies Infer<typeof vRedactedReasoningPart>;
|
|
318
337
|
}
|
|
319
338
|
default:
|
|
@@ -327,64 +346,91 @@ export async function serializeContent(
|
|
|
327
346
|
};
|
|
328
347
|
}
|
|
329
348
|
|
|
330
|
-
export function deserializeContent(
|
|
349
|
+
export function deserializeContent(
|
|
350
|
+
content: SerializedContent | ModelMessage["content"],
|
|
351
|
+
): Content {
|
|
331
352
|
if (typeof content === "string") {
|
|
332
353
|
return content;
|
|
333
354
|
}
|
|
334
355
|
return content.map((part) => {
|
|
356
|
+
const metadata: {
|
|
357
|
+
providerOptions?: ProviderOptions;
|
|
358
|
+
providerMetadata?: ProviderMetadata;
|
|
359
|
+
} = {};
|
|
360
|
+
if ("providerOptions" in part) {
|
|
361
|
+
metadata.providerOptions = part.providerOptions;
|
|
362
|
+
}
|
|
363
|
+
if ("providerMetadata" in part) {
|
|
364
|
+
metadata.providerMetadata = part.providerMetadata;
|
|
365
|
+
}
|
|
335
366
|
switch (part.type) {
|
|
336
367
|
case "text":
|
|
337
368
|
return {
|
|
338
369
|
type: part.type,
|
|
339
370
|
text: part.text,
|
|
340
|
-
|
|
371
|
+
...metadata,
|
|
341
372
|
} satisfies TextPart;
|
|
342
373
|
case "image":
|
|
343
374
|
return {
|
|
344
375
|
type: part.type,
|
|
345
376
|
image: deserializeUrl(part.image),
|
|
346
|
-
mediaType: part
|
|
347
|
-
|
|
377
|
+
mediaType: getMimeOrMediaType(part),
|
|
378
|
+
...metadata,
|
|
348
379
|
} satisfies ImagePart;
|
|
349
380
|
case "file":
|
|
350
381
|
return {
|
|
351
382
|
type: part.type,
|
|
352
383
|
data: deserializeUrl(part.data),
|
|
353
384
|
filename: part.filename,
|
|
354
|
-
mediaType: part
|
|
355
|
-
|
|
385
|
+
mediaType: getMimeOrMediaType(part)!,
|
|
386
|
+
...metadata,
|
|
356
387
|
} satisfies FilePart;
|
|
357
|
-
case "tool-call":
|
|
388
|
+
case "tool-call": {
|
|
389
|
+
const input = "input" in part ? part.input : part.args;
|
|
358
390
|
return {
|
|
359
391
|
type: part.type,
|
|
360
|
-
input:
|
|
361
|
-
providerExecuted: part.providerExecuted,
|
|
392
|
+
input: input ?? null,
|
|
362
393
|
toolCallId: part.toolCallId,
|
|
363
394
|
toolName: part.toolName,
|
|
364
|
-
|
|
395
|
+
providerExecuted: part.providerExecuted,
|
|
396
|
+
...metadata,
|
|
365
397
|
} satisfies ToolCallPart;
|
|
366
|
-
|
|
398
|
+
}
|
|
399
|
+
case "tool-result": {
|
|
400
|
+
const result = "output" in part ? part.output : part.result;
|
|
367
401
|
return {
|
|
368
402
|
type: part.type,
|
|
369
|
-
output:
|
|
403
|
+
output: result ?? null,
|
|
370
404
|
toolCallId: part.toolCallId,
|
|
371
405
|
toolName: part.toolName,
|
|
372
|
-
|
|
406
|
+
...metadata,
|
|
373
407
|
} satisfies ToolResultPart;
|
|
408
|
+
}
|
|
374
409
|
case "reasoning":
|
|
375
410
|
return {
|
|
376
411
|
type: part.type,
|
|
377
412
|
text: part.text,
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
} satisfies ReasoningUIPart;
|
|
413
|
+
...metadata,
|
|
414
|
+
} satisfies ReasoningPart;
|
|
381
415
|
case "redacted-reasoning":
|
|
382
416
|
// TODO: should we just drop this?
|
|
383
417
|
return {
|
|
384
418
|
type: "reasoning",
|
|
385
|
-
text:
|
|
386
|
-
|
|
387
|
-
|
|
419
|
+
text: "",
|
|
420
|
+
...metadata,
|
|
421
|
+
providerOptions: metadata.providerOptions
|
|
422
|
+
? {
|
|
423
|
+
...Object.fromEntries(
|
|
424
|
+
Object.entries(metadata.providerOptions ?? {}).map(
|
|
425
|
+
([key, value]) => [
|
|
426
|
+
key,
|
|
427
|
+
{ ...value, redactedData: part.data },
|
|
428
|
+
],
|
|
429
|
+
),
|
|
430
|
+
),
|
|
431
|
+
}
|
|
432
|
+
: undefined,
|
|
433
|
+
} satisfies ReasoningPart;
|
|
388
434
|
default:
|
|
389
435
|
return part satisfies Content;
|
|
390
436
|
}
|
|
@@ -482,8 +528,11 @@ export function serializeDataOrUrl(
|
|
|
482
528
|
}
|
|
483
529
|
|
|
484
530
|
export function deserializeUrl(
|
|
485
|
-
urlOrString: string | ArrayBuffer,
|
|
531
|
+
urlOrString: string | ArrayBuffer | URL | DataContent,
|
|
486
532
|
): URL | DataContent {
|
|
533
|
+
if (urlOrString instanceof URL) {
|
|
534
|
+
return urlOrString;
|
|
535
|
+
}
|
|
487
536
|
if (typeof urlOrString === "string") {
|
|
488
537
|
if (
|
|
489
538
|
urlOrString.startsWith("http://") ||
|