fix: decouple sandbox resolution from browser breakpoints - #38

Open
ondraulehla wants to merge 1 commit into
e2b-dev:mainfrom
ondraulehla:fix/decouple-sandbox-resolution-from-breakpoints
Open

fix: decouple sandbox resolution from browser breakpoints#38
ondraulehla wants to merge 1 commit into
e2b-dev:mainfrom
ondraulehla:fix/decouple-sandbox-resolution-from-breakpoints

Conversation

@ondraulehla

@ondraulehlaondraulehla commented Jul 14, 2026

Copy link
Copy Markdown

Fixes#1

Problem

The sandbox resolution was derived directly from the VNC iframe wrapper's client size, with breakpoint-dependent fallbacks. On small breakpoints (mobile) the Linux desktop was therefore created at viewport-sized resolutions around 350x300. Linux is not usable at these sizes, and since the model receives raw screenshots of that desktop, the agent gets confused. This is exactly the behavior described in #1.

Fix

  • Add lib/resolution.ts with getSandboxResolution(): large viewports are scaled down proportionally into the existing MAX_RESOLUTION_* bounds (preserving the panel's aspect ratio), while viewports below MIN_RESOLUTION_* (i.e. mobile breakpoints) fall back to DEFAULT_RESOLUTION (1024x720) instead of shrinking the VM.
  • Use it on the client (app/page.tsx), replacing the two duplicated breakpoint-dependent measurement blocks in onSubmit and handleExampleClick.
  • Enforce it server-side in app/api/chat/route.ts before Sandbox.create, so the sandbox always gets a desktop-class resolution regardless of what the client sends.

Why no display or coordinate changes are needed

The E2B stream URL uses noVNC's resize=scale (the @e2b/desktop default), which scales the framebuffer down to fit the iframe while preserving the aspect ratio, and translates pointer coordinates itself. On mobile the full 1024x720 desktop is simply displayed smaller. Model actions are unaffected: screenshots and executed actions both use the raw sandbox coordinate space.

Verified with npm run build (Next.js production build passes) and numeric checks of the helper: [343,300] -> [1024,720], [1920,1080] -> [1024,576], [700,500] -> [700,500], invalid or missing input -> [1024,720].

The sandbox resolution was taken directly from the VNC iframe wrapper's
client size, so small breakpoints (e.g. mobile) created Linux desktops at
viewport-sized resolutions (~350x300), which the agent cannot operate
reliably (e2b-dev#1).
Introduce getSandboxResolution() which scales large viewports down
proportionally to the configured max bounds and falls back to
DEFAULT_RESOLUTION whenever the viewport is below the min bounds. The
helper is applied on the client when sending a message and enforced
server-side in the chat route before Sandbox.create, so the sandbox
always gets a desktop-class resolution regardless of the client.
The displayed stream still fits small screens: the E2B stream URL uses
noVNC's resize=scale, which shrinks the framebuffer to the container
while preserving aspect ratio and translating pointer coordinates.
Model coordinates are unaffected since screenshots and actions both use
the raw sandbox coordinate space.
Fixese2b-dev#1
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@cla-bot

cla-botBot commented Jul 14, 2026

Copy link
Copy Markdown

We require contributors to sign our Contributor License Agreement, and we don't have @ondraulehla on file. You can sign our CLA at https://e2b.dev/docs/cla . Once you've signed, post a comment here that says '@cla-bot check'

@vercel

vercelBot commented Jul 14, 2026

Copy link
Copy Markdown

@ondraulehla is attempting to deploy a commit to the E2B Team on Vercel.

A member of the Team first needs to authorize it.

@ondraulehla

Copy link
Copy Markdown
Author

@cla-bot check

@cla-bot

cla-botBot commented Jul 14, 2026

Copy link
Copy Markdown

The cla-bot has been summoned, and re-checked this pull request!

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fix agent confusion on small breakpoints

1 participant

@ondraulehla
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

fix: decouple sandbox resolution from browser breakpoints - #38

Open
ondraulehla wants to merge 1 commit into
e2b-dev:mainfrom
ondraulehla:fix/decouple-sandbox-resolution-from-breakpoints
Open

fix: decouple sandbox resolution from browser breakpoints#38
ondraulehla wants to merge 1 commit into
e2b-dev:mainfrom
ondraulehla:fix/decouple-sandbox-resolution-from-breakpoints

Conversation

@ondraulehla

@ondraulehlaondraulehla commented Jul 14, 2026

Copy link
Copy Markdown

Fixes#1

Problem

The sandbox resolution was derived directly from the VNC iframe wrapper's client size, with breakpoint-dependent fallbacks. On small breakpoints (mobile) the Linux desktop was therefore created at viewport-sized resolutions around 350x300. Linux is not usable at these sizes, and since the model receives raw screenshots of that desktop, the agent gets confused. This is exactly the behavior described in #1.

Fix

  • Add lib/resolution.ts with getSandboxResolution(): large viewports are scaled down proportionally into the existing MAX_RESOLUTION_* bounds (preserving the panel's aspect ratio), while viewports below MIN_RESOLUTION_* (i.e. mobile breakpoints) fall back to DEFAULT_RESOLUTION (1024x720) instead of shrinking the VM.
  • Use it on the client (app/page.tsx), replacing the two duplicated breakpoint-dependent measurement blocks in onSubmit and handleExampleClick.
  • Enforce it server-side in app/api/chat/route.ts before Sandbox.create, so the sandbox always gets a desktop-class resolution regardless of what the client sends.

Why no display or coordinate changes are needed

The E2B stream URL uses noVNC's resize=scale (the @e2b/desktop default), which scales the framebuffer down to fit the iframe while preserving the aspect ratio, and translates pointer coordinates itself. On mobile the full 1024x720 desktop is simply displayed smaller. Model actions are unaffected: screenshots and executed actions both use the raw sandbox coordinate space.

Verified with npm run build (Next.js production build passes) and numeric checks of the helper: [343,300] -> [1024,720], [1920,1080] -> [1024,576], [700,500] -> [700,500], invalid or missing input -> [1024,720].

The sandbox resolution was taken directly from the VNC iframe wrapper's
client size, so small breakpoints (e.g. mobile) created Linux desktops at
viewport-sized resolutions (~350x300), which the agent cannot operate
reliably (e2b-dev#1).
Introduce getSandboxResolution() which scales large viewports down
proportionally to the configured max bounds and falls back to
DEFAULT_RESOLUTION whenever the viewport is below the min bounds. The
helper is applied on the client when sending a message and enforced
server-side in the chat route before Sandbox.create, so the sandbox
always gets a desktop-class resolution regardless of the client.
The displayed stream still fits small screens: the E2B stream URL uses
noVNC's resize=scale, which shrinks the framebuffer to the container
while preserving aspect ratio and translating pointer coordinates.
Model coordinates are unaffected since screenshots and actions both use
the raw sandbox coordinate space.
Fixese2b-dev#1
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@cla-bot

cla-botBot commented Jul 14, 2026

Copy link
Copy Markdown

We require contributors to sign our Contributor License Agreement, and we don't have @ondraulehla on file. You can sign our CLA at https://e2b.dev/docs/cla . Once you've signed, post a comment here that says '@cla-bot check'

@vercel

vercelBot commented Jul 14, 2026

Copy link
Copy Markdown

@ondraulehla is attempting to deploy a commit to the E2B Team on Vercel.

A member of the Team first needs to authorize it.

@ondraulehla

Copy link
Copy Markdown
Author

@cla-bot check

@cla-bot

cla-botBot commented Jul 14, 2026

Copy link
Copy Markdown

The cla-bot has been summoned, and re-checked this pull request!

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fix agent confusion on small breakpoints

1 participant

@ondraulehla
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix: decouple sandbox resolution from browser breakpoints - #38

Open
ondraulehla wants to merge 1 commit into
e2b-dev:mainfrom
ondraulehla:fix/decouple-sandbox-resolution-from-breakpoints
Open

fix: decouple sandbox resolution from browser breakpoints#38
ondraulehla wants to merge 1 commit into
e2b-dev:mainfrom
ondraulehla:fix/decouple-sandbox-resolution-from-breakpoints

Conversation

@ondraulehla

@ondraulehlaondraulehla commented Jul 14, 2026

Copy link
Copy Markdown

Fixes#1

Problem

The sandbox resolution was derived directly from the VNC iframe wrapper's client size, with breakpoint-dependent fallbacks. On small breakpoints (mobile) the Linux desktop was therefore created at viewport-sized resolutions around 350x300. Linux is not usable at these sizes, and since the model receives raw screenshots of that desktop, the agent gets confused. This is exactly the behavior described in #1.

Fix

  • Add lib/resolution.ts with getSandboxResolution(): large viewports are scaled down proportionally into the existing MAX_RESOLUTION_* bounds (preserving the panel's aspect ratio), while viewports below MIN_RESOLUTION_* (i.e. mobile breakpoints) fall back to DEFAULT_RESOLUTION (1024x720) instead of shrinking the VM.
  • Use it on the client (app/page.tsx), replacing the two duplicated breakpoint-dependent measurement blocks in onSubmit and handleExampleClick.
  • Enforce it server-side in app/api/chat/route.ts before Sandbox.create, so the sandbox always gets a desktop-class resolution regardless of what the client sends.

Why no display or coordinate changes are needed

The E2B stream URL uses noVNC's resize=scale (the @e2b/desktop default), which scales the framebuffer down to fit the iframe while preserving the aspect ratio, and translates pointer coordinates itself. On mobile the full 1024x720 desktop is simply displayed smaller. Model actions are unaffected: screenshots and executed actions both use the raw sandbox coordinate space.

Verified with npm run build (Next.js production build passes) and numeric checks of the helper: [343,300] -> [1024,720], [1920,1080] -> [1024,576], [700,500] -> [700,500], invalid or missing input -> [1024,720].

The sandbox resolution was taken directly from the VNC iframe wrapper's
client size, so small breakpoints (e.g. mobile) created Linux desktops at
viewport-sized resolutions (~350x300), which the agent cannot operate
reliably (e2b-dev#1).
Introduce getSandboxResolution() which scales large viewports down
proportionally to the configured max bounds and falls back to
DEFAULT_RESOLUTION whenever the viewport is below the min bounds. The
helper is applied on the client when sending a message and enforced
server-side in the chat route before Sandbox.create, so the sandbox
always gets a desktop-class resolution regardless of the client.
The displayed stream still fits small screens: the E2B stream URL uses
noVNC's resize=scale, which shrinks the framebuffer to the container
while preserving aspect ratio and translating pointer coordinates.
Model coordinates are unaffected since screenshots and actions both use
the raw sandbox coordinate space.
Fixese2b-dev#1
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@cla-bot

cla-botBot commented Jul 14, 2026

Copy link
Copy Markdown

We require contributors to sign our Contributor License Agreement, and we don't have @ondraulehla on file. You can sign our CLA at https://e2b.dev/docs/cla . Once you've signed, post a comment here that says '@cla-bot check'

@vercel

vercelBot commented Jul 14, 2026

Copy link
Copy Markdown

@ondraulehla is attempting to deploy a commit to the E2B Team on Vercel.

A member of the Team first needs to authorize it.

@ondraulehla

Copy link
Copy Markdown
Author

@cla-bot check

@cla-bot

cla-botBot commented Jul 14, 2026

Copy link
Copy Markdown

The cla-bot has been summoned, and re-checked this pull request!

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fix agent confusion on small breakpoints

1 participant

@ondraulehla
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix: decouple sandbox resolution from browser breakpoints - #38

Open
ondraulehla wants to merge 1 commit into
e2b-dev:mainfrom
ondraulehla:fix/decouple-sandbox-resolution-from-breakpoints
Open

fix: decouple sandbox resolution from browser breakpoints#38
ondraulehla wants to merge 1 commit into
e2b-dev:mainfrom
ondraulehla:fix/decouple-sandbox-resolution-from-breakpoints

Conversation

@ondraulehla

@ondraulehlaondraulehla commented Jul 14, 2026

Copy link
Copy Markdown

Fixes#1

Problem

The sandbox resolution was derived directly from the VNC iframe wrapper's client size, with breakpoint-dependent fallbacks. On small breakpoints (mobile) the Linux desktop was therefore created at viewport-sized resolutions around 350x300. Linux is not usable at these sizes, and since the model receives raw screenshots of that desktop, the agent gets confused. This is exactly the behavior described in #1.

Fix

  • Add lib/resolution.ts with getSandboxResolution(): large viewports are scaled down proportionally into the existing MAX_RESOLUTION_* bounds (preserving the panel's aspect ratio), while viewports below MIN_RESOLUTION_* (i.e. mobile breakpoints) fall back to DEFAULT_RESOLUTION (1024x720) instead of shrinking the VM.
  • Use it on the client (app/page.tsx), replacing the two duplicated breakpoint-dependent measurement blocks in onSubmit and handleExampleClick.
  • Enforce it server-side in app/api/chat/route.ts before Sandbox.create, so the sandbox always gets a desktop-class resolution regardless of what the client sends.

Why no display or coordinate changes are needed

The E2B stream URL uses noVNC's resize=scale (the @e2b/desktop default), which scales the framebuffer down to fit the iframe while preserving the aspect ratio, and translates pointer coordinates itself. On mobile the full 1024x720 desktop is simply displayed smaller. Model actions are unaffected: screenshots and executed actions both use the raw sandbox coordinate space.

Verified with npm run build (Next.js production build passes) and numeric checks of the helper: [343,300] -> [1024,720], [1920,1080] -> [1024,576], [700,500] -> [700,500], invalid or missing input -> [1024,720].

The sandbox resolution was taken directly from the VNC iframe wrapper's
client size, so small breakpoints (e.g. mobile) created Linux desktops at
viewport-sized resolutions (~350x300), which the agent cannot operate
reliably (e2b-dev#1).
Introduce getSandboxResolution() which scales large viewports down
proportionally to the configured max bounds and falls back to
DEFAULT_RESOLUTION whenever the viewport is below the min bounds. The
helper is applied on the client when sending a message and enforced
server-side in the chat route before Sandbox.create, so the sandbox
always gets a desktop-class resolution regardless of the client.
The displayed stream still fits small screens: the E2B stream URL uses
noVNC's resize=scale, which shrinks the framebuffer to the container
while preserving aspect ratio and translating pointer coordinates.
Model coordinates are unaffected since screenshots and actions both use
the raw sandbox coordinate space.
Fixese2b-dev#1
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@cla-bot

cla-botBot commented Jul 14, 2026

Copy link
Copy Markdown

We require contributors to sign our Contributor License Agreement, and we don't have @ondraulehla on file. You can sign our CLA at https://e2b.dev/docs/cla . Once you've signed, post a comment here that says '@cla-bot check'

@vercel

vercelBot commented Jul 14, 2026

Copy link
Copy Markdown

@ondraulehla is attempting to deploy a commit to the E2B Team on Vercel.

A member of the Team first needs to authorize it.

@ondraulehla

Copy link
Copy Markdown
Author

@cla-bot check

@cla-bot

cla-botBot commented Jul 14, 2026

Copy link
Copy Markdown

The cla-bot has been summoned, and re-checked this pull request!

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fix agent confusion on small breakpoints

1 participant

@ondraulehla
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

fix: decouple sandbox resolution from browser breakpoints - #38

Open
ondraulehla wants to merge 1 commit into
e2b-dev:mainfrom
ondraulehla:fix/decouple-sandbox-resolution-from-breakpoints
Open

fix: decouple sandbox resolution from browser breakpoints#38
ondraulehla wants to merge 1 commit into
e2b-dev:mainfrom
ondraulehla:fix/decouple-sandbox-resolution-from-breakpoints

Conversation

@ondraulehla

@ondraulehlaondraulehla commented Jul 14, 2026

Copy link
Copy Markdown

Fixes#1

Problem

The sandbox resolution was derived directly from the VNC iframe wrapper's client size, with breakpoint-dependent fallbacks. On small breakpoints (mobile) the Linux desktop was therefore created at viewport-sized resolutions around 350x300. Linux is not usable at these sizes, and since the model receives raw screenshots of that desktop, the agent gets confused. This is exactly the behavior described in #1.

Fix

  • Add lib/resolution.ts with getSandboxResolution(): large viewports are scaled down proportionally into the existing MAX_RESOLUTION_* bounds (preserving the panel's aspect ratio), while viewports below MIN_RESOLUTION_* (i.e. mobile breakpoints) fall back to DEFAULT_RESOLUTION (1024x720) instead of shrinking the VM.
  • Use it on the client (app/page.tsx), replacing the two duplicated breakpoint-dependent measurement blocks in onSubmit and handleExampleClick.
  • Enforce it server-side in app/api/chat/route.ts before Sandbox.create, so the sandbox always gets a desktop-class resolution regardless of what the client sends.

Why no display or coordinate changes are needed

The E2B stream URL uses noVNC's resize=scale (the @e2b/desktop default), which scales the framebuffer down to fit the iframe while preserving the aspect ratio, and translates pointer coordinates itself. On mobile the full 1024x720 desktop is simply displayed smaller. Model actions are unaffected: screenshots and executed actions both use the raw sandbox coordinate space.

Verified with npm run build (Next.js production build passes) and numeric checks of the helper: [343,300] -> [1024,720], [1920,1080] -> [1024,576], [700,500] -> [700,500], invalid or missing input -> [1024,720].

The sandbox resolution was taken directly from the VNC iframe wrapper's
client size, so small breakpoints (e.g. mobile) created Linux desktops at
viewport-sized resolutions (~350x300), which the agent cannot operate
reliably (e2b-dev#1).
Introduce getSandboxResolution() which scales large viewports down
proportionally to the configured max bounds and falls back to
DEFAULT_RESOLUTION whenever the viewport is below the min bounds. The
helper is applied on the client when sending a message and enforced
server-side in the chat route before Sandbox.create, so the sandbox
always gets a desktop-class resolution regardless of the client.
The displayed stream still fits small screens: the E2B stream URL uses
noVNC's resize=scale, which shrinks the framebuffer to the container
while preserving aspect ratio and translating pointer coordinates.
Model coordinates are unaffected since screenshots and actions both use
the raw sandbox coordinate space.
Fixese2b-dev#1
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@cla-bot

cla-botBot commented Jul 14, 2026

Copy link
Copy Markdown

We require contributors to sign our Contributor License Agreement, and we don't have @ondraulehla on file. You can sign our CLA at https://e2b.dev/docs/cla . Once you've signed, post a comment here that says '@cla-bot check'

@vercel

vercelBot commented Jul 14, 2026

Copy link
Copy Markdown

@ondraulehla is attempting to deploy a commit to the E2B Team on Vercel.

A member of the Team first needs to authorize it.

@ondraulehla

Copy link
Copy Markdown
Author

@cla-bot check

@cla-bot

cla-botBot commented Jul 14, 2026

Copy link
Copy Markdown

The cla-bot has been summoned, and re-checked this pull request!

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fix agent confusion on small breakpoints

1 participant

@ondraulehla
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix: decouple sandbox resolution from browser breakpoints - #38

Open
ondraulehla wants to merge 1 commit into
e2b-dev:mainfrom
ondraulehla:fix/decouple-sandbox-resolution-from-breakpoints
Open

fix: decouple sandbox resolution from browser breakpoints#38
ondraulehla wants to merge 1 commit into
e2b-dev:mainfrom
ondraulehla:fix/decouple-sandbox-resolution-from-breakpoints

Conversation

@ondraulehla

@ondraulehlaondraulehla commented Jul 14, 2026

Copy link
Copy Markdown

Fixes#1

Problem

The sandbox resolution was derived directly from the VNC iframe wrapper's client size, with breakpoint-dependent fallbacks. On small breakpoints (mobile) the Linux desktop was therefore created at viewport-sized resolutions around 350x300. Linux is not usable at these sizes, and since the model receives raw screenshots of that desktop, the agent gets confused. This is exactly the behavior described in #1.

Fix

  • Add lib/resolution.ts with getSandboxResolution(): large viewports are scaled down proportionally into the existing MAX_RESOLUTION_* bounds (preserving the panel's aspect ratio), while viewports below MIN_RESOLUTION_* (i.e. mobile breakpoints) fall back to DEFAULT_RESOLUTION (1024x720) instead of shrinking the VM.
  • Use it on the client (app/page.tsx), replacing the two duplicated breakpoint-dependent measurement blocks in onSubmit and handleExampleClick.
  • Enforce it server-side in app/api/chat/route.ts before Sandbox.create, so the sandbox always gets a desktop-class resolution regardless of what the client sends.

Why no display or coordinate changes are needed

The E2B stream URL uses noVNC's resize=scale (the @e2b/desktop default), which scales the framebuffer down to fit the iframe while preserving the aspect ratio, and translates pointer coordinates itself. On mobile the full 1024x720 desktop is simply displayed smaller. Model actions are unaffected: screenshots and executed actions both use the raw sandbox coordinate space.

Verified with npm run build (Next.js production build passes) and numeric checks of the helper: [343,300] -> [1024,720], [1920,1080] -> [1024,576], [700,500] -> [700,500], invalid or missing input -> [1024,720].

The sandbox resolution was taken directly from the VNC iframe wrapper's
client size, so small breakpoints (e.g. mobile) created Linux desktops at
viewport-sized resolutions (~350x300), which the agent cannot operate
reliably (e2b-dev#1).
Introduce getSandboxResolution() which scales large viewports down
proportionally to the configured max bounds and falls back to
DEFAULT_RESOLUTION whenever the viewport is below the min bounds. The
helper is applied on the client when sending a message and enforced
server-side in the chat route before Sandbox.create, so the sandbox
always gets a desktop-class resolution regardless of the client.
The displayed stream still fits small screens: the E2B stream URL uses
noVNC's resize=scale, which shrinks the framebuffer to the container
while preserving aspect ratio and translating pointer coordinates.
Model coordinates are unaffected since screenshots and actions both use
the raw sandbox coordinate space.
Fixese2b-dev#1
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@cla-bot

cla-botBot commented Jul 14, 2026

Copy link
Copy Markdown

We require contributors to sign our Contributor License Agreement, and we don't have @ondraulehla on file. You can sign our CLA at https://e2b.dev/docs/cla . Once you've signed, post a comment here that says '@cla-bot check'

@vercel

vercelBot commented Jul 14, 2026

Copy link
Copy Markdown

@ondraulehla is attempting to deploy a commit to the E2B Team on Vercel.

A member of the Team first needs to authorize it.

@ondraulehla

Copy link
Copy Markdown
Author

@cla-bot check

@cla-bot

cla-botBot commented Jul 14, 2026

Copy link
Copy Markdown

The cla-bot has been summoned, and re-checked this pull request!

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fix agent confusion on small breakpoints

1 participant

@ondraulehla
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix: decouple sandbox resolution from browser breakpoints - #38

Open
ondraulehla wants to merge 1 commit into
e2b-dev:mainfrom
ondraulehla:fix/decouple-sandbox-resolution-from-breakpoints
Open

fix: decouple sandbox resolution from browser breakpoints#38
ondraulehla wants to merge 1 commit into
e2b-dev:mainfrom
ondraulehla:fix/decouple-sandbox-resolution-from-breakpoints

Conversation

@ondraulehla

@ondraulehlaondraulehla commented Jul 14, 2026

Copy link
Copy Markdown

Fixes#1

Problem

The sandbox resolution was derived directly from the VNC iframe wrapper's client size, with breakpoint-dependent fallbacks. On small breakpoints (mobile) the Linux desktop was therefore created at viewport-sized resolutions around 350x300. Linux is not usable at these sizes, and since the model receives raw screenshots of that desktop, the agent gets confused. This is exactly the behavior described in #1.

Fix

  • Add lib/resolution.ts with getSandboxResolution(): large viewports are scaled down proportionally into the existing MAX_RESOLUTION_* bounds (preserving the panel's aspect ratio), while viewports below MIN_RESOLUTION_* (i.e. mobile breakpoints) fall back to DEFAULT_RESOLUTION (1024x720) instead of shrinking the VM.
  • Use it on the client (app/page.tsx), replacing the two duplicated breakpoint-dependent measurement blocks in onSubmit and handleExampleClick.
  • Enforce it server-side in app/api/chat/route.ts before Sandbox.create, so the sandbox always gets a desktop-class resolution regardless of what the client sends.

Why no display or coordinate changes are needed

The E2B stream URL uses noVNC's resize=scale (the @e2b/desktop default), which scales the framebuffer down to fit the iframe while preserving the aspect ratio, and translates pointer coordinates itself. On mobile the full 1024x720 desktop is simply displayed smaller. Model actions are unaffected: screenshots and executed actions both use the raw sandbox coordinate space.

Verified with npm run build (Next.js production build passes) and numeric checks of the helper: [343,300] -> [1024,720], [1920,1080] -> [1024,576], [700,500] -> [700,500], invalid or missing input -> [1024,720].

The sandbox resolution was taken directly from the VNC iframe wrapper's
client size, so small breakpoints (e.g. mobile) created Linux desktops at
viewport-sized resolutions (~350x300), which the agent cannot operate
reliably (e2b-dev#1).
Introduce getSandboxResolution() which scales large viewports down
proportionally to the configured max bounds and falls back to
DEFAULT_RESOLUTION whenever the viewport is below the min bounds. The
helper is applied on the client when sending a message and enforced
server-side in the chat route before Sandbox.create, so the sandbox
always gets a desktop-class resolution regardless of the client.
The displayed stream still fits small screens: the E2B stream URL uses
noVNC's resize=scale, which shrinks the framebuffer to the container
while preserving aspect ratio and translating pointer coordinates.
Model coordinates are unaffected since screenshots and actions both use
the raw sandbox coordinate space.
Fixese2b-dev#1
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@cla-bot

cla-botBot commented Jul 14, 2026

Copy link
Copy Markdown

We require contributors to sign our Contributor License Agreement, and we don't have @ondraulehla on file. You can sign our CLA at https://e2b.dev/docs/cla . Once you've signed, post a comment here that says '@cla-bot check'

@vercel

vercelBot commented Jul 14, 2026

Copy link
Copy Markdown

@ondraulehla is attempting to deploy a commit to the E2B Team on Vercel.

A member of the Team first needs to authorize it.

@ondraulehla

Copy link
Copy Markdown
Author

@cla-bot check

@cla-bot

cla-botBot commented Jul 14, 2026

Copy link
Copy Markdown

The cla-bot has been summoned, and re-checked this pull request!

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fix agent confusion on small breakpoints

1 participant

@ondraulehla
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

fix: decouple sandbox resolution from browser breakpoints - #38

Open
ondraulehla wants to merge 1 commit into
e2b-dev:mainfrom
ondraulehla:fix/decouple-sandbox-resolution-from-breakpoints
Open

fix: decouple sandbox resolution from browser breakpoints#38
ondraulehla wants to merge 1 commit into
e2b-dev:mainfrom
ondraulehla:fix/decouple-sandbox-resolution-from-breakpoints

Conversation

@ondraulehla

@ondraulehlaondraulehla commented Jul 14, 2026

Copy link
Copy Markdown

Fixes#1

Problem

The sandbox resolution was derived directly from the VNC iframe wrapper's client size, with breakpoint-dependent fallbacks. On small breakpoints (mobile) the Linux desktop was therefore created at viewport-sized resolutions around 350x300. Linux is not usable at these sizes, and since the model receives raw screenshots of that desktop, the agent gets confused. This is exactly the behavior described in #1.

Fix

  • Add lib/resolution.ts with getSandboxResolution(): large viewports are scaled down proportionally into the existing MAX_RESOLUTION_* bounds (preserving the panel's aspect ratio), while viewports below MIN_RESOLUTION_* (i.e. mobile breakpoints) fall back to DEFAULT_RESOLUTION (1024x720) instead of shrinking the VM.
  • Use it on the client (app/page.tsx), replacing the two duplicated breakpoint-dependent measurement blocks in onSubmit and handleExampleClick.
  • Enforce it server-side in app/api/chat/route.ts before Sandbox.create, so the sandbox always gets a desktop-class resolution regardless of what the client sends.

Why no display or coordinate changes are needed

The E2B stream URL uses noVNC's resize=scale (the @e2b/desktop default), which scales the framebuffer down to fit the iframe while preserving the aspect ratio, and translates pointer coordinates itself. On mobile the full 1024x720 desktop is simply displayed smaller. Model actions are unaffected: screenshots and executed actions both use the raw sandbox coordinate space.

Verified with npm run build (Next.js production build passes) and numeric checks of the helper: [343,300] -> [1024,720], [1920,1080] -> [1024,576], [700,500] -> [700,500], invalid or missing input -> [1024,720].

The sandbox resolution was taken directly from the VNC iframe wrapper's
client size, so small breakpoints (e.g. mobile) created Linux desktops at
viewport-sized resolutions (~350x300), which the agent cannot operate
reliably (e2b-dev#1).
Introduce getSandboxResolution() which scales large viewports down
proportionally to the configured max bounds and falls back to
DEFAULT_RESOLUTION whenever the viewport is below the min bounds. The
helper is applied on the client when sending a message and enforced
server-side in the chat route before Sandbox.create, so the sandbox
always gets a desktop-class resolution regardless of the client.
The displayed stream still fits small screens: the E2B stream URL uses
noVNC's resize=scale, which shrinks the framebuffer to the container
while preserving aspect ratio and translating pointer coordinates.
Model coordinates are unaffected since screenshots and actions both use
the raw sandbox coordinate space.
Fixese2b-dev#1
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@cla-bot

cla-botBot commented Jul 14, 2026

Copy link
Copy Markdown

We require contributors to sign our Contributor License Agreement, and we don't have @ondraulehla on file. You can sign our CLA at https://e2b.dev/docs/cla . Once you've signed, post a comment here that says '@cla-bot check'

@vercel

vercelBot commented Jul 14, 2026

Copy link
Copy Markdown

@ondraulehla is attempting to deploy a commit to the E2B Team on Vercel.

A member of the Team first needs to authorize it.

@ondraulehla

Copy link
Copy Markdown
Author

@cla-bot check

@cla-bot

cla-botBot commented Jul 14, 2026

Copy link
Copy Markdown

The cla-bot has been summoned, and re-checked this pull request!

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fix agent confusion on small breakpoints

1 participant

@ondraulehla