"""Demo mode helper for injecting and updating the in-browser log panel."""
from __future__ import annotations
import asyncio
import json
import logging
from datetime import datetime, timezone
from typing import Any
from browser_use.browser.session import BrowserSession
# Embedded JavaScript for demo panel (injected into browser pages)
_DEMO_PANEL_SCRIPT = r"""(function () {
// SESSION_ID_PLACEHOLDER will be replaced by DemoMode with actual session ID
const SESSION_ID = '__BROWSER_USE_SESSION_ID_PLACEHOLDER__';
const EXCLUDE_ATTR = 'data-browser-use-exclude-' + SESSION_ID;
const PANEL_ID = 'browser-use-demo-panel';
const STYLE_ID = 'browser-use-demo-panel-style';
const STORAGE_KEY = '__browserUseDemoLogs__';
const STORAGE_HTML_KEY = '__browserUseDemoLogsHTML__';
const PANEL_STATE_KEY = '__browserUseDemoPanelState__';
const TOGGLE_BUTTON_ID = 'browser-use-demo-toggle';
const MAX_MESSAGES = 100;
const EXPANDED_IDS_KEY = '__browserUseExpandedEntries__';
const LEVEL_ICONS = {
info: 'âšī¸',
action: 'âļī¸',
thought: 'đ',
success: 'â
',
warning: 'â ī¸',
error: 'â',
};
const LEVEL_LABELS = {
info: 'info',
action: 'action',
thought: 'thought',
success: 'success',
warning: 'warning',
error: 'error',
};
if (window.__browserUseDemoPanelLoaded) {
const existingPanel = document.getElementById(PANEL_ID);
if (!existingPanel) {
initializePanel();
}
return;
}
window.__browserUseDemoPanelLoaded = true;
const state = {
panel: null,
list: null,
messages: [],
isOpen: true,
toggleButton: null,
};
state.messages = restoreMessages();
function initializePanel() {
console.log('Browser-use demo panel initialized with session ID:', SESSION_ID);
addStyles();
state.isOpen = loadPanelState();
state.panel = buildPanel();
state.list = state.panel.querySelector('[data-role="log-list"]');
appendToHost(state.panel);
state.toggleButton = buildToggleButton();
appendToHost(state.toggleButton);
const savedWidth = loadPanelWidth();
if (savedWidth) {
document.documentElement.style.setProperty('--browser-use-demo-panel-width', `${savedWidth}px`);
}
if (!hydrateFromStoredMarkup()) {
state.messages.forEach((entry) => appendEntry(entry, false));
}
attachCloseHandler();
if (state.isOpen) {
openPanel(false);
} else {
closePanel(false);
}
adjustLayout();
window.addEventListener('resize', debounce(adjustLayout, 150));
}
function appendToHost(node) {
if (!node) {
return;
}
const host = document.body || document.documentElement;
if (!host.contains(node)) {
host.appendChild(node);
}
if (!document.body) {
document.addEventListener(
'DOMContentLoaded',
() => {
if (document.body && node.parentNode !== document.body) {
document.body.appendChild(node);
}
},
{ once: true }
);
}
}
function addStyles() {
if (document.getElementById(STYLE_ID)) {
return;
}
const style = document.createElement('style');
style.id = STYLE_ID;
style.setAttribute(EXCLUDE_ATTR, 'true');
style.textContent = `
#${PANEL_ID} {
position: fixed;
top: 0;
right: 0;
width: var(--browser-use-demo-panel-width, 340px);
max-width: calc(100vw - 64px);
height: 100vh;
display: flex;
flex-direction: column;
background: #05070d;
color: #f8f9ff;
font-family: 'JetBrains Mono', 'Fira Code', 'Monaco', 'Menlo', monospace;
font-size: 13px;
line-height: 1.4;
box-shadow: -6px 0 25px rgba(0, 0, 0, 0.35);
z-index: 2147480000;
border-left: 1px solid rgba(255, 255, 255, 0.14);
backdrop-filter: blur(10px);
pointer-events: auto;
transform: translateX(0);
opacity: 1;
transition: transform 0.25s ease, opacity 0.25s ease;
}
#${PANEL_ID}[data-open="false"] {
transform: translateX(110%);
opacity: 0;
pointer-events: none;
}
#${PANEL_ID} .browser-use-demo-header {
padding: 16px 18px 12px;
border-bottom: 1px solid rgba(255, 255, 255, 0.14);
display: flex;
align-items: baseline;
justify-content: space-between;
gap: 8px;
flex-wrap: wrap;
}
#${PANEL_ID} .browser-use-demo-header h1 {
font-size: 15px;
text-transform: uppercase;
letter-spacing: 0.12em;
margin: 0;
color: #f8f9ff;
}
#${PANEL_ID} .browser-use-badge {
font-size: 11px;
padding: 2px 10px;
border-radius: 999px;
border: 1px solid rgba(255, 255, 255, 0.4);
text-transform: uppercase;
letter-spacing: 0.08em;
color: #f8f9ff;
}
#${PANEL_ID} .browser-use-logo img {
height: 36px;
}
#${PANEL_ID} .browser-use-header-actions {
margin-left: auto;
display: flex;
align-items: center;
gap: 8px;
}
#${PANEL_ID} .browser-use-close-btn {
width: 28px;
height: 28px;
border-radius: 50%;
border: 1px solid rgba(255, 255, 255, 0.2);
background: rgba(255, 255, 255, 0.05);
color: #f8f9ff;
cursor: pointer;
font-size: 16px;
line-height: 1;
display: flex;
align-items: center;
justify-content: center;
transition: background 0.2s ease, border 0.2s ease;
}
#${PANEL_ID} .browser-use-close-btn:hover {
background: rgba(255, 255, 255, 0.15);
border-color: rgba(255, 255, 255, 0.35);
}
#${PANEL_ID} .browser-use-demo-body {
flex: 1;
overflow-y: auto;
scrollbar-width: thin;
scrollbar-color: rgba(255, 255, 255, 0.3) transparent;
padding: 8px 0 12px;
}
#${PANEL_ID} .browser-use-demo-body::-webkit-scrollbar {
width: 8px;
}
#${PANEL_ID} .browser-use-demo-body::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.25);
border-radius: 999px;
}
.browser-use-demo-entry {
display: flex;
gap: 12px;
padding: 10px 18px;
border-left: 2px solid transparent;
border-bottom: 1px solid rgba(255, 255, 255, 0.04);
animation: browser-use-fade-in 0.25s ease;
background: #000000;
}
.browser-use-demo-entry:last-child {
border-bottom-color: transparent;
}
.browser-use-entry-icon {
font-size: 16px;
line-height: 1.2;
width: 20px;
}
.browser-use-entry-content {
flex: 1;
min-width: 0;
}
.browser-use-entry-meta {
font-size: 11px;
letter-spacing: 0.08em;
text-transform: uppercase;
color: white;
margin-bottom: 4px;
display: flex;
justify-content: space-between;
gap: 12px;
}
.browser-use-entry-message {
margin: 0;
word-break: break-word;
font-size: 12px;
color: #f8f9ff;
display: flex;
flex-direction: column;
gap: 6px;
}
.browser-use-markdown-content {
margin: 0;
line-height: 1.5;
}
.browser-use-markdown-content p {
margin: 0 0 8px 0;
}
.browser-use-markdown-content p:last-child {
margin-bottom: 0;
}
.browser-use-markdown-content h1,
.browser-use-markdown-content h2,
.browser-use-markdown-content h3 {
margin: 8px 0 4px 0;
font-weight: 600;
color: #f8f9ff;
}
.browser-use-markdown-content h1 {
font-size: 16px;
}
.browser-use-markdown-content h2 {
font-size: 14px;
}
.browser-use-markdown-content h3 {
font-size: 13px;
}
.browser-use-markdown-content code {
background: rgba(255, 255, 255, 0.1);
padding: 2px 6px;
border-radius: 3px;
font-family: 'JetBrains Mono', 'Fira Code', 'Monaco', 'Menlo', monospace;
font-size: 11px;
color: #60a5fa;
}
.browser-use-markdown-content pre {
background: rgba(0, 0, 0, 0.3);
padding: 8px 12px;
border-radius: 4px;
overflow-x: auto;
margin: 8px 0;
border: 1px solid rgba(255, 255, 255, 0.1);
}
.browser-use-markdown-content pre code {
background: transparent;
padding: 0;
color: #f8f9ff;
font-size: 11px;
white-space: pre;
}
.browser-use-markdown-content ul,
.browser-use-markdown-content ol {
margin: 4px 0 4px 16px;
padding: 0;
}
.browser-use-markdown-content li {
margin: 2px 0;
}
.browser-use-markdown-content a {
color: #60a5fa;
text-decoration: underline;
}
.browser-use-markdown-content a:hover {
color: #93c5fd;
}
.browser-use-markdown-content strong {
font-weight: 600;
color: #f8f9ff;
}
.browser-use-markdown-content em {
font-style: italic;
}
.browser-use-demo-entry:not(.expanded) .browser-use-markdown-content {
max-height: 120px;
overflow: hidden;
mask-image: linear-gradient(to bottom, rgba(0,0,0,1), rgba(0,0,0,0));
}
.browser-use-entry-toggle {
align-self: flex-start;
background: rgba(255, 255, 255, 0.1);
border: 1px solid rgba(255, 255, 255, 0.2);
color: #f8f9ff;
padding: 2px 10px;
font-size: 11px;
border-radius: 999px;
cursor: pointer;
}
.browser-use-demo-entry.level-info { border-left-color: #60a5fa; }
.browser-use-demo-entry.level-action { border-left-color: #34d399; }
.browser-use-demo-entry.level-thought { border-left-color: #f97316; }
.browser-use-demo-entry.level-warning { border-left-color: #fbbf24; }
.browser-use-demo-entry.level-success { border-left-color: #22c55e; }
.browser-use-demo-entry.level-error { border-left-color: #f87171; }
@keyframes browser-use-fade-in {
from { opacity: 0; transform: translateY(6px); }
to { opacity: 1; transform: translateY(0); }
}
@media (max-width: 1024px) {
#${PANEL_ID} {
font-size: 12px;
}
#${PANEL_ID} .browser-use-demo-header {
padding: 12px 16px 10px;
}
}
#${TOGGLE_BUTTON_ID} {
position: fixed;
top: 20px;
right: 20px;
width: 44px;
height: 44px;
border-radius: 50%;
border: 1px solid rgba(255, 255, 255, 0.2);
background: rgba(5, 7, 13, 0.92);
color: #f8f9ff;
font-size: 18px;
display: none;
align-items: center;
justify-content: center;
cursor: pointer;
z-index: 2147480001;
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.4);
transition: transform 0.2s ease, background 0.2s ease;
}
#${TOGGLE_BUTTON_ID}:hover {
transform: scale(1.05);
background: rgba(5, 7, 13, 0.98);
}
#${TOGGLE_BUTTON_ID} img {
display: block;
width: 24px;
height: auto;
max-width: 100%;
max-height: 100%;
object-fit: contain;
pointer-events: none;
user-select: none;
}
`;
document.head.appendChild(style);
}
function buildPanel() {
const panel = document.createElement('section');
panel.id = PANEL_ID;
panel.setAttribute('role', 'complementary');
panel.setAttribute('aria-label', 'Browser-use demo panel');
panel.setAttribute(EXCLUDE_ATTR, 'true');
const header = document.createElement('header');
header.className = 'browser-use-demo-header';
const title = document.createElement('div');
title.className = 'browser-use-logo';
const logo = document.createElement('img');
logo.src = 'https://raw.githubusercontent.com/browser-use/browser-use/main/static/browser-use-dark.png';
logo.alt = 'Browser-use';
logo.loading = 'lazy';
title.appendChild(logo);
const actions = document.createElement('div');
actions.className = 'browser-use-header-actions';
const closeBtn = document.createElement('button');
closeBtn.type = 'button';
closeBtn.className = 'browser-use-close-btn';
closeBtn.setAttribute(EXCLUDE_ATTR, 'true');
closeBtn.setAttribute('aria-label', 'Hide demo panel');
closeBtn.dataset.role = 'close-toggle';
closeBtn.innerHTML = '×';
actions.appendChild(closeBtn);
header.appendChild(title);
header.appendChild(actions);
const body = document.createElement('div');
body.className = 'browser-use-demo-body';
body.setAttribute('data-role', 'log-list');
panel.appendChild(header);
panel.appendChild(body);
panel.setAttribute('data-open', 'true');
return panel;
}
function buildToggleButton() {
const button = document.createElement('button');
button.id = TOGGLE_BUTTON_ID;
button.type = 'button';
button.setAttribute(EXCLUDE_ATTR, 'true');
button.setAttribute('aria-label', 'Open demo panel');
const img = document.createElement('img');
img.alt = 'Browser-use';
img.loading = 'eager';
// Use embedded SVG as data URI to avoid CSP issues
const logoSvg = '';
img.src = 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(logoSvg);
button.appendChild(img);
button.addEventListener('click', () => openPanel(true));
return button;
}
function attachCloseHandler() {
const closeBtn = state.panel?.querySelector('[data-role="close-toggle"]');
if (closeBtn) {
closeBtn.addEventListener('click', () => closePanel(true));
}
}
function openPanel(saveState = true) {
state.isOpen = true;
if (state.panel) {
state.panel.setAttribute('data-open', 'true');
}
if (state.toggleButton) {
state.toggleButton.style.display = 'none';
}
adjustLayout();
if (saveState) {
persistPanelState();
}
}
function closePanel(saveState = true) {
state.isOpen = false;
if (state.panel) {
state.panel.setAttribute('data-open', 'false');
}
document.body.style.marginRight = '';
if (state.toggleButton) {
state.toggleButton.style.display = 'flex';
}
if (saveState) {
persistPanelState();
}
}
function persistPanelState() {
try {
sessionStorage.setItem(PANEL_STATE_KEY, state.isOpen ? 'open' : 'closed');
} catch (err) {
// Ignore storage errors
}
}
function loadPanelState() {
try {
const stored = sessionStorage.getItem(PANEL_STATE_KEY);
if (!stored) return true;
return stored === 'open';
} catch (err) {
return true;
}
}
function adjustLayout() {
const width = computePanelWidth();
document.documentElement.style.setProperty('--browser-use-demo-panel-width', `${width}px`);
if (state.isOpen) {
document.body.style.marginRight = `${width + 16}px`;
if (state.toggleButton) {
state.toggleButton.style.display = 'none';
}
} else {
document.body.style.marginRight = '';
if (state.toggleButton) {
state.toggleButton.style.display = 'flex';
}
}
}
function computePanelWidth() {
const viewport = Math.max(window.innerWidth, 320);
const maxAvailable = Math.max(220, viewport - 240);
const target = Math.min(380, Math.max(260, viewport * 0.3));
const width = Math.max(220, Math.min(target, maxAvailable));
try {
sessionStorage.setItem('__browserUsePanelWidth__', String(width));
} catch {
// fallthrough
}
return width;
}
function loadPanelWidth() {
try {
const saved = sessionStorage.getItem('__browserUsePanelWidth__');
return saved ? Number(saved) : null;
} catch {
return null;
}
}
function restoreMessages() {
try {
const raw = sessionStorage.getItem(STORAGE_KEY);
if (!raw) return [];
const parsed = JSON.parse(raw);
return Array.isArray(parsed) ? parsed : [];
} catch (err) {
return [];
}
}
function persistMessages() {
try {
sessionStorage.setItem(STORAGE_KEY, JSON.stringify(state.messages.slice(-MAX_MESSAGES)));
if (state.list) {
sessionStorage.setItem(STORAGE_HTML_KEY, state.list.innerHTML);
}
} catch (err) {
// Ignore sessionStorage errors (private mode, etc.)
}
}
function hydrateFromStoredMarkup() {
if (!state.list) return false;
try {
const html = sessionStorage.getItem(STORAGE_HTML_KEY);
if (html) {
state.list.innerHTML = html;
for (const entryNode of state.list.querySelectorAll('.browser-use-demo-entry')) {
const toggle = entryNode.querySelector('.browser-use-entry-toggle');
if (toggle) {
toggle.addEventListener('click', () =>
toggleEntryExpansion(entryNode, toggle, entryNode.getAttribute('data-id'))
);
}
applyPersistedExpansion(entryNode);
}
state.list.scrollTop = state.list.scrollHeight;
return true;
}
} catch (err) {
// ignore hydration failures
}
return false;
}
function normalizeEntry(detail) {
if (!detail) return null;
const entry = typeof detail === 'string' ? { message: detail } : { ...detail };
entry.message = typeof entry.message === 'string' ? entry.message : JSON.stringify(entry.message ?? '');
entry.level = (entry.level || 'info').toLowerCase();
if (!LEVEL_ICONS[entry.level]) {
entry.level = 'info';
}
if (!entry.metadata || typeof entry.metadata !== 'object') {
entry.metadata = {};
}
entry.timestamp = entry.timestamp || new Date().toISOString();
entry.id = entry.id || `${Date.now()}-${Math.random().toString(16).slice(2)}`;
return entry;
}
function appendEntry(entry, shouldPersist = true) {
if (shouldPersist) {
state.messages.push(entry);
if (state.messages.length > MAX_MESSAGES) {
state.messages = state.messages.slice(-MAX_MESSAGES);
}
persistMessages();
}
if (!state.list) {
return;
}
const node = createEntryNode(entry);
applyPersistedExpansion(node);
state.list.appendChild(node);
state.list.scrollTop = state.list.scrollHeight;
}
function createEntryNode(entry) {
const row = document.createElement('article');
row.className = `browser-use-demo-entry level-${entry.level}`;
row.setAttribute('data-id', entry.id);
const icon = document.createElement('span');
icon.className = 'browser-use-entry-icon';
icon.textContent = LEVEL_ICONS[entry.level] || LEVEL_ICONS.info;
const content = document.createElement('div');
content.className = 'browser-use-entry-content';
const meta = document.createElement('div');
meta.className = 'browser-use-entry-meta';
const time = formatTime(entry.timestamp);
const label = LEVEL_LABELS[entry.level] || entry.level;
meta.innerHTML = `${time}${label}`;
const messageWrapper = document.createElement('div');
messageWrapper.className = 'browser-use-entry-message';
const messageText = entry.message.trim();
const messageHtml = messageText;
const message = document.createElement('div');
message.className = 'browser-use-markdown-content';
message.textContent = messageHtml;
messageWrapper.appendChild(message);
if (messageText.length > 160) {
const toggle = document.createElement('button');
toggle.type = 'button';
toggle.className = 'browser-use-entry-toggle';
toggle.setAttribute(EXCLUDE_ATTR, 'true');
toggle.textContent = 'Expand';
toggle.addEventListener('click', () => toggleEntryExpansion(row, toggle, entry.id));
messageWrapper.appendChild(toggle);
} else {
row.classList.add('expanded');
}
content.appendChild(meta);
content.appendChild(messageWrapper);
row.appendChild(icon);
row.appendChild(content);
return row;
}
function applyPersistedExpansion(node) {
if (!node) return;
try {
const expanded = new Set(JSON.parse(sessionStorage.getItem(EXPANDED_IDS_KEY) || '[]'));
const id = node.getAttribute('data-id');
if (id && expanded.has(id)) {
node.classList.add('expanded');
const toggle = node.querySelector('.browser-use-entry-toggle');
if (toggle) {
toggle.textContent = 'Collapse';
}
}
} catch {
// ignore
}
}
function toggleEntryExpansion(row, toggle, entryId) {
if (!row) return;
const isExpanded = row.classList.toggle('expanded');
if (toggle) {
toggle.textContent = isExpanded ? 'Collapse' : 'Expand';
}
try {
const expanded = new Set(JSON.parse(sessionStorage.getItem(EXPANDED_IDS_KEY) || '[]'));
if (isExpanded) {
expanded.add(entryId);
} else {
expanded.delete(entryId);
}
sessionStorage.setItem(EXPANDED_IDS_KEY, JSON.stringify(Array.from(expanded)));
} catch {
// ignore persistence issues
}
}
function formatTime(value) {
const date = new Date(value);
if (Number.isNaN(date.getTime())) {
return new Date().toLocaleTimeString();
}
return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' });
}
function debounce(fn, delay) {
let frame;
return (...args) => {
cancelAnimationFrame(frame);
frame = requestAnimationFrame(() => fn.apply(null, args));
};
}
function handleLogEvent(event) {
const entry = normalizeEntry(event?.detail);
if (!entry) return;
appendEntry(entry, true);
}
const boot = () => {
if (window.__browserUseDemoPanelBootstrapped) {
return;
}
const start = () => {
if (window.__browserUseDemoPanelBootstrapped) {
return;
}
if (!document.body) {
requestAnimationFrame(start);
return;
}
window.__browserUseDemoPanelBootstrapped = true;
initializePanel();
};
start();
};
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', boot, { once: true });
} else {
boot();
}
window.addEventListener('browser-use-log', handleLogEvent);
})();
"""
class DemoMode:
"""Encapsulates browser overlay injection and log broadcasting for demo mode."""
VALID_LEVELS = {'info', 'action', 'thought', 'error', 'success', 'warning'}
def __init__(self, session: BrowserSession):
self.session = session
self.logger = logging.getLogger(f'{__name__}.DemoMode')
self._script_identifier: str | None = None
self._script_source: str | None = None
self._panel_ready = False
self._lock = asyncio.Lock()
def reset(self) -> None:
self._script_identifier = None
self._panel_ready = False
def _load_script(self) -> str:
if self._script_source is None:
self._script_source = _DEMO_PANEL_SCRIPT
# Replace placeholder with actual session ID
session_id = self.session.id
script_with_session_id = self._script_source.replace('__BROWSER_USE_SESSION_ID_PLACEHOLDER__', session_id)
self.logger.debug(f'Injecting session ID {session_id} into demo panel script')
return script_with_session_id
async def ensure_ready(self) -> None:
"""Add init script and inject overlay into currently open pages."""
if not self.session.browser_profile.demo_mode:
return
if self.session._cdp_client_root is None:
raise RuntimeError('Root CDP client not initialized')
async with self._lock:
script = self._load_script()
if self._script_identifier is None:
self._script_identifier = await self.session._cdp_add_init_script(script)
self.logger.debug('Added auto-injection script for demo overlay')
await self._inject_into_open_pages(script)
self._panel_ready = True
self.logger.debug('Demo overlay injected successfully')
async def send_log(self, message: str, level: str = 'info', metadata: dict[str, Any] | None = None) -> None:
"""Send a log entry to the in-browser panel."""
if not message or not self.session.browser_profile.demo_mode:
return
try:
await self.ensure_ready()
except Exception as exc:
self.logger.warning(f'Failed to ensure demo mode is ready: {exc}')
return
if self.session.agent_focus_target_id is None:
self.logger.debug('Cannot send demo log: no active target')
return
level_value = level.lower()
if level_value not in self.VALID_LEVELS:
level_value = 'info'
payload = {
'message': message,
'level': level_value,
'metadata': metadata or {},
'timestamp': datetime.now(timezone.utc).isoformat(),
}
script = self._build_event_expression(json.dumps(payload, ensure_ascii=False))
try:
session = await self.session.get_or_create_cdp_session(target_id=None, focus=False)
except Exception as exc:
self.logger.debug(f'Cannot acquire CDP session for demo log: {exc}')
return
try:
await session.cdp_client.send.Runtime.evaluate(
params={'expression': script, 'awaitPromise': False}, session_id=session.session_id
)
except Exception as exc:
self.logger.debug(f'Failed to send demo log: {exc}')
def _build_event_expression(self, payload: str) -> str:
return f"""
(() => {{
const detail = {payload};
const event = new CustomEvent('browser-use-log', {{ detail }});
window.dispatchEvent(event);
}})();
""".strip()
async def _inject_into_open_pages(self, script: str) -> None:
targets = await self.session._cdp_get_all_pages( # - intentional private access
include_http=True,
include_about=True,
include_pages=True,
include_iframes=False,
include_workers=False,
include_chrome=False,
include_chrome_extensions=False,
include_chrome_error=False,
)
target_ids = [t['targetId'] for t in targets]
if not target_ids and self.session.agent_focus_target_id:
target_ids = [self.session.agent_focus_target_id]
for target_id in target_ids:
try:
await self._inject_into_target(target_id, script)
except Exception as exc:
self.logger.debug(f'Failed to inject demo overlay into {target_id}: {exc}')
async def _inject_into_target(self, target_id: str, script: str) -> None:
session = await self.session.get_or_create_cdp_session(target_id=target_id, focus=False)
await session.cdp_client.send.Runtime.evaluate(
params={'expression': script, 'awaitPromise': False},
session_id=session.session_id,
)