@elizaos/plugin-browser 1.0.0-beta.8 → 1.0.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 CHANGED
@@ -1,384 +1,64 @@
1
1
  # @elizaos/plugin-browser
2
2
 
3
- Core Node.js plugin for Eliza OS that provides essential services and actions for file operations, media processing, and cloud integrations.
4
-
5
- ## Overview
6
-
7
- The Node plugin serves as a foundational component of Eliza OS, bridging core Node.js capabilities with the Eliza ecosystem. It provides crucial services for file operations, media processing, speech synthesis, and cloud integrations, enabling both local and cloud-based functionality for Eliza agents.
3
+ Browser plugin for Eliza OS that provides web browsing and scraping capabilities.
8
4
 
9
5
  ## Features
10
6
 
11
- - **AWS S3 Integration**: File upload and management with AWS S3
12
- - **Browser Automation**: Web scraping and content extraction with Playwright
13
- - **Image Processing**: Image description and analysis capabilities
14
- - **PDF Processing**: PDF text extraction and parsing
15
- - **Speech Synthesis**: Text-to-speech using ElevenLabs and VITS
16
- - **Transcription**: Speech-to-text using various providers (OpenAI, Deepgram, Local)
17
- - **Video Processing**: YouTube video download and transcription
18
- - **LLaMA Integration**: Local LLM support with LLaMA models
7
+ - **Web Browsing**: Navigate and interact with web pages
8
+ - **Content Extraction**: Extract text and metadata from web pages
9
+ - **CAPTCHA Solving**: Automatic CAPTCHA detection and solving
10
+ - **Stealth Mode**: Reduced bot detection with proper user agents and headers
19
11
 
20
12
  ## Installation
21
13
 
22
14
  ```bash
23
- npx elizaos plugin add @elizaos/plugin-browser
24
- ```
25
-
26
- ## Configuration
27
-
28
- The plugin requires various environment variables depending on which services you plan to use:
29
-
30
- ### Core Settings
31
-
32
- ```env
33
- OPENAI_API_KEY=your_openai_api_key
34
- ```
35
-
36
- ### Voice Settings (Optional)
37
-
38
- ```env
39
- ELEVENLABS_API_KEY=your_elevenlabs_api_key
40
- ELEVENLABS_MODEL_ID=eleven_monolingual_v1
41
- ELEVENLABS_VOICE_ID=your_voice_id
42
- ELEVENLABS_VOICE_STABILITY=0.5
43
- ELEVENLABS_VOICE_SIMILARITY_BOOST=0.75
44
- ELEVENLABS_OPTIMIZE_STREAMING_LATENCY=0
45
- ELEVENLABS_OUTPUT_FORMAT=pcm_16000
46
- VITS_VOICE=en_US-hfc_female-medium
47
- ```
48
-
49
- ### AWS Settings (Optional)
50
-
51
- ```env
52
- AWS_ACCESS_KEY_ID=your_aws_access_key
53
- AWS_SECRET_ACCESS_KEY=your_aws_secret_key
54
- AWS_REGION=your_aws_region
55
- AWS_S3_BUCKET=your_s3_bucket
56
- AWS_S3_UPLOAD_PATH=your_upload_path
57
- AWS_S3_ENDPOINT=an_alternative_endpoint
58
- AWS_S3_SSL_ENABLED=boolean(true|false)
59
- AWS_S3_FORCE_PATH_STYLE=boolean(true|false)
15
+ npm install @elizaos/plugin-browser
60
16
  ```
61
17
 
62
18
  ## Usage
63
19
 
64
20
  ```typescript
65
- import { createNodePlugin } from '@elizaos/plugin-node';
66
-
67
- // Initialize the plugin
68
- const nodePlugin = createNodePlugin();
21
+ import { browserPlugin } from '@elizaos/plugin-browser';
69
22
 
70
- // Register with Eliza OS
71
- elizaos.registerPlugin(nodePlugin);
23
+ // Add to your Eliza configuration
24
+ export default {
25
+ plugins: [browserPlugin],
26
+ // ... other config
27
+ };
72
28
  ```
73
29
 
