@convex-dev/agent 0.6.4 → 0.7.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.
- package/MIGRATION.md +60 -116
- package/dist/client/messages.d.ts +1 -398
- package/dist/client/messages.d.ts.map +1 -1
- package/dist/client/messages.js +3 -47
- package/dist/client/messages.js.map +1 -1
- package/dist/client/types.d.ts +1 -455
- package/dist/client/types.d.ts.map +1 -1
- package/dist/component/_generated/component.d.ts +805 -45
- package/dist/component/_generated/component.d.ts.map +1 -1
- package/dist/component/messages.d.ts +1252 -201
- package/dist/component/messages.d.ts.map +1 -1
- package/dist/component/messages.js +49 -23
- package/dist/component/messages.js.map +1 -1
- package/dist/component/schema.d.ts +2593 -332
- package/dist/component/schema.d.ts.map +1 -1
- package/dist/component/streams.d.ts +7 -1
- package/dist/component/streams.d.ts.map +1 -1
- package/dist/component/streams.js +24 -30
- package/dist/component/streams.js.map +1 -1
- package/dist/component/threads.d.ts.map +1 -1
- package/dist/component/threads.js +1 -2
- package/dist/component/threads.js.map +1 -1
- package/dist/react/index.d.ts +5 -5
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +5 -5
- package/dist/react/index.js.map +1 -1
- package/dist/shared.d.ts +19 -7
- package/dist/shared.d.ts.map +1 -1
- package/dist/shared.js +4 -4
- package/dist/shared.js.map +1 -1
- package/dist/streaming/materializePersistedUIMessageChunks.d.ts +16 -0
- package/dist/streaming/materializePersistedUIMessageChunks.d.ts.map +1 -0
- package/dist/streaming/materializePersistedUIMessageChunks.js +302 -0
- package/dist/streaming/materializePersistedUIMessageChunks.js.map +1 -0
- package/dist/streaming/persistedUIMessageChunks.d.ts +106 -0
- package/dist/streaming/persistedUIMessageChunks.d.ts.map +1 -0
- package/dist/streaming/persistedUIMessageChunks.js +475 -0
- package/dist/streaming/persistedUIMessageChunks.js.map +1 -0
- package/dist/validators.d.ts +10026 -1055
- package/dist/validators.d.ts.map +1 -1
- package/dist/validators.js +71 -9
- package/dist/validators.js.map +1 -1
- package/dist/{UIMessages.d.ts → vercel/UIMessages.d.ts} +1 -1
- package/dist/vercel/UIMessages.d.ts.map +1 -0
- package/dist/{UIMessages.js → vercel/UIMessages.js} +63 -1
- package/dist/vercel/UIMessages.js.map +1 -0
- package/dist/{client → vercel/client}/createTool.d.ts +23 -16
- package/dist/vercel/client/createTool.d.ts.map +1 -0
- package/dist/{client → vercel/client}/createTool.js +2 -0
- package/dist/vercel/client/createTool.js.map +1 -0
- package/dist/{client → vercel/client}/definePlaygroundAPI.d.ts +533 -79
- package/dist/{client → vercel/client}/definePlaygroundAPI.d.ts.map +1 -1
- package/dist/{client → vercel/client}/definePlaygroundAPI.js +8 -7
- package/dist/vercel/client/definePlaygroundAPI.js.map +1 -0
- package/dist/{client → vercel/client}/files.d.ts +2 -2
- package/dist/vercel/client/files.d.ts.map +1 -0
- package/dist/vercel/client/files.js.map +1 -0
- package/dist/vercel/client/messages.d.ts +542 -0
- package/dist/vercel/client/messages.d.ts.map +1 -0
- package/dist/vercel/client/messages.js +66 -0
- package/dist/vercel/client/messages.js.map +1 -0
- package/dist/{client → vercel/client}/mockModel.d.ts +17 -17
- package/dist/vercel/client/mockModel.d.ts.map +1 -0
- package/dist/{client → vercel/client}/mockModel.js +12 -13
- package/dist/vercel/client/mockModel.js.map +1 -0
- package/dist/{client → vercel/client}/saveInputMessages.d.ts +2 -2
- package/dist/vercel/client/saveInputMessages.d.ts.map +1 -0
- package/dist/vercel/client/saveInputMessages.js.map +1 -0
- package/dist/{client → vercel/client}/search.d.ts +119 -22
- package/dist/vercel/client/search.d.ts.map +1 -0
- package/dist/{client → vercel/client}/search.js +2 -2
- package/dist/vercel/client/search.js.map +1 -0
- package/dist/{client → vercel/client}/start.d.ts +26 -11
- package/dist/vercel/client/start.d.ts.map +1 -0
- package/dist/{client → vercel/client}/start.js +64 -22
- package/dist/vercel/client/start.js.map +1 -0
- package/dist/{client → vercel/client}/streamText.d.ts +13 -12
- package/dist/vercel/client/streamText.d.ts.map +1 -0
- package/dist/{client → vercel/client}/streamText.js +43 -9
- package/dist/vercel/client/streamText.js.map +1 -0
- package/dist/{client → vercel/client}/streaming.d.ts +1410 -183
- package/dist/vercel/client/streaming.d.ts.map +1 -0
- package/dist/{client → vercel/client}/streaming.js +120 -52
- package/dist/vercel/client/streaming.js.map +1 -0
- package/dist/vercel/client/types.d.ts +456 -0
- package/dist/vercel/client/types.d.ts.map +1 -0
- package/dist/vercel/client/types.js +3 -0
- package/dist/vercel/client/types.js.map +1 -0
- package/dist/{client → vercel/client}/utils.d.ts +3 -2
- package/dist/vercel/client/utils.d.ts.map +1 -0
- package/dist/{client → vercel/client}/utils.js +2 -2
- package/dist/vercel/client/utils.js.map +1 -0
- package/dist/{deltas.d.ts → vercel/deltas.d.ts} +3 -4
- package/dist/vercel/deltas.d.ts.map +1 -0
- package/dist/{deltas.js → vercel/deltas.js} +195 -99
- package/dist/vercel/deltas.js.map +1 -0
- package/dist/{client → vercel}/index.d.ts +482 -106
- package/dist/vercel/index.d.ts.map +1 -0
- package/dist/{client → vercel}/index.js +64 -46
- package/dist/vercel/index.js.map +1 -0
- package/dist/{mapping.d.ts → vercel/mapping.d.ts} +5 -19
- package/dist/vercel/mapping.d.ts.map +1 -0
- package/dist/{mapping.js → vercel/mapping.js} +411 -114
- package/dist/vercel/mapping.js.map +1 -0
- package/dist/{react → vercel/react}/optimisticallySendMessage.d.ts +2 -2
- package/dist/vercel/react/optimisticallySendMessage.d.ts.map +1 -0
- package/dist/vercel/react/optimisticallySendMessage.js.map +1 -0
- package/dist/{react → vercel/react}/types.d.ts +1 -1
- package/dist/vercel/react/types.d.ts.map +1 -0
- package/dist/{react → vercel/react}/types.js.map +1 -1
- package/dist/{react → vercel/react}/useDeltaStreams.d.ts +1 -1
- package/dist/vercel/react/useDeltaStreams.d.ts.map +1 -0
- package/dist/{react → vercel/react}/useDeltaStreams.js +1 -1
- package/dist/vercel/react/useDeltaStreams.js.map +1 -0
- package/dist/{react → vercel/react}/useStreamingUIMessages.d.ts +1 -1
- package/dist/vercel/react/useStreamingUIMessages.d.ts.map +1 -0
- package/dist/{react → vercel/react}/useStreamingUIMessages.js +7 -3
- package/dist/vercel/react/useStreamingUIMessages.js.map +1 -0
- package/dist/{react → vercel/react}/useThreadMessages.d.ts +1 -1
- package/dist/vercel/react/useThreadMessages.d.ts.map +1 -0
- package/dist/{react → vercel/react}/useThreadMessages.js +1 -1
- package/dist/vercel/react/useThreadMessages.js.map +1 -0
- package/dist/{react → vercel/react}/useUIMessages.d.ts +1 -1
- package/dist/vercel/react/useUIMessages.d.ts.map +1 -0
- package/dist/{react → vercel/react}/useUIMessages.js +1 -1
- package/dist/vercel/react/useUIMessages.js.map +1 -0
- package/package.json +31 -24
- package/src/client/messages.ts +5 -107
- package/src/client/types.ts +0 -608
- package/src/component/_generated/component.ts +1089 -48
- package/src/component/messages.test.ts +273 -1
- package/src/component/messages.ts +62 -32
- package/src/component/streams.ts +47 -47
- package/src/component/threads.ts +5 -2
- package/src/eslintConfig.test.ts +44 -0
- package/src/react/index.ts +8 -5
- package/src/shared.ts +26 -36
- package/src/streaming/materializePersistedUIMessageChunks.test.ts +513 -0
- package/src/streaming/materializePersistedUIMessageChunks.ts +398 -0
- package/src/streaming/persistedUIMessageChunks.test.ts +205 -0
- package/src/streaming/persistedUIMessageChunks.ts +658 -0
- package/src/validators.test.ts +4 -1
- package/src/validators.ts +89 -8
- package/src/{UIMessages.combineUIMessages.test.ts → vercel/UIMessages.combineUIMessages.test.ts} +4 -1
- package/src/{UIMessages.ts → vercel/UIMessages.ts} +95 -3
- package/src/{client → vercel/client}/approval.test.ts +23 -13
- package/src/{client → vercel/client}/createTool.ts +62 -22
- package/src/{client → vercel/client}/definePlaygroundAPI.ts +15 -16
- package/src/{client → vercel/client}/files.ts +2 -2
- package/src/{client → vercel/client}/index.test.ts +99 -31
- package/src/vercel/client/messages.ts +182 -0
- package/src/{client → vercel/client}/mockModel.ts +38 -39
- package/src/{client → vercel/client}/saveInputMessages.test.ts +1 -1
- package/src/{client → vercel/client}/saveInputMessages.ts +3 -3
- package/src/{client → vercel/client}/search.test.ts +3 -3
- package/src/{client → vercel/client}/search.ts +4 -4
- package/src/{client → vercel/client}/setup.test.ts +6 -3
- package/src/vercel/client/start.test.ts +14 -0
- package/src/{client → vercel/client}/start.ts +147 -36
- package/src/vercel/client/streamText.test.ts +223 -0
- package/src/{client → vercel/client}/streamText.ts +102 -31
- package/src/{client → vercel/client}/streaming.integration.test.ts +6 -3
- package/src/{client → vercel/client}/streaming.test.ts +178 -4
- package/src/{client → vercel/client}/streaming.ts +114 -52
- package/src/vercel/client/types.test.ts +13 -0
- package/src/vercel/client/types.ts +679 -0
- package/src/{client → vercel/client}/utils.ts +13 -7
- package/src/{deltas.test.ts → vercel/deltas.test.ts} +384 -93
- package/src/{deltas.ts → vercel/deltas.ts} +218 -115
- package/src/{fromUIMessages.test.ts → vercel/fromUIMessages.test.ts} +17 -1
- package/src/{client → vercel}/index.ts +167 -84
- package/src/{mapping.test.ts → vercel/mapping.test.ts} +377 -92
- package/src/{mapping.ts → vercel/mapping.ts} +501 -137
- package/src/{react → vercel/react}/optimisticallySendMessage.ts +2 -2
- package/src/{react → vercel/react}/types.ts +1 -1
- package/src/{react → vercel/react}/useDeltaStreams.ts +6 -2
- package/src/{react → vercel/react}/useStreamingUIMessages.ts +7 -3
- package/src/{react → vercel/react}/useThreadMessages.ts +2 -2
- package/src/{react → vercel/react}/useUIMessages.ts +2 -2
- package/src/{toUIMessages.test.ts → vercel/toUIMessages.test.ts} +49 -2
- package/dist/UIMessages.d.ts.map +0 -1
- package/dist/UIMessages.js.map +0 -1
- package/dist/client/createTool.d.ts.map +0 -1
- package/dist/client/createTool.js.map +0 -1
- package/dist/client/definePlaygroundAPI.js.map +0 -1
- package/dist/client/files.d.ts.map +0 -1
- package/dist/client/files.js.map +0 -1
- package/dist/client/index.d.ts.map +0 -1
- package/dist/client/index.js.map +0 -1
- package/dist/client/mockModel.d.ts.map +0 -1
- package/dist/client/mockModel.js.map +0 -1
- package/dist/client/saveInputMessages.d.ts.map +0 -1
- package/dist/client/saveInputMessages.js.map +0 -1
- package/dist/client/search.d.ts.map +0 -1
- package/dist/client/search.js.map +0 -1
- package/dist/client/start.d.ts.map +0 -1
- package/dist/client/start.js.map +0 -1
- package/dist/client/streamText.d.ts.map +0 -1
- package/dist/client/streamText.js.map +0 -1
- package/dist/client/streaming.d.ts.map +0 -1
- package/dist/client/streaming.js.map +0 -1
- package/dist/client/utils.d.ts.map +0 -1
- package/dist/client/utils.js.map +0 -1
- package/dist/deltas.d.ts.map +0 -1
- package/dist/deltas.js.map +0 -1
- package/dist/mapping.d.ts.map +0 -1
- package/dist/mapping.js.map +0 -1
- package/dist/react/optimisticallySendMessage.d.ts.map +0 -1
- package/dist/react/optimisticallySendMessage.js.map +0 -1
- package/dist/react/types.d.ts.map +0 -1
- package/dist/react/useDeltaStreams.d.ts.map +0 -1
- package/dist/react/useDeltaStreams.js.map +0 -1
- package/dist/react/useStreamingUIMessages.d.ts.map +0 -1
- package/dist/react/useStreamingUIMessages.js.map +0 -1
- package/dist/react/useThreadMessages.d.ts.map +0 -1
- package/dist/react/useThreadMessages.js.map +0 -1
- package/dist/react/useUIMessages.d.ts.map +0 -1
- package/dist/react/useUIMessages.js.map +0 -1
- package/src/client/streamText.test.ts +0 -102
- /package/dist/{client → vercel/client}/files.js +0 -0
- /package/dist/{client → vercel/client}/saveInputMessages.js +0 -0
- /package/dist/{react → vercel/react}/optimisticallySendMessage.js +0 -0
- /package/dist/{react → vercel/react}/types.js +0 -0
- /package/src/{UIMessages.test.ts → vercel/UIMessages.test.ts} +0 -0
- /package/src/{react → vercel/react}/useUIMessages.test.ts +0 -0
package/src/validators.ts
CHANGED
|
@@ -15,6 +15,11 @@ export const vProviderMetadata = vProviderOptions;
|
|
|
15
15
|
const providerMetadata = providerOptions;
|
|
16
16
|
export type ProviderMetadata = Infer<typeof providerMetadata>;
|
|
17
17
|
|
|
18
|
+
export const vProviderReference = v.object({
|
|
19
|
+
type: v.literal("reference"),
|
|
20
|
+
reference: v.record(v.string(), v.string()),
|
|
21
|
+
});
|
|
22
|
+
|
|
18
23
|
export const vThreadStatus = v.union(
|
|
19
24
|
v.literal("active"),
|
|
20
25
|
v.literal("archived"), // unused
|
|
@@ -42,7 +47,7 @@ export const vTextPart = v.object({
|
|
|
42
47
|
|
|
43
48
|
export const vImagePart = v.object({
|
|
44
49
|
type: v.literal("image"),
|
|
45
|
-
image: v.union(v.string(), v.bytes()),
|
|
50
|
+
image: v.union(v.string(), v.bytes(), vProviderReference),
|
|
46
51
|
mediaType: v.optional(v.string()),
|
|
47
52
|
/** @deprecated Use `mediaType` instead. */
|
|
48
53
|
mimeType: v.optional(v.string()),
|
|
@@ -51,7 +56,7 @@ export const vImagePart = v.object({
|
|
|
51
56
|
|
|
52
57
|
export const vFilePart = v.object({
|
|
53
58
|
type: v.literal("file"),
|
|
54
|
-
data: v.union(v.string(), v.bytes()),
|
|
59
|
+
data: v.union(v.string(), v.bytes(), vProviderReference),
|
|
55
60
|
filename: v.optional(v.string()),
|
|
56
61
|
mediaType: v.optional(v.string()),
|
|
57
62
|
/** @deprecated Use `mediaType` instead. */
|
|
@@ -73,6 +78,21 @@ export const vReasoningPart = v.object({
|
|
|
73
78
|
providerMetadata,
|
|
74
79
|
});
|
|
75
80
|
|
|
81
|
+
export const vReasoningFilePart = v.object({
|
|
82
|
+
type: v.literal("reasoning-file"),
|
|
83
|
+
url: v.optional(v.string()),
|
|
84
|
+
data: v.optional(v.union(v.string(), v.bytes())),
|
|
85
|
+
mediaType: v.string(),
|
|
86
|
+
providerOptions,
|
|
87
|
+
providerMetadata,
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
export const vCustomContentPart = v.object({
|
|
91
|
+
type: v.literal("custom"),
|
|
92
|
+
kind: v.string(),
|
|
93
|
+
providerOptions,
|
|
94
|
+
providerMetadata,
|
|
95
|
+
});
|
|
76
96
|
export const vRedactedReasoningPart = v.object({
|
|
77
97
|
type: v.literal("redacted-reasoning"),
|
|
78
98
|
data: v.string(),
|
|
@@ -127,6 +147,8 @@ export const vToolCallPart = v.union(
|
|
|
127
147
|
/** @deprecated Use `input` instead. */
|
|
128
148
|
args: v.optional(v.any()),
|
|
129
149
|
providerExecuted: v.optional(v.boolean()),
|
|
150
|
+
title: v.optional(v.string()),
|
|
151
|
+
toolMetadata: v.optional(v.record(v.string(), v.any())),
|
|
130
152
|
providerOptions,
|
|
131
153
|
providerMetadata,
|
|
132
154
|
}),
|
|
@@ -139,6 +161,8 @@ export const vToolCallPart = v.union(
|
|
|
139
161
|
args: v.any(),
|
|
140
162
|
input: v.optional(v.any()),
|
|
141
163
|
providerExecuted: v.optional(v.boolean()),
|
|
164
|
+
title: v.optional(v.string()),
|
|
165
|
+
toolMetadata: v.optional(v.record(v.string(), v.any())),
|
|
142
166
|
providerOptions,
|
|
143
167
|
providerMetadata,
|
|
144
168
|
}),
|
|
@@ -178,6 +202,21 @@ export const vToolResultOutput = v.union(
|
|
|
178
202
|
text: v.string(),
|
|
179
203
|
providerOptions,
|
|
180
204
|
}),
|
|
205
|
+
v.object({
|
|
206
|
+
type: v.literal("file"),
|
|
207
|
+
data: v.union(
|
|
208
|
+
v.object({ type: v.literal("url"), url: v.string() }),
|
|
209
|
+
vProviderReference,
|
|
210
|
+
v.object({
|
|
211
|
+
type: v.literal("data"),
|
|
212
|
+
data: v.union(v.string(), v.bytes()),
|
|
213
|
+
}),
|
|
214
|
+
v.object({ type: v.literal("text"), text: v.string() }),
|
|
215
|
+
),
|
|
216
|
+
mediaType: v.string(),
|
|
217
|
+
filename: v.optional(v.string()),
|
|
218
|
+
providerOptions,
|
|
219
|
+
}),
|
|
181
220
|
/** @deprecated Use `image-data` or `file-data` instead. */
|
|
182
221
|
v.object({
|
|
183
222
|
type: v.literal("media"),
|
|
@@ -199,6 +238,7 @@ export const vToolResultOutput = v.union(
|
|
|
199
238
|
v.object({
|
|
200
239
|
type: v.literal("file-url"),
|
|
201
240
|
url: v.string(),
|
|
241
|
+
mediaType: v.optional(v.string()),
|
|
202
242
|
providerOptions,
|
|
203
243
|
}),
|
|
204
244
|
v.object({
|
|
@@ -214,6 +254,11 @@ export const vToolResultOutput = v.union(
|
|
|
214
254
|
fileId: v.union(v.string(), v.record(v.string(), v.string())),
|
|
215
255
|
providerOptions,
|
|
216
256
|
}),
|
|
257
|
+
v.object({
|
|
258
|
+
type: v.literal("file-reference"),
|
|
259
|
+
providerReference: v.record(v.string(), v.string()),
|
|
260
|
+
providerOptions,
|
|
261
|
+
}),
|
|
217
262
|
v.object({
|
|
218
263
|
type: v.literal("image-data"),
|
|
219
264
|
data: v.string(),
|
|
@@ -224,6 +269,11 @@ export const vToolResultOutput = v.union(
|
|
|
224
269
|
mediaType: v.string(),
|
|
225
270
|
providerOptions,
|
|
226
271
|
}),
|
|
272
|
+
v.object({
|
|
273
|
+
type: v.literal("image-file-reference"),
|
|
274
|
+
providerReference: v.record(v.string(), v.string()),
|
|
275
|
+
providerOptions,
|
|
276
|
+
}),
|
|
227
277
|
v.object({
|
|
228
278
|
type: v.literal("image-url"),
|
|
229
279
|
url: v.string(),
|
|
@@ -271,6 +321,8 @@ export const vToolApprovalRequest = v.object({
|
|
|
271
321
|
* ID of the tool call that the approval request is for.
|
|
272
322
|
*/
|
|
273
323
|
toolCallId: v.string(),
|
|
324
|
+
isAutomatic: v.optional(v.boolean()),
|
|
325
|
+
signature: v.optional(v.string()),
|
|
274
326
|
/** @todo Should we continue to include? */
|
|
275
327
|
providerMetadata,
|
|
276
328
|
/** @todo Should we continue to include? */
|
|
@@ -334,6 +386,8 @@ export const vAssistantContent = v.union(
|
|
|
334
386
|
vTextPart,
|
|
335
387
|
vFilePart,
|
|
336
388
|
vReasoningPart,
|
|
389
|
+
vReasoningFilePart,
|
|
390
|
+
vCustomContentPart,
|
|
337
391
|
vRedactedReasoningPart,
|
|
338
392
|
vToolCallPart,
|
|
339
393
|
vToolResultPart,
|
|
@@ -383,6 +437,8 @@ export type MessageContentParts =
|
|
|
383
437
|
| Infer<typeof vImagePart>
|
|
384
438
|
| Infer<typeof vFilePart>
|
|
385
439
|
| Infer<typeof vReasoningPart>
|
|
440
|
+
| Infer<typeof vReasoningFilePart>
|
|
441
|
+
| Infer<typeof vCustomContentPart>
|
|
386
442
|
| Infer<typeof vRedactedReasoningPart>
|
|
387
443
|
| Infer<typeof vToolCallPart>
|
|
388
444
|
| Infer<typeof vToolResultPart>
|
|
@@ -431,15 +487,34 @@ export const vFinishReason = v.union(
|
|
|
431
487
|
);
|
|
432
488
|
|
|
433
489
|
export const vUsage = v.object({
|
|
434
|
-
promptTokens: v.number(),
|
|
435
|
-
completionTokens: v.number(),
|
|
436
|
-
totalTokens: v.number(),
|
|
490
|
+
promptTokens: v.optional(v.number()),
|
|
491
|
+
completionTokens: v.optional(v.number()),
|
|
492
|
+
totalTokens: v.optional(v.number()),
|
|
437
493
|
reasoningTokens: v.optional(v.number()),
|
|
438
494
|
cachedInputTokens: v.optional(v.number()),
|
|
495
|
+
nonCachedInputTokens: v.optional(v.number()),
|
|
496
|
+
cacheWriteInputTokens: v.optional(v.number()),
|
|
497
|
+
textOutputTokens: v.optional(v.number()),
|
|
498
|
+
raw: v.optional(v.record(v.string(), v.any())),
|
|
439
499
|
});
|
|
440
500
|
export type Usage = Infer<typeof vUsage>;
|
|
441
501
|
|
|
442
502
|
export const vLanguageModelCallWarning = v.union(
|
|
503
|
+
v.object({
|
|
504
|
+
type: v.literal("unsupported"),
|
|
505
|
+
feature: v.string(),
|
|
506
|
+
details: v.optional(v.string()),
|
|
507
|
+
}),
|
|
508
|
+
v.object({
|
|
509
|
+
type: v.literal("compatibility"),
|
|
510
|
+
feature: v.string(),
|
|
511
|
+
details: v.optional(v.string()),
|
|
512
|
+
}),
|
|
513
|
+
v.object({
|
|
514
|
+
type: v.literal("deprecated"),
|
|
515
|
+
setting: v.string(),
|
|
516
|
+
message: v.string(),
|
|
517
|
+
}),
|
|
443
518
|
v.object({
|
|
444
519
|
type: v.literal("unsupported-setting"),
|
|
445
520
|
setting: v.string(),
|
|
@@ -515,8 +590,13 @@ export const vStorageOptions = v.object({
|
|
|
515
590
|
),
|
|
516
591
|
});
|
|
517
592
|
|
|
518
|
-
|
|
519
|
-
|
|
593
|
+
// Generated Convex actions keep the established `system` wire field. The
|
|
594
|
+
// Vercel adapter translates it to AI SDK 7's `instructions` before invoking
|
|
595
|
+
// the model, so action payloads never carry both spellings.
|
|
596
|
+
const vActionPromptFields = {
|
|
597
|
+
system: v.optional(
|
|
598
|
+
v.union(v.string(), vSystemMessage, v.array(vSystemMessage)),
|
|
599
|
+
),
|
|
520
600
|
prompt: v.optional(v.string()),
|
|
521
601
|
messages: v.optional(v.array(vMessage)),
|
|
522
602
|
promptMessageId: v.optional(v.string()),
|
|
@@ -543,7 +623,8 @@ const vCommonArgs = {
|
|
|
543
623
|
storageOptions: v.optional(vStorageOptions),
|
|
544
624
|
providerOptions,
|
|
545
625
|
callSettings: v.optional(vCallSettings),
|
|
546
|
-
|
|
626
|
+
allowSystemInMessages: v.optional(v.boolean()),
|
|
627
|
+
...vActionPromptFields,
|
|
547
628
|
};
|
|
548
629
|
|
|
549
630
|
export const vTextArgs = v.object({
|
package/src/{UIMessages.combineUIMessages.test.ts → vercel/UIMessages.combineUIMessages.test.ts}
RENAMED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { describe, it, expect } from "vitest";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
combineUIMessages,
|
|
4
|
+
type UIMessage,
|
|
5
|
+
} from "./UIMessages.js";
|
|
3
6
|
|
|
4
7
|
describe("combineUIMessages", () => {
|
|
5
8
|
it("should preserve all tool calls when combining messages", () => {
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
convertToModelMessages,
|
|
3
3
|
type UIMessage as AIUIMessage,
|
|
4
|
+
type CustomContentUIPart,
|
|
4
5
|
type DeepPartial,
|
|
5
6
|
type DynamicToolUIPart,
|
|
7
|
+
type ReasoningFileUIPart,
|
|
6
8
|
type ReasoningUIPart,
|
|
7
9
|
type SourceDocumentUIPart,
|
|
8
10
|
type SourceUrlUIPart,
|
|
@@ -13,6 +15,10 @@ import {
|
|
|
13
15
|
type UIDataTypes,
|
|
14
16
|
type UITools,
|
|
15
17
|
} from "ai";
|
|
18
|
+
import {
|
|
19
|
+
convertUint8ArrayToBase64,
|
|
20
|
+
type ReasoningFilePart,
|
|
21
|
+
} from "@ai-sdk/provider-utils";
|
|
16
22
|
import type { Infer } from "convex/values";
|
|
17
23
|
import { toModelMessage, fromModelMessage, toUIFilePart } from "./mapping.js";
|
|
18
24
|
import {
|
|
@@ -21,14 +27,14 @@ import {
|
|
|
21
27
|
isTool,
|
|
22
28
|
joinText,
|
|
23
29
|
sorted,
|
|
24
|
-
} from "
|
|
30
|
+
} from "../shared.js";
|
|
25
31
|
import type {
|
|
26
32
|
MessageDoc,
|
|
27
33
|
MessageStatus,
|
|
28
34
|
ProviderOptions,
|
|
29
35
|
SourcePart,
|
|
30
36
|
vSource,
|
|
31
|
-
} from "
|
|
37
|
+
} from "../validators.js";
|
|
32
38
|
import { omit, pick } from "convex-helpers";
|
|
33
39
|
|
|
34
40
|
export type UIStatus = "streaming" | MessageStatus;
|
|
@@ -153,6 +159,7 @@ function fromSourceParts(parts: UIMessage["parts"]): Infer<typeof vSource>[] {
|
|
|
153
159
|
id: part.sourceId,
|
|
154
160
|
providerMetadata: part.providerMetadata,
|
|
155
161
|
title: part.title,
|
|
162
|
+
filename: part.filename,
|
|
156
163
|
} satisfies Infer<typeof vSource>;
|
|
157
164
|
}
|
|
158
165
|
return undefined;
|
|
@@ -398,7 +405,13 @@ function createAssistantUIMessage<
|
|
|
398
405
|
|
|
399
406
|
// Extract approval parts from raw message content for UI rendering
|
|
400
407
|
type ApprovalPart =
|
|
401
|
-
| {
|
|
408
|
+
| {
|
|
409
|
+
type: "tool-approval-request";
|
|
410
|
+
approvalId: string;
|
|
411
|
+
toolCallId: string;
|
|
412
|
+
isAutomatic?: boolean;
|
|
413
|
+
signature?: string;
|
|
414
|
+
}
|
|
402
415
|
| {
|
|
403
416
|
type: "tool-approval-response";
|
|
404
417
|
approvalId: string;
|
|
@@ -496,6 +509,16 @@ function createAssistantUIMessage<
|
|
|
496
509
|
...contentPart,
|
|
497
510
|
} satisfies ReasoningUIPart);
|
|
498
511
|
break;
|
|
512
|
+
case "reasoning-file":
|
|
513
|
+
allParts.push(toUIReasoningFilePart(contentPart));
|
|
514
|
+
break;
|
|
515
|
+
case "custom":
|
|
516
|
+
allParts.push({
|
|
517
|
+
type: "custom",
|
|
518
|
+
kind: contentPart.kind,
|
|
519
|
+
providerMetadata: contentPart.providerOptions,
|
|
520
|
+
} satisfies CustomContentUIPart);
|
|
521
|
+
break;
|
|
499
522
|
case "file":
|
|
500
523
|
case "image":
|
|
501
524
|
allParts.push(toUIFilePart(contentPart));
|
|
@@ -613,6 +636,8 @@ function createAssistantUIMessage<
|
|
|
613
636
|
const typedPart = contentPart as {
|
|
614
637
|
toolCallId: string;
|
|
615
638
|
approvalId: string;
|
|
639
|
+
isAutomatic?: boolean;
|
|
640
|
+
signature?: string;
|
|
616
641
|
};
|
|
617
642
|
const toolCallPart = allParts.find(
|
|
618
643
|
(part) =>
|
|
@@ -623,6 +648,12 @@ function createAssistantUIMessage<
|
|
|
623
648
|
toolCallPart.state = "approval-requested";
|
|
624
649
|
(toolCallPart as ToolUIPart & { approval?: object }).approval = {
|
|
625
650
|
id: typedPart.approvalId,
|
|
651
|
+
...(typedPart.isAutomatic !== undefined
|
|
652
|
+
? { isAutomatic: typedPart.isAutomatic }
|
|
653
|
+
: {}),
|
|
654
|
+
...(typedPart.signature !== undefined
|
|
655
|
+
? { signature: typedPart.signature }
|
|
656
|
+
: {}),
|
|
626
657
|
};
|
|
627
658
|
} else {
|
|
628
659
|
console.warn(
|
|
@@ -647,9 +678,15 @@ function createAssistantUIMessage<
|
|
|
647
678
|
) as ToolUIPart | undefined;
|
|
648
679
|
|
|
649
680
|
if (toolCallPart) {
|
|
681
|
+
const approval = (
|
|
682
|
+
toolCallPart as ToolUIPart & {
|
|
683
|
+
approval?: { isAutomatic?: boolean; signature?: string };
|
|
684
|
+
}
|
|
685
|
+
).approval;
|
|
650
686
|
if (typedPart.approved) {
|
|
651
687
|
toolCallPart.state = "approval-responded";
|
|
652
688
|
(toolCallPart as ToolUIPart & { approval?: object }).approval = {
|
|
689
|
+
...approval,
|
|
653
690
|
id: typedPart.approvalId,
|
|
654
691
|
approved: true,
|
|
655
692
|
reason: typedPart.reason,
|
|
@@ -657,6 +694,7 @@ function createAssistantUIMessage<
|
|
|
657
694
|
} else {
|
|
658
695
|
toolCallPart.state = "output-denied";
|
|
659
696
|
(toolCallPart as ToolUIPart & { approval?: object }).approval = {
|
|
697
|
+
...approval,
|
|
660
698
|
id: typedPart.approvalId,
|
|
661
699
|
approved: false,
|
|
662
700
|
reason: typedPart.reason,
|
|
@@ -710,6 +748,12 @@ function createAssistantUIMessage<
|
|
|
710
748
|
// update state if not in a final state
|
|
711
749
|
(toolCallPart as ToolUIPart & { approval?: object }).approval = {
|
|
712
750
|
id: approvalPart.approvalId,
|
|
751
|
+
...(approvalPart.isAutomatic !== undefined
|
|
752
|
+
? { isAutomatic: approvalPart.isAutomatic }
|
|
753
|
+
: {}),
|
|
754
|
+
...(approvalPart.signature !== undefined
|
|
755
|
+
? { signature: approvalPart.signature }
|
|
756
|
+
: {}),
|
|
713
757
|
};
|
|
714
758
|
if (!finalStates.has(toolCallPart.state)) {
|
|
715
759
|
toolCallPart.state = "approval-requested";
|
|
@@ -725,7 +769,13 @@ function createAssistantUIMessage<
|
|
|
725
769
|
|
|
726
770
|
if (toolCallPart) {
|
|
727
771
|
// Always update approval info, but only update state if not in a final state
|
|
772
|
+
const approval = (
|
|
773
|
+
toolCallPart as ToolUIPart & {
|
|
774
|
+
approval?: { isAutomatic?: boolean; signature?: string };
|
|
775
|
+
}
|
|
776
|
+
).approval;
|
|
728
777
|
(toolCallPart as ToolUIPart & { approval?: object }).approval = {
|
|
778
|
+
...approval,
|
|
729
779
|
id: approvalPart.approvalId,
|
|
730
780
|
approved: approvalPart.approved,
|
|
731
781
|
reason: approvalPart.reason,
|
|
@@ -777,6 +827,48 @@ function createAssistantUIMessage<
|
|
|
777
827
|
};
|
|
778
828
|
}
|
|
779
829
|
|
|
830
|
+
function toUIReasoningFilePart(part: ReasoningFilePart): ReasoningFileUIPart {
|
|
831
|
+
const data = part.data;
|
|
832
|
+
return {
|
|
833
|
+
type: "reasoning-file",
|
|
834
|
+
mediaType: part.mediaType,
|
|
835
|
+
url: toUIReasoningFileUrl(data, part.mediaType),
|
|
836
|
+
providerMetadata: part.providerOptions,
|
|
837
|
+
};
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
function toUIReasoningFileUrl(
|
|
841
|
+
data: ReasoningFilePart["data"],
|
|
842
|
+
mediaType: string,
|
|
843
|
+
): string {
|
|
844
|
+
if (isTaggedReasoningFileData(data)) {
|
|
845
|
+
if (data.type === "url") return data.url.toString();
|
|
846
|
+
data = data.data;
|
|
847
|
+
}
|
|
848
|
+
if (data instanceof URL) return data.toString();
|
|
849
|
+
if (typeof data === "string") {
|
|
850
|
+
return data.startsWith("data:") ? data : `data:${mediaType};base64,${data}`;
|
|
851
|
+
}
|
|
852
|
+
const bytes =
|
|
853
|
+
data instanceof ArrayBuffer
|
|
854
|
+
? new Uint8Array(data)
|
|
855
|
+
: new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
|
856
|
+
return `data:${mediaType};base64,${convertUint8ArrayToBase64(bytes)}`;
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
function isTaggedReasoningFileData(
|
|
860
|
+
data: ReasoningFilePart["data"],
|
|
861
|
+
): data is Extract<ReasoningFilePart["data"], { type: string }> {
|
|
862
|
+
return (
|
|
863
|
+
typeof data === "object" &&
|
|
864
|
+
data !== null &&
|
|
865
|
+
!(data instanceof URL) &&
|
|
866
|
+
!(data instanceof ArrayBuffer) &&
|
|
867
|
+
!(data instanceof Uint8Array) &&
|
|
868
|
+
"type" in data
|
|
869
|
+
);
|
|
870
|
+
}
|
|
871
|
+
|
|
780
872
|
function toSourcePart(
|
|
781
873
|
part: SourcePart | Infer<typeof vSource>,
|
|
782
874
|
): SourceUrlUIPart | SourceDocumentUIPart {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, expect, test } from "vitest";
|
|
2
|
-
import { Agent, createTool } from "
|
|
2
|
+
import { Agent, createTool } from "../index.js";
|
|
3
3
|
import type {
|
|
4
4
|
DataModelFromSchemaDefinition,
|
|
5
5
|
ApiFromModules,
|
|
@@ -145,6 +145,14 @@ export const testApproveFlow = action({
|
|
|
145
145
|
threadId: thread.threadId,
|
|
146
146
|
paginationOpts: { cursor: null, numItems: 20 },
|
|
147
147
|
});
|
|
148
|
+
const toolResults = allMessages.page.flatMap((message) =>
|
|
149
|
+
Array.isArray(message.message?.content)
|
|
150
|
+
? message.message.content.filter(
|
|
151
|
+
(part) =>
|
|
152
|
+
part.type === "tool-result" && part.toolCallId === "tc-approve",
|
|
153
|
+
)
|
|
154
|
+
: [],
|
|
155
|
+
);
|
|
148
156
|
|
|
149
157
|
return {
|
|
150
158
|
approvalId,
|
|
@@ -154,8 +162,9 @@ export const testApproveFlow = action({
|
|
|
154
162
|
secondSavedCount: result2.savedMessages?.length ?? 0,
|
|
155
163
|
totalThreadMessages: allMessages.page.length,
|
|
156
164
|
threadMessageRoles: allMessages.page.map((m) => m.message?.role),
|
|
165
|
+
toolResults,
|
|
157
166
|
usageCallCount: usageCalls.length,
|
|
158
|
-
// Verify usage data includes detail fields
|
|
167
|
+
// Verify usage data includes detail fields.
|
|
159
168
|
lastUsage: usageCalls.at(-1),
|
|
160
169
|
};
|
|
161
170
|
},
|
|
@@ -431,8 +440,6 @@ describe("Tool Approval Workflow", () => {
|
|
|
431
440
|
expect(result.firstSavedCount).toBeGreaterThanOrEqual(2);
|
|
432
441
|
// Second call: tool-result + assistant text
|
|
433
442
|
expect(result.secondSavedCount).toBeGreaterThanOrEqual(1);
|
|
434
|
-
// Thread should have (ascending): user, assistant(tool-call+approval),
|
|
435
|
-
// tool(approval-response), tool(tool-result), assistant(text)
|
|
436
443
|
// listMessages returns descending order:
|
|
437
444
|
expect(result.threadMessageRoles).toEqual([
|
|
438
445
|
"assistant", // final text
|
|
@@ -441,9 +448,17 @@ describe("Tool Approval Workflow", () => {
|
|
|
441
448
|
"assistant", // tool-call + approval-request
|
|
442
449
|
"user", // prompt
|
|
443
450
|
]);
|
|
451
|
+
expect(result.toolResults).toEqual([
|
|
452
|
+
{
|
|
453
|
+
type: "tool-result",
|
|
454
|
+
toolCallId: "tc-approve",
|
|
455
|
+
toolName: "deleteFile",
|
|
456
|
+
output: { type: "text", value: "Deleted: test.txt" },
|
|
457
|
+
},
|
|
458
|
+
]);
|
|
444
459
|
// Usage handler should be called for each generateText call
|
|
445
460
|
expect(result.usageCallCount).toBeGreaterThanOrEqual(2);
|
|
446
|
-
// Usage data should include
|
|
461
|
+
// Usage data should include detail fields.
|
|
447
462
|
expect(result.lastUsage).toBeDefined();
|
|
448
463
|
expect(result.lastUsage!.inputTokenDetails).toBeDefined();
|
|
449
464
|
expect(result.lastUsage!.outputTokenDetails).toBeDefined();
|
|
@@ -457,9 +472,7 @@ describe("Tool Approval Workflow", () => {
|
|
|
457
472
|
expect(result.approvalId).toBeDefined();
|
|
458
473
|
expect(result.firstText).toBe("");
|
|
459
474
|
expect(result.secondText).toBe("OK, I won't delete that file.");
|
|
460
|
-
// Same message ordering as approve flow
|
|
461
|
-
// user, assistant(tool-call+approval), tool(denial-response),
|
|
462
|
-
// tool(execution-denied result), assistant(text)
|
|
475
|
+
// Same message ordering as approve flow.
|
|
463
476
|
expect(result.threadMessageRoles).toEqual([
|
|
464
477
|
"assistant",
|
|
465
478
|
"tool",
|
|
@@ -483,14 +496,11 @@ describe("Tool Approval Workflow", () => {
|
|
|
483
496
|
expect(result.secondText).toBe(
|
|
484
497
|
"Done! Deleted old.txt and renamed a.txt to b.txt.",
|
|
485
498
|
);
|
|
486
|
-
//
|
|
487
|
-
// (write-time merge in respondToToolCallApproval via findApprovalContext)
|
|
488
|
-
// Thread: user, assistant(2 tool-calls + 2 approvals),
|
|
489
|
-
// tool(2 approval-responses merged), tool(2 tool-results), assistant(text)
|
|
499
|
+
// Executed results are persisted separately from approval responses.
|
|
490
500
|
expect(result.threadMessageRoles).toEqual([
|
|
491
501
|
"assistant", // final text
|
|
492
502
|
"tool", // tool-results
|
|
493
|
-
"tool", // approval-responses
|
|
503
|
+
"tool", // approval-responses
|
|
494
504
|
"assistant", // tool-calls + approval-requests
|
|
495
505
|
"user", // prompt
|
|
496
506
|
]);
|