@elizaos/plugin-browser 1.0.3 → 2.0.0-alpha.1

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 (87) hide show
  1. package/README.md +75 -23
  2. package/dist/actions/click.d.ts +3 -0
  3. package/dist/actions/click.d.ts.map +1 -0
  4. package/dist/actions/click.js +98 -0
  5. package/dist/actions/click.js.map +1 -0
  6. package/dist/actions/extract.d.ts +3 -0
  7. package/dist/actions/extract.d.ts.map +1 -0
  8. package/dist/actions/extract.js +110 -0
  9. package/dist/actions/extract.js.map +1 -0
  10. package/dist/actions/index.d.ts +7 -0
  11. package/dist/actions/index.d.ts.map +1 -0
  12. package/dist/actions/index.js +7 -0
  13. package/dist/actions/index.js.map +1 -0
  14. package/dist/actions/navigate.d.ts +3 -0
  15. package/dist/actions/navigate.d.ts.map +1 -0
  16. package/dist/actions/navigate.js +129 -0
  17. package/dist/actions/navigate.js.map +1 -0
  18. package/dist/actions/screenshot.d.ts +3 -0
  19. package/dist/actions/screenshot.d.ts.map +1 -0
  20. package/dist/actions/screenshot.js +107 -0
  21. package/dist/actions/screenshot.js.map +1 -0
  22. package/dist/actions/select.d.ts +3 -0
  23. package/dist/actions/select.d.ts.map +1 -0
  24. package/dist/actions/select.js +105 -0
  25. package/dist/actions/select.js.map +1 -0
  26. package/dist/actions/type.d.ts +3 -0
  27. package/dist/actions/type.d.ts.map +1 -0
  28. package/dist/actions/type.js +105 -0
  29. package/dist/actions/type.js.map +1 -0
  30. package/dist/index.d.ts +17 -5
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +119 -348
  33. package/dist/index.js.map +1 -1
  34. package/dist/providers/browser-state.d.ts +3 -0
  35. package/dist/providers/browser-state.d.ts.map +1 -0
  36. package/dist/providers/browser-state.js +47 -0
  37. package/dist/providers/browser-state.js.map +1 -0
  38. package/dist/providers/index.d.ts +2 -0
  39. package/dist/providers/index.d.ts.map +1 -0
  40. package/dist/providers/index.js +2 -0
  41. package/dist/providers/index.js.map +1 -0
  42. package/dist/services/browser-service.d.ts +30 -0
  43. package/dist/services/browser-service.d.ts.map +1 -0
  44. package/dist/services/browser-service.js +164 -0
  45. package/dist/services/browser-service.js.map +1 -0
  46. package/dist/services/index.d.ts +4 -0
  47. package/dist/services/index.d.ts.map +1 -0
  48. package/dist/services/index.js +4 -0
  49. package/dist/services/index.js.map +1 -0
  50. package/dist/services/process-manager.d.ts +15 -0
  51. package/dist/services/process-manager.d.ts.map +1 -0
  52. package/dist/services/process-manager.js +186 -0
  53. package/dist/services/process-manager.js.map +1 -0
  54. package/dist/services/websocket-client.d.ts +35 -0
  55. package/dist/services/websocket-client.d.ts.map +1 -0
  56. package/dist/services/websocket-client.js +219 -0
  57. package/dist/services/websocket-client.js.map +1 -0
  58. package/dist/types.d.ts +101 -0
  59. package/dist/types.d.ts.map +1 -0
  60. package/dist/types.js +2 -0
  61. package/dist/types.js.map +1 -0
  62. package/dist/utils/captcha.d.ts +33 -0
  63. package/dist/utils/captcha.d.ts.map +1 -0
  64. package/dist/utils/captcha.js +219 -0
  65. package/dist/utils/captcha.js.map +1 -0
  66. package/dist/utils/errors.d.ts +37 -0
  67. package/dist/utils/errors.d.ts.map +1 -0
  68. package/dist/utils/errors.js +81 -0
  69. package/dist/utils/errors.js.map +1 -0
  70. package/dist/utils/index.d.ts +5 -0
  71. package/dist/utils/index.d.ts.map +1 -0
  72. package/dist/utils/index.js +5 -0
  73. package/dist/utils/index.js.map +1 -0
  74. package/dist/utils/retry.d.ts +26 -0
  75. package/dist/utils/retry.d.ts.map +1 -0
  76. package/dist/utils/retry.js +55 -0
  77. package/dist/utils/retry.js.map +1 -0
  78. package/dist/utils/security.d.ts +27 -0
  79. package/dist/utils/security.d.ts.map +1 -0
  80. package/dist/utils/security.js +138 -0
  81. package/dist/utils/security.js.map +1 -0
  82. package/dist/utils/url.d.ts +12 -0
  83. package/dist/utils/url.d.ts.map +1 -0
  84. package/dist/utils/url.js +38 -0
  85. package/dist/utils/url.js.map +1 -0
  86. package/package.json +60 -42
  87. package/LICENSE +0 -21