74
- ## Services
75
-
76
- ### AwsS3Service
77
-
78
- Handles file uploads and management with AWS S3.
79
-
80
- ### BrowserService
81
-
82
- Provides web scraping and content extraction capabilities using Playwright.
83
-
84
- ### ImageDescriptionService
85
-
86
- Processes and analyzes images to generate descriptions. Supports multiple providers:
87
-
88
- - Local processing using Florence model
89
- - OpenAI Vision API
90
- - Google Gemini
91
-
92
- Configuration:
93
-
94
- ```env
95
- # For OpenAI Vision
96
- OPENAI_API_KEY=your_openai_api_key
97
-
98
- # For Google Gemini
99
- GOOGLE_GENERATIVE_AI_API_KEY=your_google_api_key
100
- ```
101
-
102
- Provider selection:
103
-
104
- - If `imageVisionModelProvider` is set to `google/openai`, it will use this one.
105
- - Else if `model` is set to `google/openai`, it will use this one.
106
- - Default if nothing is set is OpenAI.
107
-
108
- The service automatically handles different image formats, including GIFs (first frame extraction).
109
-
110
- Features by provider:
111
-
112
- **Local (Florence):**
113
-
114
- - Basic image captioning
115
- - Local processing without API calls
116
-
117
- **OpenAI Vision:**
118
-
119
- - Detailed image descriptions
120
- - Text detection
121
- - Object recognition
122
-
123
- **Google Gemini 1.5:**
124
-
125
- - High-quality image understanding
126
- - Detailed descriptions with natural language
127
- - Multi-modal context understanding
128
- - Support for complex scenes and content
129
-
130
- The provider can be configured through the runtime settings, allowing easy switching between providers based on your needs.
131
-
132
- ### LlamaService
133
-
134
- Provides local LLM capabilities using LLaMA models.
135
-
136
- ### PdfService
137
-
138
- Extracts and processes text content from PDF files.
139
-
140
- ### SpeechService
141
-
142
- Handles text-to-speech conversion using ElevenLabs and VITS.
143
-
144
- ### TranscriptionService
145
-
146
- Converts speech to text using various providers.
147
-
148
- ### VideoService
149
-
150
- Processes video content, including YouTube video downloads and transcription.
151
-
152
- ## Actions
153
-
154
- ### describeImage
155
-
156
- Analyzes and generates descriptions for images.
157
-
158
- ```typescript
159
- // Example usage
160
- const result = await runtime.executeAction('DESCRIBE_IMAGE', {
161
- imageUrl: 'path/to/image.jpg',
162
- });
163
- ```
164
-
165
- ## Dependencies
166
-
167
- The plugin requires several peer dependencies:
168
-
169
- - `onnxruntime-node`: 1.20.1
170
- - `whatwg-url`: 7.1.0
171
-
172
- And trusted dependencies:
173
-
174
- - `onnxruntime-node`: 1.20.1
175
- - `sharp`: 0.33.5
176
-
177
- ## Safety & Security
178
-
179
- ### File Operations
180
-
181
- - **Path Sanitization**: All file paths are sanitized to prevent directory traversal attacks
182
- - **File Size Limits**: Enforced limits on upload sizes
183
- - **Type Checking**: Strict file type validation
184
- - **Temporary File Cleanup**: Automatic cleanup of temporary files
185
-
186
- ### API Keys & Credentials
187
-
188
- - **Environment Isolation**: Sensitive credentials are isolated in environment variables
189
- - **Access Scoping**: Services are initialized with minimum required permissions
190
- - **Key Rotation**: Support for credential rotation without service interruption
191
-
192
- ### Media Processing
193
-
194
- - **Resource Limits**: Memory and CPU usage limits for media processing
195
- - **Timeout Controls**: Automatic termination of long-running processes
196
- - **Format Validation**: Strict media format validation before processing
197
-
198
- ## Troubleshooting
30
+ ## Configuration
199
31
 
200
- ### Common Issues
32
+ The plugin uses the following environment variables:
201
33
 
202
- 1. **Service Initialization Failures**
34
+ - `CAPSOLVER_API_KEY` - API key for CAPTCHA solving service (optional)
203
35
 
