@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.
Files changed (246) hide show
  1. package/MIGRATION.md +60 -116
  2. package/dist/client/messages.d.ts +1 -398
  3. package/dist/client/messages.d.ts.map +1 -1
  4. package/dist/client/messages.js +3 -47
  5. package/dist/client/messages.js.map +1 -1
  6. package/dist/client/types.d.ts +1 -455
  7. package/dist/client/types.d.ts.map +1 -1
  8. package/dist/component/_generated/component.d.ts +805 -45
  9. package/dist/component/_generated/component.d.ts.map +1 -1
  10. package/dist/component/apiKeys.js +5 -5
  11. package/dist/component/apiKeys.js.map +1 -1
  12. package/dist/component/files.d.ts.map +1 -1
  13. package/dist/component/files.js +13 -11
  14. package/dist/component/files.js.map +1 -1
  15. package/dist/component/messages.d.ts +1252 -201
  16. package/dist/component/messages.d.ts.map +1 -1
  17. package/dist/component/messages.js +83 -47
  18. package/dist/component/messages.js.map +1 -1
  19. package/dist/component/schema.d.ts +2593 -332
  20. package/dist/component/schema.d.ts.map +1 -1
  21. package/dist/component/streams.d.ts +7 -1
  22. package/dist/component/streams.d.ts.map +1 -1
  23. package/dist/component/streams.js +46 -47
  24. package/dist/component/streams.js.map +1 -1
  25. package/dist/component/threads.d.ts.map +1 -1
  26. package/dist/component/threads.js +8 -9
  27. package/dist/component/threads.js.map +1 -1
  28. package/dist/component/users.js +2 -2
  29. package/dist/component/users.js.map +1 -1
  30. package/dist/component/vector/index.d.ts.map +1 -1
  31. package/dist/component/vector/index.js +14 -8
  32. package/dist/component/vector/index.js.map +1 -1
  33. package/dist/react/index.d.ts +5 -5
  34. package/dist/react/index.d.ts.map +1 -1
  35. package/dist/react/index.js +5 -5
  36. package/dist/react/index.js.map +1 -1
  37. package/dist/shared.d.ts +19 -7
  38. package/dist/shared.d.ts.map +1 -1
  39. package/dist/shared.js +4 -4
  40. package/dist/shared.js.map +1 -1
  41. package/dist/streaming/materializePersistedUIMessageChunks.d.ts +16 -0
  42. package/dist/streaming/materializePersistedUIMessageChunks.d.ts.map +1 -0
  43. package/dist/streaming/materializePersistedUIMessageChunks.js +302 -0
  44. package/dist/streaming/materializePersistedUIMessageChunks.js.map +1 -0
  45. package/dist/streaming/persistedUIMessageChunks.d.ts +106 -0
  46. package/dist/streaming/persistedUIMessageChunks.d.ts.map +1 -0
  47. package/dist/streaming/persistedUIMessageChunks.js +475 -0
  48. package/dist/streaming/persistedUIMessageChunks.js.map +1 -0
  49. package/dist/validators.d.ts +10026 -1055
  50. package/dist/validators.d.ts.map +1 -1
  51. package/dist/validators.js +71 -9
  52. package/dist/validators.js.map +1 -1
  53. package/dist/{UIMessages.d.ts → vercel/UIMessages.d.ts} +1 -1
  54. package/dist/vercel/UIMessages.d.ts.map +1 -0
  55. package/dist/{UIMessages.js → vercel/UIMessages.js} +63 -1
  56. package/dist/vercel/UIMessages.js.map +1 -0
  57. package/dist/{client → vercel/client}/createTool.d.ts +23 -16
  58. package/dist/vercel/client/createTool.d.ts.map +1 -0
  59. package/dist/{client → vercel/client}/createTool.js +2 -0
  60. package/dist/vercel/client/createTool.js.map +1 -0
  61. package/dist/{client → vercel/client}/definePlaygroundAPI.d.ts +593 -134
  62. package/dist/{client → vercel/client}/definePlaygroundAPI.d.ts.map +1 -1
  63. package/dist/{client → vercel/client}/definePlaygroundAPI.js +13 -9
  64. package/dist/vercel/client/definePlaygroundAPI.js.map +1 -0
  65. package/dist/{client → vercel/client}/files.d.ts +2 -2
  66. package/dist/vercel/client/files.d.ts.map +1 -0
  67. package/dist/vercel/client/files.js.map +1 -0
  68. package/dist/vercel/client/messages.d.ts +542 -0
  69. package/dist/vercel/client/messages.d.ts.map +1 -0
  70. package/dist/vercel/client/messages.js +66 -0
  71. package/dist/vercel/client/messages.js.map +1 -0
  72. package/dist/{client → vercel/client}/mockModel.d.ts +17 -17
  73. package/dist/vercel/client/mockModel.d.ts.map +1 -0
  74. package/dist/{client → vercel/client}/mockModel.js +12 -13
  75. package/dist/vercel/client/mockModel.js.map +1 -0
  76. package/dist/{client → vercel/client}/saveInputMessages.d.ts +2 -2
  77. package/dist/vercel/client/saveInputMessages.d.ts.map +1 -0
  78. package/dist/vercel/client/saveInputMessages.js.map +1 -0
  79. package/dist/{client → vercel/client}/search.d.ts +119 -22
  80. package/dist/vercel/client/search.d.ts.map +1 -0
  81. package/dist/{client → vercel/client}/search.js +2 -2
  82. package/dist/vercel/client/search.js.map +1 -0
  83. package/dist/{client → vercel/client}/start.d.ts +26 -11
  84. package/dist/vercel/client/start.d.ts.map +1 -0
  85. package/dist/{client → vercel/client}/start.js +64 -22
  86. package/dist/vercel/client/start.js.map +1 -0
  87. package/dist/{client → vercel/client}/streamText.d.ts +13 -12
  88. package/dist/vercel/client/streamText.d.ts.map +1 -0
  89. package/dist/{client → vercel/client}/streamText.js +43 -9
  90. package/dist/vercel/client/streamText.js.map +1 -0
  91. package/dist/{client → vercel/client}/streaming.d.ts +1410 -183
  92. package/dist/vercel/client/streaming.d.ts.map +1 -0
  93. package/dist/{client → vercel/client}/streaming.js +120 -52
  94. package/dist/vercel/client/streaming.js.map +1 -0
  95. package/dist/vercel/client/types.d.ts +456 -0
  96. package/dist/vercel/client/types.d.ts.map +1 -0
  97. package/dist/vercel/client/types.js +3 -0
  98. package/dist/vercel/client/types.js.map +1 -0
  99. package/dist/{client → vercel/client}/utils.d.ts +3 -2
  100. package/dist/vercel/client/utils.d.ts.map +1 -0
  101. package/dist/{client → vercel/client}/utils.js +2 -2
  102. package/dist/vercel/client/utils.js.map +1 -0
  103. package/dist/vercel/deltas.d.ts +31 -0
  104. package/dist/vercel/deltas.d.ts.map +1 -0
  105. package/dist/vercel/deltas.js +525 -0
  106. package/dist/vercel/deltas.js.map +1 -0
  107. package/dist/{client → vercel}/index.d.ts +484 -97
  108. package/dist/vercel/index.d.ts.map +1 -0
  109. package/dist/{client → vercel}/index.js +65 -38
  110. package/dist/vercel/index.js.map +1 -0
  111. package/dist/{mapping.d.ts → vercel/mapping.d.ts} +5 -13
  112. package/dist/vercel/mapping.d.ts.map +1 -0
  113. package/dist/{mapping.js → vercel/mapping.js} +411 -112
  114. package/dist/vercel/mapping.js.map +1 -0
  115. package/dist/{react → vercel/react}/optimisticallySendMessage.d.ts +2 -2
  116. package/dist/vercel/react/optimisticallySendMessage.d.ts.map +1 -0
  117. package/dist/vercel/react/optimisticallySendMessage.js.map +1 -0
  118. package/dist/{react → vercel/react}/types.d.ts +1 -1
  119. package/dist/vercel/react/types.d.ts.map +1 -0
  120. package/dist/{react → vercel/react}/types.js.map +1 -1
  121. package/dist/{react → vercel/react}/useDeltaStreams.d.ts +1 -1
  122. package/dist/vercel/react/useDeltaStreams.d.ts.map +1 -0
  123. package/dist/{react → vercel/react}/useDeltaStreams.js +1 -1
  124. package/dist/vercel/react/useDeltaStreams.js.map +1 -0
  125. package/dist/{react → vercel/react}/useStreamingUIMessages.d.ts +1 -1
  126. package/dist/vercel/react/useStreamingUIMessages.d.ts.map +1 -0
  127. package/dist/vercel/react/useStreamingUIMessages.js +112 -0
  128. package/dist/vercel/react/useStreamingUIMessages.js.map +1 -0
  129. package/dist/{react → vercel/react}/useThreadMessages.d.ts +1 -1
  130. package/dist/vercel/react/useThreadMessages.d.ts.map +1 -0
  131. package/dist/{react → vercel/react}/useThreadMessages.js +1 -1
  132. package/dist/vercel/react/useThreadMessages.js.map +1 -0
  133. package/dist/{react → vercel/react}/useUIMessages.d.ts +2 -1
  134. package/dist/vercel/react/useUIMessages.d.ts.map +1 -0
  135. package/dist/{react → vercel/react}/useUIMessages.js +8 -4
  136. package/dist/vercel/react/useUIMessages.js.map +1 -0
  137. package/package.json +30 -22
  138. package/src/client/messages.ts +5 -107
  139. package/src/client/types.ts +0 -621
  140. package/src/component/_generated/component.ts +1089 -48
  141. package/src/component/apiKeys.ts +5 -5
  142. package/src/component/files.test.ts +1 -1
  143. package/src/component/files.ts +14 -12
  144. package/src/component/messages.test.ts +273 -1
  145. package/src/component/messages.ts +99 -57
  146. package/src/component/streams.ts +80 -64
  147. package/src/component/threads.ts +12 -9
  148. package/src/component/users.ts +2 -2
  149. package/src/component/vector/index.ts +14 -7
  150. package/src/eslintConfig.test.ts +44 -0
  151. package/src/react/index.ts +8 -5
  152. package/src/shared.ts +26 -36
  153. package/src/streaming/materializePersistedUIMessageChunks.test.ts +513 -0
  154. package/src/streaming/materializePersistedUIMessageChunks.ts +398 -0
  155. package/src/streaming/persistedUIMessageChunks.test.ts +205 -0
  156. package/src/streaming/persistedUIMessageChunks.ts +658 -0
  157. package/src/validators.test.ts +4 -1
  158. package/src/validators.ts +89 -8
  159. package/src/{UIMessages.combineUIMessages.test.ts → vercel/UIMessages.combineUIMessages.test.ts} +4 -1
  160. package/src/{UIMessages.ts → vercel/UIMessages.ts} +96 -5
  161. package/src/{client → vercel/client}/approval.test.ts +48 -19
  162. package/src/{client → vercel/client}/createTool.ts +63 -23
  163. package/src/{client → vercel/client}/definePlaygroundAPI.ts +44 -29
  164. package/src/{client → vercel/client}/files.ts +2 -2
  165. package/src/{client → vercel/client}/index.test.ts +162 -3
  166. package/src/vercel/client/messages.ts +182 -0
  167. package/src/{client → vercel/client}/mockModel.ts +38 -39
  168. package/src/{client → vercel/client}/saveInputMessages.test.ts +1 -1
  169. package/src/{client → vercel/client}/saveInputMessages.ts +7 -4
  170. package/src/{client → vercel/client}/search.test.ts +3 -3
  171. package/src/{client → vercel/client}/search.ts +4 -4
  172. package/src/{client → vercel/client}/setup.test.ts +6 -3
  173. package/src/vercel/client/start.test.ts +14 -0
  174. package/src/{client → vercel/client}/start.ts +147 -36
  175. package/src/vercel/client/streamText.test.ts +223 -0
  176. package/src/{client → vercel/client}/streamText.ts +102 -31
  177. package/src/{client → vercel/client}/streaming.integration.test.ts +40 -115
  178. package/src/{client → vercel/client}/streaming.test.ts +178 -4
  179. package/src/{client → vercel/client}/streaming.ts +114 -52
  180. package/src/vercel/client/types.test.ts +13 -0
  181. package/src/vercel/client/types.ts +679 -0
  182. package/src/{client → vercel/client}/utils.ts +13 -7
  183. package/src/vercel/deltas.test.ts +898 -0
  184. package/src/vercel/deltas.ts +633 -0
  185. package/src/{fromUIMessages.test.ts → vercel/fromUIMessages.test.ts} +17 -1
  186. package/src/{client → vercel}/index.ts +169 -62
  187. package/src/vercel/mapping.test.ts +965 -0
  188. package/src/{mapping.ts → vercel/mapping.ts} +501 -131
  189. package/src/{react → vercel/react}/optimisticallySendMessage.ts +2 -2
  190. package/src/{react → vercel/react}/types.ts +1 -1
  191. package/src/{react → vercel/react}/useDeltaStreams.ts +6 -2
  192. package/src/{react → vercel/react}/useStreamingUIMessages.ts +67 -35
  193. package/src/{react → vercel/react}/useThreadMessages.ts +2 -2
  194. package/src/{react → vercel/react}/useUIMessages.test.ts +80 -1
  195. package/src/{react → vercel/react}/useUIMessages.ts +13 -5
  196. package/src/{toUIMessages.test.ts → vercel/toUIMessages.test.ts} +49 -2
  197. package/dist/UIMessages.d.ts.map +0 -1
  198. package/dist/UIMessages.js.map +0 -1
  199. package/dist/client/createTool.d.ts.map +0 -1
  200. package/dist/client/createTool.js.map +0 -1
  201. package/dist/client/definePlaygroundAPI.js.map +0 -1
  202. package/dist/client/files.d.ts.map +0 -1
  203. package/dist/client/files.js.map +0 -1
  204. package/dist/client/index.d.ts.map +0 -1
  205. package/dist/client/index.js.map +0 -1
  206. package/dist/client/mockModel.d.ts.map +0 -1
  207. package/dist/client/mockModel.js.map +0 -1
  208. package/dist/client/saveInputMessages.d.ts.map +0 -1
  209. package/dist/client/saveInputMessages.js.map +0 -1
  210. package/dist/client/search.d.ts.map +0 -1
  211. package/dist/client/search.js.map +0 -1
  212. package/dist/client/start.d.ts.map +0 -1
  213. package/dist/client/start.js.map +0 -1
  214. package/dist/client/streamText.d.ts.map +0 -1
  215. package/dist/client/streamText.js.map +0 -1
  216. package/dist/client/streaming.d.ts.map +0 -1
  217. package/dist/client/streaming.js.map +0 -1
  218. package/dist/client/utils.d.ts.map +0 -1
  219. package/dist/client/utils.js.map +0 -1
  220. package/dist/deltas.d.ts +0 -43
  221. package/dist/deltas.d.ts.map +0 -1
  222. package/dist/deltas.js +0 -446
  223. package/dist/deltas.js.map +0 -1
  224. package/dist/mapping.d.ts.map +0 -1
  225. package/dist/mapping.js.map +0 -1
  226. package/dist/react/optimisticallySendMessage.d.ts.map +0 -1
  227. package/dist/react/optimisticallySendMessage.js.map +0 -1
  228. package/dist/react/types.d.ts.map +0 -1
  229. package/dist/react/useDeltaStreams.d.ts.map +0 -1
  230. package/dist/react/useDeltaStreams.js.map +0 -1
  231. package/dist/react/useStreamingUIMessages.d.ts.map +0 -1
  232. package/dist/react/useStreamingUIMessages.js +0 -92
  233. package/dist/react/useStreamingUIMessages.js.map +0 -1
  234. package/dist/react/useThreadMessages.d.ts.map +0 -1
  235. package/dist/react/useThreadMessages.js.map +0 -1
  236. package/dist/react/useUIMessages.d.ts.map +0 -1
  237. package/dist/react/useUIMessages.js.map +0 -1
  238. package/src/client/streamText.test.ts +0 -102
  239. package/src/deltas.test.ts +0 -626
  240. package/src/deltas.ts +0 -569
  241. package/src/mapping.test.ts +0 -402
  242. /package/dist/{client → vercel/client}/files.js +0 -0
  243. /package/dist/{client → vercel/client}/saveInputMessages.js +0 -0
  244. /package/dist/{react → vercel/react}/optimisticallySendMessage.js +0 -0
  245. /package/dist/{react → vercel/react}/types.js +0 -0
  246. /package/src/{UIMessages.test.ts → vercel/UIMessages.test.ts} +0 -0
