@testdriverai/runner 7.9.100-test → 7.9.102-test

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.
@@ -40,16 +40,16 @@ function getLocalVersion() {
40
40
 
41
41
  /**
42
42
  * Upload a screenshot to S3 via presigned URL from the API
43
- *
43
+ *
44
44
  * @param {string} apiRoot - API base URL
45
45
  * @param {string} apiKey - Team API key
46
46
  * @param {string} sandboxId - Sandbox ID
47
- * @param {string} base64 - Base64-encoded image data
47
+ * @param {string|Buffer} payload - PNG bytes as a Buffer (preferred) or base64 string
48
48
  * @param {string} label - Label for the screenshot (e.g., 'screenshot', 'before', 'after')
49
49
  * @returns {Promise<{ s3Key: string, fileName: string } | null>}
50
50
  */
51
- async function uploadToS3(apiRoot, apiKey, sandboxId, base64, label = 'screenshot') {
52
- if (!base64 || !apiRoot || !apiKey) return null;
51
+ async function uploadToS3(apiRoot, apiKey, sandboxId, payload, label = 'screenshot') {
52
+ if (!payload || !apiRoot || !apiKey) return null;
53
53
 
54
54
  try {
55
55
  const fileName = `${label}-${Date.now()}.png`;
@@ -68,8 +68,10 @@ async function uploadToS3(apiRoot, apiKey, sandboxId, base64, label = 'screensho
68
68
  return null;
69
69
  }
70
70
 
71
- // Upload to S3 via presigned URL
72
- const pngBuffer = Buffer.from(base64, 'base64');
71
+ // Upload to S3 via presigned URL. Accept either a Buffer (no decode) or
72
+ // a base64 string (legacy callers) — Buffer is preferred to avoid the
73
+ // wasteful PNG → base64 → PNG round-trip.
74
+ const pngBuffer = Buffer.isBuffer(payload) ? payload : Buffer.from(payload, 'base64');
73
75
  const url = new URL(uploadUrlResponse.uploadUrl);
74
76
  const transport = url.protocol === 'https:' ? https : http;
75
77
 
package/lib/automation.js CHANGED
@@ -591,19 +591,20 @@ class Automation extends EventEmitter {
591
591
  // For extract/remember: capture screenshot, upload to S3, return s3Key
592
592
  // SDK will then call API with the s3Key
593
593
  // For system.screenshot (normalized to 'screenshot'): same flow (return s3Key instead of base64)
594
-
595
- // Capture screenshot locally
594
+
595
+ // Capture screenshot locally — buffer variant avoids an unnecessary
596
+ // round-trip through base64 (PNG buffer → base64 → PNG buffer) that
597
+ // doubles peak memory and adds ~10–30 ms of pure encoding cost on
598
+ // large screenshots.
596
599
  console.log('[automation] Step 1: Capturing screenshot...');
597
- const screenshot = await this._captureScreenshot();
598
- console.log(`[automation] Step 2: Screenshot captured, size: ${screenshot.length} bytes (base64)`);
599
- const buffer = Buffer.from(screenshot, 'base64');
600
- console.log(`[automation] Step 3: Buffer created, size: ${buffer.length} bytes`);
600
+ const buffer = await this._captureScreenshotBuffer();
601
+ console.log(`[automation] Step 2: Screenshot captured, size: ${buffer.length} bytes`);
601
602
 
602
603
  // Upload screenshot to S3 and return key
603
- console.log('[automation] Step 4: Uploading to S3...');
604
+ console.log('[automation] Step 3: Uploading to S3...');
604
605
  const s3Key = await this._uploadToS3(buffer, this._sandboxId, 'image/png');
605
- console.log(`[automation] Step 5: Upload complete, s3Key: ${s3Key}`);
606
-
606
+ console.log(`[automation] Step 4: Upload complete, s3Key: ${s3Key}`);
607
+
607
608
  return { s3Key };
608
609
  }
609
610
 
@@ -668,7 +669,15 @@ class Automation extends EventEmitter {
668
669
 
669
670
  // ── Screenshot (highest quality PNG, via pyautogui → temp file → sharp) ──
670
671
 
671
- async _captureScreenshot() {
672
+ /**
673
+ * Capture a screenshot and return the raw PNG buffer.
674
+ *
675
+ * Prefer this when the next consumer of the bytes is binary (e.g. an HTTP
676
+ * PUT to S3): it avoids the wasteful PNG → base64 → PNG round-trip that
677
+ * `_captureScreenshot()` does for backwards compatibility with callers
678
+ * that still expect a base64 string.
679
+ */
680
+ async _captureScreenshotBuffer() {
672
681
  const sharp = require('sharp');
673
682
  const maxAttempts = 3;
674
683
 
@@ -726,8 +735,7 @@ class Automation extends EventEmitter {
726
735
  }
727
736
  }
728
737
 
729
- const buffer = await image.png({ compressionLevel: 0 }).toBuffer();
730
- return buffer.toString('base64');
738
+ return await image.png({ compressionLevel: 0 }).toBuffer();
731
739
  } finally {
732
740
  // Clean up temp file
733
741
  try { fs.unlinkSync(tmpFile); } catch {}
@@ -735,6 +743,14 @@ class Automation extends EventEmitter {
735
743
  }
736
744
  }
737
745
 
746
+ async _captureScreenshot() {
747
+ // Kept for backwards compatibility with callers (e.g. Ably channel
748
+ // messages) that still want a base64 string. New code paths should
749
+ // prefer `_captureScreenshotBuffer()` to avoid the round-trip.
750
+ const buffer = await this._captureScreenshotBuffer();
751
+ return buffer.toString('base64');
752
+ }
753
+
738
754
  // ── Focus window (platform-specific) ───────────────────────────────
739
755
 
740
756
  async _focusWindow(data) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@testdriverai/runner",
3
- "version": "7.9.100-test",
3
+ "version": "7.9.102-test",
4
4
  "description": "TestDriver Runner - Ably-based remote automation agent with Node.js automation",
5
5
  "main": "index.js",
6
6
  "bin": {