package/dist/index.js CHANGED
@@ -1,353 +1,124 @@
1
- // src/services/browser.ts
2
- import {
3
- ModelType,
4
- Service,
5
- ServiceType,
6
- logger,
7
- parseJSONObjectFromText,
8
- stringToUuid,
9
- trimTokens
10
- } from "@elizaos/core";
11
- import CaptchaSolver from "capsolver-npm";
12
- import { chromium } from "patchright";
13
- async function generateSummary(runtime, text) {
14
- const trimmedText = await trimTokens(text, 1e5, runtime);
15
- const prompt = `Please generate a concise summary for the following text:
16
-
17
- Text: """
18
- ${trimmedText}
19
- """
20
-
21
- Respond with a JSON object in the following format:
22
- \`\`\`json
23
- {
24
- "title": "Generated Title",
25
- "summary": "Generated summary and/or description of the text"
26
- }
27
- \`\`\``;
28
- const response = await runtime.useModel(ModelType.TEXT_SMALL, {
29
- prompt
30
- });
31
- const parsedResponse = parseJSONObjectFromText(response);
32
- if (parsedResponse?.title && parsedResponse?.summary) {
33
- return {
34
- title: parsedResponse.title,
35
- description: parsedResponse.summary
36
- };
37
- }
38
- return {
39
- title: "",
40
- description: ""
41
- };
42
- }
43
- var BrowserService = class _BrowserService extends Service {
44
- browser;
45
- context;
46
- captchaSolver;
47
- cacheKey = "content/browser";
48
- static serviceType = ServiceType.BROWSER;
49
- capabilityDescription = "The agent is able to browse the web and fetch content";
50
- /**
51
- * Constructor for the Agent class.
52
- * @param {IAgentRuntime} runtime - The runtime object for the agent.
53
- */
54
- constructor(runtime) {
55
- super();
56
- this.runtime = runtime;
57
- this.browser = void 0;
58
- this.context = void 0;
59
- this.captchaSolver = new CaptchaSolver(runtime.getSetting("CAPSOLVER_API_KEY") || "");
60
- }
61
- /**
62
- * Starts the BrowserService asynchronously.
63
- *
64
- * @param {IAgentRuntime} runtime - The runtime for the agent.
65
- * @returns {Promise<BrowserService>} A promise that resolves to the initialized BrowserService.
66
- */
67
- static async start(runtime) {
68
- const service = new _BrowserService(runtime);
69
- await service.initializeBrowser();
70
- return service;
71
- }
72
- /**
73
- * Function to stop the browser service asynchronously.
74
- *
75
- * @param {IAgentRuntime} runtime - The runtime environment for the agent.
76
- */
77
- static async stop(runtime) {
78
- const service = runtime.getService(ServiceType.BROWSER);
79
- if (service) {
80
- await service.stop();
81
- }
82
- }
83
- /**
84
- * Initializes the browser by launching Chromium with specified options and setting the user agent based on the platform.
85
- * @returns {Promise<void>} A promise that resolves once the browser is successfully initialized.
86
- */
87
- async initializeBrowser() {
88
- if (!this.browser) {
89
- this.browser = await chromium.launch({
90
- headless: true,
91
- args: [
92
- "--disable-dev-shm-usage",
93
- // Uses /tmp instead of /dev/shm. Prevents memory issues on low-memory systems
94
- "--block-new-web-contents"
95
- // Prevents creation of new windows/tabs
96
- ]
97
- });
98
- const platform = process.platform;
99
- let userAgent = "";
100
- switch (platform) {
101
- case "darwin":
102
- userAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36";
103
- break;
104
- case "win32":
105
- userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36";
106
- break;
107
- case "linux":
108
- userAgent = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36";
109
- break;
110
- default:
111
- userAgent = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36";
112
- }
113
- this.context = await this.browser.newContext({
114
- userAgent,
115
- acceptDownloads: false
116
- });
117
- }
118
- }
119
- /**
120
- * Asynchronously stops the browser and context if they are currently running.
121
- */
122
- async stop() {
123
- if (this.context) {
124
- await this.context.close();
125
- this.context = void 0;
126
- }
127
- if (this.browser) {
128
- await this.browser.close();
129
- this.browser = void 0;
130
- }
131
- }
132
- /**
133
- * Asynchronously fetches the content of a web page.
134
- *
135
- * @param {string} url - The URL of the web page to fetch content from.
136
- * @param {IAgentRuntime} runtime - The runtime environment for the web scraping agent.
137
- * @returns {Promise<PageContent>} A Promise that resolves with the content of the web page.
138
- */
139
- async getPageContent(url, runtime) {
140
- await this.initializeBrowser();
141
- return await this.fetchPageContent(url, runtime);
142
- }
143
- /**
144
- * Generates a cache key for the provided URL by converting it to a UUID string.
145
- *
146
- * @param {string} url - The URL for which a cache key is being generated.
147
- * @returns {string} A UUID string representing the cache key for the URL.
148
- */
149
- getCacheKey(url) {
150
- return stringToUuid(url);
151
- }
152
- /**
153
- * Fetches the content of a page from the specified URL using a headless browser.
154
- *
155
- * @param {string} url - The URL of the page to fetch the content from.
156
- * @param {IAgentRuntime} runtime - The runtime environment for the agent.
157
- * @returns {Promise<PageContent>} A promise that resolves to the content of the fetched page.
158
- */
159
- async fetchPageContent(url, runtime) {
160
- const cacheKey = this.getCacheKey(url);
161
- const cached = await runtime.getCache(`${this.cacheKey}/${cacheKey}`);
162
- if (cached) {
163
- return cached.content;
164
- }
165
- let page;
166
- try {
167
- if (!this.context) {
168
- logger.log("Browser context not initialized. Call initializeBrowser() first.");
169
- throw new Error("Browser context not initialized");
170
- }
171
- page = await this.context.newPage();
172
- await page.setExtraHTTPHeaders({
173
- "Accept-Language": "en-US,en;q=0.9"
174
- });
175
- const response = await page.goto(url, { waitUntil: "networkidle" });
176
- if (!response) {
177
- logger.error("Failed to load the page");
178
- throw new Error("Failed to load the page");
179
- }
180
- if (response.status() === 403 || response.status() === 404) {
181
- return await this.tryAlternativeSources(url, runtime);
182
- }
183
- const captchaDetected = await this.detectCaptcha(page);
184
- if (captchaDetected) {
185
- await this.solveCaptcha(page, url);
186
- }
187
- const documentTitle = await page.evaluate(() => document.title);
188
- const bodyContent = await page.evaluate(() => document.body.innerText);
189
- const { title: parsedTitle, description } = await generateSummary(
190
- runtime,
191
- `${documentTitle}
192
- ${bodyContent}`
193
- );
194
- const content = { title: parsedTitle, description, bodyContent };
195
- await runtime.setCache(`${this.cacheKey}/${cacheKey}`, {
196
- url,
197
- content
198
- });
199
- return content;
200
- } catch (error) {
201
- logger.error("Error:", error);
202
- return {
203
- title: url,
204
- description: "Error, could not fetch content",
205
- bodyContent: ""
206
- };
207
- } finally {
208
- if (page) {
209
- await page.close();
210
- }
211
- }
212
- }
213
- /**
214
- * Detects if a captcha is present on the page based on the specified selectors.
215
- *
216
- * @param {Page} page The Puppeteer page to check for captcha.
217
- * @returns {Promise<boolean>} A boolean indicating whether a captcha was detected.
218
- */
219
- async detectCaptcha(page) {
220
- const captchaSelectors = [
221
- 'iframe[src*="captcha"]',
222
- 'div[class*="captcha"]',
223
- "#captcha",
224
- ".g-recaptcha",
225
- ".h-captcha"
226
- ];
227
- for (const selector of captchaSelectors) {
228
- const element = await page.$(selector);
229
- if (element) return true;
230
- }
231
- return false;
232
- }
233
- /**
234
- * Solves the CAPTCHA challenge on the provided page using either hCaptcha or reCaptcha.
235
- *
236
- * @param {Page} page - The page where the CAPTCHA challenge needs to be solved.
237
- * @param {string} url - The URL of the website with the CAPTCHA challenge.
238
- * @returns {Promise<void>} - A promise that resolves once the CAPTCHA is solved.
239
- */
240
- async solveCaptcha(page, url) {
241
- try {
242
- const hcaptchaKey = await this.getHCaptchaWebsiteKey(page);
243
- if (hcaptchaKey) {
244
- const solution = await this.captchaSolver.hcaptchaProxyless({
245
- websiteURL: url,
246
- websiteKey: hcaptchaKey
247
- });
248
- await page.evaluate((token) => {
249
- window.hcaptcha.setResponse(token);
250
- }, solution.gRecaptchaResponse);
251
- return;
252
- }
253
- const recaptchaKey = await this.getReCaptchaWebsiteKey(page);
254
- if (recaptchaKey) {
255
- const solution = await this.captchaSolver.recaptchaV2Proxyless({
256
- websiteURL: url,
257
- websiteKey: recaptchaKey
258
- });
259
- await page.evaluate((token) => {
260
- document.getElementById("g-recaptcha-response").innerHTML = token;
261
- }, solution.gRecaptchaResponse);
262
- }
263
- } catch (error) {
264
- logger.error("Error solving CAPTCHA:", error);
265
- }
266
- }
267
- /**
268
- * Get the hCaptcha website key from the given Page
269
- * @param {Page} page - The Page object to extract the hCaptcha website key from
270
- * @returns {Promise<string>} The hCaptcha website key
271
- */
272
- async getHCaptchaWebsiteKey(page) {
273
- return page.evaluate(() => {
274
- const hcaptchaIframe = document.querySelector('iframe[src*="hcaptcha.com"]');
275
- if (hcaptchaIframe) {
276
- const src = hcaptchaIframe.getAttribute("src");
277
- const match = src?.match(/sitekey=([^&]*)/);
278
- return match ? match[1] : "";
279
- }
280
- return "";
281
- });
282
- }
283
- /**
284
- * Retrieves the ReCaptcha website key from a given page.
285
- * @param {Page} page - The page to extract the ReCaptcha website key from.
286
- * @returns {Promise<string>} The ReCaptcha website key, or an empty string if not found.
287
- */
288
- async getReCaptchaWebsiteKey(page) {
289
- return page.evaluate(() => {
290
- const recaptchaElement = document.querySelector(".g-recaptcha");
291
- return recaptchaElement ? recaptchaElement.getAttribute("data-sitekey") || "" : "";
292
- });
293
- }
294
- /**
295
- * Try fetching content from alternative sources if the original source fails.
296
- *
297
- * @param {string} url - The URL of the content to fetch.
298
- * @param {IAgentRuntime} runtime - The runtime environment.
299
- * @returns {Promise<{ title: string; description: string; bodyContent: string }>} The fetched content with title, description, and body.
300
- */
301
- async tryAlternativeSources(url, runtime) {
302
- if (!url.match(/web.archive.org\/web/)) {
303
- const archiveUrl = `https://web.archive.org/web/${url}`;
304
- try {
305
- return await this.fetchPageContent(archiveUrl, runtime);
306
- } catch (error) {
307
- logger.error("Error fetching from Internet Archive:", error);
308
- }
309
- }
310
- if (!url.match(/www.google.com\/search/)) {
311
- const googleSearchUrl = `https://www.google.com/search?q=${encodeURIComponent(url)}`;
312
- try {
313
- return await this.fetchPageContent(googleSearchUrl, runtime);
314
- } catch (error) {
315
- logger.error("Error fetching from Google Search:", error);
316
- logger.error("Failed to fetch content from alternative sources");
317
- }
318
- }
319
- return {
320
- title: url,
321
- description: "Error, could not fetch content from alternative sources",
322
- bodyContent: ""
323
- };
324
- }
1
+ import { logger, ServiceType } from "@elizaos/core";
2
+ import { z } from "zod";
3
+ import { browserClickAction } from "./actions/click.js";
4
+ import { browserExtractAction } from "./actions/extract.js";
5
+ import { browserNavigateAction } from "./actions/navigate.js";
6
+ import { browserScreenshotAction } from "./actions/screenshot.js";
7
+ import { browserSelectAction } from "./actions/select.js";
8
+ import { browserTypeAction } from "./actions/type.js";
9
+ import { BrowserService, Session } from "./services/browser-service.js";
10
+ import { BrowserProcessManager } from "./services/process-manager.js";
11
+ import { BrowserWebSocketClient } from "./services/websocket-client.js";
12
+ export * from "./types.js";
13
+ export * from "./utils/index.js";
14
+ export { BrowserService, Session, BrowserWebSocketClient, BrowserProcessManager };
15
+ export { browserNavigateAction, browserClickAction, browserTypeAction, browserSelectAction, browserExtractAction, browserScreenshotAction, };
16
+ const configSchema = z.object({
17
+ BROWSERBASE_API_KEY: z.string().optional(),
18
+ BROWSERBASE_PROJECT_ID: z.string().optional(),
19
+ OPENAI_API_KEY: z.string().optional(),
20
+ ANTHROPIC_API_KEY: z.string().optional(),
21
+ OLLAMA_BASE_URL: z.string().optional(),
22
+ OLLAMA_MODEL: z.string().optional(),
23
+ BROWSER_HEADLESS: z
24
+ .string()
25
+ .transform((val) => val === "true")
26
+ .optional()
27
+ .default(true),
28
+ CAPSOLVER_API_KEY: z.string().optional(),
29
+ BROWSER_SERVER_PORT: z.string().optional().default("3456"),
30
+ });
31
+ const browserStateProvider = {
32
+ name: "BROWSER_STATE",
33
+ description: "Provides current browser state information",
34
+ get: async (runtime, _message, _state) => {
35
+ const service = runtime.getService(ServiceType.BROWSER);
36
+ const session = await service?.getCurrentSession();
37
+ if (!session || !service) {
38
+ return {
39
+ text: "No active browser session",
40
+ values: {
41
+ hasSession: false,
42
+ },
43
+ data: {},
44
+ };
45
+ }
46
+ try {
47
+ const client = service.getClient();
48
+ const state = await client.getState(session.id);
49
+ return {
50
+ text: `Current browser page: "${state.title}" at ${state.url}`,
51
+ values: {
52
+ hasSession: true,
53
+ url: state.url,
54
+ title: state.title,
55
+ },
56
+ data: {
57
+ sessionId: session.id,
58
+ createdAt: session.createdAt.toISOString(),
59
+ },
60
+ };
61
+ }
62
+ catch (error) {
63
+ const errorMessage = error instanceof Error ? error.message : String(error);
64
+ logger.error(`Error getting browser state: ${errorMessage}`);
65
+ return {
66
+ text: "Error getting browser state",
67
+ values: {
68
+ hasSession: true,
69
+ error: true,
70
+ },
71
+ data: {},
72
+ };
73
+ }
74
+ },
325
75
  };
326
-
327
- // src/index.ts
328
- var browserPlugin = {
329
- name: "browser-plugin",
330
- description: "Plugin for browser actions",
331
- services: [BrowserService],
332
- actions: [],
333
- tests: [
334
- {
335
- name: "test browser service",
336
- tests: [
337
- {
338
- name: "Browser service initialization",
339
- fn: async (runtime) => {
340
- const service = await BrowserService.start(runtime);
341
- if (!service) {
342
- throw new Error("Failed to initialize BrowserService");
76
+ export const browserPlugin = {
77
+ name: "plugin-browser",
78
+ description: "Browser automation plugin",
79
+ config: {
80
+ BROWSERBASE_API_KEY: process.env.BROWSERBASE_API_KEY ?? null,
81
+ BROWSERBASE_PROJECT_ID: process.env.BROWSERBASE_PROJECT_ID ?? null,
82
+ OPENAI_API_KEY: process.env.OPENAI_API_KEY ?? null,
83
+ ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY ?? null,
84
+ OLLAMA_BASE_URL: process.env.OLLAMA_BASE_URL ?? null,
85
+ OLLAMA_MODEL: process.env.OLLAMA_MODEL ?? null,
86
+ BROWSER_HEADLESS: process.env.BROWSER_HEADLESS ?? "true",
87
+ CAPSOLVER_API_KEY: process.env.CAPSOLVER_API_KEY ?? null,
88
+ BROWSER_SERVER_PORT: process.env.BROWSER_SERVER_PORT ?? "3456",
89
+ },
90
+ async init(config, _runtime) {
91
+ logger.info("Initializing browser automation plugin");
92
+ try {
93
+ const validatedConfig = await configSchema.parseAsync(config);
94
+ for (const [key, value] of Object.entries(validatedConfig)) {
95
+ if (value !== undefined && value !== null) {
96
+ process.env[key] = String(value);
97
+ }
343
98
  }
344
- }
99
+ logger.info("Browser plugin initialized successfully");
345
100
  }
346
- ]
347
- }
348
- ]
349
- };
350
- export {
351
- browserPlugin
101
+ catch (error) {
102
+ if (error && typeof error === "object" && "issues" in error) {
103
+ const zodError = error;
104
+ if (Array.isArray(zodError.issues)) {
105
+ const errorMessages = zodError.issues.map((e) => e.message).join(", ");
106
+ throw new Error(`Invalid plugin configuration: ${errorMessages}`);
107
+ }
108
+ }
109
+ throw error;
110
+ }
111
+ },
112
+ services: [BrowserService],
113
+ actions: [
114
+ browserNavigateAction,
115
+ browserClickAction,
116
+ browserTypeAction,
117
+ browserSelectAction,
118
+ browserExtractAction,
119
+ browserScreenshotAction,
120
+ ],
121
+ providers: [browserStateProvider],
352
122
  };
123
+ export default browserPlugin;
353
124
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/services/browser.ts","../src/index.ts"],"sourcesContent":["import {\n type IAgentRuntime,\n ModelType,\n Service,\n type ServiceTypeName,\n ServiceType,\n logger,\n parseJSONObjectFromText,\n stringToUuid,\n trimTokens,\n} from '@elizaos/core';\nimport CaptchaSolver from 'capsolver-npm';\nimport { type Browser, type BrowserContext, type Page, chromium } from 'patchright';\n\n// Type for cached content\ninterface CachedContent {\n url: string;\n content: PageContent;\n}\n\n/**\n * Asynchronously generates a summary for a given text using a machine learning model.\n *\n * @param {IAgentRuntime} runtime - The runtime environment for the agent\n * @param {string} text - The text to generate a summary for\n * @returns {Promise<{ title: string; description: string }>} A promise that resolves to an object containing the generated title and summary\n */\nasync function generateSummary(\n runtime: IAgentRuntime,\n text: string\n): Promise<{ title: string; description: string }> {\n // make sure text is under 128k characters\n const trimmedText = await trimTokens(text, 100000, runtime);\n\n const prompt = `Please generate a concise summary for the following text:\n\n Text: \"\"\"\n ${trimmedText}\n \"\"\"\n\n Respond with a JSON object in the following format:\n \\`\\`\\`json\n {\n \"title\": \"Generated Title\",\n \"summary\": \"Generated summary and/or description of the text\"\n }\n \\`\\`\\``;\n\n const response = await runtime.useModel(ModelType.TEXT_SMALL, {\n prompt,\n });\n\n const parsedResponse = parseJSONObjectFromText(response);\n\n if (parsedResponse?.title && parsedResponse?.summary) {\n return {\n title: parsedResponse.title,\n description: parsedResponse.summary,\n };\n }\n\n return {\n title: '',\n description: '',\n };\n}\n\n/**\n * Represents the content of a page.\n * @typedef { Object } PageContent\n * @property { string } title - The title of the page.\n * @property { string } description - The description of the page.\n * @property { string } bodyContent - The main content of the page.\n */\ntype PageContent = {\n title: string;\n description: string;\n bodyContent: string;\n};\n\n/**\n * Represents a BrowserService class that extends Service.\n * Provides methods for initializing browser, stopping browser, fetching page content, solving CAPTCHAs, detecting CAPTCHAs, and getting cache key.\n * @extends Service\n */\nexport class BrowserService extends Service {\n private browser: Browser | undefined;\n private context: BrowserContext | undefined;\n private captchaSolver: CaptchaSolver;\n private cacheKey = 'content/browser';\n\n static serviceType: ServiceTypeName = ServiceType.BROWSER;\n capabilityDescription = 'The agent is able to browse the web and fetch content';\n\n /**\n * Constructor for the Agent class.\n * @param {IAgentRuntime} runtime - The runtime object for the agent.\n */\n constructor(runtime: IAgentRuntime) {\n super();\n this.runtime = runtime;\n this.browser = undefined;\n this.context = undefined;\n this.captchaSolver = new CaptchaSolver(runtime.getSetting('CAPSOLVER_API_KEY') || '');\n }\n\n /**\n * Starts the BrowserService asynchronously.\n *\n * @param {IAgentRuntime} runtime - The runtime for the agent.\n * @returns {Promise<BrowserService>} A promise that resolves to the initialized BrowserService.\n */\n static async start(runtime: IAgentRuntime): Promise<BrowserService> {\n const service = new BrowserService(runtime);\n await service.initializeBrowser();\n return service;\n }\n\n /**\n * Function to stop the browser service asynchronously.\n *\n * @param {IAgentRuntime} runtime - The runtime environment for the agent.\n */\n static async stop(runtime: IAgentRuntime) {\n const service = runtime.getService(ServiceType.BROWSER);\n if (service) {\n await service.stop();\n }\n }\n\n /**\n * Initializes the browser by launching Chromium with specified options and setting the user agent based on the platform.\n * @returns {Promise<void>} A promise that resolves once the browser is successfully initialized.\n */\n async initializeBrowser() {\n if (!this.browser) {\n this.browser = await chromium.launch({\n headless: true,\n args: [\n '--disable-dev-shm-usage', // Uses /tmp instead of /dev/shm. Prevents memory issues on low-memory systems\n '--block-new-web-contents', // Prevents creation of new windows/tabs\n ],\n });\n\n const platform = process.platform;\n let userAgent = '';\n\n // Change the user agent to match the platform to reduce bot detection\n switch (platform) {\n case 'darwin':\n userAgent =\n 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36';\n break;\n case 'win32':\n userAgent =\n 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36';\n break;\n case 'linux':\n userAgent =\n 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36';\n break;\n default:\n userAgent =\n 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36';\n }\n\n this.context = await this.browser.newContext({\n userAgent,\n acceptDownloads: false,\n });\n }\n }\n\n /**\n * Asynchronously stops the browser and context if they are currently running.\n */\n async stop() {\n if (this.context) {\n await this.context.close();\n this.context = undefined;\n }\n if (this.browser) {\n await this.browser.close();\n this.browser = undefined;\n }\n }\n\n /**\n * Asynchronously fetches the content of a web page.\n *\n * @param {string} url - The URL of the web page to fetch content from.\n * @param {IAgentRuntime} runtime - The runtime environment for the web scraping agent.\n * @returns {Promise<PageContent>} A Promise that resolves with the content of the web page.\n */\n async getPageContent(url: string, runtime: IAgentRuntime): Promise<PageContent> {\n await this.initializeBrowser();\n return await this.fetchPageContent(url, runtime);\n }\n\n /**\n * Generates a cache key for the provided URL by converting it to a UUID string.\n *\n * @param {string} url - The URL for which a cache key is being generated.\n * @returns {string} A UUID string representing the cache key for the URL.\n */\n private getCacheKey(url: string): string {\n return stringToUuid(url);\n }\n\n /**\n * Fetches the content of a page from the specified URL using a headless browser.\n *\n * @param {string} url - The URL of the page to fetch the content from.\n * @param {IAgentRuntime} runtime - The runtime environment for the agent.\n * @returns {Promise<PageContent>} A promise that resolves to the content of the fetched page.\n */\n private async fetchPageContent(url: string, runtime: IAgentRuntime): Promise<PageContent> {\n const cacheKey = this.getCacheKey(url);\n const cached = await runtime.getCache<CachedContent>(`${this.cacheKey}/${cacheKey}`);\n\n if (cached) {\n return cached.content;\n }\n\n let page: Page | undefined;\n\n try {\n if (!this.context) {\n logger.log('Browser context not initialized. Call initializeBrowser() first.');\n throw new Error('Browser context not initialized');\n }\n\n page = await this.context.newPage();\n\n // Enable stealth mode\n await page.setExtraHTTPHeaders({\n 'Accept-Language': 'en-US,en;q=0.9',\n });\n\n const response = await page.goto(url, { waitUntil: 'networkidle' });\n\n if (!response) {\n logger.error('Failed to load the page');\n throw new Error('Failed to load the page');\n }\n\n if (response.status() === 403 || response.status() === 404) {\n return await this.tryAlternativeSources(url, runtime);\n }\n\n // Check for CAPTCHA\n const captchaDetected = await this.detectCaptcha(page);\n if (captchaDetected) {\n await this.solveCaptcha(page, url);\n }\n const documentTitle = await page.evaluate(() => document.title);\n const bodyContent = await page.evaluate(() => document.body.innerText);\n const { title: parsedTitle, description } = await generateSummary(\n runtime,\n `${documentTitle}\\n${bodyContent}`\n );\n const content = { title: parsedTitle, description, bodyContent };\n await runtime.setCache<CachedContent>(`${this.cacheKey}/${cacheKey}`, {\n url,\n content,\n });\n return content;\n } catch (error) {\n logger.error('Error:', error);\n return {\n title: url,\n description: 'Error, could not fetch content',\n bodyContent: '',\n };\n } finally {\n if (page) {\n await page.close();\n }\n }\n }\n\n /**\n * Detects if a captcha is present on the page based on the specified selectors.\n *\n * @param {Page} page The Puppeteer page to check for captcha.\n * @returns {Promise<boolean>} A boolean indicating whether a captcha was detected.\n */\n private async detectCaptcha(page: Page): Promise<boolean> {\n const captchaSelectors = [\n 'iframe[src*=\"captcha\"]',\n 'div[class*=\"captcha\"]',\n '#captcha',\n '.g-recaptcha',\n '.h-captcha',\n ];\n\n for (const selector of captchaSelectors) {\n const element = await page.$(selector);\n if (element) return true;\n }\n\n return false;\n }\n\n /**\n * Solves the CAPTCHA challenge on the provided page using either hCaptcha or reCaptcha.\n *\n * @param {Page} page - The page where the CAPTCHA challenge needs to be solved.\n * @param {string} url - The URL of the website with the CAPTCHA challenge.\n * @returns {Promise<void>} - A promise that resolves once the CAPTCHA is solved.\n */\n private async solveCaptcha(page: Page, url: string): Promise<void> {\n try {\n const hcaptchaKey = await this.getHCaptchaWebsiteKey(page);\n if (hcaptchaKey) {\n const solution = await this.captchaSolver.hcaptchaProxyless({\n websiteURL: url,\n websiteKey: hcaptchaKey,\n });\n await page.evaluate((token) => {\n // eslint-disable-next-line\n // @ts-ignore\n window.hcaptcha.setResponse(token);\n }, solution.gRecaptchaResponse);\n return;\n }\n\n const recaptchaKey = await this.getReCaptchaWebsiteKey(page);\n if (recaptchaKey) {\n const solution = await this.captchaSolver.recaptchaV2Proxyless({\n websiteURL: url,\n websiteKey: recaptchaKey,\n });\n await page.evaluate((token) => {\n // eslint-disable-next-line\n // @ts-ignore\n document.getElementById('g-recaptcha-response').innerHTML = token;\n }, solution.gRecaptchaResponse);\n }\n } catch (error) {\n logger.error('Error solving CAPTCHA:', error);\n }\n }\n\n /**\n * Get the hCaptcha website key from the given Page\n * @param {Page} page - The Page object to extract the hCaptcha website key from\n * @returns {Promise<string>} The hCaptcha website key\n */\n private async getHCaptchaWebsiteKey(page: Page): Promise<string> {\n return page.evaluate(() => {\n const hcaptchaIframe = document.querySelector('iframe[src*=\"hcaptcha.com\"]');\n if (hcaptchaIframe) {\n const src = hcaptchaIframe.getAttribute('src');\n const match = src?.match(/sitekey=([^&]*)/);\n return match ? match[1] : '';\n }\n return '';\n });\n }\n\n /**\n * Retrieves the ReCaptcha website key from a given page.\n * @param {Page} page - The page to extract the ReCaptcha website key from.\n * @returns {Promise<string>} The ReCaptcha website key, or an empty string if not found.\n */\n private async getReCaptchaWebsiteKey(page: Page): Promise<string> {\n return page.evaluate(() => {\n const recaptchaElement = document.querySelector('.g-recaptcha');\n return recaptchaElement ? recaptchaElement.getAttribute('data-sitekey') || '' : '';\n });\n }\n\n /**\n * Try fetching content from alternative sources if the original source fails.\n *\n * @param {string} url - The URL of the content to fetch.\n * @param {IAgentRuntime} runtime - The runtime environment.\n * @returns {Promise<{ title: string; description: string; bodyContent: string }>} The fetched content with title, description, and body.\n */\n private async tryAlternativeSources(\n url: string,\n runtime: IAgentRuntime\n ): Promise<{ title: string; description: string; bodyContent: string }> {\n // because this (tryAlternativeSources) calls fetchPageContent\n // and fetchPageContent calls tryAlternativeSources\n // we need these url.matches to progress\n // through the things to try\n if (!url.match(/web.archive.org\\/web/)) {\n // Try Internet Archive\n const archiveUrl = `https://web.archive.org/web/${url}`;\n try {\n return await this.fetchPageContent(archiveUrl, runtime);\n } catch (error) {\n logger.error('Error fetching from Internet Archive:', error);\n }\n }\n\n if (!url.match(/www.google.com\\/search/)) {\n // Try Google Search as a last resort\n const googleSearchUrl = `https://www.google.com/search?q=${encodeURIComponent(url)}`;\n try {\n return await this.fetchPageContent(googleSearchUrl, runtime);\n } catch (error) {\n logger.error('Error fetching from Google Search:', error);\n logger.error('Failed to fetch content from alternative sources');\n }\n }\n\n // Return error content if all alternatives fail\n return {\n title: url,\n description: 'Error, could not fetch content from alternative sources',\n bodyContent: '',\n };\n }\n}\n","import type { Plugin , IAgentRuntime} from \"@elizaos/core\";\n\nimport { BrowserService } from \"./services/browser\";\n\nexport const browserPlugin: Plugin = {\n name: \"browser-plugin\",\n description: \"Plugin for browser actions\",\n services: [BrowserService],\n actions: [],\n tests: [\n {\n name: \"test browser service\",\n tests: [\n {\n name: \"Browser service initialization\",\n fn: async (runtime: IAgentRuntime) => {\n const service = await BrowserService.start(runtime);\n if (!service) {\n throw new Error(\"Failed to initialize BrowserService\");\n }\n },\n },\n ],\n }\n ],\n};\n"],"mappings":"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","names":[]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IAgentRuntime, Memory, Plugin, Provider, ProviderResult, State } from \"@elizaos/core\";\nimport { logger, ServiceType } from \"@elizaos/core\";\nimport { z } from \"zod\";\nimport { browserClickAction } from \"./actions/click.js\";\nimport { browserExtractAction } from \"./actions/extract.js\";\nimport { browserNavigateAction } from \"./actions/navigate.js\";\nimport { browserScreenshotAction } from \"./actions/screenshot.js\";\nimport { browserSelectAction } from \"./actions/select.js\";\nimport { browserTypeAction } from \"./actions/type.js\";\nimport { BrowserService, Session } from \"./services/browser-service.js\";\nimport { BrowserProcessManager } from \"./services/process-manager.js\";\nimport { BrowserWebSocketClient } from \"./services/websocket-client.js\";\n\nexport * from \"./types.js\";\nexport * from \"./utils/index.js\";\nexport { BrowserService, Session, BrowserWebSocketClient, BrowserProcessManager };\nexport {\n browserNavigateAction,\n browserClickAction,\n browserTypeAction,\n browserSelectAction,\n browserExtractAction,\n browserScreenshotAction,\n};\nconst configSchema = z.object({\n BROWSERBASE_API_KEY: z.string().optional(),\n BROWSERBASE_PROJECT_ID: z.string().optional(),\n OPENAI_API_KEY: z.string().optional(),\n ANTHROPIC_API_KEY: z.string().optional(),\n OLLAMA_BASE_URL: z.string().optional(),\n OLLAMA_MODEL: z.string().optional(),\n BROWSER_HEADLESS: z\n .string()\n .transform((val: string) => val === \"true\")\n .optional()\n .default(true),\n CAPSOLVER_API_KEY: z.string().optional(),\n BROWSER_SERVER_PORT: z.string().optional().default(\"3456\"),\n});\n\nconst browserStateProvider: Provider = {\n name: \"BROWSER_STATE\",\n description: \"Provides current browser state information\",\n\n get: async (\n runtime: IAgentRuntime,\n _message: Memory,\n _state?: State\n ): Promise<ProviderResult> => {\n const service = runtime.getService<BrowserService>(ServiceType.BROWSER);\n const session = await service?.getCurrentSession();\n\n if (!session || !service) {\n return {\n text: \"No active browser session\",\n values: {\n hasSession: false,\n },\n data: {},\n };\n }\n\n try {\n const client = service.getClient();\n const state = await client.getState(session.id);\n\n return {\n text: `Current browser page: \"${state.title}\" at ${state.url}`,\n values: {\n hasSession: true,\n url: state.url,\n title: state.title,\n },\n data: {\n sessionId: session.id,\n createdAt: session.createdAt.toISOString(),\n },\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.error(`Error getting browser state: ${errorMessage}`);\n return {\n text: \"Error getting browser state\",\n values: {\n hasSession: true,\n error: true,\n },\n data: {},\n };\n }\n },\n};\n\nexport const browserPlugin: Plugin = {\n name: \"plugin-browser\",\n description: \"Browser automation plugin\",\n config: {\n BROWSERBASE_API_KEY: process.env.BROWSERBASE_API_KEY ?? null,\n BROWSERBASE_PROJECT_ID: process.env.BROWSERBASE_PROJECT_ID ?? null,\n OPENAI_API_KEY: process.env.OPENAI_API_KEY ?? null,\n ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY ?? null,\n OLLAMA_BASE_URL: process.env.OLLAMA_BASE_URL ?? null,\n OLLAMA_MODEL: process.env.OLLAMA_MODEL ?? null,\n BROWSER_HEADLESS: process.env.BROWSER_HEADLESS ?? \"true\",\n CAPSOLVER_API_KEY: process.env.CAPSOLVER_API_KEY ?? null,\n BROWSER_SERVER_PORT: process.env.BROWSER_SERVER_PORT ?? \"3456\",\n },\n async init(config: Record<string, string | null>, _runtime: IAgentRuntime) {\n logger.info(\"Initializing browser automation plugin\");\n try {\n const validatedConfig = await configSchema.parseAsync(config);\n\n for (const [key, value] of Object.entries(validatedConfig)) {\n if (value !== undefined && value !== null) {\n process.env[key] = String(value);\n }\n }\n\n logger.info(\"Browser plugin initialized successfully\");\n } catch (error) {\n if (error && typeof error === \"object\" && \"issues\" in error) {\n const zodError = error as { issues?: Array<{ message: string }> };\n if (Array.isArray(zodError.issues)) {\n const errorMessages = zodError.issues.map((e) => e.message).join(\", \");\n throw new Error(`Invalid plugin configuration: ${errorMessages}`);\n }\n }\n throw error;\n }\n },\n services: [BrowserService],\n actions: [\n browserNavigateAction,\n browserClickAction,\n browserTypeAction,\n browserSelectAction,\n browserExtractAction,\n browserScreenshotAction,\n ],\n providers: [browserStateProvider],\n};\n\nexport default browserPlugin;\n"]}
@@ -0,0 +1,3 @@
1
+ import type { Provider } from "@elizaos/core";
2
+ export declare const browserStateProvider: Provider;
3
+ //# sourceMappingURL=browser-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-state.d.ts","sourceRoot":"","sources":["../../src/providers/browser-state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAyB,QAAQ,EAAyB,MAAM,eAAe,CAAC;AAI5F,eAAO,MAAM,oBAAoB,EAAE,QAmDlC,CAAC"}
@@ -0,0 +1,47 @@
1
+ import { logger, ServiceType } from "@elizaos/core";
2
+ export const browserStateProvider = {
3
+ name: "BROWSER_STATE",
4
+ description: "Provides current browser state information",
5
+ get: async (runtime, _message, _state) => {
6
+ const service = runtime.getService(ServiceType.BROWSER);
7
+ const session = await service?.getCurrentSession();
8
+ if (!session || !service) {
9
+ return {
10
+ text: "No active browser session",
11
+ values: {
12
+ hasSession: false,
13
+ },
14
+ data: {},
15
+ };
16
+ }
17
+ try {
18
+ const client = service.getClient();
19
+ const state = await client.getState(session.id);
20
+ return {
21
+ text: `Current browser page: "${state.title}" at ${state.url}`,
22
+ values: {
23
+ hasSession: true,
24
+ url: state.url,
25
+ title: state.title,
26
+ },
27
+ data: {
28
+ sessionId: session.id,
29
+ createdAt: session.createdAt.toISOString(),
30
+ },
31
+ };
32
+ }
33
+ catch (error) {
34
+ const errorMessage = error instanceof Error ? error.message : String(error);
35
+ logger.error(`Error getting browser state: ${errorMessage}`);
36
+ return {
37
+ text: "Error getting browser state",
38
+ values: {
39
+ hasSession: true,
40
+ error: true,
41
+ },
42
+ data: {},
43
+ };
44
+ }
45
+ },
46
+ };
47
+ //# sourceMappingURL=browser-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-state.js","sourceRoot":"","sources":["../../src/providers/browser-state.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAGpD,MAAM,CAAC,MAAM,oBAAoB,GAAa;IAC5C,IAAI,EAAE,eAAe;IACrB,WAAW,EAAE,4CAA4C;IAEzD,GAAG,EAAE,KAAK,EACR,OAAsB,EACtB,QAAgB,EAChB,MAAc,EACW,EAAE;QAC3B,MAAM,OAAO,GAAG,OAAO,CAAC,UAAU,CAAiB,WAAW,CAAC,OAAO,CAAC,CAAC;QACxE,MAAM,OAAO,GAAG,MAAM,OAAO,EAAE,iBAAiB,EAAE,CAAC;QAEnD,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC;YACzB,OAAO;gBACL,IAAI,EAAE,2BAA2B;gBACjC,MAAM,EAAE;oBACN,UAAU,EAAE,KAAK;iBAClB;gBACD,IAAI,EAAE,EAAE;aACT,CAAC;QACJ,CAAC;QAED,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;YACnC,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YAEhD,OAAO;gBACL,IAAI,EAAE,0BAA0B,KAAK,CAAC,KAAK,QAAQ,KAAK,CAAC,GAAG,EAAE;gBAC9D,MAAM,EAAE;oBACN,UAAU,EAAE,IAAI;oBAChB,GAAG,EAAE,KAAK,CAAC,GAAG;oBACd,KAAK,EAAE,KAAK,CAAC,KAAK;iBACnB;gBACD,IAAI,EAAE;oBACJ,SAAS,EAAE,OAAO,CAAC,EAAE;oBACrB,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,WAAW,EAAE;iBAC3C;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,YAAY,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC5E,MAAM,CAAC,KAAK,CAAC,gCAAgC,YAAY,EAAE,CAAC,CAAC;YAC7D,OAAO;gBACL,IAAI,EAAE,6BAA6B;gBACnC,MAAM,EAAE;oBACN,UAAU,EAAE,IAAI;oBAChB,KAAK,EAAE,IAAI;iBACZ;gBACD,IAAI,EAAE,EAAE;aACT,CAAC;QACJ,CAAC;IACH,CAAC;CACF,CAAC","sourcesContent":["import type { IAgentRuntime, Memory, Provider, ProviderResult, State } from \"@elizaos/core\";\nimport { logger, ServiceType } from \"@elizaos/core\";\nimport type { BrowserService } from \"../services/browser-service.js\";\n\nexport const browserStateProvider: Provider = {\n name: \"BROWSER_STATE\",\n description: \"Provides current browser state information\",\n\n get: async (\n runtime: IAgentRuntime,\n _message: Memory,\n _state?: State\n ): Promise<ProviderResult> => {\n const service = runtime.getService<BrowserService>(ServiceType.BROWSER);\n const session = await service?.getCurrentSession();\n\n if (!session || !service) {\n return {\n text: \"No active browser session\",\n values: {\n hasSession: false,\n },\n data: {},\n };\n }\n\n try {\n const client = service.getClient();\n const state = await client.getState(session.id);\n\n return {\n text: `Current browser page: \"${state.title}\" at ${state.url}`,\n values: {\n hasSession: true,\n url: state.url,\n title: state.title,\n },\n data: {\n sessionId: session.id,\n createdAt: session.createdAt.toISOString(),\n },\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n logger.error(`Error getting browser state: ${errorMessage}`);\n return {\n text: \"Error getting browser state\",\n values: {\n hasSession: true,\n error: true,\n },\n data: {},\n };\n }\n },\n};\n"]}
@@ -0,0 +1,2 @@
1
+ export { browserStateProvider } from "./browser-state.js";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { browserStateProvider } from "./browser-state.js";
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC","sourcesContent":["export { browserStateProvider } from \"./browser-state.js\";\n"]}