@minded-ai/mindedjs 1.0.0-ec2-beta-5 → 1.0.0-ec2-beta-6
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.
|
@@ -22,6 +22,7 @@ from browser_use.llm import ChatOpenAI
|
|
|
22
22
|
import os
|
|
23
23
|
import sys
|
|
24
24
|
import logging
|
|
25
|
+
import base64
|
|
25
26
|
from datetime import datetime
|
|
26
27
|
from pathlib import Path
|
|
27
28
|
from dotenv import load_dotenv
|
|
@@ -104,17 +105,47 @@ class ScreenshotCapture:
|
|
|
104
105
|
self.step_counter += 1
|
|
105
106
|
|
|
106
107
|
# Take screenshot - browser-use takes viewport by default
|
|
107
|
-
|
|
108
|
+
screenshot_data = await page.screenshot()
|
|
109
|
+
|
|
110
|
+
# Ensure we have bytes - browser-use might return different format
|
|
111
|
+
if isinstance(screenshot_data, bytes):
|
|
112
|
+
screenshot_bytes = screenshot_data
|
|
113
|
+
elif isinstance(screenshot_data, str):
|
|
114
|
+
# If it's base64 encoded string
|
|
115
|
+
screenshot_bytes = base64.b64decode(screenshot_data)
|
|
116
|
+
else:
|
|
117
|
+
# Try to get bytes from whatever format it is
|
|
118
|
+
screenshot_bytes = bytes(screenshot_data)
|
|
119
|
+
|
|
120
|
+
logger.debug(f"Screenshot data type: {type(screenshot_data)}, size: {len(screenshot_bytes)} bytes")
|
|
108
121
|
|
|
109
122
|
# Generate filename with metadata
|
|
110
123
|
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S_%f")[:-3]
|
|
111
124
|
filename = f"{self.session_id}/step_{step_number:04d}_{timestamp}.png"
|
|
112
125
|
|
|
126
|
+
# Optional: Save to temp file for debugging (like Lambda does)
|
|
127
|
+
if os.getenv('DEBUG_SCREENSHOTS') == 'true':
|
|
128
|
+
temp_dir = Path("/tmp/screenshots")
|
|
129
|
+
temp_dir.mkdir(exist_ok=True, parents=True)
|
|
130
|
+
temp_path = temp_dir / f"step_{step_number:04d}_{timestamp}.png"
|
|
131
|
+
with open(temp_path, "wb") as f:
|
|
132
|
+
f.write(screenshot_bytes)
|
|
133
|
+
logger.debug(f"💾 Debug: Saved screenshot to: {temp_path}")
|
|
134
|
+
|
|
113
135
|
# Upload to S3
|
|
114
136
|
s3_key = f"{self.s3_prefix}{filename}"
|
|
115
137
|
|
|
116
138
|
try:
|
|
117
|
-
#
|
|
139
|
+
# Verify we have valid PNG data before uploading
|
|
140
|
+
if not screenshot_bytes or len(screenshot_bytes) == 0:
|
|
141
|
+
logger.error(f"❌ Screenshot bytes are empty!")
|
|
142
|
+
return
|
|
143
|
+
|
|
144
|
+
# Check for PNG header (89 50 4E 47 = PNG signature)
|
|
145
|
+
if len(screenshot_bytes) > 4 and screenshot_bytes[:4] != b'\x89PNG':
|
|
146
|
+
logger.warning(f"⚠️ Screenshot may not be valid PNG format. First 4 bytes: {screenshot_bytes[:4].hex()}")
|
|
147
|
+
|
|
148
|
+
# Upload with KMS encryption if required by bucket (matching Lambda implementation)
|
|
118
149
|
self.s3_client.put_object(
|
|
119
150
|
Bucket=self.s3_bucket,
|
|
120
151
|
Key=s3_key,
|
|
@@ -122,10 +153,11 @@ class ScreenshotCapture:
|
|
|
122
153
|
ContentType='image/png',
|
|
123
154
|
ServerSideEncryption='aws:kms',
|
|
124
155
|
Tagging='retention=30d'
|
|
156
|
+
# Using bucket's default KMS key
|
|
125
157
|
)
|
|
126
158
|
|
|
127
159
|
s3_url = f"s3://{self.s3_bucket}/{s3_key}"
|
|
128
|
-
logger.info(f"✅ Screenshot uploaded: {s3_url}")
|
|
160
|
+
logger.info(f"✅ Screenshot uploaded: {s3_url} (size: {len(screenshot_bytes)} bytes)")
|
|
129
161
|
|
|
130
162
|
except self.ClientError as e:
|
|
131
163
|
logger.error(f"❌ Failed to upload screenshot to S3: {str(e)}")
|
package/package.json
CHANGED
|
@@ -22,6 +22,7 @@ from browser_use.llm import ChatOpenAI
|
|
|
22
22
|
import os
|
|
23
23
|
import sys
|
|
24
24
|
import logging
|
|
25
|
+
import base64
|
|
25
26
|
from datetime import datetime
|
|
26
27
|
from pathlib import Path
|
|
27
28
|
from dotenv import load_dotenv
|
|
@@ -104,17 +105,47 @@ class ScreenshotCapture:
|
|
|
104
105
|
self.step_counter += 1
|
|
105
106
|
|
|
106
107
|
# Take screenshot - browser-use takes viewport by default
|
|
107
|
-
|
|
108
|
+
screenshot_data = await page.screenshot()
|
|
109
|
+
|
|
110
|
+
# Ensure we have bytes - browser-use might return different format
|
|
111
|
+
if isinstance(screenshot_data, bytes):
|
|
112
|
+
screenshot_bytes = screenshot_data
|
|
113
|
+
elif isinstance(screenshot_data, str):
|
|
114
|
+
# If it's base64 encoded string
|
|
115
|
+
screenshot_bytes = base64.b64decode(screenshot_data)
|
|
116
|
+
else:
|
|
117
|
+
# Try to get bytes from whatever format it is
|
|
118
|
+
screenshot_bytes = bytes(screenshot_data)
|
|
119
|
+
|
|
120
|
+
logger.debug(f"Screenshot data type: {type(screenshot_data)}, size: {len(screenshot_bytes)} bytes")
|
|
108
121
|
|
|
109
122
|
# Generate filename with metadata
|
|
110
123
|
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S_%f")[:-3]
|
|
111
124
|
filename = f"{self.session_id}/step_{step_number:04d}_{timestamp}.png"
|
|
112
125
|
|
|
126
|
+
# Optional: Save to temp file for debugging (like Lambda does)
|
|
127
|
+
if os.getenv('DEBUG_SCREENSHOTS') == 'true':
|
|
128
|
+
temp_dir = Path("/tmp/screenshots")
|
|
129
|
+
temp_dir.mkdir(exist_ok=True, parents=True)
|
|
130
|
+
temp_path = temp_dir / f"step_{step_number:04d}_{timestamp}.png"
|
|
131
|
+
with open(temp_path, "wb") as f:
|
|
132
|
+
f.write(screenshot_bytes)
|
|
133
|
+
logger.debug(f"💾 Debug: Saved screenshot to: {temp_path}")
|
|
134
|
+
|
|
113
135
|
# Upload to S3
|
|
114
136
|
s3_key = f"{self.s3_prefix}{filename}"
|
|
115
137
|
|
|
116
138
|
try:
|
|
117
|
-
#
|
|
139
|
+
# Verify we have valid PNG data before uploading
|
|
140
|
+
if not screenshot_bytes or len(screenshot_bytes) == 0:
|
|
141
|
+
logger.error(f"❌ Screenshot bytes are empty!")
|
|
142
|
+
return
|
|
143
|
+
|
|
144
|
+
# Check for PNG header (89 50 4E 47 = PNG signature)
|
|
145
|
+
if len(screenshot_bytes) > 4 and screenshot_bytes[:4] != b'\x89PNG':
|
|
146
|
+
logger.warning(f"⚠️ Screenshot may not be valid PNG format. First 4 bytes: {screenshot_bytes[:4].hex()}")
|
|
147
|
+
|
|
148
|
+
# Upload with KMS encryption if required by bucket (matching Lambda implementation)
|
|
118
149
|
self.s3_client.put_object(
|
|
119
150
|
Bucket=self.s3_bucket,
|
|
120
151
|
Key=s3_key,
|
|
@@ -122,10 +153,11 @@ class ScreenshotCapture:
|
|
|
122
153
|
ContentType='image/png',
|
|
123
154
|
ServerSideEncryption='aws:kms',
|
|
124
155
|
Tagging='retention=30d'
|
|
156
|
+
# Using bucket's default KMS key
|
|
125
157
|
)
|
|
126
158
|
|
|
127
159
|
s3_url = f"s3://{self.s3_bucket}/{s3_key}"
|
|
128
|
-
logger.info(f"✅ Screenshot uploaded: {s3_url}")
|
|
160
|
+
logger.info(f"✅ Screenshot uploaded: {s3_url} (size: {len(screenshot_bytes)} bytes)")
|
|
129
161
|
|
|
130
162
|
except self.ClientError as e:
|
|
131
163
|
logger.error(f"❌ Failed to upload screenshot to S3: {str(e)}")
|