browser-use 0.2.0 → 0.3.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 (259) hide show
  1. package/README.md +295 -686
  2. package/dist/actor/element.d.ts +19 -0
  3. package/dist/actor/element.js +46 -0
  4. package/dist/actor/index.d.ts +4 -0
  5. package/dist/actor/index.js +4 -0
  6. package/dist/actor/mouse.d.ts +19 -0
  7. package/dist/actor/mouse.js +39 -0
  8. package/dist/actor/page.d.ts +29 -0
  9. package/dist/actor/page.js +88 -0
  10. package/dist/actor/utils.d.ts +4 -0
  11. package/dist/actor/utils.js +35 -0
  12. package/dist/agent/cloud-events.d.ts +18 -0
  13. package/dist/agent/cloud-events.js +65 -2
  14. package/dist/agent/gif.d.ts +1 -0
  15. package/dist/agent/gif.js +24 -2
  16. package/dist/agent/judge.d.ts +17 -0
  17. package/dist/agent/judge.js +197 -0
  18. package/dist/agent/message-manager/service.d.ts +12 -4
  19. package/dist/agent/message-manager/service.js +205 -39
  20. package/dist/agent/message-manager/utils.js +0 -1
  21. package/dist/agent/message-manager/views.d.ts +4 -0
  22. package/dist/agent/message-manager/views.js +11 -7
  23. package/dist/agent/prompts.d.ts +24 -3
  24. package/dist/agent/prompts.js +274 -59
  25. package/dist/agent/service.d.ts +99 -41
  26. package/dist/agent/service.js +2266 -472
  27. package/dist/agent/variable-detector.d.ts +12 -0
  28. package/dist/agent/variable-detector.js +211 -0
  29. package/dist/agent/views.d.ts +237 -18
  30. package/dist/agent/views.js +446 -33
  31. package/dist/browser/cloud/cloud.d.ts +20 -0
  32. package/dist/browser/cloud/cloud.js +129 -0
  33. package/dist/browser/cloud/index.d.ts +2 -0
  34. package/dist/browser/cloud/index.js +2 -0
  35. package/dist/browser/cloud/views.d.ts +41 -0
  36. package/dist/browser/cloud/views.js +35 -0
  37. package/dist/browser/events.d.ts +345 -0
  38. package/dist/browser/events.js +566 -0
  39. package/dist/browser/extensions.js +17 -17
  40. package/dist/browser/index.d.ts +4 -0
  41. package/dist/browser/index.js +4 -0
  42. package/dist/browser/profile.d.ts +8 -2
  43. package/dist/browser/profile.js +79 -12
  44. package/dist/browser/session-manager.d.ts +85 -0
  45. package/dist/browser/session-manager.js +208 -0
  46. package/dist/browser/session.d.ts +100 -8
  47. package/dist/browser/session.js +1097 -58
  48. package/dist/browser/types.d.ts +0 -2
  49. package/dist/browser/views.d.ts +39 -0
  50. package/dist/browser/views.js +32 -0
  51. package/dist/browser/watchdogs/aboutblank-watchdog.d.ts +12 -0
  52. package/dist/browser/watchdogs/aboutblank-watchdog.js +131 -0
  53. package/dist/browser/watchdogs/base.d.ts +21 -0
  54. package/dist/browser/watchdogs/base.js +81 -0
  55. package/dist/browser/watchdogs/cdp-session-watchdog.d.ts +14 -0
  56. package/dist/browser/watchdogs/cdp-session-watchdog.js +177 -0
  57. package/dist/browser/watchdogs/crash-watchdog.d.ts +38 -0
  58. package/dist/browser/watchdogs/crash-watchdog.js +296 -0
  59. package/dist/browser/watchdogs/default-action-watchdog.d.ts +49 -0
  60. package/dist/browser/watchdogs/default-action-watchdog.js +212 -0
  61. package/dist/browser/watchdogs/dom-watchdog.d.ts +8 -0
  62. package/dist/browser/watchdogs/dom-watchdog.js +31 -0
  63. package/dist/browser/watchdogs/downloads-watchdog.d.ts +77 -0
  64. package/dist/browser/watchdogs/downloads-watchdog.js +409 -0
  65. package/dist/browser/watchdogs/har-recording-watchdog.d.ts +19 -0
  66. package/dist/browser/watchdogs/har-recording-watchdog.js +317 -0
  67. package/dist/browser/watchdogs/index.d.ts +15 -0
  68. package/dist/browser/watchdogs/index.js +15 -0
  69. package/dist/browser/watchdogs/local-browser-watchdog.d.ts +10 -0
  70. package/dist/browser/watchdogs/local-browser-watchdog.js +32 -0
  71. package/dist/browser/watchdogs/permissions-watchdog.d.ts +8 -0
  72. package/dist/browser/watchdogs/permissions-watchdog.js +73 -0
  73. package/dist/browser/watchdogs/popups-watchdog.d.ts +13 -0
  74. package/dist/browser/watchdogs/popups-watchdog.js +77 -0
  75. package/dist/browser/watchdogs/recording-watchdog.d.ts +27 -0
  76. package/dist/browser/watchdogs/recording-watchdog.js +249 -0
  77. package/dist/browser/watchdogs/screenshot-watchdog.d.ts +6 -0
  78. package/dist/browser/watchdogs/screenshot-watchdog.js +13 -0
  79. package/dist/browser/watchdogs/security-watchdog.d.ts +10 -0
  80. package/dist/browser/watchdogs/security-watchdog.js +84 -0
  81. package/dist/browser/watchdogs/storage-state-watchdog.d.ts +24 -0
  82. package/dist/browser/watchdogs/storage-state-watchdog.js +288 -0
  83. package/dist/cli.d.ts +7 -2
  84. package/dist/cli.js +182 -25
  85. package/dist/code-use/formatting.d.ts +3 -0
  86. package/dist/code-use/formatting.js +18 -0
  87. package/dist/code-use/index.d.ts +6 -0
  88. package/dist/code-use/index.js +6 -0
  89. package/dist/code-use/namespace.d.ts +5 -0
  90. package/dist/code-use/namespace.js +81 -0
  91. package/dist/code-use/notebook-export.d.ts +3 -0
  92. package/dist/code-use/notebook-export.js +56 -0
  93. package/dist/code-use/service.d.ts +24 -0
  94. package/dist/code-use/service.js +104 -0
  95. package/dist/code-use/utils.d.ts +4 -0
  96. package/dist/code-use/utils.js +98 -0
  97. package/dist/code-use/views.d.ts +108 -0
  98. package/dist/code-use/views.js +165 -0
  99. package/dist/config.d.ts +13 -0
  100. package/dist/config.js +69 -3
  101. package/dist/controller/registry/service.d.ts +10 -1
  102. package/dist/controller/registry/service.js +266 -10
  103. package/dist/controller/registry/views.d.ts +4 -1
  104. package/dist/controller/registry/views.js +25 -2
  105. package/dist/controller/service.d.ts +10 -1
  106. package/dist/controller/service.js +1807 -268
  107. package/dist/controller/views.d.ts +78 -155
  108. package/dist/controller/views.js +61 -12
  109. package/dist/dom/history-tree-processor/service.d.ts +5 -0
  110. package/dist/dom/history-tree-processor/service.js +169 -14
  111. package/dist/dom/history-tree-processor/view.d.ts +7 -1
  112. package/dist/dom/history-tree-processor/view.js +10 -1
  113. package/dist/dom/markdown-extractor.d.ts +37 -0
  114. package/dist/dom/markdown-extractor.js +345 -0
  115. package/dist/dom/service.d.ts +3 -1
  116. package/dist/dom/service.js +76 -0
  117. package/dist/dom/views.d.ts +1 -0
  118. package/dist/dom/views.js +45 -0
  119. package/dist/event-bus.d.ts +107 -7
  120. package/dist/event-bus.js +313 -10
  121. package/dist/exceptions.d.ts +0 -3
  122. package/dist/exceptions.js +0 -7
  123. package/dist/filesystem/file-system.d.ts +18 -0
  124. package/dist/filesystem/file-system.js +503 -42
  125. package/dist/index.d.ts +7 -0
  126. package/dist/index.js +6 -0
  127. package/dist/integrations/gmail/actions.d.ts +3 -3
  128. package/dist/integrations/gmail/actions.js +4 -4
  129. package/dist/llm/anthropic/chat.d.ts +18 -1
  130. package/dist/llm/anthropic/chat.js +123 -55
  131. package/dist/llm/anthropic/serializer.d.ts +2 -0
  132. package/dist/llm/anthropic/serializer.js +81 -9
  133. package/dist/llm/aws/chat-anthropic.d.ts +17 -0
  134. package/dist/llm/aws/chat-anthropic.js +126 -26
  135. package/dist/llm/aws/chat-bedrock.d.ts +28 -1
  136. package/dist/llm/aws/chat-bedrock.js +161 -34
  137. package/dist/llm/aws/serializer.d.ts +13 -1
  138. package/dist/llm/aws/serializer.js +56 -17
  139. package/dist/llm/azure/chat.d.ts +53 -2
  140. package/dist/llm/azure/chat.js +366 -54
  141. package/dist/llm/base.d.ts +2 -0
  142. package/dist/llm/browser-use/chat.d.ts +40 -0
  143. package/dist/llm/browser-use/chat.js +305 -0
  144. package/dist/llm/browser-use/index.d.ts +1 -0
  145. package/dist/llm/browser-use/index.js +1 -0
  146. package/dist/llm/cerebras/chat.d.ts +39 -0
  147. package/dist/llm/cerebras/chat.js +178 -0
  148. package/dist/llm/cerebras/index.d.ts +2 -0
  149. package/dist/llm/cerebras/index.js +2 -0
  150. package/dist/llm/cerebras/serializer.d.ts +7 -0
  151. package/dist/llm/cerebras/serializer.js +82 -0
  152. package/dist/llm/deepseek/chat.d.ts +19 -2
  153. package/dist/llm/deepseek/chat.js +138 -25
  154. package/dist/llm/google/chat.d.ts +46 -2
  155. package/dist/llm/google/chat.js +267 -64
  156. package/dist/llm/google/serializer.d.ts +9 -1
  157. package/dist/llm/google/serializer.js +141 -34
  158. package/dist/llm/groq/chat.d.ts +21 -2
  159. package/dist/llm/groq/chat.js +125 -26
  160. package/dist/llm/groq/parser.js +3 -1
  161. package/dist/llm/mistral/chat.d.ts +43 -0
  162. package/dist/llm/mistral/chat.js +154 -0
  163. package/dist/llm/mistral/index.d.ts +2 -0
  164. package/dist/llm/mistral/index.js +2 -0
  165. package/dist/llm/mistral/schema.d.ts +8 -0
  166. package/dist/llm/mistral/schema.js +27 -0
  167. package/dist/llm/models.d.ts +2 -0
  168. package/dist/llm/models.js +317 -0
  169. package/dist/llm/ollama/chat.d.ts +13 -1
  170. package/dist/llm/ollama/chat.js +110 -19
  171. package/dist/llm/ollama/serializer.d.ts +1 -0
  172. package/dist/llm/ollama/serializer.js +34 -12
  173. package/dist/llm/openai/chat.d.ts +16 -0
  174. package/dist/llm/openai/chat.js +94 -44
  175. package/dist/llm/openai/like.d.ts +5 -3
  176. package/dist/llm/openai/like.js +7 -3
  177. package/dist/llm/openai/responses-serializer.d.ts +18 -0
  178. package/dist/llm/openai/responses-serializer.js +72 -0
  179. package/dist/llm/openrouter/chat.d.ts +28 -2
  180. package/dist/llm/openrouter/chat.js +115 -29
  181. package/dist/llm/schema.d.ts +11 -1
  182. package/dist/llm/schema.js +81 -1
  183. package/dist/llm/vercel/chat.d.ts +50 -0
  184. package/dist/llm/vercel/chat.js +276 -0
  185. package/dist/llm/vercel/index.d.ts +1 -0
  186. package/dist/llm/vercel/index.js +1 -0
  187. package/dist/llm/vercel/serializer.d.ts +5 -0
  188. package/dist/llm/vercel/serializer.js +7 -0
  189. package/dist/llm/views.d.ts +2 -1
  190. package/dist/llm/views.js +3 -1
  191. package/dist/logging-config.d.ts +2 -0
  192. package/dist/logging-config.js +82 -29
  193. package/dist/mcp/client.d.ts +10 -5
  194. package/dist/mcp/client.js +14 -9
  195. package/dist/mcp/controller.d.ts +42 -3
  196. package/dist/mcp/controller.js +56 -31
  197. package/dist/mcp/server.d.ts +14 -0
  198. package/dist/mcp/server.js +255 -52
  199. package/dist/observability.js +10 -4
  200. package/dist/sandbox/index.d.ts +2 -0
  201. package/dist/sandbox/index.js +2 -0
  202. package/dist/sandbox/sandbox.d.ts +19 -0
  203. package/dist/sandbox/sandbox.js +140 -0
  204. package/dist/sandbox/views.d.ts +67 -0
  205. package/dist/sandbox/views.js +121 -0
  206. package/dist/skill-cli/index.d.ts +3 -0
  207. package/dist/skill-cli/index.js +3 -0
  208. package/dist/skill-cli/protocol.d.ts +30 -0
  209. package/dist/skill-cli/protocol.js +48 -0
  210. package/dist/skill-cli/server.d.ts +11 -0
  211. package/dist/skill-cli/server.js +85 -0
  212. package/dist/skill-cli/sessions.d.ts +24 -0
  213. package/dist/skill-cli/sessions.js +47 -0
  214. package/dist/skills/index.d.ts +3 -0
  215. package/dist/skills/index.js +3 -0
  216. package/dist/skills/service.d.ts +27 -0
  217. package/dist/skills/service.js +266 -0
  218. package/dist/skills/utils.d.ts +6 -0
  219. package/dist/skills/utils.js +53 -0
  220. package/dist/skills/views.d.ts +40 -0
  221. package/dist/skills/views.js +10 -0
  222. package/dist/sync/auth.js +8 -3
  223. package/dist/sync/service.d.ts +6 -6
  224. package/dist/sync/service.js +54 -89
  225. package/dist/telemetry/views.d.ts +20 -6
  226. package/dist/telemetry/views.js +23 -5
  227. package/dist/tokens/custom-pricing.d.ts +2 -0
  228. package/dist/tokens/custom-pricing.js +22 -0
  229. package/dist/tokens/index.d.ts +2 -0
  230. package/dist/tokens/index.js +2 -0
  231. package/dist/tokens/mappings.d.ts +1 -0
  232. package/dist/tokens/mappings.js +3 -0
  233. package/dist/tokens/service.js +27 -8
  234. package/dist/tools/extraction/index.d.ts +2 -0
  235. package/dist/tools/extraction/index.js +2 -0
  236. package/dist/tools/extraction/schema-utils.d.ts +6 -0
  237. package/dist/tools/extraction/schema-utils.js +237 -0
  238. package/dist/tools/extraction/views.d.ts +7 -0
  239. package/dist/tools/index.d.ts +5 -0
  240. package/dist/tools/index.js +5 -0
  241. package/dist/tools/registry/index.d.ts +2 -0
  242. package/dist/tools/registry/index.js +2 -0
  243. package/dist/tools/registry/service.d.ts +1 -0
  244. package/dist/tools/registry/service.js +1 -0
  245. package/dist/tools/registry/views.d.ts +1 -0
  246. package/dist/tools/registry/views.js +1 -0
  247. package/dist/tools/service.d.ts +2 -0
  248. package/dist/tools/service.js +1 -0
  249. package/dist/tools/utils.d.ts +2 -0
  250. package/dist/tools/utils.js +57 -0
  251. package/dist/tools/views.d.ts +1 -0
  252. package/dist/tools/views.js +1 -0
  253. package/dist/utils.d.ts +10 -1
  254. package/dist/utils.js +70 -3
  255. package/package.json +87 -26
  256. package/dist/dom/playground/process-dom.js +0 -5
  257. package/dist/dom/playground/test-accessibility.d.ts +0 -44
  258. package/dist/dom/playground/test-accessibility.js +0 -111
  259. /package/dist/{dom/playground/process-dom.d.ts → tools/extraction/views.js} +0 -0
