@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
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { JSONObject } from "@ai-sdk/provider";
|
|
2
|
+
import type {
|
|
3
|
+
Context,
|
|
4
|
+
Experimental_SandboxSession,
|
|
5
|
+
ToolResultOutput,
|
|
6
|
+
} from "@ai-sdk/provider-utils";
|
|
2
7
|
import type {
|
|
3
8
|
FlexibleSchema,
|
|
4
9
|
ModelMessage,
|
|
@@ -8,8 +13,8 @@ import type {
|
|
|
8
13
|
} from "ai";
|
|
9
14
|
import { tool } from "ai";
|
|
10
15
|
import type { GenericActionCtx, GenericDataModel } from "convex/server";
|
|
11
|
-
import type { ProviderOptions } from "
|
|
12
|
-
import type { Agent } from "
|
|
16
|
+
import type { ProviderOptions } from "../../validators.js";
|
|
17
|
+
import type { Agent } from "../index.js";
|
|
13
18
|
|
|
14
19
|
const MIGRATION_URL = "node_modules/@convex-dev/agent/MIGRATION.md";
|
|
15
20
|
const warnedDeprecations = new Set<string>();
|
|
@@ -28,12 +33,16 @@ export type ToolCtx<DataModel extends GenericDataModel = GenericDataModel> =
|
|
|
28
33
|
messageId?: string;
|
|
29
34
|
};
|
|
30
35
|
|
|
36
|
+
export type AgentToolExecutionOptions<TOOL_CONTEXT extends Context = Context> =
|
|
37
|
+
ToolExecutionOptions<TOOL_CONTEXT>;
|
|
38
|
+
|
|
31
39
|
/**
|
|
32
40
|
* Function that is called to determine if the tool needs approval before it can be executed.
|
|
33
41
|
*/
|
|
34
42
|
export type ToolNeedsApprovalFunctionCtx<
|
|
35
43
|
INPUT,
|
|
36
44
|
Ctx extends ToolCtx = ToolCtx,
|
|
45
|
+
TOOL_CONTEXT extends Context = Context,
|
|
37
46
|
> = (
|
|
38
47
|
ctx: Ctx,
|
|
39
48
|
input: INPUT,
|
|
@@ -52,7 +61,7 @@ export type ToolNeedsApprovalFunctionCtx<
|
|
|
52
61
|
*
|
|
53
62
|
* Experimental (can break in patch releases).
|
|
54
63
|
*/
|
|
55
|
-
|
|
64
|
+
context: TOOL_CONTEXT;
|
|
56
65
|
},
|
|
57
66
|
) => boolean | PromiseLike<boolean>;
|
|
58
67
|
|
|
@@ -60,10 +69,11 @@ export type ToolExecuteFunctionCtx<
|
|
|
60
69
|
INPUT,
|
|
61
70
|
OUTPUT,
|
|
62
71
|
Ctx extends ToolCtx = ToolCtx,
|
|
72
|
+
TOOL_CONTEXT extends Context = Context,
|
|
63
73
|
> = (
|
|
64
74
|
ctx: Ctx,
|
|
65
75
|
input: INPUT,
|
|
66
|
-
options:
|
|
76
|
+
options: AgentToolExecutionOptions<TOOL_CONTEXT>,
|
|
67
77
|
) => AsyncIterable<OUTPUT> | PromiseLike<OUTPUT>;
|
|
68
78
|
|
|
69
79
|
type NeverOptional<N, T> = 0 extends 1 & N
|
|
@@ -83,6 +93,7 @@ export type ToolOutputPropertiesCtx<
|
|
|
83
93
|
INPUT,
|
|
84
94
|
OUTPUT,
|
|
85
95
|
Ctx extends ToolCtx = ToolCtx,
|
|
96
|
+
TOOL_CONTEXT extends Context = Context,
|
|
86
97
|
> = NeverOptional<
|
|
87
98
|
OUTPUT,
|
|
88
99
|
{
|
|
@@ -93,7 +104,7 @@ export type ToolOutputPropertiesCtx<
|
|
|
93
104
|
* @param input - The input of the tool call.
|
|
94
105
|
* @param options.abortSignal - A signal that can be used to abort the tool call.
|
|
95
106
|
*/
|
|
96
|
-
execute?: ToolExecuteFunctionCtx<INPUT, OUTPUT, Ctx>;
|
|
107
|
+
execute?: ToolExecuteFunctionCtx<INPUT, OUTPUT, Ctx, TOOL_CONTEXT>;
|
|
97
108
|
outputSchema?: FlexibleSchema<OUTPUT>;
|
|
98
109
|
/**
|
|
99
110
|
* @deprecated Removed in v0.6.0. Use `execute` instead.
|
|
@@ -130,17 +141,27 @@ export type ToolInputProperties<INPUT> = {
|
|
|
130
141
|
* @param tool The tool. See https://sdk.vercel.ai/docs/ai-sdk-core/tools-and-tool-calling
|
|
131
142
|
* Currently contains deprecated parameters `args` and `handler` to maintain backwards compatibility
|
|
132
143
|
* but these will be removed in the future. Use `inputSchema` and `execute` instead, respectively.
|
|
133
|
-
*
|
|
144
|
+
*
|
|
134
145
|
* @returns A tool to be used with the AI SDK.
|
|
135
146
|
*/
|
|
136
|
-
export function createTool<
|
|
147
|
+
export function createTool<
|
|
148
|
+
INPUT,
|
|
149
|
+
OUTPUT,
|
|
150
|
+
Ctx extends ToolCtx = ToolCtx,
|
|
151
|
+
TOOL_CONTEXT extends Context = Context,
|
|
152
|
+
>(
|
|
137
153
|
def: {
|
|
138
154
|
/**
|
|
139
155
|
* An optional description of what the tool does.
|
|
140
156
|
* Will be used by the language model to decide whether to use the tool.
|
|
141
157
|
* Not used for provider-defined tools.
|
|
142
158
|
*/
|
|
143
|
-
description?:
|
|
159
|
+
description?:
|
|
160
|
+
| string
|
|
161
|
+
| ((options: {
|
|
162
|
+
context: NoInfer<TOOL_CONTEXT>;
|
|
163
|
+
experimental_sandbox?: Experimental_SandboxSession;
|
|
164
|
+
}) => string);
|
|
144
165
|
/**
|
|
145
166
|
* An optional title of the tool.
|
|
146
167
|
*/
|
|
@@ -151,6 +172,8 @@ export function createTool<INPUT, OUTPUT, Ctx extends ToolCtx = ToolCtx>(
|
|
|
151
172
|
* functionality that can be fully encapsulated in the provider.
|
|
152
173
|
*/
|
|
153
174
|
providerOptions?: ProviderOptions;
|
|
175
|
+
metadata?: JSONObject;
|
|
176
|
+
contextSchema?: FlexibleSchema<TOOL_CONTEXT>;
|
|
154
177
|
} & ToolInputProperties<INPUT> & {
|
|
155
178
|
/**
|
|
156
179
|
* An optional list of input examples that show the language
|
|
@@ -166,7 +189,8 @@ export function createTool<INPUT, OUTPUT, Ctx extends ToolCtx = ToolCtx>(
|
|
|
166
189
|
| boolean
|
|
167
190
|
| ToolNeedsApprovalFunctionCtx<
|
|
168
191
|
[INPUT] extends [never] ? unknown : INPUT,
|
|
169
|
-
Ctx
|
|
192
|
+
Ctx,
|
|
193
|
+
TOOL_CONTEXT
|
|
170
194
|
>;
|
|
171
195
|
/**
|
|
172
196
|
* Strict mode setting for the tool.
|
|
@@ -186,7 +210,7 @@ export function createTool<INPUT, OUTPUT, Ctx extends ToolCtx = ToolCtx>(
|
|
|
186
210
|
*/
|
|
187
211
|
onInputStart?: (
|
|
188
212
|
ctx: Ctx,
|
|
189
|
-
options:
|
|
213
|
+
options: AgentToolExecutionOptions<TOOL_CONTEXT>,
|
|
190
214
|
) => void | PromiseLike<void>;
|
|
191
215
|
/**
|
|
192
216
|
* Optional function that is called when an argument streaming delta is available.
|
|
@@ -194,7 +218,9 @@ export function createTool<INPUT, OUTPUT, Ctx extends ToolCtx = ToolCtx>(
|
|
|
194
218
|
*/
|
|
195
219
|
onInputDelta?: (
|
|
196
220
|
ctx: Ctx,
|
|
197
|
-
options: {
|
|
221
|
+
options: {
|
|
222
|
+
inputTextDelta: string;
|
|
223
|
+
} & AgentToolExecutionOptions<TOOL_CONTEXT>,
|
|
198
224
|
) => void | PromiseLike<void>;
|
|
199
225
|
/**
|
|
200
226
|
* Optional function that is called when a tool call can be started,
|
|
@@ -204,9 +230,9 @@ export function createTool<INPUT, OUTPUT, Ctx extends ToolCtx = ToolCtx>(
|
|
|
204
230
|
ctx: Ctx,
|
|
205
231
|
options: {
|
|
206
232
|
input: [INPUT] extends [never] ? unknown : INPUT;
|
|
207
|
-
} &
|
|
233
|
+
} & AgentToolExecutionOptions<TOOL_CONTEXT>,
|
|
208
234
|
) => void | PromiseLike<void>;
|
|
209
|
-
} & ToolOutputPropertiesCtx<INPUT, OUTPUT, Ctx> & {
|
|
235
|
+
} & ToolOutputPropertiesCtx<INPUT, OUTPUT, Ctx, TOOL_CONTEXT> & {
|
|
210
236
|
/**
|
|
211
237
|
* Optional conversion function that maps the tool result to an output that can be used by the language model.
|
|
212
238
|
*
|
|
@@ -234,7 +260,7 @@ export function createTool<INPUT, OUTPUT, Ctx extends ToolCtx = ToolCtx>(
|
|
|
234
260
|
},
|
|
235
261
|
) => ToolResultOutput | PromiseLike<ToolResultOutput>;
|
|
236
262
|
},
|
|
237
|
-
): Tool<INPUT, OUTPUT> {
|
|
263
|
+
): Tool<INPUT, OUTPUT, TOOL_CONTEXT> {
|
|
238
264
|
// Runtime backwards compat - types will show errors but runtime still works
|
|
239
265
|
const inputSchema = def.inputSchema ?? (def as any).args;
|
|
240
266
|
if (!inputSchema)
|
|
@@ -260,16 +286,18 @@ export function createTool<INPUT, OUTPUT, Ctx extends ToolCtx = ToolCtx>(
|
|
|
260
286
|
" handler function, define an outputSchema, or both",
|
|
261
287
|
);
|
|
262
288
|
|
|
263
|
-
const t = tool<INPUT, OUTPUT>({
|
|
289
|
+
const t = tool<INPUT, OUTPUT, TOOL_CONTEXT>({
|
|
264
290
|
type: "function",
|
|
265
291
|
__acceptsCtx: true,
|
|
266
292
|
ctx: def.ctx,
|
|
267
293
|
description: def.description,
|
|
268
294
|
title: def.title,
|
|
269
295
|
providerOptions: def.providerOptions,
|
|
296
|
+
metadata: def.metadata,
|
|
270
297
|
inputSchema,
|
|
298
|
+
contextSchema: def.contextSchema,
|
|
271
299
|
inputExamples: def.inputExamples,
|
|
272
|
-
needsApproval(this: Tool<INPUT, OUTPUT>, input, options) {
|
|
300
|
+
needsApproval(this: Tool<INPUT, OUTPUT, TOOL_CONTEXT>, input, options) {
|
|
273
301
|
const needsApproval = def.needsApproval;
|
|
274
302
|
if (!needsApproval || typeof needsApproval === "boolean")
|
|
275
303
|
return Boolean(needsApproval);
|
|
@@ -287,9 +315,9 @@ export function createTool<INPUT, OUTPUT, Ctx extends ToolCtx = ToolCtx>(
|
|
|
287
315
|
...(executeHandler
|
|
288
316
|
? {
|
|
289
317
|
execute(
|
|
290
|
-
this: Tool<INPUT, OUTPUT>,
|
|
318
|
+
this: Tool<INPUT, OUTPUT, TOOL_CONTEXT>,
|
|
291
319
|
input: INPUT,
|
|
292
|
-
options: ToolExecutionOptions
|
|
320
|
+
options: ToolExecutionOptions<TOOL_CONTEXT>,
|
|
293
321
|
) {
|
|
294
322
|
if (!getCtx(this)) {
|
|
295
323
|
throw new Error(
|
|
@@ -306,25 +334,37 @@ export function createTool<INPUT, OUTPUT, Ctx extends ToolCtx = ToolCtx>(
|
|
|
306
334
|
});
|
|
307
335
|
if (def.onInputStart) {
|
|
308
336
|
const origOnInputStart = def.onInputStart;
|
|
309
|
-
t.onInputStart = function (
|
|
337
|
+
t.onInputStart = function (
|
|
338
|
+
this: Tool<INPUT, OUTPUT, TOOL_CONTEXT>,
|
|
339
|
+
options,
|
|
340
|
+
) {
|
|
310
341
|
return origOnInputStart.call(this, getCtx(this), options);
|
|
311
342
|
};
|
|
312
343
|
}
|
|
313
344
|
if (def.onInputDelta) {
|
|
314
345
|
const origOnInputDelta = def.onInputDelta;
|
|
315
|
-
t.onInputDelta = function (
|
|
346
|
+
t.onInputDelta = function (
|
|
347
|
+
this: Tool<INPUT, OUTPUT, TOOL_CONTEXT>,
|
|
348
|
+
options,
|
|
349
|
+
) {
|
|
316
350
|
return origOnInputDelta.call(this, getCtx(this), options);
|
|
317
351
|
};
|
|
318
352
|
}
|
|
319
353
|
if (def.onInputAvailable) {
|
|
320
354
|
const origOnInputAvailable = def.onInputAvailable;
|
|
321
|
-
t.onInputAvailable = function (
|
|
355
|
+
t.onInputAvailable = function (
|
|
356
|
+
this: Tool<INPUT, OUTPUT, TOOL_CONTEXT>,
|
|
357
|
+
options,
|
|
358
|
+
) {
|
|
322
359
|
return origOnInputAvailable.call(this, getCtx(this), options);
|
|
323
360
|
};
|
|
324
361
|
}
|
|
325
362
|
if (def.toModelOutput) {
|
|
326
363
|
const origToModelOutput = def.toModelOutput;
|
|
327
|
-
t.toModelOutput = function (
|
|
364
|
+
t.toModelOutput = function (
|
|
365
|
+
this: Tool<INPUT, OUTPUT, TOOL_CONTEXT>,
|
|
366
|
+
options,
|
|
367
|
+
) {
|
|
328
368
|
return origToModelOutput.call(this, getCtx(this), options);
|
|
329
369
|
};
|
|
330
370
|
}
|
|
@@ -6,30 +6,32 @@ import {
|
|
|
6
6
|
type ApiFromModules,
|
|
7
7
|
type GenericActionCtx,
|
|
8
8
|
type GenericDataModel,
|
|
9
|
+
type GenericMutationCtx,
|
|
9
10
|
type GenericQueryCtx,
|
|
10
11
|
} from "convex/server";
|
|
11
12
|
import { v } from "convex/values";
|
|
12
13
|
import {
|
|
13
|
-
createThread as createThread_,
|
|
14
|
-
listMessages as listMessages_,
|
|
15
|
-
toModelMessage,
|
|
16
14
|
vContextOptions,
|
|
17
15
|
vMessage,
|
|
18
16
|
vMessageDoc,
|
|
19
17
|
vPaginationResult,
|
|
20
18
|
vStorageOptions,
|
|
21
19
|
vThreadDoc,
|
|
22
|
-
type Agent,
|
|
23
|
-
type AgentComponent,
|
|
24
20
|
vStreamArgs,
|
|
25
|
-
syncStreams,
|
|
26
|
-
vStreamMessagesReturnValue,
|
|
27
|
-
isTool,
|
|
28
|
-
extractText,
|
|
29
21
|
type MessageDoc,
|
|
30
|
-
} from "
|
|
31
|
-
import {
|
|
32
|
-
import {
|
|
22
|
+
} from "../../validators.js";
|
|
23
|
+
import { createThread as createThread_ } from "../../client/threads.js";
|
|
24
|
+
import {
|
|
25
|
+
extractText,
|
|
26
|
+
getModelName,
|
|
27
|
+
getProviderName,
|
|
28
|
+
isTool,
|
|
29
|
+
} from "../../shared.js";
|
|
30
|
+
import { serializeResponseMessages, toModelMessage } from "../mapping.js";
|
|
31
|
+
import type { Agent } from "../index.js";
|
|
32
|
+
import { listMessages as listMessages_ } from "./messages.js";
|
|
33
|
+
import { syncStreams, vStreamMessagesReturnValue } from "./streaming.js";
|
|
34
|
+
import type { AgentComponent } from "./types.js";
|
|
33
35
|
|
|
34
36
|
export type PlaygroundAPI = ApiFromModules<{
|
|
35
37
|
playground: ReturnType<typeof definePlaygroundAPI>;
|
|
@@ -64,7 +66,10 @@ export function definePlaygroundAPI<DataModel extends GenericDataModel>(
|
|
|
64
66
|
}
|
|
65
67
|
}
|
|
66
68
|
|
|
67
|
-
async function validateApiKey(
|
|
69
|
+
async function validateApiKey(
|
|
70
|
+
ctx: QueryCtx | MutationCtx | ActionCtx,
|
|
71
|
+
apiKey: string,
|
|
72
|
+
) {
|
|
68
73
|
await ctx.runQuery(component.apiKeys.validate, { apiKey });
|
|
69
74
|
}
|
|
70
75
|
|
|
@@ -276,18 +281,20 @@ export function definePlaygroundAPI<DataModel extends GenericDataModel>(
|
|
|
276
281
|
},
|
|
277
282
|
{ contextOptions, storageOptions, saveStreamDeltas: true },
|
|
278
283
|
);
|
|
279
|
-
const outputMessages =
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
284
|
+
const outputMessages: MessageDoc[][] = [];
|
|
285
|
+
for (const step of await steps) {
|
|
286
|
+
const { messages } = await serializeResponseMessages(
|
|
287
|
+
ctx,
|
|
288
|
+
component,
|
|
289
|
+
step,
|
|
290
|
+
{
|
|
291
|
+
model: getModelName(agent.options.languageModel),
|
|
292
|
+
provider: getProviderName(agent.options.languageModel),
|
|
293
|
+
},
|
|
294
|
+
step.response.messages,
|
|
295
|
+
);
|
|
296
|
+
outputMessages.push(
|
|
297
|
+
messages.map((messageWithMetadata, i) => {
|
|
291
298
|
return {
|
|
292
299
|
...messageWithMetadata,
|
|
293
300
|
tool: isTool(messageWithMetadata.message),
|
|
@@ -300,9 +307,9 @@ export function definePlaygroundAPI<DataModel extends GenericDataModel>(
|
|
|
300
307
|
order: 0,
|
|
301
308
|
stepOrder: i + 1,
|
|
302
309
|
} satisfies MessageDoc;
|
|
303
|
-
})
|
|
304
|
-
|
|
305
|
-
|
|
310
|
+
}),
|
|
311
|
+
);
|
|
312
|
+
}
|
|
306
313
|
return { text: await text, messages: outputMessages.flat() };
|
|
307
314
|
},
|
|
308
315
|
returns: v.object({ text: v.string(), messages: v.array(vMessageDoc) }),
|
|
@@ -367,4 +374,12 @@ export function definePlaygroundAPI<DataModel extends GenericDataModel>(
|
|
|
367
374
|
};
|
|
368
375
|
}
|
|
369
376
|
|
|
370
|
-
type
|
|
377
|
+
type QueryCtx = Pick<GenericQueryCtx<GenericDataModel>, "runQuery">;
|
|
378
|
+
type MutationCtx = Pick<
|
|
379
|
+
GenericMutationCtx<GenericDataModel>,
|
|
380
|
+
"runQuery" | "runMutation"
|
|
381
|
+
>;
|
|
382
|
+
type ActionCtx = Pick<
|
|
383
|
+
GenericActionCtx<GenericDataModel>,
|
|
384
|
+
"runQuery" | "runMutation" | "runAction"
|
|
385
|
+
>;
|
|
@@ -5,14 +5,14 @@ import type {
|
|
|
5
5
|
ModelMessage,
|
|
6
6
|
UserContent,
|
|
7
7
|
} from "ai";
|
|
8
|
-
import type { Id } from "
|
|
8
|
+
import type { Id } from "../../component/_generated/dataModel.js";
|
|
9
9
|
import type {
|
|
10
10
|
ActionCtx,
|
|
11
11
|
AgentComponent,
|
|
12
12
|
MutationCtx,
|
|
13
13
|
QueryCtx,
|
|
14
14
|
} from "./types.js";
|
|
15
|
-
import type { Message } from "
|
|
15
|
+
import type { Message } from "../../validators.js";
|
|
16
16
|
import { assert } from "convex-helpers";
|
|
17
17
|
import type { StorageReader } from "convex/server";
|
|
18
18
|
|
|
@@ -2,9 +2,10 @@ import { describe, expect, test } from "vitest";
|
|
|
2
2
|
import {
|
|
3
3
|
Agent,
|
|
4
4
|
createThread,
|
|
5
|
+
createTool,
|
|
5
6
|
filterOutOrphanedToolMessages,
|
|
6
7
|
type MessageDoc,
|
|
7
|
-
} from "
|
|
8
|
+
} from "../index.js";
|
|
8
9
|
import type { DataModelFromSchemaDefinition } from "convex/server";
|
|
9
10
|
import {
|
|
10
11
|
anyApi,
|
|
@@ -23,7 +24,7 @@ import { defineSchema } from "convex/server";
|
|
|
23
24
|
import { stepCountIs } from "ai";
|
|
24
25
|
import { components, initConvexTest } from "./setup.test.js";
|
|
25
26
|
import { z } from "zod/v4";
|
|
26
|
-
import { mockModel } from "./mockModel.js";
|
|
27
|
+
import { MockLanguageModel, mockModel } from "./mockModel.js";
|
|
27
28
|
|
|
28
29
|
const schema = defineSchema({});
|
|
29
30
|
type DataModel = DataModelFromSchemaDefinition<typeof schema>;
|
|
@@ -34,12 +35,50 @@ const action = actionGeneric as ActionBuilder<DataModel, "public">;
|
|
|
34
35
|
|
|
35
36
|
const TEST_TEXT = JSON.stringify({ hello: "world" });
|
|
36
37
|
|
|
38
|
+
const agentModel = new MockLanguageModel({
|
|
39
|
+
content: [{ type: "text", text: TEST_TEXT }],
|
|
40
|
+
});
|
|
37
41
|
const agent = new Agent(components.agent, {
|
|
38
42
|
name: "test",
|
|
39
43
|
instructions: "You are a test agent",
|
|
44
|
+
languageModel: agentModel,
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
let capturedRawBodies: { request?: unknown; response?: unknown } | undefined;
|
|
48
|
+
const rawBodyAgent = new Agent(components.agent, {
|
|
49
|
+
name: "raw-body-test",
|
|
40
50
|
languageModel: mockModel({
|
|
41
|
-
|
|
51
|
+
doGenerate: async () => ({
|
|
52
|
+
content: [{ type: "text", text: "raw" }],
|
|
53
|
+
finishReason: { unified: "stop", raw: undefined },
|
|
54
|
+
usage: {
|
|
55
|
+
inputTokens: { total: 1, noCache: 1, cacheRead: 0, cacheWrite: 0 },
|
|
56
|
+
outputTokens: { total: 1, text: 1, reasoning: 0 },
|
|
57
|
+
},
|
|
58
|
+
request: { body: { prompt: "request-body" } },
|
|
59
|
+
response: { body: { text: "response-body" }, headers: {} },
|
|
60
|
+
warnings: [],
|
|
61
|
+
}),
|
|
42
62
|
}),
|
|
63
|
+
rawRequestResponseHandler: async (_ctx, event) => {
|
|
64
|
+
capturedRawBodies = {
|
|
65
|
+
request: event.request.body,
|
|
66
|
+
response: event.response.body,
|
|
67
|
+
};
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
export const captureRawBodies = action({
|
|
72
|
+
args: {},
|
|
73
|
+
handler: async (ctx) => {
|
|
74
|
+
capturedRawBodies = undefined;
|
|
75
|
+
await rawBodyAgent.generateText(
|
|
76
|
+
ctx,
|
|
77
|
+
{ userId: "raw-body-user" },
|
|
78
|
+
{ prompt: "raw" },
|
|
79
|
+
);
|
|
80
|
+
return capturedRawBodies;
|
|
81
|
+
},
|
|
43
82
|
});
|
|
44
83
|
|
|
45
84
|
export const testQuery = query({
|
|
@@ -62,6 +101,77 @@ export const createThreadManually = mutation({
|
|
|
62
101
|
},
|
|
63
102
|
});
|
|
64
103
|
|
|
104
|
+
const saveStepAgent = new Agent(components.agent, {
|
|
105
|
+
name: "save-step-test",
|
|
106
|
+
instructions: "test",
|
|
107
|
+
tools: {
|
|
108
|
+
echo: createTool({
|
|
109
|
+
description: "Echo a value",
|
|
110
|
+
inputSchema: z.object({ value: z.string() }),
|
|
111
|
+
execute: async (_ctx, input) => `echo:${input.value}`,
|
|
112
|
+
}),
|
|
113
|
+
},
|
|
114
|
+
languageModel: mockModel({
|
|
115
|
+
contentSteps: [
|
|
116
|
+
[
|
|
117
|
+
{
|
|
118
|
+
type: "tool-call",
|
|
119
|
+
toolCallId: "ss-1",
|
|
120
|
+
toolName: "echo",
|
|
121
|
+
input: JSON.stringify({ value: "hi" }),
|
|
122
|
+
},
|
|
123
|
+
],
|
|
124
|
+
[{ type: "text", text: "done" }],
|
|
125
|
+
],
|
|
126
|
+
}),
|
|
127
|
+
stopWhen: stepCountIs(5),
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
export const replayStepsViaSaveStep = action({
|
|
131
|
+
args: { withPreviousStep: v.boolean() },
|
|
132
|
+
handler: async (ctx, args) => {
|
|
133
|
+
const { thread } = await saveStepAgent.createThread(ctx, {
|
|
134
|
+
userId: "ss-gen",
|
|
135
|
+
});
|
|
136
|
+
const genResult = await thread.generateText({ prompt: "echo hi" });
|
|
137
|
+
const steps = genResult.steps;
|
|
138
|
+
|
|
139
|
+
const { threadId } = await saveStepAgent.createThread(ctx, {
|
|
140
|
+
userId: "ss-replay",
|
|
141
|
+
});
|
|
142
|
+
const { messageId: promptMessageId } = await saveStepAgent.saveMessage(
|
|
143
|
+
ctx,
|
|
144
|
+
{
|
|
145
|
+
threadId,
|
|
146
|
+
message: { role: "user", content: "echo hi" },
|
|
147
|
+
skipEmbeddings: true,
|
|
148
|
+
},
|
|
149
|
+
);
|
|
150
|
+
let previousStep: (typeof steps)[number] | undefined;
|
|
151
|
+
for (const step of steps) {
|
|
152
|
+
await saveStepAgent.saveStep(ctx, {
|
|
153
|
+
threadId,
|
|
154
|
+
promptMessageId,
|
|
155
|
+
step,
|
|
156
|
+
previousStep: args.withPreviousStep ? previousStep : undefined,
|
|
157
|
+
});
|
|
158
|
+
previousStep = step;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const replayed = await saveStepAgent.listMessages(ctx, {
|
|
162
|
+
threadId,
|
|
163
|
+
paginationOpts: { cursor: null, numItems: 50 },
|
|
164
|
+
statuses: ["success", "pending", "failed"],
|
|
165
|
+
});
|
|
166
|
+
const contentTypes = replayed.page.flatMap((m) =>
|
|
167
|
+
Array.isArray(m.message?.content)
|
|
168
|
+
? m.message!.content.map((c: { type?: string }) => c.type ?? "text")
|
|
169
|
+
: ["text"],
|
|
170
|
+
);
|
|
171
|
+
return { stepCount: steps.length, contentTypes };
|
|
172
|
+
},
|
|
173
|
+
});
|
|
174
|
+
|
|
65
175
|
export const createThreadMutation = agent.createThreadMutation();
|
|
66
176
|
export const generateObjectAction = agent.asObjectAction({
|
|
67
177
|
schema: z.object({ hello: z.string().describe("A string for testing") }),
|
|
@@ -162,6 +272,8 @@ const testApi: ApiFromModules<{
|
|
|
162
272
|
generateTextAction: typeof generateTextAction;
|
|
163
273
|
generateObjectAction: typeof generateObjectAction;
|
|
164
274
|
saveMessageMutation: typeof saveMessageMutation;
|
|
275
|
+
captureRawBodies: typeof captureRawBodies;
|
|
276
|
+
replayStepsViaSaveStep: typeof replayStepsViaSaveStep;
|
|
165
277
|
};
|
|
166
278
|
}>["fns"] = anyApi["index.test"] as any;
|
|
167
279
|
|
|
@@ -177,6 +289,26 @@ describe("Agent thick client", () => {
|
|
|
177
289
|
expect(result).toBeDefined();
|
|
178
290
|
expect(result).toMatch(TEST_TEXT);
|
|
179
291
|
});
|
|
292
|
+
test.each([true, false])(
|
|
293
|
+
"saveStep persists each SDK 7 step once (previousStep: %s)",
|
|
294
|
+
async (withPreviousStep) => {
|
|
295
|
+
const t = initConvexTest(schema);
|
|
296
|
+
const res = await t.action(testApi.replayStepsViaSaveStep, {
|
|
297
|
+
withPreviousStep,
|
|
298
|
+
});
|
|
299
|
+
expect(res.stepCount).toBe(2);
|
|
300
|
+
const toolCalls = res.contentTypes.filter(
|
|
301
|
+
(t) => t === "tool-call",
|
|
302
|
+
).length;
|
|
303
|
+
const toolResults = res.contentTypes.filter(
|
|
304
|
+
(t) => t === "tool-result",
|
|
305
|
+
).length;
|
|
306
|
+
expect({ toolCalls, toolResults }).toEqual({
|
|
307
|
+
toolCalls: 1,
|
|
308
|
+
toolResults: 1,
|
|
309
|
+
});
|
|
310
|
+
},
|
|
311
|
+
);
|
|
180
312
|
});
|
|
181
313
|
|
|
182
314
|
describe("filterOutOrphanedToolMessages", () => {
|
|
@@ -244,6 +376,14 @@ describe("filterOutOrphanedToolMessages", () => {
|
|
|
244
376
|
});
|
|
245
377
|
|
|
246
378
|
describe("Agent option variations and normal behavior", () => {
|
|
379
|
+
test("raw handler opts into retained SDK 7 request and response bodies", async () => {
|
|
380
|
+
const t = initConvexTest(schema);
|
|
381
|
+
await expect(t.action(testApi.captureRawBodies, {})).resolves.toEqual({
|
|
382
|
+
request: { prompt: "request-body" },
|
|
383
|
+
response: { text: "response-body" },
|
|
384
|
+
});
|
|
385
|
+
});
|
|
386
|
+
|
|
247
387
|
test("Agent can be constructed with minimal options", () => {
|
|
248
388
|
const a = new Agent(components.agent, {
|
|
249
389
|
name: "minimal",
|
|
@@ -378,6 +518,25 @@ describe("Agent-generated mutations/actions/queries", () => {
|
|
|
378
518
|
expect(objResult.object).toBeDefined();
|
|
379
519
|
});
|
|
380
520
|
|
|
521
|
+
test("asTextAction maps its system wire field to AI SDK instructions", async () => {
|
|
522
|
+
const t = initConvexTest(schema);
|
|
523
|
+
const before = agentModel.doGenerateCalls.length;
|
|
524
|
+
|
|
525
|
+
await t.action(testApi.generateTextAction, {
|
|
526
|
+
userId: "8",
|
|
527
|
+
system: "Action-scoped instructions",
|
|
528
|
+
prompt: "Say hi",
|
|
529
|
+
});
|
|
530
|
+
|
|
531
|
+
const call = agentModel.doGenerateCalls.at(-1);
|
|
532
|
+
expect(agentModel.doGenerateCalls).toHaveLength(before + 1);
|
|
533
|
+
expect(call?.prompt[0]).toEqual({
|
|
534
|
+
role: "system",
|
|
535
|
+
content: "Action-scoped instructions",
|
|
536
|
+
});
|
|
537
|
+
expect(call).not.toHaveProperty("system");
|
|
538
|
+
});
|
|
539
|
+
|
|
381
540
|
test("asSaveMessagesMutation works via t.mutation", async () => {
|
|
382
541
|
const t = initConvexTest(schema);
|
|
383
542
|
const threadId = await t.run(async (ctx) =>
|