204
- ```bash
205
- Error: Service initialization failed
206
- ```
207
-
208
- - Verify environment variables are properly set
209
- - Check service dependencies are installed
210
- - Ensure sufficient system permissions
211
-
212
- 2. **Media Processing Errors**
36
+ ## Services
213
37
 
214
- ```bash
215
- Error: Failed to process media file
216
- ```
38
+ ### BrowserService
217
39
 
218
- - Verify file format is supported
219
- - Check available system memory
220
- - Ensure ffmpeg is properly installed
40
+ Provides web browsing capabilities including:
41
+ - Page content extraction
42
+ - CAPTCHA detection and solving
43
+ - Alternative source fallbacks (Internet Archive, Google Search)
44
+ - Content caching for performance
221
45
 
222
- 3. **AWS S3 Connection Issues**
46
+ ## Development
223
47
 
224
48
  ```bash
225
- Error: AWS credentials not configured
226
- ```
49
+ # Install dependencies
50
+ npm install
227
51
 
228
- - Verify AWS credentials are set
229
- - Check S3 bucket permissions
230
- - Ensure correct region configuration
52
+ # Build the plugin
53
+ npm run build
231
54
 
232
- ### Debug Mode
55
+ # Development mode with watch
56
+ npm run dev
233
57
 
234
- Enable debug logging for detailed troubleshooting:
235
-
236
- ```typescript
237
- process.env.DEBUG = 'eliza:plugin-node:*';
58
+ # Format code
59
+ npm run format
238
60
  ```
239
61
 