@@ -1,37 +1,89 @@
1
- import { AssistantMessage, ContentPartImageParam, ContentPartTextParam, SystemMessage, UserMessage, } from '../messages.js';
1
+ import { AssistantMessage, ContentPartImageParam, ContentPartRefusalParam, ContentPartTextParam, SystemMessage, UserMessage, } from '../messages.js';
2
2
  export class GoogleMessageSerializer {
3
3
  serialize(messages) {
4
- return messages
5
- .filter((msg) => !(msg instanceof SystemMessage)) // System instructions are passed separately
6
- .map((message) => this.serializeMessage(message));
4
+ return this.serializeWithSystem(messages).contents;
7
5
  }
8
- serializeMessage(message) {
9
- if (message instanceof UserMessage) {
10
- return {
6
+ serializeWithSystem(messages, includeSystemInUser = false) {
7
+ const contents = [];
8
+ const systemParts = [];
9
+ let systemInstruction = null;
10
+ let injectedSystemIntoUser = false;
11
+ for (const message of messages) {
12
+ const role = message?.role;
13
+ if (message instanceof SystemMessage ||
14
+ role === 'system' ||
15
+ role === 'developer') {
16
+ const text = this.extractMessageText(message);
17
+ if (text) {
18
+ if (includeSystemInUser) {
19
+ systemParts.push(text);
20
+ }
21
+ else {
22
+ systemInstruction = text;
23
+ }
24
+ }
25
+ continue;
26
+ }
27
+ if (message instanceof UserMessage) {
28
+ const prependSystem = includeSystemInUser &&
29
+ !injectedSystemIntoUser &&
30
+ systemParts.length > 0
31
+ ? systemParts.join('\n\n')
32
+ : null;
33
+ contents.push(this.serializeUserMessage(message, prependSystem));
34
+ if (prependSystem) {
35
+ injectedSystemIntoUser = true;
36
+ }
37
+ continue;
38
+ }
39
+ if (message instanceof AssistantMessage) {
40
+ contents.push(this.serializeAssistantMessage(message));
41
+ }
42
+ }
43
+ if (includeSystemInUser &&
44
+ systemParts.length > 0 &&
45
+ !injectedSystemIntoUser) {
46
+ contents.unshift({
11
47
  role: 'user',
12
- parts: Array.isArray(message.content)
13
- ? message.content.map((part) => {
14
- if (part instanceof ContentPartTextParam) {
15
- return { text: part.text };
16
- }
17
- if (part instanceof ContentPartImageParam) {
18
- // Google GenAI expects inlineData for images usually
19
- const data = part.image_url.url.split(',')[1];
20
- const mimeType = part.image_url.media_type;
21
- return {
22
- inlineData: {
23
- mimeType: mimeType,
24
- data: data,
25
- },
26
- };
27
- }
28
- return { text: '' };
29
- })
30
- : [{ text: message.content }],
31
- };
48
+ parts: [{ text: systemParts.join('\n\n') }],
49
+ });
50
+ }
51
+ return {
52
+ contents,
53
+ systemInstruction: includeSystemInUser ? null : systemInstruction,
54
+ };
55
+ }
56
+ serializeUserMessage(message, prependSystem = null) {
57
+ const parts = [];
58
+ if (prependSystem) {
59
+ parts.push({ text: prependSystem });
32
60
  }
61
+ if (message instanceof UserMessage) {
62
+ if (Array.isArray(message.content)) {
63
+ for (const part of message.content) {
64
+ if (part instanceof ContentPartTextParam) {
65
+ parts.push({ text: part.text });
66
+ }
67
+ else if (part instanceof ContentPartRefusalParam) {
68
+ parts.push({ text: `[Refusal] ${part.refusal}` });
69
+ }
70
+ else if (part instanceof ContentPartImageParam) {
71
+ parts.push(this.serializeImagePart(part));
72
+ }
73
+ }
74
+ }
75
+ else {
76
+ parts.push({ text: message.content });
77
+ }
78
+ }
79
+ return {
80
+ role: 'user',
81
+ parts,
82
+ };
83
+ }
84
+ serializeAssistantMessage(message) {
85
+ const parts = [];
33
86
  if (message instanceof AssistantMessage) {
34
- const parts = [];
35
87
  if (message.content) {
36
88
  if (typeof message.content === 'string') {
37
89
  parts.push({ text: message.content });
@@ -41,24 +93,79 @@ export class GoogleMessageSerializer {
41
93
  if (part instanceof ContentPartTextParam) {
42
94
  parts.push({ text: part.text });
43
95
  }
96
+ else if (part instanceof ContentPartRefusalParam) {
97
+ parts.push({ text: `[Refusal] ${part.refusal}` });
98
+ }
99
+ else if (part instanceof ContentPartImageParam) {
100
+ parts.push(this.serializeImagePart(part));
101
+ }
44
102
  });
45
103
  }
46
104
  }
47
105
  if (message.tool_calls) {
48
106
  message.tool_calls.forEach((toolCall) => {
107
+ let args;
108
+ try {
109
+ const parsed = JSON.parse(toolCall.functionCall.arguments);
110
+ args =
111
+ parsed && typeof parsed === 'object' && !Array.isArray(parsed)
112
+ ? parsed
113
+ : {};
114
+ }
115
+ catch {
116
+ args = {};
117
+ }
49
118
  parts.push({
50
119
  functionCall: {
51
120
  name: toolCall.functionCall.name,
52
- args: JSON.parse(toolCall.functionCall.arguments),
121
+ args,
53
122
  },
54
123
  });
55
124
  });
56
125
  }
57
- return {
58
- role: 'model',
59
- parts: parts,
60
- };
61
126
  }
62
- throw new Error(`Unknown message type: ${message.constructor.name}`);
127
+ return {
128
+ role: 'model',
129
+ parts: parts,
130
+ };
131
+ }
132
+ serializeImagePart(part) {
133
+ const imageUrl = part.image_url.url;
134
+ if (!imageUrl.startsWith('data:')) {
135
+ return { text: imageUrl };
136
+ }
137
+ const commaIndex = imageUrl.indexOf(',');
138
+ if (commaIndex === -1) {
139
+ return { text: imageUrl };
140
+ }
141
+ const data = imageUrl.slice(commaIndex + 1);
142
+ return {
143
+ inlineData: {
144
+ mimeType: part.image_url.media_type,
145
+ data,
146
+ },
147
+ };
148
+ }
149
+ extractMessageText(message) {
150
+ const content = message?.content;
151
+ if (typeof content === 'string') {
152
+ return content;
153
+ }
154
+ if (!Array.isArray(content)) {
155
+ return '';
156
+ }
157
+ const parts = [];
158
+ for (const part of content) {
159
+ if (part instanceof ContentPartTextParam) {
160
+ parts.push(part.text);
161
+ }
162
+ else if (part &&
163
+ typeof part === 'object' &&
164
+ part.type === 'text' &&
165
+ typeof part.text === 'string') {
166
+ parts.push(part.text);
167
+ }
168
+ }
169
+ return parts.join('\n');
63
170
  }
64
171
  }
@@ -1,13 +1,32 @@
1
1
  import type { BaseChatModel, ChatInvokeOptions } from '../base.js';
2
- import { ChatInvokeCompletion } from '../views.js';
3
2
  import type { Message } from '../messages.js';
3
+ import { ChatInvokeCompletion } from '../views.js';
4
+ export interface ChatGroqOptions {
5
+ model?: string;
6
+ apiKey?: string;
7
+ baseURL?: string;
8
+ temperature?: number | null;
9
+ serviceTier?: 'auto' | 'on_demand' | 'flex' | null;
10
+ topP?: number | null;
11
+ seed?: number | null;
12
+ maxRetries?: number;
13
+ removeMinItemsFromSchema?: boolean;
14
+ removeDefaultsFromSchema?: boolean;
15
+ }
4
16
  export declare class ChatGroq implements BaseChatModel {
5
17
  model: string;
6
18
  provider: string;
7
19
  private client;
8
- constructor(model?: string);
20
+ private temperature;
21
+ private serviceTier;
22
+ private topP;
23
+ private seed;
24
+ private removeMinItemsFromSchema;
25
+ private removeDefaultsFromSchema;
26
+ constructor(options?: string | ChatGroqOptions);
9
27
  get name(): string;
10
28
  get model_name(): string;
29
+ private getUsage;
11
30
  ainvoke(messages: Message[], output_format?: undefined, options?: ChatInvokeOptions): Promise<ChatInvokeCompletion<string>>;
12
31
  ainvoke<T>(messages: Message[], output_format: {
13
32
  parse: (input: string) => T;
@@ -1,14 +1,38 @@
1
1
  import Groq from 'groq-sdk';
2
+ import { ModelProviderError, ModelRateLimitError } from '../exceptions.js';
3
+ import { SchemaOptimizer, zodSchemaToJsonSchema } from '../schema.js';
2
4
  import { ChatInvokeCompletion } from '../views.js';
3
5
  import { GroqMessageSerializer } from './serializer.js';
6
+ const JsonSchemaModels = [
7
+ 'meta-llama/llama-4-maverick-17b-128e-instruct',
8
+ 'meta-llama/llama-4-scout-17b-16e-instruct',
9
+ 'openai/gpt-oss-20b',
10
+ 'openai/gpt-oss-120b',
11
+ ];
4
12
  export class ChatGroq {
5
13
  model;
6
14
  provider = 'groq';
7
15
  client;
8
- constructor(model = 'llama-3.1-70b-versatile') {
16
+ temperature;
17
+ serviceTier;
18
+ topP;
19
+ seed;
20
+ removeMinItemsFromSchema;
21
+ removeDefaultsFromSchema;
22
+ constructor(options = {}) {
23
+ const normalizedOptions = typeof options === 'string' ? { model: options } : options;
24
+ const { model = 'llama-3.1-70b-versatile', apiKey = process.env.GROQ_API_KEY, baseURL, temperature = null, serviceTier = null, topP = null, seed = null, maxRetries = 10, removeMinItemsFromSchema = false, removeDefaultsFromSchema = false, } = normalizedOptions;
9
25
  this.model = model;
26
+ this.temperature = temperature;
27
+ this.serviceTier = serviceTier;
28
+ this.topP = topP;
29
+ this.seed = seed;
30
+ this.removeMinItemsFromSchema = removeMinItemsFromSchema;
31
+ this.removeDefaultsFromSchema = removeDefaultsFromSchema;
10
32
  this.client = new Groq({
11
- apiKey: process.env.GROQ_API_KEY,
33
+ apiKey,
34
+ baseURL,
35
+ maxRetries,
12
36
  });
13
37
  }
14
38
  get name() {
@@ -17,36 +41,111 @@ export class ChatGroq {
17
41
  get model_name() {
18
42
  return this.model;
19
43
  }
44
+ getUsage(response) {
45
+ if (!response?.usage) {
46
+ return null;
47
+ }
48
+ return {
49
+ prompt_tokens: response.usage.prompt_tokens,
50
+ prompt_cached_tokens: null,
51
+ prompt_cache_creation_tokens: null,
52
+ prompt_image_tokens: null,
53
+ completion_tokens: response.usage.completion_tokens,
54
+ total_tokens: response.usage.total_tokens,
55
+ };
56
+ }
20
57
  async ainvoke(messages, output_format, options = {}) {
21
58
  const serializer = new GroqMessageSerializer();
22
59
  const groqMessages = serializer.serialize(messages);
60
+ const modelParams = {};
61
+ if (this.temperature !== null) {
62
+ modelParams.temperature = this.temperature;
63
+ }
64
+ if (this.topP !== null) {
65
+ modelParams.top_p = this.topP;
66
+ }
67
+ if (this.seed !== null) {
68
+ modelParams.seed = this.seed;
69
+ }
70
+ if (this.serviceTier !== null) {
71
+ modelParams.service_tier = this.serviceTier;
72
+ }
73
+ const zodSchemaCandidate = (() => {
74
+ const output = output_format;
75
+ if (output &&
76
+ typeof output === 'object' &&
77
+ typeof output.safeParse === 'function' &&
78
+ typeof output.parse === 'function') {
79
+ return output;
80
+ }
81
+ if (output &&
82
+ typeof output === 'object' &&
83
+ output.schema &&
84
+ typeof output.schema.safeParse === 'function' &&
85
+ typeof output.schema.parse === 'function') {
86
+ return output.schema;
87
+ }
88
+ return null;
89
+ })();
23
90
  let responseFormat = undefined;
24
- if (output_format && 'schema' in output_format && output_format.schema) {
25
- // Groq supports JSON mode, but not full JSON schema validation in the same way as OpenAI yet (or maybe it does now).
26
- // For now, we'll enforce JSON mode and prompt engineering or use tools if needed.
27
- // But let's try to use json_object which is supported.
28
- responseFormat = { type: 'json_object' };
29
- }
30
- const response = await this.client.chat.completions.create({
31
- model: this.model,
32
- messages: groqMessages,
33
- response_format: responseFormat,
34
- }, options.signal ? { signal: options.signal } : undefined);
35
- const content = response.choices[0].message.content || '';
36
- let completion = content;
37
- if (output_format) {
38
- try {
39
- completion = output_format.parse(JSON.parse(content));
91
+ if (zodSchemaCandidate) {
92
+ if (JsonSchemaModels.includes(this.model)) {
93
+ try {
94
+ const rawJsonSchema = zodSchemaToJsonSchema(zodSchemaCandidate, {
95
+ name: 'agent_output',
96
+ target: 'jsonSchema7',
97
+ });
98
+ const optimizedJsonSchema = SchemaOptimizer.createOptimizedJsonSchema(rawJsonSchema, {
99
+ removeMinItems: this.removeMinItemsFromSchema,
100
+ removeDefaults: this.removeDefaultsFromSchema,
101
+ });
102
+ responseFormat = {
103
+ type: 'json_schema',
104
+ json_schema: {
105
+ name: 'agent_output',
106
+ schema: optimizedJsonSchema,
107
+ },
108
+ };
109
+ }
110
+ catch {
111
+ responseFormat = { type: 'json_object' };
112
+ }
40
113
  }
41
- catch (e) {
42
- console.error('Failed to parse completion', e);
43
- throw e;
114
+ else {
115
+ responseFormat = { type: 'json_object' };
44
116
  }
45
117
  }
46
- return new ChatInvokeCompletion(completion, {
47
- prompt_tokens: response.usage?.prompt_tokens ?? 0,
48
- completion_tokens: response.usage?.completion_tokens ?? 0,
49
- total_tokens: response.usage?.total_tokens ?? 0,
50
- });
118
+ try {
119
+ const response = await this.client.chat.completions.create({
120
+ model: this.model,
121
+ messages: groqMessages,
122
+ response_format: responseFormat,
123
+ ...modelParams,
124
+ }, options.signal ? { signal: options.signal } : undefined);
125
+ const content = response.choices[0].message.content || '';
126
+ const usage = this.getUsage(response);
127
+ const stopReason = response.choices[0].finish_reason ?? null;
128
+ let completion = content;
129
+ if (output_format) {
130
+ const parsedJson = JSON.parse(content);
131
+ const output = output_format;
132
+ if (output &&
133
+ typeof output === 'object' &&
134
+ output.schema &&
135
+ typeof output.schema.parse === 'function') {
136
+ completion = output.schema.parse(parsedJson);
137
+ }
138
+ else {
139
+ completion = output.parse(parsedJson);
140
+ }
141
+ }
142
+ return new ChatInvokeCompletion(completion, usage, null, null, stopReason);
143
+ }
144
+ catch (error) {
145
+ if (error?.status === 429) {
146
+ throw new ModelRateLimitError(error?.message ?? 'Rate limit exceeded', 429, this.model);
147
+ }
148
+ throw new ModelProviderError(error?.message ?? String(error), error?.status ?? 500, this.model);
149
+ }
51
150
  }
52
151
  }
@@ -98,7 +98,9 @@ export function tryParseGroqFailedGeneration(error, outputFormat) {
98
98
  }
99
99
  if (err instanceof SyntaxError) {
100
100
  logger.warning(`Failed to parse model output: ${err.message}`);
101
- throw new Error(`Could not parse response. ${err.message}`);
101
+ throw new Error(`Could not parse response. ${err.message}`, {
102
+ cause: err,
103
+ });
102
104
  }
103
105
  const errorMessage = error.message || String(error);
104
106
  throw new ParseFailedGenerationError(errorMessage);
@@ -0,0 +1,43 @@
1
+ import type { BaseChatModel, ChatInvokeOptions } from '../base.js';
2
+ import type { Message } from '../messages.js';
3
+ import { ChatInvokeCompletion } from '../views.js';
4
+ export interface ChatMistralOptions {
5
+ model?: string;
6
+ apiKey?: string;
7
+ baseURL?: string;
8
+ timeout?: number | null;
9
+ defaultHeaders?: Record<string, string> | null;
10
+ defaultQuery?: Record<string, string | undefined> | null;
11
+ fetchImplementation?: typeof fetch;
12
+ fetchOptions?: RequestInit | null;
13
+ clientParams?: Record<string, unknown> | null;
14
+ temperature?: number | null;
15
+ maxTokens?: number | null;
16
+ topP?: number | null;
17
+ seed?: number | null;
18
+ safePrompt?: boolean;
19
+ maxRetries?: number;
20
+ removeMinItemsFromSchema?: boolean;
21
+ removeDefaultsFromSchema?: boolean;
22
+ }
23
+ export declare class ChatMistral implements BaseChatModel {
24
+ model: string;
25
+ provider: string;
26
+ private client;
27
+ private temperature;
28
+ private maxTokens;
29
+ private topP;
30
+ private seed;
31
+ private safePrompt;
32
+ private removeMinItemsFromSchema;
33
+ private removeDefaultsFromSchema;
34
+ constructor(options?: string | ChatMistralOptions);
35
+ get name(): string;
36
+ get model_name(): string;
37
+ private getUsage;
38
+ private getSchemaCandidate;
39
+ ainvoke(messages: Message[], output_format?: undefined, options?: ChatInvokeOptions): Promise<ChatInvokeCompletion<string>>;
40
+ ainvoke<T>(messages: Message[], output_format: {
41
+ parse: (input: string) => T;
42
+ } | undefined, options?: ChatInvokeOptions): Promise<ChatInvokeCompletion<T>>;
43
+ }
@@ -0,0 +1,154 @@
1
+ import OpenAI from 'openai';
2
+ import { ModelProviderError, ModelRateLimitError } from '../exceptions.js';
3
+ import { ChatInvokeCompletion } from '../views.js';
4
+ import { zodSchemaToJsonSchema } from '../schema.js';
5
+ import { OpenAIMessageSerializer } from '../openai/serializer.js';
6
+ import { MistralSchemaOptimizer } from './schema.js';
7
+ export class ChatMistral {
8
+ model;
9
+ provider = 'mistral';
10
+ client;
11
+ temperature;
12
+ maxTokens;
13
+ topP;
14
+ seed;
15
+ safePrompt;
16
+ removeMinItemsFromSchema;
17
+ removeDefaultsFromSchema;
18
+ constructor(options = {}) {
19
+ const normalizedOptions = typeof options === 'string' ? { model: options } : options;
20
+ const { model = 'mistral-medium-latest', apiKey = process.env.MISTRAL_API_KEY, baseURL = process.env.MISTRAL_BASE_URL || 'https://api.mistral.ai/v1', timeout = null, defaultHeaders = null, defaultQuery = null, fetchImplementation, fetchOptions = null, clientParams = null, temperature = 0.2, maxTokens = 4096, topP = null, seed = null, safePrompt = false, maxRetries = 5, removeMinItemsFromSchema = false, removeDefaultsFromSchema = false, } = normalizedOptions;
21
+ this.model = model;
22
+ this.temperature = temperature;
23
+ this.maxTokens = maxTokens;
24
+ this.topP = topP;
25
+ this.seed = seed;
26
+ this.safePrompt = safePrompt;
27
+ this.removeMinItemsFromSchema = removeMinItemsFromSchema;
28
+ this.removeDefaultsFromSchema = removeDefaultsFromSchema;
29
+ this.client = new OpenAI({
30
+ apiKey,
31
+ baseURL,
32
+ ...(timeout !== null ? { timeout } : {}),
33
+ maxRetries,
34
+ defaultHeaders: defaultHeaders ?? undefined,
35
+ defaultQuery: defaultQuery ?? undefined,
36
+ fetch: fetchImplementation,
37
+ fetchOptions: (fetchOptions ?? undefined),
38
+ ...(clientParams ?? {}),
39
+ });
40
+ }
41
+ get name() {
42
+ return this.model;
43
+ }
44
+ get model_name() {
45
+ return this.model;
46
+ }
47
+ getUsage(response) {
48
+ if (!response.usage) {
49
+ return null;
50
+ }
51
+ return {
52
+ prompt_tokens: response.usage.prompt_tokens,
53
+ prompt_cached_tokens: response.usage.prompt_tokens_details?.cached_tokens ?? null,
54
+ prompt_cache_creation_tokens: null,
55
+ prompt_image_tokens: null,
56
+ completion_tokens: response.usage.completion_tokens,
57
+ total_tokens: response.usage.total_tokens,
58
+ };
59
+ }
60
+ getSchemaCandidate(output_format) {
61
+ const output = output_format;
62
+ if (output &&
63
+ typeof output === 'object' &&
64
+ typeof output.safeParse === 'function' &&
65
+ typeof output.parse === 'function') {
66
+ return output;
67
+ }
68
+ if (output &&
69
+ typeof output === 'object' &&
70
+ output.schema &&
71
+ typeof output.schema.safeParse === 'function' &&
72
+ typeof output.schema.parse === 'function') {
73
+ return output.schema;
74
+ }
75
+ return null;
76
+ }
77
+ async ainvoke(messages, output_format, options = {}) {
78
+ const serializer = new OpenAIMessageSerializer();
79
+ const mistralMessages = serializer.serialize(messages);
80
+ const modelParams = {};
81
+ if (this.temperature !== null) {
82
+ modelParams.temperature = this.temperature;
83
+ }
84
+ if (this.maxTokens !== null) {
85
+ modelParams.max_tokens = this.maxTokens;
86
+ }
87
+ if (this.topP !== null) {
88
+ modelParams.top_p = this.topP;
89
+ }
90
+ if (this.seed !== null) {
91
+ modelParams.seed = this.seed;
92
+ }
93
+ if (this.safePrompt) {
94
+ modelParams.safe_prompt = true;
95
+ }
96
+ const zodSchemaCandidate = this.getSchemaCandidate(output_format);
97
+ let responseFormat = undefined;
98
+ if (zodSchemaCandidate) {
99
+ try {
100
+ const rawJsonSchema = zodSchemaToJsonSchema(zodSchemaCandidate, {
101
+ name: 'agent_output',
102
+ target: 'jsonSchema7',
103
+ });
104
+ const optimizedJsonSchema = MistralSchemaOptimizer.createMistralCompatibleSchema(rawJsonSchema, {
105
+ removeMinItems: this.removeMinItemsFromSchema,
106
+ removeDefaults: this.removeDefaultsFromSchema,
107
+ });
108
+ responseFormat = {
109
+ type: 'json_schema',
110
+ json_schema: {
111
+ name: 'agent_output',
112
+ schema: optimizedJsonSchema,
113
+ strict: true,
114
+ },
115
+ };
116
+ }
117
+ catch {
118
+ responseFormat = undefined;
119
+ }
120
+ }
121
+ try {
122
+ const response = await this.client.chat.completions.create({
123
+ model: this.model,
124
+ messages: mistralMessages,
125
+ response_format: responseFormat,
126
+ ...modelParams,
127
+ }, options.signal ? { signal: options.signal } : undefined);
128
+ const content = response.choices[0].message.content || '';
129
+ const usage = this.getUsage(response);
130
+ const stopReason = response.choices[0].finish_reason ?? null;
131
+ let completion = content;
132
+ if (output_format) {
133
+ const parsedJson = JSON.parse(content);
134
+ const output = output_format;
135
+ if (output &&
136
+ typeof output === 'object' &&
137
+ output.schema &&
138
+ typeof output.schema.parse === 'function') {
139
+ completion = output.schema.parse(parsedJson);
140
+ }
141
+ else {
142
+ completion = output.parse(parsedJson);
143
+ }
144
+ }
145
+ return new ChatInvokeCompletion(completion, usage, null, null, stopReason);
146
+ }
147
+ catch (error) {
148
+ if (error?.status === 429) {
149
+ throw new ModelRateLimitError(error?.message ?? 'Rate limit exceeded', 429, this.model);
150
+ }
151
+ throw new ModelProviderError(error?.message ?? String(error), error?.status ?? 500, this.model);
152
+ }
153
+ }
154
+ }
@@ -0,0 +1,2 @@
1
+ export * from './chat.js';
2
+ export * from './schema.js';
@@ -0,0 +1,2 @@
1
+ export * from './chat.js';
2
+ export * from './schema.js';
@@ -0,0 +1,8 @@
1
+ export declare class MistralSchemaOptimizer {
2
+ static readonly UNSUPPORTED_KEYWORDS: Set<string>;
3
+ static createMistralCompatibleSchema(rawSchema: Record<string, unknown>, options?: {
4
+ removeMinItems?: boolean;
5
+ removeDefaults?: boolean;
6
+ }): Record<string, unknown>;
7
+ static stripUnsupportedKeywords(value: unknown): any;
8
+ }
@@ -0,0 +1,27 @@
1
+ import { SchemaOptimizer } from '../schema.js';
2
+ export class MistralSchemaOptimizer {
3
+ static UNSUPPORTED_KEYWORDS = new Set([
4
+ 'minLength',
5
+ 'maxLength',
6
+ 'pattern',
7
+ 'format',
8
+ ]);
9
+ static createMistralCompatibleSchema(rawSchema, options = {}) {
10
+ const baseSchema = SchemaOptimizer.createOptimizedJsonSchema(rawSchema, {
11
+ removeMinItems: options.removeMinItems ?? false,
12
+ removeDefaults: options.removeDefaults ?? false,
13
+ });
14
+ return this.stripUnsupportedKeywords(baseSchema);
15
+ }
16
+ static stripUnsupportedKeywords(value) {
17
+ if (Array.isArray(value)) {
18
+ return value.map((item) => this.stripUnsupportedKeywords(item));
19
+ }
20
+ if (!value || typeof value !== 'object') {
21
+ return value;
22
+ }
23
+ return Object.fromEntries(Object.entries(value)
24
+ .filter(([key]) => !this.UNSUPPORTED_KEYWORDS.has(key))
25
+ .map(([key, item]) => [key, this.stripUnsupportedKeywords(item)]));
26
+ }
27
+ }
@@ -0,0 +1,2 @@
1
+ import type { BaseChatModel } from './base.js';
2
+ export declare const getLlmByName: (modelName: string) => BaseChatModel;