browser-use 0.0.1 → 0.0.2
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/LICENSE +21 -0
- package/README.md +761 -0
- package/dist/agent/cloud-events.d.ts +264 -0
- package/dist/agent/cloud-events.js +318 -0
- package/dist/agent/gif.d.ts +15 -0
- package/dist/agent/gif.js +215 -0
- package/dist/agent/index.d.ts +8 -0
- package/dist/agent/index.js +8 -0
- package/dist/agent/message-manager/service.d.ts +30 -0
- package/dist/agent/message-manager/service.js +208 -0
- package/dist/agent/message-manager/utils.d.ts +2 -0
- package/dist/agent/message-manager/utils.js +41 -0
- package/dist/agent/message-manager/views.d.ts +26 -0
- package/dist/agent/message-manager/views.js +73 -0
- package/dist/agent/prompts.d.ts +52 -0
- package/dist/agent/prompts.js +259 -0
- package/dist/agent/service.d.ts +290 -0
- package/dist/agent/service.js +2200 -0
- package/dist/agent/views.d.ts +741 -0
- package/dist/agent/views.js +537 -0
- package/dist/browser/browser.d.ts +7 -0
- package/dist/browser/browser.js +5 -0
- package/dist/browser/context.d.ts +8 -0
- package/dist/browser/context.js +4 -0
- package/dist/browser/dvd-screensaver.d.ts +101 -0
- package/dist/browser/dvd-screensaver.js +270 -0
- package/dist/browser/extensions.d.ts +63 -0
- package/dist/browser/extensions.js +359 -0
- package/dist/browser/index.d.ts +10 -0
- package/dist/browser/index.js +9 -0
- package/dist/browser/playwright-manager.d.ts +47 -0
- package/dist/browser/playwright-manager.js +146 -0
- package/dist/browser/profile.d.ts +196 -0
- package/dist/browser/profile.js +815 -0
- package/dist/browser/session.d.ts +505 -0
- package/dist/browser/session.js +3409 -0
- package/dist/browser/types.d.ts +1184 -0
- package/dist/browser/types.js +1 -0
- package/dist/browser/utils.d.ts +1 -0
- package/dist/browser/utils.js +19 -0
- package/dist/browser/views.d.ts +78 -0
- package/dist/browser/views.js +72 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +44 -0
- package/dist/config.d.ts +108 -0
- package/dist/config.js +430 -0
- package/dist/controller/index.d.ts +3 -0
- package/dist/controller/index.js +3 -0
- package/dist/controller/registry/index.d.ts +2 -0
- package/dist/controller/registry/index.js +2 -0
- package/dist/controller/registry/service.d.ts +45 -0
- package/dist/controller/registry/service.js +184 -0
- package/dist/controller/registry/views.d.ts +55 -0
- package/dist/controller/registry/views.js +174 -0
- package/dist/controller/service.d.ts +49 -0
- package/dist/controller/service.js +1176 -0
- package/dist/controller/views.d.ts +241 -0
- package/dist/controller/views.js +88 -0
- package/dist/dom/clickable-element-processor/service.d.ts +11 -0
- package/dist/dom/clickable-element-processor/service.js +60 -0
- package/dist/dom/dom_tree/index.js +1400 -0
- package/dist/dom/history-tree-processor/service.d.ts +14 -0
- package/dist/dom/history-tree-processor/service.js +75 -0
- package/dist/dom/history-tree-processor/view.d.ts +54 -0
- package/dist/dom/history-tree-processor/view.js +56 -0
- package/dist/dom/playground/extraction.d.ts +19 -0
- package/dist/dom/playground/extraction.js +187 -0
- package/dist/dom/playground/process-dom.d.ts +1 -0
- package/dist/dom/playground/process-dom.js +5 -0
- package/dist/dom/playground/test-accessibility.d.ts +44 -0
- package/dist/dom/playground/test-accessibility.js +111 -0
- package/dist/dom/service.d.ts +19 -0
- package/dist/dom/service.js +227 -0
- package/dist/dom/utils.d.ts +1 -0
- package/dist/dom/utils.js +6 -0
- package/dist/dom/views.d.ts +61 -0
- package/dist/dom/views.js +247 -0
- package/dist/event-bus.d.ts +11 -0
- package/dist/event-bus.js +19 -0
- package/dist/exceptions.d.ts +10 -0
- package/dist/exceptions.js +22 -0
- package/dist/filesystem/file-system.d.ts +68 -0
- package/dist/filesystem/file-system.js +412 -0
- package/dist/filesystem/index.d.ts +1 -0
- package/dist/filesystem/index.js +1 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.js +33 -0
- package/dist/integrations/gmail/actions.d.ts +12 -0
- package/dist/integrations/gmail/actions.js +113 -0
- package/dist/integrations/gmail/index.d.ts +2 -0
- package/dist/integrations/gmail/index.js +2 -0
- package/dist/integrations/gmail/service.d.ts +61 -0
- package/dist/integrations/gmail/service.js +260 -0
- package/dist/llm/anthropic/chat.d.ts +28 -0
- package/dist/llm/anthropic/chat.js +126 -0
- package/dist/llm/anthropic/index.d.ts +2 -0
- package/dist/llm/anthropic/index.js +2 -0
- package/dist/llm/anthropic/serializer.d.ts +68 -0
- package/dist/llm/anthropic/serializer.js +285 -0
- package/dist/llm/aws/chat-anthropic.d.ts +61 -0
- package/dist/llm/aws/chat-anthropic.js +176 -0
- package/dist/llm/aws/chat-bedrock.d.ts +15 -0
- package/dist/llm/aws/chat-bedrock.js +80 -0
- package/dist/llm/aws/index.d.ts +3 -0
- package/dist/llm/aws/index.js +3 -0
- package/dist/llm/aws/serializer.d.ts +5 -0
- package/dist/llm/aws/serializer.js +68 -0
- package/dist/llm/azure/chat.d.ts +15 -0
- package/dist/llm/azure/chat.js +83 -0
- package/dist/llm/azure/index.d.ts +1 -0
- package/dist/llm/azure/index.js +1 -0
- package/dist/llm/base.d.ts +16 -0
- package/dist/llm/base.js +1 -0
- package/dist/llm/deepseek/chat.d.ts +15 -0
- package/dist/llm/deepseek/chat.js +51 -0
- package/dist/llm/deepseek/index.d.ts +2 -0
- package/dist/llm/deepseek/index.js +2 -0
- package/dist/llm/deepseek/serializer.d.ts +6 -0
- package/dist/llm/deepseek/serializer.js +57 -0
- package/dist/llm/exceptions.d.ts +10 -0
- package/dist/llm/exceptions.js +18 -0
- package/dist/llm/google/chat.d.ts +20 -0
- package/dist/llm/google/chat.js +144 -0
- package/dist/llm/google/index.d.ts +2 -0
- package/dist/llm/google/index.js +2 -0
- package/dist/llm/google/serializer.d.ts +6 -0
- package/dist/llm/google/serializer.js +64 -0
- package/dist/llm/groq/chat.d.ts +15 -0
- package/dist/llm/groq/chat.js +52 -0
- package/dist/llm/groq/index.d.ts +3 -0
- package/dist/llm/groq/index.js +3 -0
- package/dist/llm/groq/parser.d.ts +32 -0
- package/dist/llm/groq/parser.js +189 -0
- package/dist/llm/groq/serializer.d.ts +6 -0
- package/dist/llm/groq/serializer.js +56 -0
- package/dist/llm/messages.d.ts +77 -0
- package/dist/llm/messages.js +157 -0
- package/dist/llm/ollama/chat.d.ts +15 -0
- package/dist/llm/ollama/chat.js +77 -0
- package/dist/llm/ollama/index.d.ts +2 -0
- package/dist/llm/ollama/index.js +2 -0
- package/dist/llm/ollama/serializer.d.ts +6 -0
- package/dist/llm/ollama/serializer.js +53 -0
- package/dist/llm/openai/chat.d.ts +38 -0
- package/dist/llm/openai/chat.js +174 -0
- package/dist/llm/openai/index.d.ts +3 -0
- package/dist/llm/openai/index.js +3 -0
- package/dist/llm/openai/like.d.ts +17 -0
- package/dist/llm/openai/like.js +19 -0
- package/dist/llm/openai/serializer.d.ts +6 -0
- package/dist/llm/openai/serializer.js +57 -0
- package/dist/llm/openrouter/chat.d.ts +15 -0
- package/dist/llm/openrouter/chat.js +74 -0
- package/dist/llm/openrouter/index.d.ts +2 -0
- package/dist/llm/openrouter/index.js +2 -0
- package/dist/llm/openrouter/serializer.d.ts +3 -0
- package/dist/llm/openrouter/serializer.js +3 -0
- package/dist/llm/schema.d.ts +6 -0
- package/dist/llm/schema.js +77 -0
- package/dist/llm/views.d.ts +15 -0
- package/dist/llm/views.js +12 -0
- package/dist/logging-config.d.ts +25 -0
- package/dist/logging-config.js +89 -0
- package/dist/mcp/client.d.ts +142 -0
- package/dist/mcp/client.js +638 -0
- package/dist/mcp/controller.d.ts +6 -0
- package/dist/mcp/controller.js +38 -0
- package/dist/mcp/index.d.ts +3 -0
- package/dist/mcp/index.js +3 -0
- package/dist/mcp/server.d.ts +134 -0
- package/dist/mcp/server.js +759 -0
- package/dist/observability-decorators.d.ts +158 -0
- package/dist/observability-decorators.js +286 -0
- package/dist/observability.d.ts +23 -0
- package/dist/observability.js +58 -0
- package/dist/screenshots/index.d.ts +1 -0
- package/dist/screenshots/index.js +1 -0
- package/dist/screenshots/service.d.ts +6 -0
- package/dist/screenshots/service.js +28 -0
- package/dist/sync/auth.d.ts +27 -0
- package/dist/sync/auth.js +205 -0
- package/dist/sync/index.d.ts +2 -0
- package/dist/sync/index.js +2 -0
- package/dist/sync/service.d.ts +21 -0
- package/dist/sync/service.js +146 -0
- package/dist/telemetry/index.d.ts +2 -0
- package/dist/telemetry/index.js +2 -0
- package/dist/telemetry/service.d.ts +12 -0
- package/dist/telemetry/service.js +85 -0
- package/dist/telemetry/views.d.ts +112 -0
- package/dist/telemetry/views.js +112 -0
- package/dist/tokens/index.d.ts +2 -0
- package/dist/tokens/index.js +2 -0
- package/dist/tokens/service.d.ts +35 -0
- package/dist/tokens/service.js +423 -0
- package/dist/tokens/views.d.ts +58 -0
- package/dist/tokens/views.js +1 -0
- package/dist/utils.d.ts +128 -0
- package/dist/utils.js +529 -0
- package/package.json +94 -5
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anthropic Message Serializer with Prompt Caching Support
|
|
3
|
+
*
|
|
4
|
+
* This serializer converts custom message types to Anthropic's MessageParam format
|
|
5
|
+
* and implements Anthropic's Prompt Caching feature to reduce costs by up to 90%.
|
|
6
|
+
*
|
|
7
|
+
* Caching Strategy:
|
|
8
|
+
* - Only the last message with cache=true will have cache_control enabled
|
|
9
|
+
* - Caching is most effective for system prompts and large conversation histories
|
|
10
|
+
* - Cache writes cost 25% more, but cache reads cost 90% less
|
|
11
|
+
*
|
|
12
|
+
* Example cost savings:
|
|
13
|
+
* - Without caching: 10,000 tokens @ $3/M = $0.030 per request
|
|
14
|
+
* - With caching (90% hit rate):
|
|
15
|
+
* - First request: 10,000 tokens @ $3.75/M (write) = $0.0375
|
|
16
|
+
* - Subsequent: 1,000 tokens @ $3/M + 9,000 tokens @ $0.30/M = $0.0057
|
|
17
|
+
* - Savings: 81% cost reduction
|
|
18
|
+
*/
|
|
19
|
+
import { AssistantMessage, ContentPartImageParam, ContentPartTextParam, UserMessage, SystemMessage, } from '../messages.js';
|
|
20
|
+
export class AnthropicMessageSerializer {
|
|
21
|
+
/**
|
|
22
|
+
* Serialize a list of messages, extracting any system message
|
|
23
|
+
*
|
|
24
|
+
* @param messages - List of messages to serialize
|
|
25
|
+
* @returns Tuple of [messages, system_message]
|
|
26
|
+
*/
|
|
27
|
+
serializeMessages(messages) {
|
|
28
|
+
// Make deep copies to avoid modifying originals
|
|
29
|
+
const messagesCopy = messages.map((m) => ({ ...m }));
|
|
30
|
+
// Separate system messages from normal messages
|
|
31
|
+
const normalMessages = [];
|
|
32
|
+
let systemMessage = null;
|
|
33
|
+
for (const message of messagesCopy) {
|
|
34
|
+
if (message instanceof SystemMessage) {
|
|
35
|
+
systemMessage = message;
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
normalMessages.push(message);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// Clean cache messages so only the last cache=true message remains cached
|
|
42
|
+
const cleanedMessages = this._cleanCacheMessages(normalMessages);
|
|
43
|
+
// Serialize normal messages
|
|
44
|
+
const serializedMessages = cleanedMessages.map((msg) => this.serializeMessage(msg));
|
|
45
|
+
// Serialize system message
|
|
46
|
+
let serializedSystemMessage = undefined;
|
|
47
|
+
if (systemMessage) {
|
|
48
|
+
serializedSystemMessage = this._serializeContentToStr(systemMessage.content, systemMessage.cache);
|
|
49
|
+
}
|
|
50
|
+
return [serializedMessages, serializedSystemMessage];
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Serialize a single message
|
|
54
|
+
*/
|
|
55
|
+
serializeMessage(message) {
|
|
56
|
+
if (message instanceof UserMessage) {
|
|
57
|
+
return {
|
|
58
|
+
role: 'user',
|
|
59
|
+
content: Array.isArray(message.content)
|
|
60
|
+
? message.content.map((part, idx, arr) => {
|
|
61
|
+
const isLastPart = idx === arr.length - 1;
|
|
62
|
+
const useCache = message.cache && isLastPart;
|
|
63
|
+
if (part instanceof ContentPartTextParam) {
|
|
64
|
+
return this._serializeContentPartText(part, useCache);
|
|
65
|
+
}
|
|
66
|
+
if (part instanceof ContentPartImageParam) {
|
|
67
|
+
return this._serializeContentPartImage(part);
|
|
68
|
+
}
|
|
69
|
+
return { type: 'text', text: '' };
|
|
70
|
+
})
|
|
71
|
+
: this._serializeContent(message.content, message.cache),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
if (message instanceof AssistantMessage) {
|
|
75
|
+
const content = [];
|
|
76
|
+
// Add content blocks if present
|
|
77
|
+
if (message.content) {
|
|
78
|
+
if (typeof message.content === 'string') {
|
|
79
|
+
content.push({
|
|
80
|
+
type: 'text',
|
|
81
|
+
text: message.content,
|
|
82
|
+
...(message.cache
|
|
83
|
+
? { cache_control: this._serializeCacheControl(true) }
|
|
84
|
+
: {}),
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
else if (Array.isArray(message.content)) {
|
|
88
|
+
message.content.forEach((part, idx, arr) => {
|
|
89
|
+
const isLastPart = idx === arr.length - 1;
|
|
90
|
+
const useCache = message.cache && isLastPart && !message.tool_calls?.length;
|
|
91
|
+
if (part instanceof ContentPartTextParam) {
|
|
92
|
+
content.push(this._serializeContentPartText(part, useCache));
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// Add tool use blocks if present
|
|
98
|
+
if (message.tool_calls) {
|
|
99
|
+
message.tool_calls.forEach((toolCall, idx, arr) => {
|
|
100
|
+
const isLastToolCall = idx === arr.length - 1;
|
|
101
|
+
const useCache = message.cache && isLastToolCall;
|
|
102
|
+
content.push({
|
|
103
|
+
type: 'tool_use',
|
|
104
|
+
id: toolCall.id,
|
|
105
|
+
name: toolCall.functionCall.name,
|
|
106
|
+
input: JSON.parse(toolCall.functionCall.arguments),
|
|
107
|
+
...(useCache
|
|
108
|
+
? { cache_control: this._serializeCacheControl(true) }
|
|
109
|
+
: {}),
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
// If no content or tool calls, add empty text block
|
|
114
|
+
if (!content.length) {
|
|
115
|
+
content.push({
|
|
116
|
+
type: 'text',
|
|
117
|
+
text: '',
|
|
118
|
+
...(message.cache
|
|
119
|
+
? { cache_control: this._serializeCacheControl(true) }
|
|
120
|
+
: {}),
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
role: 'assistant',
|
|
125
|
+
content: content,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
throw new Error(`Unknown message type or unhandled role: ${message.role}`);
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Serialize cache control parameter
|
|
132
|
+
*/
|
|
133
|
+
_serializeCacheControl(useCache) {
|
|
134
|
+
return useCache ? { type: 'ephemeral' } : undefined;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Serialize text content part with optional caching
|
|
138
|
+
*/
|
|
139
|
+
_serializeContentPartText(part, useCache) {
|
|
140
|
+
return {
|
|
141
|
+
type: 'text',
|
|
142
|
+
text: part.text,
|
|
143
|
+
...(useCache ? { cache_control: this._serializeCacheControl(true) } : {}),
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Serialize image content part
|
|
148
|
+
*/
|
|
149
|
+
_serializeContentPartImage(part) {
|
|
150
|
+
const url = part.image_url.url;
|
|
151
|
+
if (this._isBase64Image(url)) {
|
|
152
|
+
// Handle base64 encoded images
|
|
153
|
+
const [mediaType, data] = this._parseBase64Url(url);
|
|
154
|
+
return {
|
|
155
|
+
type: 'image',
|
|
156
|
+
source: {
|
|
157
|
+
type: 'base64',
|
|
158
|
+
media_type: mediaType,
|
|
159
|
+
data: data,
|
|
160
|
+
},
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
// Handle URL images
|
|
165
|
+
return {
|
|
166
|
+
type: 'image',
|
|
167
|
+
source: {
|
|
168
|
+
type: 'url',
|
|
169
|
+
url: url,
|
|
170
|
+
},
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Serialize content (string or array) with optional caching
|
|
176
|
+
*/
|
|
177
|
+
_serializeContent(content, useCache) {
|
|
178
|
+
if (typeof content === 'string') {
|
|
179
|
+
if (useCache) {
|
|
180
|
+
return [
|
|
181
|
+
{
|
|
182
|
+
type: 'text',
|
|
183
|
+
text: content,
|
|
184
|
+
cache_control: this._serializeCacheControl(true),
|
|
185
|
+
},
|
|
186
|
+
];
|
|
187
|
+
}
|
|
188
|
+
return content;
|
|
189
|
+
}
|
|
190
|
+
return content.map((part, idx, arr) => {
|
|
191
|
+
const isLastPart = idx === arr.length - 1;
|
|
192
|
+
const partUseCache = useCache && isLastPart;
|
|
193
|
+
if (part instanceof ContentPartTextParam) {
|
|
194
|
+
return this._serializeContentPartText(part, partUseCache);
|
|
195
|
+
}
|
|
196
|
+
else if (part instanceof ContentPartImageParam) {
|
|
197
|
+
return this._serializeContentPartImage(part);
|
|
198
|
+
}
|
|
199
|
+
return { type: 'text', text: '' };
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Serialize content to string format (for system messages)
|
|
204
|
+
*/
|
|
205
|
+
_serializeContentToStr(content, useCache) {
|
|
206
|
+
if (typeof content === 'string') {
|
|
207
|
+
if (useCache) {
|
|
208
|
+
return [
|
|
209
|
+
{
|
|
210
|
+
type: 'text',
|
|
211
|
+
text: content,
|
|
212
|
+
cache_control: this._serializeCacheControl(true),
|
|
213
|
+
},
|
|
214
|
+
];
|
|
215
|
+
}
|
|
216
|
+
return content;
|
|
217
|
+
}
|
|
218
|
+
return content.map((part, idx, arr) => {
|
|
219
|
+
const isLastPart = idx === arr.length - 1;
|
|
220
|
+
const partUseCache = useCache && isLastPart;
|
|
221
|
+
return this._serializeContentPartText(part, partUseCache);
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Check if URL is a base64 encoded image
|
|
226
|
+
*/
|
|
227
|
+
_isBase64Image(url) {
|
|
228
|
+
return url.startsWith('data:image/');
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Parse base64 data URL to extract media type and data
|
|
232
|
+
*/
|
|
233
|
+
_parseBase64Url(url) {
|
|
234
|
+
if (!url.startsWith('data:')) {
|
|
235
|
+
throw new Error(`Invalid base64 URL: ${url}`);
|
|
236
|
+
}
|
|
237
|
+
const [header, data] = url.split(',', 2);
|
|
238
|
+
if (!header || !data) {
|
|
239
|
+
throw new Error(`Invalid base64 URL format: ${url}`);
|
|
240
|
+
}
|
|
241
|
+
let mediaType = header.split(';')[0]?.replace('data:', '') || 'image/png';
|
|
242
|
+
// Ensure it's a supported media type
|
|
243
|
+
const supportedTypes = [
|
|
244
|
+
'image/jpeg',
|
|
245
|
+
'image/png',
|
|
246
|
+
'image/gif',
|
|
247
|
+
'image/webp',
|
|
248
|
+
];
|
|
249
|
+
if (!supportedTypes.includes(mediaType)) {
|
|
250
|
+
// Default to png if not recognized
|
|
251
|
+
mediaType = 'image/png';
|
|
252
|
+
}
|
|
253
|
+
return [mediaType, data];
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Clean cache settings so only the last cache=true message remains cached
|
|
257
|
+
*
|
|
258
|
+
* Because of how Claude caching works, only the last cache message matters.
|
|
259
|
+
* This method automatically removes cache=True from all messages except the last one.
|
|
260
|
+
*/
|
|
261
|
+
_cleanCacheMessages(messages) {
|
|
262
|
+
if (!messages.length) {
|
|
263
|
+
return messages;
|
|
264
|
+
}
|
|
265
|
+
// Create deep copies to avoid modifying originals
|
|
266
|
+
const cleanedMessages = messages.map((msg) => ({ ...msg }));
|
|
267
|
+
// Find the last message with cache=true
|
|
268
|
+
let lastCacheIndex = -1;
|
|
269
|
+
for (let i = cleanedMessages.length - 1; i >= 0; i--) {
|
|
270
|
+
if (cleanedMessages[i].cache) {
|
|
271
|
+
lastCacheIndex = i;
|
|
272
|
+
break;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
// If we found a cached message, disable cache for all others
|
|
276
|
+
if (lastCacheIndex !== -1) {
|
|
277
|
+
for (let i = 0; i < cleanedMessages.length; i++) {
|
|
278
|
+
if (i !== lastCacheIndex && cleanedMessages[i].cache) {
|
|
279
|
+
cleanedMessages[i].cache = false;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return cleanedMessages;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AWS Bedrock Anthropic Claude chat model.
|
|
3
|
+
*
|
|
4
|
+
* This is a convenience class that provides Claude-specific defaults
|
|
5
|
+
* for the AWS Bedrock service. It inherits all functionality from
|
|
6
|
+
* ChatBedrockConverse but sets Anthropic Claude as the default model
|
|
7
|
+
* and uses the Anthropic message serializer for better compatibility.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* ```typescript
|
|
11
|
+
* import { ChatAnthropicBedrock } from './llm/aws/chat-anthropic.js';
|
|
12
|
+
*
|
|
13
|
+
* const llm = new ChatAnthropicBedrock({
|
|
14
|
+
* model: 'anthropic.claude-3-5-sonnet-20241022-v2:0',
|
|
15
|
+
* region: 'us-east-1'
|
|
16
|
+
* });
|
|
17
|
+
*
|
|
18
|
+
* const response = await llm.ainvoke(messages);
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
import type { BaseChatModel, ChatInvokeOptions } from '../base.js';
|
|
22
|
+
import { ChatInvokeCompletion } from '../views.js';
|
|
23
|
+
import { type Message } from '../messages.js';
|
|
24
|
+
export interface ChatAnthropicBedrockConfig {
|
|
25
|
+
/** Model ID, defaults to Claude 3.5 Sonnet */
|
|
26
|
+
model?: string;
|
|
27
|
+
/** AWS region, defaults to us-east-1 */
|
|
28
|
+
region?: string;
|
|
29
|
+
/** Maximum tokens to generate */
|
|
30
|
+
max_tokens?: number;
|
|
31
|
+
/** Temperature for sampling (0-1) */
|
|
32
|
+
temperature?: number | null;
|
|
33
|
+
/** Top-p sampling parameter */
|
|
34
|
+
top_p?: number | null;
|
|
35
|
+
/** Top-k sampling parameter */
|
|
36
|
+
top_k?: number | null;
|
|
37
|
+
/** Stop sequences */
|
|
38
|
+
stop_sequences?: string[] | null;
|
|
39
|
+
}
|
|
40
|
+
export declare class ChatAnthropicBedrock implements BaseChatModel {
|
|
41
|
+
model: string;
|
|
42
|
+
provider: string;
|
|
43
|
+
private client;
|
|
44
|
+
private max_tokens;
|
|
45
|
+
private temperature;
|
|
46
|
+
private top_p;
|
|
47
|
+
private top_k;
|
|
48
|
+
private stop_sequences;
|
|
49
|
+
constructor(config?: ChatAnthropicBedrockConfig);
|
|
50
|
+
get name(): string;
|
|
51
|
+
get model_name(): string;
|
|
52
|
+
private _getInferenceParams;
|
|
53
|
+
ainvoke(messages: Message[], output_format?: undefined, options?: ChatInvokeOptions): Promise<ChatInvokeCompletion<string>>;
|
|
54
|
+
ainvoke<T>(messages: Message[], output_format: {
|
|
55
|
+
parse: (input: string) => T;
|
|
56
|
+
}, options?: ChatInvokeOptions): Promise<ChatInvokeCompletion<T>>;
|
|
57
|
+
/**
|
|
58
|
+
* Simple Zod to JSON Schema conversion for structured output
|
|
59
|
+
*/
|
|
60
|
+
private _zodToJsonSchema;
|
|
61
|
+
}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AWS Bedrock Anthropic Claude chat model.
|
|
3
|
+
*
|
|
4
|
+
* This is a convenience class that provides Claude-specific defaults
|
|
5
|
+
* for the AWS Bedrock service. It inherits all functionality from
|
|
6
|
+
* ChatBedrockConverse but sets Anthropic Claude as the default model
|
|
7
|
+
* and uses the Anthropic message serializer for better compatibility.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* ```typescript
|
|
11
|
+
* import { ChatAnthropicBedrock } from './llm/aws/chat-anthropic.js';
|
|
12
|
+
*
|
|
13
|
+
* const llm = new ChatAnthropicBedrock({
|
|
14
|
+
* model: 'anthropic.claude-3-5-sonnet-20241022-v2:0',
|
|
15
|
+
* region: 'us-east-1'
|
|
16
|
+
* });
|
|
17
|
+
*
|
|
18
|
+
* const response = await llm.ainvoke(messages);
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
import { BedrockRuntimeClient, ConverseCommand, } from '@aws-sdk/client-bedrock-runtime';
|
|
22
|
+
import { ChatInvokeCompletion } from '../views.js';
|
|
23
|
+
import { AnthropicMessageSerializer } from '../anthropic/serializer.js';
|
|
24
|
+
export class ChatAnthropicBedrock {
|
|
25
|
+
model;
|
|
26
|
+
provider = 'anthropic_bedrock';
|
|
27
|
+
client;
|
|
28
|
+
max_tokens;
|
|
29
|
+
temperature;
|
|
30
|
+
top_p;
|
|
31
|
+
top_k;
|
|
32
|
+
stop_sequences;
|
|
33
|
+
constructor(config = {}) {
|
|
34
|
+
// Anthropic Claude specific defaults
|
|
35
|
+
this.model = config.model || 'anthropic.claude-3-5-sonnet-20241022-v2:0';
|
|
36
|
+
this.max_tokens = config.max_tokens || 8192;
|
|
37
|
+
this.temperature =
|
|
38
|
+
config.temperature === undefined ? null : config.temperature;
|
|
39
|
+
this.top_p = config.top_p === undefined ? null : config.top_p;
|
|
40
|
+
this.top_k = config.top_k === undefined ? null : config.top_k;
|
|
41
|
+
this.stop_sequences =
|
|
42
|
+
config.stop_sequences === undefined ? null : config.stop_sequences;
|
|
43
|
+
const region = config.region || process.env.AWS_REGION || 'us-east-1';
|
|
44
|
+
this.client = new BedrockRuntimeClient({ region });
|
|
45
|
+
}
|
|
46
|
+
get name() {
|
|
47
|
+
return this.model;
|
|
48
|
+
}
|
|
49
|
+
get model_name() {
|
|
50
|
+
return this.model;
|
|
51
|
+
}
|
|
52
|
+
_getInferenceParams() {
|
|
53
|
+
const params = {
|
|
54
|
+
maxTokens: this.max_tokens,
|
|
55
|
+
};
|
|
56
|
+
if (this.temperature !== null) {
|
|
57
|
+
params.temperature = this.temperature;
|
|
58
|
+
}
|
|
59
|
+
if (this.top_p !== null) {
|
|
60
|
+
params.topP = this.top_p;
|
|
61
|
+
}
|
|
62
|
+
if (this.stop_sequences !== null && this.stop_sequences.length > 0) {
|
|
63
|
+
params.stopSequences = this.stop_sequences;
|
|
64
|
+
}
|
|
65
|
+
return params;
|
|
66
|
+
}
|
|
67
|
+
async ainvoke(messages, output_format, options = {}) {
|
|
68
|
+
// Use Anthropic-specific message serializer
|
|
69
|
+
const serializer = new AnthropicMessageSerializer();
|
|
70
|
+
const [anthropicMessages, systemPrompt] = serializer.serializeMessages(messages);
|
|
71
|
+
// Convert Anthropic messages to Bedrock format
|
|
72
|
+
const bedrockMessages = anthropicMessages.map((msg) => {
|
|
73
|
+
const content = Array.isArray(msg.content)
|
|
74
|
+
? msg.content.map((block) => {
|
|
75
|
+
if (block.type === 'text') {
|
|
76
|
+
return { text: block.text };
|
|
77
|
+
}
|
|
78
|
+
else if (block.type === 'image') {
|
|
79
|
+
// Handle image blocks if needed
|
|
80
|
+
return { text: '[Image]' };
|
|
81
|
+
}
|
|
82
|
+
return { text: String(block) };
|
|
83
|
+
})
|
|
84
|
+
: [{ text: msg.content }];
|
|
85
|
+
return {
|
|
86
|
+
role: msg.role,
|
|
87
|
+
content,
|
|
88
|
+
};
|
|
89
|
+
});
|
|
90
|
+
// Handle system message
|
|
91
|
+
const system = systemPrompt
|
|
92
|
+
? [
|
|
93
|
+
{
|
|
94
|
+
text: typeof systemPrompt === 'string'
|
|
95
|
+
? systemPrompt
|
|
96
|
+
: JSON.stringify(systemPrompt),
|
|
97
|
+
},
|
|
98
|
+
]
|
|
99
|
+
: undefined;
|
|
100
|
+
let tools = undefined;
|
|
101
|
+
let toolConfig = undefined;
|
|
102
|
+
if (output_format && 'schema' in output_format) {
|
|
103
|
+
// Structured output using tools
|
|
104
|
+
try {
|
|
105
|
+
const schema = output_format.schema?.shape
|
|
106
|
+
? this._zodToJsonSchema(output_format.schema)
|
|
107
|
+
: {};
|
|
108
|
+
tools = [
|
|
109
|
+
{
|
|
110
|
+
toolSpec: {
|
|
111
|
+
name: 'extract_structured_data',
|
|
112
|
+
description: 'Extract structured data from the response',
|
|
113
|
+
inputSchema: {
|
|
114
|
+
json: schema,
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
];
|
|
119
|
+
toolConfig = {
|
|
120
|
+
tools: tools,
|
|
121
|
+
toolChoice: { tool: { name: 'extract_structured_data' } },
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
catch (e) {
|
|
125
|
+
console.warn('Failed to convert output_format to JSON schema', e);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
const command = new ConverseCommand({
|
|
129
|
+
modelId: this.model,
|
|
130
|
+
messages: bedrockMessages,
|
|
131
|
+
system: system,
|
|
132
|
+
toolConfig: toolConfig,
|
|
133
|
+
inferenceConfig: this._getInferenceParams(),
|
|
134
|
+
});
|
|
135
|
+
const response = await this.client.send(command, options.signal ? { abortSignal: options.signal } : undefined);
|
|
136
|
+
let completion = '';
|
|
137
|
+
if (response.output?.message?.content) {
|
|
138
|
+
// Check for tool use (structured output)
|
|
139
|
+
const toolUseBlock = response.output.message.content.find((block) => block.toolUse);
|
|
140
|
+
if (toolUseBlock && toolUseBlock.toolUse && output_format) {
|
|
141
|
+
completion = output_format.parse(toolUseBlock.toolUse.input);
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
// Fallback to text
|
|
145
|
+
const textBlock = response.output.message.content.find((block) => block.text);
|
|
146
|
+
completion = textBlock?.text || '';
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return new ChatInvokeCompletion(completion, {
|
|
150
|
+
prompt_tokens: response.usage?.inputTokens ?? 0,
|
|
151
|
+
completion_tokens: response.usage?.outputTokens ?? 0,
|
|
152
|
+
total_tokens: response.usage?.totalTokens ?? 0,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Simple Zod to JSON Schema conversion for structured output
|
|
157
|
+
*/
|
|
158
|
+
_zodToJsonSchema(schema) {
|
|
159
|
+
// This is a simplified version - you might want to use zod-to-json-schema package
|
|
160
|
+
try {
|
|
161
|
+
const { zodToJsonSchema } = require('zod-to-json-schema');
|
|
162
|
+
return zodToJsonSchema(schema, {
|
|
163
|
+
name: 'Response',
|
|
164
|
+
target: 'jsonSchema7',
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
// Fallback if zod-to-json-schema is not available
|
|
169
|
+
return {
|
|
170
|
+
type: 'object',
|
|
171
|
+
properties: {},
|
|
172
|
+
required: [],
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { BaseChatModel, ChatInvokeOptions } from '../base.js';
|
|
2
|
+
import { ChatInvokeCompletion } from '../views.js';
|
|
3
|
+
import { type Message } from '../messages.js';
|
|
4
|
+
export declare class ChatBedrockConverse implements BaseChatModel {
|
|
5
|
+
model: string;
|
|
6
|
+
provider: string;
|
|
7
|
+
private client;
|
|
8
|
+
constructor(model?: string, region?: string);
|
|
9
|
+
get name(): string;
|
|
10
|
+
get model_name(): string;
|
|
11
|
+
ainvoke(messages: Message[], output_format?: undefined, options?: ChatInvokeOptions): Promise<ChatInvokeCompletion<string>>;
|
|
12
|
+
ainvoke<T>(messages: Message[], output_format: {
|
|
13
|
+
parse: (input: string) => T;
|
|
14
|
+
} | undefined, options?: ChatInvokeOptions): Promise<ChatInvokeCompletion<T>>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { BedrockRuntimeClient, ConverseCommand, } from '@aws-sdk/client-bedrock-runtime';
|
|
2
|
+
import { zodToJsonSchema } from 'zod-to-json-schema';
|
|
3
|
+
import { ChatInvokeCompletion } from '../views.js';
|
|
4
|
+
import { SystemMessage } from '../messages.js';
|
|
5
|
+
import { AWSBedrockMessageSerializer } from './serializer.js';
|
|
6
|
+
export class ChatBedrockConverse {
|
|
7
|
+
model;
|
|
8
|
+
provider = 'aws';
|
|
9
|
+
client;
|
|
10
|
+
constructor(model = 'anthropic.claude-3-5-sonnet-20240620-v1:0', region = process.env.AWS_REGION || 'us-east-1') {
|
|
11
|
+
this.model = model;
|
|
12
|
+
this.client = new BedrockRuntimeClient({ region });
|
|
13
|
+
}
|
|
14
|
+
get name() {
|
|
15
|
+
return this.model;
|
|
16
|
+
}
|
|
17
|
+
get model_name() {
|
|
18
|
+
return this.model;
|
|
19
|
+
}
|
|
20
|
+
async ainvoke(messages, output_format, options = {}) {
|
|
21
|
+
const serializer = new AWSBedrockMessageSerializer();
|
|
22
|
+
const bedrockMessages = serializer.serialize(messages);
|
|
23
|
+
const systemMessage = messages.find((msg) => msg instanceof SystemMessage);
|
|
24
|
+
const system = systemMessage ? [{ text: systemMessage.text }] : undefined;
|
|
25
|
+
let tools = undefined;
|
|
26
|
+
let toolConfig = undefined;
|
|
27
|
+
if (output_format && 'schema' in output_format && output_format.schema) {
|
|
28
|
+
try {
|
|
29
|
+
const jsonSchema = zodToJsonSchema(output_format, {
|
|
30
|
+
name: 'Response',
|
|
31
|
+
target: 'jsonSchema7',
|
|
32
|
+
});
|
|
33
|
+
tools = [
|
|
34
|
+
{
|
|
35
|
+
toolSpec: {
|
|
36
|
+
name: 'response',
|
|
37
|
+
description: 'The response to the user request',
|
|
38
|
+
inputSchema: {
|
|
39
|
+
json: jsonSchema,
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
];
|
|
44
|
+
toolConfig = {
|
|
45
|
+
tools: tools,
|
|
46
|
+
toolChoice: { tool: { name: 'response' } },
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
catch (e) {
|
|
50
|
+
console.warn('Failed to convert output_format to JSON schema for AWS Bedrock', e);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
const command = new ConverseCommand({
|
|
54
|
+
modelId: this.model,
|
|
55
|
+
messages: bedrockMessages,
|
|
56
|
+
system: system,
|
|
57
|
+
toolConfig: toolConfig,
|
|
58
|
+
});
|
|
59
|
+
const response = await this.client.send(command, options.signal ? { abortSignal: options.signal } : undefined);
|
|
60
|
+
let completion = '';
|
|
61
|
+
if (response.output?.message?.content) {
|
|
62
|
+
// Check for tool use
|
|
63
|
+
const toolUseBlock = response.output.message.content.find((block) => block.toolUse);
|
|
64
|
+
if (toolUseBlock && toolUseBlock.toolUse && output_format) {
|
|
65
|
+
completion = output_format.parse(toolUseBlock.toolUse.input);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
// Fallback to text
|
|
69
|
+
const textBlock = response.output.message.content.find((block) => block.text);
|
|
70
|
+
completion = textBlock?.text || '';
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
const usage = response.usage || {};
|
|
74
|
+
return new ChatInvokeCompletion(completion, {
|
|
75
|
+
prompt_tokens: usage.inputTokens || 0,
|
|
76
|
+
completion_tokens: usage.outputTokens || 0,
|
|
77
|
+
total_tokens: usage.totalTokens || 0,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|