240
- ### System Requirements
241
-
242
- - Node.js 16.x or higher
243
- - FFmpeg for media processing
244
- - Minimum 4GB RAM recommended
245
- - CUDA-compatible GPU (optional, for ML features)
246
-
247
- ### Performance Optimization
248
-
249
- 1. **Cache Management**
250
-
251
- - Regular cleanup of `content_cache` directory
252
- - Implement cache size limits
253
- - Monitor disk usage
254
-
255
- 2. **Memory Usage**
256
-
257
- - Configure max buffer sizes
258
- - Implement streaming for large files
259
- - Monitor memory consumption
260
-
261
- 3. **Concurrent Operations**
262
- - Adjust queue size limits
263
- - Configure worker threads
264
- - Monitor process pool
265
-
266
- ## Support
267
-
268
- For issues and feature requests, please:
269
-
270
- 1. Check the troubleshooting guide above
271
- 2. Review existing GitHub issues
272
- 3. Submit a new issue with:
273
- - System information
274
- - Error logs
275
- - Steps to reproduce
276
-
277
- ## Future Enhancements
278
-
279
- 1. **File Operations**
280
-
281
- - Enhanced streaming capabilities
282
- - Advanced compression options
283
- - Batch file processing
284
- - File type detection
285
- - Metadata management
286
- - Version control integration
287
-
288
- 2. **Media Processing**
289
-
290
- - Additional video formats
291
- - Advanced image processing
292
- - Audio enhancement tools
293
- - Real-time processing
294
- - Quality optimization
295
- - Format conversion
296
-
297
- 3. **Cloud Integration**
298
-
299
- - Multi-cloud support
300
- - Advanced caching
301
- - CDN optimization
302
- - Auto-scaling features
303
- - Cost optimization
304
- - Backup automation
305
-
306
- 4. **Speech Services**
307
-
308
- - Additional voice models
309
- - Language expansion
310
- - Emotion detection
311
- - Voice cloning
312
- - Real-time synthesis
313
- - Custom voice training
314
-
315
- 5. **Browser Automation**
316
-
317
- - Headless optimization
318
- - Parallel processing
319
- - Session management
320
- - Cookie handling
321
- - Proxy support
322
- - Resource optimization
323
-
324
- 6. **Security Features**
325
-
326
- - Enhanced encryption
327
- - Access control
328
- - Audit logging
329
- - Threat detection
330
- - Rate limiting
331
- - Compliance tools
332
-
333
- 7. **Performance Optimization**
334
-
335
- - Memory management
336
- - CPU utilization
337
- - Concurrent operations
338
- - Resource pooling
339
- - Cache strategies
340
- - Load balancing
341
-
342
- 8. **Developer Tools**
343
- - Enhanced debugging
344
- - Testing framework
345
- - Documentation generator
346
- - CLI improvements
347
- - Monitoring tools
348
- - Integration templates
349
-
350
- We welcome community feedback and contributions to help prioritize these enhancements.
351
-
352
- ## Contributing
353
-
354
- Contributions are welcome! Please see the [CONTRIBUTING.md](CONTRIBUTING.md) file for more information.
355
-
356
- ## Credits
357
-
358
- This plugin integrates with and builds upon several key technologies:
359
-
360
- - [Node.js](https://nodejs.org/) - The core runtime environment
361
- - [FFmpeg](https://ffmpeg.org/) - Media processing capabilities
362
- - [ElevenLabs](https://elevenlabs.io/) - Voice synthesis
363
- - [OpenAI](https://openai.com/) - Transcription and AI services
364
- - [AWS S3](https://aws.amazon.com/s3/) - Cloud storage
365
- - [Playwright](https://playwright.dev/) - Browser automation
366
- - [LLaMA](https://github.com/facebookresearch/llama) - Local language models
367
- - [VITS](https://github.com/jaywalnut310/vits) - Voice synthesis
368
- - [Deepgram](https://deepgram.com/) - Speech recognition
369
- - [Sharp](https://sharp.pixelplumbing.com/) - Image processing
370
-
371
- Special thanks to:
372
-
373
- - The Node.js community and all the open-source contributors who make these integrations possible.
374
- - The Eliza community for their contributions and feedback.
375
-
376
- For more information about Node.js capabilities:
377
-
378
- - [Node.js Documentation](https://nodejs.org/en/docs/)
379
- - [Node.js Developer Portal](https://nodejs.org/en/about/)
380
- - [Node.js GitHub Repository](https://github.com/nodejs/node)
381
-
382
62
  ## License
383
63
 
384
- This plugin is part of the Eliza project. See the main project repository for license information.
64
+ MIT
@@ -0,0 +1,5 @@
1
+ import { Plugin } from '@elizaos/core';
2
+
3
+ declare const browserPlugin: Plugin;
4
+
5
+ export { browserPlugin };
package/dist/index.js CHANGED
@@ -11,11 +11,11 @@ import {
11
11
  import CaptchaSolver from "capsolver-npm";
12
12
  import { chromium } from "patchright";
13
13
  async function generateSummary(runtime, text) {
14
- text = await trimTokens(text, 1e5, runtime);
14
+ const trimmedText = await trimTokens(text, 1e5, runtime);
15
15
  const prompt = `Please generate a concise summary for the following text:
16
16
 
17
17
  Text: """
18
- ${text}
18
+ ${trimmedText}
19
19
  """
20
20
 
21
21
  Respond with a JSON object in the following format:
@@ -166,6 +166,7 @@ var BrowserService = class _BrowserService extends Service {
166
166
  try {
167
167
  if (!this.context) {
168
168
  logger.log("Browser context not initialized. Call initializeBrowser() first.");
169
+ throw new Error("Browser context not initialized");
169
170
  }
170
171
  page = await this.context.newPage();
171
172
  await page.setExtraHTTPHeaders({
@@ -174,6 +175,7 @@ var BrowserService = class _BrowserService extends Service {
174
175
  const response = await page.goto(url, { waitUntil: "networkidle" });
175
176
  if (!response) {
176
177
  logger.error("Failed to load the page");
178
+ throw new Error("Failed to load the page");
177
179
  }
178
180
  if (response.status() === 403 || response.status() === 404) {
179
181
  return await this.tryAlternativeSources(url, runtime);
@@ -312,13 +314,13 @@ ${bodyContent}`
312
314
  } catch (error) {
313
315
  logger.error("Error fetching from Google Search:", error);
314
316
  logger.error("Failed to fetch content from alternative sources");
315
- return {
316
- title: url,
317
- description: "Error, could not fetch content from alternative sources",
318
- bodyContent: ""
319
- };
320
317
  }
321
318
  }
319
+ return {
320
+ title: url,
321
+ description: "Error, could not fetch content from alternative sources",
322
+ bodyContent: ""
323
+ };
322
324
  }
323
325
  };
324
326
 
@@ -327,7 +329,23 @@ var browserPlugin = {
327
329
  name: "browser-plugin",
328
330
  description: "Plugin for browser actions",
329
331
  services: [BrowserService],
330
- actions: []
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");
343
+ }
344
+ }
345
+ }
346
+ ]
347
+ }
348
+ ]
331
349
  };
332
350
  export {
333
351
  browserPlugin
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 type IBrowserService,\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/**\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 text = await trimTokens(text, 100000, runtime);\n\n const prompt = `Please generate a concise summary for the following text:\n\n Text: \"\"\"\n ${text}\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 and implements IBrowserService interface.\n * Provides methods for initializing browser, stopping browser, fetching page content, solving CAPTCHAs, detecting CAPTCHAs, and getting cache key.\n * @extends Service\n * @implements IBrowserService\n */\nexport class BrowserService extends Service implements IBrowserService {\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<any>(`${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 }\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 }\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<any>(`${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 return {\n title: url,\n description: 'Error, could not fetch content from alternative sources',\n bodyContent: '',\n };\n }\n }\n }\n}\n","import type { Plugin } 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};\n"],"mappings":"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","names":[]}
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":[]}
package/package.json CHANGED
@@ -1,13 +1,20 @@
1
1
  {
2
2
  "name": "@elizaos/plugin-browser",
3
- "version": "1.0.0-beta.8",
3
+ "description": "Plugin for browser actions and web scraping",
4
+ "version": "1.0.0",
4
5
  "type": "module",
5
6
  "main": "dist/index.js",
6
7
  "module": "dist/index.js",
7
8
  "types": "dist/index.d.ts",
9
+ "keywords": [
10
+ "plugin",
11
+ "elizaos",
12
+ "browser",
13
+ "web-scraping"
14
+ ],
8
15
  "repository": {
9
16
  "type": "git",
10
- "url": "https://github.com/elizaos-plugins/plugin-browser"
17
+ "url": ""
11
18
  },
12
19
  "exports": {
13
20
  "./package.json": "./package.json",
@@ -19,39 +26,37 @@
19
26
  }
20
27
  },
21
28
  "files": [
22
- "dist",
23
- "scripts",
24
- "package.json",
25
- "LICENSE",
26
- "tsup.config.ts"
29
+ "dist"
27
30
  ],
28
31
  "dependencies": {
29
- "@elizaos/core": "^1.0.0-beta.8",
32
+ "@elizaos/core": "^1.0.0",
33
+ "@elizaos/plugin-anthropic": "^1.0.0-beta.54",
34
+ "@elizaos/plugin-bootstrap": "^1.0.0-beta.76",
35
+ "@elizaos/plugin-knowledge": "^1.0.0-beta.78",
36
+ "@elizaos/plugin-openai": "^1.0.0-beta.74",
37
+ "@elizaos/plugin-telegram": "^1.0.0-beta.55",
38
+ "@elizaos/plugin-twitter": "^1.0.0-beta.57",
30
39
  "@types/uuid": "10.0.0",
31
40
  "capsolver-npm": "2.0.2",
32
41
  "fluent-ffmpeg": "2.1.3",
33
42
  "glob": "11.0.0",
34
43
  "patchright": "1.50.1",
35
- "uuid": "11.0.3"
44
+ "uuid": "11.0.3",
45
+ "zod": "3.25.23"
36
46
  },
37
47
  "devDependencies": {
38
- "@types/node": "22.8.4",
39
- "prettier": "3.5.3",
40
- "tsup": "8.4.0",
41
- "vitest": "^1.6.1",
42
- "zod": "^3.22.4"
48
+ "tsup": "8.5.0",
49
+ "typescript": "5.8.3",
50
+ "prettier": "3.5.3"
43
51
  },
44
52
  "scripts": {
45
- "build": "tsup",
46
53
  "dev": "tsup --watch",
47
- "postinstall": "node scripts/postinstall.js",
54
+ "build": "tsup",
48
55
  "lint": "prettier --write ./src",
49
- "clean": "rm -rf dist .turbo node_modules .turbo-tsconfig.json tsconfig.tsbuildinfo",
56
+ "test": "elizaos test",
50
57
  "format": "prettier --write ./src",
51
58
  "format:check": "prettier --check ./src",
52
- "test": "vitest run",
53
- "test:watch": "vitest",
54
- "test:coverage": "vitest run --coverage"
59
+ "clean": "rm -rf dist .turbo node_modules .turbo-tsconfig.json tsconfig.tsbuildinfo"
55
60
  },
56
61
  "peerDependencies": {
57
62
  "whatwg-url": "7.1.0"
@@ -59,5 +64,8 @@
59
64
  "publishConfig": {
60
65
  "access": "public"
61
66
  },
62
- "gitHead": "a84e25ee21e33387a1303e62a2f95dc670ffddd4"
67
+ "resolutions": {
68
+ "zod": "3.25.23"
69
+ },
70
+ "gitHead": "646c632924826e2b75c2304a75ee56959fe4a460"
63
71
  }
@@ -1,67 +0,0 @@
1
- import { execSync } from 'node:child_process';
2
- import fs from 'node:fs';
3
- import os from 'node:os';
4
-
5
- const platform = os.platform();
6
- const rel = os.release();
7
-
8
- if (platform !== 'linux') {
9
- console.log('Skipping [patchright] installation: non-Linux platform detected:', platform);
10
- process.exit(0);
11
- }
12
-
13
- function getDistroName() {
14
- try {
15
- const osReleaseContent = fs.readFileSync('/etc/os-release', 'utf8');
16
- const lines = osReleaseContent.split('\n');
17
- const info = {};
18
- for (const line of lines) {
19
- const [key, value] = line.split('=');
20
- if (key && value) {
21
- info[key.toLowerCase()] = value.replace(/"/g, '').toLowerCase().trim();
22
- }
23
- }
24
- return info.id || info.id_like || null;
25
- } catch (err) {
26
- console.error('Error reading /etc/os-release:', err.message);
27
- }
28
- return null;
29
- }
30
-
31
- const distro = getDistroName();
32
- console.log('Detected Linux distribution:', distro || 'unknown');
33
-
34
- const supportedDistros = [
35
- 'ubuntu',
36
- 'debian',
37
- 'pve',
38
- 'raspbian',
39
- 'pop',
40
- 'zorin',
41
- 'linuxmint',
42
- 'elementary',
43
- 'pureos',
44
- 'kali',
45
- ];
46
-
47
- if (!distro || !supportedDistros.some((name) => distro.includes(name))) {
48
- console.log(
49
- 'Skipping [patchright] installation on unsupported platform:',
50
- platform,
51
- rel,
52
- distro || 'unknown distro'
53
- );
54
- process.exit(0);
55
- }
56
-
57
- try {
58
- execSync('npx patchright install', {
59
- stdio: 'inherit',
60
- });
61
- } catch (err) {
62
- console.error(
63
- "Failed to install [patchright] you may need to install [patchright] deps with 'sudo npx patchright install-deps'. Error: ",
64
- err.message
65
- );
66
- process.exit(1);
67
- }
package/tsup.config.ts DELETED
@@ -1,23 +0,0 @@
1
- import { defineConfig } from 'tsup';
2
-
3
- export default defineConfig({
4
- entry: ['src/index.ts'],
5
- outDir: 'dist',
6
- tsconfig: './tsconfig.build.json', // Use build-specific tsconfig
7
- sourcemap: true,
8
- clean: true,
9
- format: ['esm'], // Ensure you're targeting CommonJS
10
- dts: false, // Skip DTS generation to avoid external import issues // Ensure you're targeting CommonJS
11
- external: [
12
- 'dotenv', // Externalize dotenv to prevent bundling
13
- 'fs', // Externalize fs to use Node.js built-in module
14
- 'path', // Externalize other built-ins if necessary
15
- '@reflink/reflink',
16
- 'https',
17
- 'http',
18
- 'agentkeepalive',
19
- 'zod',
20
- '@elizaos/core',
21
- // Add other modules you want to externalize
22
- ],
23
- });