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
@@ -0,0 +1,317 @@
1
+ import { ChatAnthropic } from './anthropic/chat.js';
2
+ import { ChatBedrockConverse } from './aws/chat-bedrock.js';
3
+ import { ChatAzure } from './azure/chat.js';
4
+ import { ChatBrowserUse } from './browser-use/chat.js';
5
+ import { ChatCerebras } from './cerebras/chat.js';
6
+ import { ChatDeepSeek } from './deepseek/chat.js';
7
+ import { ChatGoogle } from './google/chat.js';
8
+ import { ChatGroq } from './groq/chat.js';
9
+ import { ChatMistral } from './mistral/chat.js';
10
+ import { ChatOllama } from './ollama/chat.js';
11
+ import { ChatOpenAI } from './openai/chat.js';
12
+ import { ChatOpenRouter } from './openrouter/chat.js';
13
+ import { ChatVercel } from './vercel/chat.js';
14
+ const AVAILABLE_PROVIDERS = [
15
+ 'openai',
16
+ 'anthropic',
17
+ 'google',
18
+ 'deepseek',
19
+ 'groq',
20
+ 'openrouter',
21
+ 'azure',
22
+ 'ollama',
23
+ 'aws',
24
+ 'browser-use',
25
+ 'mistral',
26
+ 'cerebras',
27
+ 'vercel',
28
+ ];
29
+ const MISTRAL_ALIAS_MAP = {
30
+ large: 'mistral-large-latest',
31
+ medium: 'mistral-medium-latest',
32
+ small: 'mistral-small-latest',
33
+ codestral: 'codestral-latest',
34
+ 'pixtral-large': 'pixtral-large-latest',
35
+ pixtral_large: 'pixtral-large-latest',
36
+ };
37
+ const convertPythonModelPart = (modelPart) => {
38
+ if (modelPart.includes('gpt_4_1_mini')) {
39
+ return modelPart.replace('gpt_4_1_mini', 'gpt-4.1-mini');
40
+ }
41
+ if (modelPart.includes('gpt_4o_mini')) {
42
+ return modelPart.replace('gpt_4o_mini', 'gpt-4o-mini');
43
+ }
44
+ if (modelPart.includes('gpt_4o')) {
45
+ return modelPart.replace('gpt_4o', 'gpt-4o');
46
+ }
47
+ if (modelPart.includes('gemini_2_0')) {
48
+ return modelPart.replace('gemini_2_0', 'gemini-2.0').replace(/_/g, '-');
49
+ }
50
+ if (modelPart.includes('gemini_2_5')) {
51
+ return modelPart.replace('gemini_2_5', 'gemini-2.5').replace(/_/g, '-');
52
+ }
53
+ if (modelPart.includes('llama3_1')) {
54
+ return modelPart.replace('llama3_1', 'llama3.1').replace(/_/g, '-');
55
+ }
56
+ if (modelPart.includes('llama3_3')) {
57
+ return modelPart.replace('llama3_3', 'llama-3.3').replace(/_/g, '-');
58
+ }
59
+ if (modelPart.includes('llama_4_scout')) {
60
+ return modelPart
61
+ .replace('llama_4_scout', 'llama-4-scout')
62
+ .replace(/_/g, '-');
63
+ }
64
+ if (modelPart.includes('llama_4_maverick')) {
65
+ return modelPart
66
+ .replace('llama_4_maverick', 'llama-4-maverick')
67
+ .replace(/_/g, '-');
68
+ }
69
+ if (modelPart.includes('gpt_oss_120b')) {
70
+ return modelPart.replace('gpt_oss_120b', 'gpt-oss-120b');
71
+ }
72
+ if (modelPart.includes('qwen_3_32b')) {
73
+ return modelPart.replace('qwen_3_32b', 'qwen-3-32b');
74
+ }
75
+ if (modelPart.includes('qwen_3_235b_a22b_instruct_2507')) {
76
+ return modelPart.replace('qwen_3_235b_a22b_instruct_2507', 'qwen-3-235b-a22b-instruct-2507');
77
+ }
78
+ if (modelPart.includes('qwen_3_235b_a22b_instruct')) {
79
+ return modelPart.replace('qwen_3_235b_a22b_instruct', 'qwen-3-235b-a22b-instruct-2507');
80
+ }
81
+ if (modelPart.includes('qwen_3_235b_a22b_thinking_2507')) {
82
+ return modelPart.replace('qwen_3_235b_a22b_thinking_2507', 'qwen-3-235b-a22b-thinking-2507');
83
+ }
84
+ if (modelPart.includes('qwen_3_235b_a22b_thinking')) {
85
+ return modelPart.replace('qwen_3_235b_a22b_thinking', 'qwen-3-235b-a22b-thinking-2507');
86
+ }
87
+ if (modelPart.includes('qwen_3_coder_480b')) {
88
+ return modelPart.replace('qwen_3_coder_480b', 'qwen-3-coder-480b');
89
+ }
90
+ return modelPart.replace(/_/g, '-');
91
+ };
92
+ const normalizeMistralModel = (model) => {
93
+ const key = model.trim().toLowerCase();
94
+ return MISTRAL_ALIAS_MAP[key] ?? model;
95
+ };
96
+ const inferProviderFromModel = (model) => {
97
+ const lower = model.toLowerCase();
98
+ if (lower.startsWith('gpt') ||
99
+ lower.startsWith('o1') ||
100
+ lower.startsWith('o3') ||
101
+ lower.startsWith('o4') ||
102
+ lower.startsWith('gpt-5')) {
103
+ return 'openai';
104
+ }
105
+ if (lower.startsWith('claude')) {
106
+ return 'anthropic';
107
+ }
108
+ if (lower.startsWith('gemini')) {
109
+ return 'google';
110
+ }
111
+ if (lower.startsWith('deepseek')) {
112
+ return 'deepseek';
113
+ }
114
+ if (lower.startsWith('groq:')) {
115
+ return 'groq';
116
+ }
117
+ if (lower.startsWith('openrouter:')) {
118
+ return 'openrouter';
119
+ }
120
+ if (lower.startsWith('azure:')) {
121
+ return 'azure';
122
+ }
123
+ if (lower.startsWith('ollama:')) {
124
+ return 'ollama';
125
+ }
126
+ if (lower.startsWith('mistral:')) {
127
+ return 'mistral';
128
+ }
129
+ if (lower.startsWith('cerebras:')) {
130
+ return 'cerebras';
131
+ }
132
+ if (lower.startsWith('vercel:')) {
133
+ return 'vercel';
134
+ }
135
+ if (lower.startsWith('mistral-') ||
136
+ lower.startsWith('codestral') ||
137
+ lower.startsWith('pixtral')) {
138
+ return 'mistral';
139
+ }
140
+ if (lower.startsWith('llama3.') ||
141
+ lower.startsWith('llama-4-') ||
142
+ lower.startsWith('gpt-oss-') ||
143
+ lower.startsWith('qwen-3-')) {
144
+ return 'cerebras';
145
+ }
146
+ if (lower.startsWith('bedrock:')) {
147
+ return 'aws';
148
+ }
149
+ if (lower.startsWith('anthropic.')) {
150
+ return 'aws';
151
+ }
152
+ if (lower.startsWith('bu-') || lower.startsWith('browser-use/')) {
153
+ return 'browser-use';
154
+ }
155
+ if (lower.includes('/') &&
156
+ !lower.startsWith('http://') &&
157
+ !lower.startsWith('https://')) {
158
+ return 'openrouter';
159
+ }
160
+ return null;
161
+ };
162
+ const normalizeModelForProvider = (provider, model) => {
163
+ const lower = model.toLowerCase();
164
+ if (provider === 'groq' && lower.startsWith('groq:')) {
165
+ return model.slice('groq:'.length);
166
+ }
167
+ if (provider === 'openrouter' && lower.startsWith('openrouter:')) {
168
+ return model.slice('openrouter:'.length);
169
+ }
170
+ if (provider === 'azure' && lower.startsWith('azure:')) {
171
+ return model.slice('azure:'.length);
172
+ }
173
+ if (provider === 'ollama' && lower.startsWith('ollama:')) {
174
+ return model.slice('ollama:'.length);
175
+ }
176
+ if (provider === 'mistral' && lower.startsWith('mistral:')) {
177
+ return model.slice('mistral:'.length);
178
+ }
179
+ if (provider === 'cerebras' && lower.startsWith('cerebras:')) {
180
+ return model.slice('cerebras:'.length);
181
+ }
182
+ if (provider === 'vercel' && lower.startsWith('vercel:')) {
183
+ return model.slice('vercel:'.length);
184
+ }
185
+ if (provider === 'aws' && lower.startsWith('bedrock:')) {
186
+ return model.slice('bedrock:'.length);
187
+ }
188
+ return model;
189
+ };
190
+ const buildProviderModel = (provider, model) => {
191
+ switch (provider) {
192
+ case 'openai':
193
+ return new ChatOpenAI({
194
+ model,
195
+ apiKey: process.env.OPENAI_API_KEY,
196
+ });
197
+ case 'anthropic':
198
+ return new ChatAnthropic({
199
+ model,
200
+ apiKey: process.env.ANTHROPIC_API_KEY,
201
+ });
202
+ case 'google':
203
+ return new ChatGoogle({
204
+ model,
205
+ apiKey: process.env.GOOGLE_API_KEY || '',
206
+ });
207
+ case 'deepseek':
208
+ return new ChatDeepSeek({
209
+ model,
210
+ apiKey: process.env.DEEPSEEK_API_KEY,
211
+ });
212
+ case 'groq':
213
+ return new ChatGroq({
214
+ model,
215
+ apiKey: process.env.GROQ_API_KEY,
216
+ });
217
+ case 'openrouter':
218
+ return new ChatOpenRouter({
219
+ model,
220
+ apiKey: process.env.OPENROUTER_API_KEY,
221
+ });
222
+ case 'azure':
223
+ return new ChatAzure({
224
+ model,
225
+ apiKey: process.env.AZURE_OPENAI_KEY ?? process.env.AZURE_OPENAI_API_KEY,
226
+ endpoint: process.env.AZURE_OPENAI_ENDPOINT,
227
+ });
228
+ case 'ollama':
229
+ return new ChatOllama({
230
+ model,
231
+ host: process.env.OLLAMA_HOST || 'http://localhost:11434',
232
+ });
233
+ case 'mistral':
234
+ return new ChatMistral({
235
+ model: normalizeMistralModel(model),
236
+ apiKey: process.env.MISTRAL_API_KEY,
237
+ baseURL: process.env.MISTRAL_BASE_URL,
238
+ });
239
+ case 'cerebras':
240
+ return new ChatCerebras({
241
+ model,
242
+ apiKey: process.env.CEREBRAS_API_KEY,
243
+ baseURL: process.env.CEREBRAS_BASE_URL,
244
+ });
245
+ case 'vercel':
246
+ return new ChatVercel({
247
+ model,
248
+ apiKey: process.env.VERCEL_API_KEY,
249
+ baseURL: process.env.VERCEL_BASE_URL,
250
+ });
251
+ case 'aws':
252
+ return new ChatBedrockConverse({
253
+ model,
254
+ region: process.env.AWS_REGION || 'us-east-1',
255
+ });
256
+ case 'browser-use':
257
+ return new ChatBrowserUse({
258
+ model,
259
+ apiKey: process.env.BROWSER_USE_API_KEY,
260
+ });
261
+ default:
262
+ throw new Error(`Unknown provider '${provider}'. Available providers: ${AVAILABLE_PROVIDERS.join(', ')}`);
263
+ }
264
+ };
265
+ export const getLlmByName = (modelName) => {
266
+ const normalizedName = modelName.trim();
267
+ if (!normalizedName) {
268
+ throw new Error('Model name cannot be empty');
269
+ }
270
+ if (normalizedName === 'bu_latest') {
271
+ return buildProviderModel('browser-use', 'bu-latest');
272
+ }
273
+ if (normalizedName === 'bu_1_0') {
274
+ return buildProviderModel('browser-use', 'bu-1-0');
275
+ }
276
+ if (normalizedName === 'bu_2_0') {
277
+ return buildProviderModel('browser-use', 'bu-2-0');
278
+ }
279
+ if (normalizedName === 'mistral_large') {
280
+ return buildProviderModel('mistral', 'mistral-large-latest');
281
+ }
282
+ if (normalizedName === 'mistral_medium') {
283
+ return buildProviderModel('mistral', 'mistral-medium-latest');
284
+ }
285
+ if (normalizedName === 'mistral_small') {
286
+ return buildProviderModel('mistral', 'mistral-small-latest');
287
+ }
288
+ if (normalizedName === 'codestral') {
289
+ return buildProviderModel('mistral', 'codestral-latest');
290
+ }
291
+ if (normalizedName === 'pixtral_large') {
292
+ return buildProviderModel('mistral', 'pixtral-large-latest');
293
+ }
294
+ const separator = normalizedName.indexOf('_');
295
+ if (separator > 0) {
296
+ const provider = normalizedName.slice(0, separator);
297
+ if (provider === 'oci') {
298
+ throw new Error('OCI models require manual configuration. Use ChatOCIRaw directly with your OCI credentials.');
299
+ }
300
+ const modelPart = normalizedName.slice(separator + 1);
301
+ if (provider === 'bu') {
302
+ return buildProviderModel('browser-use', `bu-${modelPart.replace(/_/g, '-')}`);
303
+ }
304
+ if (provider === 'browser-use') {
305
+ return buildProviderModel('browser-use', modelPart.replace(/_/g, '/'));
306
+ }
307
+ if (AVAILABLE_PROVIDERS.includes(provider)) {
308
+ return buildProviderModel(provider, convertPythonModelPart(modelPart));
309
+ }
310
+ }
311
+ const inferredProvider = inferProviderFromModel(normalizedName);
312
+ if (!inferredProvider) {
313
+ throw new Error(`Invalid model name format: '${normalizedName}'. Expected provider-prefixed name like 'openai_gpt_4o' or a recognizable model prefix.`);
314
+ }
315
+ const normalizedModel = normalizeModelForProvider(inferredProvider, normalizedName);
316
+ return buildProviderModel(inferredProvider, normalizedModel);
317
+ };
@@ -1,13 +1,25 @@
1
+ import { type Config as OllamaClientConfig, type Options as OllamaOptions } from 'ollama';
1
2
  import type { BaseChatModel, ChatInvokeOptions } from '../base.js';
