@mindstudio-ai/local-model-tunnel 0.5.55 → 0.5.56
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/dist/{chunk-5A5ASXUO.js → chunk-M37JM7QT.js} +3 -2
- package/dist/chunk-M37JM7QT.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/headless.js +1 -1
- package/dist/index.js +1 -1
- package/dist/{tui-T24TDGEV.js → tui-KTSJTXQG.js} +4 -4
- package/package.json +1 -1
- package/dist/chunk-5A5ASXUO.js.map +0 -1
- /package/dist/{tui-T24TDGEV.js.map → tui-KTSJTXQG.js.map} +0 -0
|
@@ -372,7 +372,8 @@ var PREROLL_NETWORK_IDLE_MS = 1500;
|
|
|
372
372
|
var PREROLL_TOP_DWELL_MS = 100;
|
|
373
373
|
async function captureViaCdp(page, opts) {
|
|
374
374
|
if (opts.path) {
|
|
375
|
-
|
|
375
|
+
const absolute = new URL(opts.path, page.url()).toString();
|
|
376
|
+
await page.goto(absolute, {
|
|
376
377
|
waitUntil: "networkidle0",
|
|
377
378
|
timeout: GOTO_TIMEOUT_MS
|
|
378
379
|
});
|
|
@@ -1224,4 +1225,4 @@ async function startHeadless(opts = {}) {
|
|
|
1224
1225
|
export {
|
|
1225
1226
|
startHeadless
|
|
1226
1227
|
};
|
|
1227
|
-
//# sourceMappingURL=chunk-
|
|
1228
|
+
//# sourceMappingURL=chunk-M37JM7QT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/dev/browser/launcher.ts","../src/dev/browser/chrome-path.ts","../src/dev/ipc/ipc.ts","../src/dev/browser/supervisor.ts","../src/dev/browser/screenshot.ts","../src/dev/browser/cookies.ts","../src/dev/ipc/session-events.ts","../src/dev/stdin-commands/run-scenario.ts","../src/dev/stdin-commands/run-method.ts","../src/dev/stdin-commands/impersonate.ts","../src/dev/stdin-commands/browser.ts","../src/dev/stdin-commands/screenshot-full-page.ts","../src/dev/stdin-commands/dev-server-restarting.ts","../src/dev/stdin-commands/db-query.ts","../src/dev/stdin-commands/setup-browser.ts","../src/dev/stdin-commands/index.ts","../src/headless.ts"],"sourcesContent":["/**\n * Launch a headless Chrome instance pointed at the local tunnel proxy.\n *\n * The launched browser loads `http://127.0.0.1:<proxyPort>/?ms_sandbox=1`.\n * The tunnel proxy injects the browser-agent script as usual, which opens\n * a WebSocket back to the tunnel and registers as a client. The proxy's\n * hello handler recognizes the `ms_sandbox=1` query from a loopback source\n * and forces the client mode to 'headless'.\n *\n * This module knows nothing about the client registry or the command\n * dispatch path — those stay untouched. It only spawns Chrome and navigates.\n */\n\nimport puppeteer, { type Browser, type Page, type Viewport } from 'puppeteer-core';\nimport { resolveChromePath } from './chrome-path';\nimport { log } from '../logging/logger';\n\nexport interface LaunchedBrowser {\n browser: Browser;\n page: Page;\n executablePath: string;\n pid: number | null;\n previewMode: PreviewMode;\n viewport: string;\n}\n\nexport type PreviewMode = 'desktop' | 'mobile';\n\nconst LAUNCH_ARGS = [\n '--no-sandbox',\n '--disable-dev-shm-usage',\n '--disable-gpu',\n '--hide-scrollbars',\n '--force-color-profile=srgb',\n '--font-render-hinting=none',\n '--disable-blink-features=AutomationControlled',\n '--lang=en-US',\n];\n\n// Modern laptop — fits most desktop-first app layouts without extra gutters.\nconst DESKTOP_VIEWPORT: Viewport = {\n width: 1440,\n height: 900,\n deviceScaleFactor: 1,\n isMobile: false,\n hasTouch: false,\n};\n\n// iPhone 15 Pro portrait. DPR 2 is the sweet spot — retina-ish fidelity\n// without 3× screenshot bloat. `isMobile`/`hasTouch` engage Chrome's mobile\n// emulation (viewport meta tag handling, touch events, orientation APIs).\nconst MOBILE_VIEWPORT: Viewport = {\n width: 390,\n height: 844,\n deviceScaleFactor: 2,\n isMobile: true,\n hasTouch: true,\n};\n\nfunction viewportFor(mode: PreviewMode): Viewport {\n return mode === 'mobile' ? MOBILE_VIEWPORT : DESKTOP_VIEWPORT;\n}\n\nexport async function launchSandboxBrowser(opts: {\n proxyPort: number;\n previewMode?: PreviewMode;\n}): Promise<LaunchedBrowser | null> {\n const executablePath = resolveChromePath();\n if (!executablePath) {\n log.warn(\n 'browser',\n 'No Chrome executable found — sandbox-browser mode disabled for this session',\n );\n return null;\n }\n\n const previewMode: PreviewMode = opts.previewMode === 'mobile' ? 'mobile' : 'desktop';\n const viewport = viewportFor(previewMode);\n\n const browser = await puppeteer.launch({\n executablePath,\n headless: true,\n args: LAUNCH_ARGS,\n defaultViewport: viewport,\n });\n\n // Pipe Chrome stderr through the debug logger. Chrome is chatty on startup\n // and we don't want that at info level.\n const proc = browser.process();\n proc?.stderr?.on('data', (buf: Buffer) => {\n const line = buf.toString().trim();\n if (line) log.debug('browser-chrome', line);\n });\n\n const pages = await browser.pages();\n const page = pages[0] ?? (await browser.newPage());\n\n const target = `http://127.0.0.1:${opts.proxyPort}/?ms_sandbox=1`;\n // `networkidle0` waits for the injected `<script async>` browser-agent to\n // finish loading AND its WebSocket to open (at which point the page is\n // idle). That way `running` corresponds to \"ready for both CDP *and* WS\n // tool calls\", closing the first-tool-call race where the WS client\n // hadn't registered before the first command dispatched.\n try {\n await page.goto(target, { waitUntil: 'networkidle0', timeout: 15_000 });\n } catch (err) {\n // Leaked Chromium otherwise — if navigation fails, close the browser\n // so the supervisor's restart loop can start clean.\n await browser.close().catch(() => {});\n throw err;\n }\n\n const viewportStr = `${viewport.width}x${viewport.height}@${viewport.deviceScaleFactor}x`;\n\n log.info('browser', 'Sandbox browser launched', {\n executablePath,\n target,\n previewMode,\n viewport: viewportStr,\n pid: proc?.pid ?? null,\n });\n\n return {\n browser,\n page,\n executablePath,\n pid: proc?.pid ?? null,\n previewMode,\n viewport: viewportStr,\n };\n}\n","/**\n * Resolve the path to a Chrome/Chromium executable. Returns null if none\n * found — the supervisor downgrades to a no-op and logs in that case.\n *\n * The sandbox image bakes in `google-chrome-stable`. On dev machines\n * the user may have Chrome installed at a different path; we probe a\n * short list of common locations.\n */\n\nimport { existsSync } from 'node:fs';\nimport { execSync } from 'node:child_process';\n\nconst CANDIDATES = [\n '/usr/bin/google-chrome-stable',\n '/usr/bin/google-chrome',\n '/usr/bin/chromium',\n '/usr/bin/chromium-browser',\n '/opt/google/chrome/google-chrome',\n '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',\n '/Applications/Chromium.app/Contents/MacOS/Chromium',\n];\n\nconst PATH_COMMANDS = ['google-chrome-stable', 'google-chrome', 'chromium'];\n\nexport function resolveChromePath(): string | null {\n for (const candidate of CANDIDATES) {\n if (existsSync(candidate)) return candidate;\n }\n\n for (const cmd of PATH_COMMANDS) {\n try {\n const resolved = execSync(`command -v ${cmd}`, {\n encoding: 'utf-8',\n stdio: ['ignore', 'pipe', 'ignore'],\n }).trim();\n if (resolved && existsSync(resolved)) return resolved;\n } catch {\n // Not on PATH — try next\n }\n }\n\n return null;\n}\n","/**\n * Central IPC module for headless mode.\n *\n * All stdout writes go through here. Two distinct message types:\n * - System events: unsolicited, no requestId (session lifecycle, connection, etc.)\n * - Command responses: always have requestId + status (started/completed)\n *\n * The caller distinguishes them by the presence of `requestId`.\n */\n\n/**\n * Emit a system event (no requestId).\n * Used for unsolicited events: session lifecycle, connection health, auth, etc.\n */\nexport function emitEvent(event: string, data?: Record<string, unknown>): void {\n process.stdout.write(JSON.stringify({ event, ...data }) + '\\n');\n}\n\n/**\n * Emit a command response (always has requestId).\n * Used for responses to stdin commands.\n */\nexport function emitResponse(\n action: string,\n requestId: string,\n status: 'started' | 'completed',\n data?: Record<string, unknown>,\n): void {\n process.stdout.write(\n JSON.stringify({ event: action, requestId, status, ...data }) + '\\n',\n );\n}\n","/**\n * BrowserSupervisor — keeps a headless Chrome instance alive for the lifetime\n * of a dev session.\n *\n * Responsibilities:\n * - Launch Chrome once at session start.\n * - Watch for unexpected disconnect (Chrome crash, killed process).\n * - Restart with exponential backoff; enter degraded mode after repeated\n * failures so automation falls through to user-browser clients.\n * - Clean teardown on session stop so no orphan Chrome processes linger.\n *\n * Emits structured `sandbox-browser-state` events on stdout at every state\n * transition so the sandbox manager can track Chrome in its /status surface\n * (resource metrics, debug bundles, degraded-mode alerts).\n *\n * The supervisor does NOT dispatch commands. Chrome connects back over the\n * existing WS path and the proxy's client registry picks it up like any\n * other client.\n */\n\nimport type { Browser, Page } from 'puppeteer-core';\nimport { launchSandboxBrowser, type PreviewMode } from './launcher';\nimport { log } from '../logging/logger';\nimport { emitEvent } from '../ipc/ipc';\n\nconst BACKOFF_MS = [1_000, 2_000, 4_000, 8_000, 16_000, 30_000];\nconst MAX_FAILURES = 5;\nconst CLOSE_TIMEOUT_MS = 5_000;\n\nexport class BrowserSupervisor {\n private browser: Browser | null = null;\n private page: Page | null = null;\n private stopping = false;\n private degraded = false;\n private consecutiveFailures = 0;\n private restartTimer: ReturnType<typeof setTimeout> | null = null;\n private runningSince: number | null = null;\n private lastExitInfo: {\n exitCode: number | null;\n signal: string | null;\n } | null = null;\n\n constructor(\n private readonly proxyPort: number,\n private readonly previewMode: PreviewMode = 'desktop',\n ) {}\n\n async start(): Promise<void> {\n if (this.browser) return;\n await this.launchOnce();\n }\n\n async stop(): Promise<void> {\n if (this.stopping) return; // idempotent — double SIGTERM shouldn't double-fire events\n this.stopping = true;\n if (this.restartTimer) {\n clearTimeout(this.restartTimer);\n this.restartTimer = null;\n }\n const browser = this.browser;\n this.browser = null;\n this.page = null;\n if (browser) {\n await this.closeBrowser(browser);\n }\n this.runningSince = null;\n this.lastExitInfo = null;\n emitEvent('sandbox-browser-state', { state: 'stopped' });\n }\n\n isRunning(): boolean {\n return !!this.browser && !this.degraded;\n }\n\n isDegraded(): boolean {\n return this.degraded;\n }\n\n /**\n * Returns the active puppeteer Page when the sandbox browser is running\n * and not degraded; null otherwise. Callers use this to decide whether\n * a CDP-side fast path is available for a given command.\n */\n getActivePage(): Page | null {\n if (this.stopping || this.degraded) return null;\n if (!this.browser || !this.page) return null;\n return this.page;\n }\n\n private async launchOnce(): Promise<void> {\n if (this.stopping) return;\n\n const attempt = this.consecutiveFailures + 1;\n log.info('browser', 'Sandbox browser launch starting', {\n proxyPort: this.proxyPort,\n attempt,\n });\n emitEvent('sandbox-browser-state', {\n state: 'starting',\n attempt,\n previewMode: this.previewMode,\n });\n\n try {\n const launched = await launchSandboxBrowser({\n proxyPort: this.proxyPort,\n previewMode: this.previewMode,\n });\n if (!launched) {\n // No Chrome executable — enter degraded mode permanently for this session.\n this.degraded = true;\n emitEvent('sandbox-browser-state', {\n state: 'degraded',\n reason: 'no-executable',\n });\n return;\n }\n\n // If stop() landed while we were launching, the supervisor has already\n // emitted `stopped` and cleared its state. Don't register the browser\n // we just got — close it and bail, otherwise we'd leak Chromium.\n if (this.stopping) {\n await this.closeBrowser(launched.browser).catch(() => {});\n return;\n }\n\n this.browser = launched.browser;\n this.page = launched.page;\n this.consecutiveFailures = 0;\n this.degraded = false;\n this.runningSince = Date.now();\n this.lastExitInfo = null;\n\n // Capture exit info directly from the child process so `crashed` events\n // carry an accurate signal / exitCode alongside puppeteer's `disconnected`.\n const proc = launched.browser.process();\n proc?.once('exit', (code, signal) => {\n this.lastExitInfo = { exitCode: code, signal: signal ?? null };\n });\n\n launched.browser.on('disconnected', () => this.onDisconnect());\n\n emitEvent('sandbox-browser-state', {\n state: 'running',\n pid: launched.pid,\n previewMode: launched.previewMode,\n viewport: launched.viewport,\n executablePath: launched.executablePath,\n });\n } catch (err) {\n // Don't track failures or restart if we were torn down mid-launch.\n if (this.stopping) return;\n\n this.consecutiveFailures++;\n const message = err instanceof Error ? err.message : String(err);\n log.warn('browser', 'Failed to launch sandbox browser', {\n attempt: this.consecutiveFailures,\n error: message,\n });\n emitEvent('sandbox-browser-state', {\n state: 'crashed',\n exitCode: null,\n signal: null,\n durationMs: 0,\n consecutiveFailures: this.consecutiveFailures,\n error: message,\n });\n this.scheduleRestart();\n }\n }\n\n private async onDisconnect(): Promise<void> {\n if (this.stopping) return;\n const hadBrowser = !!this.browser;\n this.browser = null;\n this.page = null;\n if (!hadBrowser) return;\n\n this.consecutiveFailures++;\n const durationMs = this.runningSince ? Date.now() - this.runningSince : 0;\n this.runningSince = null;\n log.warn('browser', 'Sandbox browser disconnected', {\n attempt: this.consecutiveFailures,\n });\n\n // puppeteer's disconnect sometimes fires before the child's `exit` listener,\n // leaving exit info unpopulated. Give that listener a short window.\n await this.waitForExitInfo();\n\n emitEvent('sandbox-browser-state', {\n state: 'crashed',\n exitCode: this.lastExitInfo?.exitCode ?? null,\n signal: this.lastExitInfo?.signal ?? null,\n durationMs,\n consecutiveFailures: this.consecutiveFailures,\n });\n this.lastExitInfo = null;\n this.scheduleRestart();\n }\n\n private async waitForExitInfo(timeoutMs = 200): Promise<void> {\n if (this.lastExitInfo) return;\n const deadline = Date.now() + timeoutMs;\n while (!this.lastExitInfo && Date.now() < deadline) {\n await new Promise((r) => setTimeout(r, 20));\n }\n }\n\n private scheduleRestart(): void {\n if (this.stopping) return;\n\n if (this.consecutiveFailures >= MAX_FAILURES) {\n this.degraded = true;\n log.warn(\n 'browser',\n 'Sandbox browser entering degraded mode after repeated failures — automation will fall back to user browsers',\n { failures: this.consecutiveFailures },\n );\n emitEvent('sandbox-browser-state', {\n state: 'degraded',\n reason: 'repeated-crashes',\n consecutiveFailures: this.consecutiveFailures,\n });\n return;\n }\n\n const delay =\n BACKOFF_MS[Math.min(this.consecutiveFailures, BACKOFF_MS.length - 1)];\n log.info('browser', 'Scheduling sandbox browser restart', {\n delayMs: delay,\n attempt: this.consecutiveFailures,\n });\n emitEvent('sandbox-browser-state', {\n state: 'restarting',\n delayMs: delay,\n nextAttempt: this.consecutiveFailures + 1,\n });\n this.restartTimer = setTimeout(() => {\n this.restartTimer = null;\n void this.launchOnce();\n }, delay);\n }\n\n private async closeBrowser(browser: Browser): Promise<void> {\n let resolved = false;\n await new Promise<void>((resolve) => {\n const done = () => {\n if (resolved) return;\n resolved = true;\n resolve();\n };\n const timeout = setTimeout(() => {\n // Graceful close timed out — kill the underlying process.\n try {\n browser.process()?.kill('SIGKILL');\n } catch {\n // Best effort\n }\n done();\n }, CLOSE_TIMEOUT_MS);\n\n browser\n .close()\n .then(() => {\n clearTimeout(timeout);\n done();\n })\n .catch(() => {\n clearTimeout(timeout);\n try {\n browser.process()?.kill('SIGKILL');\n } catch {\n // Best effort\n }\n done();\n });\n });\n }\n}\n","/**\n * CDP-based screenshot capture.\n *\n * Runs inside the tunnel (Node) against the puppeteer Page owned by the\n * BrowserSupervisor. Produces real pixels via Chrome's own rendering path\n * (replacing browser-agent's snapdom DOM→SVG→Canvas pipeline for headless\n * targets) and uploads the result to the same presigned S3 URL the WS\n * path uses, so callers see an identical result shape.\n */\n\nimport type { Page } from 'puppeteer-core';\n\nexport interface CaptureOpts {\n fullPage: boolean;\n path?: string;\n uploadUrl: string;\n uploadFields: Record<string, string>;\n}\n\nexport interface CaptureResult {\n uploaded: true;\n width: number;\n height: number;\n styleMap?: string;\n}\n\nconst GOTO_TIMEOUT_MS = 15_000;\nconst SETTLE_TIMEOUT_MS = 3_000;\nconst SETTLE_IDLE_MS = 200;\nconst JPEG_QUALITY = 85;\n// Pre-roll timings: used only for fullPage captures to trigger\n// IntersectionObservers, lazy-loaded images, and scroll-linked animations\n// before the single-shot CDP capture.\nconst PREROLL_BOTTOM_DWELL_MS = 300;\nconst PREROLL_NETWORK_IDLE_MS = 1_500;\nconst PREROLL_TOP_DWELL_MS = 100;\n\nexport async function captureViaCdp(\n page: Page,\n opts: CaptureOpts,\n): Promise<CaptureResult> {\n if (opts.path) {\n // Puppeteer's page.goto requires an absolute URL — callers pass paths\n // like \"/welcome\", so resolve against the current page origin.\n const absolute = new URL(opts.path, page.url()).toString();\n await page.goto(absolute, {\n waitUntil: 'networkidle0',\n timeout: GOTO_TIMEOUT_MS,\n });\n }\n\n // Match browser-agent's in-page network-idle settle so layout/fonts are\n // stable at capture time. Swallow timeout — best-effort.\n await page\n .waitForNetworkIdle({ timeout: SETTLE_TIMEOUT_MS, idleTime: SETTLE_IDLE_MS })\n .catch(() => {});\n\n // Pre-roll for fullPage captures only. CDP's `fullPage: true` renders in a\n // single pass with the viewport logically at the top, so IntersectionObserver\n // callbacks, lazy-loaded images, and scroll-triggered animations never fire.\n // Scrolling to the bottom and back nudges them into their revealed state;\n // Chrome then captures the fully-revealed layout in one shot.\n if (opts.fullPage) {\n await preRollScroll(page);\n }\n\n let width: number;\n let height: number;\n if (opts.fullPage) {\n const dims = await page.evaluate(() => ({\n width: document.documentElement.scrollWidth,\n height: document.documentElement.scrollHeight,\n }));\n width = dims.width;\n height = dims.height;\n } else {\n const vp = page.viewport();\n width = vp?.width ?? 0;\n height = vp?.height ?? 0;\n }\n\n // Best-effort styleMap via the already-loaded browser-agent. The browser\n // agent is injected into every page the proxy serves, so it's running in\n // this Chrome instance too. Silently skipped if the served version\n // predates the exposed API.\n let styleMap: string | undefined;\n try {\n const result = await page.evaluate(() => {\n const api = (window as unknown as {\n __MINDSTUDIO_BROWSER_AGENT__?: { computeStyleMap?: () => string };\n }).__MINDSTUDIO_BROWSER_AGENT__;\n return api?.computeStyleMap?.() ?? null;\n });\n if (typeof result === 'string' && result.length > 0) styleMap = result;\n } catch {\n // Non-fatal — styleMap stays undefined.\n }\n\n const buf = (await page.screenshot({\n type: 'jpeg',\n quality: JPEG_QUALITY,\n fullPage: opts.fullPage,\n })) as Buffer;\n\n await uploadToPresigned(opts.uploadUrl, opts.uploadFields, buf);\n\n return {\n uploaded: true,\n width,\n height,\n ...(styleMap ? { styleMap } : {}),\n };\n}\n\n/**\n * Scroll the document to the bottom, wait for observer callbacks and any\n * lazy-loaded content to settle, then scroll back to the top. Gives\n * fullPage captures a chance to include scroll-triggered fade-ins, lazy\n * images, and windowed-list items.\n *\n * Best-effort — all timeouts swallowed. If the page can't be scrolled\n * (short content, scroll-locked body) the function is effectively a no-op.\n */\nasync function preRollScroll(page: Page): Promise<void> {\n try {\n const scrolled = await page.evaluate(() => {\n const el = document.scrollingElement || document.documentElement;\n const max = Math.max(\n document.documentElement.scrollHeight,\n document.body.scrollHeight,\n );\n if (max <= window.innerHeight + 10) return false; // nothing to scroll\n el.scrollTo({ top: max, left: 0, behavior: 'instant' as ScrollBehavior });\n return true;\n });\n\n if (!scrolled) return;\n\n // Let IntersectionObservers fire and any triggered animations settle.\n await new Promise((r) => setTimeout(r, PREROLL_BOTTOM_DWELL_MS));\n\n // If the observers kicked off image/data loads, wait for them briefly.\n await page\n .waitForNetworkIdle({\n timeout: PREROLL_NETWORK_IDLE_MS,\n idleTime: SETTLE_IDLE_MS,\n })\n .catch(() => {});\n\n await page.evaluate(() => {\n const el = document.scrollingElement || document.documentElement;\n el.scrollTo({ top: 0, left: 0, behavior: 'instant' as ScrollBehavior });\n });\n\n await new Promise((r) => setTimeout(r, PREROLL_TOP_DWELL_MS));\n } catch {\n // Non-fatal — proceed to capture regardless.\n }\n}\n\nasync function uploadToPresigned(\n uploadUrl: string,\n uploadFields: Record<string, string>,\n buf: Buffer,\n): Promise<void> {\n const form = new FormData();\n for (const [k, v] of Object.entries(uploadFields)) form.append(k, v);\n form.append(\n 'file',\n new Blob([buf as unknown as BlobPart], { type: 'image/jpeg' }),\n 'screenshot.jpg',\n );\n const res = await fetch(uploadUrl, { method: 'POST', body: form });\n if (!res.ok) {\n throw new Error(`Screenshot upload failed: ${res.status}`);\n }\n}\n","/**\n * Auth-cookie helpers for the sandbox-owned Chrome.\n *\n * `setup-browser` and `reset-browser` both operate on the `__ms_auth` cookie\n * via CDP now — no more WS round-trip through browser-agent. These wrappers\n * keep the cookie shape + lifetime in one place.\n */\n\nimport type { Page } from 'puppeteer-core';\n\nconst AUTH_COOKIE_NAME = '__ms_auth';\n\nfunction cookieHost(page: Page): string {\n try {\n return new URL(page.url()).hostname || '127.0.0.1';\n } catch {\n return '127.0.0.1';\n }\n}\n\nexport async function clearAuthCookies(page: Page): Promise<void> {\n const domain = cookieHost(page);\n try {\n await page.deleteCookie({ name: AUTH_COOKIE_NAME, domain });\n } catch {\n // Cookie may not exist — fine.\n }\n // `deleteCookie` is scoped by domain; make sure any `/`-path variants go too.\n try {\n await page.deleteCookie({ name: AUTH_COOKIE_NAME });\n } catch {\n // Best effort.\n }\n}\n\nexport async function setAuthCookie(page: Page, value: string): Promise<void> {\n const domain = cookieHost(page);\n await page.setCookie({\n name: AUTH_COOKIE_NAME,\n value,\n domain,\n path: '/',\n sameSite: 'None',\n secure: true,\n });\n}\n","/**\n * Subscribe to DevRunner events and relay them as system events to stdout.\n * Only relays genuinely unsolicited events (poll-loop methods, connection, auth).\n * Command responses (scenarios, impersonation) are handled by stdin handlers directly.\n *\n * Returns an array of unsubscribe functions for cleanup on teardown.\n */\n\nimport { devRequestEvents } from './events';\nimport { emitEvent } from './ipc';\n\nexport function subscribeDevEvents(\n shutdown: () => Promise<void>,\n): Array<() => void> {\n const unsubs: Array<() => void> = [];\n\n // Platform-triggered method execution (poll loop)\n unsubs.push(\n devRequestEvents.onStart((event) => {\n emitEvent('platform-method-started', { id: event.id, method: event.method });\n }),\n );\n\n unsubs.push(\n devRequestEvents.onComplete((event) => {\n emitEvent('platform-method-completed', {\n id: event.id,\n success: event.success,\n duration: event.duration,\n ...(event.error ? { error: event.error } : {}),\n });\n }),\n );\n\n // Connection health\n unsubs.push(\n devRequestEvents.onConnectionWarning((message) => {\n emitEvent('connection-lost', { message });\n }),\n );\n\n unsubs.push(\n devRequestEvents.onConnectionRestored(() => {\n emitEvent('connection-restored');\n }),\n );\n\n // Session expiry\n unsubs.push(\n devRequestEvents.onSessionExpired(() => {\n emitEvent('session-expired');\n shutdown().then(() => process.exit(1));\n }),\n );\n\n // Auth refresh\n unsubs.push(\n devRequestEvents.onAuthRefreshStart((url) => {\n emitEvent('auth-refresh-start', { url });\n }),\n );\n\n unsubs.push(\n devRequestEvents.onAuthRefreshSuccess(() => {\n emitEvent('auth-refresh-success');\n }),\n );\n\n unsubs.push(\n devRequestEvents.onAuthRefreshFailed(() => {\n emitEvent('auth-refresh-failed');\n }),\n );\n\n return unsubs;\n}\n","import { detectAppConfig } from '../config/app-config';\nimport { CommandError } from './types';\nimport type { CommandContext } from './types';\n\nexport async function handleRunScenario(\n ctx: CommandContext,\n cmd: Record<string, unknown>,\n): Promise<Record<string, unknown>> {\n if (!ctx.state.runner) throw new CommandError('No active session', 'NO_SESSION');\n\n const freshConfig = detectAppConfig(ctx.cwd) ?? ctx.state.appConfig;\n const scenario = freshConfig?.scenarios.find((s) => s.id === cmd.scenarioId);\n if (!scenario) throw new CommandError(`Unknown scenario: ${cmd.scenarioId}`, 'INVALID_INPUT');\n\n const scenarioName = scenario.name ?? scenario.export;\n ctx.started({ scenarioId: scenario.id, name: scenarioName });\n\n const skipTruncate = cmd.skipTruncate === true;\n const result = await ctx.state.runner.runScenario(scenario, { skipTruncate });\n\n // Reset the browser so it picks up the new data/roles from the scenario\n if (result.success && ctx.state.proxy?.isBrowserConnected()) {\n ctx.state.proxy.broadcastToClients('reload');\n }\n\n return {\n success: result.success,\n scenarioId: scenario.id,\n name: scenarioName,\n error: result.error ?? null,\n errorCode: result.success ? undefined : 'EXECUTION_ERROR',\n };\n}\n","import { detectAppConfig } from '../config/app-config';\nimport { CommandError } from './types';\nimport type { CommandContext } from './types';\n\nexport async function handleRunMethod(\n ctx: CommandContext,\n cmd: Record<string, unknown>,\n): Promise<Record<string, unknown>> {\n if (!ctx.state.runner) throw new CommandError('No active session', 'NO_SESSION');\n\n const methodName = cmd.method as string;\n if (!methodName) throw new CommandError('run-method requires \"method\" (export name or ID)', 'INVALID_INPUT');\n\n const freshConfig = detectAppConfig(ctx.cwd) ?? ctx.state.appConfig;\n const method =\n freshConfig?.methods.find((m) => m.export === methodName) ??\n freshConfig?.methods.find((m) => m.id === methodName);\n if (!method) throw new CommandError(`Unknown method: ${methodName}`, 'INVALID_INPUT');\n\n ctx.started({ method: method.export });\n\n const result = await ctx.state.runner.runMethod({\n methodExport: method.export,\n methodPath: method.path,\n input: cmd.input ?? {},\n roles: Array.isArray(cmd.roles) ? cmd.roles as string[] : undefined,\n userId: typeof cmd.userId === 'string' ? cmd.userId : undefined,\n });\n\n return {\n success: result.success,\n method: method.export,\n output: result.output ?? null,\n error: result.error?.message ?? null,\n errorCode: result.success ? undefined : 'EXECUTION_ERROR',\n errorDetail: result.error ?? null,\n stdout: result.stdout ?? [],\n duration: result.duration,\n };\n}\n","import { CommandError } from './types';\nimport type { CommandContext } from './types';\n\nexport async function handleImpersonate(\n ctx: CommandContext,\n cmd: Record<string, unknown>,\n): Promise<Record<string, unknown>> {\n if (!ctx.state.runner) throw new CommandError('No active session', 'NO_SESSION');\n\n const roles = cmd.roles as string[];\n if (!Array.isArray(roles)) throw new CommandError('impersonate requires roles array', 'INVALID_INPUT');\n\n await ctx.state.runner.setImpersonation(roles);\n return { success: true, roles };\n}\n\nexport async function handleClearImpersonation(\n ctx: CommandContext,\n): Promise<Record<string, unknown>> {\n if (!ctx.state.runner) throw new CommandError('No active session', 'NO_SESSION');\n\n await ctx.state.runner.clearImpersonation();\n return { success: true, roles: null };\n}\n","import { getUploadUrl } from '../api';\nimport { captureViaCdp } from '../browser';\nimport { log } from '../logging/logger';\nimport { CommandError } from './types';\nimport type { CommandContext } from './types';\nimport type { Page } from 'puppeteer-core';\n\n// Recordings smaller than this (after JSON serialization) aren't worth\n// the round trip — probably a FullSnapshot with no interesting deltas.\nconst MIN_RECORDING_BYTES = 5_000;\n\nexport async function handleBrowser(\n ctx: CommandContext,\n cmd: Record<string, unknown>,\n): Promise<Record<string, unknown>> {\n if (!ctx.state.proxy) throw new CommandError('No active proxy', 'NO_BROWSER');\n\n const steps = cmd.steps as Array<Record<string, unknown>>;\n if (!Array.isArray(steps) || steps.length === 0) {\n throw new CommandError('browser action requires a non-empty \"steps\" array', 'INVALID_INPUT');\n }\n\n const page = ctx.state.browser?.getActivePage();\n if (!page) {\n throw new CommandError(\n 'Sandbox browser unavailable — headless Chrome is required for automation',\n 'NO_BROWSER',\n );\n }\n\n const resultsByIndex = new Array<Record<string, unknown> | undefined>(\n steps.length,\n );\n let lastSnapshot = '';\n let lastLogs: unknown[] = [];\n let totalDuration = 0;\n const allEvents: unknown[] = [];\n\n let buffer: Array<{ idx: number; step: Record<string, unknown> }> = [];\n\n const flushBuffer = async () => {\n if (buffer.length === 0) return;\n const batch = buffer.map((b) => b.step);\n const out = await ctx.state.proxy!.dispatchBrowserCommand(batch);\n const outSteps = (out.steps as Array<Record<string, unknown>>) ?? [];\n for (let i = 0; i < buffer.length; i++) {\n const returned = outSteps[i] ?? {};\n resultsByIndex[buffer[i].idx] = {\n ...returned,\n index: buffer[i].idx,\n command: buffer[i].step.command,\n };\n }\n if (typeof out.snapshot === 'string' && out.snapshot.length > 0) {\n lastSnapshot = out.snapshot;\n }\n if (Array.isArray(out.logs)) lastLogs = out.logs as unknown[];\n if (typeof out.duration === 'number') totalDuration += out.duration;\n if (Array.isArray(out.events)) allEvents.push(...(out.events as unknown[]));\n buffer = [];\n };\n\n for (let i = 0; i < steps.length; i++) {\n const step = steps[i];\n const command = step.command;\n if (command === 'screenshotFullPage' || command === 'screenshotViewport') {\n await flushBuffer();\n const captured = await captureScreenshotStep(ctx, page, step as Record<string, unknown>, command);\n resultsByIndex[i] = { index: i, command, result: captured };\n totalDuration += captured._durationMs ?? 0;\n delete captured._durationMs;\n } else {\n buffer.push({ idx: i, step });\n }\n }\n await flushBuffer();\n\n const densified = resultsByIndex.map((r, idx) =>\n r ?? { index: idx, command: steps[idx].command, error: 'no result' },\n );\n const hasStepError = densified.some((s) => s?.error);\n const recordingUrl = await uploadRecording(ctx, allEvents);\n\n return {\n success: !hasStepError,\n ...(hasStepError ? { errorCode: 'BROWSER_ERROR' } : {}),\n steps: densified,\n snapshot: lastSnapshot,\n logs: lastLogs,\n duration: totalDuration,\n ...(recordingUrl ? { recordingUrl } : {}),\n };\n}\n\n/**\n * Capture a screenshot step via CDP. Returns a result that matches the\n * shape today's stdin callers expect: `{ url, width, height, styleMap? }`.\n * Navigation before the capture is handled inside `captureViaCdp`.\n */\nasync function captureScreenshotStep(\n ctx: CommandContext,\n page: Page,\n step: Record<string, unknown>,\n command: string,\n): Promise<Record<string, unknown> & { _durationMs?: number }> {\n const session = ctx.state.runner?.getSession();\n const appId = ctx.state.appConfig?.appId;\n if (!session || !appId) {\n throw new CommandError('No active session', 'NO_SESSION');\n }\n const { uploadUrl, uploadFields, publicUrl } = await getUploadUrl(\n appId,\n session.sessionId,\n 'jpg',\n 'image/jpeg',\n );\n const start = Date.now();\n const r = await captureViaCdp(page, {\n fullPage: command === 'screenshotFullPage',\n path: typeof step.path === 'string' ? step.path : undefined,\n uploadUrl,\n uploadFields,\n });\n return {\n url: publicUrl,\n width: r.width,\n height: r.height,\n ...(r.styleMap ? { styleMap: r.styleMap } : {}),\n _durationMs: Date.now() - start,\n };\n}\n\n/**\n * Upload an rrweb event array to S3 using the same presigned-URL flow\n * screenshots use. Returns the public URL on success, null on any failure\n * (including too-small recordings that aren't worth keeping).\n */\nasync function uploadRecording(\n ctx: CommandContext,\n events: unknown[],\n): Promise<string | null> {\n if (events.length === 0) return null;\n const session = ctx.state.runner?.getSession();\n const appId = ctx.state.appConfig?.appId;\n if (!session || !appId) return null;\n\n const body = JSON.stringify(events);\n if (body.length < MIN_RECORDING_BYTES) return null;\n\n try {\n const { uploadUrl, uploadFields, publicUrl } = await getUploadUrl(\n appId,\n session.sessionId,\n 'json',\n 'application/json',\n );\n const form = new FormData();\n for (const [k, v] of Object.entries(uploadFields)) form.append(k, v);\n form.append(\n 'file',\n new Blob([body], { type: 'application/json' }),\n 'recording.json',\n );\n const res = await fetch(uploadUrl, { method: 'POST', body: form });\n if (!res.ok) {\n log.warn('browser', 'Recording upload failed', {\n status: res.status,\n bytes: body.length,\n });\n return null;\n }\n log.info('browser', 'Recording uploaded', {\n bytes: body.length,\n events: events.length,\n });\n return publicUrl;\n } catch (err) {\n log.warn('browser', 'Recording upload errored', {\n error: err instanceof Error ? err.message : String(err),\n });\n return null;\n }\n}\n","import { getUploadUrl } from '../api';\nimport { captureViaCdp } from '../browser';\nimport { CommandError } from './types';\nimport type { CommandContext } from './types';\n\nexport async function handleScreenshotFullPage(\n ctx: CommandContext,\n cmd: Record<string, unknown>,\n): Promise<Record<string, unknown>> {\n if (!ctx.state.runner?.getSession() || !ctx.state.appConfig?.appId) {\n throw new CommandError('No active session', 'NO_SESSION');\n }\n const page = ctx.state.browser?.getActivePage();\n if (!page) {\n throw new CommandError(\n 'Sandbox browser unavailable — headless Chrome is required for screenshots',\n 'NO_BROWSER',\n );\n }\n\n const startTime = Date.now();\n\n const session = ctx.state.runner.getSession()!;\n const { uploadUrl, uploadFields, publicUrl } = await getUploadUrl(\n ctx.state.appConfig.appId,\n session.sessionId,\n 'jpg',\n 'image/jpeg',\n );\n\n const r = await captureViaCdp(page, {\n fullPage: true,\n path: typeof cmd.path === 'string' ? cmd.path : undefined,\n uploadUrl,\n uploadFields,\n });\n\n return {\n success: true,\n url: publicUrl,\n width: r.width,\n height: r.height,\n ...(r.styleMap ? { styleMap: r.styleMap } : {}),\n duration: Date.now() - startTime,\n };\n}\n","import { CommandError } from './types';\nimport type { CommandContext } from './types';\n\nexport async function handleDevServerRestarting(\n ctx: CommandContext,\n): Promise<Record<string, unknown>> {\n if (!ctx.state.proxy) throw new CommandError('No active proxy', 'NO_BROWSER');\n\n ctx.state.proxy.markUpstreamDown();\n return { success: true };\n}\n","import { getApiBaseUrl } from '../../config';\nimport { fetchCallbackToken } from '../api';\nimport { CommandError } from './types';\nimport type { CommandContext } from './types';\n\nexport async function handleDbQuery(\n ctx: CommandContext,\n cmd: Record<string, unknown>,\n): Promise<Record<string, unknown>> {\n if (!ctx.state.runner) throw new CommandError('No active session', 'NO_SESSION');\n\n const session = ctx.state.runner.getSession();\n if (!session) throw new CommandError('No active session', 'NO_SESSION');\n\n const sql = cmd.sql as string;\n if (!sql) throw new CommandError('db-query requires \"sql\"', 'INVALID_INPUT');\n\n // Resolve database — use explicit databaseId, or default to the first one\n let databaseId = cmd.databaseId as string | undefined;\n if (!databaseId) {\n if (session.databases.length === 0) throw new CommandError('No databases available', 'NO_SESSION');\n databaseId = session.databases[0].id;\n }\n\n const appId = ctx.state.appConfig?.appId;\n if (!appId) throw new CommandError('No app config available', 'NO_SESSION');\n\n ctx.started({ databaseId, sql });\n\n const token = await fetchCallbackToken(appId, session.sessionId);\n const url = `${getApiBaseUrl()}/_internal/v2/db/query`;\n\n const res = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: token,\n },\n body: JSON.stringify({\n databaseId,\n queries: [{ sql }],\n }),\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => '');\n throw new CommandError(`Database query failed: ${res.status} ${text}`, 'EXECUTION_ERROR');\n }\n\n const data = await res.json() as { results: { rows: unknown[]; changes: number }[] };\n\n return {\n success: true,\n databaseId,\n results: data.results,\n };\n}\n","import { createAuthSession } from '../api';\nimport { clearAuthCookies, setAuthCookie } from '../browser';\nimport { CommandError } from './types';\nimport type { CommandContext } from './types';\n\nexport async function handleSetupBrowser(\n ctx: CommandContext,\n cmd: Record<string, unknown>,\n): Promise<Record<string, unknown>> {\n if (!ctx.state.appConfig?.appId) throw new CommandError('No active session', 'NO_SESSION');\n\n const page = ctx.state.browser?.getActivePage();\n if (!page) {\n throw new CommandError(\n 'Sandbox browser unavailable — headless Chrome is required for setup-browser',\n 'NO_BROWSER',\n );\n }\n\n const auth = cmd.auth as { email?: string; phone?: string; roles?: string[] } | undefined;\n const path = (cmd.path as string) || '/';\n\n // Fresh slate: clear any auth cookie the previous test left behind.\n await clearAuthCookies(page);\n\n // Mint + set the automation auth cookie if requested.\n if (auth) {\n const { cookie } = await createAuthSession(ctx.state.appConfig.appId, auth);\n await setAuthCookie(page, cookie);\n }\n\n // Navigate to the target path so the proxy resolves the cookie and the\n // page injects the correct `window.__MINDSTUDIO__` context. puppeteer's\n // goto requires an absolute URL — resolve `path` against the current\n // origin (always the proxy when the sandbox browser is running).\n const absolute = new URL(path, page.url()).toString();\n try {\n await page.goto(absolute, { waitUntil: 'networkidle0', timeout: 15_000 });\n } catch (err) {\n throw new CommandError(\n `Navigation to ${path} failed: ${err instanceof Error ? err.message : String(err)}`,\n 'BROWSER_ERROR',\n );\n }\n\n return { success: true, path, authenticated: !!auth };\n}\n","/**\n * Stdin command router for headless mode.\n *\n * Reads NDJSON commands from stdin and dispatches to individual handlers.\n * Every command must include a `requestId` for response correlation.\n * The router wraps handlers with automatic response framing.\n */\n\nimport { emitResponse } from '../ipc/ipc';\nimport { log } from '../logging/logger';\nimport { handleRunScenario } from './run-scenario';\nimport { handleRunMethod } from './run-method';\nimport { handleImpersonate, handleClearImpersonation } from './impersonate';\nimport { handleBrowser } from './browser';\nimport { handleScreenshotFullPage } from './screenshot-full-page';\nimport { handleDevServerRestarting } from './dev-server-restarting';\nimport { handleDbQuery } from './db-query';\nimport { handleSetupBrowser } from './setup-browser';\nimport { CommandError } from './types';\nimport type { SessionState, CommandContext, CommandHandler } from './types';\n\nexport type { SessionState } from './types';\n\nconst handlers: Record<string, CommandHandler> = {\n 'run-method': handleRunMethod,\n 'run-scenario': handleRunScenario,\n 'impersonate': handleImpersonate,\n 'clear-impersonation': handleClearImpersonation,\n 'browser': handleBrowser,\n 'screenshotFullPage': handleScreenshotFullPage,\n 'db-query': handleDbQuery,\n 'setup-browser': handleSetupBrowser,\n 'dev-server-restarting': handleDevServerRestarting,\n};\n\nexport function setupStdinCommands(\n state: SessionState,\n cwd: string,\n): void {\n if (!process.stdin.readable) return;\n\n let buffer = '';\n process.stdin.setEncoding('utf-8');\n process.stdin.on('data', (chunk: string) => {\n buffer += chunk;\n let idx: number;\n while ((idx = buffer.indexOf('\\n')) !== -1) {\n const line = buffer.slice(0, idx).trim();\n buffer = buffer.slice(idx + 1);\n if (!line) continue;\n\n let cmd: { action: string; requestId?: string; [key: string]: unknown };\n try {\n cmd = JSON.parse(line);\n } catch {\n log.warn('stdin', 'Invalid JSON on stdin', { preview: line.slice(0, 100) });\n continue;\n }\n\n handleStdinCommand(cmd, state, cwd);\n }\n });\n}\n\nasync function handleStdinCommand(\n cmd: { action: string; requestId?: string; [key: string]: unknown },\n state: SessionState,\n cwd: string,\n): Promise<void> {\n const { requestId, action } = cmd;\n\n if (!requestId) {\n log.warn('stdin', 'Command rejected: missing requestId', { action });\n return;\n }\n\n const handler = handlers[action];\n if (!handler) {\n emitResponse(action ?? 'unknown', requestId, 'completed', {\n success: false,\n error: `Unknown action: ${action}`,\n errorCode: 'UNKNOWN_ACTION',\n });\n return;\n }\n\n log.info('stdin', 'Command received', { requestId, action });\n\n const ctx: CommandContext = {\n state,\n cwd,\n requestId,\n started: (data) => emitResponse(action, requestId, 'started', data),\n };\n\n try {\n const result = await handler(ctx, cmd);\n log.info('stdin', 'Command complete', { requestId, action, success: result.success !== false });\n emitResponse(action, requestId, 'completed', result);\n } catch (err) {\n const code = err instanceof CommandError ? err.code : 'INFRASTRUCTURE';\n const message = err instanceof Error ? err.message : String(err);\n log.warn('stdin', 'Command failed', { requestId, action, error: message, errorCode: code });\n emitResponse(action, requestId, 'completed', {\n success: false,\n error: message,\n errorCode: code,\n });\n }\n}\n","/**\n * Headless Dev Mode\n *\n * Runs the MindStudio dev tunnel without a TUI. Designed for programmatic\n * control by a parent process (e.g., a sandbox C&C server or CI pipeline).\n *\n * Outputs structured JSON events to stdout (one per line, newline-delimited).\n * The parent process reads these to track session state, method execution,\n * errors, and connection health.\n *\n * Does NOT start a dev server — the parent process manages that separately.\n * The tunnel just needs to know which port to proxy to.\n *\n * @module\n */\n\nimport { DevRunner } from './dev/execution/runner';\nimport { DevProxy } from './dev/proxy/proxy';\nimport { BrowserSupervisor } from './dev/browser';\nimport { syncSchema } from './dev/api';\nimport {\n detectAppConfig,\n getWebInterfaceConfig,\n readTableSources,\n} from './dev/config/app-config';\nimport { initRequestLog, closeRequestLog } from './dev/logging/request-log';\nimport { initBrowserLog, closeBrowserLog } from './dev/logging/browser-log';\nimport { subscribeDevEvents } from './dev/ipc/session-events';\nimport { setupStdinCommands, type SessionState } from './dev/stdin-commands';\nimport { emitEvent } from './dev/ipc/ipc';\nimport {\n getApiKey,\n getApiBaseUrl,\n getUserId,\n getEnvironment,\n getConfigPath,\n} from './config';\nimport { initLoggerHeadless, log, type LogLevel } from './dev/logging/logger';\nimport { stablePort, detectGitBranch } from './dev/utils';\nimport { watchTableFiles } from './dev/config/table-watcher';\nimport { watchConfigFile } from './dev/config/config-watcher';\n\n/**\n * Options for headless dev mode.\n */\nexport interface HeadlessOptions {\n /** Working directory containing mindstudio.json. Defaults to process.cwd(). */\n cwd?: string;\n /** Port the dev server is running on. If omitted, reads from web.json. If neither, proxy is skipped. */\n devPort?: number;\n /** Preferred port for the local proxy. Defaults to a stable port derived from the app ID. */\n proxyPort?: number;\n /** Bind address for the proxy server. Use '0.0.0.0' for hosted sandboxes. Defaults to '127.0.0.1'. */\n bindAddress?: string;\n /** Log level for stderr output. Defaults to 'info'. */\n logLevel?: LogLevel;\n /** URL for the browser agent script. Defaults to unpkg latest. Set to an ngrok URL for development. */\n browserAgentUrl?: string;\n /** Launch a sandbox-side headless Chrome that participates as a WS client. */\n sandboxBrowser?: boolean;\n}\n\n\n// ---------------------------------------------------------------------------\n// Session lifecycle\n// ---------------------------------------------------------------------------\n\nasync function startSession(\n cwd: string,\n opts: HeadlessOptions,\n state: SessionState,\n shutdown: () => Promise<void>,\n): Promise<boolean> {\n const bindAddress = opts.bindAddress ?? '127.0.0.1';\n\n // Read fresh config\n const appConfig = detectAppConfig(cwd);\n if (!appConfig) {\n emitEvent('config-error', { message: 'No valid mindstudio.json found in ' + cwd });\n return false;\n }\n\n if (!appConfig.appId) {\n emitEvent('config-error', { message: 'Missing \"appId\" in mindstudio.json' });\n return false;\n }\n\n state.appConfig = appConfig;\n\n // Resolve dev port\n let devPort = opts.devPort ?? null;\n if (devPort === null) {\n const webConfig = getWebInterfaceConfig(appConfig, cwd);\n devPort = webConfig?.devPort ?? null;\n }\n\n emitEvent('session-starting', { appId: appConfig.appId, name: appConfig.name });\n\n try {\n // Start platform session\n const branch = detectGitBranch();\n const runner = new DevRunner(appConfig.appId, cwd, {\n branch,\n methods: appConfig.methods.map((m) => ({ id: m.id, export: m.export, path: m.path })),\n });\n runner.setAppConfig(appConfig);\n const session = await runner.start();\n state.runner = runner;\n\n // Initialize logs\n initRequestLog(cwd);\n initBrowserLog(cwd);\n\n // Sync schema\n if (appConfig.tables.length > 0) {\n try {\n const tableSources = readTableSources(appConfig, cwd);\n if (tableSources.length > 0) {\n const syncResult = await syncSchema(appConfig.appId, session.sessionId, tableSources);\n session.databases = syncResult.databases;\n emitEvent('schema-sync-completed', {\n created: syncResult.created,\n altered: syncResult.altered,\n errors: syncResult.errors,\n });\n } else {\n log.warn('session', 'No table source files found, skipping schema sync', {\n expected: appConfig.tables.map((t) => t.path),\n });\n }\n } catch (err) {\n emitEvent('schema-sync-completed', {\n created: [],\n altered: [],\n errors: [err instanceof Error ? err.message : 'Schema sync failed'],\n });\n }\n }\n\n // Start or reuse proxy\n if (devPort !== null && session.clientContext) {\n if (state.proxy) {\n // Proxy persists across restarts — just update the context\n state.proxy.updateClientContext(session.clientContext);\n } else {\n const proxy = new DevProxy(devPort, session.clientContext, appConfig.appId, bindAddress, opts.browserAgentUrl);\n const preferred = opts.proxyPort ?? stablePort(appConfig.appId);\n const proxyPort = await proxy.start(preferred);\n state.proxy = proxy;\n state.proxyPort = proxyPort;\n }\n\n runner.setProxyUrl(`http://${bindAddress === '0.0.0.0' ? 'localhost' : bindAddress}:${state.proxyPort}`);\n runner.setProxy(state.proxy);\n\n // Optional sandbox-side headless Chrome. Connects back to the proxy\n // as just another WS client; the proxy registers it with mode='headless'\n // and getCommandTarget() prefers it for automation. Viewport follows\n // the web interface's defaultPreviewMode so mobile-first apps render\n // at mobile dimensions in the sandbox Chrome too.\n if (opts.sandboxBrowser && state.proxyPort !== null && !state.browser) {\n const webConfig = getWebInterfaceConfig(appConfig, cwd);\n const previewMode = webConfig?.defaultPreviewMode ?? 'desktop';\n const supervisor = new BrowserSupervisor(state.proxyPort, previewMode);\n state.browser = supervisor;\n supervisor.start().catch((err) => {\n log.warn('browser', 'Sandbox browser failed to start', {\n error: err instanceof Error ? err.message : String(err),\n });\n });\n }\n }\n\n emitEvent('session-started', {\n sessionId: session.sessionId,\n releaseId: session.releaseId,\n branch: session.branch,\n proxyPort: state.proxyPort,\n proxyUrl: state.proxyPort\n ? `http://${bindAddress === '0.0.0.0' ? 'localhost' : bindAddress}:${state.proxyPort}/`\n : null,\n webInterfaceUrl: session.webInterfaceUrl,\n roles: appConfig.roles.map((r) => ({ id: r.id, name: r.name ?? r.id, description: r.description })),\n scenarios: appConfig.scenarios.map((s) => ({\n id: s.id,\n name: s.name ?? s.export,\n description: s.description,\n path: s.path,\n roles: s.roles,\n })),\n });\n\n // Subscribe to runner events\n state.unsubscribers.push(...subscribeDevEvents(shutdown));\n\n // Watch table source files for changes — auto-sync without session restart\n setupTableWatchers(cwd, state);\n\n // Start polling for platform method requests now that schema sync,\n // proxy, and watchers are all set up. Starting earlier would risk\n // executing methods against stale session state (e.g. missing tables).\n runner.startPolling();\n\n return true;\n } catch (err) {\n emitEvent('config-error', {\n message: err instanceof Error ? err.message : 'Failed to start session',\n });\n return false;\n }\n}\n\nfunction setupTableWatchers(cwd: string, state: SessionState): void {\n if (!state.appConfig || state.appConfig.tables.length === 0) return;\n\n const cleanup = watchTableFiles(state.appConfig.tables, cwd, async () => {\n if (!state.runner || !state.appConfig?.appId) return;\n const session = state.runner.getSession();\n if (!session) return;\n\n emitEvent('schema-sync-started');\n log.info('session', 'Table source file changed, syncing schema');\n\n try {\n const tableSources = readTableSources(state.appConfig, cwd);\n if (tableSources.length > 0) {\n const result = await syncSchema(state.appConfig.appId, session.sessionId, tableSources);\n session.databases = result.databases;\n emitEvent('schema-sync-completed', {\n created: result.created,\n altered: result.altered,\n errors: result.errors,\n });\n log.info('session', 'Schema sync complete', { created: result.created, altered: result.altered });\n } else {\n log.warn('session', 'Table source file change detected but file(s) still missing', {\n expected: state.appConfig.tables.map((t) => t.path),\n });\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Schema sync failed';\n emitEvent('schema-sync-completed', { created: [], altered: [], errors: [message] });\n log.warn('session', 'Schema sync failed', { error: message });\n }\n });\n\n state.unsubscribers.push(cleanup);\n}\n\n/** Tear down the runner, logs, and watchers. Proxy stays alive for reuse. */\nasync function teardownRunner(state: SessionState): Promise<void> {\n for (const unsub of state.unsubscribers) unsub();\n state.unsubscribers = [];\n\n if (state.runner) {\n await state.runner.stop().catch(() => {});\n state.runner = null;\n }\n\n closeRequestLog();\n closeBrowserLog();\n}\n\n/** Full teardown including proxy. Used on process shutdown. */\nasync function teardownAll(state: SessionState): Promise<void> {\n await teardownRunner(state);\n\n if (state.browser) {\n await state.browser.stop().catch(() => {});\n state.browser = null;\n }\n\n state.proxy?.stop();\n state.proxy = null;\n state.proxyPort = null;\n}\n\n// ---------------------------------------------------------------------------\n// Entry point\n// ---------------------------------------------------------------------------\n\n/**\n * Start the dev tunnel in headless mode.\n */\nexport async function startHeadless(opts: HeadlessOptions = {}): Promise<void> {\n initLoggerHeadless(opts.logLevel ?? 'info');\n\n const cwd = opts.cwd ?? process.cwd();\n\n const apiKey = getApiKey();\n const userId = getUserId();\n log.info('session', 'Startup config', {\n configPath: getConfigPath(),\n environment: getEnvironment(),\n apiBaseUrl: getApiBaseUrl(),\n hasApiKey: !!apiKey,\n apiKeyPrefix: apiKey ? apiKey.slice(0, 8) + '...' : null,\n hasUserId: !!userId,\n userId: userId ?? null,\n cwd,\n });\n\n const state: SessionState = {\n runner: null,\n proxy: null,\n browser: null,\n appConfig: null,\n proxyPort: null,\n unsubscribers: [],\n };\n\n let restarting = false;\n let cleanupConfigWatcher: (() => void) | undefined;\n\n let stopping = false;\n let degradedRetryTimer: ReturnType<typeof setInterval> | null = null;\n const shutdown = async () => {\n if (stopping) return;\n stopping = true;\n if (degradedRetryTimer) { clearInterval(degradedRetryTimer); degradedRetryTimer = null; }\n emitEvent('session-stopping');\n cleanupConfigWatcher?.();\n await teardownAll(state);\n emitEvent('session-stopped');\n };\n\n process.on('SIGTERM', () => { shutdown().then(() => process.exit(0)); });\n process.on('SIGINT', () => { shutdown().then(() => process.exit(0)); });\n\n // Initial session start — retry a few times with backoff before degrading.\n // Snapshot resumes often hit a transient 400 from /manage/start because the\n // platform-side session state is stale. A short retry usually recovers.\n const MAX_START_RETRIES = 5;\n let started = false;\n for (let attempt = 1; attempt <= MAX_START_RETRIES && !stopping; attempt++) {\n started = await startSession(cwd, opts, state, shutdown);\n if (started) break;\n if (attempt < MAX_START_RETRIES) {\n const delay = Math.min(1000 * 2 ** (attempt - 1), 10_000);\n log.info('session', `Start failed, retrying in ${delay}ms`, { attempt, maxAttempts: MAX_START_RETRIES });\n await new Promise((r) => setTimeout(r, delay));\n }\n }\n\n if (!started && !stopping) {\n emitEvent('degraded-state', {\n reason: 'Config invalid or missing at boot. Waiting for valid mindstudio.json.',\n });\n log.warn('session', 'Booting in degraded state — no valid config. Watching for changes.');\n\n // Periodically retry in degraded state (covers transient platform issues\n // that outlast the initial retry window, e.g. long snapshot resume).\n degradedRetryTimer = setInterval(async () => {\n if (stopping || restarting || state.runner) {\n if (state.runner && degradedRetryTimer) {\n clearInterval(degradedRetryTimer);\n degradedRetryTimer = null;\n }\n return;\n }\n restarting = true;\n try {\n log.info('session', 'Retrying session start from degraded state');\n const ok = await startSession(cwd, opts, state, shutdown);\n if (ok) {\n emitEvent('degraded-state-resolved', { appId: state.appConfig?.appId });\n log.info('session', 'Recovered from degraded state');\n if (degradedRetryTimer) {\n clearInterval(degradedRetryTimer);\n degradedRetryTimer = null;\n }\n }\n } finally {\n restarting = false;\n }\n }, 15_000);\n }\n\n // Stdin command loop\n setupStdinCommands(state, cwd);\n\n // Watch mindstudio.json for changes — validate before teardown so corrupt\n // writes don't kill a running session. In degraded state (no runner), a\n // valid config triggers a fresh startSession.\n cleanupConfigWatcher = watchConfigFile(cwd, async () => {\n if (stopping || restarting) return;\n restarting = true;\n try {\n emitEvent('config-changed');\n\n // Validate BEFORE tearing down the running session\n const newConfig = detectAppConfig(cwd);\n if (!newConfig || !newConfig.appId) {\n emitEvent('config-error', {\n message: 'mindstudio.json is invalid — keeping current session',\n });\n log.warn('session', 'Config change detected but file is invalid, keeping current session');\n return;\n }\n\n const wasDegraded = !state.runner;\n await teardownRunner(state);\n const ok = await startSession(cwd, opts, state, shutdown);\n if (ok) {\n if (wasDegraded) {\n emitEvent('degraded-state-resolved', { appId: newConfig.appId });\n log.info('session', 'Recovered from degraded state');\n if (degradedRetryTimer) { clearInterval(degradedRetryTimer); degradedRetryTimer = null; }\n }\n if (state.proxy) {\n state.proxy.broadcastToClients('reload');\n }\n } else {\n emitEvent('degraded-state', {\n reason: 'Session restart failed after config change. Will retry on next change.',\n });\n log.warn('session', 'Session restart failed, entering degraded state');\n }\n } finally {\n restarting = false;\n }\n });\n\n // Keep the process alive — the poll loop runs in DevRunner\n await new Promise<void>(() => {});\n}\n"],"mappings":"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","names":[]}
|
package/dist/cli.js
CHANGED
|
@@ -18,7 +18,7 @@ async function main() {
|
|
|
18
18
|
sandboxBrowser: process.argv.includes("--sandbox-browser")
|
|
19
19
|
});
|
|
20
20
|
} else {
|
|
21
|
-
const { startTUI } = await import("./tui-
|
|
21
|
+
const { startTUI } = await import("./tui-KTSJTXQG.js");
|
|
22
22
|
await startTUI();
|
|
23
23
|
}
|
|
24
24
|
process.exit(0);
|
package/dist/headless.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -151,7 +151,7 @@ function Header({
|
|
|
151
151
|
/* @__PURE__ */ jsx(Text, { bold: true, color: "white", children: "MindStudio Local Tunnel" }),
|
|
152
152
|
compact && /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
|
|
153
153
|
" v",
|
|
154
|
-
"0.5.
|
|
154
|
+
"0.5.56"
|
|
155
155
|
] }),
|
|
156
156
|
environment !== "prod" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
157
157
|
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
@@ -169,7 +169,7 @@ function Header({
|
|
|
169
169
|
] }),
|
|
170
170
|
!compact && /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
|
|
171
171
|
"v",
|
|
172
|
-
"0.5.
|
|
172
|
+
"0.5.56"
|
|
173
173
|
] })
|
|
174
174
|
] })
|
|
175
175
|
]
|
|
@@ -3788,7 +3788,7 @@ function getInstallMethod() {
|
|
|
3788
3788
|
return "npm";
|
|
3789
3789
|
}
|
|
3790
3790
|
function getCurrentVersion() {
|
|
3791
|
-
return "0.5.
|
|
3791
|
+
return "0.5.56";
|
|
3792
3792
|
}
|
|
3793
3793
|
async function fetchLatestVersion() {
|
|
3794
3794
|
try {
|
|
@@ -4030,4 +4030,4 @@ async function startTUI() {
|
|
|
4030
4030
|
export {
|
|
4031
4031
|
startTUI
|
|
4032
4032
|
};
|
|
4033
|
-
//# sourceMappingURL=tui-
|
|
4033
|
+
//# sourceMappingURL=tui-KTSJTXQG.js.map
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/dev/browser/launcher.ts","../src/dev/browser/chrome-path.ts","../src/dev/ipc/ipc.ts","../src/dev/browser/supervisor.ts","../src/dev/browser/screenshot.ts","../src/dev/browser/cookies.ts","../src/dev/ipc/session-events.ts","../src/dev/stdin-commands/run-scenario.ts","../src/dev/stdin-commands/run-method.ts","../src/dev/stdin-commands/impersonate.ts","../src/dev/stdin-commands/browser.ts","../src/dev/stdin-commands/screenshot-full-page.ts","../src/dev/stdin-commands/dev-server-restarting.ts","../src/dev/stdin-commands/db-query.ts","../src/dev/stdin-commands/setup-browser.ts","../src/dev/stdin-commands/index.ts","../src/headless.ts"],"sourcesContent":["/**\n * Launch a headless Chrome instance pointed at the local tunnel proxy.\n *\n * The launched browser loads `http://127.0.0.1:<proxyPort>/?ms_sandbox=1`.\n * The tunnel proxy injects the browser-agent script as usual, which opens\n * a WebSocket back to the tunnel and registers as a client. The proxy's\n * hello handler recognizes the `ms_sandbox=1` query from a loopback source\n * and forces the client mode to 'headless'.\n *\n * This module knows nothing about the client registry or the command\n * dispatch path — those stay untouched. It only spawns Chrome and navigates.\n */\n\nimport puppeteer, { type Browser, type Page, type Viewport } from 'puppeteer-core';\nimport { resolveChromePath } from './chrome-path';\nimport { log } from '../logging/logger';\n\nexport interface LaunchedBrowser {\n browser: Browser;\n page: Page;\n executablePath: string;\n pid: number | null;\n previewMode: PreviewMode;\n viewport: string;\n}\n\nexport type PreviewMode = 'desktop' | 'mobile';\n\nconst LAUNCH_ARGS = [\n '--no-sandbox',\n '--disable-dev-shm-usage',\n '--disable-gpu',\n '--hide-scrollbars',\n '--force-color-profile=srgb',\n '--font-render-hinting=none',\n '--disable-blink-features=AutomationControlled',\n '--lang=en-US',\n];\n\n// Modern laptop — fits most desktop-first app layouts without extra gutters.\nconst DESKTOP_VIEWPORT: Viewport = {\n width: 1440,\n height: 900,\n deviceScaleFactor: 1,\n isMobile: false,\n hasTouch: false,\n};\n\n// iPhone 15 Pro portrait. DPR 2 is the sweet spot — retina-ish fidelity\n// without 3× screenshot bloat. `isMobile`/`hasTouch` engage Chrome's mobile\n// emulation (viewport meta tag handling, touch events, orientation APIs).\nconst MOBILE_VIEWPORT: Viewport = {\n width: 390,\n height: 844,\n deviceScaleFactor: 2,\n isMobile: true,\n hasTouch: true,\n};\n\nfunction viewportFor(mode: PreviewMode): Viewport {\n return mode === 'mobile' ? MOBILE_VIEWPORT : DESKTOP_VIEWPORT;\n}\n\nexport async function launchSandboxBrowser(opts: {\n proxyPort: number;\n previewMode?: PreviewMode;\n}): Promise<LaunchedBrowser | null> {\n const executablePath = resolveChromePath();\n if (!executablePath) {\n log.warn(\n 'browser',\n 'No Chrome executable found — sandbox-browser mode disabled for this session',\n );\n return null;\n }\n\n const previewMode: PreviewMode = opts.previewMode === 'mobile' ? 'mobile' : 'desktop';\n const viewport = viewportFor(previewMode);\n\n const browser = await puppeteer.launch({\n executablePath,\n headless: true,\n args: LAUNCH_ARGS,\n defaultViewport: viewport,\n });\n\n // Pipe Chrome stderr through the debug logger. Chrome is chatty on startup\n // and we don't want that at info level.\n const proc = browser.process();\n proc?.stderr?.on('data', (buf: Buffer) => {\n const line = buf.toString().trim();\n if (line) log.debug('browser-chrome', line);\n });\n\n const pages = await browser.pages();\n const page = pages[0] ?? (await browser.newPage());\n\n const target = `http://127.0.0.1:${opts.proxyPort}/?ms_sandbox=1`;\n // `networkidle0` waits for the injected `<script async>` browser-agent to\n // finish loading AND its WebSocket to open (at which point the page is\n // idle). That way `running` corresponds to \"ready for both CDP *and* WS\n // tool calls\", closing the first-tool-call race where the WS client\n // hadn't registered before the first command dispatched.\n try {\n await page.goto(target, { waitUntil: 'networkidle0', timeout: 15_000 });\n } catch (err) {\n // Leaked Chromium otherwise — if navigation fails, close the browser\n // so the supervisor's restart loop can start clean.\n await browser.close().catch(() => {});\n throw err;\n }\n\n const viewportStr = `${viewport.width}x${viewport.height}@${viewport.deviceScaleFactor}x`;\n\n log.info('browser', 'Sandbox browser launched', {\n executablePath,\n target,\n previewMode,\n viewport: viewportStr,\n pid: proc?.pid ?? null,\n });\n\n return {\n browser,\n page,\n executablePath,\n pid: proc?.pid ?? null,\n previewMode,\n viewport: viewportStr,\n };\n}\n","/**\n * Resolve the path to a Chrome/Chromium executable. Returns null if none\n * found — the supervisor downgrades to a no-op and logs in that case.\n *\n * The sandbox image bakes in `google-chrome-stable`. On dev machines\n * the user may have Chrome installed at a different path; we probe a\n * short list of common locations.\n */\n\nimport { existsSync } from 'node:fs';\nimport { execSync } from 'node:child_process';\n\nconst CANDIDATES = [\n '/usr/bin/google-chrome-stable',\n '/usr/bin/google-chrome',\n '/usr/bin/chromium',\n '/usr/bin/chromium-browser',\n '/opt/google/chrome/google-chrome',\n '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',\n '/Applications/Chromium.app/Contents/MacOS/Chromium',\n];\n\nconst PATH_COMMANDS = ['google-chrome-stable', 'google-chrome', 'chromium'];\n\nexport function resolveChromePath(): string | null {\n for (const candidate of CANDIDATES) {\n if (existsSync(candidate)) return candidate;\n }\n\n for (const cmd of PATH_COMMANDS) {\n try {\n const resolved = execSync(`command -v ${cmd}`, {\n encoding: 'utf-8',\n stdio: ['ignore', 'pipe', 'ignore'],\n }).trim();\n if (resolved && existsSync(resolved)) return resolved;\n } catch {\n // Not on PATH — try next\n }\n }\n\n return null;\n}\n","/**\n * Central IPC module for headless mode.\n *\n * All stdout writes go through here. Two distinct message types:\n * - System events: unsolicited, no requestId (session lifecycle, connection, etc.)\n * - Command responses: always have requestId + status (started/completed)\n *\n * The caller distinguishes them by the presence of `requestId`.\n */\n\n/**\n * Emit a system event (no requestId).\n * Used for unsolicited events: session lifecycle, connection health, auth, etc.\n */\nexport function emitEvent(event: string, data?: Record<string, unknown>): void {\n process.stdout.write(JSON.stringify({ event, ...data }) + '\\n');\n}\n\n/**\n * Emit a command response (always has requestId).\n * Used for responses to stdin commands.\n */\nexport function emitResponse(\n action: string,\n requestId: string,\n status: 'started' | 'completed',\n data?: Record<string, unknown>,\n): void {\n process.stdout.write(\n JSON.stringify({ event: action, requestId, status, ...data }) + '\\n',\n );\n}\n","/**\n * BrowserSupervisor — keeps a headless Chrome instance alive for the lifetime\n * of a dev session.\n *\n * Responsibilities:\n * - Launch Chrome once at session start.\n * - Watch for unexpected disconnect (Chrome crash, killed process).\n * - Restart with exponential backoff; enter degraded mode after repeated\n * failures so automation falls through to user-browser clients.\n * - Clean teardown on session stop so no orphan Chrome processes linger.\n *\n * Emits structured `sandbox-browser-state` events on stdout at every state\n * transition so the sandbox manager can track Chrome in its /status surface\n * (resource metrics, debug bundles, degraded-mode alerts).\n *\n * The supervisor does NOT dispatch commands. Chrome connects back over the\n * existing WS path and the proxy's client registry picks it up like any\n * other client.\n */\n\nimport type { Browser, Page } from 'puppeteer-core';\nimport { launchSandboxBrowser, type PreviewMode } from './launcher';\nimport { log } from '../logging/logger';\nimport { emitEvent } from '../ipc/ipc';\n\nconst BACKOFF_MS = [1_000, 2_000, 4_000, 8_000, 16_000, 30_000];\nconst MAX_FAILURES = 5;\nconst CLOSE_TIMEOUT_MS = 5_000;\n\nexport class BrowserSupervisor {\n private browser: Browser | null = null;\n private page: Page | null = null;\n private stopping = false;\n private degraded = false;\n private consecutiveFailures = 0;\n private restartTimer: ReturnType<typeof setTimeout> | null = null;\n private runningSince: number | null = null;\n private lastExitInfo: {\n exitCode: number | null;\n signal: string | null;\n } | null = null;\n\n constructor(\n private readonly proxyPort: number,\n private readonly previewMode: PreviewMode = 'desktop',\n ) {}\n\n async start(): Promise<void> {\n if (this.browser) return;\n await this.launchOnce();\n }\n\n async stop(): Promise<void> {\n if (this.stopping) return; // idempotent — double SIGTERM shouldn't double-fire events\n this.stopping = true;\n if (this.restartTimer) {\n clearTimeout(this.restartTimer);\n this.restartTimer = null;\n }\n const browser = this.browser;\n this.browser = null;\n this.page = null;\n if (browser) {\n await this.closeBrowser(browser);\n }\n this.runningSince = null;\n this.lastExitInfo = null;\n emitEvent('sandbox-browser-state', { state: 'stopped' });\n }\n\n isRunning(): boolean {\n return !!this.browser && !this.degraded;\n }\n\n isDegraded(): boolean {\n return this.degraded;\n }\n\n /**\n * Returns the active puppeteer Page when the sandbox browser is running\n * and not degraded; null otherwise. Callers use this to decide whether\n * a CDP-side fast path is available for a given command.\n */\n getActivePage(): Page | null {\n if (this.stopping || this.degraded) return null;\n if (!this.browser || !this.page) return null;\n return this.page;\n }\n\n private async launchOnce(): Promise<void> {\n if (this.stopping) return;\n\n const attempt = this.consecutiveFailures + 1;\n log.info('browser', 'Sandbox browser launch starting', {\n proxyPort: this.proxyPort,\n attempt,\n });\n emitEvent('sandbox-browser-state', {\n state: 'starting',\n attempt,\n previewMode: this.previewMode,\n });\n\n try {\n const launched = await launchSandboxBrowser({\n proxyPort: this.proxyPort,\n previewMode: this.previewMode,\n });\n if (!launched) {\n // No Chrome executable — enter degraded mode permanently for this session.\n this.degraded = true;\n emitEvent('sandbox-browser-state', {\n state: 'degraded',\n reason: 'no-executable',\n });\n return;\n }\n\n // If stop() landed while we were launching, the supervisor has already\n // emitted `stopped` and cleared its state. Don't register the browser\n // we just got — close it and bail, otherwise we'd leak Chromium.\n if (this.stopping) {\n await this.closeBrowser(launched.browser).catch(() => {});\n return;\n }\n\n this.browser = launched.browser;\n this.page = launched.page;\n this.consecutiveFailures = 0;\n this.degraded = false;\n this.runningSince = Date.now();\n this.lastExitInfo = null;\n\n // Capture exit info directly from the child process so `crashed` events\n // carry an accurate signal / exitCode alongside puppeteer's `disconnected`.\n const proc = launched.browser.process();\n proc?.once('exit', (code, signal) => {\n this.lastExitInfo = { exitCode: code, signal: signal ?? null };\n });\n\n launched.browser.on('disconnected', () => this.onDisconnect());\n\n emitEvent('sandbox-browser-state', {\n state: 'running',\n pid: launched.pid,\n previewMode: launched.previewMode,\n viewport: launched.viewport,\n executablePath: launched.executablePath,\n });\n } catch (err) {\n // Don't track failures or restart if we were torn down mid-launch.\n if (this.stopping) return;\n\n this.consecutiveFailures++;\n const message = err instanceof Error ? err.message : String(err);\n log.warn('browser', 'Failed to launch sandbox browser', {\n attempt: this.consecutiveFailures,\n error: message,\n });\n emitEvent('sandbox-browser-state', {\n state: 'crashed',\n exitCode: null,\n signal: null,\n durationMs: 0,\n consecutiveFailures: this.consecutiveFailures,\n error: message,\n });\n this.scheduleRestart();\n }\n }\n\n private async onDisconnect(): Promise<void> {\n if (this.stopping) return;\n const hadBrowser = !!this.browser;\n this.browser = null;\n this.page = null;\n if (!hadBrowser) return;\n\n this.consecutiveFailures++;\n const durationMs = this.runningSince ? Date.now() - this.runningSince : 0;\n this.runningSince = null;\n log.warn('browser', 'Sandbox browser disconnected', {\n attempt: this.consecutiveFailures,\n });\n\n // puppeteer's disconnect sometimes fires before the child's `exit` listener,\n // leaving exit info unpopulated. Give that listener a short window.\n await this.waitForExitInfo();\n\n emitEvent('sandbox-browser-state', {\n state: 'crashed',\n exitCode: this.lastExitInfo?.exitCode ?? null,\n signal: this.lastExitInfo?.signal ?? null,\n durationMs,\n consecutiveFailures: this.consecutiveFailures,\n });\n this.lastExitInfo = null;\n this.scheduleRestart();\n }\n\n private async waitForExitInfo(timeoutMs = 200): Promise<void> {\n if (this.lastExitInfo) return;\n const deadline = Date.now() + timeoutMs;\n while (!this.lastExitInfo && Date.now() < deadline) {\n await new Promise((r) => setTimeout(r, 20));\n }\n }\n\n private scheduleRestart(): void {\n if (this.stopping) return;\n\n if (this.consecutiveFailures >= MAX_FAILURES) {\n this.degraded = true;\n log.warn(\n 'browser',\n 'Sandbox browser entering degraded mode after repeated failures — automation will fall back to user browsers',\n { failures: this.consecutiveFailures },\n );\n emitEvent('sandbox-browser-state', {\n state: 'degraded',\n reason: 'repeated-crashes',\n consecutiveFailures: this.consecutiveFailures,\n });\n return;\n }\n\n const delay =\n BACKOFF_MS[Math.min(this.consecutiveFailures, BACKOFF_MS.length - 1)];\n log.info('browser', 'Scheduling sandbox browser restart', {\n delayMs: delay,\n attempt: this.consecutiveFailures,\n });\n emitEvent('sandbox-browser-state', {\n state: 'restarting',\n delayMs: delay,\n nextAttempt: this.consecutiveFailures + 1,\n });\n this.restartTimer = setTimeout(() => {\n this.restartTimer = null;\n void this.launchOnce();\n }, delay);\n }\n\n private async closeBrowser(browser: Browser): Promise<void> {\n let resolved = false;\n await new Promise<void>((resolve) => {\n const done = () => {\n if (resolved) return;\n resolved = true;\n resolve();\n };\n const timeout = setTimeout(() => {\n // Graceful close timed out — kill the underlying process.\n try {\n browser.process()?.kill('SIGKILL');\n } catch {\n // Best effort\n }\n done();\n }, CLOSE_TIMEOUT_MS);\n\n browser\n .close()\n .then(() => {\n clearTimeout(timeout);\n done();\n })\n .catch(() => {\n clearTimeout(timeout);\n try {\n browser.process()?.kill('SIGKILL');\n } catch {\n // Best effort\n }\n done();\n });\n });\n }\n}\n","/**\n * CDP-based screenshot capture.\n *\n * Runs inside the tunnel (Node) against the puppeteer Page owned by the\n * BrowserSupervisor. Produces real pixels via Chrome's own rendering path\n * (replacing browser-agent's snapdom DOM→SVG→Canvas pipeline for headless\n * targets) and uploads the result to the same presigned S3 URL the WS\n * path uses, so callers see an identical result shape.\n */\n\nimport type { Page } from 'puppeteer-core';\n\nexport interface CaptureOpts {\n fullPage: boolean;\n path?: string;\n uploadUrl: string;\n uploadFields: Record<string, string>;\n}\n\nexport interface CaptureResult {\n uploaded: true;\n width: number;\n height: number;\n styleMap?: string;\n}\n\nconst GOTO_TIMEOUT_MS = 15_000;\nconst SETTLE_TIMEOUT_MS = 3_000;\nconst SETTLE_IDLE_MS = 200;\nconst JPEG_QUALITY = 85;\n// Pre-roll timings: used only for fullPage captures to trigger\n// IntersectionObservers, lazy-loaded images, and scroll-linked animations\n// before the single-shot CDP capture.\nconst PREROLL_BOTTOM_DWELL_MS = 300;\nconst PREROLL_NETWORK_IDLE_MS = 1_500;\nconst PREROLL_TOP_DWELL_MS = 100;\n\nexport async function captureViaCdp(\n page: Page,\n opts: CaptureOpts,\n): Promise<CaptureResult> {\n if (opts.path) {\n await page.goto(opts.path, {\n waitUntil: 'networkidle0',\n timeout: GOTO_TIMEOUT_MS,\n });\n }\n\n // Match browser-agent's in-page network-idle settle so layout/fonts are\n // stable at capture time. Swallow timeout — best-effort.\n await page\n .waitForNetworkIdle({ timeout: SETTLE_TIMEOUT_MS, idleTime: SETTLE_IDLE_MS })\n .catch(() => {});\n\n // Pre-roll for fullPage captures only. CDP's `fullPage: true` renders in a\n // single pass with the viewport logically at the top, so IntersectionObserver\n // callbacks, lazy-loaded images, and scroll-triggered animations never fire.\n // Scrolling to the bottom and back nudges them into their revealed state;\n // Chrome then captures the fully-revealed layout in one shot.\n if (opts.fullPage) {\n await preRollScroll(page);\n }\n\n let width: number;\n let height: number;\n if (opts.fullPage) {\n const dims = await page.evaluate(() => ({\n width: document.documentElement.scrollWidth,\n height: document.documentElement.scrollHeight,\n }));\n width = dims.width;\n height = dims.height;\n } else {\n const vp = page.viewport();\n width = vp?.width ?? 0;\n height = vp?.height ?? 0;\n }\n\n // Best-effort styleMap via the already-loaded browser-agent. The browser\n // agent is injected into every page the proxy serves, so it's running in\n // this Chrome instance too. Silently skipped if the served version\n // predates the exposed API.\n let styleMap: string | undefined;\n try {\n const result = await page.evaluate(() => {\n const api = (window as unknown as {\n __MINDSTUDIO_BROWSER_AGENT__?: { computeStyleMap?: () => string };\n }).__MINDSTUDIO_BROWSER_AGENT__;\n return api?.computeStyleMap?.() ?? null;\n });\n if (typeof result === 'string' && result.length > 0) styleMap = result;\n } catch {\n // Non-fatal — styleMap stays undefined.\n }\n\n const buf = (await page.screenshot({\n type: 'jpeg',\n quality: JPEG_QUALITY,\n fullPage: opts.fullPage,\n })) as Buffer;\n\n await uploadToPresigned(opts.uploadUrl, opts.uploadFields, buf);\n\n return {\n uploaded: true,\n width,\n height,\n ...(styleMap ? { styleMap } : {}),\n };\n}\n\n/**\n * Scroll the document to the bottom, wait for observer callbacks and any\n * lazy-loaded content to settle, then scroll back to the top. Gives\n * fullPage captures a chance to include scroll-triggered fade-ins, lazy\n * images, and windowed-list items.\n *\n * Best-effort — all timeouts swallowed. If the page can't be scrolled\n * (short content, scroll-locked body) the function is effectively a no-op.\n */\nasync function preRollScroll(page: Page): Promise<void> {\n try {\n const scrolled = await page.evaluate(() => {\n const el = document.scrollingElement || document.documentElement;\n const max = Math.max(\n document.documentElement.scrollHeight,\n document.body.scrollHeight,\n );\n if (max <= window.innerHeight + 10) return false; // nothing to scroll\n el.scrollTo({ top: max, left: 0, behavior: 'instant' as ScrollBehavior });\n return true;\n });\n\n if (!scrolled) return;\n\n // Let IntersectionObservers fire and any triggered animations settle.\n await new Promise((r) => setTimeout(r, PREROLL_BOTTOM_DWELL_MS));\n\n // If the observers kicked off image/data loads, wait for them briefly.\n await page\n .waitForNetworkIdle({\n timeout: PREROLL_NETWORK_IDLE_MS,\n idleTime: SETTLE_IDLE_MS,\n })\n .catch(() => {});\n\n await page.evaluate(() => {\n const el = document.scrollingElement || document.documentElement;\n el.scrollTo({ top: 0, left: 0, behavior: 'instant' as ScrollBehavior });\n });\n\n await new Promise((r) => setTimeout(r, PREROLL_TOP_DWELL_MS));\n } catch {\n // Non-fatal — proceed to capture regardless.\n }\n}\n\nasync function uploadToPresigned(\n uploadUrl: string,\n uploadFields: Record<string, string>,\n buf: Buffer,\n): Promise<void> {\n const form = new FormData();\n for (const [k, v] of Object.entries(uploadFields)) form.append(k, v);\n form.append(\n 'file',\n new Blob([buf as unknown as BlobPart], { type: 'image/jpeg' }),\n 'screenshot.jpg',\n );\n const res = await fetch(uploadUrl, { method: 'POST', body: form });\n if (!res.ok) {\n throw new Error(`Screenshot upload failed: ${res.status}`);\n }\n}\n","/**\n * Auth-cookie helpers for the sandbox-owned Chrome.\n *\n * `setup-browser` and `reset-browser` both operate on the `__ms_auth` cookie\n * via CDP now — no more WS round-trip through browser-agent. These wrappers\n * keep the cookie shape + lifetime in one place.\n */\n\nimport type { Page } from 'puppeteer-core';\n\nconst AUTH_COOKIE_NAME = '__ms_auth';\n\nfunction cookieHost(page: Page): string {\n try {\n return new URL(page.url()).hostname || '127.0.0.1';\n } catch {\n return '127.0.0.1';\n }\n}\n\nexport async function clearAuthCookies(page: Page): Promise<void> {\n const domain = cookieHost(page);\n try {\n await page.deleteCookie({ name: AUTH_COOKIE_NAME, domain });\n } catch {\n // Cookie may not exist — fine.\n }\n // `deleteCookie` is scoped by domain; make sure any `/`-path variants go too.\n try {\n await page.deleteCookie({ name: AUTH_COOKIE_NAME });\n } catch {\n // Best effort.\n }\n}\n\nexport async function setAuthCookie(page: Page, value: string): Promise<void> {\n const domain = cookieHost(page);\n await page.setCookie({\n name: AUTH_COOKIE_NAME,\n value,\n domain,\n path: '/',\n sameSite: 'None',\n secure: true,\n });\n}\n","/**\n * Subscribe to DevRunner events and relay them as system events to stdout.\n * Only relays genuinely unsolicited events (poll-loop methods, connection, auth).\n * Command responses (scenarios, impersonation) are handled by stdin handlers directly.\n *\n * Returns an array of unsubscribe functions for cleanup on teardown.\n */\n\nimport { devRequestEvents } from './events';\nimport { emitEvent } from './ipc';\n\nexport function subscribeDevEvents(\n shutdown: () => Promise<void>,\n): Array<() => void> {\n const unsubs: Array<() => void> = [];\n\n // Platform-triggered method execution (poll loop)\n unsubs.push(\n devRequestEvents.onStart((event) => {\n emitEvent('platform-method-started', { id: event.id, method: event.method });\n }),\n );\n\n unsubs.push(\n devRequestEvents.onComplete((event) => {\n emitEvent('platform-method-completed', {\n id: event.id,\n success: event.success,\n duration: event.duration,\n ...(event.error ? { error: event.error } : {}),\n });\n }),\n );\n\n // Connection health\n unsubs.push(\n devRequestEvents.onConnectionWarning((message) => {\n emitEvent('connection-lost', { message });\n }),\n );\n\n unsubs.push(\n devRequestEvents.onConnectionRestored(() => {\n emitEvent('connection-restored');\n }),\n );\n\n // Session expiry\n unsubs.push(\n devRequestEvents.onSessionExpired(() => {\n emitEvent('session-expired');\n shutdown().then(() => process.exit(1));\n }),\n );\n\n // Auth refresh\n unsubs.push(\n devRequestEvents.onAuthRefreshStart((url) => {\n emitEvent('auth-refresh-start', { url });\n }),\n );\n\n unsubs.push(\n devRequestEvents.onAuthRefreshSuccess(() => {\n emitEvent('auth-refresh-success');\n }),\n );\n\n unsubs.push(\n devRequestEvents.onAuthRefreshFailed(() => {\n emitEvent('auth-refresh-failed');\n }),\n );\n\n return unsubs;\n}\n","import { detectAppConfig } from '../config/app-config';\nimport { CommandError } from './types';\nimport type { CommandContext } from './types';\n\nexport async function handleRunScenario(\n ctx: CommandContext,\n cmd: Record<string, unknown>,\n): Promise<Record<string, unknown>> {\n if (!ctx.state.runner) throw new CommandError('No active session', 'NO_SESSION');\n\n const freshConfig = detectAppConfig(ctx.cwd) ?? ctx.state.appConfig;\n const scenario = freshConfig?.scenarios.find((s) => s.id === cmd.scenarioId);\n if (!scenario) throw new CommandError(`Unknown scenario: ${cmd.scenarioId}`, 'INVALID_INPUT');\n\n const scenarioName = scenario.name ?? scenario.export;\n ctx.started({ scenarioId: scenario.id, name: scenarioName });\n\n const skipTruncate = cmd.skipTruncate === true;\n const result = await ctx.state.runner.runScenario(scenario, { skipTruncate });\n\n // Reset the browser so it picks up the new data/roles from the scenario\n if (result.success && ctx.state.proxy?.isBrowserConnected()) {\n ctx.state.proxy.broadcastToClients('reload');\n }\n\n return {\n success: result.success,\n scenarioId: scenario.id,\n name: scenarioName,\n error: result.error ?? null,\n errorCode: result.success ? undefined : 'EXECUTION_ERROR',\n };\n}\n","import { detectAppConfig } from '../config/app-config';\nimport { CommandError } from './types';\nimport type { CommandContext } from './types';\n\nexport async function handleRunMethod(\n ctx: CommandContext,\n cmd: Record<string, unknown>,\n): Promise<Record<string, unknown>> {\n if (!ctx.state.runner) throw new CommandError('No active session', 'NO_SESSION');\n\n const methodName = cmd.method as string;\n if (!methodName) throw new CommandError('run-method requires \"method\" (export name or ID)', 'INVALID_INPUT');\n\n const freshConfig = detectAppConfig(ctx.cwd) ?? ctx.state.appConfig;\n const method =\n freshConfig?.methods.find((m) => m.export === methodName) ??\n freshConfig?.methods.find((m) => m.id === methodName);\n if (!method) throw new CommandError(`Unknown method: ${methodName}`, 'INVALID_INPUT');\n\n ctx.started({ method: method.export });\n\n const result = await ctx.state.runner.runMethod({\n methodExport: method.export,\n methodPath: method.path,\n input: cmd.input ?? {},\n roles: Array.isArray(cmd.roles) ? cmd.roles as string[] : undefined,\n userId: typeof cmd.userId === 'string' ? cmd.userId : undefined,\n });\n\n return {\n success: result.success,\n method: method.export,\n output: result.output ?? null,\n error: result.error?.message ?? null,\n errorCode: result.success ? undefined : 'EXECUTION_ERROR',\n errorDetail: result.error ?? null,\n stdout: result.stdout ?? [],\n duration: result.duration,\n };\n}\n","import { CommandError } from './types';\nimport type { CommandContext } from './types';\n\nexport async function handleImpersonate(\n ctx: CommandContext,\n cmd: Record<string, unknown>,\n): Promise<Record<string, unknown>> {\n if (!ctx.state.runner) throw new CommandError('No active session', 'NO_SESSION');\n\n const roles = cmd.roles as string[];\n if (!Array.isArray(roles)) throw new CommandError('impersonate requires roles array', 'INVALID_INPUT');\n\n await ctx.state.runner.setImpersonation(roles);\n return { success: true, roles };\n}\n\nexport async function handleClearImpersonation(\n ctx: CommandContext,\n): Promise<Record<string, unknown>> {\n if (!ctx.state.runner) throw new CommandError('No active session', 'NO_SESSION');\n\n await ctx.state.runner.clearImpersonation();\n return { success: true, roles: null };\n}\n","import { getUploadUrl } from '../api';\nimport { captureViaCdp } from '../browser';\nimport { log } from '../logging/logger';\nimport { CommandError } from './types';\nimport type { CommandContext } from './types';\nimport type { Page } from 'puppeteer-core';\n\n// Recordings smaller than this (after JSON serialization) aren't worth\n// the round trip — probably a FullSnapshot with no interesting deltas.\nconst MIN_RECORDING_BYTES = 5_000;\n\nexport async function handleBrowser(\n ctx: CommandContext,\n cmd: Record<string, unknown>,\n): Promise<Record<string, unknown>> {\n if (!ctx.state.proxy) throw new CommandError('No active proxy', 'NO_BROWSER');\n\n const steps = cmd.steps as Array<Record<string, unknown>>;\n if (!Array.isArray(steps) || steps.length === 0) {\n throw new CommandError('browser action requires a non-empty \"steps\" array', 'INVALID_INPUT');\n }\n\n const page = ctx.state.browser?.getActivePage();\n if (!page) {\n throw new CommandError(\n 'Sandbox browser unavailable — headless Chrome is required for automation',\n 'NO_BROWSER',\n );\n }\n\n const resultsByIndex = new Array<Record<string, unknown> | undefined>(\n steps.length,\n );\n let lastSnapshot = '';\n let lastLogs: unknown[] = [];\n let totalDuration = 0;\n const allEvents: unknown[] = [];\n\n let buffer: Array<{ idx: number; step: Record<string, unknown> }> = [];\n\n const flushBuffer = async () => {\n if (buffer.length === 0) return;\n const batch = buffer.map((b) => b.step);\n const out = await ctx.state.proxy!.dispatchBrowserCommand(batch);\n const outSteps = (out.steps as Array<Record<string, unknown>>) ?? [];\n for (let i = 0; i < buffer.length; i++) {\n const returned = outSteps[i] ?? {};\n resultsByIndex[buffer[i].idx] = {\n ...returned,\n index: buffer[i].idx,\n command: buffer[i].step.command,\n };\n }\n if (typeof out.snapshot === 'string' && out.snapshot.length > 0) {\n lastSnapshot = out.snapshot;\n }\n if (Array.isArray(out.logs)) lastLogs = out.logs as unknown[];\n if (typeof out.duration === 'number') totalDuration += out.duration;\n if (Array.isArray(out.events)) allEvents.push(...(out.events as unknown[]));\n buffer = [];\n };\n\n for (let i = 0; i < steps.length; i++) {\n const step = steps[i];\n const command = step.command;\n if (command === 'screenshotFullPage' || command === 'screenshotViewport') {\n await flushBuffer();\n const captured = await captureScreenshotStep(ctx, page, step as Record<string, unknown>, command);\n resultsByIndex[i] = { index: i, command, result: captured };\n totalDuration += captured._durationMs ?? 0;\n delete captured._durationMs;\n } else {\n buffer.push({ idx: i, step });\n }\n }\n await flushBuffer();\n\n const densified = resultsByIndex.map((r, idx) =>\n r ?? { index: idx, command: steps[idx].command, error: 'no result' },\n );\n const hasStepError = densified.some((s) => s?.error);\n const recordingUrl = await uploadRecording(ctx, allEvents);\n\n return {\n success: !hasStepError,\n ...(hasStepError ? { errorCode: 'BROWSER_ERROR' } : {}),\n steps: densified,\n snapshot: lastSnapshot,\n logs: lastLogs,\n duration: totalDuration,\n ...(recordingUrl ? { recordingUrl } : {}),\n };\n}\n\n/**\n * Capture a screenshot step via CDP. Returns a result that matches the\n * shape today's stdin callers expect: `{ url, width, height, styleMap? }`.\n * Navigation before the capture is handled inside `captureViaCdp`.\n */\nasync function captureScreenshotStep(\n ctx: CommandContext,\n page: Page,\n step: Record<string, unknown>,\n command: string,\n): Promise<Record<string, unknown> & { _durationMs?: number }> {\n const session = ctx.state.runner?.getSession();\n const appId = ctx.state.appConfig?.appId;\n if (!session || !appId) {\n throw new CommandError('No active session', 'NO_SESSION');\n }\n const { uploadUrl, uploadFields, publicUrl } = await getUploadUrl(\n appId,\n session.sessionId,\n 'jpg',\n 'image/jpeg',\n );\n const start = Date.now();\n const r = await captureViaCdp(page, {\n fullPage: command === 'screenshotFullPage',\n path: typeof step.path === 'string' ? step.path : undefined,\n uploadUrl,\n uploadFields,\n });\n return {\n url: publicUrl,\n width: r.width,\n height: r.height,\n ...(r.styleMap ? { styleMap: r.styleMap } : {}),\n _durationMs: Date.now() - start,\n };\n}\n\n/**\n * Upload an rrweb event array to S3 using the same presigned-URL flow\n * screenshots use. Returns the public URL on success, null on any failure\n * (including too-small recordings that aren't worth keeping).\n */\nasync function uploadRecording(\n ctx: CommandContext,\n events: unknown[],\n): Promise<string | null> {\n if (events.length === 0) return null;\n const session = ctx.state.runner?.getSession();\n const appId = ctx.state.appConfig?.appId;\n if (!session || !appId) return null;\n\n const body = JSON.stringify(events);\n if (body.length < MIN_RECORDING_BYTES) return null;\n\n try {\n const { uploadUrl, uploadFields, publicUrl } = await getUploadUrl(\n appId,\n session.sessionId,\n 'json',\n 'application/json',\n );\n const form = new FormData();\n for (const [k, v] of Object.entries(uploadFields)) form.append(k, v);\n form.append(\n 'file',\n new Blob([body], { type: 'application/json' }),\n 'recording.json',\n );\n const res = await fetch(uploadUrl, { method: 'POST', body: form });\n if (!res.ok) {\n log.warn('browser', 'Recording upload failed', {\n status: res.status,\n bytes: body.length,\n });\n return null;\n }\n log.info('browser', 'Recording uploaded', {\n bytes: body.length,\n events: events.length,\n });\n return publicUrl;\n } catch (err) {\n log.warn('browser', 'Recording upload errored', {\n error: err instanceof Error ? err.message : String(err),\n });\n return null;\n }\n}\n","import { getUploadUrl } from '../api';\nimport { captureViaCdp } from '../browser';\nimport { CommandError } from './types';\nimport type { CommandContext } from './types';\n\nexport async function handleScreenshotFullPage(\n ctx: CommandContext,\n cmd: Record<string, unknown>,\n): Promise<Record<string, unknown>> {\n if (!ctx.state.runner?.getSession() || !ctx.state.appConfig?.appId) {\n throw new CommandError('No active session', 'NO_SESSION');\n }\n const page = ctx.state.browser?.getActivePage();\n if (!page) {\n throw new CommandError(\n 'Sandbox browser unavailable — headless Chrome is required for screenshots',\n 'NO_BROWSER',\n );\n }\n\n const startTime = Date.now();\n\n const session = ctx.state.runner.getSession()!;\n const { uploadUrl, uploadFields, publicUrl } = await getUploadUrl(\n ctx.state.appConfig.appId,\n session.sessionId,\n 'jpg',\n 'image/jpeg',\n );\n\n const r = await captureViaCdp(page, {\n fullPage: true,\n path: typeof cmd.path === 'string' ? cmd.path : undefined,\n uploadUrl,\n uploadFields,\n });\n\n return {\n success: true,\n url: publicUrl,\n width: r.width,\n height: r.height,\n ...(r.styleMap ? { styleMap: r.styleMap } : {}),\n duration: Date.now() - startTime,\n };\n}\n","import { CommandError } from './types';\nimport type { CommandContext } from './types';\n\nexport async function handleDevServerRestarting(\n ctx: CommandContext,\n): Promise<Record<string, unknown>> {\n if (!ctx.state.proxy) throw new CommandError('No active proxy', 'NO_BROWSER');\n\n ctx.state.proxy.markUpstreamDown();\n return { success: true };\n}\n","import { getApiBaseUrl } from '../../config';\nimport { fetchCallbackToken } from '../api';\nimport { CommandError } from './types';\nimport type { CommandContext } from './types';\n\nexport async function handleDbQuery(\n ctx: CommandContext,\n cmd: Record<string, unknown>,\n): Promise<Record<string, unknown>> {\n if (!ctx.state.runner) throw new CommandError('No active session', 'NO_SESSION');\n\n const session = ctx.state.runner.getSession();\n if (!session) throw new CommandError('No active session', 'NO_SESSION');\n\n const sql = cmd.sql as string;\n if (!sql) throw new CommandError('db-query requires \"sql\"', 'INVALID_INPUT');\n\n // Resolve database — use explicit databaseId, or default to the first one\n let databaseId = cmd.databaseId as string | undefined;\n if (!databaseId) {\n if (session.databases.length === 0) throw new CommandError('No databases available', 'NO_SESSION');\n databaseId = session.databases[0].id;\n }\n\n const appId = ctx.state.appConfig?.appId;\n if (!appId) throw new CommandError('No app config available', 'NO_SESSION');\n\n ctx.started({ databaseId, sql });\n\n const token = await fetchCallbackToken(appId, session.sessionId);\n const url = `${getApiBaseUrl()}/_internal/v2/db/query`;\n\n const res = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: token,\n },\n body: JSON.stringify({\n databaseId,\n queries: [{ sql }],\n }),\n });\n\n if (!res.ok) {\n const text = await res.text().catch(() => '');\n throw new CommandError(`Database query failed: ${res.status} ${text}`, 'EXECUTION_ERROR');\n }\n\n const data = await res.json() as { results: { rows: unknown[]; changes: number }[] };\n\n return {\n success: true,\n databaseId,\n results: data.results,\n };\n}\n","import { createAuthSession } from '../api';\nimport { clearAuthCookies, setAuthCookie } from '../browser';\nimport { CommandError } from './types';\nimport type { CommandContext } from './types';\n\nexport async function handleSetupBrowser(\n ctx: CommandContext,\n cmd: Record<string, unknown>,\n): Promise<Record<string, unknown>> {\n if (!ctx.state.appConfig?.appId) throw new CommandError('No active session', 'NO_SESSION');\n\n const page = ctx.state.browser?.getActivePage();\n if (!page) {\n throw new CommandError(\n 'Sandbox browser unavailable — headless Chrome is required for setup-browser',\n 'NO_BROWSER',\n );\n }\n\n const auth = cmd.auth as { email?: string; phone?: string; roles?: string[] } | undefined;\n const path = (cmd.path as string) || '/';\n\n // Fresh slate: clear any auth cookie the previous test left behind.\n await clearAuthCookies(page);\n\n // Mint + set the automation auth cookie if requested.\n if (auth) {\n const { cookie } = await createAuthSession(ctx.state.appConfig.appId, auth);\n await setAuthCookie(page, cookie);\n }\n\n // Navigate to the target path so the proxy resolves the cookie and the\n // page injects the correct `window.__MINDSTUDIO__` context. puppeteer's\n // goto requires an absolute URL — resolve `path` against the current\n // origin (always the proxy when the sandbox browser is running).\n const absolute = new URL(path, page.url()).toString();\n try {\n await page.goto(absolute, { waitUntil: 'networkidle0', timeout: 15_000 });\n } catch (err) {\n throw new CommandError(\n `Navigation to ${path} failed: ${err instanceof Error ? err.message : String(err)}`,\n 'BROWSER_ERROR',\n );\n }\n\n return { success: true, path, authenticated: !!auth };\n}\n","/**\n * Stdin command router for headless mode.\n *\n * Reads NDJSON commands from stdin and dispatches to individual handlers.\n * Every command must include a `requestId` for response correlation.\n * The router wraps handlers with automatic response framing.\n */\n\nimport { emitResponse } from '../ipc/ipc';\nimport { log } from '../logging/logger';\nimport { handleRunScenario } from './run-scenario';\nimport { handleRunMethod } from './run-method';\nimport { handleImpersonate, handleClearImpersonation } from './impersonate';\nimport { handleBrowser } from './browser';\nimport { handleScreenshotFullPage } from './screenshot-full-page';\nimport { handleDevServerRestarting } from './dev-server-restarting';\nimport { handleDbQuery } from './db-query';\nimport { handleSetupBrowser } from './setup-browser';\nimport { CommandError } from './types';\nimport type { SessionState, CommandContext, CommandHandler } from './types';\n\nexport type { SessionState } from './types';\n\nconst handlers: Record<string, CommandHandler> = {\n 'run-method': handleRunMethod,\n 'run-scenario': handleRunScenario,\n 'impersonate': handleImpersonate,\n 'clear-impersonation': handleClearImpersonation,\n 'browser': handleBrowser,\n 'screenshotFullPage': handleScreenshotFullPage,\n 'db-query': handleDbQuery,\n 'setup-browser': handleSetupBrowser,\n 'dev-server-restarting': handleDevServerRestarting,\n};\n\nexport function setupStdinCommands(\n state: SessionState,\n cwd: string,\n): void {\n if (!process.stdin.readable) return;\n\n let buffer = '';\n process.stdin.setEncoding('utf-8');\n process.stdin.on('data', (chunk: string) => {\n buffer += chunk;\n let idx: number;\n while ((idx = buffer.indexOf('\\n')) !== -1) {\n const line = buffer.slice(0, idx).trim();\n buffer = buffer.slice(idx + 1);\n if (!line) continue;\n\n let cmd: { action: string; requestId?: string; [key: string]: unknown };\n try {\n cmd = JSON.parse(line);\n } catch {\n log.warn('stdin', 'Invalid JSON on stdin', { preview: line.slice(0, 100) });\n continue;\n }\n\n handleStdinCommand(cmd, state, cwd);\n }\n });\n}\n\nasync function handleStdinCommand(\n cmd: { action: string; requestId?: string; [key: string]: unknown },\n state: SessionState,\n cwd: string,\n): Promise<void> {\n const { requestId, action } = cmd;\n\n if (!requestId) {\n log.warn('stdin', 'Command rejected: missing requestId', { action });\n return;\n }\n\n const handler = handlers[action];\n if (!handler) {\n emitResponse(action ?? 'unknown', requestId, 'completed', {\n success: false,\n error: `Unknown action: ${action}`,\n errorCode: 'UNKNOWN_ACTION',\n });\n return;\n }\n\n log.info('stdin', 'Command received', { requestId, action });\n\n const ctx: CommandContext = {\n state,\n cwd,\n requestId,\n started: (data) => emitResponse(action, requestId, 'started', data),\n };\n\n try {\n const result = await handler(ctx, cmd);\n log.info('stdin', 'Command complete', { requestId, action, success: result.success !== false });\n emitResponse(action, requestId, 'completed', result);\n } catch (err) {\n const code = err instanceof CommandError ? err.code : 'INFRASTRUCTURE';\n const message = err instanceof Error ? err.message : String(err);\n log.warn('stdin', 'Command failed', { requestId, action, error: message, errorCode: code });\n emitResponse(action, requestId, 'completed', {\n success: false,\n error: message,\n errorCode: code,\n });\n }\n}\n","/**\n * Headless Dev Mode\n *\n * Runs the MindStudio dev tunnel without a TUI. Designed for programmatic\n * control by a parent process (e.g., a sandbox C&C server or CI pipeline).\n *\n * Outputs structured JSON events to stdout (one per line, newline-delimited).\n * The parent process reads these to track session state, method execution,\n * errors, and connection health.\n *\n * Does NOT start a dev server — the parent process manages that separately.\n * The tunnel just needs to know which port to proxy to.\n *\n * @module\n */\n\nimport { DevRunner } from './dev/execution/runner';\nimport { DevProxy } from './dev/proxy/proxy';\nimport { BrowserSupervisor } from './dev/browser';\nimport { syncSchema } from './dev/api';\nimport {\n detectAppConfig,\n getWebInterfaceConfig,\n readTableSources,\n} from './dev/config/app-config';\nimport { initRequestLog, closeRequestLog } from './dev/logging/request-log';\nimport { initBrowserLog, closeBrowserLog } from './dev/logging/browser-log';\nimport { subscribeDevEvents } from './dev/ipc/session-events';\nimport { setupStdinCommands, type SessionState } from './dev/stdin-commands';\nimport { emitEvent } from './dev/ipc/ipc';\nimport {\n getApiKey,\n getApiBaseUrl,\n getUserId,\n getEnvironment,\n getConfigPath,\n} from './config';\nimport { initLoggerHeadless, log, type LogLevel } from './dev/logging/logger';\nimport { stablePort, detectGitBranch } from './dev/utils';\nimport { watchTableFiles } from './dev/config/table-watcher';\nimport { watchConfigFile } from './dev/config/config-watcher';\n\n/**\n * Options for headless dev mode.\n */\nexport interface HeadlessOptions {\n /** Working directory containing mindstudio.json. Defaults to process.cwd(). */\n cwd?: string;\n /** Port the dev server is running on. If omitted, reads from web.json. If neither, proxy is skipped. */\n devPort?: number;\n /** Preferred port for the local proxy. Defaults to a stable port derived from the app ID. */\n proxyPort?: number;\n /** Bind address for the proxy server. Use '0.0.0.0' for hosted sandboxes. Defaults to '127.0.0.1'. */\n bindAddress?: string;\n /** Log level for stderr output. Defaults to 'info'. */\n logLevel?: LogLevel;\n /** URL for the browser agent script. Defaults to unpkg latest. Set to an ngrok URL for development. */\n browserAgentUrl?: string;\n /** Launch a sandbox-side headless Chrome that participates as a WS client. */\n sandboxBrowser?: boolean;\n}\n\n\n// ---------------------------------------------------------------------------\n// Session lifecycle\n// ---------------------------------------------------------------------------\n\nasync function startSession(\n cwd: string,\n opts: HeadlessOptions,\n state: SessionState,\n shutdown: () => Promise<void>,\n): Promise<boolean> {\n const bindAddress = opts.bindAddress ?? '127.0.0.1';\n\n // Read fresh config\n const appConfig = detectAppConfig(cwd);\n if (!appConfig) {\n emitEvent('config-error', { message: 'No valid mindstudio.json found in ' + cwd });\n return false;\n }\n\n if (!appConfig.appId) {\n emitEvent('config-error', { message: 'Missing \"appId\" in mindstudio.json' });\n return false;\n }\n\n state.appConfig = appConfig;\n\n // Resolve dev port\n let devPort = opts.devPort ?? null;\n if (devPort === null) {\n const webConfig = getWebInterfaceConfig(appConfig, cwd);\n devPort = webConfig?.devPort ?? null;\n }\n\n emitEvent('session-starting', { appId: appConfig.appId, name: appConfig.name });\n\n try {\n // Start platform session\n const branch = detectGitBranch();\n const runner = new DevRunner(appConfig.appId, cwd, {\n branch,\n methods: appConfig.methods.map((m) => ({ id: m.id, export: m.export, path: m.path })),\n });\n runner.setAppConfig(appConfig);\n const session = await runner.start();\n state.runner = runner;\n\n // Initialize logs\n initRequestLog(cwd);\n initBrowserLog(cwd);\n\n // Sync schema\n if (appConfig.tables.length > 0) {\n try {\n const tableSources = readTableSources(appConfig, cwd);\n if (tableSources.length > 0) {\n const syncResult = await syncSchema(appConfig.appId, session.sessionId, tableSources);\n session.databases = syncResult.databases;\n emitEvent('schema-sync-completed', {\n created: syncResult.created,\n altered: syncResult.altered,\n errors: syncResult.errors,\n });\n } else {\n log.warn('session', 'No table source files found, skipping schema sync', {\n expected: appConfig.tables.map((t) => t.path),\n });\n }\n } catch (err) {\n emitEvent('schema-sync-completed', {\n created: [],\n altered: [],\n errors: [err instanceof Error ? err.message : 'Schema sync failed'],\n });\n }\n }\n\n // Start or reuse proxy\n if (devPort !== null && session.clientContext) {\n if (state.proxy) {\n // Proxy persists across restarts — just update the context\n state.proxy.updateClientContext(session.clientContext);\n } else {\n const proxy = new DevProxy(devPort, session.clientContext, appConfig.appId, bindAddress, opts.browserAgentUrl);\n const preferred = opts.proxyPort ?? stablePort(appConfig.appId);\n const proxyPort = await proxy.start(preferred);\n state.proxy = proxy;\n state.proxyPort = proxyPort;\n }\n\n runner.setProxyUrl(`http://${bindAddress === '0.0.0.0' ? 'localhost' : bindAddress}:${state.proxyPort}`);\n runner.setProxy(state.proxy);\n\n // Optional sandbox-side headless Chrome. Connects back to the proxy\n // as just another WS client; the proxy registers it with mode='headless'\n // and getCommandTarget() prefers it for automation. Viewport follows\n // the web interface's defaultPreviewMode so mobile-first apps render\n // at mobile dimensions in the sandbox Chrome too.\n if (opts.sandboxBrowser && state.proxyPort !== null && !state.browser) {\n const webConfig = getWebInterfaceConfig(appConfig, cwd);\n const previewMode = webConfig?.defaultPreviewMode ?? 'desktop';\n const supervisor = new BrowserSupervisor(state.proxyPort, previewMode);\n state.browser = supervisor;\n supervisor.start().catch((err) => {\n log.warn('browser', 'Sandbox browser failed to start', {\n error: err instanceof Error ? err.message : String(err),\n });\n });\n }\n }\n\n emitEvent('session-started', {\n sessionId: session.sessionId,\n releaseId: session.releaseId,\n branch: session.branch,\n proxyPort: state.proxyPort,\n proxyUrl: state.proxyPort\n ? `http://${bindAddress === '0.0.0.0' ? 'localhost' : bindAddress}:${state.proxyPort}/`\n : null,\n webInterfaceUrl: session.webInterfaceUrl,\n roles: appConfig.roles.map((r) => ({ id: r.id, name: r.name ?? r.id, description: r.description })),\n scenarios: appConfig.scenarios.map((s) => ({\n id: s.id,\n name: s.name ?? s.export,\n description: s.description,\n path: s.path,\n roles: s.roles,\n })),\n });\n\n // Subscribe to runner events\n state.unsubscribers.push(...subscribeDevEvents(shutdown));\n\n // Watch table source files for changes — auto-sync without session restart\n setupTableWatchers(cwd, state);\n\n // Start polling for platform method requests now that schema sync,\n // proxy, and watchers are all set up. Starting earlier would risk\n // executing methods against stale session state (e.g. missing tables).\n runner.startPolling();\n\n return true;\n } catch (err) {\n emitEvent('config-error', {\n message: err instanceof Error ? err.message : 'Failed to start session',\n });\n return false;\n }\n}\n\nfunction setupTableWatchers(cwd: string, state: SessionState): void {\n if (!state.appConfig || state.appConfig.tables.length === 0) return;\n\n const cleanup = watchTableFiles(state.appConfig.tables, cwd, async () => {\n if (!state.runner || !state.appConfig?.appId) return;\n const session = state.runner.getSession();\n if (!session) return;\n\n emitEvent('schema-sync-started');\n log.info('session', 'Table source file changed, syncing schema');\n\n try {\n const tableSources = readTableSources(state.appConfig, cwd);\n if (tableSources.length > 0) {\n const result = await syncSchema(state.appConfig.appId, session.sessionId, tableSources);\n session.databases = result.databases;\n emitEvent('schema-sync-completed', {\n created: result.created,\n altered: result.altered,\n errors: result.errors,\n });\n log.info('session', 'Schema sync complete', { created: result.created, altered: result.altered });\n } else {\n log.warn('session', 'Table source file change detected but file(s) still missing', {\n expected: state.appConfig.tables.map((t) => t.path),\n });\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Schema sync failed';\n emitEvent('schema-sync-completed', { created: [], altered: [], errors: [message] });\n log.warn('session', 'Schema sync failed', { error: message });\n }\n });\n\n state.unsubscribers.push(cleanup);\n}\n\n/** Tear down the runner, logs, and watchers. Proxy stays alive for reuse. */\nasync function teardownRunner(state: SessionState): Promise<void> {\n for (const unsub of state.unsubscribers) unsub();\n state.unsubscribers = [];\n\n if (state.runner) {\n await state.runner.stop().catch(() => {});\n state.runner = null;\n }\n\n closeRequestLog();\n closeBrowserLog();\n}\n\n/** Full teardown including proxy. Used on process shutdown. */\nasync function teardownAll(state: SessionState): Promise<void> {\n await teardownRunner(state);\n\n if (state.browser) {\n await state.browser.stop().catch(() => {});\n state.browser = null;\n }\n\n state.proxy?.stop();\n state.proxy = null;\n state.proxyPort = null;\n}\n\n// ---------------------------------------------------------------------------\n// Entry point\n// ---------------------------------------------------------------------------\n\n/**\n * Start the dev tunnel in headless mode.\n */\nexport async function startHeadless(opts: HeadlessOptions = {}): Promise<void> {\n initLoggerHeadless(opts.logLevel ?? 'info');\n\n const cwd = opts.cwd ?? process.cwd();\n\n const apiKey = getApiKey();\n const userId = getUserId();\n log.info('session', 'Startup config', {\n configPath: getConfigPath(),\n environment: getEnvironment(),\n apiBaseUrl: getApiBaseUrl(),\n hasApiKey: !!apiKey,\n apiKeyPrefix: apiKey ? apiKey.slice(0, 8) + '...' : null,\n hasUserId: !!userId,\n userId: userId ?? null,\n cwd,\n });\n\n const state: SessionState = {\n runner: null,\n proxy: null,\n browser: null,\n appConfig: null,\n proxyPort: null,\n unsubscribers: [],\n };\n\n let restarting = false;\n let cleanupConfigWatcher: (() => void) | undefined;\n\n let stopping = false;\n let degradedRetryTimer: ReturnType<typeof setInterval> | null = null;\n const shutdown = async () => {\n if (stopping) return;\n stopping = true;\n if (degradedRetryTimer) { clearInterval(degradedRetryTimer); degradedRetryTimer = null; }\n emitEvent('session-stopping');\n cleanupConfigWatcher?.();\n await teardownAll(state);\n emitEvent('session-stopped');\n };\n\n process.on('SIGTERM', () => { shutdown().then(() => process.exit(0)); });\n process.on('SIGINT', () => { shutdown().then(() => process.exit(0)); });\n\n // Initial session start — retry a few times with backoff before degrading.\n // Snapshot resumes often hit a transient 400 from /manage/start because the\n // platform-side session state is stale. A short retry usually recovers.\n const MAX_START_RETRIES = 5;\n let started = false;\n for (let attempt = 1; attempt <= MAX_START_RETRIES && !stopping; attempt++) {\n started = await startSession(cwd, opts, state, shutdown);\n if (started) break;\n if (attempt < MAX_START_RETRIES) {\n const delay = Math.min(1000 * 2 ** (attempt - 1), 10_000);\n log.info('session', `Start failed, retrying in ${delay}ms`, { attempt, maxAttempts: MAX_START_RETRIES });\n await new Promise((r) => setTimeout(r, delay));\n }\n }\n\n if (!started && !stopping) {\n emitEvent('degraded-state', {\n reason: 'Config invalid or missing at boot. Waiting for valid mindstudio.json.',\n });\n log.warn('session', 'Booting in degraded state — no valid config. Watching for changes.');\n\n // Periodically retry in degraded state (covers transient platform issues\n // that outlast the initial retry window, e.g. long snapshot resume).\n degradedRetryTimer = setInterval(async () => {\n if (stopping || restarting || state.runner) {\n if (state.runner && degradedRetryTimer) {\n clearInterval(degradedRetryTimer);\n degradedRetryTimer = null;\n }\n return;\n }\n restarting = true;\n try {\n log.info('session', 'Retrying session start from degraded state');\n const ok = await startSession(cwd, opts, state, shutdown);\n if (ok) {\n emitEvent('degraded-state-resolved', { appId: state.appConfig?.appId });\n log.info('session', 'Recovered from degraded state');\n if (degradedRetryTimer) {\n clearInterval(degradedRetryTimer);\n degradedRetryTimer = null;\n }\n }\n } finally {\n restarting = false;\n }\n }, 15_000);\n }\n\n // Stdin command loop\n setupStdinCommands(state, cwd);\n\n // Watch mindstudio.json for changes — validate before teardown so corrupt\n // writes don't kill a running session. In degraded state (no runner), a\n // valid config triggers a fresh startSession.\n cleanupConfigWatcher = watchConfigFile(cwd, async () => {\n if (stopping || restarting) return;\n restarting = true;\n try {\n emitEvent('config-changed');\n\n // Validate BEFORE tearing down the running session\n const newConfig = detectAppConfig(cwd);\n if (!newConfig || !newConfig.appId) {\n emitEvent('config-error', {\n message: 'mindstudio.json is invalid — keeping current session',\n });\n log.warn('session', 'Config change detected but file is invalid, keeping current session');\n return;\n }\n\n const wasDegraded = !state.runner;\n await teardownRunner(state);\n const ok = await startSession(cwd, opts, state, shutdown);\n if (ok) {\n if (wasDegraded) {\n emitEvent('degraded-state-resolved', { appId: newConfig.appId });\n log.info('session', 'Recovered from degraded state');\n if (degradedRetryTimer) { clearInterval(degradedRetryTimer); degradedRetryTimer = null; }\n }\n if (state.proxy) {\n state.proxy.broadcastToClients('reload');\n }\n } else {\n emitEvent('degraded-state', {\n reason: 'Session restart failed after config change. Will retry on next change.',\n });\n log.warn('session', 'Session restart failed, entering degraded state');\n }\n } finally {\n restarting = false;\n }\n });\n\n // Keep the process alive — the poll loop runs in DevRunner\n await new Promise<void>(() => {});\n}\n"],"mappings":"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","names":[]}
|
|
File without changes
|