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.
- package/README.md +295 -686
- package/dist/actor/element.d.ts +19 -0
- package/dist/actor/element.js +46 -0
- package/dist/actor/index.d.ts +4 -0
- package/dist/actor/index.js +4 -0
- package/dist/actor/mouse.d.ts +19 -0
- package/dist/actor/mouse.js +39 -0
- package/dist/actor/page.d.ts +29 -0
- package/dist/actor/page.js +88 -0
- package/dist/actor/utils.d.ts +4 -0
- package/dist/actor/utils.js +35 -0
- package/dist/agent/cloud-events.d.ts +18 -0
- package/dist/agent/cloud-events.js +65 -2
- package/dist/agent/gif.d.ts +1 -0
- package/dist/agent/gif.js +24 -2
- package/dist/agent/judge.d.ts +17 -0
- package/dist/agent/judge.js +197 -0
- package/dist/agent/message-manager/service.d.ts +12 -4
- package/dist/agent/message-manager/service.js +205 -39
- package/dist/agent/message-manager/utils.js +0 -1
- package/dist/agent/message-manager/views.d.ts +4 -0
- package/dist/agent/message-manager/views.js +11 -7
- package/dist/agent/prompts.d.ts +24 -3
- package/dist/agent/prompts.js +274 -59
- package/dist/agent/service.d.ts +99 -41
- package/dist/agent/service.js +2266 -472
- package/dist/agent/variable-detector.d.ts +12 -0
- package/dist/agent/variable-detector.js +211 -0
- package/dist/agent/views.d.ts +237 -18
- package/dist/agent/views.js +446 -33
- package/dist/browser/cloud/cloud.d.ts +20 -0
- package/dist/browser/cloud/cloud.js +129 -0
- package/dist/browser/cloud/index.d.ts +2 -0
- package/dist/browser/cloud/index.js +2 -0
- package/dist/browser/cloud/views.d.ts +41 -0
- package/dist/browser/cloud/views.js +35 -0
- package/dist/browser/events.d.ts +345 -0
- package/dist/browser/events.js +566 -0
- package/dist/browser/extensions.js +17 -17
- package/dist/browser/index.d.ts +4 -0
- package/dist/browser/index.js +4 -0
- package/dist/browser/profile.d.ts +8 -2
- package/dist/browser/profile.js +79 -12
- package/dist/browser/session-manager.d.ts +85 -0
- package/dist/browser/session-manager.js +208 -0
- package/dist/browser/session.d.ts +100 -8
- package/dist/browser/session.js +1097 -58
- package/dist/browser/types.d.ts +0 -2
- package/dist/browser/views.d.ts +39 -0
- package/dist/browser/views.js +32 -0
- package/dist/browser/watchdogs/aboutblank-watchdog.d.ts +12 -0
- package/dist/browser/watchdogs/aboutblank-watchdog.js +131 -0
- package/dist/browser/watchdogs/base.d.ts +21 -0
- package/dist/browser/watchdogs/base.js +81 -0
- package/dist/browser/watchdogs/cdp-session-watchdog.d.ts +14 -0
- package/dist/browser/watchdogs/cdp-session-watchdog.js +177 -0
- package/dist/browser/watchdogs/crash-watchdog.d.ts +38 -0
- package/dist/browser/watchdogs/crash-watchdog.js +296 -0
- package/dist/browser/watchdogs/default-action-watchdog.d.ts +49 -0
- package/dist/browser/watchdogs/default-action-watchdog.js +212 -0
- package/dist/browser/watchdogs/dom-watchdog.d.ts +8 -0
- package/dist/browser/watchdogs/dom-watchdog.js +31 -0
- package/dist/browser/watchdogs/downloads-watchdog.d.ts +77 -0
- package/dist/browser/watchdogs/downloads-watchdog.js +409 -0
- package/dist/browser/watchdogs/har-recording-watchdog.d.ts +19 -0
- package/dist/browser/watchdogs/har-recording-watchdog.js +317 -0
- package/dist/browser/watchdogs/index.d.ts +15 -0
- package/dist/browser/watchdogs/index.js +15 -0
- package/dist/browser/watchdogs/local-browser-watchdog.d.ts +10 -0
- package/dist/browser/watchdogs/local-browser-watchdog.js +32 -0
- package/dist/browser/watchdogs/permissions-watchdog.d.ts +8 -0
- package/dist/browser/watchdogs/permissions-watchdog.js +73 -0
- package/dist/browser/watchdogs/popups-watchdog.d.ts +13 -0
- package/dist/browser/watchdogs/popups-watchdog.js +77 -0
- package/dist/browser/watchdogs/recording-watchdog.d.ts +27 -0
- package/dist/browser/watchdogs/recording-watchdog.js +249 -0
- package/dist/browser/watchdogs/screenshot-watchdog.d.ts +6 -0
- package/dist/browser/watchdogs/screenshot-watchdog.js +13 -0
- package/dist/browser/watchdogs/security-watchdog.d.ts +10 -0
- package/dist/browser/watchdogs/security-watchdog.js +84 -0
- package/dist/browser/watchdogs/storage-state-watchdog.d.ts +24 -0
- package/dist/browser/watchdogs/storage-state-watchdog.js +288 -0
- package/dist/cli.d.ts +7 -2
- package/dist/cli.js +182 -25
- package/dist/code-use/formatting.d.ts +3 -0
- package/dist/code-use/formatting.js +18 -0
- package/dist/code-use/index.d.ts +6 -0
- package/dist/code-use/index.js +6 -0
- package/dist/code-use/namespace.d.ts +5 -0
- package/dist/code-use/namespace.js +81 -0
- package/dist/code-use/notebook-export.d.ts +3 -0
- package/dist/code-use/notebook-export.js +56 -0
- package/dist/code-use/service.d.ts +24 -0
- package/dist/code-use/service.js +104 -0
- package/dist/code-use/utils.d.ts +4 -0
- package/dist/code-use/utils.js +98 -0
- package/dist/code-use/views.d.ts +108 -0
- package/dist/code-use/views.js +165 -0
- package/dist/config.d.ts +13 -0
- package/dist/config.js +69 -3
- package/dist/controller/registry/service.d.ts +10 -1
- package/dist/controller/registry/service.js +266 -10
- package/dist/controller/registry/views.d.ts +4 -1
- package/dist/controller/registry/views.js +25 -2
- package/dist/controller/service.d.ts +10 -1
- package/dist/controller/service.js +1807 -268
- package/dist/controller/views.d.ts +78 -155
- package/dist/controller/views.js +61 -12
- package/dist/dom/history-tree-processor/service.d.ts +5 -0
- package/dist/dom/history-tree-processor/service.js +169 -14
- package/dist/dom/history-tree-processor/view.d.ts +7 -1
- package/dist/dom/history-tree-processor/view.js +10 -1
- package/dist/dom/markdown-extractor.d.ts +37 -0
- package/dist/dom/markdown-extractor.js +345 -0
- package/dist/dom/service.d.ts +3 -1
- package/dist/dom/service.js +76 -0
- package/dist/dom/views.d.ts +1 -0
- package/dist/dom/views.js +45 -0
- package/dist/event-bus.d.ts +107 -7
- package/dist/event-bus.js +313 -10
- package/dist/exceptions.d.ts +0 -3
- package/dist/exceptions.js +0 -7
- package/dist/filesystem/file-system.d.ts +18 -0
- package/dist/filesystem/file-system.js +503 -42
- package/dist/index.d.ts +7 -0
- package/dist/index.js +6 -0
- package/dist/integrations/gmail/actions.d.ts +3 -3
- package/dist/integrations/gmail/actions.js +4 -4
- package/dist/llm/anthropic/chat.d.ts +18 -1
- package/dist/llm/anthropic/chat.js +123 -55
- package/dist/llm/anthropic/serializer.d.ts +2 -0
- package/dist/llm/anthropic/serializer.js +81 -9
- package/dist/llm/aws/chat-anthropic.d.ts +17 -0
- package/dist/llm/aws/chat-anthropic.js +126 -26
- package/dist/llm/aws/chat-bedrock.d.ts +28 -1
- package/dist/llm/aws/chat-bedrock.js +161 -34
- package/dist/llm/aws/serializer.d.ts +13 -1
- package/dist/llm/aws/serializer.js +56 -17
- package/dist/llm/azure/chat.d.ts +53 -2
- package/dist/llm/azure/chat.js +366 -54
- package/dist/llm/base.d.ts +2 -0
- package/dist/llm/browser-use/chat.d.ts +40 -0
- package/dist/llm/browser-use/chat.js +305 -0
- package/dist/llm/browser-use/index.d.ts +1 -0
- package/dist/llm/browser-use/index.js +1 -0
- package/dist/llm/cerebras/chat.d.ts +39 -0
- package/dist/llm/cerebras/chat.js +178 -0
- package/dist/llm/cerebras/index.d.ts +2 -0
- package/dist/llm/cerebras/index.js +2 -0
- package/dist/llm/cerebras/serializer.d.ts +7 -0
- package/dist/llm/cerebras/serializer.js +82 -0
- package/dist/llm/deepseek/chat.d.ts +19 -2
- package/dist/llm/deepseek/chat.js +138 -25
- package/dist/llm/google/chat.d.ts +46 -2
- package/dist/llm/google/chat.js +267 -64
- package/dist/llm/google/serializer.d.ts +9 -1
- package/dist/llm/google/serializer.js +141 -34
- package/dist/llm/groq/chat.d.ts +21 -2
- package/dist/llm/groq/chat.js +125 -26
- package/dist/llm/groq/parser.js +3 -1
- package/dist/llm/mistral/chat.d.ts +43 -0
- package/dist/llm/mistral/chat.js +154 -0
- package/dist/llm/mistral/index.d.ts +2 -0
- package/dist/llm/mistral/index.js +2 -0
- package/dist/llm/mistral/schema.d.ts +8 -0
- package/dist/llm/mistral/schema.js +27 -0
- package/dist/llm/models.d.ts +2 -0
- package/dist/llm/models.js +317 -0
- package/dist/llm/ollama/chat.d.ts +13 -1
- package/dist/llm/ollama/chat.js +110 -19
- package/dist/llm/ollama/serializer.d.ts +1 -0
- package/dist/llm/ollama/serializer.js +34 -12
- package/dist/llm/openai/chat.d.ts +16 -0
- package/dist/llm/openai/chat.js +94 -44
- package/dist/llm/openai/like.d.ts +5 -3
- package/dist/llm/openai/like.js +7 -3
- package/dist/llm/openai/responses-serializer.d.ts +18 -0
- package/dist/llm/openai/responses-serializer.js +72 -0
- package/dist/llm/openrouter/chat.d.ts +28 -2
- package/dist/llm/openrouter/chat.js +115 -29
- package/dist/llm/schema.d.ts +11 -1
- package/dist/llm/schema.js +81 -1
- package/dist/llm/vercel/chat.d.ts +50 -0
- package/dist/llm/vercel/chat.js +276 -0
- package/dist/llm/vercel/index.d.ts +1 -0
- package/dist/llm/vercel/index.js +1 -0
- package/dist/llm/vercel/serializer.d.ts +5 -0
- package/dist/llm/vercel/serializer.js +7 -0
- package/dist/llm/views.d.ts +2 -1
- package/dist/llm/views.js +3 -1
- package/dist/logging-config.d.ts +2 -0
- package/dist/logging-config.js +82 -29
- package/dist/mcp/client.d.ts +10 -5
- package/dist/mcp/client.js +14 -9
- package/dist/mcp/controller.d.ts +42 -3
- package/dist/mcp/controller.js +56 -31
- package/dist/mcp/server.d.ts +14 -0
- package/dist/mcp/server.js +255 -52
- package/dist/observability.js +10 -4
- package/dist/sandbox/index.d.ts +2 -0
- package/dist/sandbox/index.js +2 -0
- package/dist/sandbox/sandbox.d.ts +19 -0
- package/dist/sandbox/sandbox.js +140 -0
- package/dist/sandbox/views.d.ts +67 -0
- package/dist/sandbox/views.js +121 -0
- package/dist/skill-cli/index.d.ts +3 -0
- package/dist/skill-cli/index.js +3 -0
- package/dist/skill-cli/protocol.d.ts +30 -0
- package/dist/skill-cli/protocol.js +48 -0
- package/dist/skill-cli/server.d.ts +11 -0
- package/dist/skill-cli/server.js +85 -0
- package/dist/skill-cli/sessions.d.ts +24 -0
- package/dist/skill-cli/sessions.js +47 -0
- package/dist/skills/index.d.ts +3 -0
- package/dist/skills/index.js +3 -0
- package/dist/skills/service.d.ts +27 -0
- package/dist/skills/service.js +266 -0
- package/dist/skills/utils.d.ts +6 -0
- package/dist/skills/utils.js +53 -0
- package/dist/skills/views.d.ts +40 -0
- package/dist/skills/views.js +10 -0
- package/dist/sync/auth.js +8 -3
- package/dist/sync/service.d.ts +6 -6
- package/dist/sync/service.js +54 -89
- package/dist/telemetry/views.d.ts +20 -6
- package/dist/telemetry/views.js +23 -5
- package/dist/tokens/custom-pricing.d.ts +2 -0
- package/dist/tokens/custom-pricing.js +22 -0
- package/dist/tokens/index.d.ts +2 -0
- package/dist/tokens/index.js +2 -0
- package/dist/tokens/mappings.d.ts +1 -0
- package/dist/tokens/mappings.js +3 -0
- package/dist/tokens/service.js +27 -8
- package/dist/tools/extraction/index.d.ts +2 -0
- package/dist/tools/extraction/index.js +2 -0
- package/dist/tools/extraction/schema-utils.d.ts +6 -0
- package/dist/tools/extraction/schema-utils.js +237 -0
- package/dist/tools/extraction/views.d.ts +7 -0
- package/dist/tools/index.d.ts +5 -0
- package/dist/tools/index.js +5 -0
- package/dist/tools/registry/index.d.ts +2 -0
- package/dist/tools/registry/index.js +2 -0
- package/dist/tools/registry/service.d.ts +1 -0
- package/dist/tools/registry/service.js +1 -0
- package/dist/tools/registry/views.d.ts +1 -0
- package/dist/tools/registry/views.js +1 -0
- package/dist/tools/service.d.ts +2 -0
- package/dist/tools/service.js +1 -0
- package/dist/tools/utils.d.ts +2 -0
- package/dist/tools/utils.js +57 -0
- package/dist/tools/views.d.ts +1 -0
- package/dist/tools/views.js +1 -0
- package/dist/utils.d.ts +10 -1
- package/dist/utils.js +70 -3
- package/package.json +87 -26
- package/dist/dom/playground/process-dom.js +0 -5
- package/dist/dom/playground/test-accessibility.d.ts +0 -44
- package/dist/dom/playground/test-accessibility.js +0 -111
- /package/dist/{dom/playground/process-dom.d.ts → tools/extraction/views.js} +0 -0
package/dist/llm/openai/chat.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import OpenAI from 'openai';
|
|
2
|
-
import { zodToJsonSchema } from 'zod-to-json-schema';
|
|
3
2
|
import { ChatInvokeCompletion } from '../views.js';
|
|
4
3
|
import { OpenAIMessageSerializer } from './serializer.js';
|
|
5
|
-
import { ModelProviderError } from '../exceptions.js';
|
|
4
|
+
import { ModelProviderError, ModelRateLimitError } from '../exceptions.js';
|
|
5
|
+
import { SchemaOptimizer, zodSchemaToJsonSchema } from '../schema.js';
|
|
6
6
|
// Reasoning models that support reasoning_effort parameter
|
|
7
|
-
const
|
|
7
|
+
const DEFAULT_REASONING_MODELS = [
|
|
8
8
|
'o4-mini',
|
|
9
9
|
'o3',
|
|
10
10
|
'o3-mini',
|
|
@@ -22,25 +22,43 @@ export class ChatOpenAI {
|
|
|
22
22
|
temperature;
|
|
23
23
|
frequencyPenalty;
|
|
24
24
|
reasoningEffort;
|
|
25
|
+
serviceTier;
|
|
25
26
|
maxCompletionTokens;
|
|
26
27
|
seed;
|
|
27
28
|
topP;
|
|
28
29
|
addSchemaToSystemPrompt;
|
|
30
|
+
dontForceStructuredOutput;
|
|
31
|
+
removeMinItemsFromSchema;
|
|
32
|
+
removeDefaultsFromSchema;
|
|
33
|
+
reasoningModels;
|
|
29
34
|
constructor(options = {}) {
|
|
30
|
-
const { model = 'gpt-4o', apiKey, organization, baseURL, temperature = 0.2, frequencyPenalty = 0.
|
|
35
|
+
const { model = 'gpt-4o', apiKey, organization, project, baseURL, timeout = null, temperature = 0.2, frequencyPenalty = 0.3, reasoningEffort = 'low', serviceTier = null, maxCompletionTokens = 4096, maxRetries = 5, defaultHeaders = null, defaultQuery = null, fetchImplementation, fetchOptions = null, seed = null, topP = null, addSchemaToSystemPrompt = false, dontForceStructuredOutput = false, removeMinItemsFromSchema = false, removeDefaultsFromSchema = false, reasoningModels = DEFAULT_REASONING_MODELS, } = options;
|
|
31
36
|
this.model = model;
|
|
32
37
|
this.temperature = temperature;
|
|
33
38
|
this.frequencyPenalty = frequencyPenalty;
|
|
34
39
|
this.reasoningEffort = reasoningEffort;
|
|
40
|
+
this.serviceTier = serviceTier;
|
|
35
41
|
this.maxCompletionTokens = maxCompletionTokens;
|
|
36
42
|
this.seed = seed;
|
|
37
43
|
this.topP = topP;
|
|
38
44
|
this.addSchemaToSystemPrompt = addSchemaToSystemPrompt;
|
|
45
|
+
this.dontForceStructuredOutput = dontForceStructuredOutput;
|
|
46
|
+
this.removeMinItemsFromSchema = removeMinItemsFromSchema;
|
|
47
|
+
this.removeDefaultsFromSchema = removeDefaultsFromSchema;
|
|
48
|
+
this.reasoningModels = reasoningModels
|
|
49
|
+
? [...reasoningModels]
|
|
50
|
+
: reasoningModels;
|
|
39
51
|
this.client = new OpenAI({
|
|
40
52
|
apiKey,
|
|
41
53
|
organization,
|
|
54
|
+
project,
|
|
42
55
|
baseURL,
|
|
56
|
+
timeout: timeout ?? undefined,
|
|
43
57
|
maxRetries,
|
|
58
|
+
defaultHeaders: defaultHeaders ?? undefined,
|
|
59
|
+
defaultQuery: defaultQuery ?? undefined,
|
|
60
|
+
fetch: fetchImplementation,
|
|
61
|
+
fetchOptions: (fetchOptions ?? undefined),
|
|
44
62
|
});
|
|
45
63
|
}
|
|
46
64
|
get name() {
|
|
@@ -50,7 +68,7 @@ export class ChatOpenAI {
|
|
|
50
68
|
return this.model;
|
|
51
69
|
}
|
|
52
70
|
isReasoningModel() {
|
|
53
|
-
return
|
|
71
|
+
return (this.reasoningModels ?? []).some((m) => this.model.toLowerCase().includes(m.toLowerCase()));
|
|
54
72
|
}
|
|
55
73
|
getUsage(response) {
|
|
56
74
|
if (!response.usage)
|
|
@@ -96,36 +114,69 @@ export class ChatOpenAI {
|
|
|
96
114
|
if (this.topP !== null) {
|
|
97
115
|
modelParams.top_p = this.topP;
|
|
98
116
|
}
|
|
117
|
+
if (this.serviceTier !== null) {
|
|
118
|
+
modelParams.service_tier = this.serviceTier;
|
|
119
|
+
}
|
|
120
|
+
const zodSchemaCandidate = (() => {
|
|
121
|
+
const output = output_format;
|
|
122
|
+
if (output &&
|
|
123
|
+
typeof output === 'object' &&
|
|
124
|
+
typeof output.safeParse === 'function' &&
|
|
125
|
+
typeof output.parse === 'function') {
|
|
126
|
+
return output;
|
|
127
|
+
}
|
|
128
|
+
if (output &&
|
|
129
|
+
typeof output === 'object' &&
|
|
130
|
+
output.schema &&
|
|
131
|
+
typeof output.schema.safeParse === 'function' &&
|
|
132
|
+
typeof output.schema.parse === 'function') {
|
|
133
|
+
return output.schema;
|
|
134
|
+
}
|
|
135
|
+
return null;
|
|
136
|
+
})();
|
|
99
137
|
let responseFormat = undefined;
|
|
100
|
-
if (
|
|
101
|
-
// Assuming output_format is a Zod schema wrapper or similar that has a schema property
|
|
102
|
-
// But the interface says { parse: ... }
|
|
103
|
-
// In the plan, it was passed as a Zod schema directly.
|
|
104
|
-
// However, the BaseChatModel interface I saw earlier has:
|
|
105
|
-
// ainvoke<T>(messages: Message[], output_format: { parse: (input: string) => T } | undefined): Promise<ChatInvokeCompletion<T>>;
|
|
106
|
-
// So I need to handle how to extract the schema if I want to use structured outputs.
|
|
107
|
-
// If output_format is just a Zod schema, it has a parse method.
|
|
108
|
-
// Let's assume it's a Zod schema for now, as that's what the plan implies.
|
|
109
|
-
// We need to cast it to any or check if it's a Zod schema to get the schema for JSON schema generation.
|
|
110
|
-
// For now, I'll try to use zodToJsonSchema on it if possible.
|
|
138
|
+
if (zodSchemaCandidate) {
|
|
111
139
|
try {
|
|
112
|
-
const
|
|
113
|
-
name: '
|
|
140
|
+
const rawJsonSchema = zodSchemaToJsonSchema(zodSchemaCandidate, {
|
|
141
|
+
name: 'agent_output',
|
|
114
142
|
target: 'jsonSchema7',
|
|
115
143
|
});
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
144
|
+
const optimizedJsonSchema = SchemaOptimizer.createOptimizedJsonSchema(rawJsonSchema, {
|
|
145
|
+
removeMinItems: this.removeMinItemsFromSchema,
|
|
146
|
+
removeDefaults: this.removeDefaultsFromSchema,
|
|
147
|
+
});
|
|
148
|
+
const responseJsonSchema = {
|
|
149
|
+
name: 'agent_output',
|
|
150
|
+
schema: optimizedJsonSchema,
|
|
151
|
+
strict: true,
|
|
124
152
|
};
|
|
153
|
+
if (this.addSchemaToSystemPrompt && openaiMessages.length > 0) {
|
|
154
|
+
const firstMessage = openaiMessages[0];
|
|
155
|
+
const schemaText = `\n<json_schema>\n` +
|
|
156
|
+
`${JSON.stringify(responseJsonSchema, null, 2)}\n` +
|
|
157
|
+
`</json_schema>`;
|
|
158
|
+
if (firstMessage?.role === 'system') {
|
|
159
|
+
if (typeof firstMessage.content === 'string') {
|
|
160
|
+
firstMessage.content =
|
|
161
|
+
(firstMessage.content ?? '') + schemaText;
|
|
162
|
+
}
|
|
163
|
+
else if (Array.isArray(firstMessage.content)) {
|
|
164
|
+
firstMessage.content = [
|
|
165
|
+
...firstMessage.content,
|
|
166
|
+
{ type: 'text', text: schemaText },
|
|
167
|
+
];
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
if (!this.dontForceStructuredOutput) {
|
|
172
|
+
responseFormat = {
|
|
173
|
+
type: 'json_schema',
|
|
174
|
+
json_schema: responseJsonSchema,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
125
177
|
}
|
|
126
|
-
catch
|
|
127
|
-
|
|
128
|
-
console.warn('Failed to convert output_format to JSON schema', e);
|
|
178
|
+
catch {
|
|
179
|
+
responseFormat = undefined;
|
|
129
180
|
}
|
|
130
181
|
}
|
|
131
182
|
try {
|
|
@@ -137,33 +188,32 @@ export class ChatOpenAI {
|
|
|
137
188
|
}, options.signal ? { signal: options.signal } : undefined);
|
|
138
189
|
const content = response.choices[0].message.content || '';
|
|
139
190
|
const usage = this.getUsage(response);
|
|
191
|
+
const stopReason = response.choices[0].finish_reason ?? null;
|
|
140
192
|
let completion = content;
|
|
141
193
|
if (output_format) {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
194
|
+
if (zodSchemaCandidate) {
|
|
195
|
+
const parsedJson = JSON.parse(content);
|
|
196
|
+
const output = output_format;
|
|
197
|
+
if (output &&
|
|
198
|
+
typeof output === 'object' &&
|
|
199
|
+
output.schema &&
|
|
200
|
+
typeof output.schema.parse === 'function') {
|
|
201
|
+
completion = output.schema.parse(parsedJson);
|
|
147
202
|
}
|
|
148
203
|
else {
|
|
149
|
-
|
|
150
|
-
// But usually for OpenAI we want structured output if a schema is provided.
|
|
151
|
-
// If we didn't use json_schema, we might still try to parse if it looks like JSON?
|
|
152
|
-
// For now, let's trust the output_format.parse
|
|
153
|
-
completion = output_format.parse(content);
|
|
204
|
+
completion = output_format.parse(parsedJson);
|
|
154
205
|
}
|
|
155
206
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
throw e;
|
|
207
|
+
else {
|
|
208
|
+
completion = output_format.parse(content);
|
|
159
209
|
}
|
|
160
210
|
}
|
|
161
|
-
return new ChatInvokeCompletion(completion, usage);
|
|
211
|
+
return new ChatInvokeCompletion(completion, usage, null, null, stopReason);
|
|
162
212
|
}
|
|
163
213
|
catch (error) {
|
|
164
214
|
// Handle OpenAI-specific errors
|
|
165
215
|
if (error?.status === 429) {
|
|
166
|
-
throw new
|
|
216
|
+
throw new ModelRateLimitError(error?.message ?? 'Rate limit exceeded', 429, this.model);
|
|
167
217
|
}
|
|
168
218
|
if (error?.status >= 500) {
|
|
169
219
|
throw new ModelProviderError(error?.message ?? 'Server error', error.status, this.model);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ChatOpenAI } from './chat.js';
|
|
1
|
+
import { ChatOpenAI, type ChatOpenAIOptions } from './chat.js';
|
|
2
2
|
/**
|
|
3
3
|
* A class to interact with any provider using the OpenAI API schema.
|
|
4
4
|
*
|
|
@@ -11,7 +11,9 @@ import { ChatOpenAI } from './chat.js';
|
|
|
11
11
|
*/
|
|
12
12
|
export declare class ChatOpenAILike extends ChatOpenAI {
|
|
13
13
|
/**
|
|
14
|
-
* @param
|
|
14
|
+
* @param options - A model name or ChatOpenAI-compatible options
|
|
15
15
|
*/
|
|
16
|
-
constructor(
|
|
16
|
+
constructor(options: string | (ChatOpenAIOptions & {
|
|
17
|
+
model: string;
|
|
18
|
+
}));
|
|
17
19
|
}
|
package/dist/llm/openai/like.js
CHANGED
|
@@ -11,9 +11,13 @@ import { ChatOpenAI } from './chat.js';
|
|
|
11
11
|
*/
|
|
12
12
|
export class ChatOpenAILike extends ChatOpenAI {
|
|
13
13
|
/**
|
|
14
|
-
* @param
|
|
14
|
+
* @param options - A model name or ChatOpenAI-compatible options
|
|
15
15
|
*/
|
|
16
|
-
constructor(
|
|
17
|
-
|
|
16
|
+
constructor(options) {
|
|
17
|
+
if (typeof options === 'string') {
|
|
18
|
+
super({ model: options });
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
super(options);
|
|
18
22
|
}
|
|
19
23
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type Message } from '../messages.js';
|
|
2
|
+
type ResponsesInputPart = {
|
|
3
|
+
type: 'input_text';
|
|
4
|
+
text: string;
|
|
5
|
+
} | {
|
|
6
|
+
type: 'input_image';
|
|
7
|
+
image_url: string;
|
|
8
|
+
detail?: 'auto' | 'low' | 'high';
|
|
9
|
+
};
|
|
10
|
+
export type ResponsesInputMessage = {
|
|
11
|
+
role: 'user' | 'system' | 'assistant';
|
|
12
|
+
content: string | ResponsesInputPart[];
|
|
13
|
+
};
|
|
14
|
+
export declare class ResponsesAPIMessageSerializer {
|
|
15
|
+
serialize(messages: Message[]): ResponsesInputMessage[];
|
|
16
|
+
private serializeMessage;
|
|
17
|
+
}
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { AssistantMessage, ContentPartImageParam, ContentPartRefusalParam, ContentPartTextParam, SystemMessage, UserMessage, } from '../messages.js';
|
|
2
|
+
export class ResponsesAPIMessageSerializer {
|
|
3
|
+
serialize(messages) {
|
|
4
|
+
return messages.map((message) => this.serializeMessage(message));
|
|
5
|
+
}
|
|
6
|
+
serializeMessage(message) {
|
|
7
|
+
if (message instanceof UserMessage) {
|
|
8
|
+
if (typeof message.content === 'string') {
|
|
9
|
+
return { role: 'user', content: message.content };
|
|
10
|
+
}
|
|
11
|
+
const content = message.content
|
|
12
|
+
.map((part) => {
|
|
13
|
+
if (part instanceof ContentPartTextParam) {
|
|
14
|
+
return { type: 'input_text', text: part.text };
|
|
15
|
+
}
|
|
16
|
+
if (part instanceof ContentPartImageParam) {
|
|
17
|
+
return {
|
|
18
|
+
type: 'input_image',
|
|
19
|
+
image_url: part.image_url.url,
|
|
20
|
+
detail: part.image_url.detail,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
return null;
|
|
24
|
+
})
|
|
25
|
+
.filter((part) => part !== null);
|
|
26
|
+
return { role: 'user', content };
|
|
27
|
+
}
|
|
28
|
+
if (message instanceof SystemMessage) {
|
|
29
|
+
if (typeof message.content === 'string') {
|
|
30
|
+
return { role: 'system', content: message.content };
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
role: 'system',
|
|
34
|
+
content: message.content.map((part) => ({
|
|
35
|
+
type: 'input_text',
|
|
36
|
+
text: part.text,
|
|
37
|
+
})),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
if (message instanceof AssistantMessage) {
|
|
41
|
+
if (message.content == null) {
|
|
42
|
+
if (Array.isArray(message.tool_calls) &&
|
|
43
|
+
message.tool_calls.length > 0) {
|
|
44
|
+
const toolCallText = message.tool_calls
|
|
45
|
+
.map((toolCall) => `[Tool call: ${toolCall.functionCall.name}(${toolCall.functionCall.arguments})]`)
|
|
46
|
+
.join('\n');
|
|
47
|
+
return { role: 'assistant', content: toolCallText };
|
|
48
|
+
}
|
|
49
|
+
return { role: 'assistant', content: '' };
|
|
50
|
+
}
|
|
51
|
+
if (typeof message.content === 'string') {
|
|
52
|
+
return { role: 'assistant', content: message.content };
|
|
53
|
+
}
|
|
54
|
+
const content = message.content
|
|
55
|
+
.map((part) => {
|
|
56
|
+
if (part instanceof ContentPartTextParam) {
|
|
57
|
+
return { type: 'input_text', text: part.text };
|
|
58
|
+
}
|
|
59
|
+
if (part instanceof ContentPartRefusalParam) {
|
|
60
|
+
return {
|
|
61
|
+
type: 'input_text',
|
|
62
|
+
text: `[Refusal: ${part.refusal}]`,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
return null;
|
|
66
|
+
})
|
|
67
|
+
.filter((part) => part !== null);
|
|
68
|
+
return { role: 'assistant', content };
|
|
69
|
+
}
|
|
70
|
+
throw new Error(`Unknown message type: ${message?.constructor?.name ?? typeof message}`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -1,13 +1,39 @@
|
|
|
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 ChatOpenRouterOptions {
|
|
5
|
+
model?: string;
|
|
6
|
+
apiKey?: string;
|
|
7
|
+
baseURL?: string;
|
|
8
|
+
timeout?: number | null;
|
|
9
|
+
temperature?: number | null;
|
|
10
|
+
topP?: number | null;
|
|
11
|
+
seed?: number | null;
|
|
12
|
+
maxRetries?: number;
|
|
13
|
+
defaultHeaders?: Record<string, string> | null;
|
|
14
|
+
defaultQuery?: Record<string, string | undefined> | null;
|
|
15
|
+
fetchImplementation?: typeof fetch;
|
|
16
|
+
fetchOptions?: RequestInit | null;
|
|
17
|
+
httpReferer?: string | null;
|
|
18
|
+
extraBody?: Record<string, unknown> | null;
|
|
19
|
+
removeMinItemsFromSchema?: boolean;
|
|
20
|
+
removeDefaultsFromSchema?: boolean;
|
|
21
|
+
}
|
|
4
22
|
export declare class ChatOpenRouter implements BaseChatModel {
|
|
5
23
|
model: string;
|
|
6
24
|
provider: string;
|
|
7
25
|
private client;
|
|
8
|
-
|
|
26
|
+
private temperature;
|
|
27
|
+
private topP;
|
|
28
|
+
private seed;
|
|
29
|
+
private httpReferer;
|
|
30
|
+
private extraBody;
|
|
31
|
+
private removeMinItemsFromSchema;
|
|
32
|
+
private removeDefaultsFromSchema;
|
|
33
|
+
constructor(options?: string | ChatOpenRouterOptions);
|
|
9
34
|
get name(): string;
|
|
10
35
|
get model_name(): string;
|
|
36
|
+
private getUsage;
|
|
11
37
|
ainvoke(messages: Message[], output_format?: undefined, options?: ChatInvokeOptions): Promise<ChatInvokeCompletion<string>>;
|
|
12
38
|
ainvoke<T>(messages: Message[], output_format: {
|
|
13
39
|
parse: (input: string) => T;
|
|
@@ -1,16 +1,39 @@
|
|
|
1
1
|
import OpenAI from 'openai';
|
|
2
|
-
import {
|
|
2
|
+
import { ModelProviderError } from '../exceptions.js';
|
|
3
|
+
import { SchemaOptimizer, zodSchemaToJsonSchema } from '../schema.js';
|
|
3
4
|
import { ChatInvokeCompletion } from '../views.js';
|
|
4
5
|
import { OpenRouterMessageSerializer } from './serializer.js';
|
|
5
6
|
export class ChatOpenRouter {
|
|
6
7
|
model;
|
|
7
8
|
provider = 'openrouter';
|
|
8
9
|
client;
|
|
9
|
-
|
|
10
|
+
temperature;
|
|
11
|
+
topP;
|
|
12
|
+
seed;
|
|
13
|
+
httpReferer;
|
|
14
|
+
extraBody;
|
|
15
|
+
removeMinItemsFromSchema;
|
|
16
|
+
removeDefaultsFromSchema;
|
|
17
|
+
constructor(options = {}) {
|
|
18
|
+
const normalizedOptions = typeof options === 'string' ? { model: options } : options;
|
|
19
|
+
const { model = 'openai/gpt-4o', apiKey = process.env.OPENROUTER_API_KEY, baseURL = 'https://openrouter.ai/api/v1', timeout = null, temperature = null, topP = null, seed = null, maxRetries = 10, defaultHeaders = null, defaultQuery = null, fetchImplementation, fetchOptions = null, httpReferer = null, extraBody = null, removeMinItemsFromSchema = false, removeDefaultsFromSchema = false, } = normalizedOptions;
|
|
10
20
|
this.model = model;
|
|
21
|
+
this.temperature = temperature;
|
|
22
|
+
this.topP = topP;
|
|
23
|
+
this.seed = seed;
|
|
24
|
+
this.httpReferer = httpReferer;
|
|
25
|
+
this.extraBody = extraBody;
|
|
26
|
+
this.removeMinItemsFromSchema = removeMinItemsFromSchema;
|
|
27
|
+
this.removeDefaultsFromSchema = removeDefaultsFromSchema;
|
|
11
28
|
this.client = new OpenAI({
|
|
12
|
-
apiKey
|
|
13
|
-
baseURL
|
|
29
|
+
apiKey,
|
|
30
|
+
baseURL,
|
|
31
|
+
timeout: timeout ?? undefined,
|
|
32
|
+
maxRetries,
|
|
33
|
+
defaultHeaders: defaultHeaders ?? undefined,
|
|
34
|
+
defaultQuery: defaultQuery ?? undefined,
|
|
35
|
+
fetch: fetchImplementation,
|
|
36
|
+
fetchOptions: (fetchOptions ?? undefined),
|
|
14
37
|
});
|
|
15
38
|
}
|
|
16
39
|
get name() {
|
|
@@ -19,56 +42,119 @@ export class ChatOpenRouter {
|
|
|
19
42
|
get model_name() {
|
|
20
43
|
return this.model;
|
|
21
44
|
}
|
|
45
|
+
getUsage(response) {
|
|
46
|
+
if (!response.usage) {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
prompt_tokens: response.usage.prompt_tokens,
|
|
51
|
+
prompt_cached_tokens: response.usage.prompt_tokens_details?.cached_tokens ?? null,
|
|
52
|
+
prompt_cache_creation_tokens: null,
|
|
53
|
+
prompt_image_tokens: null,
|
|
54
|
+
completion_tokens: response.usage.completion_tokens,
|
|
55
|
+
total_tokens: response.usage.total_tokens,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
22
58
|
async ainvoke(messages, output_format, options = {}) {
|
|
23
59
|
const serializer = new OpenRouterMessageSerializer();
|
|
24
60
|
const openRouterMessages = serializer.serialize(messages);
|
|
61
|
+
const modelParams = {};
|
|
62
|
+
if (this.temperature !== null) {
|
|
63
|
+
modelParams.temperature = this.temperature;
|
|
64
|
+
}
|
|
65
|
+
if (this.topP !== null) {
|
|
66
|
+
modelParams.top_p = this.topP;
|
|
67
|
+
}
|
|
68
|
+
if (this.seed !== null) {
|
|
69
|
+
modelParams.seed = this.seed;
|
|
70
|
+
}
|
|
71
|
+
const zodSchemaCandidate = (() => {
|
|
72
|
+
const output = output_format;
|
|
73
|
+
if (output &&
|
|
74
|
+
typeof output === 'object' &&
|
|
75
|
+
typeof output.safeParse === 'function' &&
|
|
76
|
+
typeof output.parse === 'function') {
|
|
77
|
+
return output;
|
|
78
|
+
}
|
|
79
|
+
if (output &&
|
|
80
|
+
typeof output === 'object' &&
|
|
81
|
+
output.schema &&
|
|
82
|
+
typeof output.schema.safeParse === 'function' &&
|
|
83
|
+
typeof output.schema.parse === 'function') {
|
|
84
|
+
return output.schema;
|
|
85
|
+
}
|
|
86
|
+
return null;
|
|
87
|
+
})();
|
|
25
88
|
let responseFormat = undefined;
|
|
26
|
-
if (
|
|
27
|
-
// OpenRouter supports structured outputs for some models, but it depends on the underlying provider.
|
|
28
|
-
// We'll try to use json_schema if possible, or json_object.
|
|
89
|
+
if (zodSchemaCandidate) {
|
|
29
90
|
try {
|
|
30
|
-
const
|
|
31
|
-
name: '
|
|
91
|
+
const rawJsonSchema = zodSchemaToJsonSchema(zodSchemaCandidate, {
|
|
92
|
+
name: 'agent_output',
|
|
32
93
|
target: 'jsonSchema7',
|
|
33
94
|
});
|
|
95
|
+
const optimizedJsonSchema = SchemaOptimizer.createOptimizedJsonSchema(rawJsonSchema, {
|
|
96
|
+
removeMinItems: this.removeMinItemsFromSchema,
|
|
97
|
+
removeDefaults: this.removeDefaultsFromSchema,
|
|
98
|
+
});
|
|
34
99
|
responseFormat = {
|
|
35
100
|
type: 'json_schema',
|
|
36
101
|
json_schema: {
|
|
37
|
-
name: '
|
|
38
|
-
schema:
|
|
102
|
+
name: 'agent_output',
|
|
103
|
+
schema: optimizedJsonSchema,
|
|
39
104
|
strict: true,
|
|
40
105
|
},
|
|
41
106
|
};
|
|
42
107
|
}
|
|
43
|
-
catch
|
|
44
|
-
|
|
108
|
+
catch {
|
|
109
|
+
responseFormat = undefined;
|
|
45
110
|
}
|
|
46
111
|
}
|
|
47
|
-
const
|
|
112
|
+
const request = {
|
|
48
113
|
model: this.model,
|
|
49
114
|
messages: openRouterMessages,
|
|
50
115
|
response_format: responseFormat,
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
if (
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
116
|
+
...modelParams,
|
|
117
|
+
...(this.extraBody ?? {}),
|
|
118
|
+
};
|
|
119
|
+
if (this.httpReferer) {
|
|
120
|
+
request.extra_headers = {
|
|
121
|
+
'HTTP-Referer': this.httpReferer,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
try {
|
|
125
|
+
const response = await this.client.chat.completions.create(request, options.signal ? { signal: options.signal } : undefined);
|
|
126
|
+
const content = response.choices[0].message.content || '';
|
|
127
|
+
const usage = this.getUsage(response);
|
|
128
|
+
const stopReason = response.choices[0].finish_reason ?? null;
|
|
129
|
+
let completion = content;
|
|
130
|
+
if (output_format) {
|
|
131
|
+
if (zodSchemaCandidate) {
|
|
132
|
+
const parsedJson = JSON.parse(content);
|
|
133
|
+
const output = output_format;
|
|
134
|
+
if (output &&
|
|
135
|
+
typeof output === 'object' &&
|
|
136
|
+
output.schema &&
|
|
137
|
+
typeof output.schema.parse === 'function') {
|
|
138
|
+
completion = output.schema.parse(parsedJson);
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
completion = output_format.parse(parsedJson);
|
|
142
|
+
}
|
|
58
143
|
}
|
|
59
144
|
else {
|
|
60
145
|
completion = output_format.parse(content);
|
|
61
146
|
}
|
|
62
147
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
148
|
+
return new ChatInvokeCompletion(completion, usage, null, null, stopReason);
|
|
149
|
+
}
|
|
150
|
+
catch (error) {
|
|
151
|
+
if (error?.status === 429) {
|
|
152
|
+
throw new ModelProviderError(error?.message ?? 'Rate limit exceeded', 429, this.model);
|
|
153
|
+
}
|
|
154
|
+
if (error?.status >= 500) {
|
|
155
|
+
throw new ModelProviderError(error?.message ?? 'Server error', error.status, this.model);
|
|
66
156
|
}
|
|
157
|
+
throw new ModelProviderError(error?.message ?? String(error), error?.status ?? 500, this.model);
|
|
67
158
|
}
|
|
68
|
-
return new ChatInvokeCompletion(completion, {
|
|
69
|
-
prompt_tokens: response.usage?.prompt_tokens ?? 0,
|
|
70
|
-
completion_tokens: response.usage?.completion_tokens ?? 0,
|
|
71
|
-
total_tokens: response.usage?.total_tokens ?? 0,
|
|
72
|
-
});
|
|
73
159
|
}
|
|
74
160
|
}
|
package/dist/llm/schema.d.ts
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
type JsonSchema = Record<string, unknown>;
|
|
2
|
+
interface ZodJsonSchemaOptions {
|
|
3
|
+
name?: string;
|
|
4
|
+
target?: string;
|
|
5
|
+
[key: string]: unknown;
|
|
6
|
+
}
|
|
7
|
+
export declare const zodSchemaToJsonSchema: (schema: unknown, options?: ZodJsonSchemaOptions) => JsonSchema;
|
|
2
8
|
export declare class SchemaOptimizer {
|
|
3
|
-
static createOptimizedJsonSchema(schema: JsonSchema
|
|
9
|
+
static createOptimizedJsonSchema(schema: JsonSchema, options?: {
|
|
10
|
+
removeMinItems?: boolean;
|
|
11
|
+
removeDefaults?: boolean;
|
|
12
|
+
}): JsonSchema;
|
|
13
|
+
static createGeminiOptimizedSchema(schema: JsonSchema): JsonSchema;
|
|
4
14
|
static makeStrictCompatible(schema: any): void;
|
|
5
15
|
}
|
|
6
16
|
export {};
|