2
3
  import { ChatInvokeCompletion } from '../views.js';
3
4
  import type { Message } from '../messages.js';
5
+ export interface ChatOllamaOptions {
6
+ model?: string;
7
+ host?: string;
8
+ timeout?: number | null;
9
+ clientParams?: Partial<OllamaClientConfig> | null;
10
+ ollamaOptions?: Partial<OllamaOptions> | null;
11
+ }
4
12
  export declare class ChatOllama implements BaseChatModel {
5
13
  model: string;
6
14
  provider: string;
7
15
  private client;
8
- constructor(model?: string, host?: string);
16
+ private ollamaOptions;
17
+ constructor(modelOrOptions?: string | ChatOllamaOptions, host?: string);
9
18
  get name(): string;
10
19
  get model_name(): string;
20
+ private getZodSchemaCandidate;
21
+ private parseOutput;
22
+ private createTimeoutFetch;
11
23
  ainvoke(messages: Message[], output_format?: undefined, options?: ChatInvokeOptions): Promise<ChatInvokeCompletion<string>>;
12
24
  ainvoke<T>(messages: Message[], output_format: {
13
25
  parse: (input: string) => T;
@@ -1,13 +1,33 @@
1
- import { Ollama } from 'ollama';
1
+ import { Ollama, } from 'ollama';
2
+ import { ModelProviderError } from '../exceptions.js';
2
3
  import { ChatInvokeCompletion } from '../views.js';
4
+ import { zodSchemaToJsonSchema } from '../schema.js';
3
5
  import { OllamaMessageSerializer } from './serializer.js';
4
6
  export class ChatOllama {
5
7
  model;
6
8
  provider = 'ollama';
7
9
  client;
8
- constructor(model = 'qwen2.5:latest', host = 'http://localhost:11434') {
10
+ ollamaOptions;
11
+ constructor(modelOrOptions = 'qwen2.5:latest', host = 'http://localhost:11434') {
12
+ const normalizedOptions = typeof modelOrOptions === 'string'
13
+ ? { model: modelOrOptions, host }
14
+ : modelOrOptions;
15
+ const { model = 'qwen2.5:latest', host: ollamaHost = 'http://localhost:11434', timeout = null, clientParams = null, ollamaOptions = null, } = normalizedOptions;
9
16
  this.model = model;
10
- this.client = new Ollama({ host });
17
+ this.ollamaOptions = ollamaOptions;
18
+ const baseFetch = clientParams?.fetch;
19
+ let fetchWithTimeout = baseFetch;
20
+ if (timeout !== null && timeout !== undefined) {
21
+ const timeoutMs = Number(timeout);
22
+ if (Number.isFinite(timeoutMs) && timeoutMs > 0) {
23
+ fetchWithTimeout = this.createTimeoutFetch(baseFetch, timeoutMs);
24
+ }
25
+ }
26
+ this.client = new Ollama({
27
+ host: ollamaHost,
28
+ ...(clientParams ?? {}),
29
+ ...(fetchWithTimeout ? { fetch: fetchWithTimeout } : {}),
30
+ });
11
31
  }
12
32
  get name() {
13
33
  return this.model;
@@ -15,18 +35,79 @@ export class ChatOllama {
15
35
  get model_name() {
16
36
  return this.model;
17
37
  }
38
+ getZodSchemaCandidate(output_format) {
39
+ const output = output_format;
40
+ if (output &&
41
+ typeof output === 'object' &&
42
+ typeof output.safeParse === 'function' &&
43
+ typeof output.parse === 'function') {
44
+ return output;
45
+ }
46
+ if (output &&
47
+ typeof output === 'object' &&
48
+ output.schema &&
49
+ typeof output.schema.safeParse === 'function' &&
50
+ typeof output.schema.parse === 'function') {
51
+ return output.schema;
52
+ }
53
+ return null;
54
+ }
55
+ parseOutput(output_format, payload) {
56
+ const output = output_format;
57
+ if (output &&
58
+ typeof output === 'object' &&
59
+ output.schema &&
60
+ typeof output.schema.parse === 'function') {
61
+ return output.schema.parse(payload);
62
+ }
63
+ return output.parse(payload);
64
+ }
65
+ createTimeoutFetch(baseFetch, timeoutMs) {
66
+ return async (input, init) => {
67
+ const fetchImpl = baseFetch ?? fetch;
68
+ const timeoutController = new AbortController();
69
+ const timeoutHandle = setTimeout(() => timeoutController.abort(), timeoutMs);
70
+ const externalSignal = init?.signal;
71
+ const onAbort = () => timeoutController.abort();
72
+ try {
73
+ if (externalSignal) {
74
+ if (externalSignal.aborted) {
75
+ timeoutController.abort();
76
+ }
77
+ else {
78
+ externalSignal.addEventListener('abort', onAbort, { once: true });
79
+ }
80
+ }
81
+ return await fetchImpl(input, {
82
+ ...init,
83
+ signal: timeoutController.signal,
84
+ });
85
+ }
86
+ finally {
87
+ clearTimeout(timeoutHandle);
88
+ externalSignal?.removeEventListener('abort', onAbort);
89
+ }
90
+ };
91
+ }
18
92
  async ainvoke(messages, output_format, options = {}) {
19
93
  const serializer = new OllamaMessageSerializer();
20
94
  const ollamaMessages = serializer.serialize(messages);
95
+ const zodSchemaCandidate = this.getZodSchemaCandidate(output_format);
21
96
  let format = undefined;
22
- if (output_format && 'schema' in output_format && output_format.schema) {
23
- // Ollama supports 'json' format
97
+ if (zodSchemaCandidate) {
98
+ format = zodSchemaToJsonSchema(zodSchemaCandidate, {
99
+ name: 'Response',
100
+ target: 'jsonSchema7',
101
+ });
102
+ }
103
+ else if (output_format) {
24
104
  format = 'json';
25
105
  }
26
106
  const requestPromise = this.client.chat({
27
107
  model: this.model,
28
108
  messages: ollamaMessages,
29
109
  format: format,
110
+ options: this.ollamaOptions ?? undefined,
30
111
  stream: false,
31
112
  });
32
113
  const abortSignal = options.signal;
@@ -57,21 +138,31 @@ export class ChatOllama {
57
138
  });
58
139
  })
59
140
  : await requestPromise;
60
- const content = response.message.content;
61
- let completion = content;
62
- if (output_format) {
63
- try {
64
- completion = output_format.parse(JSON.parse(content));
65
- }
66
- catch (e) {
67
- console.error('Failed to parse completion', e);
68
- throw e;
141
+ try {
142
+ const content = response.message.content;
143
+ let completion = content;
144
+ if (output_format) {
145
+ if (zodSchemaCandidate) {
146
+ completion = this.parseOutput(output_format, JSON.parse(content));
147
+ }
148
+ else {
149
+ try {
150
+ completion = this.parseOutput(output_format, JSON.parse(content));
151
+ }
152
+ catch {
153
+ completion = this.parseOutput(output_format, content);
154
+ }
155
+ }
69
156
  }
157
+ const stopReason = response.done_reason ?? null;
158
+ return new ChatInvokeCompletion(completion, {
159
+ prompt_tokens: response.prompt_eval_count ?? 0,
160
+ completion_tokens: response.eval_count ?? 0,
161
+ total_tokens: (response.prompt_eval_count ?? 0) + (response.eval_count ?? 0),
162
+ }, null, null, stopReason);
163
+ }
164
+ catch (error) {
165
+ throw new ModelProviderError(error?.message ?? String(error), error?.status ?? 502, this.model);
70
166
  }
71
- return new ChatInvokeCompletion(completion, {
72
- prompt_tokens: response.prompt_eval_count ?? 0,
73
- completion_tokens: response.eval_count ?? 0,
74
- total_tokens: (response.prompt_eval_count ?? 0) + (response.eval_count ?? 0),
75
- });
76
167
  }
77
168
  }
@@ -2,5 +2,6 @@ import type { Message as OllamaMessage } from 'ollama';
2
2
  import { type Message } from '../messages.js';
3
3
  export declare class OllamaMessageSerializer {
4
4
  serialize(messages: Message[]): OllamaMessage[];
5
+ private extractTextContent;
5
6
  private serializeMessage;
6
7
  }
@@ -1,18 +1,36 @@
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 OllamaMessageSerializer {
3
3
  serialize(messages) {
4
4
  return messages.map((message) => this.serializeMessage(message));
5
5
  }
6
+ extractTextContent(content) {
7
+ if (content === null || content === undefined) {
8
+ return '';
9
+ }
10
+ if (typeof content === 'string') {
11
+ return content;
12
+ }
13
+ if (!Array.isArray(content)) {
14
+ return '';
15
+ }
16
+ const parts = [];
17
+ for (const part of content) {
18
+ if (part instanceof ContentPartTextParam) {
19
+ parts.push(part.text);
20
+ }
21
+ else if (part instanceof ContentPartRefusalParam) {
22
+ parts.push(`[Refusal] ${part.refusal}`);
23
+ }
24
+ }
25
+ return parts.join('\n');
26
+ }
6
27
  serializeMessage(message) {
7
28
  if (message instanceof UserMessage) {
8
29
  const images = [];
9
- let content = '';
30
+ const content = this.extractTextContent(message.content);
10
31
  if (Array.isArray(message.content)) {
11
32
  message.content.forEach((part) => {
12
- if (part instanceof ContentPartTextParam) {
13
- content += part.text;
14
- }
15
- else if (part instanceof ContentPartImageParam) {
33
+ if (part instanceof ContentPartImageParam) {
16
34
  // Ollama expects base64 string without header
17
35
  const data = part.image_url.url.split(',')[1];
18
36
  if (data)
@@ -20,9 +38,6 @@ export class OllamaMessageSerializer {
20
38
  }
21
39
  });
22
40
  }
23
- else {
24
- content = message.content;
25
- }
26
41
  return {
27
42
  role: 'user',
28
43
  content: content,
@@ -32,19 +47,26 @@ export class OllamaMessageSerializer {
32
47
  if (message instanceof SystemMessage) {
33
48
  return {
34
49
  role: 'system',
35
- content: message.text,
50
+ content: this.extractTextContent(message.content),
36
51
  };
37
52
  }
38
53
  if (message instanceof AssistantMessage) {
39
54
  const toolCalls = message.tool_calls?.map((toolCall) => ({
40
55
  function: {
41
56
  name: toolCall.functionCall.name,
42
- arguments: JSON.parse(toolCall.functionCall.arguments),
57
+ arguments: (() => {
58
+ try {
59
+ return JSON.parse(toolCall.functionCall.arguments);
60
+ }
61
+ catch {
62
+ return { arguments: toolCall.functionCall.arguments };
63
+ }
64
+ })(),
43
65
  },
44
66
  }));
45
67
  return {
46
68
  role: 'assistant',
47
- content: message.text,
69
+ content: this.extractTextContent(message.content),
48
70
  tool_calls: toolCalls,
49
71
  };
50
72
  }
@@ -5,15 +5,26 @@ export interface ChatOpenAIOptions {
5
5
  model?: string;
6
6
  apiKey?: string;
7
7
  organization?: string;
8
+ project?: string;
8
9
  baseURL?: string;
10
+ timeout?: number | null;
9
11
  temperature?: number | null;
10
12
  frequencyPenalty?: number | null;
11
13
  reasoningEffort?: 'low' | 'medium' | 'high';
14
+ serviceTier?: 'auto' | 'default' | 'flex' | 'priority' | 'scale' | null;
12
15
  maxCompletionTokens?: number | null;
13
16
  maxRetries?: number;
17
+ defaultHeaders?: Record<string, string> | null;
18
+ defaultQuery?: Record<string, string | undefined> | null;
19
+ fetchImplementation?: typeof fetch;
20
+ fetchOptions?: RequestInit | null;
14
21
  seed?: number | null;
15
22
  topP?: number | null;
16
23
  addSchemaToSystemPrompt?: boolean;
24
+ dontForceStructuredOutput?: boolean;
25
+ removeMinItemsFromSchema?: boolean;
26
+ removeDefaultsFromSchema?: boolean;
27
+ reasoningModels?: string[] | null;
17
28
  }
18
29
  export declare class ChatOpenAI implements BaseChatModel {
19
30
  model: string;
@@ -22,10 +33,15 @@ export declare class ChatOpenAI implements BaseChatModel {
22
33
  private temperature;
23
34
  private frequencyPenalty;
24
35
  private reasoningEffort;
36
+ private serviceTier;
25
37
  private maxCompletionTokens;
26
38
  private seed;
27
39
  private topP;
28
40
  private addSchemaToSystemPrompt;
41
+ private dontForceStructuredOutput;
42
+ private removeMinItemsFromSchema;
43
+ private removeDefaultsFromSchema;
44
+ private reasoningModels;
29
45
  constructor(options?: ChatOpenAIOptions);
30
46
  get name(): string;
31
47
  get model_name(): string;