@@ -0,0 +1,182 @@
1
+ import type { ModelMessage } from "ai";
2
+ import type { PaginationOptions, PaginationResult } from "convex/server";
3
+ import type { MessageDoc } from "../../validators.js";
4
+ import {
5
+ type Message,
6
+ type MessageEmbeddings,
7
+ type MessageWithMetadata,
8
+ } from "../../validators.js";
9
+ import { serializeMessage } from "../mapping.js";
10
+ import { toUIMessages, type UIMessage } from "../UIMessages.js";
11
+ import {
12
+ listMessages,
13
+ saveMessages as saveCanonicalMessages,
14
+ } from "../../client/messages.js";
15
+ import type {
16
+ AgentComponent,
17
+ MutationCtx,
18
+ QueryCtx,
19
+ ActionCtx,
20
+ } from "./types.js";
21
+
22
+ export { listMessages } from "../../client/messages.js";
23
+
24
+ export async function listUIMessages(
25
+ ctx: QueryCtx | MutationCtx | ActionCtx,
26
+ component: AgentComponent,
27
+ args: {
28
+ threadId: string;
29
+ paginationOpts: PaginationOptions;
30
+ },
31
+ ): Promise<PaginationResult<UIMessage>> {
32
+ const result = await listMessages(ctx, component, args);
33
+ return { ...result, page: toUIMessages(result.page) };
34
+ }
35
+
36
+ export type SaveMessagesArgs = {
37
+ threadId: string;
38
+ userId?: string | null;
39
+ /**
40
+ * The message that these messages are in response to. They will be
41
+ * the same "order" as this message, at increasing stepOrder(s).
42
+ */
43
+ promptMessageId?: string;
44
+ /**
45
+ * The messages to save.
46
+ */
47
+ messages: (ModelMessage | Message)[];
48
+ /**
49
+ * Metadata to save with the messages. Each element corresponds to the
50
+ * message at the same index.
51
+ */
52
+ metadata?: Omit<MessageWithMetadata, "message">[];
53
+ /**
54
+ * If true, it will fail any pending steps.
55
+ * Defaults to false.
56
+ */
57
+ failPendingSteps?: boolean;
58
+ /**
59
+ * The embeddings to save with the messages.
60
+ */
61
+ embeddings?: MessageEmbeddings;
62
+ /**
63
+ * A pending message ID to replace when adding messages.
64
+ */
65
+ pendingMessageId?: string;
66
+ };
67
+
68
+ /**
69
+ * Explicitly save messages associated with the thread (& user if provided)
70
+ */
71
+ export async function saveMessages(
72
+ ctx: MutationCtx | ActionCtx,
73
+ component: AgentComponent,
74
+ args: SaveMessagesArgs & {
75
+ /**
76
+ * The agent name to associate with the messages.
77
+ */
78
+ agentName?: string;
79
+ },
80
+ ): Promise<{ messages: MessageDoc[] }> {
81
+ const serialized = await Promise.all(
82
+ args.messages.map((message) => serializeMessage(ctx, component, message)),
83
+ );
84
+ return saveCanonicalMessages(ctx, component, {
85
+ threadId: args.threadId,
86
+ userId: args.userId ?? undefined,
87
+ agentName: args.agentName,
88
+ promptMessageId: args.promptMessageId,
89
+ pendingMessageId: args.pendingMessageId,
90
+ embeddings: args.embeddings,
91
+ messages: serialized.map(({ message }) => message),
92
+ metadata: serialized.map(({ fileIds }, i) => {
93
+ const base = args.metadata?.[i];
94
+ const allFileIds = [...(base?.fileIds ?? [])];
95
+ if (fileIds) allFileIds.push(...fileIds);
96
+ return {
97
+ ...base,
98
+ ...(allFileIds.length > 0 ? { fileIds: allFileIds } : {}),
99
+ };
100
+ }),
101
+ failPendingSteps: args.failPendingSteps ?? false,
102
+ });
103
+ }
104
+
105
+ export type SaveMessageArgs = {
106
+ threadId: string;
107
+ userId?: string | null;
108
+ /**
109
+ * The message that these messages are in response to. They will be
110
+ * the same "order" as this message, at increasing stepOrder(s).
111
+ */
112
+ promptMessageId?: string;
113
+ /**
114
+ * Metadata to save with the messages. Each element corresponds to the
115
+ * message at the same index.
116
+ */
117
+ metadata?: Omit<MessageWithMetadata, "message">;
118
+ /**
119
+ * The embedding to save with the message.
120
+ */
121
+ embedding?: { vector: number[]; model: string };
122
+ /**
123
+ * A pending message ID to replace with this message.
124
+ */
125
+ pendingMessageId?: string;
126
+ } & (
127
+ | {
128
+ prompt?: undefined;
129
+ /**
130
+ * The message to save.
131
+ */
132
+ message: ModelMessage | Message;
133
+ }
134
+ | {
135
+ /*
136
+ * The prompt to save with the message.
137
+ */
138
+ prompt: string;
139
+ message?: undefined;
140
+ }
141
+ );
142
+
143
+ /**
144
+ * Save a message to the thread.
145
+ * @param ctx A ctx object from a mutation or action.
146
+ * @param args The message and what to associate it with (user / thread)
147
+ * You can pass extra metadata alongside the message, e.g. associated fileIds.
148
+ * @returns The messageId of the saved message.
149
+ */
150
+ export async function saveMessage(
151
+ ctx: MutationCtx | ActionCtx,
152
+ component: AgentComponent,
153
+ args: SaveMessageArgs & {
154
+ /**
155
+ * The agent name to associate with the message.
156
+ */
157
+ agentName?: string;
158
+ },
159
+ ) {
160
+ let embeddings: { vectors: number[][]; model: string } | undefined;
161
+ if (args.embedding && args.embedding.vector) {
162
+ embeddings = {
163
+ model: args.embedding.model,
164
+ vectors: [args.embedding.vector],
165
+ };
166
+ }
167
+ const { messages } = await saveMessages(ctx, component, {
168
+ threadId: args.threadId,
169
+ userId: args.userId ?? undefined,
170
+ agentName: args.agentName,
171
+ promptMessageId: args.promptMessageId,
172
+ pendingMessageId: args.pendingMessageId,
173
+ messages:
174
+ args.prompt !== undefined
175
+ ? [{ role: "user", content: args.prompt }]
176
+ : [args.message],
177
+ metadata: args.metadata ? [args.metadata] : undefined,
178
+ embeddings,
179
+ });
180
+ const message = messages.at(-1)!;
181
+ return { messageId: message._id, message };
182
+ }
@@ -1,7 +1,7 @@
1
1
  import type {
2
- LanguageModelV3,
3
- LanguageModelV3Content,
4
- LanguageModelV3StreamPart,
2
+ LanguageModelV4,
3
+ LanguageModelV4Content,
4
+ LanguageModelV4StreamPart,
5
5
  } from "@ai-sdk/provider";
