@convex-dev/agent 0.6.3 → 0.7.0-alpha.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/apiKeys.js +5 -5
- package/dist/component/apiKeys.js.map +1 -1
- package/dist/component/files.d.ts.map +1 -1
- package/dist/component/files.js +13 -11
- package/dist/component/files.js.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 +83 -47
- 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 +46 -47
- package/dist/component/streams.js.map +1 -1
- package/dist/component/threads.d.ts.map +1 -1
- package/dist/component/threads.js +8 -9
- package/dist/component/threads.js.map +1 -1
- package/dist/component/users.js +2 -2
- package/dist/component/users.js.map +1 -1
- package/dist/component/vector/index.d.ts.map +1 -1
- package/dist/component/vector/index.js +14 -8
- package/dist/component/vector/index.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 +593 -134
- package/dist/{client → vercel/client}/definePlaygroundAPI.d.ts.map +1 -1
- package/dist/{client → vercel/client}/definePlaygroundAPI.js +13 -9
- 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/vercel/deltas.d.ts +31 -0
- package/dist/vercel/deltas.d.ts.map +1 -0
- package/dist/vercel/deltas.js +525 -0
- package/dist/vercel/deltas.js.map +1 -0
- package/dist/{client → vercel}/index.d.ts +484 -97
- package/dist/vercel/index.d.ts.map +1 -0
- package/dist/{client → vercel}/index.js +65 -38
- package/dist/vercel/index.js.map +1 -0
- package/dist/{mapping.d.ts → vercel/mapping.d.ts} +5 -13
- package/dist/vercel/mapping.d.ts.map +1 -0
- package/dist/{mapping.js → vercel/mapping.js} +411 -112
- 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/vercel/react/useStreamingUIMessages.js +112 -0
- 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 +2 -1
- package/dist/vercel/react/useUIMessages.d.ts.map +1 -0
- package/dist/{react → vercel/react}/useUIMessages.js +8 -4
- package/dist/vercel/react/useUIMessages.js.map +1 -0
- package/package.json +30 -22
- package/src/client/messages.ts +5 -107
- package/src/client/types.ts +0 -621
- package/src/component/_generated/component.ts +1089 -48
- package/src/component/apiKeys.ts +5 -5
- package/src/component/files.test.ts +1 -1
- package/src/component/files.ts +14 -12
- package/src/component/messages.test.ts +273 -1
- package/src/component/messages.ts +99 -57
- package/src/component/streams.ts +80 -64
- package/src/component/threads.ts +12 -9
- package/src/component/users.ts +2 -2
- package/src/component/vector/index.ts +14 -7
- 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} +96 -5
- package/src/{client → vercel/client}/approval.test.ts +48 -19
- package/src/{client → vercel/client}/createTool.ts +63 -23
- package/src/{client → vercel/client}/definePlaygroundAPI.ts +44 -29
- package/src/{client → vercel/client}/files.ts +2 -2
- package/src/{client → vercel/client}/index.test.ts +162 -3
- 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 +7 -4
- 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 +40 -115
- 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/vercel/deltas.test.ts +898 -0
- package/src/vercel/deltas.ts +633 -0
- package/src/{fromUIMessages.test.ts → vercel/fromUIMessages.test.ts} +17 -1
- package/src/{client → vercel}/index.ts +169 -62
- package/src/vercel/mapping.test.ts +965 -0
- package/src/{mapping.ts → vercel/mapping.ts} +501 -131
- 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 +67 -35
- package/src/{react → vercel/react}/useThreadMessages.ts +2 -2
- package/src/{react → vercel/react}/useUIMessages.test.ts +80 -1
- package/src/{react → vercel/react}/useUIMessages.ts +13 -5
- 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 +0 -43
- package/dist/deltas.d.ts.map +0 -1
- package/dist/deltas.js +0 -446
- 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 +0 -92
- 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/src/deltas.test.ts +0 -626
- package/src/deltas.ts +0 -569
- package/src/mapping.test.ts +0 -402
- /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/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,
|
|
@@ -744,8 +794,7 @@ function createAssistantUIMessage<
|
|
|
744
794
|
// Process execution-denied results to update tool call states
|
|
745
795
|
for (const denied of executionDeniedResults) {
|
|
746
796
|
const toolCallPart = allParts.find(
|
|
747
|
-
(part) =>
|
|
748
|
-
"toolCallId" in part && part.toolCallId === denied.toolCallId,
|
|
797
|
+
(part) => "toolCallId" in part && part.toolCallId === denied.toolCallId,
|
|
749
798
|
) as ToolUIPart | undefined;
|
|
750
799
|
|
|
751
800
|
if (toolCallPart) {
|
|
@@ -778,6 +827,48 @@ function createAssistantUIMessage<
|
|
|
778
827
|
};
|
|
779
828
|
}
|
|
780
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
|
+
|
|
781
872
|
function toSourcePart(
|
|
782
873
|
part: SourcePart | Infer<typeof vSource>,
|
|
783
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,
|
|
@@ -65,7 +65,8 @@ const renameFileTool = createTool({
|
|
|
65
65
|
newName: z.string(),
|
|
66
66
|
}),
|
|
67
67
|
needsApproval: () => true,
|
|
68
|
-
execute: async (_ctx, input) =>
|
|
68
|
+
execute: async (_ctx, input) =>
|
|
69
|
+
`Renamed: ${input.oldName} → ${input.newName}`,
|
|
69
70
|
});
|
|
70
71
|
|
|
71
72
|
// --- Agents (separate mock model instances to avoid shared callIndex) ---
|
|
@@ -144,6 +145,14 @@ export const testApproveFlow = action({
|
|
|
144
145
|
threadId: thread.threadId,
|
|
145
146
|
paginationOpts: { cursor: null, numItems: 20 },
|
|
146
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
|
+
);
|
|
147
156
|
|
|
148
157
|
return {
|
|
149
158
|
approvalId,
|
|
@@ -153,8 +162,9 @@ export const testApproveFlow = action({
|
|
|
153
162
|
secondSavedCount: result2.savedMessages?.length ?? 0,
|
|
154
163
|
totalThreadMessages: allMessages.page.length,
|
|
155
164
|
threadMessageRoles: allMessages.page.map((m) => m.message?.role),
|
|
165
|
+
toolResults,
|
|
156
166
|
usageCallCount: usageCalls.length,
|
|
157
|
-
// Verify usage data includes detail fields
|
|
167
|
+
// Verify usage data includes detail fields.
|
|
158
168
|
lastUsage: usageCalls.at(-1),
|
|
159
169
|
};
|
|
160
170
|
},
|
|
@@ -291,7 +301,12 @@ const multiToolAgent = new Agent(components.agent, {
|
|
|
291
301
|
},
|
|
292
302
|
],
|
|
293
303
|
// Step 2: after both tools execute, model responds
|
|
294
|
-
[
|
|
304
|
+
[
|
|
305
|
+
{
|
|
306
|
+
type: "text",
|
|
307
|
+
text: "Done! Deleted old.txt and renamed a.txt to b.txt.",
|
|
308
|
+
},
|
|
309
|
+
],
|
|
295
310
|
],
|
|
296
311
|
}),
|
|
297
312
|
stopWhen: stepCountIs(5),
|
|
@@ -377,14 +392,22 @@ export const submitApprovalForMultiToolAgent = mutation({
|
|
|
377
392
|
});
|
|
378
393
|
|
|
379
394
|
export const submitApprovalForApprovalAgent = mutation({
|
|
380
|
-
args: {
|
|
395
|
+
args: {
|
|
396
|
+
threadId: v.string(),
|
|
397
|
+
approvalId: v.string(),
|
|
398
|
+
reason: v.optional(v.string()),
|
|
399
|
+
},
|
|
381
400
|
handler: async (ctx, { threadId, approvalId, reason }) => {
|
|
382
401
|
return approvalAgent.approveToolCall(ctx, { threadId, approvalId, reason });
|
|
383
402
|
},
|
|
384
403
|
});
|
|
385
404
|
|
|
386
405
|
export const submitDenialForDenialAgent = mutation({
|
|
387
|
-
args: {
|
|
406
|
+
args: {
|
|
407
|
+
threadId: v.string(),
|
|
408
|
+
approvalId: v.string(),
|
|
409
|
+
reason: v.optional(v.string()),
|
|
410
|
+
},
|
|
388
411
|
handler: async (ctx, { threadId, approvalId, reason }) => {
|
|
389
412
|
return denialAgent.denyToolCall(ctx, { threadId, approvalId, reason });
|
|
390
413
|
},
|
|
@@ -417,8 +440,6 @@ describe("Tool Approval Workflow", () => {
|
|
|
417
440
|
expect(result.firstSavedCount).toBeGreaterThanOrEqual(2);
|
|
418
441
|
// Second call: tool-result + assistant text
|
|
419
442
|
expect(result.secondSavedCount).toBeGreaterThanOrEqual(1);
|
|
420
|
-
// Thread should have (ascending): user, assistant(tool-call+approval),
|
|
421
|
-
// tool(approval-response), tool(tool-result), assistant(text)
|
|
422
443
|
// listMessages returns descending order:
|
|
423
444
|
expect(result.threadMessageRoles).toEqual([
|
|
424
445
|
"assistant", // final text
|
|
@@ -427,9 +448,17 @@ describe("Tool Approval Workflow", () => {
|
|
|
427
448
|
"assistant", // tool-call + approval-request
|
|
428
449
|
"user", // prompt
|
|
429
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
|
+
]);
|
|
430
459
|
// Usage handler should be called for each generateText call
|
|
431
460
|
expect(result.usageCallCount).toBeGreaterThanOrEqual(2);
|
|
432
|
-
// Usage data should include
|
|
461
|
+
// Usage data should include detail fields.
|
|
433
462
|
expect(result.lastUsage).toBeDefined();
|
|
434
463
|
expect(result.lastUsage!.inputTokenDetails).toBeDefined();
|
|
435
464
|
expect(result.lastUsage!.outputTokenDetails).toBeDefined();
|
|
@@ -443,9 +472,7 @@ describe("Tool Approval Workflow", () => {
|
|
|
443
472
|
expect(result.approvalId).toBeDefined();
|
|
444
473
|
expect(result.firstText).toBe("");
|
|
445
474
|
expect(result.secondText).toBe("OK, I won't delete that file.");
|
|
446
|
-
// Same message ordering as approve flow
|
|
447
|
-
// user, assistant(tool-call+approval), tool(denial-response),
|
|
448
|
-
// tool(execution-denied result), assistant(text)
|
|
475
|
+
// Same message ordering as approve flow.
|
|
449
476
|
expect(result.threadMessageRoles).toEqual([
|
|
450
477
|
"assistant",
|
|
451
478
|
"tool",
|
|
@@ -469,14 +496,11 @@ describe("Tool Approval Workflow", () => {
|
|
|
469
496
|
expect(result.secondText).toBe(
|
|
470
497
|
"Done! Deleted old.txt and renamed a.txt to b.txt.",
|
|
471
498
|
);
|
|
472
|
-
//
|
|
473
|
-
// (write-time merge in respondToToolCallApproval via findApprovalContext)
|
|
474
|
-
// Thread: user, assistant(2 tool-calls + 2 approvals),
|
|
475
|
-
// tool(2 approval-responses merged), tool(2 tool-results), assistant(text)
|
|
499
|
+
// Executed results are persisted separately from approval responses.
|
|
476
500
|
expect(result.threadMessageRoles).toEqual([
|
|
477
501
|
"assistant", // final text
|
|
478
502
|
"tool", // tool-results
|
|
479
|
-
"tool", // approval-responses
|
|
503
|
+
"tool", // approval-responses
|
|
480
504
|
"assistant", // tool-calls + approval-requests
|
|
481
505
|
"user", // prompt
|
|
482
506
|
]);
|
|
@@ -485,10 +509,15 @@ describe("Tool Approval Workflow", () => {
|
|
|
485
509
|
test("approve remains valid with an intervening thread message", async () => {
|
|
486
510
|
usageCalls.length = 0;
|
|
487
511
|
const t = initConvexTest(schema);
|
|
488
|
-
const result = await t.action(
|
|
512
|
+
const result = await t.action(
|
|
513
|
+
testApi.testApproveFlowWithInterveningMessage,
|
|
514
|
+
{},
|
|
515
|
+
);
|
|
489
516
|
|
|
490
517
|
expect(result.secondText).toBe("Done! I deleted test.txt.");
|
|
491
518
|
expect(result.approvalResponseOrder).toBe(result.approvalRequestOrder);
|
|
492
|
-
expect(result.interveningOrder).toBeGreaterThan(
|
|
519
|
+
expect(result.interveningOrder).toBeGreaterThan(
|
|
520
|
+
result.approvalResponseOrder,
|
|
521
|
+
);
|
|
493
522
|
});
|
|
494
523
|
});
|