@kritchoff/agent-browser 1.0.5 → 1.0.7

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/cli.cjs CHANGED
@@ -70,7 +70,7 @@ var Orchestrator = class {
70
70
  env: { ...process.env, ...env }
71
71
  });
72
72
  return true;
73
- } catch (e) {
73
+ } catch {
74
74
  return false;
75
75
  }
76
76
  }
@@ -158,7 +158,7 @@ var Orchestrator = class {
158
158
  { stdio: "ignore" }
159
159
  );
160
160
  await new Promise((r) => setTimeout(r, 3e3));
161
- } catch (e) {
161
+ } catch {
162
162
  this.log(`Network rehydration warning: ${e}`, "warn");
163
163
  }
164
164
  }
@@ -222,7 +222,6 @@ var Orchestrator = class {
222
222
  } catch {
223
223
  }
224
224
  this.log("Waiting for device to come online...", "info");
225
- const start = Date.now();
226
225
  let online = false;
227
226
  while (Date.now() - start < 3e4) {
228
227
  try {
@@ -269,7 +268,6 @@ var Orchestrator = class {
269
268
  }
270
269
  waitForLog(container, pattern, timeoutMs = 12e4) {
271
270
  return new Promise((resolve, reject) => {
272
- const start = Date.now();
273
271
  const tail = (0, import_child_process.spawn)("docker", ["logs", "-f", container]);
274
272
  const timer = setTimeout(() => {
275
273
  tail.kill();
@@ -365,12 +363,12 @@ var WootzAgent = class {
365
363
  * @param timeoutMs The maximum amount of time (in ms) to wait for the daemon.
366
364
  */
367
365
  async waitForDaemon(timeoutMs = 18e4) {
368
- const start = Date.now();
369
- while (Date.now() - start < timeoutMs) {
366
+ const start2 = Date.now();
367
+ while (Date.now() - start2 < timeoutMs) {
370
368
  try {
371
369
  await this.sendCommand({ action: "tab_list" });
372
370
  return;
373
- } catch (e) {
371
+ } catch {
374
372
  await new Promise((r) => setTimeout(r, 1e3));
375
373
  }
376
374
  }
@@ -594,7 +592,7 @@ var WootzAgent = class {
594
592
  } else {
595
593
  reject(new Error(response.error || "Unknown error"));
596
594
  }
597
- } catch (e) {
595
+ } catch {
598
596
  reject(new Error(`Invalid response from daemon: ${responseBuffer}`));
599
597
  }
600
598
  });
package/dist/cli.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../node_modules/tsup/assets/cjs_shims.js","../src/index.ts","../src/orchestrator.ts","../src/cli.ts"],"sourcesContent":["// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () => \n typeof document === \"undefined\" \n ? new URL(`file:${__filename}`).href \n : (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') \n ? document.currentScript.src \n : new URL(\"main.js\", document.baseURI).href;\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","import * as net from 'net';\nimport { randomUUID } from 'crypto';\nimport { Orchestrator } from './orchestrator.js';\nimport { z } from 'zod';\nimport pino from 'pino';\n\nconst DAEMON_PORT = 32001;\n\n// --- Custom Errors ---\nexport class WootzConnectionError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'WootzConnectionError';\n }\n}\n\nexport class WootzTimeoutError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'WootzTimeoutError';\n }\n}\n\nexport class WootzValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'WootzValidationError';\n }\n}\n\n// --- Schema Validation ---\nconst AgentOptionsSchema = z.object({\n dist: z.boolean().optional().default(true),\n logLevel: z.enum(['debug', 'info', 'warn', 'error', 'silent']).optional().default('info'),\n}).passthrough();\n\n/**\n * Options for initializing the WootzAgent.\n */\nexport interface AgentOptions extends z.input<typeof AgentOptionsSchema> {}\n\n/**\n * Main entry point for interacting with the Agent Browser environment.\n */\nexport class WootzAgent {\n private options: AgentOptions;\n private orchestrator: Orchestrator;\n public logger: pino.Logger;\n\n /**\n * Creates a new instance of the WootzAgent.\n * @param options Configuration options.\n * @throws {WootzValidationError} If the provided options do not match the expected schema.\n */\n constructor(options: AgentOptions = {}) {\n const parsedOptions = AgentOptionsSchema.safeParse(options);\n if (!parsedOptions.success) {\n throw new WootzValidationError(`Invalid agent options: ${parsedOptions.error.message}`);\n }\n \n this.options = parsedOptions.data;\n \n this.logger = pino({\n level: this.options.logLevel,\n transport: this.options.logLevel !== 'silent' ? {\n target: 'pino-pretty',\n options: {\n colorize: true,\n translateTime: 'HH:MM:ss Z',\n ignore: 'pid,hostname',\n },\n } : undefined,\n });\n\n this.orchestrator = new Orchestrator(this.options.dist!, this.logger);\n }\n\n // --- Lifecycle Management (Infrastructure) ---\n\n /**\n * Starts the underlying orchestrator and waits for the browser daemon to be ready.\n * @throws {WootzTimeoutError} If the daemon fails to become available within the timeout.\n */\n async start(): Promise<void> {\n await this.orchestrator.start();\n await this.waitForDaemon();\n }\n\n /**\n * Polls the daemon port until it accepts connections.\n * @param timeoutMs The maximum amount of time (in ms) to wait for the daemon.\n */\n private async waitForDaemon(timeoutMs = 180000): Promise<void> {\n const start = Date.now();\n while (Date.now() - start < timeoutMs) {\n try {\n await this.sendCommand({ action: 'tab_list' }); // Health check\n return; // Success\n } catch (e) {\n await new Promise((r) => setTimeout(r, 1000));\n }\n }\n throw new WootzTimeoutError(\n `Timed out waiting for Agent Daemon on port ${DAEMON_PORT} after ${timeoutMs / 1000}s`\n );\n }\n\n /**\n * Stops the orchestrator and cleans up resources.\n */\n async stop(): Promise<void> {\n await this.orchestrator.stop();\n }\n\n /**\n * Resets the environment completely.\n */\n async reset(): Promise<void> {\n await this.orchestrator.reset();\n }\n\n // --- Core Browser Actions (Direct Daemon) ---\n\n /**\n * Navigates the current tab to a specified URL.\n * @param url The URL to navigate to.\n * @param waitUntil The load state to wait for ('load', 'domcontentloaded', 'networkidle').\n */\n async navigate(\n url: string,\n waitUntil: 'load' | 'domcontentloaded' | 'networkidle' = 'load'\n ): Promise<string> {\n return await this.sendCommand({ action: 'navigate', url, waitUntil });\n }\n\n /**\n * Clicks on an element matching the given selector.\n * @param selector The CSS or semantic selector of the element to click.\n */\n async click(selector: string): Promise<string> {\n return await this.sendCommand({ action: 'click', selector });\n }\n\n /**\n * Double-clicks on an element matching the given selector.\n * @param selector The CSS or semantic selector.\n */\n async doubleClick(selector: string): Promise<string> {\n return await this.sendCommand({ action: 'dblclick', selector });\n }\n\n /**\n * Types text into a form field character by character.\n * @param selector The CSS or semantic selector of the input field.\n * @param text The text to type.\n * @param delay Delay between keystrokes in milliseconds.\n */\n async type(selector: string, text: string, delay?: number): Promise<string> {\n return await this.sendCommand({ action: 'type', selector, text, delay });\n }\n\n /**\n * Fills an input field directly with a value (faster than type).\n * @param selector The CSS or semantic selector of the input field.\n * @param value The value to fill.\n */\n async fill(selector: string, value: string): Promise<string> {\n return await this.sendCommand({ action: 'fill', selector, value });\n }\n\n async check(selector: string): Promise<string> {\n return await this.sendCommand({ action: 'check', selector });\n }\n\n async uncheck(selector: string): Promise<string> {\n return await this.sendCommand({ action: 'uncheck', selector });\n }\n\n async hover(selector: string): Promise<string> {\n return await this.sendCommand({ action: 'hover', selector });\n }\n\n async focus(selector: string): Promise<string> {\n return await this.sendCommand({ action: 'focus', selector });\n }\n\n async press(key: string, selector?: string): Promise<string> {\n return await this.sendCommand({ action: 'press', key, selector });\n }\n\n async selectOption(selector: string, value: string | string[]): Promise<string> {\n return await this.sendCommand({ action: 'select', selector, values: value });\n }\n\n // --- Introspection & State ---\n\n /**\n * Captures the full DOM/AXTree snapshot of the current page.\n * @returns A string representation of the interactive accessibility tree.\n */\n async snapshot(): Promise<string> {\n const result = await this.sendCommand({ action: 'snapshot' }, true);\n return result.snapshot || '';\n }\n\n async innerText(selector: string): Promise<string> {\n const res = await this.sendCommand({ action: 'innertext', selector }, true);\n return res.text;\n }\n\n async innerHTML(selector: string): Promise<string> {\n const res = await this.sendCommand({ action: 'innerhtml', selector }, true);\n return res.html;\n }\n\n async getAttribute(selector: string, attribute: string): Promise<string> {\n const res = await this.sendCommand({ action: 'getattribute', selector, attribute }, true);\n return res.value;\n }\n\n async inputValue(selector: string): Promise<string> {\n const res = await this.sendCommand({ action: 'inputvalue', selector }, true);\n return res.value;\n }\n\n async isVisible(selector: string): Promise<boolean> {\n const res = await this.sendCommand({ action: 'isvisible', selector }, true);\n return res.visible;\n }\n\n async isEnabled(selector: string): Promise<boolean> {\n const res = await this.sendCommand({ action: 'isenabled', selector }, true);\n return res.enabled;\n }\n\n async isChecked(selector: string): Promise<boolean> {\n const res = await this.sendCommand({ action: 'ischecked', selector }, true);\n return res.checked;\n }\n\n // --- Waiting & Navigation ---\n\n async waitForSelector(\n selector: string,\n state: 'attached' | 'detached' | 'visible' | 'hidden' = 'visible',\n timeout?: number\n ): Promise<string> {\n return await this.sendCommand({ action: 'wait', selector, state, timeout });\n }\n\n async waitForTimeout(ms: number): Promise<string> {\n return await this.sendCommand({ action: 'wait', timeout: ms });\n }\n\n async waitForLoadState(\n state: 'load' | 'domcontentloaded' | 'networkidle' = 'load'\n ): Promise<string> {\n return await this.sendCommand({ action: 'waitforloadstate', state });\n }\n\n async reload(): Promise<string> {\n return await this.sendCommand({ action: 'reload' });\n }\n\n async goBack(): Promise<string> {\n return await this.sendCommand({ action: 'back' });\n }\n\n async goForward(): Promise<string> {\n return await this.sendCommand({ action: 'forward' });\n }\n\n // --- Semantic Locators ---\n\n async getByRole(role: string, name?: string, _exact: boolean = false): Promise<string> {\n throw new Error(\n 'Locator builders (getByRole) are not fully supported in stateless mode yet. Use standard selectors.'\n );\n }\n\n // --- Utilities ---\n\n /**\n * Captures a screenshot of the current page.\n * @param path Optional file path to save the screenshot.\n */\n async screenshot(path?: string): Promise<string> {\n const res = await this.sendCommand({ action: 'screenshot', path }, true);\n return res.path;\n }\n\n async scroll(x: number, y: number): Promise<string> {\n return await this.sendCommand({ action: 'scroll', x, y });\n }\n\n async evaluate(script: string): Promise<any> {\n const res = await this.sendCommand({ action: 'evaluate', script }, true);\n return res.result;\n }\n\n // --- Tab Management ---\n\n async newTab(url?: string): Promise<string> {\n return await this.sendCommand({ action: 'tab_new', url });\n }\n\n async switchTab(index: number): Promise<string> {\n return await this.sendCommand({ action: 'tab_switch', index });\n }\n\n async closeTab(index?: number): Promise<string> {\n return await this.sendCommand({ action: 'tab_close', index });\n }\n\n async listTabs(): Promise<any[]> {\n const res = await this.sendCommand({ action: 'tab_list' }, true);\n return res.tabs;\n }\n\n // --- Generic Execution ---\n\n async command(action: string, ...args: string[]): Promise<string> {\n const cmd: any = { action };\n\n if (action === 'open' || action === 'navigate') {\n cmd.action = 'navigate';\n cmd.url = args[0];\n } else if (action === 'click') {\n cmd.selector = args[0];\n } else if (action === 'type') {\n cmd.selector = args[0];\n cmd.text = args[1];\n } else if (action === 'press') {\n cmd.key = args[0];\n } else if (action === 'scroll') {\n cmd.x = parseInt(args[0] || '0');\n cmd.y = parseInt(args[1] || '0');\n } else if (action === 'wait') {\n if (/^\\d+$/.test(args[0])) cmd.timeout = parseInt(args[0]);\n else cmd.selector = args[0];\n } else {\n if (args[0]) cmd.selector = args[0];\n if (args[1]) cmd.text = args[1] || args[1]; // value/text\n }\n\n const res = await this.sendCommand(cmd, true);\n\n if (typeof res === 'object') {\n if (res.text) return res.text;\n if (res.url) return res.url;\n if (res.snapshot) return res.snapshot;\n return JSON.stringify(res);\n }\n return String(res);\n }\n\n private sendCommand(command: any, returnData = false): Promise<any> {\n return new Promise((resolve, reject) => {\n if (!command.id) command.id = randomUUID();\n\n const client = new net.Socket();\n\n client.connect(DAEMON_PORT, '127.0.0.1', () => {\n client.write(JSON.stringify(command) + '\\n');\n });\n\n let responseBuffer = '';\n\n client.on('data', (data) => {\n responseBuffer += data.toString();\n if (responseBuffer.includes('\\n')) {\n client.end();\n }\n });\n\n client.on('end', () => {\n try {\n const response = JSON.parse(responseBuffer.trim());\n if (response.success) {\n resolve(returnData ? response.data : 'OK');\n } else {\n reject(new Error(response.error || 'Unknown error'));\n }\n } catch (e) {\n reject(new Error(`Invalid response from daemon: ${responseBuffer}`));\n }\n });\n\n client.on('error', (err) => {\n reject(new WootzConnectionError(`Failed to connect to agent daemon (is it running?): ${err.message}`));\n });\n });\n }\n}\n\nexport default WootzAgent;","import { spawn, spawnSync, execSync } from 'child_process';\nimport path from 'path';\nimport 'fs';\nimport { fileURLToPath } from 'url';\nimport pino from 'pino';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst PROJECT_ROOT = path.resolve(__dirname, '..');\n\nexport class Orchestrator {\n private composeFile: string;\n private logger: pino.Logger;\n\n constructor(distMode: boolean, logger?: pino.Logger) {\n this.composeFile = path.join(\n PROJECT_ROOT,\n distMode ? 'docker-compose.sdk.yml' : 'docker-compose.prod.yml'\n );\n this.logger = logger || pino();\n }\n\n private log(msg: string, level: 'info' | 'success' | 'warn' | 'error' = 'info') {\n switch (level) {\n case 'success':\n this.logger.info({ sdk: true }, msg);\n break;\n case 'warn':\n this.logger.warn({ sdk: true }, msg);\n break;\n case 'error':\n this.logger.error({ sdk: true }, msg);\n break;\n default:\n this.logger.info({ sdk: true }, msg);\n }\n }\n\n private runCommand(cmd: string, env: Record<string, string> = {}): boolean {\n try {\n execSync(cmd, {\n stdio: 'inherit',\n env: { ...process.env, ...env },\n });\n return true;\n } catch (e) {\n return false;\n }\n }\n\n private getContainerId(serviceName: string): string | null {\n try {\n const output = execSync(`docker compose -f \"${this.composeFile}\" ps -q ${serviceName}`, {\n encoding: 'utf-8',\n });\n return output.trim() || null;\n } catch {\n return null;\n }\n }\n\n private isPortMapped(containerId: string, port: number): boolean {\n try {\n const output = execSync(`docker port \"${containerId}\" ${port}`, { encoding: 'utf-8' });\n return output.includes('0.0.0.0:') || output.includes(':::');\n } catch {\n return false;\n }\n }\n\n private async pullImagesWithRetry(): Promise<void> {\n if (!this.composeFile.endsWith('docker-compose.sdk.yml')) return;\n\n this.log('Please wait while we get things ready...', 'info');\n const maxRetries = 10;\n\n for (let count = 0; count < maxRetries; count++) {\n if (this.runCommand(`docker compose -f \"${this.composeFile}\" pull`)) {\n return;\n }\n this.log(\n `Download failed/interrupted. Retrying (${count + 1}/${maxRetries}) in 10s...`,\n 'warn'\n );\n await new Promise((r) => setTimeout(r, 10000));\n }\n\n this.log(\n `Failed to download images after ${maxRetries} attempts. Check internet connection.`,\n 'error'\n );\n process.exit(1);\n }\n\n private async hasSnapshot(): Promise<boolean> {\n try {\n // 1. Check if volume exists\n execSync(`docker volume inspect agent-snapshots`, { stdio: 'ignore' });\n\n // 2. Check if volume contains the 'quickboot' directory\n // We use a tiny helper container to look inside the managed volume\n const output = execSync(`docker run --rm -v agent-snapshots:/data busybox ls /data`, {\n encoding: 'utf-8',\n });\n return output.includes('quickboot');\n } catch {\n return false;\n }\n }\n\n public async start(): Promise<void> {\n this.log(`Initializing Agent Environment...`, 'info');\n\n await this.pullImagesWithRetry();\n\n this.log('Cleaning up previous container state...', 'info');\n this.runCommand(`docker compose -f \"${this.composeFile}\" down -v --remove-orphans`);\n\n const hasSnapshot = await this.hasSnapshot();\n\n if (hasSnapshot) {\n // === WARM START ===\n this.log('Found cached baseline snapshot. Performing HYPER-SPEED WARM BOOT...', 'success');\n\n const success = this.runCommand(`docker compose -f \"${this.composeFile}\" up -d`, {\n EMULATOR_SNAPSHOT_NAME: 'quickboot',\n });\n\n if (!success) throw new Error('Startup failed during docker compose up.');\n\n const agentCont = this.getContainerId('agent-service');\n const androidCont = this.getContainerId('android-service');\n\n // Verify Port Mapping\n if (agentCont && !this.isPortMapped(agentCont, 3000)) {\n this.log('Port 3000 (Host 32001) is not mapped! Container config is stale.', 'warn');\n this.log('Forcing full restart to apply network settings...', 'info');\n this.runCommand(`docker compose -f \"${this.composeFile}\" down -v --remove-orphans`);\n await new Promise((r) => setTimeout(r, 5000));\n this.runCommand(`docker compose -f \"${this.composeFile}\" up -d`, {\n EMULATOR_SNAPSHOT_NAME: 'quickboot',\n });\n }\n\n if (androidCont) {\n this.log('Rehydrating Android network connection...', 'info');\n try {\n execSync(`docker exec \"${androidCont}\" adb shell cmd connectivity airplane-mode enable`, {\n stdio: 'ignore',\n });\n await new Promise((r) => setTimeout(r, 2000));\n execSync(\n `docker exec \"${androidCont}\" adb shell cmd connectivity airplane-mode disable`,\n { stdio: 'ignore' }\n );\n await new Promise((r) => setTimeout(r, 3000));\n } catch (e) {\n this.log(`Network rehydration warning: ${e}`, 'warn');\n }\n }\n\n this.log('Waiting for Daemon Connection...');\n if (agentCont) await this.waitForLog(agentCont, 'Daemon listening on TCP', 180000);\n } else {\n // === COLD START ===\n this.log('No baseline found. Performing FIRST RUN SETUP (Cold Boot)...', 'warn');\n this.log('This will take ~60-90 seconds, but only once.', 'warn');\n\n const success = this.runCommand(`docker compose -f \"${this.composeFile}\" up -d`, {\n EMULATOR_SNAPSHOT_NAME: '',\n });\n\n if (!success) throw new Error('Startup failed during docker compose up.');\n\n let androidCont = this.getContainerId('android-service');\n const agentCont = this.getContainerId('agent-service');\n\n if (!androidCont) throw new Error('Error: Android container not found.');\n\n // Verify Port Mapping\n if (agentCont && !this.isPortMapped(agentCont, 3000)) {\n this.log('Port 3000 (Host 32001) is not mapped! Container config is stale.', 'warn');\n this.log('Forcing full restart to apply network settings...', 'info');\n this.runCommand(`docker compose -f \"${this.composeFile}\" down -v --remove-orphans`);\n await new Promise((r) => setTimeout(r, 5000));\n this.runCommand(`docker compose -f \"${this.composeFile}\" up -d`, {\n EMULATOR_SNAPSHOT_NAME: '',\n });\n androidCont = this.getContainerId('android-service') || androidCont;\n }\n\n this.log('Waiting for Android OS to boot (this takes a moment)...', 'info');\n await this.waitForLog(androidCont, 'Emulator boot complete');\n\n this.log('Waiting for Browser Installation...', 'info');\n await this.waitForLog(androidCont, 'APK installation complete');\n\n this.log('Waiting for CDP Bridge...', 'info');\n await this.waitForLog(androidCont, 'CDP Bridge ready');\n\n this.log('Waiting for Agent Daemon Connection...');\n if (agentCont) await this.waitForLog(agentCont, 'Daemon listening on TCP');\n\n // Save Snapshot\n this.log('Saving emulator state (quickboot)...', 'info');\n const saved = this.runCommand(\n `docker exec \"${androidCont}\" adb emu avd snapshot save quickboot`\n );\n if (saved) {\n this.log('Snapshot saved to host volume.', 'success');\n this.log('Setup Complete! Future runs will launch instantly.', 'success');\n } else {\n throw new Error('Failed to save snapshot inside emulator.');\n }\n }\n }\n\n public async stop(): Promise<void> {\n this.log('Stopping environment...', 'info');\n this.runCommand(`docker compose -f \"${this.composeFile}\" down -v --remove-orphans`);\n this.log('Environment cleaned and stopped.', 'success');\n }\n\n public async reset(): Promise<void> {\n this.log('Performing Fast Browser Reset...', 'info');\n const androidCont = this.getContainerId('android-service');\n if (!androidCont) {\n this.log('Android container not running.', 'error');\n return;\n }\n\n this.log('Initiating fast reset (userspace reboot)...', 'info');\n try {\n execSync(`docker exec \"${androidCont}\" adb shell reboot userspace`, { stdio: 'ignore' });\n } catch {\n // Ignored\n }\n\n this.log('Waiting for device to come online...', 'info');\n const start = Date.now();\n let online = false;\n\n while (Date.now() - start < 30000) {\n try {\n const state = execSync(`docker exec \"${androidCont}\" adb get-state`, {\n encoding: 'utf-8',\n }).trim();\n if (state === 'device') {\n execSync(`docker exec \"${androidCont}\" adb shell echo ok`, { stdio: 'ignore' });\n online = true;\n break;\n }\n } catch {\n // Still offline\n }\n await new Promise((r) => setTimeout(r, 1000));\n }\n\n if (!online) throw new Error('Timeout waiting for device after reboot');\n this.log('Device online', 'success');\n\n this.log('Waiting for browser CDP...', 'info');\n const cdpStart = Date.now();\n let cdpReady = false;\n\n while (Date.now() - cdpStart < 30000) {\n try {\n execSync(\n `docker exec \"${androidCont}\" curl -s --connect-timeout 2 http://localhost:9224/json/version`,\n { stdio: 'ignore' }\n );\n cdpReady = true;\n break;\n } catch {\n if (Date.now() - cdpStart > 15000) {\n try {\n execSync(\n `docker exec \"${androidCont}\" adb shell am start -n com.wootzapp.web/com.aspect.chromium.ChromiumMain -a android.intent.action.VIEW -d 'about:blank'`,\n { stdio: 'ignore' }\n );\n } catch {}\n }\n }\n await new Promise((r) => setTimeout(r, 1000));\n }\n\n if (!cdpReady) throw new Error('Timeout waiting for CDP');\n this.log('Fast reset complete!', 'success');\n }\n\n private waitForLog(container: string, pattern: string, timeoutMs = 120000): Promise<void> {\n return new Promise((resolve, reject) => {\n const start = Date.now();\n const tail = spawn('docker', ['logs', '-f', container]);\n\n const timer = setTimeout(() => {\n tail.kill();\n reject(new Error(`Timeout waiting for log pattern \"${pattern}\" in container ${container}`));\n }, timeoutMs);\n\n tail.stdout.on('data', (data) => {\n if (data.toString().includes(pattern)) {\n clearTimeout(timer);\n tail.kill();\n resolve();\n }\n });\n\n tail.stderr.on('data', (data) => {\n if (data.toString().includes(pattern)) {\n clearTimeout(timer);\n tail.kill();\n resolve();\n }\n });\n\n tail.on('error', (err) => {\n clearTimeout(timer);\n reject(err);\n });\n });\n }\n}\n","#!/usr/bin/env node\n\n/**\n * WootzApp Agent Browser CLI\n * \n * Provides terminal-based control over the Android Agent environment.\n * Usage:\n * agent-browser start - Initialize environment (Warm/Cold boot)\n * agent-browser stop - Stop environment\n * agent-browser reset - Fast browser reset (15s)\n * agent-browser open <url> - Open a URL in the browser\n */\n\nimport { WootzAgent } from './index.js';\n\nconst args = process.argv.slice(2);\n// Find the first argument that doesn't start with '-' to be the command\nconst command = args.find(arg => !arg.startsWith('-'));\n\nif (!command || command === 'help') {\n console.log(`\nWootzApp Agent Browser CLI\n\nUsage:\n agent-browser start Initialize and start the environment\n agent-browser stop Stop the environment\n agent-browser reset Fast reset the browser state\n agent-browser <cmd> Run an agent command (e.g. open https://google.com)\n\nOptions:\n --dist Use pre-built images from Docker Hub (default)\n --local Build images locally from source\n`);\n process.exit(0);\n}\n\n// Check for mode flags\nconst isLocal = args.includes('--local');\n// Filter out the --local/--dist flags before passing to command if necessary, \n// but currently our command() method handles raw args.\nconst filteredArgs = args.filter(arg => arg !== '--local' && arg !== '--dist');\n\nconst agent = new WootzAgent({ dist: !isLocal });\n\nasync function main() {\n try {\n switch (command) {\n case 'start':\n await agent.start();\n break;\n case 'stop':\n await agent.stop();\n break;\n case 'reset':\n await agent.reset();\n break;\n default:\n // Pass through arbitrary commands to the agent daemon\n // e.g. \"agent-browser open https://google.com\"\n const result = await agent.command(command!, ...filteredArgs.slice(1));\n console.log(result);\n break;\n }\n } catch (error: any) {\n console.error(`\\n❌ Error: ${error.message || error}`);\n process.exit(1);\n }\n}\n\nmain();\n"],"mappings":"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","names":["path","pino","import_pino","pino","path","args","command"]}
1
+ {"version":3,"sources":["../node_modules/tsup/assets/cjs_shims.js","../src/index.ts","../src/orchestrator.ts","../src/cli.ts"],"sourcesContent":["// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () => \n typeof document === \"undefined\" \n ? new URL(`file:${__filename}`).href \n : (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') \n ? document.currentScript.src \n : new URL(\"main.js\", document.baseURI).href;\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","import * as net from 'net';\nimport { randomUUID } from 'crypto';\nimport { Orchestrator } from './orchestrator.js';\nimport { z } from 'zod';\nimport pino from 'pino';\n\nconst DAEMON_PORT = 32001;\n\n// --- Custom Errors ---\nexport class WootzConnectionError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'WootzConnectionError';\n }\n}\n\nexport class WootzTimeoutError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'WootzTimeoutError';\n }\n}\n\nexport class WootzValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'WootzValidationError';\n }\n}\n\n// --- Schema Validation ---\nconst AgentOptionsSchema = z.object({\n dist: z.boolean().optional().default(true),\n logLevel: z.enum(['debug', 'info', 'warn', 'error', 'silent']).optional().default('info'),\n}).passthrough();\n\n/**\n * Options for initializing the WootzAgent.\n */\nexport type AgentOptions = z.input<typeof AgentOptionsSchema>;\n\n/**\n * Main entry point for interacting with the Agent Browser environment.\n */\nexport class WootzAgent {\n private options: AgentOptions;\n private orchestrator: Orchestrator;\n public logger: pino.Logger;\n\n /**\n * Creates a new instance of the WootzAgent.\n * @param options Configuration options.\n * @throws {WootzValidationError} If the provided options do not match the expected schema.\n */\n constructor(options: AgentOptions = {}) {\n const parsedOptions = AgentOptionsSchema.safeParse(options);\n if (!parsedOptions.success) {\n throw new WootzValidationError(`Invalid agent options: ${parsedOptions.error.message}`);\n }\n \n this.options = parsedOptions.data;\n \n this.logger = pino({\n level: this.options.logLevel,\n transport: this.options.logLevel !== 'silent' ? {\n target: 'pino-pretty',\n options: {\n colorize: true,\n translateTime: 'HH:MM:ss Z',\n ignore: 'pid,hostname',\n },\n } : undefined,\n });\n\n this.orchestrator = new Orchestrator(this.options.dist!, this.logger);\n }\n\n // --- Lifecycle Management (Infrastructure) ---\n\n /**\n * Starts the underlying orchestrator and waits for the browser daemon to be ready.\n * @throws {WootzTimeoutError} If the daemon fails to become available within the timeout.\n */\n async start(): Promise<void> {\n await this.orchestrator.start();\n await this.waitForDaemon();\n }\n\n /**\n * Polls the daemon port until it accepts connections.\n * @param timeoutMs The maximum amount of time (in ms) to wait for the daemon.\n */\n private async waitForDaemon(timeoutMs = 180000): Promise<void> {\n const start = Date.now();\n while (Date.now() - start < timeoutMs) {\n try {\n await this.sendCommand({ action: 'tab_list' }); // Health check\n return; // Success\n } catch {\n await new Promise((r) => setTimeout(r, 1000));\n }\n }\n throw new WootzTimeoutError(\n `Timed out waiting for Agent Daemon on port ${DAEMON_PORT} after ${timeoutMs / 1000}s`\n );\n }\n\n /**\n * Stops the orchestrator and cleans up resources.\n */\n async stop(): Promise<void> {\n await this.orchestrator.stop();\n }\n\n /**\n * Resets the environment completely.\n */\n async reset(): Promise<void> {\n await this.orchestrator.reset();\n }\n\n // --- Core Browser Actions (Direct Daemon) ---\n\n /**\n * Navigates the current tab to a specified URL.\n * @param url The URL to navigate to.\n * @param waitUntil The load state to wait for ('load', 'domcontentloaded', 'networkidle').\n */\n async navigate(\n url: string,\n waitUntil: 'load' | 'domcontentloaded' | 'networkidle' = 'load'\n ): Promise<string> {\n return await this.sendCommand({ action: 'navigate', url, waitUntil });\n }\n\n /**\n * Clicks on an element matching the given selector.\n * @param selector The CSS or semantic selector of the element to click.\n */\n async click(selector: string): Promise<string> {\n return await this.sendCommand({ action: 'click', selector });\n }\n\n /**\n * Double-clicks on an element matching the given selector.\n * @param selector The CSS or semantic selector.\n */\n async doubleClick(selector: string): Promise<string> {\n return await this.sendCommand({ action: 'dblclick', selector });\n }\n\n /**\n * Types text into a form field character by character.\n * @param selector The CSS or semantic selector of the input field.\n * @param text The text to type.\n * @param delay Delay between keystrokes in milliseconds.\n */\n async type(selector: string, text: string, delay?: number): Promise<string> {\n return await this.sendCommand({ action: 'type', selector, text, delay });\n }\n\n /**\n * Fills an input field directly with a value (faster than type).\n * @param selector The CSS or semantic selector of the input field.\n * @param value The value to fill.\n */\n async fill(selector: string, value: string): Promise<string> {\n return await this.sendCommand({ action: 'fill', selector, value });\n }\n\n async check(selector: string): Promise<string> {\n return await this.sendCommand({ action: 'check', selector });\n }\n\n async uncheck(selector: string): Promise<string> {\n return await this.sendCommand({ action: 'uncheck', selector });\n }\n\n async hover(selector: string): Promise<string> {\n return await this.sendCommand({ action: 'hover', selector });\n }\n\n async focus(selector: string): Promise<string> {\n return await this.sendCommand({ action: 'focus', selector });\n }\n\n async press(key: string, selector?: string): Promise<string> {\n return await this.sendCommand({ action: 'press', key, selector });\n }\n\n async selectOption(selector: string, value: string | string[]): Promise<string> {\n return await this.sendCommand({ action: 'select', selector, values: value });\n }\n\n // --- Introspection & State ---\n\n /**\n * Captures the full DOM/AXTree snapshot of the current page.\n * @returns A string representation of the interactive accessibility tree.\n */\n async snapshot(): Promise<string> {\n const result = await this.sendCommand({ action: 'snapshot' }, true);\n return result.snapshot || '';\n }\n\n async innerText(selector: string): Promise<string> {\n const res = await this.sendCommand({ action: 'innertext', selector }, true);\n return res.text;\n }\n\n async innerHTML(selector: string): Promise<string> {\n const res = await this.sendCommand({ action: 'innerhtml', selector }, true);\n return res.html;\n }\n\n async getAttribute(selector: string, attribute: string): Promise<string> {\n const res = await this.sendCommand({ action: 'getattribute', selector, attribute }, true);\n return res.value;\n }\n\n async inputValue(selector: string): Promise<string> {\n const res = await this.sendCommand({ action: 'inputvalue', selector }, true);\n return res.value;\n }\n\n async isVisible(selector: string): Promise<boolean> {\n const res = await this.sendCommand({ action: 'isvisible', selector }, true);\n return res.visible;\n }\n\n async isEnabled(selector: string): Promise<boolean> {\n const res = await this.sendCommand({ action: 'isenabled', selector }, true);\n return res.enabled;\n }\n\n async isChecked(selector: string): Promise<boolean> {\n const res = await this.sendCommand({ action: 'ischecked', selector }, true);\n return res.checked;\n }\n\n // --- Waiting & Navigation ---\n\n async waitForSelector(\n selector: string,\n state: 'attached' | 'detached' | 'visible' | 'hidden' = 'visible',\n timeout?: number\n ): Promise<string> {\n return await this.sendCommand({ action: 'wait', selector, state, timeout });\n }\n\n async waitForTimeout(ms: number): Promise<string> {\n return await this.sendCommand({ action: 'wait', timeout: ms });\n }\n\n async waitForLoadState(\n state: 'load' | 'domcontentloaded' | 'networkidle' = 'load'\n ): Promise<string> {\n return await this.sendCommand({ action: 'waitforloadstate', state });\n }\n\n async reload(): Promise<string> {\n return await this.sendCommand({ action: 'reload' });\n }\n\n async goBack(): Promise<string> {\n return await this.sendCommand({ action: 'back' });\n }\n\n async goForward(): Promise<string> {\n return await this.sendCommand({ action: 'forward' });\n }\n\n // --- Semantic Locators ---\n\n async getByRole(role: string, name?: string, _exact: boolean = false): Promise<string> {\n throw new Error(\n 'Locator builders (getByRole) are not fully supported in stateless mode yet. Use standard selectors.'\n );\n }\n\n // --- Utilities ---\n\n /**\n * Captures a screenshot of the current page.\n * @param path Optional file path to save the screenshot.\n */\n async screenshot(path?: string): Promise<string> {\n const res = await this.sendCommand({ action: 'screenshot', path }, true);\n return res.path;\n }\n\n async scroll(x: number, y: number): Promise<string> {\n return await this.sendCommand({ action: 'scroll', x, y });\n }\n\n async evaluate(script: string): Promise<any> {\n const res = await this.sendCommand({ action: 'evaluate', script }, true);\n return res.result;\n }\n\n // --- Tab Management ---\n\n async newTab(url?: string): Promise<string> {\n return await this.sendCommand({ action: 'tab_new', url });\n }\n\n async switchTab(index: number): Promise<string> {\n return await this.sendCommand({ action: 'tab_switch', index });\n }\n\n async closeTab(index?: number): Promise<string> {\n return await this.sendCommand({ action: 'tab_close', index });\n }\n\n async listTabs(): Promise<any[]> {\n const res = await this.sendCommand({ action: 'tab_list' }, true);\n return res.tabs;\n }\n\n // --- Generic Execution ---\n\n async command(action: string, ...args: string[]): Promise<string> {\n const cmd: any = { action };\n\n if (action === 'open' || action === 'navigate') {\n cmd.action = 'navigate';\n cmd.url = args[0];\n } else if (action === 'click') {\n cmd.selector = args[0];\n } else if (action === 'type') {\n cmd.selector = args[0];\n cmd.text = args[1];\n } else if (action === 'press') {\n cmd.key = args[0];\n } else if (action === 'scroll') {\n cmd.x = parseInt(args[0] || '0');\n cmd.y = parseInt(args[1] || '0');\n } else if (action === 'wait') {\n if (/^\\d+$/.test(args[0])) cmd.timeout = parseInt(args[0]);\n else cmd.selector = args[0];\n } else {\n if (args[0]) cmd.selector = args[0];\n if (args[1]) cmd.text = args[1] || args[1]; // value/text\n }\n\n const res = await this.sendCommand(cmd, true);\n\n if (typeof res === 'object') {\n if (res.text) return res.text;\n if (res.url) return res.url;\n if (res.snapshot) return res.snapshot;\n return JSON.stringify(res);\n }\n return String(res);\n }\n\n private sendCommand(command: any, returnData = false): Promise<any> {\n return new Promise((resolve, reject) => {\n if (!command.id) command.id = randomUUID();\n\n const client = new net.Socket();\n\n client.connect(DAEMON_PORT, '127.0.0.1', () => {\n client.write(JSON.stringify(command) + '\\n');\n });\n\n let responseBuffer = '';\n\n client.on('data', (data) => {\n responseBuffer += data.toString();\n if (responseBuffer.includes('\\n')) {\n client.end();\n }\n });\n\n client.on('end', () => {\n try {\n const response = JSON.parse(responseBuffer.trim());\n if (response.success) {\n resolve(returnData ? response.data : 'OK');\n } else {\n reject(new Error(response.error || 'Unknown error'));\n }\n } catch {\n reject(new Error(`Invalid response from daemon: ${responseBuffer}`));\n }\n });\n\n client.on('error', (err) => {\n reject(new WootzConnectionError(`Failed to connect to agent daemon (is it running?): ${err.message}`));\n });\n });\n }\n}\n\nexport default WootzAgent;","import { spawn, execSync } from 'child_process';\nimport path from 'path';\nimport 'fs';\nimport { fileURLToPath } from 'url';\nimport pino from 'pino';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst PROJECT_ROOT = path.resolve(__dirname, '..');\n\nexport class Orchestrator {\n private composeFile: string;\n private logger: pino.Logger;\n\n constructor(distMode: boolean, logger?: pino.Logger) {\n this.composeFile = path.join(\n PROJECT_ROOT,\n distMode ? 'docker-compose.sdk.yml' : 'docker-compose.prod.yml'\n );\n this.logger = logger || pino();\n }\n\n private log(msg: string, level: 'info' | 'success' | 'warn' | 'error' = 'info') {\n switch (level) {\n case 'success':\n this.logger.info({ sdk: true }, msg);\n break;\n case 'warn':\n this.logger.warn({ sdk: true }, msg);\n break;\n case 'error':\n this.logger.error({ sdk: true }, msg);\n break;\n default:\n this.logger.info({ sdk: true }, msg);\n }\n }\n\n private runCommand(cmd: string, env: Record<string, string> = {}): boolean {\n try {\n execSync(cmd, {\n stdio: 'inherit',\n env: { ...process.env, ...env },\n });\n return true;\n } catch {\n return false;\n }\n }\n\n private getContainerId(serviceName: string): string | null {\n try {\n const output = execSync(`docker compose -f \"${this.composeFile}\" ps -q ${serviceName}`, {\n encoding: 'utf-8',\n });\n return output.trim() || null;\n } catch {\n return null;\n }\n }\n\n private isPortMapped(containerId: string, port: number): boolean {\n try {\n const output = execSync(`docker port \"${containerId}\" ${port}`, { encoding: 'utf-8' });\n return output.includes('0.0.0.0:') || output.includes(':::');\n } catch {\n return false;\n }\n }\n\n private async pullImagesWithRetry(): Promise<void> {\n if (!this.composeFile.endsWith('docker-compose.sdk.yml')) return;\n\n this.log('Please wait while we get things ready...', 'info');\n const maxRetries = 10;\n\n for (let count = 0; count < maxRetries; count++) {\n if (this.runCommand(`docker compose -f \"${this.composeFile}\" pull`)) {\n return;\n }\n this.log(\n `Download failed/interrupted. Retrying (${count + 1}/${maxRetries}) in 10s...`,\n 'warn'\n );\n await new Promise((r) => setTimeout(r, 10000));\n }\n\n this.log(\n `Failed to download images after ${maxRetries} attempts. Check internet connection.`,\n 'error'\n );\n process.exit(1);\n }\n\n private async hasSnapshot(): Promise<boolean> {\n try {\n // 1. Check if volume exists\n execSync(`docker volume inspect agent-snapshots`, { stdio: 'ignore' });\n\n // 2. Check if volume contains the 'quickboot' directory\n // We use a tiny helper container to look inside the managed volume\n const output = execSync(`docker run --rm -v agent-snapshots:/data busybox ls /data`, {\n encoding: 'utf-8',\n });\n return output.includes('quickboot');\n } catch {\n return false;\n }\n }\n\n public async start(): Promise<void> {\n this.log(`Initializing Agent Environment...`, 'info');\n\n await this.pullImagesWithRetry();\n\n this.log('Cleaning up previous container state...', 'info');\n this.runCommand(`docker compose -f \"${this.composeFile}\" down -v --remove-orphans`);\n\n const hasSnapshot = await this.hasSnapshot();\n\n if (hasSnapshot) {\n // === WARM START ===\n this.log('Found cached baseline snapshot. Performing HYPER-SPEED WARM BOOT...', 'success');\n\n const success = this.runCommand(`docker compose -f \"${this.composeFile}\" up -d`, {\n EMULATOR_SNAPSHOT_NAME: 'quickboot',\n });\n\n if (!success) throw new Error('Startup failed during docker compose up.');\n\n const agentCont = this.getContainerId('agent-service');\n const androidCont = this.getContainerId('android-service');\n\n // Verify Port Mapping\n if (agentCont && !this.isPortMapped(agentCont, 3000)) {\n this.log('Port 3000 (Host 32001) is not mapped! Container config is stale.', 'warn');\n this.log('Forcing full restart to apply network settings...', 'info');\n this.runCommand(`docker compose -f \"${this.composeFile}\" down -v --remove-orphans`);\n await new Promise((r) => setTimeout(r, 5000));\n this.runCommand(`docker compose -f \"${this.composeFile}\" up -d`, {\n EMULATOR_SNAPSHOT_NAME: 'quickboot',\n });\n }\n\n if (androidCont) {\n this.log('Rehydrating Android network connection...', 'info');\n try {\n execSync(`docker exec \"${androidCont}\" adb shell cmd connectivity airplane-mode enable`, {\n stdio: 'ignore',\n });\n await new Promise((r) => setTimeout(r, 2000));\n execSync(\n `docker exec \"${androidCont}\" adb shell cmd connectivity airplane-mode disable`,\n { stdio: 'ignore' }\n );\n await new Promise((r) => setTimeout(r, 3000));\n } catch {\n this.log(`Network rehydration warning: ${e}`, 'warn');\n }\n }\n\n this.log('Waiting for Daemon Connection...');\n if (agentCont) await this.waitForLog(agentCont, 'Daemon listening on TCP', 180000);\n } else {\n // === COLD START ===\n this.log('No baseline found. Performing FIRST RUN SETUP (Cold Boot)...', 'warn');\n this.log('This will take ~60-90 seconds, but only once.', 'warn');\n\n const success = this.runCommand(`docker compose -f \"${this.composeFile}\" up -d`, {\n EMULATOR_SNAPSHOT_NAME: '',\n });\n\n if (!success) throw new Error('Startup failed during docker compose up.');\n\n let androidCont = this.getContainerId('android-service');\n const agentCont = this.getContainerId('agent-service');\n\n if (!androidCont) throw new Error('Error: Android container not found.');\n\n // Verify Port Mapping\n if (agentCont && !this.isPortMapped(agentCont, 3000)) {\n this.log('Port 3000 (Host 32001) is not mapped! Container config is stale.', 'warn');\n this.log('Forcing full restart to apply network settings...', 'info');\n this.runCommand(`docker compose -f \"${this.composeFile}\" down -v --remove-orphans`);\n await new Promise((r) => setTimeout(r, 5000));\n this.runCommand(`docker compose -f \"${this.composeFile}\" up -d`, {\n EMULATOR_SNAPSHOT_NAME: '',\n });\n androidCont = this.getContainerId('android-service') || androidCont;\n }\n\n this.log('Waiting for Android OS to boot (this takes a moment)...', 'info');\n await this.waitForLog(androidCont, 'Emulator boot complete');\n\n this.log('Waiting for Browser Installation...', 'info');\n await this.waitForLog(androidCont, 'APK installation complete');\n\n this.log('Waiting for CDP Bridge...', 'info');\n await this.waitForLog(androidCont, 'CDP Bridge ready');\n\n this.log('Waiting for Agent Daemon Connection...');\n if (agentCont) await this.waitForLog(agentCont, 'Daemon listening on TCP');\n\n // Save Snapshot\n this.log('Saving emulator state (quickboot)...', 'info');\n const saved = this.runCommand(\n `docker exec \"${androidCont}\" adb emu avd snapshot save quickboot`\n );\n if (saved) {\n this.log('Snapshot saved to host volume.', 'success');\n this.log('Setup Complete! Future runs will launch instantly.', 'success');\n } else {\n throw new Error('Failed to save snapshot inside emulator.');\n }\n }\n }\n\n public async stop(): Promise<void> {\n this.log('Stopping environment...', 'info');\n this.runCommand(`docker compose -f \"${this.composeFile}\" down -v --remove-orphans`);\n this.log('Environment cleaned and stopped.', 'success');\n }\n\n public async reset(): Promise<void> {\n this.log('Performing Fast Browser Reset...', 'info');\n const androidCont = this.getContainerId('android-service');\n if (!androidCont) {\n this.log('Android container not running.', 'error');\n return;\n }\n\n this.log('Initiating fast reset (userspace reboot)...', 'info');\n try {\n execSync(`docker exec \"${androidCont}\" adb shell reboot userspace`, { stdio: 'ignore' });\n } catch {\n // Ignored\n }\n\n this.log('Waiting for device to come online...', 'info');\n \n let online = false;\n\n while (Date.now() - start < 30000) {\n try {\n const state = execSync(`docker exec \"${androidCont}\" adb get-state`, {\n encoding: 'utf-8',\n }).trim();\n if (state === 'device') {\n execSync(`docker exec \"${androidCont}\" adb shell echo ok`, { stdio: 'ignore' });\n online = true;\n break;\n }\n } catch {\n // Still offline\n }\n await new Promise((r) => setTimeout(r, 1000));\n }\n\n if (!online) throw new Error('Timeout waiting for device after reboot');\n this.log('Device online', 'success');\n\n this.log('Waiting for browser CDP...', 'info');\n const cdpStart = Date.now();\n let cdpReady = false;\n\n while (Date.now() - cdpStart < 30000) {\n try {\n execSync(\n `docker exec \"${androidCont}\" curl -s --connect-timeout 2 http://localhost:9224/json/version`,\n { stdio: 'ignore' }\n );\n cdpReady = true;\n break;\n } catch {\n if (Date.now() - cdpStart > 15000) {\n try {\n execSync(\n `docker exec \"${androidCont}\" adb shell am start -n com.wootzapp.web/com.aspect.chromium.ChromiumMain -a android.intent.action.VIEW -d 'about:blank'`,\n { stdio: 'ignore' }\n );\n } catch {}\n }\n }\n await new Promise((r) => setTimeout(r, 1000));\n }\n\n if (!cdpReady) throw new Error('Timeout waiting for CDP');\n this.log('Fast reset complete!', 'success');\n }\n\n private waitForLog(container: string, pattern: string, timeoutMs = 120000): Promise<void> {\n return new Promise((resolve, reject) => {\n \n const tail = spawn('docker', ['logs', '-f', container]);\n\n const timer = setTimeout(() => {\n tail.kill();\n reject(new Error(`Timeout waiting for log pattern \"${pattern}\" in container ${container}`));\n }, timeoutMs);\n\n tail.stdout.on('data', (data) => {\n if (data.toString().includes(pattern)) {\n clearTimeout(timer);\n tail.kill();\n resolve();\n }\n });\n\n tail.stderr.on('data', (data) => {\n if (data.toString().includes(pattern)) {\n clearTimeout(timer);\n tail.kill();\n resolve();\n }\n });\n\n tail.on('error', (err) => {\n clearTimeout(timer);\n reject(err);\n });\n });\n }\n}\n","#!/usr/bin/env node\n\n/**\n * WootzApp Agent Browser CLI\n * \n * Provides terminal-based control over the Android Agent environment.\n * Usage:\n * agent-browser start - Initialize environment (Warm/Cold boot)\n * agent-browser stop - Stop environment\n * agent-browser reset - Fast browser reset (15s)\n * agent-browser open <url> - Open a URL in the browser\n */\n\nimport { WootzAgent } from './index.js';\n\nconst args = process.argv.slice(2);\n// Find the first argument that doesn't start with '-' to be the command\nconst command = args.find(arg => !arg.startsWith('-'));\n\nif (!command || command === 'help') {\n console.log(`\nWootzApp Agent Browser CLI\n\nUsage:\n agent-browser start Initialize and start the environment\n agent-browser stop Stop the environment\n agent-browser reset Fast reset the browser state\n agent-browser <cmd> Run an agent command (e.g. open https://google.com)\n\nOptions:\n --dist Use pre-built images from Docker Hub (default)\n --local Build images locally from source\n`);\n process.exit(0);\n}\n\n// Check for mode flags\nconst isLocal = args.includes('--local');\n// Filter out the --local/--dist flags before passing to command if necessary, \n// but currently our command() method handles raw args.\nconst filteredArgs = args.filter(arg => arg !== '--local' && arg !== '--dist');\n\nconst agent = new WootzAgent({ dist: !isLocal });\n\nasync function main() {\n try {\n switch (command) {\n case 'start':\n await agent.start();\n break;\n case 'stop':\n await agent.stop();\n break;\n case 'reset':\n await agent.reset();\n break;\n default:\n // Pass through arbitrary commands to the agent daemon\n // e.g. \"agent-browser open https://google.com\"\n const result = await agent.command(command!, ...filteredArgs.slice(1));\n console.log(result);\n break;\n }\n } catch (error: any) {\n console.error(`\\n❌ Error: ${error.message || error}`);\n process.exit(1);\n }\n}\n\nmain();\n"],"mappings":"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","names":["path","pino","import_pino","pino","start","path","args","command"]}
package/dist/cli.js CHANGED
@@ -43,7 +43,7 @@ var Orchestrator = class {
43
43
  env: { ...process.env, ...env }
44
44
  });
45
45
  return true;
46
- } catch (e) {
46
+ } catch {
47
47
  return false;
48
48
  }
49
49
  }
@@ -131,7 +131,7 @@ var Orchestrator = class {
131
131
  { stdio: "ignore" }
132
132
  );
133
133
  await new Promise((r) => setTimeout(r, 3e3));
134
- } catch (e) {
134
+ } catch {
135
135
  this.log(`Network rehydration warning: ${e}`, "warn");
136
136
  }
137
137
  }
@@ -195,7 +195,6 @@ var Orchestrator = class {
195
195
  } catch {
196
196
  }
197
197
  this.log("Waiting for device to come online...", "info");
198
- const start = Date.now();
199
198
  let online = false;
200
199
  while (Date.now() - start < 3e4) {
201
200
  try {
@@ -242,7 +241,6 @@ var Orchestrator = class {
242
241
  }
243
242
  waitForLog(container, pattern, timeoutMs = 12e4) {
244
243
  return new Promise((resolve, reject) => {
245
- const start = Date.now();
246
244
  const tail = spawn("docker", ["logs", "-f", container]);
247
245
  const timer = setTimeout(() => {
248
246
  tail.kill();
@@ -338,12 +336,12 @@ var WootzAgent = class {
338
336
  * @param timeoutMs The maximum amount of time (in ms) to wait for the daemon.
339
337
  */
340
338
  async waitForDaemon(timeoutMs = 18e4) {
341
- const start = Date.now();
342
- while (Date.now() - start < timeoutMs) {
339
+ const start2 = Date.now();
340
+ while (Date.now() - start2 < timeoutMs) {
343
341
  try {
344
342
  await this.sendCommand({ action: "tab_list" });
345
343
  return;
346
- } catch (e) {
344
+ } catch {
347
345
  await new Promise((r) => setTimeout(r, 1e3));
348
346
  }
349
347
  }
@@ -567,7 +565,7 @@ var WootzAgent = class {
567
565
  } else {
568
566
  reject(new Error(response.error || "Unknown error"));
569
567
  }
570
- } catch (e) {
568
+ } catch {
571
569
  reject(new Error(`Invalid response from daemon: ${responseBuffer}`));
572
570
  }
573
571
  });
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/orchestrator.ts","../src/cli.ts"],"sourcesContent":["import * as net from 'net';\nimport { randomUUID } from 'crypto';\nimport { Orchestrator } from './orchestrator.js';\nimport { z } from 'zod';\nimport pino from 'pino';\n\nconst DAEMON_PORT = 32001;\n\n// --- Custom Errors ---\nexport class WootzConnectionError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'WootzConnectionError';\n }\n}\n\nexport class WootzTimeoutError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'WootzTimeoutError';\n }\n}\n\nexport class WootzValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'WootzValidationError';\n }\n}\n\n// --- Schema Validation ---\nconst AgentOptionsSchema = z.object({\n dist: z.boolean().optional().default(true),\n logLevel: z.enum(['debug', 'info', 'warn', 'error', 'silent']).optional().default('info'),\n}).passthrough();\n\n/**\n * Options for initializing the WootzAgent.\n */\nexport interface AgentOptions extends z.input<typeof AgentOptionsSchema> {}\n\n/**\n * Main entry point for interacting with the Agent Browser environment.\n */\nexport class WootzAgent {\n private options: AgentOptions;\n private orchestrator: Orchestrator;\n public logger: pino.Logger;\n\n /**\n * Creates a new instance of the WootzAgent.\n * @param options Configuration options.\n * @throws {WootzValidationError} If the provided options do not match the expected schema.\n */\n constructor(options: AgentOptions = {}) {\n const parsedOptions = AgentOptionsSchema.safeParse(options);\n if (!parsedOptions.success) {\n throw new WootzValidationError(`Invalid agent options: ${parsedOptions.error.message}`);\n }\n \n this.options = parsedOptions.data;\n \n this.logger = pino({\n level: this.options.logLevel,\n transport: this.options.logLevel !== 'silent' ? {\n target: 'pino-pretty',\n options: {\n colorize: true,\n translateTime: 'HH:MM:ss Z',\n ignore: 'pid,hostname',\n },\n } : undefined,\n });\n\n this.orchestrator = new Orchestrator(this.options.dist!, this.logger);\n }\n\n // --- Lifecycle Management (Infrastructure) ---\n\n /**\n * Starts the underlying orchestrator and waits for the browser daemon to be ready.\n * @throws {WootzTimeoutError} If the daemon fails to become available within the timeout.\n */\n async start(): Promise<void> {\n await this.orchestrator.start();\n await this.waitForDaemon();\n }\n\n /**\n * Polls the daemon port until it accepts connections.\n * @param timeoutMs The maximum amount of time (in ms) to wait for the daemon.\n */\n private async waitForDaemon(timeoutMs = 180000): Promise<void> {\n const start = Date.now();\n while (Date.now() - start < timeoutMs) {\n try {\n await this.sendCommand({ action: 'tab_list' }); // Health check\n return; // Success\n } catch (e) {\n await new Promise((r) => setTimeout(r, 1000));\n }\n }\n throw new WootzTimeoutError(\n `Timed out waiting for Agent Daemon on port ${DAEMON_PORT} after ${timeoutMs / 1000}s`\n );\n }\n\n /**\n * Stops the orchestrator and cleans up resources.\n */\n async stop(): Promise<void> {\n await this.orchestrator.stop();\n }\n\n /**\n * Resets the environment completely.\n */\n async reset(): Promise<void> {\n await this.orchestrator.reset();\n }\n\n // --- Core Browser Actions (Direct Daemon) ---\n\n /**\n * Navigates the current tab to a specified URL.\n * @param url The URL to navigate to.\n * @param waitUntil The load state to wait for ('load', 'domcontentloaded', 'networkidle').\n */\n async navigate(\n url: string,\n waitUntil: 'load' | 'domcontentloaded' | 'networkidle' = 'load'\n ): Promise<string> {\n return await this.sendCommand({ action: 'navigate', url, waitUntil });\n }\n\n /**\n * Clicks on an element matching the given selector.\n * @param selector The CSS or semantic selector of the element to click.\n */\n async click(selector: string): Promise<string> {\n return await this.sendCommand({ action: 'click', selector });\n }\n\n /**\n * Double-clicks on an element matching the given selector.\n * @param selector The CSS or semantic selector.\n */\n async doubleClick(selector: string): Promise<string> {\n return await this.sendCommand({ action: 'dblclick', selector });\n }\n\n /**\n * Types text into a form field character by character.\n * @param selector The CSS or semantic selector of the input field.\n * @param text The text to type.\n * @param delay Delay between keystrokes in milliseconds.\n */\n async type(selector: string, text: string, delay?: number): Promise<string> {\n return await this.sendCommand({ action: 'type', selector, text, delay });\n }\n\n /**\n * Fills an input field directly with a value (faster than type).\n * @param selector The CSS or semantic selector of the input field.\n * @param value The value to fill.\n */\n async fill(selector: string, value: string): Promise<string> {\n return await this.sendCommand({ action: 'fill', selector, value });\n }\n\n async check(selector: string): Promise<string> {\n return await this.sendCommand({ action: 'check', selector });\n }\n\n async uncheck(selector: string): Promise<string> {\n return await this.sendCommand({ action: 'uncheck', selector });\n }\n\n async hover(selector: string): Promise<string> {\n return await this.sendCommand({ action: 'hover', selector });\n }\n\n async focus(selector: string): Promise<string> {\n return await this.sendCommand({ action: 'focus', selector });\n }\n\n async press(key: string, selector?: string): Promise<string> {\n return await this.sendCommand({ action: 'press', key, selector });\n }\n\n async selectOption(selector: string, value: string | string[]): Promise<string> {\n return await this.sendCommand({ action: 'select', selector, values: value });\n }\n\n // --- Introspection & State ---\n\n /**\n * Captures the full DOM/AXTree snapshot of the current page.\n * @returns A string representation of the interactive accessibility tree.\n */\n async snapshot(): Promise<string> {\n const result = await this.sendCommand({ action: 'snapshot' }, true);\n return result.snapshot || '';\n }\n\n async innerText(selector: string): Promise<string> {\n const res = await this.sendCommand({ action: 'innertext', selector }, true);\n return res.text;\n }\n\n async innerHTML(selector: string): Promise<string> {\n const res = await this.sendCommand({ action: 'innerhtml', selector }, true);\n return res.html;\n }\n\n async getAttribute(selector: string, attribute: string): Promise<string> {\n const res = await this.sendCommand({ action: 'getattribute', selector, attribute }, true);\n return res.value;\n }\n\n async inputValue(selector: string): Promise<string> {\n const res = await this.sendCommand({ action: 'inputvalue', selector }, true);\n return res.value;\n }\n\n async isVisible(selector: string): Promise<boolean> {\n const res = await this.sendCommand({ action: 'isvisible', selector }, true);\n return res.visible;\n }\n\n async isEnabled(selector: string): Promise<boolean> {\n const res = await this.sendCommand({ action: 'isenabled', selector }, true);\n return res.enabled;\n }\n\n async isChecked(selector: string): Promise<boolean> {\n const res = await this.sendCommand({ action: 'ischecked', selector }, true);\n return res.checked;\n }\n\n // --- Waiting & Navigation ---\n\n async waitForSelector(\n selector: string,\n state: 'attached' | 'detached' | 'visible' | 'hidden' = 'visible',\n timeout?: number\n ): Promise<string> {\n return await this.sendCommand({ action: 'wait', selector, state, timeout });\n }\n\n async waitForTimeout(ms: number): Promise<string> {\n return await this.sendCommand({ action: 'wait', timeout: ms });\n }\n\n async waitForLoadState(\n state: 'load' | 'domcontentloaded' | 'networkidle' = 'load'\n ): Promise<string> {\n return await this.sendCommand({ action: 'waitforloadstate', state });\n }\n\n async reload(): Promise<string> {\n return await this.sendCommand({ action: 'reload' });\n }\n\n async goBack(): Promise<string> {\n return await this.sendCommand({ action: 'back' });\n }\n\n async goForward(): Promise<string> {\n return await this.sendCommand({ action: 'forward' });\n }\n\n // --- Semantic Locators ---\n\n async getByRole(role: string, name?: string, _exact: boolean = false): Promise<string> {\n throw new Error(\n 'Locator builders (getByRole) are not fully supported in stateless mode yet. Use standard selectors.'\n );\n }\n\n // --- Utilities ---\n\n /**\n * Captures a screenshot of the current page.\n * @param path Optional file path to save the screenshot.\n */\n async screenshot(path?: string): Promise<string> {\n const res = await this.sendCommand({ action: 'screenshot', path }, true);\n return res.path;\n }\n\n async scroll(x: number, y: number): Promise<string> {\n return await this.sendCommand({ action: 'scroll', x, y });\n }\n\n async evaluate(script: string): Promise<any> {\n const res = await this.sendCommand({ action: 'evaluate', script }, true);\n return res.result;\n }\n\n // --- Tab Management ---\n\n async newTab(url?: string): Promise<string> {\n return await this.sendCommand({ action: 'tab_new', url });\n }\n\n async switchTab(index: number): Promise<string> {\n return await this.sendCommand({ action: 'tab_switch', index });\n }\n\n async closeTab(index?: number): Promise<string> {\n return await this.sendCommand({ action: 'tab_close', index });\n }\n\n async listTabs(): Promise<any[]> {\n const res = await this.sendCommand({ action: 'tab_list' }, true);\n return res.tabs;\n }\n\n // --- Generic Execution ---\n\n async command(action: string, ...args: string[]): Promise<string> {\n const cmd: any = { action };\n\n if (action === 'open' || action === 'navigate') {\n cmd.action = 'navigate';\n cmd.url = args[0];\n } else if (action === 'click') {\n cmd.selector = args[0];\n } else if (action === 'type') {\n cmd.selector = args[0];\n cmd.text = args[1];\n } else if (action === 'press') {\n cmd.key = args[0];\n } else if (action === 'scroll') {\n cmd.x = parseInt(args[0] || '0');\n cmd.y = parseInt(args[1] || '0');\n } else if (action === 'wait') {\n if (/^\\d+$/.test(args[0])) cmd.timeout = parseInt(args[0]);\n else cmd.selector = args[0];\n } else {\n if (args[0]) cmd.selector = args[0];\n if (args[1]) cmd.text = args[1] || args[1]; // value/text\n }\n\n const res = await this.sendCommand(cmd, true);\n\n if (typeof res === 'object') {\n if (res.text) return res.text;\n if (res.url) return res.url;\n if (res.snapshot) return res.snapshot;\n return JSON.stringify(res);\n }\n return String(res);\n }\n\n private sendCommand(command: any, returnData = false): Promise<any> {\n return new Promise((resolve, reject) => {\n if (!command.id) command.id = randomUUID();\n\n const client = new net.Socket();\n\n client.connect(DAEMON_PORT, '127.0.0.1', () => {\n client.write(JSON.stringify(command) + '\\n');\n });\n\n let responseBuffer = '';\n\n client.on('data', (data) => {\n responseBuffer += data.toString();\n if (responseBuffer.includes('\\n')) {\n client.end();\n }\n });\n\n client.on('end', () => {\n try {\n const response = JSON.parse(responseBuffer.trim());\n if (response.success) {\n resolve(returnData ? response.data : 'OK');\n } else {\n reject(new Error(response.error || 'Unknown error'));\n }\n } catch (e) {\n reject(new Error(`Invalid response from daemon: ${responseBuffer}`));\n }\n });\n\n client.on('error', (err) => {\n reject(new WootzConnectionError(`Failed to connect to agent daemon (is it running?): ${err.message}`));\n });\n });\n }\n}\n\nexport default WootzAgent;","import { spawn, spawnSync, execSync } from 'child_process';\nimport path from 'path';\nimport 'fs';\nimport { fileURLToPath } from 'url';\nimport pino from 'pino';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst PROJECT_ROOT = path.resolve(__dirname, '..');\n\nexport class Orchestrator {\n private composeFile: string;\n private logger: pino.Logger;\n\n constructor(distMode: boolean, logger?: pino.Logger) {\n this.composeFile = path.join(\n PROJECT_ROOT,\n distMode ? 'docker-compose.sdk.yml' : 'docker-compose.prod.yml'\n );\n this.logger = logger || pino();\n }\n\n private log(msg: string, level: 'info' | 'success' | 'warn' | 'error' = 'info') {\n switch (level) {\n case 'success':\n this.logger.info({ sdk: true }, msg);\n break;\n case 'warn':\n this.logger.warn({ sdk: true }, msg);\n break;\n case 'error':\n this.logger.error({ sdk: true }, msg);\n break;\n default:\n this.logger.info({ sdk: true }, msg);\n }\n }\n\n private runCommand(cmd: string, env: Record<string, string> = {}): boolean {\n try {\n execSync(cmd, {\n stdio: 'inherit',\n env: { ...process.env, ...env },\n });\n return true;\n } catch (e) {\n return false;\n }\n }\n\n private getContainerId(serviceName: string): string | null {\n try {\n const output = execSync(`docker compose -f \"${this.composeFile}\" ps -q ${serviceName}`, {\n encoding: 'utf-8',\n });\n return output.trim() || null;\n } catch {\n return null;\n }\n }\n\n private isPortMapped(containerId: string, port: number): boolean {\n try {\n const output = execSync(`docker port \"${containerId}\" ${port}`, { encoding: 'utf-8' });\n return output.includes('0.0.0.0:') || output.includes(':::');\n } catch {\n return false;\n }\n }\n\n private async pullImagesWithRetry(): Promise<void> {\n if (!this.composeFile.endsWith('docker-compose.sdk.yml')) return;\n\n this.log('Please wait while we get things ready...', 'info');\n const maxRetries = 10;\n\n for (let count = 0; count < maxRetries; count++) {\n if (this.runCommand(`docker compose -f \"${this.composeFile}\" pull`)) {\n return;\n }\n this.log(\n `Download failed/interrupted. Retrying (${count + 1}/${maxRetries}) in 10s...`,\n 'warn'\n );\n await new Promise((r) => setTimeout(r, 10000));\n }\n\n this.log(\n `Failed to download images after ${maxRetries} attempts. Check internet connection.`,\n 'error'\n );\n process.exit(1);\n }\n\n private async hasSnapshot(): Promise<boolean> {\n try {\n // 1. Check if volume exists\n execSync(`docker volume inspect agent-snapshots`, { stdio: 'ignore' });\n\n // 2. Check if volume contains the 'quickboot' directory\n // We use a tiny helper container to look inside the managed volume\n const output = execSync(`docker run --rm -v agent-snapshots:/data busybox ls /data`, {\n encoding: 'utf-8',\n });\n return output.includes('quickboot');\n } catch {\n return false;\n }\n }\n\n public async start(): Promise<void> {\n this.log(`Initializing Agent Environment...`, 'info');\n\n await this.pullImagesWithRetry();\n\n this.log('Cleaning up previous container state...', 'info');\n this.runCommand(`docker compose -f \"${this.composeFile}\" down -v --remove-orphans`);\n\n const hasSnapshot = await this.hasSnapshot();\n\n if (hasSnapshot) {\n // === WARM START ===\n this.log('Found cached baseline snapshot. Performing HYPER-SPEED WARM BOOT...', 'success');\n\n const success = this.runCommand(`docker compose -f \"${this.composeFile}\" up -d`, {\n EMULATOR_SNAPSHOT_NAME: 'quickboot',\n });\n\n if (!success) throw new Error('Startup failed during docker compose up.');\n\n const agentCont = this.getContainerId('agent-service');\n const androidCont = this.getContainerId('android-service');\n\n // Verify Port Mapping\n if (agentCont && !this.isPortMapped(agentCont, 3000)) {\n this.log('Port 3000 (Host 32001) is not mapped! Container config is stale.', 'warn');\n this.log('Forcing full restart to apply network settings...', 'info');\n this.runCommand(`docker compose -f \"${this.composeFile}\" down -v --remove-orphans`);\n await new Promise((r) => setTimeout(r, 5000));\n this.runCommand(`docker compose -f \"${this.composeFile}\" up -d`, {\n EMULATOR_SNAPSHOT_NAME: 'quickboot',\n });\n }\n\n if (androidCont) {\n this.log('Rehydrating Android network connection...', 'info');\n try {\n execSync(`docker exec \"${androidCont}\" adb shell cmd connectivity airplane-mode enable`, {\n stdio: 'ignore',\n });\n await new Promise((r) => setTimeout(r, 2000));\n execSync(\n `docker exec \"${androidCont}\" adb shell cmd connectivity airplane-mode disable`,\n { stdio: 'ignore' }\n );\n await new Promise((r) => setTimeout(r, 3000));\n } catch (e) {\n this.log(`Network rehydration warning: ${e}`, 'warn');\n }\n }\n\n this.log('Waiting for Daemon Connection...');\n if (agentCont) await this.waitForLog(agentCont, 'Daemon listening on TCP', 180000);\n } else {\n // === COLD START ===\n this.log('No baseline found. Performing FIRST RUN SETUP (Cold Boot)...', 'warn');\n this.log('This will take ~60-90 seconds, but only once.', 'warn');\n\n const success = this.runCommand(`docker compose -f \"${this.composeFile}\" up -d`, {\n EMULATOR_SNAPSHOT_NAME: '',\n });\n\n if (!success) throw new Error('Startup failed during docker compose up.');\n\n let androidCont = this.getContainerId('android-service');\n const agentCont = this.getContainerId('agent-service');\n\n if (!androidCont) throw new Error('Error: Android container not found.');\n\n // Verify Port Mapping\n if (agentCont && !this.isPortMapped(agentCont, 3000)) {\n this.log('Port 3000 (Host 32001) is not mapped! Container config is stale.', 'warn');\n this.log('Forcing full restart to apply network settings...', 'info');\n this.runCommand(`docker compose -f \"${this.composeFile}\" down -v --remove-orphans`);\n await new Promise((r) => setTimeout(r, 5000));\n this.runCommand(`docker compose -f \"${this.composeFile}\" up -d`, {\n EMULATOR_SNAPSHOT_NAME: '',\n });\n androidCont = this.getContainerId('android-service') || androidCont;\n }\n\n this.log('Waiting for Android OS to boot (this takes a moment)...', 'info');\n await this.waitForLog(androidCont, 'Emulator boot complete');\n\n this.log('Waiting for Browser Installation...', 'info');\n await this.waitForLog(androidCont, 'APK installation complete');\n\n this.log('Waiting for CDP Bridge...', 'info');\n await this.waitForLog(androidCont, 'CDP Bridge ready');\n\n this.log('Waiting for Agent Daemon Connection...');\n if (agentCont) await this.waitForLog(agentCont, 'Daemon listening on TCP');\n\n // Save Snapshot\n this.log('Saving emulator state (quickboot)...', 'info');\n const saved = this.runCommand(\n `docker exec \"${androidCont}\" adb emu avd snapshot save quickboot`\n );\n if (saved) {\n this.log('Snapshot saved to host volume.', 'success');\n this.log('Setup Complete! Future runs will launch instantly.', 'success');\n } else {\n throw new Error('Failed to save snapshot inside emulator.');\n }\n }\n }\n\n public async stop(): Promise<void> {\n this.log('Stopping environment...', 'info');\n this.runCommand(`docker compose -f \"${this.composeFile}\" down -v --remove-orphans`);\n this.log('Environment cleaned and stopped.', 'success');\n }\n\n public async reset(): Promise<void> {\n this.log('Performing Fast Browser Reset...', 'info');\n const androidCont = this.getContainerId('android-service');\n if (!androidCont) {\n this.log('Android container not running.', 'error');\n return;\n }\n\n this.log('Initiating fast reset (userspace reboot)...', 'info');\n try {\n execSync(`docker exec \"${androidCont}\" adb shell reboot userspace`, { stdio: 'ignore' });\n } catch {\n // Ignored\n }\n\n this.log('Waiting for device to come online...', 'info');\n const start = Date.now();\n let online = false;\n\n while (Date.now() - start < 30000) {\n try {\n const state = execSync(`docker exec \"${androidCont}\" adb get-state`, {\n encoding: 'utf-8',\n }).trim();\n if (state === 'device') {\n execSync(`docker exec \"${androidCont}\" adb shell echo ok`, { stdio: 'ignore' });\n online = true;\n break;\n }\n } catch {\n // Still offline\n }\n await new Promise((r) => setTimeout(r, 1000));\n }\n\n if (!online) throw new Error('Timeout waiting for device after reboot');\n this.log('Device online', 'success');\n\n this.log('Waiting for browser CDP...', 'info');\n const cdpStart = Date.now();\n let cdpReady = false;\n\n while (Date.now() - cdpStart < 30000) {\n try {\n execSync(\n `docker exec \"${androidCont}\" curl -s --connect-timeout 2 http://localhost:9224/json/version`,\n { stdio: 'ignore' }\n );\n cdpReady = true;\n break;\n } catch {\n if (Date.now() - cdpStart > 15000) {\n try {\n execSync(\n `docker exec \"${androidCont}\" adb shell am start -n com.wootzapp.web/com.aspect.chromium.ChromiumMain -a android.intent.action.VIEW -d 'about:blank'`,\n { stdio: 'ignore' }\n );\n } catch {}\n }\n }\n await new Promise((r) => setTimeout(r, 1000));\n }\n\n if (!cdpReady) throw new Error('Timeout waiting for CDP');\n this.log('Fast reset complete!', 'success');\n }\n\n private waitForLog(container: string, pattern: string, timeoutMs = 120000): Promise<void> {\n return new Promise((resolve, reject) => {\n const start = Date.now();\n const tail = spawn('docker', ['logs', '-f', container]);\n\n const timer = setTimeout(() => {\n tail.kill();\n reject(new Error(`Timeout waiting for log pattern \"${pattern}\" in container ${container}`));\n }, timeoutMs);\n\n tail.stdout.on('data', (data) => {\n if (data.toString().includes(pattern)) {\n clearTimeout(timer);\n tail.kill();\n resolve();\n }\n });\n\n tail.stderr.on('data', (data) => {\n if (data.toString().includes(pattern)) {\n clearTimeout(timer);\n tail.kill();\n resolve();\n }\n });\n\n tail.on('error', (err) => {\n clearTimeout(timer);\n reject(err);\n });\n });\n }\n}\n","#!/usr/bin/env node\n\n/**\n * WootzApp Agent Browser CLI\n * \n * Provides terminal-based control over the Android Agent environment.\n * Usage:\n * agent-browser start - Initialize environment (Warm/Cold boot)\n * agent-browser stop - Stop environment\n * agent-browser reset - Fast browser reset (15s)\n * agent-browser open <url> - Open a URL in the browser\n */\n\nimport { WootzAgent } from './index.js';\n\nconst args = process.argv.slice(2);\n// Find the first argument that doesn't start with '-' to be the command\nconst command = args.find(arg => !arg.startsWith('-'));\n\nif (!command || command === 'help') {\n console.log(`\nWootzApp Agent Browser CLI\n\nUsage:\n agent-browser start Initialize and start the environment\n agent-browser stop Stop the environment\n agent-browser reset Fast reset the browser state\n agent-browser <cmd> Run an agent command (e.g. open https://google.com)\n\nOptions:\n --dist Use pre-built images from Docker Hub (default)\n --local Build images locally from source\n`);\n process.exit(0);\n}\n\n// Check for mode flags\nconst isLocal = args.includes('--local');\n// Filter out the --local/--dist flags before passing to command if necessary, \n// but currently our command() method handles raw args.\nconst filteredArgs = args.filter(arg => arg !== '--local' && arg !== '--dist');\n\nconst agent = new WootzAgent({ dist: !isLocal });\n\nasync function main() {\n try {\n switch (command) {\n case 'start':\n await agent.start();\n break;\n case 'stop':\n await agent.stop();\n break;\n case 'reset':\n await agent.reset();\n break;\n default:\n // Pass through arbitrary commands to the agent daemon\n // e.g. \"agent-browser open https://google.com\"\n const result = await agent.command(command!, ...filteredArgs.slice(1));\n console.log(result);\n break;\n }\n } catch (error: any) {\n console.error(`\\n❌ Error: ${error.message || error}`);\n process.exit(1);\n }\n}\n\nmain();\n"],"mappings":"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","names":["pino","path","args","command"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/orchestrator.ts","../src/cli.ts"],"sourcesContent":["import * as net from 'net';\nimport { randomUUID } from 'crypto';\nimport { Orchestrator } from './orchestrator.js';\nimport { z } from 'zod';\nimport pino from 'pino';\n\nconst DAEMON_PORT = 32001;\n\n// --- Custom Errors ---\nexport class WootzConnectionError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'WootzConnectionError';\n }\n}\n\nexport class WootzTimeoutError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'WootzTimeoutError';\n }\n}\n\nexport class WootzValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'WootzValidationError';\n }\n}\n\n// --- Schema Validation ---\nconst AgentOptionsSchema = z.object({\n dist: z.boolean().optional().default(true),\n logLevel: z.enum(['debug', 'info', 'warn', 'error', 'silent']).optional().default('info'),\n}).passthrough();\n\n/**\n * Options for initializing the WootzAgent.\n */\nexport type AgentOptions = z.input<typeof AgentOptionsSchema>;\n\n/**\n * Main entry point for interacting with the Agent Browser environment.\n */\nexport class WootzAgent {\n private options: AgentOptions;\n private orchestrator: Orchestrator;\n public logger: pino.Logger;\n\n /**\n * Creates a new instance of the WootzAgent.\n * @param options Configuration options.\n * @throws {WootzValidationError} If the provided options do not match the expected schema.\n */\n constructor(options: AgentOptions = {}) {\n const parsedOptions = AgentOptionsSchema.safeParse(options);\n if (!parsedOptions.success) {\n throw new WootzValidationError(`Invalid agent options: ${parsedOptions.error.message}`);\n }\n \n this.options = parsedOptions.data;\n \n this.logger = pino({\n level: this.options.logLevel,\n transport: this.options.logLevel !== 'silent' ? {\n target: 'pino-pretty',\n options: {\n colorize: true,\n translateTime: 'HH:MM:ss Z',\n ignore: 'pid,hostname',\n },\n } : undefined,\n });\n\n this.orchestrator = new Orchestrator(this.options.dist!, this.logger);\n }\n\n // --- Lifecycle Management (Infrastructure) ---\n\n /**\n * Starts the underlying orchestrator and waits for the browser daemon to be ready.\n * @throws {WootzTimeoutError} If the daemon fails to become available within the timeout.\n */\n async start(): Promise<void> {\n await this.orchestrator.start();\n await this.waitForDaemon();\n }\n\n /**\n * Polls the daemon port until it accepts connections.\n * @param timeoutMs The maximum amount of time (in ms) to wait for the daemon.\n */\n private async waitForDaemon(timeoutMs = 180000): Promise<void> {\n const start = Date.now();\n while (Date.now() - start < timeoutMs) {\n try {\n await this.sendCommand({ action: 'tab_list' }); // Health check\n return; // Success\n } catch {\n await new Promise((r) => setTimeout(r, 1000));\n }\n }\n throw new WootzTimeoutError(\n `Timed out waiting for Agent Daemon on port ${DAEMON_PORT} after ${timeoutMs / 1000}s`\n );\n }\n\n /**\n * Stops the orchestrator and cleans up resources.\n */\n async stop(): Promise<void> {\n await this.orchestrator.stop();\n }\n\n /**\n * Resets the environment completely.\n */\n async reset(): Promise<void> {\n await this.orchestrator.reset();\n }\n\n // --- Core Browser Actions (Direct Daemon) ---\n\n /**\n * Navigates the current tab to a specified URL.\n * @param url The URL to navigate to.\n * @param waitUntil The load state to wait for ('load', 'domcontentloaded', 'networkidle').\n */\n async navigate(\n url: string,\n waitUntil: 'load' | 'domcontentloaded' | 'networkidle' = 'load'\n ): Promise<string> {\n return await this.sendCommand({ action: 'navigate', url, waitUntil });\n }\n\n /**\n * Clicks on an element matching the given selector.\n * @param selector The CSS or semantic selector of the element to click.\n */\n async click(selector: string): Promise<string> {\n return await this.sendCommand({ action: 'click', selector });\n }\n\n /**\n * Double-clicks on an element matching the given selector.\n * @param selector The CSS or semantic selector.\n */\n async doubleClick(selector: string): Promise<string> {\n return await this.sendCommand({ action: 'dblclick', selector });\n }\n\n /**\n * Types text into a form field character by character.\n * @param selector The CSS or semantic selector of the input field.\n * @param text The text to type.\n * @param delay Delay between keystrokes in milliseconds.\n */\n async type(selector: string, text: string, delay?: number): Promise<string> {\n return await this.sendCommand({ action: 'type', selector, text, delay });\n }\n\n /**\n * Fills an input field directly with a value (faster than type).\n * @param selector The CSS or semantic selector of the input field.\n * @param value The value to fill.\n */\n async fill(selector: string, value: string): Promise<string> {\n return await this.sendCommand({ action: 'fill', selector, value });\n }\n\n async check(selector: string): Promise<string> {\n return await this.sendCommand({ action: 'check', selector });\n }\n\n async uncheck(selector: string): Promise<string> {\n return await this.sendCommand({ action: 'uncheck', selector });\n }\n\n async hover(selector: string): Promise<string> {\n return await this.sendCommand({ action: 'hover', selector });\n }\n\n async focus(selector: string): Promise<string> {\n return await this.sendCommand({ action: 'focus', selector });\n }\n\n async press(key: string, selector?: string): Promise<string> {\n return await this.sendCommand({ action: 'press', key, selector });\n }\n\n async selectOption(selector: string, value: string | string[]): Promise<string> {\n return await this.sendCommand({ action: 'select', selector, values: value });\n }\n\n // --- Introspection & State ---\n\n /**\n * Captures the full DOM/AXTree snapshot of the current page.\n * @returns A string representation of the interactive accessibility tree.\n */\n async snapshot(): Promise<string> {\n const result = await this.sendCommand({ action: 'snapshot' }, true);\n return result.snapshot || '';\n }\n\n async innerText(selector: string): Promise<string> {\n const res = await this.sendCommand({ action: 'innertext', selector }, true);\n return res.text;\n }\n\n async innerHTML(selector: string): Promise<string> {\n const res = await this.sendCommand({ action: 'innerhtml', selector }, true);\n return res.html;\n }\n\n async getAttribute(selector: string, attribute: string): Promise<string> {\n const res = await this.sendCommand({ action: 'getattribute', selector, attribute }, true);\n return res.value;\n }\n\n async inputValue(selector: string): Promise<string> {\n const res = await this.sendCommand({ action: 'inputvalue', selector }, true);\n return res.value;\n }\n\n async isVisible(selector: string): Promise<boolean> {\n const res = await this.sendCommand({ action: 'isvisible', selector }, true);\n return res.visible;\n }\n\n async isEnabled(selector: string): Promise<boolean> {\n const res = await this.sendCommand({ action: 'isenabled', selector }, true);\n return res.enabled;\n }\n\n async isChecked(selector: string): Promise<boolean> {\n const res = await this.sendCommand({ action: 'ischecked', selector }, true);\n return res.checked;\n }\n\n // --- Waiting & Navigation ---\n\n async waitForSelector(\n selector: string,\n state: 'attached' | 'detached' | 'visible' | 'hidden' = 'visible',\n timeout?: number\n ): Promise<string> {\n return await this.sendCommand({ action: 'wait', selector, state, timeout });\n }\n\n async waitForTimeout(ms: number): Promise<string> {\n return await this.sendCommand({ action: 'wait', timeout: ms });\n }\n\n async waitForLoadState(\n state: 'load' | 'domcontentloaded' | 'networkidle' = 'load'\n ): Promise<string> {\n return await this.sendCommand({ action: 'waitforloadstate', state });\n }\n\n async reload(): Promise<string> {\n return await this.sendCommand({ action: 'reload' });\n }\n\n async goBack(): Promise<string> {\n return await this.sendCommand({ action: 'back' });\n }\n\n async goForward(): Promise<string> {\n return await this.sendCommand({ action: 'forward' });\n }\n\n // --- Semantic Locators ---\n\n async getByRole(role: string, name?: string, _exact: boolean = false): Promise<string> {\n throw new Error(\n 'Locator builders (getByRole) are not fully supported in stateless mode yet. Use standard selectors.'\n );\n }\n\n // --- Utilities ---\n\n /**\n * Captures a screenshot of the current page.\n * @param path Optional file path to save the screenshot.\n */\n async screenshot(path?: string): Promise<string> {\n const res = await this.sendCommand({ action: 'screenshot', path }, true);\n return res.path;\n }\n\n async scroll(x: number, y: number): Promise<string> {\n return await this.sendCommand({ action: 'scroll', x, y });\n }\n\n async evaluate(script: string): Promise<any> {\n const res = await this.sendCommand({ action: 'evaluate', script }, true);\n return res.result;\n }\n\n // --- Tab Management ---\n\n async newTab(url?: string): Promise<string> {\n return await this.sendCommand({ action: 'tab_new', url });\n }\n\n async switchTab(index: number): Promise<string> {\n return await this.sendCommand({ action: 'tab_switch', index });\n }\n\n async closeTab(index?: number): Promise<string> {\n return await this.sendCommand({ action: 'tab_close', index });\n }\n\n async listTabs(): Promise<any[]> {\n const res = await this.sendCommand({ action: 'tab_list' }, true);\n return res.tabs;\n }\n\n // --- Generic Execution ---\n\n async command(action: string, ...args: string[]): Promise<string> {\n const cmd: any = { action };\n\n if (action === 'open' || action === 'navigate') {\n cmd.action = 'navigate';\n cmd.url = args[0];\n } else if (action === 'click') {\n cmd.selector = args[0];\n } else if (action === 'type') {\n cmd.selector = args[0];\n cmd.text = args[1];\n } else if (action === 'press') {\n cmd.key = args[0];\n } else if (action === 'scroll') {\n cmd.x = parseInt(args[0] || '0');\n cmd.y = parseInt(args[1] || '0');\n } else if (action === 'wait') {\n if (/^\\d+$/.test(args[0])) cmd.timeout = parseInt(args[0]);\n else cmd.selector = args[0];\n } else {\n if (args[0]) cmd.selector = args[0];\n if (args[1]) cmd.text = args[1] || args[1]; // value/text\n }\n\n const res = await this.sendCommand(cmd, true);\n\n if (typeof res === 'object') {\n if (res.text) return res.text;\n if (res.url) return res.url;\n if (res.snapshot) return res.snapshot;\n return JSON.stringify(res);\n }\n return String(res);\n }\n\n private sendCommand(command: any, returnData = false): Promise<any> {\n return new Promise((resolve, reject) => {\n if (!command.id) command.id = randomUUID();\n\n const client = new net.Socket();\n\n client.connect(DAEMON_PORT, '127.0.0.1', () => {\n client.write(JSON.stringify(command) + '\\n');\n });\n\n let responseBuffer = '';\n\n client.on('data', (data) => {\n responseBuffer += data.toString();\n if (responseBuffer.includes('\\n')) {\n client.end();\n }\n });\n\n client.on('end', () => {\n try {\n const response = JSON.parse(responseBuffer.trim());\n if (response.success) {\n resolve(returnData ? response.data : 'OK');\n } else {\n reject(new Error(response.error || 'Unknown error'));\n }\n } catch {\n reject(new Error(`Invalid response from daemon: ${responseBuffer}`));\n }\n });\n\n client.on('error', (err) => {\n reject(new WootzConnectionError(`Failed to connect to agent daemon (is it running?): ${err.message}`));\n });\n });\n }\n}\n\nexport default WootzAgent;","import { spawn, execSync } from 'child_process';\nimport path from 'path';\nimport 'fs';\nimport { fileURLToPath } from 'url';\nimport pino from 'pino';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\nconst PROJECT_ROOT = path.resolve(__dirname, '..');\n\nexport class Orchestrator {\n private composeFile: string;\n private logger: pino.Logger;\n\n constructor(distMode: boolean, logger?: pino.Logger) {\n this.composeFile = path.join(\n PROJECT_ROOT,\n distMode ? 'docker-compose.sdk.yml' : 'docker-compose.prod.yml'\n );\n this.logger = logger || pino();\n }\n\n private log(msg: string, level: 'info' | 'success' | 'warn' | 'error' = 'info') {\n switch (level) {\n case 'success':\n this.logger.info({ sdk: true }, msg);\n break;\n case 'warn':\n this.logger.warn({ sdk: true }, msg);\n break;\n case 'error':\n this.logger.error({ sdk: true }, msg);\n break;\n default:\n this.logger.info({ sdk: true }, msg);\n }\n }\n\n private runCommand(cmd: string, env: Record<string, string> = {}): boolean {\n try {\n execSync(cmd, {\n stdio: 'inherit',\n env: { ...process.env, ...env },\n });\n return true;\n } catch {\n return false;\n }\n }\n\n private getContainerId(serviceName: string): string | null {\n try {\n const output = execSync(`docker compose -f \"${this.composeFile}\" ps -q ${serviceName}`, {\n encoding: 'utf-8',\n });\n return output.trim() || null;\n } catch {\n return null;\n }\n }\n\n private isPortMapped(containerId: string, port: number): boolean {\n try {\n const output = execSync(`docker port \"${containerId}\" ${port}`, { encoding: 'utf-8' });\n return output.includes('0.0.0.0:') || output.includes(':::');\n } catch {\n return false;\n }\n }\n\n private async pullImagesWithRetry(): Promise<void> {\n if (!this.composeFile.endsWith('docker-compose.sdk.yml')) return;\n\n this.log('Please wait while we get things ready...', 'info');\n const maxRetries = 10;\n\n for (let count = 0; count < maxRetries; count++) {\n if (this.runCommand(`docker compose -f \"${this.composeFile}\" pull`)) {\n return;\n }\n this.log(\n `Download failed/interrupted. Retrying (${count + 1}/${maxRetries}) in 10s...`,\n 'warn'\n );\n await new Promise((r) => setTimeout(r, 10000));\n }\n\n this.log(\n `Failed to download images after ${maxRetries} attempts. Check internet connection.`,\n 'error'\n );\n process.exit(1);\n }\n\n private async hasSnapshot(): Promise<boolean> {\n try {\n // 1. Check if volume exists\n execSync(`docker volume inspect agent-snapshots`, { stdio: 'ignore' });\n\n // 2. Check if volume contains the 'quickboot' directory\n // We use a tiny helper container to look inside the managed volume\n const output = execSync(`docker run --rm -v agent-snapshots:/data busybox ls /data`, {\n encoding: 'utf-8',\n });\n return output.includes('quickboot');\n } catch {\n return false;\n }\n }\n\n public async start(): Promise<void> {\n this.log(`Initializing Agent Environment...`, 'info');\n\n await this.pullImagesWithRetry();\n\n this.log('Cleaning up previous container state...', 'info');\n this.runCommand(`docker compose -f \"${this.composeFile}\" down -v --remove-orphans`);\n\n const hasSnapshot = await this.hasSnapshot();\n\n if (hasSnapshot) {\n // === WARM START ===\n this.log('Found cached baseline snapshot. Performing HYPER-SPEED WARM BOOT...', 'success');\n\n const success = this.runCommand(`docker compose -f \"${this.composeFile}\" up -d`, {\n EMULATOR_SNAPSHOT_NAME: 'quickboot',\n });\n\n if (!success) throw new Error('Startup failed during docker compose up.');\n\n const agentCont = this.getContainerId('agent-service');\n const androidCont = this.getContainerId('android-service');\n\n // Verify Port Mapping\n if (agentCont && !this.isPortMapped(agentCont, 3000)) {\n this.log('Port 3000 (Host 32001) is not mapped! Container config is stale.', 'warn');\n this.log('Forcing full restart to apply network settings...', 'info');\n this.runCommand(`docker compose -f \"${this.composeFile}\" down -v --remove-orphans`);\n await new Promise((r) => setTimeout(r, 5000));\n this.runCommand(`docker compose -f \"${this.composeFile}\" up -d`, {\n EMULATOR_SNAPSHOT_NAME: 'quickboot',\n });\n }\n\n if (androidCont) {\n this.log('Rehydrating Android network connection...', 'info');\n try {\n execSync(`docker exec \"${androidCont}\" adb shell cmd connectivity airplane-mode enable`, {\n stdio: 'ignore',\n });\n await new Promise((r) => setTimeout(r, 2000));\n execSync(\n `docker exec \"${androidCont}\" adb shell cmd connectivity airplane-mode disable`,\n { stdio: 'ignore' }\n );\n await new Promise((r) => setTimeout(r, 3000));\n } catch {\n this.log(`Network rehydration warning: ${e}`, 'warn');\n }\n }\n\n this.log('Waiting for Daemon Connection...');\n if (agentCont) await this.waitForLog(agentCont, 'Daemon listening on TCP', 180000);\n } else {\n // === COLD START ===\n this.log('No baseline found. Performing FIRST RUN SETUP (Cold Boot)...', 'warn');\n this.log('This will take ~60-90 seconds, but only once.', 'warn');\n\n const success = this.runCommand(`docker compose -f \"${this.composeFile}\" up -d`, {\n EMULATOR_SNAPSHOT_NAME: '',\n });\n\n if (!success) throw new Error('Startup failed during docker compose up.');\n\n let androidCont = this.getContainerId('android-service');\n const agentCont = this.getContainerId('agent-service');\n\n if (!androidCont) throw new Error('Error: Android container not found.');\n\n // Verify Port Mapping\n if (agentCont && !this.isPortMapped(agentCont, 3000)) {\n this.log('Port 3000 (Host 32001) is not mapped! Container config is stale.', 'warn');\n this.log('Forcing full restart to apply network settings...', 'info');\n this.runCommand(`docker compose -f \"${this.composeFile}\" down -v --remove-orphans`);\n await new Promise((r) => setTimeout(r, 5000));\n this.runCommand(`docker compose -f \"${this.composeFile}\" up -d`, {\n EMULATOR_SNAPSHOT_NAME: '',\n });\n androidCont = this.getContainerId('android-service') || androidCont;\n }\n\n this.log('Waiting for Android OS to boot (this takes a moment)...', 'info');\n await this.waitForLog(androidCont, 'Emulator boot complete');\n\n this.log('Waiting for Browser Installation...', 'info');\n await this.waitForLog(androidCont, 'APK installation complete');\n\n this.log('Waiting for CDP Bridge...', 'info');\n await this.waitForLog(androidCont, 'CDP Bridge ready');\n\n this.log('Waiting for Agent Daemon Connection...');\n if (agentCont) await this.waitForLog(agentCont, 'Daemon listening on TCP');\n\n // Save Snapshot\n this.log('Saving emulator state (quickboot)...', 'info');\n const saved = this.runCommand(\n `docker exec \"${androidCont}\" adb emu avd snapshot save quickboot`\n );\n if (saved) {\n this.log('Snapshot saved to host volume.', 'success');\n this.log('Setup Complete! Future runs will launch instantly.', 'success');\n } else {\n throw new Error('Failed to save snapshot inside emulator.');\n }\n }\n }\n\n public async stop(): Promise<void> {\n this.log('Stopping environment...', 'info');\n this.runCommand(`docker compose -f \"${this.composeFile}\" down -v --remove-orphans`);\n this.log('Environment cleaned and stopped.', 'success');\n }\n\n public async reset(): Promise<void> {\n this.log('Performing Fast Browser Reset...', 'info');\n const androidCont = this.getContainerId('android-service');\n if (!androidCont) {\n this.log('Android container not running.', 'error');\n return;\n }\n\n this.log('Initiating fast reset (userspace reboot)...', 'info');\n try {\n execSync(`docker exec \"${androidCont}\" adb shell reboot userspace`, { stdio: 'ignore' });\n } catch {\n // Ignored\n }\n\n this.log('Waiting for device to come online...', 'info');\n \n let online = false;\n\n while (Date.now() - start < 30000) {\n try {\n const state = execSync(`docker exec \"${androidCont}\" adb get-state`, {\n encoding: 'utf-8',\n }).trim();\n if (state === 'device') {\n execSync(`docker exec \"${androidCont}\" adb shell echo ok`, { stdio: 'ignore' });\n online = true;\n break;\n }\n } catch {\n // Still offline\n }\n await new Promise((r) => setTimeout(r, 1000));\n }\n\n if (!online) throw new Error('Timeout waiting for device after reboot');\n this.log('Device online', 'success');\n\n this.log('Waiting for browser CDP...', 'info');\n const cdpStart = Date.now();\n let cdpReady = false;\n\n while (Date.now() - cdpStart < 30000) {\n try {\n execSync(\n `docker exec \"${androidCont}\" curl -s --connect-timeout 2 http://localhost:9224/json/version`,\n { stdio: 'ignore' }\n );\n cdpReady = true;\n break;\n } catch {\n if (Date.now() - cdpStart > 15000) {\n try {\n execSync(\n `docker exec \"${androidCont}\" adb shell am start -n com.wootzapp.web/com.aspect.chromium.ChromiumMain -a android.intent.action.VIEW -d 'about:blank'`,\n { stdio: 'ignore' }\n );\n } catch {}\n }\n }\n await new Promise((r) => setTimeout(r, 1000));\n }\n\n if (!cdpReady) throw new Error('Timeout waiting for CDP');\n this.log('Fast reset complete!', 'success');\n }\n\n private waitForLog(container: string, pattern: string, timeoutMs = 120000): Promise<void> {\n return new Promise((resolve, reject) => {\n \n const tail = spawn('docker', ['logs', '-f', container]);\n\n const timer = setTimeout(() => {\n tail.kill();\n reject(new Error(`Timeout waiting for log pattern \"${pattern}\" in container ${container}`));\n }, timeoutMs);\n\n tail.stdout.on('data', (data) => {\n if (data.toString().includes(pattern)) {\n clearTimeout(timer);\n tail.kill();\n resolve();\n }\n });\n\n tail.stderr.on('data', (data) => {\n if (data.toString().includes(pattern)) {\n clearTimeout(timer);\n tail.kill();\n resolve();\n }\n });\n\n tail.on('error', (err) => {\n clearTimeout(timer);\n reject(err);\n });\n });\n }\n}\n","#!/usr/bin/env node\n\n/**\n * WootzApp Agent Browser CLI\n * \n * Provides terminal-based control over the Android Agent environment.\n * Usage:\n * agent-browser start - Initialize environment (Warm/Cold boot)\n * agent-browser stop - Stop environment\n * agent-browser reset - Fast browser reset (15s)\n * agent-browser open <url> - Open a URL in the browser\n */\n\nimport { WootzAgent } from './index.js';\n\nconst args = process.argv.slice(2);\n// Find the first argument that doesn't start with '-' to be the command\nconst command = args.find(arg => !arg.startsWith('-'));\n\nif (!command || command === 'help') {\n console.log(`\nWootzApp Agent Browser CLI\n\nUsage:\n agent-browser start Initialize and start the environment\n agent-browser stop Stop the environment\n agent-browser reset Fast reset the browser state\n agent-browser <cmd> Run an agent command (e.g. open https://google.com)\n\nOptions:\n --dist Use pre-built images from Docker Hub (default)\n --local Build images locally from source\n`);\n process.exit(0);\n}\n\n// Check for mode flags\nconst isLocal = args.includes('--local');\n// Filter out the --local/--dist flags before passing to command if necessary, \n// but currently our command() method handles raw args.\nconst filteredArgs = args.filter(arg => arg !== '--local' && arg !== '--dist');\n\nconst agent = new WootzAgent({ dist: !isLocal });\n\nasync function main() {\n try {\n switch (command) {\n case 'start':\n await agent.start();\n break;\n case 'stop':\n await agent.stop();\n break;\n case 'reset':\n await agent.reset();\n break;\n default:\n // Pass through arbitrary commands to the agent daemon\n // e.g. \"agent-browser open https://google.com\"\n const result = await agent.command(command!, ...filteredArgs.slice(1));\n console.log(result);\n break;\n }\n } catch (error: any) {\n console.error(`\\n❌ Error: ${error.message || error}`);\n process.exit(1);\n }\n}\n\nmain();\n"],"mappings":"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","names":["pino","start","path","args","command"]}