6
6
  import { simulateReadableStream, type ProviderMetadata } from "ai";
7
7
  import { assert, pick } from "convex-helpers";
@@ -13,26 +13,25 @@ C C C C C C C C C C C C C C C
13
13
  D D D D D D D D D D D D D D D
14
14
  `;
15
15
  const DEFAULT_USAGE = {
16
- outputTokens: 10,
17
- inputTokens: 3,
18
- totalTokens: 13,
19
- inputTokenDetails: {
20
- noCacheTokens: 3,
21
- cacheReadTokens: 0,
22
- cacheWriteTokens: 0,
16
+ inputTokens: {
17
+ total: 3,
18
+ noCache: 3,
19
+ cacheRead: 0,
20
+ cacheWrite: 0,
23
21
  },
24
- outputTokenDetails: {
25
- textTokens: 10,
26
- reasoningTokens: 0,
22
+ outputTokens: {
23
+ total: 10,
24
+ text: 10,
25
+ reasoning: 0,
27
26
  },
28
27
  };
29
28
 
30
29
  export type MockModelArgs = {
31
- provider?: LanguageModelV3["provider"];
32
- modelId?: LanguageModelV3["modelId"];
30
+ provider?: LanguageModelV4["provider"];
31
+ modelId?: LanguageModelV4["modelId"];
33
32
  supportedUrls?:
34
- | LanguageModelV3["supportedUrls"]
35
- | (() => LanguageModelV3["supportedUrls"]);
33
+ | LanguageModelV4["supportedUrls"]
34
+ | (() => LanguageModelV4["supportedUrls"]);
36
35
  chunkDelayInMs?: number;
37
36
  initialDelayInMs?: number;
38
37
  /** A list of the responses for multiple steps.
@@ -40,15 +39,15 @@ export type MockModelArgs = {
40
39
  * then the next list would be after the tool response or another tool call.
41
40
  * Tool responses come from actual tool calls!
42
41
  */
43
- contentSteps?: LanguageModelV3Content[][];
42
+ contentSteps?: LanguageModelV4Content[][];
44
43
  /** A single list of content responded from each step.
45
44
  * Provide contentSteps instead if you want to do multi-step responses with
46
45
  * tool calls.
47
46
  */
48
- content?: LanguageModelV3Content[];
47
+ content?: LanguageModelV4Content[];
49
48
  // provide either content, contentResponses or doGenerate & doStream
50
- doGenerate?: LanguageModelV3["doGenerate"];
51
- doStream?: LanguageModelV3["doStream"];
49
+ doGenerate?: LanguageModelV4["doGenerate"];
50
+ doStream?: LanguageModelV4["doStream"];
52
51
  providerMetadata?: ProviderMetadata;
53
52
  fail?:
54
53
  | boolean
@@ -62,23 +61,23 @@ function atMostOneOf(...args: unknown[]) {
62
61
  return args.filter(Boolean).length <= 1;
63
62
  }
64
63
 
65
- export function mockModel(args?: MockModelArgs): LanguageModelV3 {
64
+ export function mockModel(args?: MockModelArgs): LanguageModelV4 {
66
65
  return new MockLanguageModel(args ?? {});
67
66
  }
68
67
 
69
- export class MockLanguageModel implements LanguageModelV3 {
70
- readonly specificationVersion = "v3";
68
+ export class MockLanguageModel implements LanguageModelV4 {
69
+ readonly specificationVersion = "v4";
71
70
 
72
- private _supportedUrls: () => LanguageModelV3["supportedUrls"];
71
+ private _supportedUrls: () => LanguageModelV4["supportedUrls"];
73
72
 
74
- readonly provider: LanguageModelV3["provider"];
75
- readonly modelId: LanguageModelV3["modelId"];
73
+ readonly provider: LanguageModelV4["provider"];
74
+ readonly modelId: LanguageModelV4["modelId"];
76
75
 
77
- doGenerate: LanguageModelV3["doGenerate"];
78
- doStream: LanguageModelV3["doStream"];
76
+ doGenerate: LanguageModelV4["doGenerate"];
77
+ doStream: LanguageModelV4["doStream"];
79
78
 
80
- doGenerateCalls: Parameters<LanguageModelV3["doGenerate"]>[0][] = [];
81
- doStreamCalls: Parameters<LanguageModelV3["doStream"]>[0][] = [];
79
+ doGenerateCalls: Parameters<LanguageModelV4["doGenerate"]>[0][] = [];
80
+ doStreamCalls: Parameters<LanguageModelV4["doStream"]>[0][] = [];
82
81
 
83
82
  constructor(args: MockModelArgs) {
84
83
  assert(
@@ -108,19 +107,19 @@ export class MockLanguageModel implements LanguageModelV3 {
108
107
  "Mock error message";
109
108
  const metadata = pick(args, ["providerMetadata"]);
110
109
 
111
- const chunkResponses: LanguageModelV3StreamPart[][] = contentSteps.map(
110
+ const chunkResponses: LanguageModelV4StreamPart[][] = contentSteps.map(
112
111
  (content) => {
113
- const chunks: LanguageModelV3StreamPart[] = [
112
+ const chunks: LanguageModelV4StreamPart[] = [
114
113
  { type: "stream-start", warnings: [] },
115
114
  ];
116
115
  chunks.push(
117
- ...content.flatMap((c, ci): LanguageModelV3StreamPart[] => {
116
+ ...content.flatMap((c, ci): LanguageModelV4StreamPart[] => {
118
117
  if (c.type !== "text" && c.type !== "reasoning") {
119
118
  return [c];
120
119
  }
121
120
  const metadata = pick(c, ["providerMetadata"]);
122
121
  const deltas = c.text.split(" ");
123
- const parts: LanguageModelV3StreamPart[] = [];
122
+ const parts: LanguageModelV4StreamPart[] = [];
124
123
  if (c.type === "reasoning") {
125
124
  parts.push({
126
125
  type: "reasoning-start",
@@ -135,7 +134,7 @@ export class MockLanguageModel implements LanguageModelV3 {
135
134
  delta: (di ? " " : "") + delta,
136
135
  id: `reasoning-${ci}`,
137
136
  ...metadata,
138
- }) satisfies LanguageModelV3StreamPart,
137
+ }) satisfies LanguageModelV4StreamPart,
139
138
  ),
140
139
  );
141
140
  parts.push({
@@ -157,7 +156,7 @@ export class MockLanguageModel implements LanguageModelV3 {
157
156
  delta: (di ? " " : "") + delta,
158
157
  id: `txt-${ci}`,
159
158
  ...metadata,
160
- }) satisfies LanguageModelV3StreamPart,
159
+ }) satisfies LanguageModelV4StreamPart,
161
160
  ),
162
161
  );
163
162
  parts.push({
@@ -177,7 +176,7 @@ export class MockLanguageModel implements LanguageModelV3 {
177
176
  }
178
177
  chunks.push({
179
178
  type: "finish",
180
- finishReason: fail ? "error" : "stop",
179
+ finishReason: { unified: fail ? "error" : "stop", raw: undefined },
181
180
  usage: DEFAULT_USAGE,
182
181
  ...(metadata as any),
183
182
  });
@@ -198,7 +197,7 @@ export class MockLanguageModel implements LanguageModelV3 {
198
197
  } else if (contentSteps.length) {
199
198
  const result = {
200
199
  content: contentSteps[callIndex % contentSteps.length],
201
- finishReason: "stop" as const,
200
+ finishReason: { unified: "stop" as const, raw: undefined },
202
201
  usage: DEFAULT_USAGE,
203
202
  ...(metadata as any),
204
203
  warnings: [],
@@ -1,6 +1,6 @@
1
1
  import { beforeEach, describe, expect, test, vi } from "vitest";
2
2
  import { saveInputMessages } from "./saveInputMessages.js";
3
- import type { MessageDoc } from "../validators.js";
3
+ import type { MessageDoc } from "../../validators.js";
4
4
  import type { ActionCtx } from "./types.js";
5
5
  import {
6
6
  defineSchema,
@@ -1,5 +1,5 @@
1
1
  import { type ModelMessage } from "ai";
2
- import type { MessageDoc } from "../validators.js";
2
+ import type { MessageDoc } from "../../validators.js";
3
3
  import { embedMessages, getPromptArray } from "./search.js";
4
4
  import type {
5
5
  ActionCtx,
@@ -8,9 +8,9 @@ import type {
8
8
  MutationCtx,
9
9
  } from "./types.js";
10
10
  import { saveMessages } from "./messages.js";
11
- import type { Message } from "../validators.js";
11
+ import type { Message } from "../../validators.js";
12
12
  import { assert } from "convex-helpers";
13
- import type { VectorDimension } from "../component/vector/tables.js";
13
+ import type { VectorDimension } from "../../component/vector/tables.js";
14
14
 
15
15
  export async function saveInputMessages(
16
16
  ctx: MutationCtx | ActionCtx,
@@ -31,7 +31,10 @@ export async function saveInputMessages(
31
31
  storageOptions?: {
32
32
  saveMessages?: "all" | "promptAndOutput";
33
33
  };
34
- } & Pick<Config, "usageHandler" | "textEmbeddingModel" | "embeddingModel" | "callSettings">,
34
+ } & Pick<
35
+ Config,
36
+ "usageHandler" | "textEmbeddingModel" | "embeddingModel" | "callSettings"
37
+ >,
35
38
  ): Promise<{
36
39
  promptMessageId: string | undefined;
37
40
  pendingMessage: MessageDoc;
@@ -13,7 +13,7 @@ import {
13
13
  type StorageActionWriter,
14
14
  type StorageReader,
15
15
  } from "convex/server";
16
- import type { MessageDoc } from "../validators.js";
16
+ import type { MessageDoc } from "../../validators.js";
17
17
  import type { ActionCtx, QueryCtx } from "./types.js";
18
18
  import {
19
19
  fetchContextWithPrompt,
@@ -22,8 +22,8 @@ import {
22
22
  getPromptArray,
23
23
  } from "./search.js";
24
24
  import { components, initConvexTest } from "./setup.test.js";
25
- import { createThread } from "./threads.js";
26
- import { saveMessages } from "./messages.js";
25
+ import { createThread } from "../../client/threads.js";
26
+ import { saveMessages } from "../../client/messages.js";
27
27
 
28
28
  // Helper to create mock MessageDoc
29
29
  const createMockMessageDoc = (
@@ -4,11 +4,11 @@ import {
4
4
  type ModelMessage,
5
5
  } from "ai";
6
6
  import { assert } from "convex-helpers";
7
- import type { MessageDoc } from "../validators.js";
7
+ import type { MessageDoc } from "../../validators.js";
8
8
  import {
9
9
  validateVectorDimension,
10
10
  type VectorDimension,
11
- } from "../component/vector/tables.js";
11
+ } from "../../component/vector/tables.js";
12
12
  import {
13
13
  DEFAULT_MESSAGE_RANGE,
14
14
  DEFAULT_RECENT_MESSAGES,
@@ -17,8 +17,8 @@ import {
17
17
  getProviderName,
18
18
  isTool,
19
19
  sorted,
20
- } from "../shared.js";
21
- import type { Message } from "../validators.js";
20
+ } from "../../shared.js";
21
+ import type { Message } from "../../validators.js";
22
22
  import type {
23
23
  AgentComponent,
24
24
  Config,
@@ -1,16 +1,19 @@
1
1
  /// <reference types="vite/client" />
2
2
  import { test } from "vitest";
3
3
  import { convexTest } from "convex-test";
4
- export const modules = import.meta.glob("./**/*.*s");
4
+ export const modules = {
5
+ ...import.meta.glob("./**/*.*s"),
6
+ "./_generated/api.ts": () => import("../../component/_generated/api.js"),
7
+ };
5
8
 
6
9
  import {
7
10
  defineSchema,
8
11
  type GenericSchema,
9
12
  type SchemaDefinition,
10
13
  } from "convex/server";
11
- import { type AgentComponent } from "./index.js";
14
+ import { type AgentComponent } from "./types.js";
12
15
  import { componentsGeneric } from "convex/server";
13
- import component from "../test.js";
16
+ import component from "../../test.js";
14
17
 
15
18
  export function initConvexTest<
16
19
  Schema extends SchemaDefinition<GenericSchema, boolean>,
@@ -0,0 +1,14 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { resolveUsageModel } from "./start.js";
3
+
4
+ describe("resolveUsageModel", () => {
5
+ it("prefers a step model while object results retain the active model", () => {
6
+ const activeModel = { provider: "fallback", model: "fallback-model" };
7
+ const stepModel = { provider: "router", model: "routed-model" };
8
+
9
+ expect(resolveUsageModel({ step: { model: stepModel } }, activeModel)).toBe(
10
+ stepModel,
11
+ );
12
+ expect(resolveUsageModel({ object: {} }, activeModel)).toBe(activeModel);
13
+ });
14
+ });