@elizaos/plugin-computeruse 2.0.3-beta.2 → 2.0.3-beta.4
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/actions/clipboard.d.ts +22 -0
- package/dist/actions/clipboard.d.ts.map +1 -0
- package/dist/actions/helpers.d.ts +33 -0
- package/dist/actions/helpers.d.ts.map +1 -0
- package/dist/actions/progress.d.ts +26 -0
- package/dist/actions/progress.d.ts.map +1 -0
- package/dist/actions/use-computer-agent.d.ts +113 -0
- package/dist/actions/use-computer-agent.d.ts.map +1 -0
- package/dist/actions/use-computer.d.ts +3 -0
- package/dist/actions/use-computer.d.ts.map +1 -0
- package/dist/actions/window-handlers.d.ts +11 -0
- package/dist/actions/window-handlers.d.ts.map +1 -0
- package/dist/actions/window.d.ts +11 -0
- package/dist/actions/window.d.ts.map +1 -0
- package/dist/actor/actor.d.ts +84 -0
- package/dist/actor/actor.d.ts.map +1 -0
- package/dist/actor/agent-callbacks.d.ts +128 -0
- package/dist/actor/agent-callbacks.d.ts.map +1 -0
- package/dist/actor/agent-loop.d.ts +134 -0
- package/dist/actor/agent-loop.d.ts.map +1 -0
- package/dist/actor/aosp-input-actor.d.ts +87 -0
- package/dist/actor/aosp-input-actor.d.ts.map +1 -0
- package/dist/actor/brain.d.ts +195 -0
- package/dist/actor/brain.d.ts.map +1 -0
- package/dist/actor/cascade.d.ts +92 -0
- package/dist/actor/cascade.d.ts.map +1 -0
- package/dist/actor/computer-interface.d.ts +276 -0
- package/dist/actor/computer-interface.d.ts.map +1 -0
- package/dist/actor/dispatch.d.ts +24 -0
- package/dist/actor/dispatch.d.ts.map +1 -0
- package/dist/actor/index.d.ts +12 -0
- package/dist/actor/index.d.ts.map +1 -0
- package/dist/actor/types.d.ts +94 -0
- package/dist/actor/types.d.ts.map +1 -0
- package/dist/approval-manager.d.ts +29 -0
- package/dist/approval-manager.d.ts.map +1 -0
- package/dist/index.d.ts +46 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13649 -0
- package/dist/index.js.map +68 -0
- package/dist/mcp/index.d.ts +8 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/server.d.ts +42 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/tools.d.ts +53 -0
- package/dist/mcp/tools.d.ts.map +1 -0
- package/dist/mobile/android-bridge.d.ts +263 -0
- package/dist/mobile/android-bridge.d.ts.map +1 -0
- package/dist/mobile/android-scene.d.ts +52 -0
- package/dist/mobile/android-scene.d.ts.map +1 -0
- package/dist/mobile/android-trajectory.d.ts +66 -0
- package/dist/mobile/android-trajectory.d.ts.map +1 -0
- package/dist/mobile/index.d.ts +19 -0
- package/dist/mobile/index.d.ts.map +1 -0
- package/dist/mobile/ios-app-intent-registry.d.ts +20 -0
- package/dist/mobile/ios-app-intent-registry.d.ts.map +1 -0
- package/dist/mobile/ios-bridge.d.ts +359 -0
- package/dist/mobile/ios-bridge.d.ts.map +1 -0
- package/dist/mobile/ios-computer-interface.d.ts +160 -0
- package/dist/mobile/ios-computer-interface.d.ts.map +1 -0
- package/dist/mobile/mobile-computer-interface.d.ts +142 -0
- package/dist/mobile/mobile-computer-interface.d.ts.map +1 -0
- package/dist/mobile/mobile-screen-capture.d.ts +64 -0
- package/dist/mobile/mobile-screen-capture.d.ts.map +1 -0
- package/dist/mobile/ocr-provider.d.ts +187 -0
- package/dist/mobile/ocr-provider.d.ts.map +1 -0
- package/dist/mobile/ocr-provider.js +111 -0
- package/dist/mobile/ocr-provider.js.map +10 -0
- package/dist/osworld/action-converter.d.ts +38 -0
- package/dist/osworld/action-converter.d.ts.map +1 -0
- package/dist/osworld/adapter.d.ts +79 -0
- package/dist/osworld/adapter.d.ts.map +1 -0
- package/dist/osworld/types.d.ts +69 -0
- package/dist/osworld/types.d.ts.map +1 -0
- package/dist/parity/index.d.ts +9 -0
- package/dist/parity/index.d.ts.map +1 -0
- package/dist/parity/parity-matrix.d.ts +82 -0
- package/dist/parity/parity-matrix.d.ts.map +1 -0
- package/dist/parity/screenspot.d.ts +56 -0
- package/dist/parity/screenspot.d.ts.map +1 -0
- package/dist/platform/a11y.d.ts +64 -0
- package/dist/platform/a11y.d.ts.map +1 -0
- package/dist/platform/browser.d.ts +61 -0
- package/dist/platform/browser.d.ts.map +1 -0
- package/dist/platform/capabilities.d.ts +33 -0
- package/dist/platform/capabilities.d.ts.map +1 -0
- package/dist/platform/capture.d.ts +65 -0
- package/dist/platform/capture.d.ts.map +1 -0
- package/dist/platform/clipboard.d.ts +24 -0
- package/dist/platform/clipboard.d.ts.map +1 -0
- package/dist/platform/coords.d.ts +73 -0
- package/dist/platform/coords.d.ts.map +1 -0
- package/dist/platform/desktop.d.ts +56 -0
- package/dist/platform/desktop.d.ts.map +1 -0
- package/dist/platform/displays.d.ts +97 -0
- package/dist/platform/displays.d.ts.map +1 -0
- package/dist/platform/driver.d.ts +49 -0
- package/dist/platform/driver.d.ts.map +1 -0
- package/dist/platform/file-ops.d.ts +27 -0
- package/dist/platform/file-ops.d.ts.map +1 -0
- package/dist/platform/helpers.d.ts +60 -0
- package/dist/platform/helpers.d.ts.map +1 -0
- package/dist/platform/launch.d.ts +54 -0
- package/dist/platform/launch.d.ts.map +1 -0
- package/dist/platform/normalized-coords.d.ts +46 -0
- package/dist/platform/normalized-coords.d.ts.map +1 -0
- package/dist/platform/nut-driver.d.ts +86 -0
- package/dist/platform/nut-driver.d.ts.map +1 -0
- package/dist/platform/permissions.d.ts +33 -0
- package/dist/platform/permissions.d.ts.map +1 -0
- package/dist/platform/process-list.d.ts +32 -0
- package/dist/platform/process-list.d.ts.map +1 -0
- package/dist/platform/ps-host.d.ts +77 -0
- package/dist/platform/ps-host.d.ts.map +1 -0
- package/dist/platform/screenshot-errors.d.ts +54 -0
- package/dist/platform/screenshot-errors.d.ts.map +1 -0
- package/dist/platform/screenshot-quality.d.ts +11 -0
- package/dist/platform/screenshot-quality.d.ts.map +1 -0
- package/dist/platform/screenshot.d.ts +16 -0
- package/dist/platform/screenshot.d.ts.map +1 -0
- package/dist/platform/security.d.ts +20 -0
- package/dist/platform/security.d.ts.map +1 -0
- package/dist/platform/terminal.d.ts +38 -0
- package/dist/platform/terminal.d.ts.map +1 -0
- package/dist/platform/wayland-portal.d.ts +25 -0
- package/dist/platform/wayland-portal.d.ts.map +1 -0
- package/dist/platform/windows-list.d.ts +78 -0
- package/dist/platform/windows-list.d.ts.map +1 -0
- package/dist/providers/computer-state.d.ts +9 -0
- package/dist/providers/computer-state.d.ts.map +1 -0
- package/dist/providers/scene.d.ts +21 -0
- package/dist/providers/scene.d.ts.map +1 -0
- package/dist/register-routes.d.ts +2 -0
- package/dist/register-routes.d.ts.map +1 -0
- package/dist/register-routes.js +13836 -0
- package/dist/register-routes.js.map +71 -0
- package/dist/routes/computer-use-compat-routes.d.ts +29 -0
- package/dist/routes/computer-use-compat-routes.d.ts.map +1 -0
- package/dist/routes/computer-use-routes.d.ts +3 -0
- package/dist/routes/computer-use-routes.d.ts.map +1 -0
- package/dist/routes/sandbox-routes.d.ts +53 -0
- package/dist/routes/sandbox-routes.d.ts.map +1 -0
- package/dist/sandbox/docker-backend.d.ts +69 -0
- package/dist/sandbox/docker-backend.d.ts.map +1 -0
- package/dist/sandbox/index.d.ts +62 -0
- package/dist/sandbox/index.d.ts.map +1 -0
- package/dist/sandbox/qemu-backend.d.ts +48 -0
- package/dist/sandbox/qemu-backend.d.ts.map +1 -0
- package/dist/sandbox/remote-guest.d.ts +72 -0
- package/dist/sandbox/remote-guest.d.ts.map +1 -0
- package/dist/sandbox/sandbox-driver.d.ts +41 -0
- package/dist/sandbox/sandbox-driver.d.ts.map +1 -0
- package/dist/sandbox/surface-types.d.ts +17 -0
- package/dist/sandbox/surface-types.d.ts.map +1 -0
- package/dist/sandbox/types.d.ts +138 -0
- package/dist/sandbox/types.d.ts.map +1 -0
- package/dist/sandbox/wsb-backend.d.ts +48 -0
- package/dist/sandbox/wsb-backend.d.ts.map +1 -0
- package/dist/scene/a11y-provider.d.ts +83 -0
- package/dist/scene/a11y-provider.d.ts.map +1 -0
- package/dist/scene/apps.d.ts +39 -0
- package/dist/scene/apps.d.ts.map +1 -0
- package/dist/scene/dhash.d.ts +105 -0
- package/dist/scene/dhash.d.ts.map +1 -0
- package/dist/scene/ocr-adapter.d.ts +64 -0
- package/dist/scene/ocr-adapter.d.ts.map +1 -0
- package/dist/scene/scene-builder.d.ts +107 -0
- package/dist/scene/scene-builder.d.ts.map +1 -0
- package/dist/scene/scene-types.d.ts +70 -0
- package/dist/scene/scene-types.d.ts.map +1 -0
- package/dist/scene/screen-state.d.ts +105 -0
- package/dist/scene/screen-state.d.ts.map +1 -0
- package/dist/scene/serialize.d.ts +28 -0
- package/dist/scene/serialize.d.ts.map +1 -0
- package/dist/security/browser-script-policy.d.ts +9 -0
- package/dist/security/browser-script-policy.d.ts.map +1 -0
- package/dist/services/computer-use-service.d.ts +142 -0
- package/dist/services/computer-use-service.d.ts.map +1 -0
- package/dist/services/desktop-control.d.ts +35 -0
- package/dist/services/desktop-control.d.ts.map +1 -0
- package/dist/services/index.d.ts +7 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/vision-context-provider.d.ts +32 -0
- package/dist/services/vision-context-provider.d.ts.map +1 -0
- package/dist/types.d.ts +385 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +16 -5
- package/registry-entry.json +74 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/index.ts", "../src/platform/clipboard.ts", "../src/platform/helpers.ts", "../src/platform/ps-host.ts", "../src/actions/helpers.ts", "../src/actions/clipboard.ts", "../src/actions/progress.ts", "../src/actions/use-computer.ts", "../src/actions/use-computer-agent.ts", "../src/actor/agent-callbacks.ts", "../src/actor/actor.ts", "../src/actor/brain.ts", "../src/scene/dhash.ts", "../src/scene/serialize.ts", "../src/actor/cascade.ts", "../src/actor/agent-loop.ts", "../src/platform/capture.ts", "../src/platform/displays.ts", "../src/platform/permissions.ts", "../src/platform/wayland-portal.ts", "../src/platform/screenshot.ts", "../src/platform/screenshot-errors.ts", "../src/platform/desktop.ts", "../src/platform/nut-driver.ts", "../src/platform/driver.ts", "../src/actor/computer-interface.ts", "../src/actor/dispatch.ts", "../src/actions/window-handlers.ts", "../src/actions/window.ts", "../src/providers/computer-state.ts", "../src/providers/scene.ts", "../src/routes/computer-use-compat-routes.ts", "../src/services/computer-use-service.ts", "../src/approval-manager.ts", "../src/mobile/ocr-provider.ts", "../src/platform/browser.ts", "../src/security/browser-script-policy.ts", "../src/platform/screenshot-quality.ts", "../src/platform/capabilities.ts", "../src/platform/coords.ts", "../src/platform/file-ops.ts", "../src/platform/security.ts", "../src/platform/launch.ts", "../src/platform/terminal.ts", "../src/platform/windows-list.ts", "../src/scene/scene-builder.ts", "../src/scene/a11y-provider.ts", "../src/scene/apps.ts", "../src/platform/process-list.ts", "../src/scene/ocr-adapter.ts", "../src/scene/screen-state.ts", "../src/services/vision-context-provider.ts", "../src/mobile/android-bridge.ts", "../src/mobile/ios-app-intent-registry.ts", "../src/mobile/ios-bridge.ts", "../src/mobile/ios-computer-interface.ts", "../src/routes/computer-use-routes.ts", "../src/routes/sandbox-routes.ts", "../src/services/desktop-control.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"/**\n * @elizaos/plugin-computeruse\n *\n * Desktop automation plugin for elizaOS agents — screenshots, mouse/keyboard\n * control, browser CDP automation, and window management.\n *\n * File operations belong on the FILE action; shell/terminal access belongs on\n * the SHELL action. They are not exposed by this plugin.\n *\n * Deeply ported from coasty-ai/open-computer-use (Apache 2.0).\n *\n * Enable via:\n * - Config: features.computeruse: true\n * - Env: COMPUTER_USE_ENABLED=1\n *\n * Platform requirements:\n * macOS — screencapture (built-in), cliclick (brew install cliclick), AppleScript\n * Linux — xdotool (sudo apt install xdotool), ImageMagick/scrot for screenshots\n * Windows — PowerShell (built-in)\n * Browser — puppeteer-core + Chrome/Edge/Brave installed\n *\n * @module @elizaos/plugin-computeruse\n */\n\nimport type { Plugin, Route } from \"@elizaos/core\";\nimport { promoteSubactionsToActions } from \"@elizaos/core\";\nimport { clipboardAction } from \"./actions/clipboard.js\";\nimport { useComputerAction } from \"./actions/use-computer.js\";\nimport { computerUseAgentAction } from \"./actions/use-computer-agent.js\";\nimport { windowAction } from \"./actions/window.js\";\nimport { computerStateProvider } from \"./providers/computer-state.js\";\nimport { sceneProvider } from \"./providers/scene.js\";\nimport { computerUseRouteHandler } from \"./routes/computer-use-compat-routes.js\";\nimport { ComputerUseService } from \"./services/computer-use-service.js\";\nimport { VisionContextProvider } from \"./services/vision-context-provider.js\";\n\nconst computerUseRoutes: Route[] = [\n {\n type: \"GET\",\n path: \"/api/computer-use/approvals\",\n rawPath: true,\n handler: computerUseRouteHandler(),\n },\n {\n type: \"GET\",\n path: \"/api/computer-use/approvals/stream\",\n rawPath: true,\n public: true,\n name: \"computeruse-approvals-stream\",\n handler: computerUseRouteHandler(),\n },\n {\n type: \"POST\",\n path: \"/api/computer-use/approval-mode\",\n rawPath: true,\n handler: computerUseRouteHandler(),\n },\n {\n // Dynamic `:id` segment — handler decodes the id from req.url itself.\n type: \"POST\",\n path: \"/api/computer-use/approvals/:id\",\n rawPath: true,\n handler: computerUseRouteHandler(),\n },\n];\n\nexport const computerUsePlugin: Plugin = {\n name: \"@elizaos/plugin-computeruse\",\n description:\n \"Desktop automation — take screenshots, control mouse and keyboard, \" +\n \"automate web browsers via CDP, and manage desktop windows. \" +\n \"Ported from open-computer-use (Apache 2.0).\",\n\n services: [ComputerUseService, VisionContextProvider],\n\n async dispose(runtime) {\n const svc = runtime.getService<ComputerUseService>(\n ComputerUseService.serviceType,\n );\n await svc?.stop();\n },\n\n // COMPUTER_USE (canonical desktop interaction: screenshot/click/key/etc.)\n // and WINDOW (window management: list/focus/switch/arrange/move/...) stay\n // registered as distinct top-level actions — they cover different surfaces.\n // Each umbrella's subactions are promoted to virtual top-level actions\n // (e.g. COMPUTER_USE_CLICK, WINDOW_FOCUS) so the planner can pick a\n // specific verb directly from the action catalogue.\n actions: [\n ...promoteSubactionsToActions(useComputerAction),\n ...promoteSubactionsToActions(windowAction),\n // CLIPBOARD (read/write the host clipboard) — a core computer-use capability\n // (trycua/cua parity). Promoted to CLIPBOARD_READ / CLIPBOARD_WRITE.\n ...promoteSubactionsToActions(clipboardAction),\n computerUseAgentAction,\n ],\n\n providers: [computerStateProvider, sceneProvider],\n\n routes: computerUseRoutes,\n\n autoEnable: {\n envKeys: [\"COMPUTER_USE_ENABLED\"],\n },\n};\n\nexport const computerusePlugin = computerUsePlugin;\n\nexport default computerUsePlugin;\n\nexport {\n type ComputerUseAgentParams,\n type ComputerUseAgentReport,\n computerUseAgentAction,\n runComputerUseAgentLoop,\n} from \"./actions/use-computer-agent.js\";\n// WS7: Brain / Actor / Cascade / Dispatch — autonomous desktop loop.\nexport * from \"./actor/index.js\";\n// iOS computer-use surface. See `docs/IOS_CONSTRAINTS.md` for the honest scope.\nexport * from \"./mobile/index.js\";\nexport {\n listProcesses,\n type ProcessInfo,\n parsePsOutput,\n parseWindowsProcessJson,\n} from \"./platform/process-list.js\";\nexport { sceneProvider } from \"./providers/scene.js\";\nexport { handleComputerUseRoutes } from \"./routes/computer-use-routes.js\";\nexport { handleSandboxRoute } from \"./routes/sandbox-routes.js\";\nexport {\n type AccessibilityProvider,\n DarwinAccessibilityProvider,\n LinuxAccessibilityProvider,\n NullAccessibilityProvider,\n parseHyprlandClients,\n parseSwayTree,\n resolveAccessibilityProvider,\n setAccessibilityProvider,\n WindowsAccessibilityProvider,\n} from \"./scene/a11y-provider.js\";\nexport { enumerateApps, joinAppsAndWindows } from \"./scene/apps.js\";\nexport {\n type BlockGrid,\n blockGrid,\n type DirtyBlock,\n decodePng,\n diffBlocks,\n frameDhash,\n hamming,\n} from \"./scene/dhash.js\";\n// WS6: scene-builder surface — consumed by WS7 (Brain) and WS10 verifiers.\nexport {\n _resetDefaultSceneBuilderForTests,\n getDefaultSceneBuilder,\n SceneBuilder,\n type SceneBuilderDeps,\n type SceneUpdateEvent,\n} from \"./scene/scene-builder.js\";\nexport type {\n Scene,\n SceneApp,\n SceneAppWindow,\n SceneAxNode,\n SceneFocusedWindow,\n SceneOcrBox,\n SceneVlmElement,\n} from \"./scene/scene-types.js\";\nexport { serializeSceneForPrompt } from \"./scene/serialize.js\";\nexport { ComputerUseService } from \"./services/computer-use-service.js\";\nexport type {\n DesktopControlCapabilities,\n DesktopControlCapability,\n DesktopInputButton,\n DesktopScreenshotRegion,\n DesktopWindowInfo,\n} from \"./services/desktop-control.js\";\nexport {\n captureDesktopScreenshot,\n commandExists,\n detectDesktopControlCapabilities,\n getDesktopPlatformName,\n isHeadfulGuiAvailable,\n listDesktopWindows,\n performDesktopClick,\n performDesktopDoubleClick,\n performDesktopKeypress,\n performDesktopMouseMove,\n performDesktopScroll,\n performDesktopTextInput,\n} from \"./services/desktop-control.js\";\nexport {\n VISION_CONTEXT_SERVICE_TYPE,\n VISION_CONTEXT_TASK_GOAL_CACHE_KEY,\n type VisionContext,\n type VisionContextBBox,\n type VisionContextFocusedWindow,\n VisionContextProvider,\n type VisionContextRecentAction,\n} from \"./services/vision-context-provider.js\";\n// Re-export types for consumers\nexport type {\n ActionHistoryEntry,\n ApprovalMode,\n ApprovalResolution,\n ApprovalSnapshot,\n BrowserActionParams,\n BrowserActionResult,\n BrowserActionType,\n BrowserInfo,\n BrowserState,\n BrowserTab,\n ClickableElement,\n ComputerActionResult,\n ComputerUseConfig,\n ComputerUseResult,\n DesktopActionParams,\n DesktopActionType,\n FileActionParams,\n FileActionResult,\n FileActionType,\n FileEntry,\n PendingApproval,\n PermissionType,\n PlatformCapabilities,\n ScreenRegion,\n ScreenSize,\n TerminalActionParams,\n TerminalActionResult,\n TerminalActionType,\n WindowActionParams,\n WindowActionResult,\n WindowActionType,\n WindowInfo,\n} from \"./types.js\";\n",
|
|
6
|
+
"/**\n * Cross-platform clipboard read / write.\n *\n * Per-platform tool dependencies (install with the listed package manager when\n * not already present):\n * - Linux Wayland : `wl-clipboard` (apt: `wl-clipboard`, dnf: `wl-clipboard`,\n * pacman: `wl-clipboard`). Provides `wl-copy` / `wl-paste`.\n * Selected when `WAYLAND_DISPLAY` is set.\n * - Linux X11 : `xclip` (apt: `xclip`, dnf: `xclip`, pacman: `xclip`).\n * Used when not on Wayland.\n * - macOS : `pbcopy` / `pbpaste` (built-in, no install needed).\n * - Windows : PowerShell `Get-Clipboard` / `Set-Clipboard` (built-in\n * on Windows 10+).\n *\n * If the required tool is missing on Linux, callers receive a typed\n * `ClipboardUnavailableError` with the install hint embedded in `.message`.\n */\nimport { execFileSync, spawnSync } from \"node:child_process\";\nimport { commandExists, currentPlatform } from \"./helpers.js\";\nimport { psHostAvailable, runPsHost } from \"./ps-host.js\";\n\n// 15s to match the capture/screenshot spawn budgets. On Defender-heavy Windows\n// hosts a cold `powershell.exe` 5.1 spawn (Set-Clipboard/Get-Clipboard) can take\n// >5s under real-time AV scanning (measured ~11s on a build box), which made the\n// previous 5s budget false-fail the clipboard round-trip while the capability\n// itself was fine. See #9581 (Windows on-device CUA verification).\nconst CLIPBOARD_TIMEOUT_MS = 15_000;\nconst CLIPBOARD_MAX_BYTES = 10 * 1024 * 1024; // 10 MiB cap\n\nexport class ClipboardUnavailableError extends Error {\n readonly tool: string;\n constructor(tool: string, hint: string) {\n super(`Clipboard tool \"${tool}\" not found on PATH. ${hint}`);\n this.name = \"ClipboardUnavailableError\";\n this.tool = tool;\n }\n}\n\ntype LinuxBackend = \"wayland\" | \"x11\";\n\nfunction detectLinuxBackend(): LinuxBackend {\n const wayland = (process.env.WAYLAND_DISPLAY ?? \"\").trim();\n if (wayland.length > 0) return \"wayland\";\n return \"x11\";\n}\n\ninterface ClipboardCommand {\n command: string;\n args: readonly string[];\n}\n\ninterface ClipboardPlan {\n read: ClipboardCommand;\n write: ClipboardCommand;\n}\n\nfunction pickPlan(): ClipboardPlan {\n const os = currentPlatform();\n if (os === \"darwin\") {\n return {\n read: { command: \"pbpaste\", args: [] },\n write: { command: \"pbcopy\", args: [] },\n };\n }\n if (os === \"win32\") {\n return {\n read: {\n command: \"powershell\",\n args: [\"-NoProfile\", \"-Command\", \"Get-Clipboard -Raw\"],\n },\n write: {\n // `$input | Set-Clipboard` does NOT reliably consume piped stdin under\n // -Command (it hangs → ETIMEDOUT). Read stdin to EOF explicitly.\n command: \"powershell\",\n args: [\n \"-NoProfile\",\n \"-Command\",\n \"Set-Clipboard -Value ([Console]::In.ReadToEnd())\",\n ],\n },\n };\n }\n // Linux: Wayland-first, then X11.\n if (detectLinuxBackend() === \"wayland\") {\n if (!commandExists(\"wl-paste\") || !commandExists(\"wl-copy\")) {\n throw new ClipboardUnavailableError(\n \"wl-clipboard\",\n \"Install wl-clipboard (apt/dnf/pacman package: wl-clipboard) to enable clipboard on Wayland.\",\n );\n }\n return {\n read: { command: \"wl-paste\", args: [\"--no-newline\"] },\n write: { command: \"wl-copy\", args: [] },\n };\n }\n if (!commandExists(\"xclip\")) {\n throw new ClipboardUnavailableError(\n \"xclip\",\n \"Install xclip (apt/dnf/pacman package: xclip) to enable clipboard on X11.\",\n );\n }\n return {\n read: { command: \"xclip\", args: [\"-selection\", \"clipboard\", \"-o\"] },\n write: { command: \"xclip\", args: [\"-selection\", \"clipboard\", \"-i\"] },\n };\n}\n\nexport async function readClipboard(): Promise<string> {\n // Windows: prefer the warm PowerShell host (a cold spawn is ~10-16s under\n // Defender). Same `Get-Clipboard -Raw` command; falls back to one-shot spawn.\n if (psHostAvailable()) {\n try {\n return await runPsHost(\"Get-Clipboard -Raw\", CLIPBOARD_TIMEOUT_MS);\n } catch {\n /* warm host unavailable/errored — fall back to one-shot spawn */\n }\n }\n const plan = pickPlan();\n // encoding: \"utf-8\" forces the typed return to string.\n const out = execFileSync(plan.read.command, [...plan.read.args], {\n timeout: CLIPBOARD_TIMEOUT_MS,\n maxBuffer: CLIPBOARD_MAX_BYTES,\n encoding: \"utf-8\",\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n return out;\n}\n\nexport async function writeClipboard(text: string): Promise<void> {\n if (typeof text !== \"string\") {\n throw new TypeError(\"writeClipboard: text must be a string\");\n }\n if (Buffer.byteLength(text, \"utf-8\") > CLIPBOARD_MAX_BYTES) {\n throw new RangeError(\n `writeClipboard: payload exceeds ${CLIPBOARD_MAX_BYTES} bytes`,\n );\n }\n // Windows: prefer the warm PowerShell host. The value is base64-encoded into\n // the command (no stdin pipe needed), then decoded host-side, so it round-trips\n // any UTF-8 text safely. Falls back to the one-shot stdin-piped spawn.\n //\n // Empty string is routed to the fallback path deliberately: `Set-Clipboard\n // -Value ''` rejects an empty value, and base64('') would otherwise let the\n // host \"succeed\" where the one-shot spawn fails — a non-transparent\n // divergence. Routing both through the same path keeps the behavior identical.\n if (psHostAvailable() && text.length > 0) {\n try {\n const b64 = Buffer.from(text, \"utf-8\").toString(\"base64\");\n await runPsHost(\n `Set-Clipboard -Value ([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('${b64}')))`,\n CLIPBOARD_TIMEOUT_MS,\n );\n return;\n } catch {\n /* warm host unavailable/errored — fall back to one-shot spawn */\n }\n }\n const plan = pickPlan();\n const result = spawnSync(plan.write.command, [...plan.write.args], {\n input: text,\n timeout: CLIPBOARD_TIMEOUT_MS,\n encoding: \"utf-8\",\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n if (result.error) {\n throw result.error;\n }\n if (result.status !== 0) {\n // encoding: \"utf-8\" forces stderr to string when present.\n const stderr = result.stderr ?? \"\";\n throw new Error(\n `Clipboard write failed (${plan.write.command} exit ${result.status}): ${stderr.trim()}`,\n );\n }\n}\n\n/** Internal hook for unit tests — re-exported for parity with helpers.ts. */\nexport const __testing = {\n detectLinuxBackend,\n pickPlan,\n};\n",
|
|
7
|
+
"/**\n * Shared platform utilities for computer-use plugin.\n *\n * Ported from coasty-ai/open-computer-use desktop-automation.ts\n * and eliza sandbox-routes.ts (Apache 2.0 / MIT).\n */\n\nimport { execFileSync, execSync } from \"node:child_process\";\nimport { platform } from \"node:os\";\n\n// ── Command Execution ───────────────────────────────────────────────────────\n\n/**\n * Check if a CLI tool is available on the system.\n *\n * Memoized: tool availability on PATH does not change within a process run, and\n * the hot CUA paths call this per click/op (e.g. `commandExists(\"cliclick\")` on\n * every macOS click) — each uncached call spawns `which`/`where` (~50-100ms, and\n * far worse on Defender-heavy Windows where any spawn is ~10s). Caching collapses\n * it to a single probe per tool. `clearCommandExistsCache()` resets it for tests.\n */\nconst commandExistsCache = new Map<string, boolean>();\nexport function commandExists(cmd: string): boolean {\n const cached = commandExistsCache.get(cmd);\n if (cached !== undefined) return cached;\n let exists = false;\n try {\n const which = platform() === \"win32\" ? \"where\" : \"which\";\n execSync(`${which} ${cmd}`, { stdio: \"ignore\", timeout: 3000 });\n exists = true;\n } catch {\n exists = false;\n }\n commandExistsCache.set(cmd, exists);\n return exists;\n}\n\n/** Reset the {@link commandExists} memo (test-only / PATH change). */\nexport function clearCommandExistsCache(): void {\n commandExistsCache.clear();\n}\n\n/**\n * Run a command via execFileSync (no shell) with timeout.\n * Throws on non-zero exit or timeout.\n */\nexport function runCommand(\n command: string,\n args: string[],\n timeout: number,\n): string {\n const result = execFileSync(command, args, {\n timeout,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n encoding: \"utf-8\",\n });\n return result;\n}\n\n/**\n * Run a command via execFileSync, returning the raw Buffer stdout.\n */\nexport function runCommandBuffer(\n command: string,\n args: string[],\n timeout: number,\n): void {\n execFileSync(command, args, {\n timeout,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n}\n\n/**\n * Run a shell command string (uses shell). Use sparingly — prefer runCommand.\n */\nexport function runShellCommand(cmd: string, timeout: number): string {\n return execSync(cmd, {\n encoding: \"utf-8\",\n timeout,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n });\n}\n\n// ── Input Validation ────────────────────────────────────────────────────────\n\n/**\n * Coerce a value to a safe integer to prevent shell injection via coordinates.\n * Ported from open-computer-use desktop-automation.ts validateInt().\n */\nexport function validateInt(val: unknown): number {\n if (val === null || val === undefined) {\n throw new Error(`Invalid numeric value: ${String(val)}`);\n }\n if (typeof val === \"string\" && val.trim().length === 0) {\n throw new Error(`Invalid numeric value: ${String(val)}`);\n }\n const n = Number(val);\n if (!Number.isFinite(n)) {\n throw new Error(`Invalid numeric value: ${String(val)}`);\n }\n return Math.round(n);\n}\n\n/**\n * Validate and clamp coordinates within screen bounds.\n */\nexport function validateCoordinate(\n x: number,\n y: number,\n maxX: number,\n maxY: number,\n): [number, number] {\n const safeX = Math.max(0, Math.min(validateInt(x), maxX));\n const safeY = Math.max(0, Math.min(validateInt(y), maxY));\n return [safeX, safeY];\n}\n\n/**\n * Validate a window/process identifier before interpolating it into a\n * platform shell command (AppleScript / PowerShell). Rejects anything that\n * is not a decimal integer or `0x`-prefixed hex, preventing escape out of\n * the surrounding script literal.\n */\nexport function validateWindowId(windowId: string): string {\n if (typeof windowId !== \"string\") {\n throw new Error(`Invalid windowId: must be string, got ${typeof windowId}`);\n }\n const trimmed = windowId.trim();\n if (!/^[0-9]+$/.test(trimmed) && !/^0x[0-9a-f]+$/i.test(trimmed)) {\n throw new Error(\n `Invalid windowId: must be numeric or 0x-prefixed hex, got \"${windowId}\"`,\n );\n }\n return trimmed;\n}\n\n/**\n * Validate text input length to prevent abuse.\n */\nexport function validateText(text: string, maxLength = 4096): string {\n if (typeof text !== \"string\") {\n throw new Error(\"Text must be a string\");\n }\n if (text.length > maxLength) {\n throw new Error(`Text too long: ${text.length} chars (max ${maxLength})`);\n }\n return text;\n}\n\n// ── AppleScript Escaping ────────────────────────────────────────────────────\n\n/**\n * Safely escape a string for use inside an AppleScript double-quoted literal.\n * Ported from open-computer-use desktop-automation.ts.\n */\nexport function escapeAppleScript(value: string): string {\n return `\"${value.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"')}\"`;\n}\n\n// ── xdotool Key Validation ──────────────────────────────────────────────────\n\n/**\n * Known-safe xdotool key names. Whitelist approach from open-computer-use.\n */\nconst SAFE_XDOTOOL_KEYS = new Set([\n \"Return\",\n \"Tab\",\n \"Escape\",\n \"BackSpace\",\n \"Delete\",\n \"space\",\n \"Home\",\n \"End\",\n \"Page_Up\",\n \"Page_Down\",\n \"Left\",\n \"Right\",\n \"Up\",\n \"Down\",\n \"F1\",\n \"F2\",\n \"F3\",\n \"F4\",\n \"F5\",\n \"F6\",\n \"F7\",\n \"F8\",\n \"F9\",\n \"F10\",\n \"F11\",\n \"F12\",\n \"shift\",\n \"Shift_L\",\n \"Shift_R\",\n \"ctrl\",\n \"Control_L\",\n \"Control_R\",\n \"alt\",\n \"Alt_L\",\n \"Alt_R\",\n \"super\",\n \"Super_L\",\n \"Super_R\",\n \"Meta_L\",\n \"Meta_R\",\n \"plus\",\n \"minus\",\n \"period\",\n \"comma\",\n \"slash\",\n \"backslash\",\n \"bracketleft\",\n \"bracketright\",\n \"semicolon\",\n \"apostrophe\",\n \"grave\",\n \"equal\",\n]);\n\n/**\n * Validate a key name for xdotool. Must be a known key name or a single\n * printable ASCII character.\n */\nexport function safeXdotoolKey(key: string): string {\n const trimmed = key.trim();\n if (SAFE_XDOTOOL_KEYS.has(trimmed)) {\n return trimmed;\n }\n // Single printable ASCII character\n if (\n trimmed.length === 1 &&\n trimmed.charCodeAt(0) >= 32 &&\n trimmed.charCodeAt(0) <= 126\n ) {\n return trimmed;\n }\n throw new Error(\n `Invalid key for xdotool: \"${trimmed}\". Use a known key name or single ASCII character.`,\n );\n}\n\n/**\n * Safe keypress pattern for general validation (matches sandbox-routes).\n */\nconst SAFE_KEYPRESS_PATTERN = /^[A-Za-z0-9+_ .,:-]+$/;\n\nexport function validateKeypress(keys: string, maxLength = 128): string {\n if (typeof keys !== \"string\" || keys.length === 0) {\n throw new Error(\"Key input must be a non-empty string\");\n }\n if (keys.length > maxLength) {\n throw new Error(\n `Key input too long: ${keys.length} chars (max ${maxLength})`,\n );\n }\n if (!SAFE_KEYPRESS_PATTERN.test(keys)) {\n throw new Error(\n `Key input contains invalid characters: \"${keys}\". Only alphanumerics, +, _, ., ,, :, - and space allowed.`,\n );\n }\n return keys;\n}\n\n// ── Key Normalization ───────────────────────────────────────────────────────\n\nconst CANONICAL_KEY_ALIASES: Record<string, string> = {\n esc: \"escape\",\n escape: \"escape\",\n return: \"enter\",\n enter: \"enter\",\n spacebar: \"space\",\n space: \"space\",\n tab: \"tab\",\n up: \"up\",\n down: \"down\",\n left: \"left\",\n right: \"right\",\n pageup: \"pageup\",\n pagedown: \"pagedown\",\n home: \"home\",\n end: \"end\",\n del: \"delete\",\n delete: \"delete\",\n backspace: \"backspace\",\n};\n\nfunction normalizeKeyAlias(key: string): string {\n if (typeof key !== \"string\" || key.trim().length === 0) {\n throw new Error(\"Key input must be a non-empty string\");\n }\n return key\n .trim()\n .toLowerCase()\n .replace(/^arrow/, \"\")\n .replace(/[\\s_-]+/g, \"\");\n}\n\nexport function canonicalKeyName(key: string): string {\n const normalized = normalizeKeyAlias(key);\n if (/^f\\d{1,2}$/.test(normalized)) {\n return normalized;\n }\n return CANONICAL_KEY_ALIASES[normalized] ?? normalized;\n}\n\nconst CLICLICK_KEY_NAMES: Record<string, string> = {\n escape: \"esc\",\n enter: \"return\",\n up: \"arrow-up\",\n down: \"arrow-down\",\n left: \"arrow-left\",\n right: \"arrow-right\",\n pageup: \"page-up\",\n pagedown: \"page-down\",\n backspace: \"delete\",\n delete: \"fwd-delete\",\n home: \"home\",\n end: \"end\",\n space: \"space\",\n tab: \"tab\",\n};\n\nexport function toCliclickKeyName(key: string): string {\n const canonical = canonicalKeyName(key);\n return CLICLICK_KEY_NAMES[canonical] ?? canonical;\n}\n\nconst XDOTOOL_KEY_NAMES: Record<string, string> = {\n escape: \"Escape\",\n enter: \"Return\",\n tab: \"Tab\",\n backspace: \"BackSpace\",\n delete: \"Delete\",\n space: \"space\",\n home: \"Home\",\n end: \"End\",\n pageup: \"Page_Up\",\n pagedown: \"Page_Down\",\n left: \"Left\",\n right: \"Right\",\n up: \"Up\",\n down: \"Down\",\n};\n\nexport function toXdotoolKeyName(key: string): string {\n const canonical = canonicalKeyName(key);\n if (/^f\\d{1,2}$/.test(canonical)) {\n return canonical.toUpperCase();\n }\n return XDOTOOL_KEY_NAMES[canonical] ?? key.trim();\n}\n\nconst WINDOWS_SEND_KEYS: Record<string, string> = {\n escape: \"{ESC}\",\n enter: \"{ENTER}\",\n tab: \"{TAB}\",\n backspace: \"{BACKSPACE}\",\n delete: \"{DELETE}\",\n home: \"{HOME}\",\n end: \"{END}\",\n pageup: \"{PGUP}\",\n pagedown: \"{PGDN}\",\n left: \"{LEFT}\",\n right: \"{RIGHT}\",\n up: \"{UP}\",\n down: \"{DOWN}\",\n space: \" \",\n};\n\nexport function toWindowsSendKey(key: string): string {\n const canonical = canonicalKeyName(key);\n if (/^f\\d{1,2}$/.test(canonical)) {\n return `{${canonical.toUpperCase()}}`;\n }\n return WINDOWS_SEND_KEYS[canonical] ?? key.trim();\n}\n\n// ── Platform Detection ──────────────────────────────────────────────────────\n\nexport type PlatformOS = \"darwin\" | \"linux\" | \"win32\";\n\nexport function currentPlatform(): PlatformOS {\n const os = platform();\n if (os === \"darwin\" || os === \"linux\" || os === \"win32\") {\n return os;\n }\n throw new Error(`Unsupported platform: ${os}`);\n}\n",
|
|
8
|
+
"/**\n * Warm PowerShell host (Windows-only) — eliminates the cold-spawn tax.\n *\n * On Windows, every capability that shells out to `powershell.exe`\n * (screen capture, clipboard, window/display enumeration) pays the cost of\n * starting a fresh process. On Defender-heavy hosts real-time AV scans each new\n * process image, which measured **~10-12s per cold `powershell.exe` spawn** on a\n * build box (see #9581). The CUA scene pipeline grabs the screen — and several\n * dirty regions — every turn, so that tax compounds.\n *\n * This module keeps ONE long-lived `powershell.exe` alive and feeds it commands\n * over stdin, reading results back over stdout. The first call pays the cold\n * spawn once; every call after that runs in the already-warm process\n * (sub-second). It is a pure latency optimization: callers wrap their existing\n * one-shot PowerShell invocation and fall back to it transparently whenever the\n * host is unavailable, disabled, or errors — so behavior is unchanged, only\n * faster.\n *\n * The loop runs from a temp `.ps1` via `powershell -File` (NOT `-Command -`,\n * which would consume stdin to build the program and starve the loop's own\n * `ReadLine`). `-File` reads the program from disk, leaving stdin free for the\n * loop to read request lines.\n *\n * Protocol (host side is a tiny ReadLine server loop, see `SERVER_LOOP`):\n * - JS writes ONE line per request: `<token> <base64-utf8-script>\\n`.\n * base64 guarantees the payload is single-line and escaping-free.\n * - The host decodes the script, runs it in a child scope (`& {…}` via a\n * fresh ScriptBlock, so request state never leaks), then writes the script's\n * stdout followed by the bare `<token>` (no newline). On a terminating\n * error it writes `PSHOSTERR:<message>` before the token.\n * - JS accumulates stdout until it sees `<token>`; everything before it is the\n * response. A `PSHOSTERR:` prefix is surfaced as a rejection so the caller\n * falls back to its one-shot path.\n *\n * Requests are serialized through a single promise chain — one in flight at a\n * time over the one pipe. That is fine: each request is now sub-second, so even\n * a handful of dirty-region captures per turn complete far faster than a single\n * cold spawn used to.\n *\n * Disable entirely with `COMPUTERUSE_PS_HOST=0`.\n */\n\nimport { type ChildProcessWithoutNullStreams, spawn } from \"node:child_process\";\nimport { unlinkSync, writeFileSync } from \"node:fs\";\nimport { platform, tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\n\n/** Per-process nonce so request tokens can never collide with script output. */\nconst NONCE = `${process.pid.toString(36)}-${Date.now().toString(36)}`;\nlet seq = 0;\n\n/** Startup budget for the (one-time) cold spawn + warmup ping. */\nconst STARTUP_TIMEOUT_MS = 25_000;\n/** After this many consecutive startup failures, stop trying for the session. */\nconst MAX_START_FAILURES = 2;\n\nlet host: ChildProcessWithoutNullStreams | null = null;\nlet starting: Promise<void> | null = null;\nlet startFailures = 0;\nlet loopScriptPath: string | null = null;\n// Gate against respawning after an owner-initiated dispose. `shutdownPsHost()`\n// (timeout / test cleanup) leaves this true so the next call can respawn;\n// `disposePsHost()` (service stop) sets it false so a fire-and-forget warm\n// continuation can't resurrect a host after the service has stopped.\nlet spawnAllowed = true;\nlet stdoutBuf = \"\";\nlet stderrRing = \"\";\nlet pending: {\n token: string;\n resolve: (out: string) => void;\n reject: (err: Error) => void;\n timer: ReturnType<typeof setTimeout>;\n} | null = null;\n\n/** Serialization chain — at most one request is in flight on the host. */\nlet chain: Promise<unknown> = Promise.resolve();\n\n// The PowerShell server loop. Reads `<token> <base64>` lines from stdin, runs\n// the decoded script in a child scope, echoes the token to delimit the reply.\n// UTF-8 output so JSON / clipboard text round-trips. Pre-loads the assemblies\n// capture needs so per-request scripts stay lean (re-`Add-Type` is harmless\n// anyway). `$ErrorActionPreference='Stop'` makes failures terminate into our\n// try/catch instead of leaking to stderr mid-stream.\nconst SERVER_LOOP = [\n \"$ErrorActionPreference='Stop'\",\n \"[Console]::OutputEncoding=[System.Text.Encoding]::UTF8\",\n \"try { Add-Type -AssemblyName System.Windows.Forms,System.Drawing } catch {}\",\n \"while ($true) {\",\n \" $line=[Console]::In.ReadLine()\",\n \" if ($null -eq $line) { break }\",\n \" if ($line.Length -eq 0) { continue }\",\n \" $sp=$line.IndexOf(' ')\",\n \" if ($sp -lt 0) { continue }\",\n \" $tok=$line.Substring(0,$sp)\",\n \" $b64=$line.Substring($sp+1)\",\n \" try {\",\n \" $script=[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($b64))\",\n \" & ([ScriptBlock]::Create($script))\",\n \" } catch {\",\n \" [Console]::Out.Write('PSHOSTERR:'+$_.Exception.Message)\",\n \" }\",\n \" [Console]::Out.Write($tok)\",\n \" [Console]::Out.Flush()\",\n \"}\",\n].join(\"\\n\");\n\n/**\n * Whether the warm host is usable on this platform / configuration. Callers\n * should check this before attempting {@link runPsHost} and skip straight to\n * their one-shot path when false.\n */\nexport function psHostAvailable(): boolean {\n if (platform() !== \"win32\") return false;\n if (process.env.COMPUTERUSE_PS_HOST === \"0\") return false;\n if (startFailures >= MAX_START_FAILURES) return false;\n return true;\n}\n\nfunction onStdout(chunk: Buffer): void {\n stdoutBuf += chunk.toString(\"utf8\");\n if (!pending) return;\n const idx = stdoutBuf.indexOf(pending.token);\n if (idx === -1) return;\n const out = stdoutBuf.slice(0, idx);\n stdoutBuf = stdoutBuf.slice(idx + pending.token.length);\n const p = pending;\n pending = null;\n clearTimeout(p.timer);\n if (out.startsWith(\"PSHOSTERR:\")) {\n p.reject(\n new Error(`ps-host script error: ${out.slice(\"PSHOSTERR:\".length)}`),\n );\n } else {\n p.resolve(out);\n }\n}\n\nfunction onExit(): void {\n host = null;\n starting = null;\n stdoutBuf = \"\";\n if (pending) {\n const p = pending;\n pending = null;\n clearTimeout(p.timer);\n p.reject(new Error(\"ps-host exited unexpectedly\"));\n }\n}\n\n/** Tear the host down (test cleanup / unrecoverable state). */\nexport function shutdownPsHost(): void {\n if (host) {\n try {\n host.stdin.end();\n } catch {\n /* best effort */\n }\n try {\n host.kill();\n } catch {\n /* best effort */\n }\n }\n if (loopScriptPath) {\n try {\n unlinkSync(loopScriptPath);\n } catch {\n /* best effort */\n }\n loopScriptPath = null;\n }\n onExit();\n}\n\nasync function ensureHost(): Promise<void> {\n if (host) return;\n // Owner disposed the host (service stopped); refuse to resurrect it from a\n // late fire-and-forget continuation. Callers fall back to one-shot spawns.\n if (!spawnAllowed) throw new Error(\"ps-host disposed\");\n if (starting) return starting;\n starting = (async () => {\n // Write the server loop to disk and run it with `-File` so stdin stays free\n // for the loop's ReadLine (see module header).\n const scriptPath = join(\n tmpdir(),\n `computeruse-pshost-${process.pid}-${seq}.ps1`,\n );\n writeFileSync(scriptPath, SERVER_LOOP, \"utf8\");\n loopScriptPath = scriptPath;\n const child = spawn(\n \"powershell\",\n [\n \"-NoProfile\",\n \"-NoLogo\",\n \"-NonInteractive\",\n // `-File` is subject to the machine ExecutionPolicy; Bypass keeps the\n // loop script runnable on locked-down hosts (default policy disables\n // running .ps1 files).\n \"-ExecutionPolicy\",\n \"Bypass\",\n \"-File\",\n scriptPath,\n ],\n { stdio: [\"pipe\", \"pipe\", \"pipe\"], windowsHide: true },\n );\n child.stdout.on(\"data\", onStdout);\n child.stderr.on(\"data\", (c: Buffer) => {\n stderrRing = (stderrRing + c.toString(\"utf8\")).slice(-2048);\n });\n // Swallow stdin pipe errors (EPIPE when the host dies between requests).\n // Without this listener Node throws the 'error' as an uncaught exception\n // and crashes the whole process — defeating the transparent-fallback\n // contract. The dead pipe surfaces via onExit → a normal rejection instead.\n child.stdin.on(\"error\", () => {});\n // Bind exit/error to THIS child: a previously-killed host's late 'exit'\n // event must not tear down a freshly respawned host or reject its pending\n // request. Stale events are ignored.\n const onChildGone = () => {\n if (host !== child) return;\n onExit();\n };\n child.once(\"exit\", onChildGone);\n child.once(\"error\", onChildGone);\n host = child;\n // Warmup ping — proves the loop is reading and the process is hot.\n await sendRaw(\"$null\", STARTUP_TIMEOUT_MS);\n })();\n try {\n await starting;\n startFailures = 0;\n } catch (err) {\n startFailures += 1;\n shutdownPsHost();\n throw err;\n } finally {\n starting = null;\n }\n}\n\n/** Low-level: assumes host is alive; sends one framed request. */\nfunction sendRaw(script: string, timeoutMs: number): Promise<string> {\n return new Promise<string>((resolve, reject) => {\n if (!host) {\n reject(new Error(\"ps-host not running\"));\n return;\n }\n seq += 1;\n const token = `<<PSEOR:${NONCE}:${seq}>>`;\n const b64 = Buffer.from(script, \"utf8\").toString(\"base64\");\n const timer = setTimeout(() => {\n if (pending && pending.token === token) pending = null;\n // A wedged host is unrecoverable for this protocol — kill so the next\n // call respawns fresh rather than reading a stale, misframed stream.\n shutdownPsHost();\n reject(\n new Error(\n `ps-host timeout after ${timeoutMs}ms${stderrRing ? ` (stderr: ${stderrRing.trim().slice(-200)})` : \"\"}`,\n ),\n );\n }, timeoutMs);\n pending = { token, resolve, reject, timer };\n try {\n host.stdin.write(`${token} ${b64}\\n`);\n } catch (err) {\n // Synchronous write failure (e.g. dead pipe). Surface as a rejection so\n // the caller falls back, and tear the host down so the next call respawns.\n clearTimeout(timer);\n pending = null;\n shutdownPsHost();\n reject(err instanceof Error ? err : new Error(String(err)));\n }\n });\n}\n\n/**\n * Run a PowerShell script in the warm host and resolve with its stdout (UTF-8).\n * Serialized against other in-flight requests. Rejects (so the caller can fall\n * back to a one-shot spawn) on host-start failure, script error, timeout, or\n * unexpected host exit.\n *\n * @param script PowerShell source. Runs in a child scope; assemblies\n * `System.Windows.Forms` + `System.Drawing` are preloaded.\n * @param timeoutMs Per-request budget.\n */\nexport function runPsHost(script: string, timeoutMs: number): Promise<string> {\n const task = async (): Promise<string> => {\n await ensureHost();\n return sendRaw(script, timeoutMs);\n };\n const run = chain.then(task, task);\n chain = run.catch(() => {});\n return run;\n}\n\n/**\n * Best-effort pre-warm: pay the one-time cold spawn during service init instead\n * of on the first capture/clipboard call. Never rejects — if the host can't\n * start, callers transparently fall back to one-shot spawns.\n */\nexport function warmPsHost(): Promise<void> {\n // Re-enable spawning: an explicit warm is a fresh intent to use the host\n // (e.g. a service (re)start after a prior dispose).\n spawnAllowed = true;\n if (!psHostAvailable()) return Promise.resolve();\n return runPsHost(\"$null\", STARTUP_TIMEOUT_MS).then(\n () => {},\n () => {},\n );\n}\n\n/**\n * Owner-initiated dispose (service stop). Unlike {@link shutdownPsHost} (which\n * leaves the host respawnable for the next call — used by the timeout path),\n * this latches spawning OFF so an in-flight fire-and-forget warm continuation\n * cannot resurrect a powershell.exe after the service has stopped. A later\n * {@link warmPsHost} re-enables it.\n */\nexport function disposePsHost(): void {\n spawnAllowed = false;\n shutdownPsHost();\n}\n\n/** Test-only: reset failure latch so a fresh attempt can be made. */\nexport function __resetPsHostFailures(): void {\n startFailures = 0;\n}\n\n// Best-effort cleanup so we don't leak a powershell.exe on process exit.\nprocess.once(\"exit\", () => {\n if (host) {\n try {\n host.kill();\n } catch {\n /* best effort */\n }\n }\n});\n",
|
|
9
|
+
"import type { ActionResult, HandlerOptions, Memory } from \"@elizaos/core\";\n\nexport interface NativeComputerUseResult {\n success: boolean;\n message?: string;\n error?: string;\n permissionDenied?: boolean;\n permissionType?: string;\n approvalRequired?: boolean;\n approvalId?: string;\n screenshot?: string;\n frontendScreenshot?: string;\n}\n\nexport function resolveActionParams<T>(\n message: Memory,\n options?: HandlerOptions,\n): T {\n const params = {\n ...(((options as Record<string, unknown> | undefined)?.parameters ??\n {}) as Record<string, unknown>),\n };\n\n if (message.content && typeof message.content === \"object\") {\n for (const [key, value] of Object.entries(\n message.content as Record<string, unknown>,\n )) {\n if (params[key] === undefined) {\n params[key] = value;\n }\n }\n }\n\n return params as T;\n}\n\nexport function buildScreenshotAttachment(args: {\n idPrefix: string;\n screenshot: string;\n title: string;\n description: string;\n}) {\n return {\n id: `${args.idPrefix}-${Date.now()}`,\n url: `data:image/png;base64,${args.screenshot}`,\n title: args.title,\n source: \"computeruse\",\n description: args.description,\n contentType: \"image\" as const,\n };\n}\n\nfunction sanitizeNativeResult<T extends NativeComputerUseResult>(\n result: T,\n): Record<string, unknown> {\n const sanitized: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(result)) {\n if (key === \"screenshot\") {\n sanitized.hasScreenshot = typeof value === \"string\" && value.length > 0;\n continue;\n }\n if (key === \"frontendScreenshot\") {\n sanitized.hasFrontendScreenshot =\n typeof value === \"string\" && value.length > 0;\n continue;\n }\n sanitized[key] = value;\n }\n return sanitized;\n}\n\nexport function toComputerUseActionResult<T extends NativeComputerUseResult>({\n action,\n result,\n text,\n suppressClipboard = false,\n}: {\n action: string;\n result: T;\n text: string;\n suppressClipboard?: boolean;\n}): ActionResult {\n return {\n success: result.success,\n text,\n ...(result.success ? {} : { error: result.error ?? \"Computer-use failed\" }),\n data: {\n source: \"computeruse\",\n computerUseAction: action,\n result: sanitizeNativeResult(result),\n ...(suppressClipboard ? { suppressActionResultClipboard: true } : {}),\n },\n };\n}\n",
|
|
10
|
+
"/**\n * CLIPBOARD parent action — read or write the host system clipboard.\n *\n * Routes through `driverReadClipboard` / `driverWriteClipboard`, which\n * select the per-OS tool (pbcopy/pbpaste, wl-copy/wl-paste, xclip,\n * PowerShell Set-Clipboard / Get-Clipboard).\n *\n * Subactions: `read`, `write`. The plugin index promotes them to virtual\n * top-level actions (`CLIPBOARD_READ`, `CLIPBOARD_WRITE`) so the planner\n * can pick a specific verb directly from the action catalogue.\n */\n\nimport type {\n Action,\n ActionResult,\n HandlerCallback,\n HandlerOptions,\n IAgentRuntime,\n Memory,\n State,\n} from \"@elizaos/core\";\nimport {\n ClipboardUnavailableError,\n readClipboard as driverReadClipboard,\n writeClipboard as driverWriteClipboard,\n} from \"../platform/clipboard.js\";\nimport type { ComputerUseService } from \"../services/computer-use-service.js\";\nimport { resolveActionParams, toComputerUseActionResult } from \"./helpers.js\";\n\nconst CLIPBOARD_ACTIONS = [\"read\", \"write\"] as const;\nexport type ClipboardActionType = (typeof CLIPBOARD_ACTIONS)[number];\n\nexport interface ClipboardActionParams {\n action: ClipboardActionType;\n /** Text payload for `write`. Ignored for `read`. */\n text?: string;\n}\n\ninterface ClipboardActionResult {\n success: boolean;\n message?: string;\n error?: string;\n /** Populated for `read` on success. */\n text?: string;\n}\n\ntype ClipboardParameters = Omit<Partial<ClipboardActionParams>, \"action\"> & {\n action?: ClipboardActionType | string;\n subaction?: ClipboardActionType | string;\n op?: ClipboardActionType | string;\n};\n\nconst CLIPBOARD_PREVIEW_BYTES = 4096;\n\nfunction getComputerUseService(\n runtime: IAgentRuntime,\n): ComputerUseService | null {\n return (runtime.getService(\"computeruse\") as ComputerUseService) ?? null;\n}\n\nfunction normalizeClipboardToken(\n value: unknown,\n): ClipboardActionType | undefined {\n if (typeof value !== \"string\") return undefined;\n const normalized = value.trim().toLowerCase();\n if ((CLIPBOARD_ACTIONS as readonly string[]).includes(normalized)) {\n return normalized as ClipboardActionType;\n }\n return undefined;\n}\n\nfunction resolveClipboardAction(\n params: ClipboardParameters,\n): ClipboardActionType | undefined {\n return (\n normalizeClipboardToken(params.action) ??\n normalizeClipboardToken(params.subaction) ??\n normalizeClipboardToken(params.op)\n );\n}\n\nasync function runClipboardAction(\n params: ClipboardActionParams,\n): Promise<ClipboardActionResult> {\n if (params.action === \"read\") {\n const text = await driverReadClipboard();\n const preview =\n text.length > CLIPBOARD_PREVIEW_BYTES\n ? `${text.slice(0, CLIPBOARD_PREVIEW_BYTES)}…`\n : text;\n return {\n success: true,\n text,\n message: text.length === 0 ? \"Clipboard is empty.\" : preview,\n };\n }\n if (params.action === \"write\") {\n if (typeof params.text !== \"string\") {\n return {\n success: false,\n error: \"text is required for clipboard write\",\n };\n }\n await driverWriteClipboard(params.text);\n return {\n success: true,\n message: `Wrote ${Buffer.byteLength(params.text, \"utf-8\")} bytes to clipboard.`,\n };\n }\n return {\n success: false,\n error: `Unknown clipboard action: ${(params as { action: string }).action}`,\n };\n}\n\nexport const clipboardAction: Action = {\n name: \"CLIPBOARD\",\n contexts: [\"screen_time\", \"automation\", \"files\"],\n contextGate: {\n anyOf: [\"screen_time\", \"automation\", \"files\"],\n },\n roleGate: { minRole: \"USER\" },\n similes: [\n \"USE_CLIPBOARD\",\n \"CLIPBOARD_ACTION\",\n \"COPY\",\n \"PASTE\",\n \"READ_CLIPBOARD\",\n \"WRITE_CLIPBOARD\",\n ],\n description:\n \"CLIPBOARD action. Read or write the host system clipboard. actions: read, write. Linux requires wl-clipboard (Wayland) or xclip (X11); macOS uses pbcopy/pbpaste; Windows uses PowerShell Set-Clipboard / Get-Clipboard.\",\n descriptionCompressed: \"CLIPBOARD action=read|write\",\n parameters: [\n {\n name: \"action\",\n description: \"Clipboard operation verb.\",\n required: true,\n schema: {\n type: \"string\",\n enum: [...CLIPBOARD_ACTIONS],\n },\n },\n {\n name: \"text\",\n description: \"Payload for write.\",\n required: false,\n schema: { type: \"string\" },\n },\n ],\n validate: async (\n runtime: IAgentRuntime,\n _message: Memory,\n _state?: State,\n ): Promise<boolean> => {\n const service = getComputerUseService(runtime);\n if (!service) return false;\n return service.getCapabilities().clipboard.available;\n },\n handler: async (\n runtime: IAgentRuntime,\n message: Memory,\n _state?: State,\n options?: HandlerOptions,\n callback?: HandlerCallback,\n ): Promise<ActionResult> => {\n const service = getComputerUseService(runtime);\n if (!service) {\n return { success: false, error: \"ComputerUseService not available\" };\n }\n\n const params = resolveActionParams<ClipboardParameters>(message, options);\n const action = resolveClipboardAction(params) ?? \"read\";\n\n let result: ClipboardActionResult;\n try {\n result = await runClipboardAction({\n ...params,\n action,\n } satisfies ClipboardActionParams);\n } catch (error) {\n const message =\n error instanceof ClipboardUnavailableError\n ? error.message\n : error instanceof Error\n ? error.message\n : String(error);\n result = { success: false, error: message };\n }\n\n const text = result.success\n ? (result.message ?? `Completed clipboard ${action}.`)\n : `Clipboard action failed: ${result.error}`;\n\n if (callback) {\n await callback({ text });\n }\n\n return toComputerUseActionResult({\n action,\n result,\n text,\n // CLIPBOARD_READ deliberately surfaces text in the action result; do not\n // strip it via the shared clipboard suppression flag.\n suppressClipboard: action === \"write\",\n });\n },\n\n examples: [\n [\n {\n name: \"{{name1}}\",\n content: { text: \"What's currently on my clipboard?\", source: \"chat\" },\n },\n {\n name: \"{{agentName}}\",\n content: {\n text: \"Reading the clipboard.\",\n actions: [\"CLIPBOARD\"],\n thought:\n \"Clipboard inspection routes to CLIPBOARD action=read; the result text contains the payload.\",\n },\n },\n ],\n [\n {\n name: \"{{name1}}\",\n content: {\n text: \"Copy 'meeting at 3pm' to my clipboard.\",\n source: \"chat\",\n },\n },\n {\n name: \"{{agentName}}\",\n content: {\n text: \"Writing the text to the clipboard.\",\n actions: [\"CLIPBOARD\"],\n thought:\n \"Putting a literal string on the clipboard maps to CLIPBOARD action=write with the payload in `text`.\",\n },\n },\n ],\n ],\n};\n",
|
|
11
|
+
"import {\n type Content,\n type HandlerCallback,\n logger,\n type Memory,\n} from \"@elizaos/core\";\nimport type { ApprovalSnapshot, PendingApproval } from \"../types.js\";\n\nexport const ACTION_PROGRESS_SOURCE = \"action_progress\";\nexport const COMPUTER_USE_APPROVAL_SOURCE = \"computeruse_approval\";\n\nexport interface StepProgressInput {\n actionName: string;\n step: number;\n kind: string;\n rationale?: string;\n success?: boolean;\n error?: string;\n source?: string;\n}\n\nexport interface ApprovalRelayService {\n getApprovalSnapshot(): ApprovalSnapshot;\n subscribeApprovals(\n listener: (snapshot: ApprovalSnapshot) => void,\n ): () => void;\n}\n\nexport interface ApprovalRelayOptions {\n ownerId?: string;\n}\n\nexport function isStreamProgressEnabled(value: unknown): value is true {\n return value === true;\n}\n\nexport function formatStepProgressText(\n step: number,\n kind: string,\n rationale?: string,\n): string {\n const trimmed = rationale?.trim();\n return `Step ${step}: ${kind} — ${trimmed || \"dispatched\"}`;\n}\n\nexport function buildStepProgressContent(input: StepProgressInput): Content {\n const rationale = input.rationale?.trim() || \"dispatched\";\n return {\n text: formatStepProgressText(input.step, input.kind, rationale),\n source: ACTION_PROGRESS_SOURCE,\n merge: \"replace\",\n metadata: {\n transient: true,\n compactProgress: true,\n progress: {\n source: input.source ?? \"computeruse\",\n actionName: input.actionName,\n step: input.step,\n kind: input.kind,\n rationale,\n success: input.success,\n error: input.error,\n },\n },\n };\n}\n\nfunction approvalCallbackValue(\n approvalId: string,\n decision: \"approve\" | \"deny\",\n ownerId?: string,\n): string {\n return ownerId\n ? `cua:${approvalId}:${decision}:u${ownerId}`\n : `cua:${approvalId}:${decision}`;\n}\n\nexport function buildApprovalPromptContent(\n approval: PendingApproval,\n options: ApprovalRelayOptions = {},\n): Content {\n return {\n text: [\n `Computer-use approval requested for \\`${approval.command}\\`.`,\n `[CHOICE:computeruse-approval id=${approval.id}]`,\n `${approvalCallbackValue(approval.id, \"approve\", options.ownerId)}=Approve`,\n `${approvalCallbackValue(approval.id, \"deny\", options.ownerId)}=Deny`,\n \"[/CHOICE]\",\n ].join(\"\\n\"),\n source: COMPUTER_USE_APPROVAL_SOURCE,\n metadata: {\n transient: true,\n computeruse: {\n approvalId: approval.id,\n command: approval.command,\n requestedAt: approval.requestedAt,\n ownerId: options.ownerId,\n },\n },\n };\n}\n\nexport async function withApprovalRelay<T>(\n service: ApprovalRelayService,\n callback: HandlerCallback | undefined,\n run: () => Promise<T>,\n options: ApprovalRelayOptions = {},\n): Promise<T> {\n if (!callback) {\n return run();\n }\n\n const seen = new Set<string>();\n for (const approval of service.getApprovalSnapshot().pendingApprovals) {\n seen.add(approval.id);\n }\n\n const deliveries: Array<Promise<Memory[]>> = [];\n const unsubscribe = service.subscribeApprovals((snapshot) => {\n for (const approval of snapshot.pendingApprovals) {\n if (seen.has(approval.id)) continue;\n seen.add(approval.id);\n deliveries.push(\n callback(\n buildApprovalPromptContent(approval, options),\n \"COMPUTER_USE_APPROVAL\",\n ).catch((error) => {\n logger.warn(\n {\n src: \"plugin:computeruse\",\n approvalId: approval.id,\n error: error instanceof Error ? error.message : String(error),\n },\n \"Failed to relay computer-use approval request\",\n );\n return [];\n }),\n );\n }\n });\n\n try {\n return await run();\n } finally {\n unsubscribe();\n await Promise.allSettled(deliveries);\n }\n}\n",
|
|
12
|
+
"import type {\n Action,\n ActionResult,\n HandlerCallback,\n HandlerOptions,\n IAgentRuntime,\n Memory,\n State,\n} from \"@elizaos/core\";\nimport type { ComputerUseService } from \"../services/computer-use-service.js\";\nimport type {\n ComputerActionResult,\n DesktopActionParams,\n DesktopActionType,\n} from \"../types.js\";\nimport {\n buildScreenshotAttachment,\n resolveActionParams,\n toComputerUseActionResult,\n} from \"./helpers.js\";\nimport { withApprovalRelay } from \"./progress.js\";\n\nfunction approvalOwnerIdFromMemory(message: Memory): string | undefined {\n const metadata = message.metadata;\n if (!metadata || typeof metadata !== \"object\") return undefined;\n const telegramUserId = (metadata as Record<string, unknown>).telegramUserId;\n return typeof telegramUserId === \"string\" && telegramUserId.length > 0\n ? telegramUserId\n : undefined;\n}\n\nfunction getComputerUseService(\n runtime: IAgentRuntime,\n): ComputerUseService | null {\n return (runtime.getService(\"computeruse\") as ComputerUseService) ?? null;\n}\n\nconst DESKTOP_ACTIONS = new Set<DesktopActionType>([\n \"screenshot\",\n \"click\",\n \"click_with_modifiers\",\n \"double_click\",\n \"right_click\",\n \"mouse_move\",\n \"middle_click\",\n \"mouse_down\",\n \"mouse_up\",\n \"type\",\n \"key\",\n \"key_combo\",\n \"key_down\",\n \"key_up\",\n \"scroll\",\n \"drag\",\n \"get_cursor_position\",\n \"detect_elements\",\n \"ocr\",\n \"open\",\n \"launch\",\n \"kill_app\",\n \"set_value\",\n]);\n\ntype ComputerUseActionParams = Omit<DesktopActionParams, \"action\"> & {\n action?: DesktopActionType | \"resolve_approval\";\n approvalId?: string;\n approved?: boolean;\n reason?: string;\n};\n\ntype ApprovalDecision = {\n approvalId: string;\n approved: boolean;\n reason?: string;\n ownerMismatch?: boolean;\n};\n\nfunction formatDesktopResultText(\n params: DesktopActionParams,\n result: ComputerActionResult,\n): string {\n if (!result.success) {\n if (result.permissionDenied) {\n return `Desktop action failed because ${result.permissionType} permission is missing.`;\n }\n if (result.approvalRequired) {\n return `Desktop action \"${params.action}\" is waiting for approval (${result.approvalId}).`;\n }\n return `Desktop action failed: ${result.error}`;\n }\n\n if (params.action === \"screenshot\") {\n return result.message ?? \"Here is the current screen.\";\n }\n return result.message ?? `Completed ${params.action}.`;\n}\n\nfunction parseApprovalDecision(\n params: ComputerUseActionParams,\n message: Memory,\n): ApprovalDecision | null {\n if (params.action === \"resolve_approval\") {\n const approvalId = params.approvalId?.trim();\n if (!approvalId || typeof params.approved !== \"boolean\") {\n return null;\n }\n return {\n approvalId,\n approved: params.approved,\n reason: params.reason,\n };\n }\n\n const text = message.content?.text?.trim() ?? \"\";\n const compactMatch = /^cua:([^:]+):(approve|deny)(?::u([^:]+))?$/.exec(text);\n if (compactMatch) {\n const ownerId = compactMatch[3];\n const messageOwnerId = approvalOwnerIdFromMemory(message);\n if (ownerId && messageOwnerId && ownerId !== messageOwnerId) {\n return {\n approvalId: compactMatch[1] ?? \"\",\n approved: false,\n reason: \"Approval callback owner mismatch\",\n ownerMismatch: true,\n };\n }\n return {\n approvalId: compactMatch[1] ?? \"\",\n approved: compactMatch[2] === \"approve\",\n reason: `Resolved from chat button (${compactMatch[2]})`,\n };\n }\n\n const match = /^(approve|deny):([A-Za-z0-9_-]+)$/.exec(text);\n if (!match) {\n return null;\n }\n return {\n approved: match[1] === \"approve\",\n approvalId: match[2] ?? \"\",\n reason: `Resolved from chat button (${match[1]})`,\n };\n}\n\nfunction toDesktopActionParams(\n params: ComputerUseActionParams,\n): DesktopActionParams | null {\n const action = params.action ?? \"screenshot\";\n if (!DESKTOP_ACTIONS.has(action as DesktopActionType)) {\n return null;\n }\n return {\n ...params,\n action: action as DesktopActionType,\n };\n}\n\nasync function deliverResult(\n params: DesktopActionParams,\n result: ComputerActionResult,\n text: string,\n callback?: HandlerCallback,\n): Promise<void> {\n if (!callback) return;\n await callback({\n text,\n ...(result.screenshot\n ? {\n attachments: [\n buildScreenshotAttachment({\n idPrefix: \"computeruse-screenshot\",\n screenshot: result.screenshot,\n title: \"Screenshot\",\n description:\n params.action === \"screenshot\"\n ? \"Current screen capture\"\n : `Screen capture after ${params.action}`,\n }),\n ],\n }\n : {}),\n });\n}\n\nexport const useComputerAction: Action = {\n name: \"COMPUTER_USE\",\n contexts: [\n \"chat\",\n \"browser\",\n \"files\",\n \"terminal\",\n \"screen_time\",\n \"automation\",\n \"admin\",\n ],\n contextGate: {\n anyOf: [\n \"chat\",\n \"browser\",\n \"files\",\n \"terminal\",\n \"screen_time\",\n \"automation\",\n \"admin\",\n ],\n },\n roleGate: { minRole: \"OWNER\" },\n similes: [\n \"USE_COMPUTER\",\n \"CONTROL_COMPUTER\",\n \"COMPUTER_ACTION\",\n \"DESKTOP_ACTION\",\n \"CLICK\",\n \"CLICK_SCREEN\",\n \"TYPE_TEXT\",\n \"PRESS_KEY\",\n \"KEY_COMBO\",\n \"SCROLL_SCREEN\",\n \"MOVE_MOUSE\",\n \"DRAG\",\n \"MOUSE_CLICK\",\n \"CLICK_WITH_MODIFIERS\",\n \"TAKE_SCREENSHOT\",\n \"CAPTURE_SCREEN\",\n \"SEE_SCREEN\",\n \"APPROVE_COMPUTER_USE\",\n \"DENY_COMPUTER_USE\",\n ],\n description:\n \"computer_use: real desktop control on macOS/Linux/Windows. Screenshot before acting. Results include screenshot when available. Use for Finder/Desktop/native-app/browser/file/terminal on owner's machine. actions: screenshot/click/click_with_modifiers/double_click/right_click/mouse_move/middle_click/mouse_down/mouse_up/type/key/key_combo/key_down/key_up/scroll/drag/detect_elements/ocr/open/launch. mouse_down/up + key_down/up are press-and-hold primitives (button held until released); drag accepts a multi-point `path`; open(target) opens a file/URL/folder; launch(app,appArgs) starts an app and returns its pid. Also resolves pending computer-use approvals from approve:<id> / deny:<id> chat button callbacks.\",\n descriptionCompressed:\n \"Desktop: screenshot|click|double|right|middle|move|down|up|type|key|scroll|drag|detect|ocr|open|launch|approve\",\n routingHint:\n \"desktop/computer/native-app/Finder/window screenshots or control -> COMPUTER_USE; never invent takeScreenshot\",\n\n parameters: [\n {\n name: \"action\",\n description: \"Desktop action to perform.\",\n required: true,\n schema: {\n type: \"string\",\n enum: [\n \"screenshot\",\n \"click\",\n \"click_with_modifiers\",\n \"double_click\",\n \"right_click\",\n \"mouse_move\",\n \"middle_click\",\n \"mouse_down\",\n \"mouse_up\",\n \"type\",\n \"key\",\n \"key_combo\",\n \"key_down\",\n \"key_up\",\n \"scroll\",\n \"drag\",\n \"get_cursor_position\",\n \"detect_elements\",\n \"ocr\",\n \"open\",\n \"launch\",\n \"kill_app\",\n \"set_value\",\n \"resolve_approval\",\n ],\n },\n },\n {\n name: \"coordinate\",\n description: \"Target [x, y] pixel coordinate.\",\n required: false,\n schema: { type: \"array\", items: { type: \"number\" } },\n },\n {\n name: \"startCoordinate\",\n description: \"Start [x, y] pixel coordinate for drag.\",\n required: false,\n schema: { type: \"array\", items: { type: \"number\" } },\n },\n {\n name: \"path\",\n description:\n \"Multi-point polyline [[x,y],...] (≥2 points) for drag; traces every waypoint with the button held. Supersedes startCoordinate/coordinate when present.\",\n required: false,\n schema: {\n type: \"array\",\n items: { type: \"array\", items: { type: \"number\" } },\n },\n },\n {\n name: \"text\",\n description: \"Text to type.\",\n required: false,\n schema: { type: \"string\" },\n },\n {\n name: \"modifiers\",\n description:\n \"Modifier keys for click_with_modifiers, e.g. ['cmd','shift'] or ['ctrl'].\",\n required: false,\n schema: { type: \"array\", items: { type: \"string\" } },\n },\n {\n name: \"key\",\n description: \"Single key or combo string depending on action.\",\n required: false,\n schema: { type: \"string\" },\n },\n {\n name: \"button\",\n description:\n \"Mouse button for click_with_modifiers and mouse_down/mouse_up (default left).\",\n required: false,\n schema: { type: \"string\", enum: [\"left\", \"middle\", \"right\"] },\n },\n {\n name: \"clicks\",\n description: \"Number of clicks for click_with_modifiers.\",\n required: false,\n schema: { type: \"number\", minimum: 1, maximum: 5 },\n },\n {\n name: \"scrollDirection\",\n description: \"Scroll direction.\",\n required: false,\n schema: { type: \"string\", enum: [\"up\", \"down\", \"left\", \"right\"] },\n },\n {\n name: \"scrollAmount\",\n description: \"Scroll tick count.\",\n required: false,\n schema: { type: \"number\", minimum: 1, maximum: 20, default: 3 },\n },\n {\n name: \"displayId\",\n description:\n \"Display for coordinate. Required for coordinate actions on multi-monitor. See computerState displays[].\",\n required: false,\n schema: { type: \"number\" },\n },\n {\n name: \"coordSource\",\n description:\n \"Coordinate space: logical default matches display.bounds; backing raw retina pixels macOS only.\",\n required: false,\n schema: { type: \"string\", enum: [\"logical\", \"backing\"] },\n },\n {\n name: \"approvalId\",\n description:\n \"Pending computer-use approval id for action=resolve_approval.\",\n required: false,\n schema: { type: \"string\" },\n },\n {\n name: \"approved\",\n description: \"Approval decision for action=resolve_approval.\",\n required: false,\n schema: { type: \"boolean\" },\n },\n {\n name: \"reason\",\n description: \"Optional reason for an approval decision.\",\n required: false,\n schema: { type: \"string\" },\n },\n {\n name: \"target\",\n description:\n \"File path / URL / folder to open with the OS default handler (action=open).\",\n required: false,\n schema: { type: \"string\" },\n },\n {\n name: \"app\",\n description:\n \"Application name or executable path to launch (action=launch).\",\n required: false,\n schema: { type: \"string\" },\n },\n {\n name: \"appArgs\",\n description: \"Arguments for the launched application (action=launch).\",\n required: false,\n schema: { type: \"array\", items: { type: \"string\" } },\n },\n ],\n validate: async (\n runtime: IAgentRuntime,\n _message: Memory,\n _state?: State,\n ): Promise<boolean> => {\n const service = getComputerUseService(runtime);\n return service !== null;\n },\n handler: async (\n runtime: IAgentRuntime,\n message: Memory,\n _state?: State,\n options?: HandlerOptions,\n callback?: HandlerCallback,\n ): Promise<ActionResult> => {\n const params = resolveActionParams<ComputerUseActionParams>(\n message,\n options,\n );\n\n const service = getComputerUseService(runtime);\n if (!service) {\n return { success: false, error: \"ComputerUseService not available\" };\n }\n\n const approvalDecision = parseApprovalDecision(params, message);\n if (approvalDecision) {\n if (approvalDecision.ownerMismatch) {\n const text =\n \"Computer-use approval callback does not belong to this user.\";\n if (callback) {\n await callback({ text }, \"COMPUTER_USE\");\n }\n return {\n success: false,\n error: text,\n text,\n data: {\n source: \"computeruse\",\n computerUseAction: \"COMPUTER_USE\",\n approvalId: approvalDecision.approvalId,\n },\n };\n }\n const resolution = service.resolveApproval(\n approvalDecision.approvalId,\n approvalDecision.approved,\n approvalDecision.reason,\n );\n const verb = approvalDecision.approved ? \"approved\" : \"denied\";\n const text = resolution\n ? `Computer-use approval ${approvalDecision.approvalId} ${verb}.`\n : `Computer-use approval ${approvalDecision.approvalId} is not pending.`;\n if (callback) {\n await callback({ text }, \"COMPUTER_USE\");\n }\n return {\n success: resolution !== null,\n text,\n data: {\n source: \"computeruse\",\n computerUseAction: \"COMPUTER_USE\",\n approval: resolution,\n },\n };\n }\n\n const desktopParams = toDesktopActionParams(params);\n if (!desktopParams) {\n return {\n success: false,\n error: `Unknown COMPUTER_USE action: ${String(params.action)}`,\n };\n }\n\n const result: ComputerActionResult = await withApprovalRelay(\n service,\n callback,\n () => service.executeDesktopAction(desktopParams),\n { ownerId: approvalOwnerIdFromMemory(message) },\n );\n const text = formatDesktopResultText(desktopParams, result);\n await deliverResult(desktopParams, result, text, callback);\n return toComputerUseActionResult({\n action: desktopParams.action,\n result,\n text,\n suppressClipboard: true,\n });\n },\n\n examples: [\n [\n {\n name: \"{{name1}}\",\n content: { text: \"Take a screenshot of my screen.\", source: \"chat\" },\n },\n {\n name: \"{{agentName}}\",\n content: {\n text: \"Capturing the screen.\",\n actions: [\"COMPUTER_USE\"],\n thought:\n \"User asked for a screenshot of the desktop; COMPUTER_USE action=screenshot is the canonical handler.\",\n },\n },\n ],\n [\n {\n name: \"{{name1}}\",\n content: { text: \"Click the Send button on the page.\", source: \"chat\" },\n },\n {\n name: \"{{agentName}}\",\n content: {\n text: \"Clicking Send.\",\n actions: [\"COMPUTER_USE\"],\n thought:\n \"Direct UI click on a desktop control belongs in COMPUTER_USE action=click; pass the coordinate of the visible button.\",\n },\n },\n ],\n [\n {\n name: \"{{name1}}\",\n content: {\n text: \"Type 'Hello team' in the focused text box.\",\n source: \"chat\",\n },\n },\n {\n name: \"{{agentName}}\",\n content: {\n text: \"Typing the text.\",\n actions: [\"COMPUTER_USE\"],\n thought:\n \"Keyboard input into the focused field maps to COMPUTER_USE action=type with the literal text payload.\",\n },\n },\n ],\n [\n {\n name: \"{{name1}}\",\n content: {\n text: \"Press Cmd+Shift+T to reopen the closed tab.\",\n source: \"chat\",\n },\n },\n {\n name: \"{{agentName}}\",\n content: {\n text: \"Sending the key combo.\",\n actions: [\"COMPUTER_USE\"],\n thought:\n \"A multi-key shortcut routes to COMPUTER_USE action=key_combo with key='cmd+shift+t' so the desktop service triggers it as a single chord.\",\n },\n },\n ],\n ],\n};\n",
|
|
13
|
+
"/**\n * WS7 — COMPUTER_USE_AGENT action.\n *\n * High-level \"give me a goal, I'll click my way there\" entry point. The\n * planner emits one of these instead of the lower-level COMPUTER_USE_CLICK\n * etc. when the right action isn't obvious from the prompt.\n *\n * Loop:\n * 1. refresh scene (`agent-turn`)\n * 2. capture per-display PNGs\n * 3. Brain → Cascade → ProposedAction\n * 4. dispatch into ComputerInterface\n * 5. observe (auto-screenshot via the existing service flow happens for\n * ProposedAction.kind=click/etc; explicit captureAllDisplays after\n * every step)\n * 6. repeat until `finish` or `maxSteps`\n *\n * Trajectory events are emitted as structured `logger.info` lines with a\n * `evt: \"computeruse.agent.step\"` payload, which the trajectory-logger app\n * picks up via standard log capture. When `streamProgress` is enabled, the\n * same step boundary also emits a `HandlerCallback` status to the origin chat.\n * We don't take a hard dependency on the trajectory-logger plugin from here.\n */\n\nimport {\n type Action,\n type ActionResult,\n type Content,\n type HandlerCallback,\n type HandlerOptions,\n type IAgentRuntime,\n logger,\n type Memory,\n type State,\n} from \"@elizaos/core\";\nimport {\n type AgentMiddleware,\n createBudgetCapMiddleware,\n createImageRetentionMiddleware,\n createOperatorNormalizerMiddleware,\n createTrajectoryMiddleware,\n runAfterStep,\n runBeforeStep,\n runOnCaptures,\n runOnRunEnd,\n runOnRunStart,\n runTransformProposed,\n type TrajectoryEntry,\n} from \"../actor/agent-callbacks.js\";\nimport {\n AGENT_LOOP_SETTING,\n type AgentLoop,\n type AgentLoopStats,\n createAgentLoop,\n DEFAULT_AGENT_LOOP_MODEL,\n} from \"../actor/agent-loop.js\";\nimport type { Brain } from \"../actor/brain.js\";\nimport {\n type ComputerInterface,\n makeComputerInterface,\n} from \"../actor/computer-interface.js\";\nimport { dispatch } from \"../actor/dispatch.js\";\nimport {\n captureAllDisplays,\n type DisplayCapture,\n} from \"../platform/capture.js\";\nimport { listDisplays } from \"../platform/displays.js\";\nimport type { Scene } from \"../scene/scene-types.js\";\nimport type { ComputerUseService } from \"../services/computer-use-service.js\";\nimport { resolveActionParams } from \"./helpers.js\";\nimport {\n buildStepProgressContent,\n isStreamProgressEnabled,\n} from \"./progress.js\";\n\nconst DEFAULT_MAX_STEPS = 5;\n\nexport interface ComputerUseAgentParams {\n goal: string;\n maxSteps?: number;\n /**\n * When true, emit a chat message after each dispatched step so a long-running\n * goal does not leave the origin chat silent for minutes (#8912). The action\n * handler wires this to the runtime HandlerCallback; the loop itself calls\n * per-step progress hooks.\n */\n streamProgress?: boolean;\n /** Wall-clock budget (ms) — the loop aborts before a step that exceeds it. */\n maxDurationMs?: number;\n /**\n * Image-retention window (#9170 M11): keep only the N most-recent steps'\n * screenshots in the bounded history. Off (unbounded) when unset.\n */\n imageRetentionLast?: number;\n}\n\n/** One per-step progress event, surfaced when `streamProgress` is set. */\nexport interface ComputerUseAgentStepProgress {\n goal: string;\n step: number;\n maxSteps: number;\n sceneSummary: string;\n actionKind: string;\n rationale: string;\n rois: number;\n result: { success: boolean; error?: string };\n}\n\ninterface AgentDeps {\n brain?: Brain;\n /** Pre-built loop override (tests). Supersedes model-string selection. */\n loop?: AgentLoop;\n /** Loop model-string override (tests / explicit selection). */\n loopModel?: string;\n /**\n * Callback middleware override (#9170 M11). When set, replaces the default\n * pipeline (operator-normalizer + trajectory, plus budget/image-retention\n * when configured via params).\n */\n middleware?: AgentMiddleware[];\n /** Clock override (tests) — defaults to `Date.now`. */\n now?: () => number;\n computerInterface?: ComputerInterface;\n captureAll?: () => Promise<DisplayCapture[]>;\n /** Called after each dispatched step when `params.streamProgress` is set. */\n onStepProgress?: (\n progress: ComputerUseAgentStepProgress,\n ) => Promise<void> | void;\n /** Called with compact Content after each dispatched step when enabled. */\n onCompactStepProgress?: (content: Content) => Promise<void> | void;\n}\n\nexport interface ComputerUseAgentReport {\n goal: string;\n steps: Array<{\n step: number;\n sceneSummary: string;\n actionKind: string;\n rationale: string;\n rois: number;\n result: { success: boolean; error?: string };\n }>;\n finished: boolean;\n reason: \"finish\" | \"max_steps\" | \"error\" | \"budget\";\n error?: string;\n /** Per-step transcript recorded by the trajectory middleware (#9170 M11). */\n trajectory?: TrajectoryEntry[];\n /** Per-run model-call accounting, when the loop reports it (#9105). */\n modelStats?: AgentLoopStats;\n}\n\nexport function formatComputerUseAgentProgress(\n progress: ComputerUseAgentStepProgress,\n): string {\n const rationale = truncateForStatus(progress.rationale || \"no rationale\");\n const failure = progress.result.success\n ? \"\"\n : ` (failed: ${truncateForStatus(progress.result.error ?? \"unknown\")})`;\n return `Step ${progress.step}/${progress.maxSteps}: ${progress.actionKind} - ${rationale}${failure}`;\n}\n\nfunction getService(runtime: IAgentRuntime): ComputerUseService | null {\n return (runtime.getService(\"computeruse\") as ComputerUseService) ?? null;\n}\n\n/** Read the configured agent-loop model string (setting → env → null). */\nfunction resolveLoopModel(runtime: IAgentRuntime | null): string | null {\n const fromSetting = runtime?.getSetting?.(AGENT_LOOP_SETTING);\n if (typeof fromSetting === \"string\" && fromSetting.trim().length > 0) {\n return fromSetting.trim();\n }\n const fromEnv = process.env[AGENT_LOOP_SETTING];\n if (typeof fromEnv === \"string\" && fromEnv.trim().length > 0) {\n return fromEnv.trim();\n }\n return null;\n}\n\n/**\n * Run one Brain/Cascade/Dispatch loop. Exported so tests can drive it\n * without exercising the full Action plumbing.\n */\nexport async function runComputerUseAgentLoop(\n runtime: IAgentRuntime | null,\n params: ComputerUseAgentParams,\n service: ComputerUseService,\n deps: AgentDeps = {},\n): Promise<ComputerUseAgentReport> {\n const maxSteps = Math.max(\n 1,\n Math.min(params.maxSteps ?? DEFAULT_MAX_STEPS, 20),\n );\n const goal = params.goal;\n // Agent-loop registry (#9170 M10): a model string selects the loop. Defaults\n // to the local OCR/AX grounder (Brain → Cascade); provider plugins can\n // register Anthropic / OpenAI computer-use loops keyed by model family.\n const loopModel =\n deps.loopModel ?? resolveLoopModel(runtime) ?? DEFAULT_AGENT_LOOP_MODEL;\n const loop =\n deps.loop ??\n createAgentLoop(loopModel, {\n runtime,\n getScene: () => service.getCurrentScene(),\n brain: deps.brain,\n });\n const computer =\n deps.computerInterface ??\n makeComputerInterface({ getScene: () => service.getCurrentScene() });\n const captureAll = deps.captureAll ?? captureAllDisplays;\n const now = deps.now ?? Date.now;\n const runStart = now();\n\n // Callback middleware pipeline (#9170 M11). Default = operator-normalizer\n // (clean the planned action) + trajectory (in-memory transcript), plus\n // budget-cap / image-retention when configured via params.\n const trajectoryMw = createTrajectoryMiddleware();\n const middlewares: AgentMiddleware[] =\n deps.middleware ??\n (() => {\n const list: AgentMiddleware[] = [createOperatorNormalizerMiddleware()];\n if (params.maxDurationMs !== undefined) {\n list.unshift(\n createBudgetCapMiddleware({ maxDurationMs: params.maxDurationMs }),\n );\n }\n if (params.imageRetentionLast !== undefined) {\n list.push(\n createImageRetentionMiddleware({\n keepLast: params.imageRetentionLast,\n }),\n );\n }\n list.push(trajectoryMw);\n return list;\n })();\n\n const report: ComputerUseAgentReport = {\n goal,\n steps: [],\n finished: false,\n reason: \"max_steps\",\n };\n\n const finalize = async (): Promise<ComputerUseAgentReport> => {\n if (!deps.middleware) report.trajectory = trajectoryMw.entries();\n const stats = loop.getStats?.();\n if (stats) {\n report.modelStats = stats;\n logger.info(\n {\n evt: \"computeruse.agent.tokens\",\n goal,\n loop: loop.name,\n invocations: stats.invocations,\n cacheHits: stats.cacheHits,\n imagelessCalls: stats.imagelessCalls,\n estImageTokensSaved: stats.estImageTokensSaved,\n steps: report.steps.length,\n },\n `[computeruse/agent] ${stats.invocations} model call(s), ${stats.cacheHits} cache hit(s), ${stats.imagelessCalls} imageless (~${stats.estImageTokensSaved} image tokens saved) over ${report.steps.length} step(s)`,\n );\n }\n await runOnRunEnd(middlewares, {\n goal,\n steps: report.steps.length,\n finished: report.finished,\n reason: report.reason,\n });\n return report;\n };\n\n await runOnRunStart(middlewares, { goal, maxSteps });\n\n for (let step = 1; step <= maxSteps; step += 1) {\n const stepCtx = { step, maxSteps, goal, elapsedMs: now() - runStart };\n const decision = await runBeforeStep(middlewares, stepCtx);\n if (decision.abort) {\n report.reason = \"budget\";\n report.error = decision.reason;\n return finalize();\n }\n let scene: Scene;\n try {\n scene = await service.refreshScene(\"agent-turn\");\n } catch (err) {\n report.reason = \"error\";\n report.error = `scene refresh failed: ${errorMessage(err)}`;\n return finalize();\n }\n const captures = await safeCapture(captureAll);\n if (captures.size === 0) {\n report.reason = \"error\";\n report.error = \"no displays captured\";\n return finalize();\n }\n await runOnCaptures(middlewares, captures, stepCtx);\n let proposed: Awaited<ReturnType<typeof loop.predictStep>>;\n try {\n proposed = await loop.predictStep({ scene, goal, captures });\n } catch (err) {\n report.reason = \"error\";\n report.error = `agent loop \"${loop.name}\" failed: ${errorMessage(err)}`;\n return finalize();\n }\n // Operator-normalizer + any other transform middleware clean the planned\n // action before it is dispatched.\n proposed = await runTransformProposed(middlewares, proposed, stepCtx);\n // Persist the Brain's understanding onto the scene (#9105 M3) so the next\n // turn's `scene` provider carries `vlm_scene` instead of re-describing.\n service.setSceneVlmAnnotations(proposed.scene_summary, null);\n const dispatchResult = await dispatch(proposed.proposed, {\n interface: computer,\n listDisplays: () => service.getDisplays(),\n });\n await runAfterStep(middlewares, {\n step,\n goal,\n proposed,\n dispatchSuccess: dispatchResult.success,\n error: dispatchResult.error?.message,\n });\n logger.info(\n {\n evt: \"computeruse.agent.step\",\n step,\n goal,\n actionKind: proposed.proposed.kind,\n displayId: proposed.proposed.displayId,\n rois: proposed.rois.length,\n success: dispatchResult.success,\n error: dispatchResult.error?.code,\n rationale: proposed.proposed.rationale,\n },\n `[computeruse/agent] step ${step}: ${proposed.proposed.kind}`,\n );\n const reportStep = {\n step,\n sceneSummary: proposed.scene_summary,\n actionKind: proposed.proposed.kind,\n rationale: proposed.proposed.rationale,\n rois: proposed.rois.length,\n result: {\n success: dispatchResult.success,\n error: dispatchResult.error?.message,\n },\n };\n report.steps.push(reportStep);\n if (isStreamProgressEnabled(params.streamProgress)) {\n const progress: ComputerUseAgentStepProgress = {\n goal,\n maxSteps,\n ...reportStep,\n };\n await emitStepProgress(deps.onStepProgress, progress);\n await emitCompactStepProgress(deps.onCompactStepProgress, progress);\n }\n if (!dispatchResult.success) {\n report.reason = \"error\";\n report.error = dispatchResult.error?.message;\n return finalize();\n }\n if (proposed.proposed.kind === \"finish\") {\n report.finished = true;\n report.reason = \"finish\";\n return finalize();\n }\n if (proposed.proposed.kind === \"wait\") {\n }\n }\n return finalize();\n}\n\nasync function emitStepProgress(\n onStepProgress: AgentDeps[\"onStepProgress\"],\n progress: ComputerUseAgentStepProgress,\n): Promise<void> {\n if (!onStepProgress) {\n return;\n }\n try {\n await onStepProgress(progress);\n } catch (err) {\n logger.warn(\n {\n evt: \"computeruse.agent.progress_callback_failed\",\n step: progress.step,\n goal: progress.goal,\n error: errorMessage(err),\n },\n \"[computeruse/agent] progress callback failed\",\n );\n }\n}\n\nasync function emitCompactStepProgress(\n onCompactStepProgress: AgentDeps[\"onCompactStepProgress\"],\n progress: ComputerUseAgentStepProgress,\n): Promise<void> {\n if (!onCompactStepProgress) {\n return;\n }\n try {\n await onCompactStepProgress(\n buildStepProgressContent({\n actionName: \"COMPUTER_USE_AGENT\",\n step: progress.step,\n kind: progress.actionKind,\n rationale: progress.rationale,\n success: progress.result.success,\n error: progress.result.error,\n }),\n );\n } catch (err) {\n logger.warn(\n {\n evt: \"computeruse.agent.compact_progress_callback_failed\",\n step: progress.step,\n goal: progress.goal,\n error: errorMessage(err),\n },\n \"[computeruse/agent] compact progress callback failed\",\n );\n }\n}\n\nasync function safeCapture(\n captureAll: () => Promise<DisplayCapture[]>,\n): Promise<Map<number, DisplayCapture>> {\n const out = new Map<number, DisplayCapture>();\n try {\n const caps = await captureAll();\n for (const c of caps) out.set(c.display.id, c);\n } catch (err) {\n logger.warn(\n `[computeruse/agent] captureAll failed: ${errorMessage(err)} — falling back to per-display lookup`,\n );\n // listDisplays() is sync; we don't iterate here because the per-display\n // capture would also have failed. The empty map signals the caller.\n void listDisplays();\n }\n return out;\n}\n\nfunction errorMessage(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\nfunction truncateForStatus(value: string, maxLength = 180): string {\n const compact = value.replace(/\\s+/g, \" \").trim();\n if (compact.length <= maxLength) {\n return compact;\n }\n return `${compact.slice(0, maxLength - 3)}...`;\n}\n\nexport const computerUseAgentAction: Action = {\n name: \"COMPUTER_USE_AGENT\",\n contexts: [\"automation\", \"admin\"],\n contextGate: { anyOf: [\"automation\", \"admin\"] },\n roleGate: { minRole: \"OWNER\" },\n similes: [\"AUTOMATE_SCREEN\", \"RUN_COMPUTER_AGENT\", \"SCREEN_AGENT\"],\n description:\n \"computer_use_agent: autonomous desktop loop for a goal until done or maxSteps. Uses WS6 scene-builder, WS7 Brain+Actor cascade, WS5 multi-monitor coords. Prefer COMPUTER_USE for named single steps; use COMPUTER_USE_AGENT for goal-level screen tasks. Set streamProgress=true to send per-step progress updates to the originating chat.\",\n descriptionCompressed:\n \"Autonomous desktop loop: scene -> Brain -> cascade -> click. Pass {goal, maxSteps?, streamProgress?}.\",\n routingHint:\n \"free-form 'do X on screen' goal -> COMPUTER_USE_AGENT; single explicit step -> COMPUTER_USE\",\n parameters: [\n {\n name: \"goal\",\n description: \"Natural-language goal, e.g. click save button in dialog.\",\n required: true,\n schema: { type: \"string\" },\n },\n {\n name: \"maxSteps\",\n description: \"Max Brain->dispatch cycles before giving up. Default 5.\",\n required: false,\n schema: {\n type: \"number\",\n minimum: 1,\n maximum: 20,\n default: DEFAULT_MAX_STEPS,\n },\n },\n {\n name: \"streamProgress\",\n description:\n \"When true, emit a chat callback after each dispatched step with compact progress and the step kind/rationale.\",\n required: false,\n schema: { type: \"boolean\", default: false },\n },\n {\n name: \"maxDurationMs\",\n description:\n \"Wall-clock budget in ms; the loop aborts before a step that exceeds it.\",\n required: false,\n schema: { type: \"number\", minimum: 0 },\n },\n {\n name: \"imageRetentionLast\",\n description:\n \"Keep only the N most-recent steps' screenshots in the bounded history (token control).\",\n required: false,\n schema: { type: \"number\", minimum: 1 },\n },\n ],\n validate: async (runtime: IAgentRuntime): Promise<boolean> => {\n return getService(runtime) !== null;\n },\n handler: async (\n runtime: IAgentRuntime,\n message: Memory,\n _state?: State,\n options?: HandlerOptions,\n callback?: HandlerCallback,\n ): Promise<ActionResult> => {\n const params = resolveActionParams<ComputerUseAgentParams>(\n message,\n options,\n );\n if (!params.goal || typeof params.goal !== \"string\") {\n return {\n success: false,\n error: \"COMPUTER_USE_AGENT requires a goal string\",\n };\n }\n const service = getService(runtime);\n if (!service) {\n return {\n success: false,\n error: \"ComputerUseService not available\",\n };\n }\n const report = await runComputerUseAgentLoop(runtime, params, service, {\n onCompactStepProgress: callback\n ? async (content) => {\n await callback(content, \"COMPUTER_USE_AGENT\");\n }\n : undefined,\n });\n const text =\n report.reason === \"finish\"\n ? `Computer-use agent finished after ${report.steps.length} step(s): goal=\"${report.goal}\"`\n : report.reason === \"max_steps\"\n ? `Computer-use agent hit max steps (${report.steps.length})`\n : report.reason === \"budget\"\n ? `Computer-use agent stopped on budget after ${report.steps.length} step(s): ${report.error ?? \"budget exhausted\"}`\n : `Computer-use agent failed: ${report.error ?? \"unknown\"}`;\n if (callback) {\n await callback({ text });\n }\n return {\n success: report.reason === \"finish\",\n text,\n data: {\n source: \"computeruse\",\n computerUseAction: \"COMPUTER_USE_AGENT\",\n report,\n },\n };\n },\n examples: [\n [\n {\n name: \"{{name1}}\",\n content: {\n text: \"Click the save button in the dialog\",\n source: \"chat\",\n },\n },\n {\n name: \"{{agentName}}\",\n content: {\n text: \"Running the screen agent loop.\",\n actions: [\"COMPUTER_USE_AGENT\"],\n thought:\n \"Goal is described in free-form ('click the save button'); the agent loop will refresh the scene, reason over the captured frame, and dispatch a click on the matched OCR/AX target.\",\n },\n },\n ],\n ],\n};\n",
|
|
14
|
+
"/**\n * Agent-loop callback middleware (#9170 M11).\n *\n * trycua/cua threads a callback pipeline through its agent loop: budget caps,\n * image-retention (keep only the N most-recent screenshots in context),\n * operator-normalization (clean up the model's proposed action), and trajectory\n * recording. Each callback is a thin middleware that observes (and sometimes\n * transforms or aborts) the loop without the loop knowing which middlewares are\n * present.\n *\n * This module defines the `AgentMiddleware` hook set and four built-ins. The\n * runner (`use-computer-agent.ts`) fires the hooks at fixed points:\n * onRunStart → [ beforeStep → onCaptures → transformProposed → afterStep ]* →\n * onRunEnd\n *\n * Middlewares are pure-by-default and composable: `runBeforeStep`, etc.,\n * fold the list in order and short-circuit on the first abort.\n */\n\nimport { logger } from \"@elizaos/core\";\nimport type { DisplayCapture } from \"../platform/capture.js\";\nimport type { CascadeResult, ProposedAction } from \"./types.js\";\n\nexport interface AgentRunContext {\n goal: string;\n maxSteps: number;\n}\n\nexport interface AgentStepContext {\n step: number;\n maxSteps: number;\n goal: string;\n /** Wall-clock ms since the run started (set by the runner). */\n elapsedMs: number;\n}\n\nexport interface AgentDispatchContext {\n step: number;\n goal: string;\n proposed: CascadeResult;\n dispatchSuccess: boolean;\n error?: string;\n}\n\n/** Returned by `beforeStep` — abort halts the loop with `reason`. */\nexport interface AgentStepDecision {\n abort?: boolean;\n reason?: string;\n}\n\nexport interface AgentRunSummary {\n goal: string;\n steps: number;\n finished: boolean;\n reason: string;\n}\n\nexport interface AgentMiddleware {\n readonly name: string;\n onRunStart?(ctx: AgentRunContext): void | Promise<void>;\n /** Inspect/abort before a step runs (budget caps live here). */\n beforeStep?(\n ctx: AgentStepContext,\n ): AgentStepDecision | Promise<AgentStepDecision>;\n /** Observe the captured frames (image-retention bookkeeping). */\n onCaptures?(\n captures: Map<number, DisplayCapture>,\n ctx: AgentStepContext,\n ): void | Promise<void>;\n /** Transform the planned step before dispatch (operator-normalizer). */\n transformProposed?(\n proposed: CascadeResult,\n ctx: AgentStepContext,\n ): CascadeResult | Promise<CascadeResult>;\n /** Observe a dispatched step (trajectory recording). */\n afterStep?(ctx: AgentDispatchContext): void | Promise<void>;\n onRunEnd?(summary: AgentRunSummary): void | Promise<void>;\n}\n\n// ── Pipeline folds ───────────────────────────────────────────────────────────\n\nexport async function runOnRunStart(\n middlewares: readonly AgentMiddleware[],\n ctx: AgentRunContext,\n): Promise<void> {\n for (const m of middlewares) await m.onRunStart?.(ctx);\n}\n\n/** Fold `beforeStep`; the FIRST abort wins (and names the middleware). */\nexport async function runBeforeStep(\n middlewares: readonly AgentMiddleware[],\n ctx: AgentStepContext,\n): Promise<AgentStepDecision> {\n for (const m of middlewares) {\n const decision = await m.beforeStep?.(ctx);\n if (decision?.abort) {\n return {\n abort: true,\n reason: decision.reason ?? `aborted by ${m.name}`,\n };\n }\n }\n return { abort: false };\n}\n\nexport async function runOnCaptures(\n middlewares: readonly AgentMiddleware[],\n captures: Map<number, DisplayCapture>,\n ctx: AgentStepContext,\n): Promise<void> {\n for (const m of middlewares) await m.onCaptures?.(captures, ctx);\n}\n\n/** Fold `transformProposed` left-to-right; each sees the prior's output. */\nexport async function runTransformProposed(\n middlewares: readonly AgentMiddleware[],\n proposed: CascadeResult,\n ctx: AgentStepContext,\n): Promise<CascadeResult> {\n let current = proposed;\n for (const m of middlewares) {\n if (m.transformProposed) current = await m.transformProposed(current, ctx);\n }\n return current;\n}\n\nexport async function runAfterStep(\n middlewares: readonly AgentMiddleware[],\n ctx: AgentDispatchContext,\n): Promise<void> {\n for (const m of middlewares) await m.afterStep?.(ctx);\n}\n\nexport async function runOnRunEnd(\n middlewares: readonly AgentMiddleware[],\n summary: AgentRunSummary,\n): Promise<void> {\n for (const m of middlewares) await m.onRunEnd?.(summary);\n}\n\n// ── Built-in: budget cap ─────────────────────────────────────────────────────\n\nexport interface BudgetCapOptions {\n /** Abort once this many steps have STARTED (independent of the loop's own\n * maxSteps; use to cap below it, e.g. cost control). */\n maxSteps?: number;\n /** Abort once wall-clock elapsed exceeds this many ms. */\n maxDurationMs?: number;\n}\n\n/**\n * Halts the loop when a step or time budget is exhausted. Caps below the loop's\n * own `maxSteps`, and adds a wall-clock cap the loop has no notion of.\n */\nexport function createBudgetCapMiddleware(\n options: BudgetCapOptions,\n): AgentMiddleware {\n return {\n name: \"budget-cap\",\n beforeStep(ctx): AgentStepDecision {\n if (options.maxSteps !== undefined && ctx.step > options.maxSteps) {\n return {\n abort: true,\n reason: `step budget exhausted (${options.maxSteps})`,\n };\n }\n if (\n options.maxDurationMs !== undefined &&\n ctx.elapsedMs > options.maxDurationMs\n ) {\n return {\n abort: true,\n reason: `time budget exhausted (${options.maxDurationMs}ms)`,\n };\n }\n return { abort: false };\n },\n };\n}\n\n// ── Built-in: image retention (only-N-recent) ────────────────────────────────\n\nexport interface ImageRetentionMiddleware extends AgentMiddleware {\n /** The display-keyed captures retained from the most recent steps. */\n retained(): Array<{ step: number; displayIds: number[] }>;\n}\n\n/**\n * Bounds the screenshot history to the `keepLast` most-recent steps, mirroring\n * cua's image-retention (older frames fall out of context to cap token cost).\n * The runner forwards the per-step captures; this middleware keeps the bounded\n * window that a model-history consumer should send.\n */\nexport function createImageRetentionMiddleware(options: {\n keepLast: number;\n}): ImageRetentionMiddleware {\n const keepLast = Math.max(1, Math.floor(options.keepLast));\n const window: Array<{ step: number; displayIds: number[] }> = [];\n return {\n name: \"image-retention\",\n onCaptures(captures, ctx): void {\n window.push({ step: ctx.step, displayIds: [...captures.keys()] });\n while (window.length > keepLast) window.shift();\n },\n retained() {\n return window.map((w) => ({\n step: w.step,\n displayIds: [...w.displayIds],\n }));\n },\n };\n}\n\n// ── Built-in: operator normalizer ────────────────────────────────────────────\n\n/** Round a coordinate-like field to an integer when present. Pure. */\nfunction roundIfNumber(n: number | undefined): number | undefined {\n return typeof n === \"number\" && Number.isFinite(n) ? Math.round(n) : n;\n}\n\n/**\n * Normalize the model's proposed action into the canonical dispatch shape:\n * integer coordinates, trimmed type text, deduped/lowercased hotkey keys. Pure\n * and idempotent — re-normalizing already-clean input is a no-op.\n */\nexport function normalizeProposedAction(\n action: ProposedAction,\n): ProposedAction {\n const next: ProposedAction = { ...action };\n next.x = roundIfNumber(next.x);\n next.y = roundIfNumber(next.y);\n next.startX = roundIfNumber(next.startX);\n next.startY = roundIfNumber(next.startY);\n next.dx = roundIfNumber(next.dx);\n next.dy = roundIfNumber(next.dy);\n if (typeof next.text === \"string\")\n next.text = next.text.replace(/\\r\\n/g, \"\\n\");\n if (Array.isArray(next.keys)) {\n const seen = new Set<string>();\n next.keys = next.keys\n .map((k) => k.trim())\n .filter((k) => k.length > 0 && !seen.has(k) && seen.add(k));\n }\n return next;\n}\n\n/** Operator-normalizer middleware — cleans `proposed.proposed` before dispatch. */\nexport function createOperatorNormalizerMiddleware(): AgentMiddleware {\n return {\n name: \"operator-normalizer\",\n transformProposed(proposed): CascadeResult {\n return {\n ...proposed,\n proposed: normalizeProposedAction(proposed.proposed),\n };\n },\n };\n}\n\n// ── Built-in: trajectory recorder ────────────────────────────────────────────\n\nexport interface TrajectoryEntry {\n step: number;\n goal: string;\n actionKind: string;\n rationale: string;\n success: boolean;\n error?: string;\n}\n\nexport interface TrajectoryMiddleware extends AgentMiddleware {\n /** The recorded trajectory so far. */\n entries(): TrajectoryEntry[];\n}\n\n/**\n * Records one entry per dispatched step. Independent of the existing\n * `logger.info` trajectory events — this gives an in-memory transcript the\n * caller can attach to the run report or persist.\n */\nexport function createTrajectoryMiddleware(options?: {\n /** Also emit a debug log line per step. Default false. */\n log?: boolean;\n}): TrajectoryMiddleware {\n const recorded: TrajectoryEntry[] = [];\n return {\n name: \"trajectory\",\n afterStep(ctx): void {\n const entry: TrajectoryEntry = {\n step: ctx.step,\n goal: ctx.goal,\n actionKind: ctx.proposed.proposed.kind,\n rationale: ctx.proposed.proposed.rationale,\n success: ctx.dispatchSuccess,\n ...(ctx.error ? { error: ctx.error } : {}),\n };\n recorded.push(entry);\n if (options?.log) {\n logger.debug(\n `[computeruse/agent] trajectory step ${entry.step}: ${entry.actionKind} (${entry.success ? \"ok\" : \"fail\"})`,\n );\n }\n },\n entries() {\n return recorded.map((e) => ({ ...e }));\n },\n };\n}\n",
|
|
15
|
+
"/**\n * WS7 — Actor (optional fine-grained grounding).\n *\n * The Actor is responsible for converting a Brain-issued reference\n * (\"click the Save button I see in this crop\") into concrete display-local\n * pixel coords.\n *\n * Primary path — deterministic (no model):\n * `OcrCoordinateGroundingActor` resolves a `ref: \"t<displayId>-<seq>\"`\n * (OCR id) or `ref: \"a<displayId>-<seq>\"` (AX id) directly from the\n * Scene. Click point is bbox-center. No VLM call, fully reproducible,\n * what 99% of the cascade should use.\n *\n * Optional secondary path — VLM:\n * `OsAtlasProActor` is a typed adapter for an operator-provided model-server\n * endpoint (e.g. an OS-Atlas-Pro vLLM service). Unless a deployment\n * registers that endpoint, the cascade uses the OCR/AX grounding above.\n *\n * Register the active Actor on the cascade via `setActor(actor)` (see\n * `cascade.ts`). If none is registered, the cascade uses the OCR/AX actor\n * automatically.\n */\n\nimport type { Scene, SceneAxNode, SceneOcrBox } from \"../scene/scene-types.js\";\nimport type { GroundingResult, ReferenceTarget } from \"./types.js\";\n\nexport interface ActorGroundArgs {\n /** Display the Brain wants to act on. */\n displayId: number;\n /**\n * Cropped image of the ROI at native resolution (PNG bytes). May be a\n * empty Buffer when the deterministic grounding doesn't need image bytes.\n */\n croppedImage: Buffer;\n /** Hint from the Brain: \"the Save button in the dialog footer\". */\n hint: string;\n /** Optional reference from `BrainProposedAction.ref`. */\n ref?: string;\n}\n\nexport interface Actor {\n readonly name: string;\n ground(args: ActorGroundArgs): Promise<GroundingResult>;\n}\n\n/* ── deterministic OCR/AX grounding (primary) ──────────────────────────── */\n\nexport class OcrCoordinateGroundingActor implements Actor {\n readonly name = \"ocr-ax-grounding\";\n\n constructor(private readonly getScene: () => Scene | null) {}\n\n async ground(args: ActorGroundArgs): Promise<GroundingResult> {\n const scene = this.getScene();\n if (!scene) {\n throw new Error(\n `[computeruse/actor] cannot ground without a current scene (ref=${args.ref ?? \"?\"})`,\n );\n }\n const target = resolveReference(scene, args.ref, args.hint, args.displayId);\n if (!target) {\n throw new Error(\n `[computeruse/actor] no OCR/AX target matched ref=${args.ref ?? \"?\"} hint=${JSON.stringify(args.hint)} on display ${args.displayId}`,\n );\n }\n const [x, y, w, h] = target.bbox;\n return {\n displayId: target.displayId,\n x: Math.round(x + w / 2),\n y: Math.round(y + h / 2),\n confidence: 1,\n reason: `Matched ${target.kind} id=${describe(target)} bbox=[${x},${y},${w},${h}]`,\n };\n }\n}\n\n/**\n * Look up a scene element by stable id, OR by case-insensitive label match\n * when an id is absent. Used by both the deterministic actor and the cascade\n * dispatcher to validate Brain output.\n */\nexport function resolveReference(\n scene: Scene,\n ref: string | undefined,\n hint: string,\n preferredDisplay: number,\n): ReferenceTarget | null {\n if (ref) {\n // OCR id format: t<displayId>-<seq>\n const ocrMatch = scene.ocr.find((b) => b.id === ref);\n if (ocrMatch) return toOcrTarget(ocrMatch);\n // AX id format: a<displayId>-<seq>\n const axMatch = scene.ax.find((n) => n.id === ref);\n if (axMatch) return toAxTarget(axMatch);\n }\n // Fall back to hint-based label match. Prefer the requested display.\n const lc = hint.trim().toLowerCase();\n if (lc.length === 0) return null;\n const ocrCandidates = scene.ocr\n .filter((b) => b.text.toLowerCase().includes(lc))\n .sort(\n (a, b) =>\n preferenceScore(b, preferredDisplay) -\n preferenceScore(a, preferredDisplay),\n );\n const bestOcr = ocrCandidates[0];\n if (bestOcr) return toOcrTarget(bestOcr);\n const axCandidates = scene.ax\n .filter((n) => (n.label ?? \"\").toLowerCase().includes(lc))\n .sort(\n (a, b) =>\n preferenceScoreAx(b, preferredDisplay) -\n preferenceScoreAx(a, preferredDisplay),\n );\n const bestAx = axCandidates[0];\n if (bestAx) return toAxTarget(bestAx);\n return null;\n}\n\nfunction toOcrTarget(box: SceneOcrBox): ReferenceTarget {\n return {\n displayId: box.displayId,\n bbox: box.bbox,\n kind: \"ocr\",\n label: box.text,\n source: box,\n };\n}\n\nfunction toAxTarget(node: SceneAxNode): ReferenceTarget {\n return {\n displayId: node.displayId,\n bbox: node.bbox,\n kind: \"ax\",\n label: node.label ?? node.role,\n source: node,\n };\n}\n\nfunction preferenceScore(box: SceneOcrBox, preferredDisplay: number): number {\n return (box.displayId === preferredDisplay ? 1000 : 0) + box.conf;\n}\n\nfunction preferenceScoreAx(\n node: SceneAxNode,\n preferredDisplay: number,\n): number {\n const area = (node.bbox[2] ?? 0) * (node.bbox[3] ?? 0);\n return (node.displayId === preferredDisplay ? 1_000_000 : 0) + area;\n}\n\nfunction describe(target: ReferenceTarget): string {\n return target.kind === \"ocr\"\n ? (target.source as SceneOcrBox).id\n : (target.source as SceneAxNode).id;\n}\n\n/* ── optional VLM adapter ──────────────────────────────────────────────── */\n\nexport interface OsAtlasProActorOptions {\n /** Endpoint of the model server, e.g. `http://localhost:8000/v1`. */\n endpoint: string;\n /** Optional auth header. */\n apiKey?: string;\n /** Model identifier on the server. */\n model?: string;\n /** Override the HTTP fetch (mostly for tests). */\n fetcher?: (\n input: string,\n init: { body: string; headers: Record<string, string> },\n ) => Promise<{ ok: boolean; status: number; text: () => Promise<string> }>;\n}\n\n/**\n * Adapter for a server-side OS-Atlas-Pro (or compatible) grounding model.\n * Not wired into the cascade by default. The contract: POST a JSON payload\n * with `{ image: base64, hint }`, expect `{ x, y, confidence }` in image\n * coordinates of the crop. The cascade is responsible for converting those\n * crop-local coords back to display-local before dispatch.\n */\nexport class OsAtlasProActor implements Actor {\n readonly name = \"osatlas-pro\";\n\n constructor(private readonly opts: OsAtlasProActorOptions) {\n if (!opts.endpoint) {\n throw new Error(\n \"[computeruse/actor] OsAtlasProActor requires an endpoint\",\n );\n }\n }\n\n async ground(args: ActorGroundArgs): Promise<GroundingResult> {\n const body = JSON.stringify({\n image: args.croppedImage.toString(\"base64\"),\n hint: args.hint,\n ref: args.ref,\n model: this.opts.model,\n });\n const headers: Record<string, string> = {\n \"content-type\": \"application/json\",\n };\n if (this.opts.apiKey) headers.authorization = `Bearer ${this.opts.apiKey}`;\n const fetcher =\n this.opts.fetcher ??\n (async (url, init) => {\n const resp = await fetch(url, {\n method: \"POST\",\n body: init.body,\n headers: init.headers,\n });\n return { ok: resp.ok, status: resp.status, text: () => resp.text() };\n });\n const resp = await fetcher(this.opts.endpoint, { body, headers });\n if (!resp.ok) {\n throw new Error(\n `[computeruse/actor] osatlas-pro returned ${resp.status}: ${await resp.text()}`,\n );\n }\n const text = await resp.text();\n let parsed: { x?: number; y?: number; confidence?: number };\n try {\n parsed = JSON.parse(text) as typeof parsed;\n } catch (err) {\n throw new Error(\n `[computeruse/actor] osatlas-pro emitted non-JSON: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n if (typeof parsed.x !== \"number\" || typeof parsed.y !== \"number\") {\n throw new Error(\n `[computeruse/actor] osatlas-pro response missing (x, y): ${text}`,\n );\n }\n return {\n displayId: args.displayId,\n x: parsed.x,\n y: parsed.y,\n confidence:\n typeof parsed.confidence === \"number\" ? parsed.confidence : 0.5,\n reason: `osatlas-pro grounded ${args.ref ?? args.hint}`,\n };\n }\n}\n",
|
|
16
|
+
"/**\n * WS7 — Brain (full-screen reasoning).\n *\n * Sends one image per display (each downscaled to ~1.3 MP, the OS-Atlas /\n * Qwen3-VL `max_pixels` convention) to `runtime.useModel(IMAGE_DESCRIPTION,\n * ...)`. The model is prompted to emit a JSON `BrainOutput` describing:\n * - the scene in one paragraph,\n * - which display to act on,\n * - up to N ROIs the Actor should zoom into,\n * - a single proposed action with rationale.\n *\n * The Brain itself doesn't dispatch — it just produces `BrainOutput`. The\n * cascade (\"ScreenSeekeR\") is the orchestrator that takes a `BrainOutput`,\n * optionally calls the Actor on cropped ROIs, and produces a concrete\n * `ProposedAction` for the dispatcher.\n *\n * Image transport contract: we pass `imageUrl` as a `data:image/png;base64,...`\n * URL. The WS2 MemoryArbiter intercepts at `ModelType.IMAGE_DESCRIPTION` and\n * routes through its content-hash cache, so identical frames don't burn\n * inference budget twice.\n *\n * Image policy (#9105): the compact scene already carries OCR text + AX boxes,\n * which can suffice to pick the next target, so the `\"on-escalation\"` policy\n * plans from that text-only context with NO image — routed through a TEXT model,\n * since every IMAGE_DESCRIPTION provider rejects an empty imageUrl — and\n * attaches the ~1.3 MP frame only when the planned target cannot be grounded\n * against the OCR/AX boxes. The DEFAULT is `\"always\"` (legacy: image on every\n * call) until a real-model CUA trajectory validates imageless planning accuracy;\n * operators opt into `\"on-escalation\"` via the `COMPUTERUSE_BRAIN_IMAGE_POLICY`\n * setting. `\"never\"` never attaches pixels.\n *\n * Parse strictness:\n * - We try to parse the response as JSON (either the literal string or\n * `result.description`).\n * - On first parse failure, retry once with a stricter prompt.\n * - On second failure, throw `BrainParseError` — the cascade surfaces this\n * as a structured `ActionResult.error` and aborts the turn cleanly.\n */\n\nimport {\n type IAgentRuntime,\n type ImageDescriptionResult,\n logger,\n ModelType,\n} from \"@elizaos/core\";\nimport type { DisplayCapture } from \"../platform/capture.js\";\nimport { frameDhash, hamming, pngDimensions } from \"../scene/dhash.js\";\nimport type { Scene } from \"../scene/scene-types.js\";\nimport { serializeSceneForPrompt } from \"../scene/serialize.js\";\nimport { resolveReference } from \"./actor.js\";\nimport type { BrainOutput, BrainProposedAction, BrainRoi } from \"./types.js\";\n\nexport const BRAIN_MAX_PIXELS = 1_310_720; // 1280 * 32 * 32 ≈ 1.3 MP cap\nexport const BRAIN_MAX_ROIS = 2;\n/** Bound on the per-Brain dHash→BrainOutput cache (LRU-ish, oldest evicted). */\nexport const BRAIN_DHASH_CACHE_MAX = 16;\n/**\n * dHash Hamming threshold for cached-plan reuse (#9581 continuous-understanding\n * tuning). Exact-equality (distance 0) re-burned the IMAGE_DESCRIPTION model on\n * cosmetically-identical frames — cursor jitter, a blinking caret, anti-aliasing,\n * and tiny scroll noise all flip a few dHash bits.\n *\n * This mirrors `SCREEN_STATE_HAMMING_THRESHOLD`: distances below the threshold\n * are unchanged; distances at or above it are changed and must re-plan.\n */\nexport const BRAIN_DHASH_HAMMING_THRESHOLD = 5;\n/**\n * Image-token estimate per source pixel for a vision model with the Qwen3-VL /\n * OS-Atlas `max_pixels` convention: one visual token ≈ a 28×28 (≈750 px) patch.\n * Used only to quantify the saving when a frame is *not* attached (#9105).\n */\nexport const BRAIN_PIXELS_PER_IMAGE_TOKEN = 750;\n\n/**\n * When to attach the raw screenshot to the planning model (#9105):\n * - `\"always\"` — attach the pixels on every call (legacy behaviour). Default.\n * - `\"on-escalation\"` — plan from the compact OCR/AX scene with no image\n * first (routed through a TEXT model); attach pixels\n * only when the planned target cannot be grounded\n * against the OCR/AX boxes or a strict-retry fires.\n * - `\"never\"` — never attach the screenshot; plan from the scene alone.\n */\nexport type BrainImagePolicy = \"always\" | \"on-escalation\" | \"never\";\n\n/**\n * Default is `\"always\"` (proven legacy behaviour). `\"on-escalation\"` cuts the\n * dominant per-frame image-token cost but plans the first pass blind to the\n * pixels, so it stays opt-in (via the `COMPUTERUSE_BRAIN_IMAGE_POLICY` runtime\n * setting / env var) until a real-model CUA trajectory validates its accuracy.\n */\nexport const DEFAULT_BRAIN_IMAGE_POLICY: BrainImagePolicy = \"always\";\n\n/**\n * Resolve the Brain image policy from the `COMPUTERUSE_BRAIN_IMAGE_POLICY`\n * runtime setting / env var, falling back to {@link DEFAULT_BRAIN_IMAGE_POLICY}.\n * The operator escape hatch to enable imageless planning without a code change\n * once it is validated against a real model.\n */\nexport function resolveBrainImagePolicy(\n runtime: IAgentRuntime | null,\n): BrainImagePolicy {\n const raw = runtime?.getSetting?.(\"COMPUTERUSE_BRAIN_IMAGE_POLICY\");\n const value = typeof raw === \"string\" ? raw.trim().toLowerCase() : undefined;\n if (value === \"always\" || value === \"on-escalation\" || value === \"never\") {\n return value;\n }\n return DEFAULT_BRAIN_IMAGE_POLICY;\n}\n\n/** Token-accounting snapshot for a Brain instance (#9105 M3). */\nexport interface BrainStats {\n /** IMAGE_DESCRIPTION model calls actually issued. */\n invocations: number;\n /** Describe calls served from the frame-dHash cache (no model call). */\n cacheHits: number;\n /**\n * Model calls issued with NO screenshot attached (the scene's OCR/AX text\n * sufficed). Each one saved roughly one full-frame image's worth of tokens.\n */\n imagelessCalls: number;\n /**\n * Estimated image tokens NOT sent because of imageless calls — the sum of\n * `(width * height) / BRAIN_PIXELS_PER_IMAGE_TOKEN` over every imageless\n * call, capped per frame at `BRAIN_MAX_PIXELS`.\n */\n estImageTokensSaved: number;\n}\n\n/**\n * Action kinds whose dispatch needs a grounded display-local coordinate. For\n * these, an imageless plan is only safe when its `ref`/rationale resolves to an\n * OCR/AX box; otherwise the Brain escalates to the pixels. The remaining kinds\n * (type/hotkey/key/wait/finish) carry everything in their args.\n */\nconst COORDINATE_ACTION_KINDS: ReadonlySet<BrainProposedAction[\"kind\"]> =\n new Set([\"click\", \"double_click\", \"right_click\", \"scroll\", \"drag\"]);\n\nfunction sceneCacheSignature(scene: Scene): string {\n return JSON.stringify({\n displays: scene.displays.map((display) => ({\n id: display.id,\n name: display.name,\n bounds: display.bounds,\n primary: display.primary,\n scaleFactor: display.scaleFactor,\n })),\n focused_window: scene.focused_window,\n apps: scene.apps.map((app) => ({\n name: app.name,\n pid: app.pid,\n windows: app.windows.map((window) => ({\n id: window.id,\n title: window.title,\n bounds: window.bounds,\n displayId: window.displayId,\n })),\n })),\n ocr: scene.ocr.map((box) => ({\n id: box.id,\n text: box.text,\n bbox: box.bbox,\n conf: Number(box.conf.toFixed(3)),\n displayId: box.displayId,\n })),\n ax: scene.ax.map((node) => ({\n id: node.id,\n role: node.role,\n label: node.label,\n bbox: node.bbox,\n actions: node.actions,\n displayId: node.displayId,\n })),\n vlm_scene: scene.vlm_scene,\n vlm_elements: scene.vlm_elements,\n });\n}\n\nexport class BrainParseError extends Error {\n constructor(\n message: string,\n public readonly raw: string,\n ) {\n super(message);\n this.name = \"BrainParseError\";\n }\n}\n\nexport interface BrainDeps {\n /** Optional override for tests — bypasses runtime.useModel. */\n invokeModel?: (args: {\n imageUrl: string;\n prompt: string;\n displayId: number;\n }) => Promise<string | ImageDescriptionResult>;\n /**\n * When to attach the raw screenshot to the planning model (#9105). Defaults\n * to `\"always\"` (legacy); see {@link resolveBrainImagePolicy} for the\n * operator opt-in to `\"on-escalation\"`.\n */\n imagePolicy?: BrainImagePolicy;\n}\n\nexport interface BrainInput {\n scene: Scene;\n goal: string;\n /**\n * Per-display capture buffers. If a display from `scene.displays` is\n * missing here, the Brain skips it. The cascade is responsible for\n * supplying these alongside the scene.\n */\n captures: Map<number, DisplayCapture>;\n}\n\n/**\n * Pure description of a \"Brain\" call. Created by `Cascade.runCascade` and\n * test fixtures.\n */\nexport class Brain {\n /**\n * Frame-dHash → BrainOutput cache. The WS2 MemoryArbiter only dedups the\n * IMAGE_DESCRIPTION call for LOCAL backends; the remote/cloud path bypasses\n * it, so an identical screen re-burns tokens every step. This call-site cache\n * skips the model entirely when the same frame is observed for the same goal,\n * cutting the dominant CUA-loop token cost regardless of backend (#9105 M3).\n */\n private readonly dhashCache: Array<{\n dh: bigint;\n goal: string;\n sceneSignature: string;\n output: BrainOutput;\n }> = [];\n private readonly imagePolicy: BrainImagePolicy;\n private invocations = 0;\n private cacheHits = 0;\n private imagelessCalls = 0;\n private estImageTokensSaved = 0;\n\n constructor(\n private readonly runtime: IAgentRuntime | null,\n private readonly deps: BrainDeps = {},\n ) {\n this.imagePolicy = deps.imagePolicy ?? DEFAULT_BRAIN_IMAGE_POLICY;\n }\n\n /** Token-accounting snapshot (model calls, cache hits, imageless savings). */\n getStats(): BrainStats {\n return {\n invocations: this.invocations,\n cacheHits: this.cacheHits,\n imagelessCalls: this.imagelessCalls,\n estImageTokensSaved: this.estImageTokensSaved,\n };\n }\n\n private cacheKey(\n frame: Buffer,\n goal: string,\n sceneSignature: string,\n ): { dh: bigint; goal: string; sceneSignature: string } | null {\n const dh = frameDhash(frame);\n return dh === null ? null : { dh, goal, sceneSignature };\n }\n\n /**\n * Return a cached plan for the same goal whose frame is within\n * `BRAIN_DHASH_HAMMING_THRESHOLD` bits of `dh` — a near-identical screen, not\n * just a byte-identical one. On a hit the entry is moved to the end (LRU), so\n * a steadily-evolving screen keeps its most-recent close match warm.\n */\n private findCached(\n dh: bigint,\n goal: string,\n sceneSignature: string,\n ): BrainOutput | null {\n for (let i = this.dhashCache.length - 1; i >= 0; i--) {\n const entry = this.dhashCache[i]!;\n if (\n entry.goal === goal &&\n entry.sceneSignature === sceneSignature &&\n hamming(entry.dh, dh) < BRAIN_DHASH_HAMMING_THRESHOLD\n ) {\n this.dhashCache.splice(i, 1);\n this.dhashCache.push(entry);\n return entry.output;\n }\n }\n return null;\n }\n\n private rememberOutput(\n key: { dh: bigint; goal: string; sceneSignature: string } | null,\n output: BrainOutput,\n ): BrainOutput {\n if (key) {\n // Evict oldest to bound memory.\n if (this.dhashCache.length >= BRAIN_DHASH_CACHE_MAX) {\n this.dhashCache.shift();\n }\n this.dhashCache.push({\n dh: key.dh,\n goal: key.goal,\n sceneSignature: key.sceneSignature,\n output,\n });\n }\n return output;\n }\n\n async observeAndPlan(input: BrainInput): Promise<BrainOutput> {\n if (input.captures.size === 0) {\n throw new Error(\"[computeruse/brain] no captures supplied\");\n }\n const compactScene = serializeSceneForPrompt(input.scene);\n const primaryDisplay =\n input.scene.focused_window?.displayId ??\n input.scene.displays.find((d) => d.primary)?.id ??\n input.scene.displays[0]?.id ??\n 0;\n const targetCapture =\n input.captures.get(primaryDisplay) ??\n input.captures.values().next().value;\n if (!targetCapture) {\n throw new Error(\"[computeruse/brain] could not pick a target capture\");\n }\n\n // Frame-dHash cache: a near-identical screen + same goal → reuse the prior\n // plan, skip the (possibly remote) IMAGE_DESCRIPTION call. Tolerant to a few\n // dHash bits so cosmetic churn (cursor, caret, anti-aliasing) still hits.\n const sceneSignature = sceneCacheSignature(input.scene);\n const key = this.cacheKey(\n targetCapture.frame,\n input.goal,\n sceneSignature,\n );\n if (key) {\n const cached = this.findCached(key.dh, key.goal, key.sceneSignature);\n if (cached) {\n this.cacheHits += 1;\n return cached;\n }\n }\n\n const displayId = targetCapture.display.id;\n const tryParse = (raw: string): BrainOutput | null => {\n try {\n return parseBrainOutput(raw);\n } catch {\n return null;\n }\n };\n const lightPrompt = brainPromptFor(\n compactScene,\n input.goal,\n /*strict*/ false,\n );\n const strictPrompt = brainPromptFor(\n compactScene,\n input.goal,\n /*strict*/ true,\n );\n\n // ── Pass 1: plan from the compact OCR/AX scene with NO image, unless the\n // policy demands the pixels up front (#9105). The compact scene already\n // carries the OCR text + AX boxes the planner needs to pick a target.\n if (this.imagePolicy !== \"always\") {\n this.invocations += 1;\n let imageless: string | ImageDescriptionResult | null = null;\n try {\n imageless = await this.invoke({\n imageUrl: \"\",\n prompt: lightPrompt,\n displayId,\n });\n } catch (err) {\n // \"never\" has no pixels to fall back to — surface the failure.\n if (this.imagePolicy === \"never\") throw err;\n // Otherwise degrade to the escalation (pixels) path rather than crash\n // the whole CUA loop if the text model is unavailable.\n logger.debug(\n `[computeruse/brain] imageless planning pass failed (${\n err instanceof Error ? err.message : String(err)\n }); escalating to pixels`,\n );\n }\n if (imageless !== null) {\n const parsedImageless = tryParse(extractText(imageless));\n if (parsedImageless) {\n const capped = enforceCaps(parsedImageless);\n // Keep the imageless plan when its target is grounded against the\n // OCR/AX boxes (or it needs no coordinate at all), OR when the policy\n // forbids ever attaching pixels. Otherwise fall through to escalation.\n if (\n this.imagePolicy === \"never\" ||\n this.resolvesWithoutImage(input.scene, capped)\n ) {\n this.recordImageless(targetCapture.frame);\n return this.rememberOutput(key, capped);\n }\n } else if (this.imagePolicy === \"never\") {\n // No pixels available to escalate to — strict-retry imageless once.\n this.invocations += 1;\n const strictImageless = await this.invoke({\n imageUrl: \"\",\n prompt: strictPrompt,\n displayId,\n });\n const rawStrict = extractText(strictImageless);\n const parsedStrict = tryParse(rawStrict);\n if (parsedStrict) {\n this.recordImageless(targetCapture.frame);\n return this.rememberOutput(key, enforceCaps(parsedStrict));\n }\n throw new BrainParseError(\n \"Brain output is not valid JSON conforming to BrainOutput after retry\",\n rawStrict,\n );\n }\n }\n }\n\n // ── Escalation: attach the pixels. Either policy === \"always\", or the\n // imageless plan could not be grounded / parsed. The existing encode +\n // strict-retry path runs from here unchanged.\n const dataUrl = await encodeForBrain(targetCapture.frame);\n this.invocations += 1;\n const first = await this.invoke({\n imageUrl: dataUrl,\n prompt: lightPrompt,\n displayId,\n });\n const parsed = tryParse(extractText(first));\n if (parsed) return this.rememberOutput(key, enforceCaps(parsed));\n // Strict retry — same image, stricter prompt.\n this.invocations += 1;\n const second = await this.invoke({\n imageUrl: dataUrl,\n prompt: strictPrompt,\n displayId,\n });\n const rawSecond = extractText(second);\n const parsedRetry = tryParse(rawSecond);\n if (parsedRetry) return this.rememberOutput(key, enforceCaps(parsedRetry));\n throw new BrainParseError(\n \"Brain output is not valid JSON conforming to BrainOutput after retry\",\n rawSecond,\n );\n }\n\n /**\n * True when the imageless plan needs no screenshot to dispatch: a\n * non-coordinate action (type/hotkey/key/wait/finish) carries everything in\n * its args, and a coordinate action is fine when its `ref`/rationale resolves\n * to a concrete OCR/AX box. When the target cannot be grounded we escalate to\n * the pixels — correctness over token saving.\n */\n private resolvesWithoutImage(scene: Scene, output: BrainOutput): boolean {\n const action: BrainProposedAction = output.proposed_action;\n if (!COORDINATE_ACTION_KINDS.has(action.kind)) return true;\n return (\n resolveReference(\n scene,\n action.ref,\n action.rationale,\n output.target_display_id,\n ) !== null\n );\n }\n\n private recordImageless(frame: Buffer): void {\n this.imagelessCalls += 1;\n this.estImageTokensSaved += estimateImageTokens(frame);\n }\n\n private async invoke(args: {\n imageUrl: string;\n prompt: string;\n displayId: number;\n }): Promise<string | ImageDescriptionResult> {\n if (this.deps.invokeModel) {\n return this.deps.invokeModel(args);\n }\n if (!this.runtime) {\n throw new Error(\n \"[computeruse/brain] no runtime + no invokeModel override; cannot call the planning model\",\n );\n }\n // Imageless planning (#9105): with no pixels to describe, route the\n // text-only plan through a TEXT model. The compact OCR/AX scene is already\n // in the prompt, and every IMAGE_DESCRIPTION provider (local-inference,\n // anthropic, …) hard-rejects an empty imageUrl, so an empty frame must NOT\n // be sent there.\n if (args.imageUrl.length === 0) {\n return this.runtime.useModel(ModelType.TEXT_LARGE, {\n prompt: args.prompt,\n });\n }\n return this.runtime.useModel(ModelType.IMAGE_DESCRIPTION, {\n imageUrl: args.imageUrl,\n prompt: args.prompt,\n });\n }\n}\n\n/* ── prompt + parser ───────────────────────────────────────────────────── */\n\nexport function brainPromptFor(\n compactSceneJson: string,\n goal: string,\n strict: boolean,\n): string {\n const header = strict\n ? \"You are the planning Brain inside an autonomous desktop agent. You MUST emit ONLY a JSON object — no prose, no markdown fence — matching the BrainOutput schema. Do not include any text before or after the JSON.\"\n : \"You are the planning Brain inside an autonomous desktop agent. Decide the single next action that makes the most progress toward the goal.\";\n return [\n header,\n \"\",\n `Goal: ${goal}`,\n \"\",\n \"Current scene context (display-local coords):\",\n compactSceneJson,\n \"\",\n \"Schema:\",\n \"{\",\n ' \"scene_summary\": \"one short paragraph\",',\n ' \"target_display_id\": number,',\n ' \"roi\": [',\n ' { \"displayId\": number, \"bbox\": [x, y, w, h], \"reason\": \"why\" }',\n \" ],\",\n ' \"proposed_action\": {',\n ' \"kind\": \"click|double_click|right_click|type|hotkey|key|scroll|drag|wait|finish\",',\n ' \"ref\": \"t<displayId>-<seq> or a<displayId>-<seq> (optional)\",',\n ' \"args\": { ... action-specific keys ... },',\n ' \"rationale\": \"why this action\"',\n \" }\",\n \"}\",\n \"\",\n `Cap ROIs to ${BRAIN_MAX_ROIS}. Use action kind \"finish\" when the goal is already accomplished, \"wait\" when the screen is mid-transition.`,\n strict\n ? \"Return raw JSON. No fences, no commentary, no extra fields.\"\n : \"Output JSON only (a single object). Markdown fences are optional but will be stripped.\",\n ].join(\"\\n\");\n}\n\nconst FENCE_RE = /```(?:json)?\\s*([\\s\\S]*?)\\s*```/i;\n\nexport function parseBrainOutput(raw: string): BrainOutput {\n const trimmed = raw.trim();\n let body = trimmed;\n const fenceMatch = FENCE_RE.exec(trimmed);\n if (fenceMatch) {\n const fencedBody = fenceMatch[1];\n if (fencedBody === undefined) {\n throw new BrainParseError(\"Brain response markdown fence was empty\", raw);\n }\n body = fencedBody.trim();\n }\n // Allow a leading prose paragraph by snipping to the first `{`.\n const firstBrace = body.indexOf(\"{\");\n if (firstBrace > 0) body = body.slice(firstBrace);\n const lastBrace = body.lastIndexOf(\"}\");\n if (lastBrace !== -1 && lastBrace < body.length - 1) {\n body = body.slice(0, lastBrace + 1);\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(body);\n } catch (err) {\n throw new BrainParseError(\n `Brain response was not valid JSON: ${err instanceof Error ? err.message : String(err)}`,\n raw,\n );\n }\n if (!parsed || typeof parsed !== \"object\") {\n throw new BrainParseError(\"Brain response is not an object\", raw);\n }\n const obj = parsed as Record<string, unknown>;\n const summary =\n typeof obj.scene_summary === \"string\" ? obj.scene_summary : \"\";\n const targetDisplay =\n typeof obj.target_display_id === \"number\" ? obj.target_display_id : 0;\n const rois = Array.isArray(obj.roi) ? obj.roi : [];\n const proposed = (obj.proposed_action ?? null) as Record<\n string,\n unknown\n > | null;\n if (!proposed || typeof proposed !== \"object\") {\n throw new BrainParseError(\"Brain response missing proposed_action\", raw);\n }\n const kind = proposed.kind;\n if (typeof kind !== \"string\") {\n throw new BrainParseError(\n \"proposed_action.kind missing or not a string\",\n raw,\n );\n }\n const rationale =\n typeof proposed.rationale === \"string\" ? proposed.rationale : \"\";\n const ref = typeof proposed.ref === \"string\" ? proposed.ref : undefined;\n const args =\n proposed.args && typeof proposed.args === \"object\"\n ? (proposed.args as Record<string, unknown>)\n : undefined;\n const validated: BrainOutput = {\n scene_summary: summary,\n target_display_id: targetDisplay,\n roi: rois\n .map((r): BrainRoi | null => {\n if (!r || typeof r !== \"object\") return null;\n const ro = r as Record<string, unknown>;\n const bb = ro.bbox;\n if (!Array.isArray(bb) || bb.length !== 4) return null;\n const nums = bb.map((n) => Number(n));\n if (!nums.every((n) => Number.isFinite(n))) return null;\n const [x, y, width, height] = nums;\n if (\n x === undefined ||\n y === undefined ||\n width === undefined ||\n height === undefined\n ) {\n return null;\n }\n return {\n displayId:\n typeof ro.displayId === \"number\" ? ro.displayId : targetDisplay,\n bbox: [x, y, width, height],\n reason: typeof ro.reason === \"string\" ? ro.reason : \"\",\n };\n })\n .filter((x): x is BrainRoi => x !== null),\n proposed_action: {\n kind: kind as BrainOutput[\"proposed_action\"][\"kind\"],\n ref,\n args,\n rationale,\n },\n };\n return validated;\n}\n\nfunction enforceCaps(out: BrainOutput): BrainOutput {\n if (out.roi.length > BRAIN_MAX_ROIS) {\n out.roi = out.roi.slice(0, BRAIN_MAX_ROIS);\n }\n return out;\n}\n\nfunction extractText(value: string | ImageDescriptionResult): string {\n if (typeof value === \"string\") return value;\n if (value && typeof value === \"object\") {\n if (typeof value.description === \"string\") return value.description;\n if (typeof value.title === \"string\") return value.title;\n }\n return String(value);\n}\n\n/**\n * Encode a PNG buffer for transport to the IMAGE_DESCRIPTION model. We don't\n * resize here — `runtime.useModel` adapters (and any vLLM backends behind\n * them) handle the `max_pixels` downscale. The constant `BRAIN_MAX_PIXELS`\n * is exported for the cascade so it can crop ROIs at the right native\n * resolution before invoking the Actor.\n */\nexport async function encodeForBrain(png: Buffer): Promise<string> {\n return `data:image/png;base64,${png.toString(\"base64\")}`;\n}\n\n/**\n * Estimate the visual tokens a frame would have cost the planning model, for\n * the \"tokens saved by going imageless\" telemetry (#9105). The backends apply a\n * `max_pixels` downscale, so the per-frame estimate is capped at\n * `BRAIN_MAX_PIXELS`. Falls back to the cap when the PNG header is unreadable —\n * an attached frame would have been downscaled to that ceiling regardless.\n */\nexport function estimateImageTokens(png: Buffer): number {\n const dims = pngDimensions(png);\n const pixels = dims\n ? Math.min(dims.width * dims.height, BRAIN_MAX_PIXELS)\n : BRAIN_MAX_PIXELS;\n return Math.round(pixels / BRAIN_PIXELS_PER_IMAGE_TOKEN);\n}\n",
|
|
17
|
+
"/**\n * Difference-hash (dHash) implementation for cheap frame-level and\n * block-level change detection in the WS6 scene-builder.\n *\n * Why dHash:\n * - 64-bit integer, hammable in two cycles, vastly cheaper than a structural\n * similarity index.\n * - Robust to small re-encodings (cursor jitter, anti-alias seams) which\n * dominate \"no change\" frames in a real session.\n * - Tunable: we run an 8×8 whole-frame hash for the cheap \"did anything\n * happen?\" gate, and a 16×16 block grid (each block ~128×128 of source)\n * for dirty-block re-OCR.\n *\n * Implementation notes:\n * - The PNG decoder here is intentionally minimal — it handles the formats\n * produced by every screenshot path we ship (color type 2 = RGB, 6 =\n * RGBA, 8-bit depth, non-interlaced). Anything else returns `null` and\n * the caller falls back to a coarser whole-frame byte hash.\n * - Pure functions, no I/O. Safe to test deterministically.\n *\n * Block-grid contract:\n * - The image is gridded into N×N blocks (default 16) covering the whole\n * frame; remainder pixels go to the right/bottom edges.\n * - Each block gets its own 8-bit \"mini-hash\" derived from row-wise grayscale\n * differences sampled at four points per block. Two blocks compare equal\n * iff their hashes match. This is intentionally a much coarser test than\n * a full per-block dHash — the goal is just \"did this region change at\n * all?\" not \"how similar.\"\n */\n\nimport { inflateSync } from \"node:zlib\";\n\nconst PNG_SIGNATURE = Buffer.from([\n 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a,\n]);\n\nexport interface RawImage {\n width: number;\n height: number;\n /** RGBA scanline data, row-major, 4 bytes/pixel, length = width*height*4. */\n rgba: Buffer;\n}\n\n/**\n * Decode a PNG buffer to RGBA. Returns null for unsupported variants\n * (interlaced, palette-indexed, 16-bit depth) — caller handles that by\n * falling back to a non-block-grid hash strategy.\n */\nexport function decodePng(png: Buffer): RawImage | null {\n if (png.length < PNG_SIGNATURE.length) return null;\n for (let i = 0; i < PNG_SIGNATURE.length; i += 1) {\n if (png[i] !== PNG_SIGNATURE[i]) return null;\n }\n let offset = PNG_SIGNATURE.length;\n let width = 0;\n let height = 0;\n let bitDepth = 0;\n let colorType = 0;\n let interlace = 0;\n const idatChunks: Buffer[] = [];\n\n while (offset + 8 <= png.length) {\n const length = png.readUInt32BE(offset);\n const type = png.subarray(offset + 4, offset + 8).toString(\"ascii\");\n const dataStart = offset + 8;\n const dataEnd = dataStart + length;\n if (dataEnd > png.length) return null;\n if (type === \"IHDR\") {\n if (length < 13) return null;\n width = png.readUInt32BE(dataStart);\n height = png.readUInt32BE(dataStart + 4);\n bitDepth = png[dataStart + 8] ?? 0;\n colorType = png[dataStart + 9] ?? 0;\n interlace = png[dataStart + 12] ?? 0;\n } else if (type === \"IDAT\") {\n idatChunks.push(png.subarray(dataStart, dataEnd));\n } else if (type === \"IEND\") {\n break;\n }\n offset = dataEnd + 4; // skip CRC\n }\n\n if (width === 0 || height === 0) return null;\n if (bitDepth !== 8) return null;\n if (interlace !== 0) return null;\n if (colorType !== 2 && colorType !== 6) return null;\n if (idatChunks.length === 0) return null;\n\n const inflated = inflateSync(Buffer.concat(idatChunks));\n const bytesPerPixel = colorType === 6 ? 4 : 3;\n const stride = width * bytesPerPixel;\n const expected = (stride + 1) * height;\n if (inflated.length < expected) return null;\n\n const rgba = Buffer.alloc(width * height * 4);\n const prevRow = Buffer.alloc(stride);\n const curRow = Buffer.alloc(stride);\n\n for (let y = 0; y < height; y += 1) {\n const rowStart = y * (stride + 1);\n const filter = inflated[rowStart] ?? 0;\n const src = inflated.subarray(rowStart + 1, rowStart + 1 + stride);\n applyPngFilter(filter, src, prevRow, curRow, bytesPerPixel);\n const dstRowStart = y * width * 4;\n for (let x = 0; x < width; x += 1) {\n const sx = x * bytesPerPixel;\n const dx = dstRowStart + x * 4;\n rgba[dx] = curRow[sx] ?? 0;\n rgba[dx + 1] = curRow[sx + 1] ?? 0;\n rgba[dx + 2] = curRow[sx + 2] ?? 0;\n rgba[dx + 3] = bytesPerPixel === 4 ? (curRow[sx + 3] ?? 255) : 255;\n }\n curRow.copy(prevRow);\n }\n return { width, height, rgba };\n}\n\nfunction applyPngFilter(\n filter: number,\n src: Buffer,\n prev: Buffer,\n out: Buffer,\n bpp: number,\n): void {\n const len = src.length;\n for (let i = 0; i < len; i += 1) {\n const raw = src[i] ?? 0;\n const left = i >= bpp ? (out[i - bpp] ?? 0) : 0;\n const up = prev[i] ?? 0;\n const upLeft = i >= bpp ? (prev[i - bpp] ?? 0) : 0;\n let recon = 0;\n switch (filter) {\n case 0:\n recon = raw;\n break;\n case 1:\n recon = raw + left;\n break;\n case 2:\n recon = raw + up;\n break;\n case 3:\n recon = raw + ((left + up) >>> 1);\n break;\n case 4:\n recon = raw + paeth(left, up, upLeft);\n break;\n default:\n recon = raw;\n }\n out[i] = recon & 0xff;\n }\n}\n\nfunction paeth(a: number, b: number, c: number): number {\n const p = a + b - c;\n const pa = Math.abs(p - a);\n const pb = Math.abs(p - b);\n const pc = Math.abs(p - c);\n if (pa <= pb && pa <= pc) return a;\n if (pb <= pc) return b;\n return c;\n}\n\n/**\n * Compute a luminance value (0..255) for an RGBA pixel using\n * Rec. 601 coefficients.\n */\nfunction luminance(r: number, g: number, b: number): number {\n return (0.299 * r + 0.587 * g + 0.114 * b) | 0;\n}\n\n/**\n * Resample the image to a (cols+1) × rows grayscale grid using nearest-\n * neighbor sampling, then compare horizontal neighbors to form a (cols*rows)\n * bit hash. With cols=8, rows=8 this is the classic 64-bit dHash.\n */\nfunction dhashGrid(image: RawImage, cols: number, rows: number): bigint {\n const { width, height, rgba } = image;\n const samples = new Uint8Array((cols + 1) * rows);\n for (let y = 0; y < rows; y += 1) {\n const sy = Math.min(height - 1, Math.floor((y * height) / rows));\n for (let x = 0; x <= cols; x += 1) {\n const sx = Math.min(width - 1, Math.floor((x * width) / (cols + 1)));\n const idx = (sy * width + sx) * 4;\n samples[y * (cols + 1) + x] = luminance(\n rgba[idx] ?? 0,\n rgba[idx + 1] ?? 0,\n rgba[idx + 2] ?? 0,\n );\n }\n }\n let hash = 0n;\n for (let y = 0; y < rows; y += 1) {\n for (let x = 0; x < cols; x += 1) {\n const a = samples[y * (cols + 1) + x] ?? 0;\n const b = samples[y * (cols + 1) + x + 1] ?? 0;\n hash = (hash << 1n) | (a > b ? 1n : 0n);\n }\n }\n return hash;\n}\n\n/**\n * 64-bit dHash of the whole frame. Returns `null` if the PNG can't be\n * decoded; callers fall back to a byte-length comparison.\n */\nexport function frameDhash(png: Buffer): bigint | null {\n const decoded = decodePng(png);\n if (!decoded) return null;\n return dhashGrid(decoded, 8, 8);\n}\n\n/**\n * Hamming distance between two 64-bit dHashes. Two visually identical frames\n * report 0. We treat anything < 5 as \"no change\" for the idle gate.\n */\nexport function hamming(a: bigint, b: bigint): number {\n let x = a ^ b;\n let count = 0;\n while (x !== 0n) {\n x &= x - 1n;\n count += 1;\n }\n return count;\n}\n\nexport interface BlockGrid {\n /** Cols × Rows block-hash matrix. Index by `row * cols + col`. */\n hashes: Uint32Array;\n cols: number;\n rows: number;\n}\n\n/**\n * Split a frame into a `cols x rows` grid and return a tiny per-block hash.\n *\n * We don't use a full dHash per block — instead we sample 4 luminance points\n * per block and pack a 16-bit fingerprint. That's enough to spot \"this block\n * changed\" with very few false-negatives in practice, and stays cheap when\n * called every active-poll frame (4 Hz).\n */\nexport function blockGrid(png: Buffer, cols = 16, rows = 16): BlockGrid | null {\n const decoded = decodePng(png);\n if (!decoded) return null;\n return blockGridFromImage(decoded, cols, rows);\n}\n\nexport function blockGridFromImage(\n image: RawImage,\n cols = 16,\n rows = 16,\n): BlockGrid {\n const { width, height, rgba } = image;\n const hashes = new Uint32Array(cols * rows);\n for (let r = 0; r < rows; r += 1) {\n for (let c = 0; c < cols; c += 1) {\n const x0 = Math.floor((c * width) / cols);\n const x1 = Math.floor(((c + 1) * width) / cols);\n const y0 = Math.floor((r * height) / rows);\n const y1 = Math.floor(((r + 1) * height) / rows);\n const w = Math.max(1, x1 - x0);\n const h = Math.max(1, y1 - y0);\n // Four sample points: tl, tr, bl, br of the block interior.\n const samples = [\n sample(rgba, width, x0, y0),\n sample(rgba, width, x0 + w - 1, y0),\n sample(rgba, width, x0, y0 + h - 1),\n sample(rgba, width, x0 + w - 1, y0 + h - 1),\n ];\n // Pack four luminance values into 32 bits.\n const v0 = (samples[0] ?? 0) & 0xff;\n const v1 = (samples[1] ?? 0) & 0xff;\n const v2 = (samples[2] ?? 0) & 0xff;\n const v3 = (samples[3] ?? 0) & 0xff;\n hashes[r * cols + c] = ((v0 << 24) | (v1 << 16) | (v2 << 8) | v3) >>> 0;\n }\n }\n return { hashes, cols, rows };\n}\n\nfunction sample(rgba: Buffer, width: number, x: number, y: number): number {\n const idx = (y * width + x) * 4;\n return luminance(rgba[idx] ?? 0, rgba[idx + 1] ?? 0, rgba[idx + 2] ?? 0);\n}\n\nexport interface DirtyBlock {\n col: number;\n row: number;\n /** Pixel-space bbox `[x, y, w, h]` of this block in the source frame. */\n bbox: [number, number, number, number];\n}\n\n/**\n * Return the list of blocks whose hash changed between two grids.\n *\n * If `prev` is null (first frame) every block is dirty.\n * If `imageWidth/Height` are passed, the result includes a pixel-space bbox\n * for each dirty block so the caller can crop the source PNG to re-OCR only\n * the changed regions.\n */\nexport function diffBlocks(\n prev: BlockGrid | null,\n current: BlockGrid,\n imageWidth?: number,\n imageHeight?: number,\n): DirtyBlock[] {\n const dirty: DirtyBlock[] = [];\n const { cols, rows } = current;\n for (let r = 0; r < rows; r += 1) {\n for (let c = 0; c < cols; c += 1) {\n const i = r * cols + c;\n const same =\n prev !== null && prev.cols === cols && prev.rows === rows\n ? prev.hashes[i] === current.hashes[i]\n : false;\n if (same) continue;\n const bbox: [number, number, number, number] =\n imageWidth !== undefined && imageHeight !== undefined\n ? [\n Math.floor((c * imageWidth) / cols),\n Math.floor((r * imageHeight) / rows),\n Math.max(\n 1,\n Math.floor(((c + 1) * imageWidth) / cols) -\n Math.floor((c * imageWidth) / cols),\n ),\n Math.max(\n 1,\n Math.floor(((r + 1) * imageHeight) / rows) -\n Math.floor((r * imageHeight) / rows),\n ),\n ]\n : [c, r, 1, 1];\n dirty.push({ col: c, row: r, bbox });\n }\n }\n return dirty;\n}\n\n/**\n * Coalesce a list of dirty blocks into axis-aligned rectangles using a row-\n * sweep merge. Adjacent dirty blocks in the same row collapse into a single\n * horizontal strip, then strips in successive rows that fully overlap collapse\n * vertically. This keeps the OS region-capture count tiny in the common case\n * where a single text field or a banner area changes (1 region, not 12).\n *\n * Returns the rectangles in display-local pixel space when `imageWidth` /\n * `imageHeight` are provided; otherwise in `col, row, colspan, rowspan`\n * units (1,1,1,1 = a single block at grid position 0,0).\n */\nexport function coalesceDirtyBlocks(\n dirty: DirtyBlock[],\n grid: BlockGrid,\n imageWidth?: number,\n imageHeight?: number,\n): Array<{ bbox: [number, number, number, number] }> {\n if (dirty.length === 0) return [];\n // Build a sparse occupied set keyed by `${row}:${col}`.\n const occupied = new Set<string>();\n for (const b of dirty) occupied.add(`${b.row}:${b.col}`);\n\n // Row-sweep: merge horizontal runs first.\n const strips: Array<{ row: number; col0: number; col1: number }> = [];\n for (let r = 0; r < grid.rows; r += 1) {\n let c = 0;\n while (c < grid.cols) {\n if (!occupied.has(`${r}:${c}`)) {\n c += 1;\n continue;\n }\n let c1 = c;\n while (c1 + 1 < grid.cols && occupied.has(`${r}:${c1 + 1}`)) c1 += 1;\n strips.push({ row: r, col0: c, col1: c1 });\n c = c1 + 1;\n }\n }\n\n // Merge strips that share identical col extents in successive rows.\n const merged: Array<{\n row0: number;\n row1: number;\n col0: number;\n col1: number;\n }> = [];\n for (const strip of strips) {\n const last = merged[merged.length - 1];\n if (\n last &&\n last.col0 === strip.col0 &&\n last.col1 === strip.col1 &&\n last.row1 + 1 === strip.row\n ) {\n last.row1 = strip.row;\n continue;\n }\n merged.push({\n row0: strip.row,\n row1: strip.row,\n col0: strip.col0,\n col1: strip.col1,\n });\n }\n\n return merged.map(({ row0, row1, col0, col1 }) => {\n if (imageWidth !== undefined && imageHeight !== undefined) {\n const x0 = Math.floor((col0 * imageWidth) / grid.cols);\n const y0 = Math.floor((row0 * imageHeight) / grid.rows);\n const x1 = Math.floor(((col1 + 1) * imageWidth) / grid.cols);\n const y1 = Math.floor(((row1 + 1) * imageHeight) / grid.rows);\n return {\n bbox: [x0, y0, Math.max(1, x1 - x0), Math.max(1, y1 - y0)] as [\n number,\n number,\n number,\n number,\n ],\n };\n }\n return {\n bbox: [col0, row0, col1 - col0 + 1, row1 - row0 + 1] as [\n number,\n number,\n number,\n number,\n ],\n };\n });\n}\n\n/**\n * Read PNG dimensions without inflating IDAT. Cheap — only the IHDR chunk is\n * touched. Returns null if the buffer isn't a recognizable PNG.\n */\nexport function pngDimensions(\n png: Buffer,\n): { width: number; height: number } | null {\n if (png.length < PNG_SIGNATURE.length + 8 + 13) return null;\n for (let i = 0; i < PNG_SIGNATURE.length; i += 1) {\n if (png[i] !== PNG_SIGNATURE[i]) return null;\n }\n // IHDR follows immediately after the signature: length(4) + \"IHDR\"(4) + width(4) + height(4) + ...\n const ihdrStart = PNG_SIGNATURE.length + 4;\n if (png.subarray(ihdrStart, ihdrStart + 4).toString(\"ascii\") !== \"IHDR\")\n return null;\n const width = png.readUInt32BE(ihdrStart + 4);\n const height = png.readUInt32BE(ihdrStart + 8);\n if (\n !Number.isFinite(width) ||\n !Number.isFinite(height) ||\n width <= 0 ||\n height <= 0\n ) {\n return null;\n }\n return { width, height };\n}\n",
|
|
18
|
+
"/**\n * Token-efficient Scene serializer.\n *\n * Used by the `scene` provider to render the current Scene into the agent\n * prompt. We deliberately cap lists by display so a 4k-monitor session\n * doesn't push the prompt to thousands of tokens:\n *\n * - displays : full list (small)\n * - focused_window : full (small)\n * - apps : pid, name, window count, top-2 window titles\n * - ocr : top-N most-confident lines per display\n * (default N = 24, configurable)\n * - ax : limited to the focused window's display subtree\n * (default cap = 24)\n * - vlm_scene / elements : passed through verbatim\n *\n * The output is fenced JSON for predictable downstream tokenization.\n */\n\nimport type { Scene } from \"./scene-types.js\";\n\nexport interface SerializeOptions {\n ocrTopN?: number;\n axMax?: number;\n appTopWindows?: number;\n /** Cap total apps emitted. Prefers apps with at least one visible window. */\n appMax?: number;\n}\n\nexport function serializeSceneForPrompt(\n scene: Scene,\n options: SerializeOptions = {},\n): string {\n const ocrTopN = options.ocrTopN ?? 24;\n const axMax = options.axMax ?? 24;\n const appTopWindows = options.appTopWindows ?? 2;\n const appMax = options.appMax ?? 32;\n\n // OCR: per-display, sorted by descending confidence, capped.\n const ocrByDisplay = new Map<number, typeof scene.ocr>();\n for (const box of scene.ocr) {\n const arr = ocrByDisplay.get(box.displayId) ?? [];\n arr.push(box);\n ocrByDisplay.set(box.displayId, arr);\n }\n const trimmedOcr: typeof scene.ocr = [];\n for (const [, arr] of ocrByDisplay) {\n arr.sort((a, b) => b.conf - a.conf);\n trimmedOcr.push(...arr.slice(0, ocrTopN));\n }\n\n // AX: prefer focused-window display subtree.\n const focusedDisplay =\n scene.focused_window?.displayId ?? scene.displays[0]?.id ?? 0;\n const focusedAx = scene.ax.filter((n) => n.displayId === focusedDisplay);\n const remaining = scene.ax.filter((n) => n.displayId !== focusedDisplay);\n const trimmedAx = [...focusedAx, ...remaining].slice(0, axMax);\n\n // Prefer apps with visible windows — those are the ones the planner can\n // act on. Background-only processes get clipped to keep the prompt\n // tractable on Linux hosts with 500+ processes.\n const appsByPriority = [...scene.apps].sort((a, b) => {\n const aw = a.windows.length;\n const bw = b.windows.length;\n if (aw !== bw) return bw - aw;\n return a.name.localeCompare(b.name);\n });\n const trimmedApps = appsByPriority.slice(0, appMax);\n const compactApps = trimmedApps.map((app) => ({\n name: app.name,\n pid: app.pid,\n window_count: app.windows.length,\n windows: app.windows.slice(0, appTopWindows).map((w) => ({\n id: w.id,\n title: w.title,\n displayId: w.displayId,\n })),\n }));\n\n const compact = {\n timestamp: scene.timestamp,\n displays: scene.displays.map((d) => ({\n id: d.id,\n name: d.name,\n bounds: d.bounds,\n primary: d.primary,\n scaleFactor: d.scaleFactor,\n })),\n focused_window: scene.focused_window,\n apps: compactApps,\n ocr: trimmedOcr.map((b) => ({\n id: b.id,\n text: b.text,\n bbox: b.bbox,\n conf: Number(b.conf.toFixed(3)),\n displayId: b.displayId,\n })),\n ax: trimmedAx.map((n) => ({\n id: n.id,\n role: n.role,\n label: n.label,\n bbox: n.bbox,\n actions: n.actions,\n displayId: n.displayId,\n })),\n vlm_scene: scene.vlm_scene,\n vlm_elements: scene.vlm_elements,\n truncation: {\n ocr_total: scene.ocr.length,\n ocr_kept: trimmedOcr.length,\n ax_total: scene.ax.length,\n ax_kept: trimmedAx.length,\n apps_total: scene.apps.length,\n apps_kept: trimmedApps.length,\n },\n };\n return [\"```json\", JSON.stringify(compact, null, 2), \"```\"].join(\"\\n\");\n}\n",
|
|
19
|
+
"/**\n * WS7 — ScreenSeekeR cascade.\n *\n * Step 1: Brain looks at the full-screen scene for `target_display_id`.\n * Step 2: For each ROI (up to BRAIN_MAX_ROIS), crop the *native resolution*\n * region from the captured PNG and hand it to the Actor for\n * fine grounding. The Actor returns display-local coords.\n * Step 3: Combine the Brain's proposed action with the Actor's coordinates\n * (or fall back to the OCR/AX deterministic actor on `ref`) and\n * produce a single `ProposedAction` for the dispatcher.\n *\n * Cropping notes:\n * - We do NOT decode the PNG. The cropped buffer is what we hand to the\n * Actor. For the built-in OCR/AX actor, the crop is just a pass-through.\n * - When a real PNG cropper is wired in (sharp / native module), this\n * module is the place to add it: `cropPngToRoi(frame, bbox)`.\n * - The cascade tests use the actual frame bytes; assertions are on the\n * resolved coords and the order of Actor calls.\n */\n\nimport { logger } from \"@elizaos/core\";\nimport type { DisplayCapture } from \"../platform/capture.js\";\nimport type { Scene } from \"../scene/scene-types.js\";\nimport type { Actor, ActorGroundArgs } from \"./actor.js\";\nimport { resolveReference } from \"./actor.js\";\nimport { BRAIN_MAX_ROIS, type Brain } from \"./brain.js\";\nimport type {\n BrainOutput,\n BrainRoi,\n CascadeResult,\n ProposedAction,\n} from \"./types.js\";\n\nexport interface CascadeDeps {\n brain: Brain;\n actor?: Actor | null;\n /** Cropper override (mostly tests). Returns a Buffer for the bbox region. */\n crop?: (frame: Buffer, bbox: [number, number, number, number]) => Buffer;\n}\n\nexport interface CascadeInput {\n scene: Scene;\n goal: string;\n /** Per-display PNG captures, keyed by displayId. */\n captures: Map<number, DisplayCapture>;\n}\n\n/** Grounding-cache accounting (#9105 M5). */\nexport interface CascadeGroundStats {\n /** Grounding resolutions served from the per-Scene cache. */\n hits: number;\n /** Grounding resolutions that ran the full resolve (OCR/AX + optional actor). */\n misses: number;\n}\n\nexport class Cascade {\n /**\n * Per-Scene grounding cache (predict/ground split, #9105 M5). Grounding the\n * same target (ref or rationale) on the same Scene is deterministic, so the\n * cheap GROUND step is memoized — re-grounding within a turn skips a repeat\n * `resolveReference` (OCR/AX) scan and a repeat (possibly model-backed)\n * `actor.ground` call. Keyed by Scene timestamp so a new screen invalidates.\n */\n private readonly groundCache = new Map<\n string,\n { displayId: number; x: number; y: number }\n >();\n private groundStats: CascadeGroundStats = { hits: 0, misses: 0 };\n\n constructor(private readonly deps: CascadeDeps) {}\n\n /** Grounding cache hit/miss snapshot for token/work accounting. */\n getGroundStats(): CascadeGroundStats {\n return { ...this.groundStats };\n }\n\n async run(input: CascadeInput): Promise<CascadeResult> {\n const brainOut = await this.deps.brain.observeAndPlan({\n scene: input.scene,\n goal: input.goal,\n captures: input.captures,\n });\n return this.resolveBrainOutput(input, brainOut);\n }\n\n /**\n * Grounding-only entry (the `predict_click` half of the predict/ground split,\n * #9105 M5 / #9170 M10). Resolves a `ref` (OCR/AX id) or free-form\n * `instruction` to a display-local coordinate WITHOUT running the Brain —\n * agent loops that do their own step planning (Anthropic / OpenAI\n * computer-use) call this to reuse our deterministic OCR/AX + actor grounding\n * and its per-Scene cache. Returns `null` when nothing can be grounded.\n */\n async groundTarget(args: {\n scene: Scene;\n captures: Map<number, DisplayCapture>;\n targetDisplayId: number;\n ref?: string;\n instruction?: string;\n /** Optional ROI to ground inside when no `ref` is available. */\n roi?: BrainRoi;\n }): Promise<{ displayId: number; x: number; y: number } | null> {\n const brainOut: BrainOutput = {\n scene_summary: \"\",\n target_display_id: args.targetDisplayId,\n roi: args.roi ? [args.roi] : [],\n proposed_action: {\n kind: \"click\",\n ref: args.ref,\n rationale: args.instruction ?? \"\",\n },\n };\n return this.resolveCoords(\n {\n scene: args.scene,\n goal: args.instruction ?? \"\",\n captures: args.captures,\n },\n brainOut,\n /*allowMissing*/ true,\n );\n }\n\n private async resolveBrainOutput(\n input: CascadeInput,\n brainOut: BrainOutput,\n ): Promise<CascadeResult> {\n const action = brainOut.proposed_action;\n const targetDisplay = brainOut.target_display_id;\n\n // Non-coordinate actions short-circuit grounding.\n if (action.kind === \"wait\" || action.kind === \"finish\") {\n return {\n scene_summary: brainOut.scene_summary,\n rois: brainOut.roi.slice(0, BRAIN_MAX_ROIS),\n proposed: {\n kind: action.kind,\n displayId: targetDisplay,\n rationale: action.rationale,\n ref: action.ref,\n },\n };\n }\n if (action.kind === \"type\") {\n const text = stringOrUndef(action.args?.text);\n if (typeof text !== \"string\") {\n throw new Error(\n `[computeruse/cascade] proposed_action.kind=\"type\" requires args.text`,\n );\n }\n return {\n scene_summary: brainOut.scene_summary,\n rois: brainOut.roi.slice(0, BRAIN_MAX_ROIS),\n proposed: {\n kind: \"type\",\n displayId: targetDisplay,\n text,\n rationale: action.rationale,\n },\n };\n }\n if (action.kind === \"hotkey\") {\n const keys = action.args?.keys;\n if (!Array.isArray(keys) || keys.some((k) => typeof k !== \"string\")) {\n throw new Error(\n `[computeruse/cascade] proposed_action.kind=\"hotkey\" requires args.keys: string[]`,\n );\n }\n return {\n scene_summary: brainOut.scene_summary,\n rois: brainOut.roi.slice(0, BRAIN_MAX_ROIS),\n proposed: {\n kind: \"hotkey\",\n displayId: targetDisplay,\n keys: keys as string[],\n rationale: action.rationale,\n },\n };\n }\n if (action.kind === \"key\") {\n const key = stringOrUndef(action.args?.key);\n if (typeof key !== \"string\") {\n throw new Error(\n `[computeruse/cascade] proposed_action.kind=\"key\" requires args.key`,\n );\n }\n return {\n scene_summary: brainOut.scene_summary,\n rois: brainOut.roi.slice(0, BRAIN_MAX_ROIS),\n proposed: {\n kind: \"key\",\n displayId: targetDisplay,\n key,\n rationale: action.rationale,\n },\n };\n }\n if (action.kind === \"scroll\") {\n const dx = Number(action.args?.dx ?? 0);\n const dy = Number(action.args?.dy ?? 0);\n // Anchor scroll on the ROI if present, else display center.\n const anchor = await this.resolveCoords(\n input,\n brainOut,\n /*allowMissing*/ true,\n );\n const display = input.scene.displays.find((d) => d.id === targetDisplay);\n const cx = anchor?.x ?? Math.round((display?.bounds[2] ?? 0) / 2);\n const cy = anchor?.y ?? Math.round((display?.bounds[3] ?? 0) / 2);\n return {\n scene_summary: brainOut.scene_summary,\n rois: brainOut.roi.slice(0, BRAIN_MAX_ROIS),\n proposed: {\n kind: \"scroll\",\n displayId: targetDisplay,\n x: cx,\n y: cy,\n dx,\n dy,\n rationale: action.rationale,\n },\n };\n }\n if (action.kind === \"drag\") {\n const from = action.args?.from as { x?: number; y?: number } | undefined;\n const to = action.args?.to as { x?: number; y?: number } | undefined;\n const start =\n (await this.coordsForRef(input, brainOut, action.ref, /*from*/ true)) ??\n from;\n const end = (await this.resolveCoords(input, brainOut, false)) ?? to;\n if (\n !start ||\n !end ||\n typeof start.x !== \"number\" ||\n typeof end.x !== \"number\"\n ) {\n throw new Error(\n `[computeruse/cascade] drag requires args.from and args.to (or a ref + endpoint)`,\n );\n }\n return {\n scene_summary: brainOut.scene_summary,\n rois: brainOut.roi.slice(0, BRAIN_MAX_ROIS),\n proposed: {\n kind: \"drag\",\n displayId: targetDisplay,\n startX: Math.round(start.x),\n startY: Math.round(start.y ?? 0),\n x: Math.round(end.x),\n y: Math.round(end.y ?? 0),\n rationale: action.rationale,\n },\n };\n }\n // click / double_click / right_click — all need a single point.\n const coords = await this.resolveCoords(input, brainOut, false);\n if (!coords) {\n throw new Error(\n `[computeruse/cascade] could not resolve coordinates for action.kind=\"${action.kind}\"`,\n );\n }\n return {\n scene_summary: brainOut.scene_summary,\n rois: brainOut.roi.slice(0, BRAIN_MAX_ROIS),\n proposed: {\n kind: action.kind,\n displayId: coords.displayId,\n x: coords.x,\n y: coords.y,\n ref: action.ref,\n rationale: action.rationale,\n },\n };\n }\n\n private async resolveCoords(\n input: CascadeInput,\n brainOut: BrainOutput,\n allowMissing: boolean,\n ): Promise<{ displayId: number; x: number; y: number } | null> {\n // GROUND fast-path: a target already grounded on this Scene is reused.\n const action0 = brainOut.proposed_action;\n const cacheKey = `${input.scene.timestamp}::${brainOut.target_display_id}::${\n action0.ref ?? action0.rationale ?? \"\"\n }`;\n const cached = this.groundCache.get(cacheKey);\n if (cached) {\n this.groundStats.hits += 1;\n return cached;\n }\n const resolved = await this.resolveCoordsUncached(\n input,\n brainOut,\n allowMissing,\n );\n if (resolved) {\n this.groundStats.misses += 1;\n this.rememberGround(input.scene.timestamp, cacheKey, resolved);\n }\n return resolved;\n }\n\n /** Drop cache entries from any Scene other than `timestamp`, then store. */\n private rememberGround(\n timestamp: number,\n key: string,\n value: { displayId: number; x: number; y: number },\n ): void {\n const prefix = `${timestamp}::`;\n for (const k of this.groundCache.keys()) {\n if (!k.startsWith(prefix)) this.groundCache.delete(k);\n }\n this.groundCache.set(key, value);\n }\n\n private async resolveCoordsUncached(\n input: CascadeInput,\n brainOut: BrainOutput,\n allowMissing: boolean,\n ): Promise<{ displayId: number; x: number; y: number } | null> {\n // Strategy 1: if Brain emitted a ref, the OCR/AX grounding (or any\n // registered actor) resolves it directly.\n const action = brainOut.proposed_action;\n if (action.ref) {\n const grounded = await this.groundReference(input, brainOut, action.ref);\n if (grounded) return grounded;\n }\n // Strategy 2: fine grounding on the first ROI via the registered actor.\n if (this.deps.actor && brainOut.roi.length > 0) {\n const roi = brainOut.roi.slice(0, BRAIN_MAX_ROIS)[0];\n if (!roi) return null;\n const grounded = await this.groundRoi(input, brainOut, roi);\n if (grounded) return grounded;\n }\n // Strategy 3: ROI center fallback (deterministic).\n if (brainOut.roi.length > 0) {\n const roi = brainOut.roi[0];\n if (!roi) return null;\n const [x, y, w, h] = roi.bbox;\n return {\n displayId: roi.displayId,\n x: Math.round(x + w / 2),\n y: Math.round(y + h / 2),\n };\n }\n if (allowMissing) return null;\n return null;\n }\n\n private async coordsForRef(\n input: CascadeInput,\n brainOut: BrainOutput,\n ref: string | undefined,\n _isStart: boolean,\n ): Promise<{ displayId: number; x: number; y: number } | null> {\n if (!ref) return null;\n return this.groundReference(input, brainOut, ref);\n }\n\n private async groundReference(\n input: CascadeInput,\n brainOut: BrainOutput,\n ref: string,\n ): Promise<{ displayId: number; x: number; y: number } | null> {\n const target = resolveReference(\n input.scene,\n ref,\n brainOut.proposed_action.rationale,\n brainOut.target_display_id,\n );\n if (!target) return null;\n const [bx, by, bw, bh] = target.bbox;\n const cx = Math.round(bx + bw / 2);\n const cy = Math.round(by + bh / 2);\n // If a real Actor is registered, give it a chance to refine. We still\n // crop the ROI from the native PNG, so the Actor sees real pixels.\n if (this.deps.actor) {\n const capture = input.captures.get(target.displayId);\n if (capture) {\n const cropped = this.cropFrame(capture.frame, [bx, by, bw, bh]);\n try {\n const refined = await this.deps.actor.ground({\n displayId: target.displayId,\n croppedImage: cropped,\n hint: brainOut.proposed_action.rationale,\n ref,\n });\n if (\n refined &&\n Number.isFinite(refined.x) &&\n Number.isFinite(refined.y)\n ) {\n return {\n displayId: target.displayId,\n x: Math.round(refined.x),\n y: Math.round(refined.y),\n };\n }\n } catch (err) {\n logger.warn(\n `[computeruse/cascade] actor.ground failed for ref=${ref}: ${err instanceof Error ? err.message : String(err)} — using bbox center`,\n );\n }\n }\n }\n return { displayId: target.displayId, x: cx, y: cy };\n }\n\n private async groundRoi(\n input: CascadeInput,\n brainOut: BrainOutput,\n roi: BrainRoi,\n ): Promise<{ displayId: number; x: number; y: number } | null> {\n if (!this.deps.actor) return null;\n const capture = input.captures.get(roi.displayId);\n if (!capture) return null;\n const cropped = this.cropFrame(capture.frame, roi.bbox);\n const args: ActorGroundArgs = {\n displayId: roi.displayId,\n croppedImage: cropped,\n hint: brainOut.proposed_action.rationale,\n ref: brainOut.proposed_action.ref,\n };\n try {\n const grounded = await this.deps.actor.ground(args);\n if (!Number.isFinite(grounded.x) || !Number.isFinite(grounded.y)) {\n return null;\n }\n return {\n displayId: roi.displayId,\n x: Math.round(grounded.x),\n y: Math.round(grounded.y),\n };\n } catch (err) {\n logger.warn(\n `[computeruse/cascade] actor.ground threw for ROI: ${err instanceof Error ? err.message : String(err)}`,\n );\n return null;\n }\n }\n\n private cropFrame(\n frame: Buffer,\n bbox: [number, number, number, number],\n ): Buffer {\n if (this.deps.crop) {\n return this.deps.crop(frame, bbox);\n }\n // No native PNG cropper in-tree. We pass the full frame through; the\n // built-in OcrCoordinateGroundingActor ignores the image anyway. When\n // a real Actor lands, the deps.crop callback should be injected.\n return frame;\n }\n}\n\nfunction stringOrUndef(v: unknown): string | undefined {\n return typeof v === \"string\" ? v : undefined;\n}\n\n/** Registry: register an Actor for the cascade to use globally. */\nlet _registeredActor: Actor | null = null;\nexport function setActor(actor: Actor | null): void {\n _registeredActor = actor;\n}\nexport function getRegisteredActor(): Actor | null {\n return _registeredActor;\n}\n",
|
|
20
|
+
"/**\n * Agent-loop registry (#9170 M10).\n *\n * trycua/cua selects an agent *loop* from a model string: an `anthropic/...`\n * model routes to the Claude computer-use loop, `openai/computer-use-preview`\n * routes to the OpenAI operator loop, an OmniParser/grounder string routes to a\n * local set-of-marks loop, etc. Each loop implements the same two-call seam —\n * `predict_step` (observe + plan the next action) and `predict_click` (ground a\n * target to a coordinate) — so the runner is decoupled from *how* a step is\n * produced.\n *\n * elizaOS shipped a single hardcoded Brain→Cascade (ScreenSeekeR). This module\n * replaces that hardcoding with a registry:\n * - `AgentLoop` — the `predictStep` / `predictClick` seam.\n * - `registerAgentLoop` — register a loop keyed by a model-string matcher.\n * - `createAgentLoop(modelString, deps)` — pick the highest-priority matching\n * loop and instantiate it.\n *\n * The built-in `local-grounder` loop wraps the existing Brain→Cascade and\n * exposes the M5 grounding cache through `predictClick`. Anthropic / OpenAI\n * computer-use loops are *pluggable*: a provider plugin calls\n * `registerAgentLoop` with `matchesModelFamily(\"anthropic\")` (etc.) and its own\n * `predictStep`. With none registered, every model string falls through to the\n * local grounder (which always matches at the lowest priority).\n */\n\nimport type { IAgentRuntime } from \"@elizaos/core\";\nimport type { DisplayCapture } from \"../platform/capture.js\";\nimport type { Scene } from \"../scene/scene-types.js\";\nimport { type Actor, OcrCoordinateGroundingActor } from \"./actor.js\";\nimport { Brain, resolveBrainImagePolicy } from \"./brain.js\";\nimport { Cascade, getRegisteredActor } from \"./cascade.js\";\nimport type { CascadeResult, GroundingResult } from \"./types.js\";\n\n/** Default loop model-string — the local OCR/AX + actor grounder. */\nexport const DEFAULT_AGENT_LOOP_MODEL = \"local-grounder\";\n\n/** Setting / env key the runner reads to choose a loop. */\nexport const AGENT_LOOP_SETTING = \"COMPUTER_USE_AGENT_LOOP\";\n\nexport interface AgentStepInput {\n scene: Scene;\n goal: string;\n captures: Map<number, DisplayCapture>;\n}\n\nexport interface PredictClickInput {\n scene: Scene;\n captures: Map<number, DisplayCapture>;\n targetDisplayId: number;\n /** OCR/AX id to ground (`t<d>-<n>` / `a<d>-<n>`). */\n ref?: string;\n /** Free-form instruction when no ref is available. */\n instruction?: string;\n}\n\n/**\n * The two-call seam every loop implements. `predictStep` plans the next\n * concrete action; `predictClick` grounds a target to a coordinate (used by\n * loops that plan elsewhere but reuse our grounding, and by callers that want\n * grounding without a full step).\n */\n/**\n * Per-run model-call accounting (#9105). `invocations` counts the token-bearing\n * model calls a loop actually issued; `cacheHits` counts calls served without a\n * model round-trip. Reported once per run as `evt:\"computeruse.agent.tokens\"`.\n */\nexport interface AgentLoopStats {\n /** Token-bearing model calls actually issued during the run. */\n invocations: number;\n /** Calls served from cache (no model call, no tokens). */\n cacheHits: number;\n /** Model calls issued with no screenshot attached (#9105). */\n imagelessCalls: number;\n /** Estimated image tokens not sent because of imageless calls (#9105). */\n estImageTokensSaved: number;\n}\n\nexport interface AgentLoop {\n readonly name: string;\n predictStep(input: AgentStepInput): Promise<CascadeResult>;\n predictClick(input: PredictClickInput): Promise<GroundingResult | null>;\n /** Per-run model-call accounting, when the loop tracks it (#9105). */\n getStats?(): AgentLoopStats;\n}\n\nexport interface AgentLoopDeps {\n runtime: IAgentRuntime | null;\n /** Latest-scene accessor for the default actor. */\n getScene: () => Scene | null;\n /** Brain override (mostly tests). */\n brain?: Brain;\n /** Actor override (mostly tests). */\n actor?: Actor | null;\n}\n\nexport interface AgentLoopRegistration {\n /** Stable id for telemetry + explicit selection. */\n readonly name: string;\n /** True when this loop handles `modelString`. */\n matches: (modelString: string) => boolean;\n /** Instantiate the loop for a run. */\n create: (deps: AgentLoopDeps) => AgentLoop;\n /** Higher wins when multiple registrations match. Default 0. */\n priority?: number;\n}\n\n// ── Built-in: local OCR/AX + actor grounder (Brain → Cascade) ────────────────\n\n/**\n * Wraps the existing ScreenSeekeR (Brain → Cascade). `predictStep` is the full\n * observe→plan→ground cascade; `predictClick` calls the cascade's grounding-only\n * path so the M5 per-Scene grounding cache is shared across both.\n */\nexport class LocalGrounderLoop implements AgentLoop {\n readonly name = DEFAULT_AGENT_LOOP_MODEL;\n private readonly cascade: Cascade;\n private readonly brain: Brain;\n\n constructor(deps: AgentLoopDeps) {\n const brain =\n deps.brain ??\n new Brain(deps.runtime, {\n imagePolicy: resolveBrainImagePolicy(deps.runtime),\n });\n this.brain = brain;\n const actor =\n deps.actor ??\n getRegisteredActor() ??\n new OcrCoordinateGroundingActor(deps.getScene);\n this.cascade = new Cascade({ brain, actor });\n }\n\n predictStep(input: AgentStepInput): Promise<CascadeResult> {\n return this.cascade.run(input);\n }\n\n async predictClick(\n input: PredictClickInput,\n ): Promise<GroundingResult | null> {\n const coords = await this.cascade.groundTarget({\n scene: input.scene,\n captures: input.captures,\n targetDisplayId: input.targetDisplayId,\n ref: input.ref,\n instruction: input.instruction,\n });\n if (!coords) return null;\n return {\n displayId: coords.displayId,\n x: coords.x,\n y: coords.y,\n confidence: 1,\n reason: input.ref ?? input.instruction ?? \"grounded\",\n };\n }\n\n /** Grounding cache hit/miss snapshot (delegates to the wrapped cascade). */\n getGroundStats() {\n return this.cascade.getGroundStats();\n }\n\n /** Model-call accounting from the wrapped Brain (#9105). */\n getStats(): AgentLoopStats {\n return this.brain.getStats();\n }\n}\n\n// ── Model-string helpers ─────────────────────────────────────────────────────\n\n/**\n * A matcher for a provider family — `anthropic`, `openai`, `google`, … A\n * pluggable loop registers with `matches: matchesModelFamily(\"anthropic\")` so a\n * model string like `anthropic/claude-...` or `claude-3-7-sonnet` routes to it.\n */\nexport function matchesModelFamily(\n family: string,\n): (modelString: string) => boolean {\n const f = family.trim().toLowerCase();\n return (modelString: string): boolean => {\n const m = modelString.trim().toLowerCase();\n return (\n m === f ||\n m.startsWith(`${f}/`) ||\n m.startsWith(`${f}-`) ||\n m.includes(`/${f}/`) ||\n m.includes(f)\n );\n };\n}\n\n// ── Registry ─────────────────────────────────────────────────────────────────\n\nconst REGISTRY = new Map<string, AgentLoopRegistration>();\n\n/** Register (or replace, by name) an agent-loop. */\nexport function registerAgentLoop(registration: AgentLoopRegistration): void {\n REGISTRY.set(registration.name, registration);\n}\n\nexport function unregisterAgentLoop(name: string): void {\n REGISTRY.delete(name);\n}\n\nexport function listAgentLoops(): readonly AgentLoopRegistration[] {\n return [...REGISTRY.values()].sort(\n (a, b) => (b.priority ?? 0) - (a.priority ?? 0),\n );\n}\n\n/**\n * The built-in local grounder. Registered at module load with the lowest\n * priority and a match-anything predicate, so it is always the fallback.\n */\nconst LOCAL_GROUNDER_REGISTRATION: AgentLoopRegistration = {\n name: DEFAULT_AGENT_LOOP_MODEL,\n // Matches the explicit name plus common local/grounder aliases; also the\n // universal fallback (every string) because its priority is the floor.\n matches: (modelString: string): boolean => {\n const m = modelString.trim().toLowerCase();\n return (\n m === \"\" ||\n m === DEFAULT_AGENT_LOOP_MODEL ||\n m === \"local\" ||\n m === \"omniparser\" ||\n m === \"screenseeker\" ||\n true\n );\n },\n create: (deps) => new LocalGrounderLoop(deps),\n priority: Number.NEGATIVE_INFINITY,\n};\nregisterAgentLoop(LOCAL_GROUNDER_REGISTRATION);\n\n/**\n * Pick the registration for a model string: the highest-priority one whose\n * `matches` returns true. The local grounder's match-anything floor guarantees\n * a result, so this never throws.\n */\nexport function selectAgentLoopRegistration(\n modelString: string,\n): AgentLoopRegistration {\n let best: AgentLoopRegistration | null = null;\n let bestPriority = Number.NEGATIVE_INFINITY;\n for (const reg of REGISTRY.values()) {\n if (!reg.matches(modelString)) continue;\n const p = reg.priority ?? 0;\n // Strictly-greater keeps the first registrant on ties — but the local\n // grounder sits at -Infinity so any real loop outranks it.\n if (best === null || p > bestPriority) {\n best = reg;\n bestPriority = p;\n }\n }\n // The local grounder always matches, so `best` is non-null here.\n return best ?? LOCAL_GROUNDER_REGISTRATION;\n}\n\n/** Resolve + instantiate the loop for a model string. */\nexport function createAgentLoop(\n modelString: string,\n deps: AgentLoopDeps,\n): AgentLoop {\n return selectAgentLoopRegistration(modelString).create(deps);\n}\n\n/** Test helper — restore the registry to just the built-in local grounder. */\nexport function _resetAgentLoopsForTests(): void {\n REGISTRY.clear();\n registerAgentLoop(LOCAL_GROUNDER_REGISTRATION);\n}\n",
|
|
21
|
+
"/**\n * Per-display capture (WS5).\n *\n * Canonical capture entry point. Replaces `screenshot.ts` for any caller that\n * cares about multi-monitor or DPI. The legacy `captureScreenshot()` keeps\n * working (single-display, primary only) for back-compat.\n *\n * Returned `frame` is a PNG buffer at backing-store resolution:\n * - macOS retina — 2× the logical bounds (e.g. 5120×2880 for a 2560×1440\n * display reported as scaleFactor 2).\n * - Windows/Linux — pixel-equivalent to logical bounds.\n *\n * Implementation notes:\n * - macOS uses `screencapture -D <displayIndex+1>` to pick a specific\n * display (1-indexed). For ScreenCaptureKit follow-up, replace this\n * dispatch with the Swift sidecar.\n * - Linux/Wayland prefers the xdg-desktop-portal screenshot sidecar. X11\n * uses `import` (ImageMagick) or `scrot` cropped to the display's xrandr\n * rect.\n * - Windows uses PowerShell + System.Drawing to crop the virtual desktop\n * to the screen bounds.\n *\n * Every code path is conditional on the current platform — a Linux test host\n * can exercise the Linux paths; macOS / Windows paths are typechecked but\n * exercised only in CI on those OSes.\n */\n\nimport { execFileSync, execSync } from \"node:child_process\";\nimport { readFileSync, unlinkSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { ScreenRegion } from \"../types.js\";\nimport type { DisplayInfo } from \"./displays.js\";\nimport { findDisplay, getPrimaryDisplay, listDisplays } from \"./displays.js\";\nimport { commandExists, currentPlatform, runCommandBuffer } from \"./helpers.js\";\nimport {\n classifyPermissionDeniedError,\n createPermissionDeniedError,\n isPermissionDeniedError,\n} from \"./permissions.js\";\nimport { psHostAvailable, runPsHost } from \"./ps-host.js\";\nimport {\n canUseWaylandScreenshotPortal,\n captureWaylandPortalScreenshot,\n isWaylandSession,\n} from \"./wayland-portal.js\";\n\nconst SCREEN_RECORDING_OPERATION_MESSAGE =\n \"macOS Screen Recording permission is required for screenshots. Grant access in System Settings > Privacy & Security > Screen Recording, then retry.\";\n\nexport interface DisplayCapture {\n display: DisplayInfo;\n /** PNG bytes at backing-store resolution. */\n frame: Buffer;\n}\n\n/**\n * Capture every attached display in parallel. Returns one entry per display.\n * Errors on any display are surfaced as rejected promises — caller decides\n * whether to retry or partial-fail.\n */\nexport async function captureAllDisplays(): Promise<DisplayCapture[]> {\n const displays = listDisplays();\n return Promise.all(displays.map((d) => captureDisplay(d.id)));\n}\n\n/**\n * Capture a specific display by id.\n */\nexport async function captureDisplay(\n displayId: number,\n): Promise<DisplayCapture> {\n const display = findDisplay(displayId);\n if (!display) {\n throw new Error(\n `Unknown displayId ${displayId}. Known: ${listDisplays()\n .map((d) => d.id)\n .join(\", \")}`,\n );\n }\n const os = currentPlatform();\n const tmpFile = join(\n tmpdir(),\n `computeruse-display-${displayId}-${Date.now()}.png`,\n );\n try {\n if (os === \"darwin\") captureDisplayDarwin(tmpFile, display);\n else if (os === \"linux\") captureDisplayLinux(tmpFile, display);\n else if (os === \"win32\") await captureDisplayWindows(tmpFile, display);\n\n const data = readFileSync(tmpFile);\n if (os === \"darwin\" && data.length === 0) {\n throw createPermissionDeniedError({\n permissionType: \"screen_recording\",\n operation: \"screenshot_capture\",\n message: SCREEN_RECORDING_OPERATION_MESSAGE,\n details: \"screencapture returned an empty file.\",\n });\n }\n return { display, frame: data };\n } catch (err) {\n if (isPermissionDeniedError(err)) throw err;\n const permissionError = classifyPermissionDeniedError(err, {\n permissionType: \"screen_recording\",\n operation: \"screenshot_capture\",\n });\n if (permissionError) throw permissionError;\n throw err;\n } finally {\n try {\n unlinkSync(tmpFile);\n } catch {\n /* best effort */\n }\n }\n}\n\n/**\n * Capture a region within a specific display. Region coordinates are LOCAL\n * to that display.\n */\nexport async function captureDisplayRegion(\n displayId: number,\n region: ScreenRegion,\n): Promise<DisplayCapture> {\n const display = findDisplay(displayId);\n if (!display) {\n throw new Error(`Unknown displayId ${displayId}.`);\n }\n const globalRegion: ScreenRegion = {\n x: display.bounds[0] + region.x,\n y: display.bounds[1] + region.y,\n width: region.width,\n height: region.height,\n };\n const os = currentPlatform();\n const tmpFile = join(\n tmpdir(),\n `computeruse-region-${displayId}-${Date.now()}.png`,\n );\n try {\n if (os === \"darwin\") captureRegionDarwin(tmpFile, globalRegion);\n else if (os === \"linux\") captureRegionLinux(tmpFile, globalRegion);\n else if (os === \"win32\") await captureRegionWindows(tmpFile, globalRegion);\n const data = readFileSync(tmpFile);\n return { display, frame: data };\n } finally {\n try {\n unlinkSync(tmpFile);\n } catch {\n /* best effort */\n }\n }\n}\n\n/**\n * Convenience: capture the primary display.\n */\nexport async function capturePrimaryDisplay(): Promise<DisplayCapture> {\n return captureDisplay(getPrimaryDisplay().id);\n}\n\n// ── macOS ───────────────────────────────────────────────────────────────────\n\nfunction captureDisplayDarwin(tmpFile: string, display: DisplayInfo): void {\n // `screencapture -D N` selects display N (1-based). Display ids reported\n // by CG are 32-bit handles; we map our 0-based index to the -D argument.\n const ordinal = displayOrdinal(display);\n try {\n runCommandBuffer(\n \"screencapture\",\n [\"-D\", String(ordinal + 1), \"-x\", tmpFile],\n 10000,\n );\n } catch (error) {\n const permissionError = classifyPermissionDeniedError(error, {\n permissionType: \"screen_recording\",\n operation: \"screenshot_capture\",\n });\n if (permissionError) throw permissionError;\n throw error;\n }\n}\n\nfunction captureRegionDarwin(tmpFile: string, region: ScreenRegion): void {\n runCommandBuffer(\n \"screencapture\",\n [\n `-R${region.x},${region.y},${region.width},${region.height}`,\n \"-x\",\n tmpFile,\n ],\n 10000,\n );\n}\n\n// ── Linux ───────────────────────────────────────────────────────────────────\n\nfunction captureDisplayLinux(tmpFile: string, display: DisplayInfo): void {\n const [x, y, w, h] = display.bounds;\n if (tryCaptureWaylandPortal(tmpFile)) return;\n if (commandExists(\"import\")) {\n runCommandBuffer(\n \"import\",\n [\"-window\", \"root\", \"-crop\", `${w}x${h}+${x}+${y}`, tmpFile],\n 10000,\n );\n return;\n }\n if (commandExists(\"scrot\")) {\n runCommandBuffer(\"scrot\", [\"-a\", `${x},${y},${w},${h}`, tmpFile], 10000);\n return;\n }\n if (commandExists(\"gnome-screenshot\")) {\n // gnome-screenshot doesn't crop precisely — fall back to whole screen.\n runCommandBuffer(\"gnome-screenshot\", [\"-f\", tmpFile], 10000);\n return;\n }\n throw new Error(\n isWaylandSession()\n ? \"No screenshot tool available. Install xdg-desktop-portal with gdbus/python3 for Wayland, or ImageMagick (import), scrot, or gnome-screenshot for X11 fallback.\"\n : \"No screenshot tool available. Install ImageMagick (import), scrot, or gnome-screenshot.\",\n );\n}\n\nfunction captureRegionLinux(tmpFile: string, region: ScreenRegion): void {\n if (commandExists(\"import\")) {\n runCommandBuffer(\n \"import\",\n [\n \"-window\",\n \"root\",\n \"-crop\",\n `${region.width}x${region.height}+${region.x}+${region.y}`,\n tmpFile,\n ],\n 10000,\n );\n return;\n }\n if (commandExists(\"scrot\")) {\n runCommandBuffer(\n \"scrot\",\n [\n \"-a\",\n `${region.x},${region.y},${region.width},${region.height}`,\n tmpFile,\n ],\n 10000,\n );\n return;\n }\n throw new Error(\"No screenshot tool available for region capture.\");\n}\n\nfunction tryCaptureWaylandPortal(tmpFile: string): boolean {\n if (!canUseWaylandScreenshotPortal()) return false;\n try {\n captureWaylandPortalScreenshot(tmpFile);\n return true;\n } catch (error) {\n if (isPermissionDeniedError(error)) throw error;\n return false;\n }\n}\n\n// ── Windows ─────────────────────────────────────────────────────────────────\n\n/**\n * Coerce a capture region to integer pixels and reject empty/degenerate sizes.\n *\n * `New-Object System.Drawing.Bitmap(w, h)` throws an opaque \"Parameter is not\n * valid\" GDI+ error for a zero/negative/non-integer width or height, so we\n * validate up front and surface a clear message. `x`/`y` may legitimately be\n * negative — secondary monitors placed left of / above the primary live in the\n * negative quadrant of the Windows virtual-desktop coordinate space — so only\n * the dimensions are bounds-checked. Exported for cross-platform unit tests.\n */\nexport function normalizeCaptureRegion(region: ScreenRegion): ScreenRegion {\n const width = Math.round(region.width);\n const height = Math.round(region.height);\n if (!Number.isFinite(width) || !Number.isFinite(height)) {\n throw new Error(\n `Invalid capture region: width/height must be finite numbers (got ${region.width}x${region.height}).`,\n );\n }\n if (width <= 0 || height <= 0) {\n throw new Error(\n `Invalid capture region: width and height must be positive (got ${width}x${height}).`,\n );\n }\n return {\n x: Math.round(region.x),\n y: Math.round(region.y),\n width,\n height,\n };\n}\n\nasync function captureDisplayWindows(\n tmpFile: string,\n display: DisplayInfo,\n): Promise<void> {\n const [x, y, w, h] = display.bounds;\n await captureRegionWindows(tmpFile, { x, y, width: w, height: h });\n}\n\nasync function captureRegionWindows(\n tmpFile: string,\n region: ScreenRegion,\n): Promise<void> {\n const safe = normalizeCaptureRegion(region);\n const escapedPath = tmpFile.replace(/\\//g, \"\\\\\");\n const psCmd = [\n \"Add-Type -AssemblyName System.Windows.Forms,System.Drawing\",\n `$bitmap = New-Object System.Drawing.Bitmap(${safe.width}, ${safe.height})`,\n \"$graphics = [System.Drawing.Graphics]::FromImage($bitmap)\",\n `$origin = New-Object System.Drawing.Point(${safe.x}, ${safe.y})`,\n `$size = New-Object System.Drawing.Size(${safe.width}, ${safe.height})`,\n \"$graphics.CopyFromScreen($origin, [System.Drawing.Point]::Empty, $size)\",\n `$bitmap.Save('${escapedPath}')`,\n \"$graphics.Dispose()\",\n \"$bitmap.Dispose()\",\n ].join(\"; \");\n // Prefer the warm PowerShell host — a cold `powershell.exe` spawn is ~10-16s\n // on Defender-heavy hosts, and capture runs every turn (full frame + each\n // dirty region). The host runs the SAME script in an already-warm process\n // (sub-second). Any host failure falls through to the one-shot spawn so\n // behavior is unchanged, only faster.\n if (psHostAvailable()) {\n try {\n await runPsHost(psCmd, 15000);\n return;\n } catch {\n /* warm host unavailable/errored — fall back to one-shot spawn */\n }\n }\n execSync(`powershell -NoProfile -Command \"${psCmd}\"`, {\n timeout: 15000,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n}\n\n// ── helpers ─────────────────────────────────────────────────────────────────\n\nfunction displayOrdinal(display: DisplayInfo): number {\n const all = listDisplays();\n const idx = all.findIndex((d) => d.id === display.id);\n return idx >= 0 ? idx : 0;\n}\n\n// Re-export the legacy single-display API so that screenshot.ts callers work.\nexport { captureScreenshot } from \"./screenshot.js\";\n\n// Suppress unused-import lint when execFileSync isn't reached on every build.\nvoid execFileSync;\n",
|
|
22
|
+
"/**\n * Multi-monitor display enumeration (WS5).\n *\n * Returns the live set of physical displays attached to the host, in a\n * single, OS-agnostic shape:\n *\n * { id, bounds: [x, y, w, h], scaleFactor, primary, name }\n *\n * Notes on `id`:\n * - macOS — `CGDirectDisplayID` (32-bit unsigned). Stable across reboots.\n * - Windows — `Screen.DeviceName` hash → small integer. We expose a 0-based\n * index because PowerShell `System.Windows.Forms.Screen` does\n * not surface a kernel handle, and the device name (e.g.\n * `\\\\.\\DISPLAY1`) is a string. The index is stable for a given\n * process but may shift across hot-plug events.\n * - Linux X — `xrandr --listmonitors` ordinal. Stable per process.\n * - Linux W — compositor-specific output id (Hyprland/Sway). Best effort.\n *\n * Coordinate space:\n * `bounds` is in OS-global pixel space. On macOS, that means scaled\n * \"points\" by default — we record the backing-store scale factor in\n * `scaleFactor` so callers can translate to pixel-perfect coords when\n * composing captures.\n *\n * This module never executes input. It is read-only.\n */\n\nimport { execFileSync, execSync } from \"node:child_process\";\nimport { currentPlatform } from \"./helpers.js\";\nimport { psHostAvailable, runPsHost } from \"./ps-host.js\";\n\nexport interface DisplayInfo {\n /** OS-stable identifier or a 0-based fallback index. */\n id: number;\n /** [x, y, width, height] in OS-global pixel space. */\n bounds: [number, number, number, number];\n /** Backing-store scale factor. 1 on Linux, 1..N on HiDPI macOS/Windows. */\n scaleFactor: number;\n /** Whether this is the primary display. */\n primary: boolean;\n /** Human-readable name (e.g. `eDP-1`, `Built-in Retina Display`). */\n name: string;\n}\n\n/**\n * Error thrown when the host has no usable display surface. Headless Linux\n * (no `DISPLAY` and no `WAYLAND_DISPLAY`), CI containers without an X\n * server, and macOS/Windows hosts that report zero active displays all\n * surface as this typed error so callers can distinguish \"no monitors\" from\n * a transient enumeration failure.\n */\nexport class NoDisplayError extends Error {\n readonly code = \"NO_DISPLAY\" as const;\n constructor(message: string) {\n super(message);\n this.name = \"NoDisplayError\";\n }\n}\n\nlet cached: DisplayInfo[] | null = null;\nlet cachedAt = 0;\n// Display topology is stable for the life of a session in the overwhelming\n// majority of cases (hot-plug mid-task is rare), and enumeration shells out —\n// on Windows a cold `powershell.exe` spawn is ~10-16s under Defender (#9581),\n// and it sits on the capture hot path (`captureDisplay` → `findDisplay` →\n// `listDisplays` every turn, plus a burst per dirty-region capture). A 2s TTL\n// re-spawned that probe constantly. A longer TTL collapses it to ~once per\n// window; `refreshDisplays()` forces a fresh read when a caller knows the\n// layout changed. Override with `COMPUTERUSE_DISPLAYS_CACHE_MS`.\nconst CACHE_MS = (() => {\n const raw = Number(process.env.COMPUTERUSE_DISPLAYS_CACHE_MS);\n return Number.isFinite(raw) && raw >= 0 ? raw : 30_000;\n})();\n\n/**\n * List all attached displays. Cached to avoid spamming xrandr / PowerShell on\n * burst calls (provider runs every turn; see {@link CACHE_MS}).\n *\n * Returns a single-display fallback when the OS reports nothing — most\n * callers want a sensible default, not an empty array. Use `isHeadless()`\n * or `assertHasDisplays()` to distinguish the truly-headless case from a\n * single attached monitor.\n */\nexport function listDisplays(): DisplayInfo[] {\n const now = Date.now();\n if (cached && now - cachedAt < CACHE_MS) return cached;\n const real = enumerateDisplays();\n const fresh = real.length > 0 ? real : [fallbackPrimary()];\n cached = fresh;\n cachedAt = now;\n return fresh;\n}\n\n/** Force a fresh enumeration, ignoring cache. */\nexport function refreshDisplays(): DisplayInfo[] {\n cached = null;\n return listDisplays();\n}\n\n/** Convenience: the primary display, or the first one if none is flagged. */\nexport function getPrimaryDisplay(): DisplayInfo {\n const all = listDisplays();\n if (all.length === 0) {\n return fallbackPrimary();\n }\n const first = all[0];\n if (!first) {\n return fallbackPrimary();\n }\n return all.find((d) => d.primary) ?? first;\n}\n\n/** Look up a display by id, or null if unknown. */\nexport function findDisplay(id: number): DisplayInfo | null {\n return listDisplays().find((d) => d.id === id) ?? null;\n}\n\n/**\n * Detect a truly headless host. Returns true when:\n * - Linux: neither `DISPLAY` nor `WAYLAND_DISPLAY` is set, AND no\n * compositor / X server enumeration tool reports anything.\n * - macOS / Windows: enumeration via system_profiler / PowerShell yields\n * zero displays.\n * The single-display fallback returned by `listDisplays()` does NOT count as\n * a real display for this check.\n */\nexport function isHeadless(): boolean {\n const os = currentPlatform();\n if (os === \"linux\") {\n const hasX = (process.env.DISPLAY ?? \"\").length > 0;\n const hasWayland = (process.env.WAYLAND_DISPLAY ?? \"\").length > 0;\n if (!hasX && !hasWayland) return true;\n }\n return enumerateDisplays().length === 0;\n}\n\n/**\n * Capture-path guard: throws `NoDisplayError` on a truly headless host.\n * Callers that hit \"no monitor\" should surface this typed error rather than\n * returning an empty buffer or a generic `Error`.\n */\nexport function assertHasDisplays(): void {\n if (isHeadless()) {\n throw new NoDisplayError(\n \"[displays] No attached display. Headless host detected — set DISPLAY/WAYLAND_DISPLAY or run on a desktop session.\",\n );\n }\n}\n\n/**\n * Run the platform-specific enumeration. Returns an empty array when nothing\n * is attached or the OS returned no displays — callers wanting the legacy\n * single-display fallback should call `listDisplays()` instead.\n */\nfunction enumerateDisplays(): DisplayInfo[] {\n const os = currentPlatform();\n if (os === \"linux\") return enumerateLinux();\n if (os === \"darwin\") return enumerateDarwin();\n if (os === \"win32\") return enumerateWindows();\n return [];\n}\n\nfunction fallbackPrimary(): DisplayInfo {\n return {\n id: 0,\n bounds: [0, 0, 1920, 1080],\n scaleFactor: 1,\n primary: true,\n name: \"primary\",\n };\n}\n\n// ── Linux: X11 ──────────────────────────────────────────────────────────────\n//\n// `xrandr --listmonitors` produces:\n// Monitors: N\n// i: <prefix>name w/mm_x h/mm+xoff+yoff name\n// where <prefix> is `+*` for primary, `+` for secondary.\n//\n// Example:\n// 0: +*eDP-1 2560/390x1600/240+0+0 eDP-1\n// 1: +HDMI-0 3840/600x2160/340+2560+0 HDMI-0\n\nconst XRANDR_LINE =\n /^\\s*(\\d+):\\s*\\+(\\*?)\\S*\\s+(\\d+)\\/\\d+x(\\d+)\\/\\d+([+-]\\d+)([+-]\\d+)\\s+(\\S+)/;\n\nexport function parseXrandrMonitors(output: string): DisplayInfo[] {\n const displays: DisplayInfo[] = [];\n for (const rawLine of output.split(/\\r?\\n/)) {\n const m = rawLine.match(XRANDR_LINE);\n if (!m) continue;\n const idText = m[1];\n const widthText = m[3];\n const heightText = m[4];\n const xText = m[5];\n const yText = m[6];\n const name = m[7];\n if (!idText || !widthText || !heightText || !xText || !yText || !name) {\n continue;\n }\n const id = Number.parseInt(idText, 10);\n const primary = m[2] === \"*\";\n const width = Number.parseInt(widthText, 10);\n const height = Number.parseInt(heightText, 10);\n // m[5] / m[6] include the explicit sign (e.g. \"-1920\" or \"+0\").\n const x = Number.parseInt(xText, 10);\n const y = Number.parseInt(yText, 10);\n if (![id, width, height, x, y].every((n) => Number.isFinite(n))) continue;\n displays.push({\n id,\n bounds: [x, y, width, height],\n scaleFactor: 1,\n primary,\n name,\n });\n }\n return ensurePrimary(displays);\n}\n\nfunction enumerateLinux(): DisplayInfo[] {\n const hasX = (process.env.DISPLAY ?? \"\").length > 0;\n const hasWayland = (process.env.WAYLAND_DISPLAY ?? \"\").length > 0;\n if (!hasX && !hasWayland) return [];\n const sessionType = (process.env.XDG_SESSION_TYPE ?? \"\").toLowerCase();\n if (sessionType === \"wayland\" || hasWayland) {\n const w = enumerateWayland();\n if (w.length > 0) return w;\n }\n // X11 — preferred path. Works under XWayland too.\n try {\n const output = execFileSync(\"xrandr\", [\"--listmonitors\"], {\n timeout: 3000,\n encoding: \"utf-8\",\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n const parsed = parseXrandrMonitors(output);\n if (parsed.length > 0) return parsed;\n } catch {\n /* xrandr unavailable — fall through to empty */\n }\n return [];\n}\n\nfunction enumerateWayland(): DisplayInfo[] {\n // Hyprland\n try {\n const output = execFileSync(\"hyprctl\", [\"monitors\", \"-j\"], {\n timeout: 3000,\n encoding: \"utf-8\",\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n const parsed = parseHyprlandMonitors(output);\n if (parsed.length > 0) return parsed;\n } catch {\n /* try sway */\n }\n // Sway\n try {\n const output = execFileSync(\"swaymsg\", [\"-t\", \"get_outputs\"], {\n timeout: 3000,\n encoding: \"utf-8\",\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n const parsed = parseSwayOutputs(output);\n if (parsed.length > 0) return parsed;\n } catch {\n /* fall through to xrandr/xwayland */\n }\n return [];\n}\n\ninterface HyprlandMonitor {\n id?: number;\n name?: string;\n x?: number;\n y?: number;\n width?: number;\n height?: number;\n scale?: number;\n focused?: boolean;\n}\n\nexport function parseHyprlandMonitors(output: string): DisplayInfo[] {\n let raw: unknown;\n try {\n raw = JSON.parse(output);\n } catch {\n return [];\n }\n if (!Array.isArray(raw)) return [];\n const displays: DisplayInfo[] = [];\n let idx = 0;\n for (const item of raw as HyprlandMonitor[]) {\n if (!item || typeof item !== \"object\") continue;\n const w = Number(item.width);\n const h = Number(item.height);\n const x = Number(item.x);\n const y = Number(item.y);\n if (![w, h, x, y].every((n) => Number.isFinite(n))) continue;\n displays.push({\n id: Number.isFinite(Number(item.id)) ? Number(item.id) : idx,\n bounds: [x, y, w, h],\n scaleFactor: Number.isFinite(Number(item.scale)) ? Number(item.scale) : 1,\n primary: Boolean(item.focused) || idx === 0,\n name: typeof item.name === \"string\" ? item.name : `output-${idx}`,\n });\n idx += 1;\n }\n return ensurePrimary(displays);\n}\n\ninterface SwayOutput {\n name?: string;\n focused?: boolean;\n primary?: boolean;\n rect?: { x?: number; y?: number; width?: number; height?: number };\n scale?: number;\n}\n\nexport function parseSwayOutputs(output: string): DisplayInfo[] {\n let raw: unknown;\n try {\n raw = JSON.parse(output);\n } catch {\n return [];\n }\n if (!Array.isArray(raw)) return [];\n const displays: DisplayInfo[] = [];\n let idx = 0;\n for (const item of raw as SwayOutput[]) {\n if (!item || typeof item !== \"object\") continue;\n const rect = item.rect ?? {};\n const w = Number(rect.width);\n const h = Number(rect.height);\n const x = Number(rect.x);\n const y = Number(rect.y);\n if (![w, h, x, y].every((n) => Number.isFinite(n))) continue;\n displays.push({\n id: idx,\n bounds: [x, y, w, h],\n scaleFactor: Number.isFinite(Number(item.scale)) ? Number(item.scale) : 1,\n primary: Boolean(item.primary || item.focused) || idx === 0,\n name: typeof item.name === \"string\" ? item.name : `output-${idx}`,\n });\n idx += 1;\n }\n return ensurePrimary(displays);\n}\n\n// ── macOS ───────────────────────────────────────────────────────────────────\n//\n// We avoid shipping a Swift sidecar for v1. CoreGraphics is reachable via\n// `osascript -l JavaScript` (JXA) — the same path the existing single-display\n// code uses. JXA gives us `CGGetActiveDisplayList` + `CGDisplayBounds`, plus\n// `CGDisplayScreenSize` and `CGDisplayPixelsWide/High` for the scale factor.\n//\n// For macOS 14+ a native ScreenCaptureKit binary will yield richer metadata\n// (name, refresh rate, color space). That's a follow-up — the interface here\n// is shaped to absorb it without breaking callers.\n\ninterface JXADisplay {\n id?: number;\n bounds?: { x?: number; y?: number; width?: number; height?: number };\n pixelWidth?: number;\n pixelHeight?: number;\n primary?: boolean;\n name?: string;\n}\n\nexport function parseDarwinDisplays(output: string): DisplayInfo[] {\n let raw: unknown;\n try {\n raw = JSON.parse(output);\n } catch {\n return [];\n }\n if (!Array.isArray(raw)) return [];\n const displays: DisplayInfo[] = [];\n let idx = 0;\n for (const item of raw as JXADisplay[]) {\n if (!item || typeof item !== \"object\") continue;\n const b = item.bounds ?? {};\n const w = Number(b.width);\n const h = Number(b.height);\n const x = Number(b.x);\n const y = Number(b.y);\n if (![w, h, x, y].every((n) => Number.isFinite(n))) continue;\n const pixelW = Number(item.pixelWidth);\n const pixelH = Number(item.pixelHeight);\n let scale = 1;\n if (Number.isFinite(pixelW) && w > 0) {\n scale = pixelW / w;\n } else if (Number.isFinite(pixelH) && h > 0) {\n scale = pixelH / h;\n }\n displays.push({\n id: Number.isFinite(Number(item.id)) ? Number(item.id) : idx,\n bounds: [x, y, w, h],\n scaleFactor: Number.isFinite(scale) && scale > 0 ? scale : 1,\n primary: Boolean(item.primary) || idx === 0,\n name:\n typeof item.name === \"string\" && item.name.length > 0\n ? item.name\n : `display-${idx}`,\n });\n idx += 1;\n }\n return ensurePrimary(displays);\n}\n\nfunction enumerateDarwin(): DisplayInfo[] {\n // JXA's pointer manipulation for CGGetActiveDisplayList is brittle. Use a\n // simpler shell-out path: `system_profiler SPDisplaysDataType -json` lists\n // every display with resolution, but no per-display origin. For origin we\n // fall back to AppleScript `tell app \"System Events\" to get displays` (10.15+)\n // or accept primary-only when origin is missing.\n try {\n const output = execSync(\"system_profiler SPDisplaysDataType -json\", {\n timeout: 5000,\n encoding: \"utf-8\",\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n const parsed = parseSystemProfilerDisplays(output);\n if (parsed.length > 0) return parsed;\n } catch {\n /* fall through */\n }\n // Last-resort: CGMainDisplay bounds + scale via osascript JXA.\n try {\n const output = execSync(\n `osascript -l JavaScript -e 'ObjC.import(\"CoreGraphics\"); const id=$.CGMainDisplayID(); const b=$.CGDisplayBounds(id); const pw=$.CGDisplayPixelsWide(id); const ph=$.CGDisplayPixelsHigh(id); JSON.stringify({id:Number(id), x:b.origin.x, y:b.origin.y, w:b.size.width, h:b.size.height, pw:pw, ph:ph});'`,\n { timeout: 4000, encoding: \"utf-8\" },\n );\n const j = JSON.parse(output) as {\n id: number;\n x: number;\n y: number;\n w: number;\n h: number;\n pw: number;\n ph: number;\n };\n const scale = j.w > 0 ? j.pw / j.w : 1;\n return [\n {\n id: Number.isFinite(j.id) ? j.id : 0,\n bounds: [\n Math.round(j.x),\n Math.round(j.y),\n Math.round(j.w),\n Math.round(j.h),\n ],\n scaleFactor: Number.isFinite(scale) && scale > 0 ? scale : 1,\n primary: true,\n name: \"main\",\n },\n ];\n } catch {\n return [fallbackPrimary()];\n }\n}\n\ninterface SPDisplay {\n _name?: string;\n _spdisplays_resolution?: string;\n spdisplays_resolution?: string;\n _spdisplays_pixelresolution?: string;\n spdisplays_pixelresolution?: string;\n spdisplays_main?: string; // \"spdisplays_yes\" when primary\n}\n\ninterface SPDisplaysCard {\n spdisplays_ndrvs?: SPDisplay[];\n}\n\ninterface SPDisplaysRoot {\n SPDisplaysDataType?: SPDisplaysCard[];\n}\n\nconst SP_RES = /(\\d+)\\s*[x×]\\s*(\\d+)/i;\n\nexport function parseSystemProfilerDisplays(output: string): DisplayInfo[] {\n let parsed: SPDisplaysRoot;\n try {\n parsed = JSON.parse(output) as SPDisplaysRoot;\n } catch {\n return [];\n }\n const cards = parsed.SPDisplaysDataType;\n if (!Array.isArray(cards)) return [];\n const displays: DisplayInfo[] = [];\n let idx = 0;\n // Best-effort: system_profiler omits origins. We lay each display out\n // horizontally starting at x=0. Callers needing accurate origins should\n // fall back to the JXA path or supply explicit positions via env.\n let xCursor = 0;\n for (const card of cards) {\n const drivers = card.spdisplays_ndrvs;\n if (!Array.isArray(drivers)) continue;\n for (const d of drivers) {\n const logicalText =\n d.spdisplays_resolution ?? d._spdisplays_resolution ?? \"\";\n const pixelText =\n d.spdisplays_pixelresolution ?? d._spdisplays_pixelresolution ?? \"\";\n const logicalMatch = SP_RES.exec(logicalText);\n const pixelMatch = SP_RES.exec(pixelText);\n if (!logicalMatch && !pixelMatch) continue;\n const logicalWidthText = logicalMatch?.[1] ?? pixelMatch?.[1];\n const logicalHeightText = logicalMatch?.[2] ?? pixelMatch?.[2];\n if (!logicalWidthText || !logicalHeightText) continue;\n const logicalW = Number.parseInt(logicalWidthText, 10);\n const logicalH = Number.parseInt(logicalHeightText, 10);\n const pixelW = pixelMatch?.[1]\n ? Number.parseInt(pixelMatch[1], 10)\n : logicalW;\n let scale = logicalW > 0 ? pixelW / logicalW : 1;\n if (!Number.isFinite(scale) || scale <= 0) scale = 1;\n const primary = d.spdisplays_main === \"spdisplays_yes\" || idx === 0;\n displays.push({\n id: idx,\n bounds: [xCursor, 0, logicalW, logicalH],\n scaleFactor: scale,\n primary,\n name: typeof d._name === \"string\" ? d._name : `display-${idx}`,\n });\n xCursor += logicalW;\n idx += 1;\n }\n }\n return ensurePrimary(displays);\n}\n\n// ── Windows ─────────────────────────────────────────────────────────────────\n//\n// PowerShell + System.Windows.Forms.Screen gives bounds and primary flag for\n// every monitor. It does NOT give a per-monitor DPI; for that we'd need a\n// native binding to `GetDpiForMonitor` (shcore.dll) or to enumerate via\n// `EnumDisplayMonitors`. v1 reports scaleFactor=1 and the app manifest must\n// declare PerMonitorV2 dpi awareness so coordinates are in pixels.\n\ninterface WinScreen {\n DeviceName?: string;\n Primary?: boolean;\n Bounds?: { X?: number; Y?: number; Width?: number; Height?: number };\n}\n\nexport function parseWindowsScreens(output: string): DisplayInfo[] {\n let raw: unknown;\n try {\n raw = JSON.parse(output);\n } catch {\n return [];\n }\n const items: WinScreen[] = Array.isArray(raw)\n ? (raw as WinScreen[])\n : [raw as WinScreen];\n const displays: DisplayInfo[] = [];\n let idx = 0;\n for (const s of items) {\n if (!s || typeof s !== \"object\") continue;\n const b = s.Bounds ?? {};\n const w = Number(b.Width);\n const h = Number(b.Height);\n const x = Number(b.X);\n const y = Number(b.Y);\n if (![w, h, x, y].every((n) => Number.isFinite(n))) continue;\n displays.push({\n id: idx,\n bounds: [x, y, w, h],\n scaleFactor: 1,\n primary: Boolean(s.Primary) || idx === 0,\n name:\n typeof s.DeviceName === \"string\" && s.DeviceName.length > 0\n ? s.DeviceName\n : `display-${idx}`,\n });\n idx += 1;\n }\n return ensurePrimary(displays);\n}\n\nfunction ensurePrimary(displays: DisplayInfo[]): DisplayInfo[] {\n if (displays.length === 0 || displays.some((display) => display.primary)) {\n return displays;\n }\n const first = displays[0];\n if (first) {\n first.primary = true;\n }\n return displays;\n}\n\nconst WIN_ENUM_PS =\n \"Add-Type -AssemblyName System.Windows.Forms; \" +\n \"[System.Windows.Forms.Screen]::AllScreens | \" +\n \"Select-Object DeviceName,Primary,Bounds | \" +\n \"ConvertTo-Json -Compress -Depth 4\";\n\nfunction enumerateWindows(): DisplayInfo[] {\n try {\n const output = execSync(`powershell -NoProfile -Command \"${WIN_ENUM_PS}\"`, {\n timeout: 5000,\n encoding: \"utf-8\",\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n const parsed = parseWindowsScreens(output);\n if (parsed.length > 0) return parsed;\n } catch {\n /* fall through */\n }\n return [fallbackPrimary()];\n}\n\n/**\n * Asynchronously populate the display cache via the warm PowerShell host\n * (Windows only). Lets the service pre-seed the cache at init without the\n * blocking ~10-16s cold `powershell.exe` spawn that the sync\n * {@link listDisplays} path would otherwise pay on the first turn. No-op (and\n * never throws) when the host is unavailable — the sync path remains the\n * fallback. Override the resulting TTL with `COMPUTERUSE_DISPLAYS_CACHE_MS`.\n */\nexport async function warmDisplaysCache(): Promise<void> {\n if (currentPlatform() !== \"win32\" || !psHostAvailable()) return;\n try {\n const output = await runPsHost(WIN_ENUM_PS, 15_000);\n const parsed = parseWindowsScreens(output);\n if (parsed.length > 0) {\n cached = parsed;\n cachedAt = Date.now();\n }\n } catch {\n /* leave cache untouched; sync enumeration remains the fallback */\n }\n}\n",
|
|
23
|
+
"import { execFileSync } from \"node:child_process\";\nimport type { PermissionType } from \"../types.js\";\n\ntype PermissionErrorOptions = {\n permissionType: PermissionType;\n operation: string;\n message: string;\n details?: string;\n};\n\nexport type PermissionDeniedError = Error & {\n permissionDenied: true;\n permissionType: PermissionType;\n operation: string;\n details?: string;\n};\n\nfunction toMessage(error: unknown): string {\n if (error instanceof Error) {\n return error.message;\n }\n return String(error);\n}\n\n// ── Windows permission classifiers ───────────────────────────────────────────\n//\n// Windows surfaces privacy denials through a small set of recognizable error\n// shapes:\n// - \"Access is denied\" / HRESULT 0x80070005 (E_ACCESSDENIED) — generic Win32\n// - \"Class not registered\" + Get-AppxPackage missing → camera/screen privacy\n// blocks expressed as the COM facade returning failure (Windows 10/11\n// returns this when the Settings → Privacy → Camera switch is off for\n// Win32 apps).\n// - \"ConsentStore\" — UWP camera/microphone consent store entries when\n// enumerated through PowerShell registry queries.\n// - \"BlockedByPolicy\" — Group Policy disabled the device.\n\nfunction matchesWindowsPrivacyDeniedError(message: string): boolean {\n return /access(?:\\s+is)?\\s+denied|0x80070005|class not registered|consentstore|blockedbypolicy|the device is not ready|element not found.*camera|element not found.*microphone|requestedaccess.*denied/i.test(\n message,\n );\n}\n\nfunction matchesWindowsScreenCaptureDenied(message: string): boolean {\n return /screen capture.*denied|graphicscapturesession|capture is not supported|displaymanagement.*denied|monitor info.*access/i.test(\n message,\n );\n}\n\nexport function createPermissionDeniedError(\n options: PermissionErrorOptions,\n): PermissionDeniedError {\n const error = new Error(options.message) as PermissionDeniedError;\n error.name = \"PermissionDeniedError\";\n error.permissionDenied = true;\n error.permissionType = options.permissionType;\n error.operation = options.operation;\n if (options.details) {\n error.details = options.details;\n }\n return error;\n}\n\nexport function isPermissionDeniedError(\n value: unknown,\n): value is PermissionDeniedError {\n return (\n value instanceof Error &&\n \"permissionDenied\" in value &&\n value.permissionDenied === true &&\n \"permissionType\" in value &&\n typeof value.permissionType === \"string\"\n );\n}\n\nfunction matchesAccessibilityPermissionError(message: string): boolean {\n return /accessibility|assistive access|not authorized to send apple events|osascript.*not allowed|osascript.*etimedout|spawnsync osascript etimedout|system events got an error|not permitted to send keystrokes|control.*not allowed/i.test(\n message,\n );\n}\n\nfunction matchesScreenRecordingPermissionError(message: string): boolean {\n return /screen recording|screen capture|not authorized|permission denied|could not create image from display|screencapture.*empty|cgwindowlistcreateimage|capture failed/i.test(\n message,\n );\n}\n\nexport function classifyPermissionDeniedError(\n error: unknown,\n fallback: {\n permissionType: PermissionType;\n operation: string;\n },\n): PermissionDeniedError | null {\n if (isPermissionDeniedError(error)) {\n return error;\n }\n\n const message = toMessage(error);\n const platform = process.platform;\n\n if (\n fallback.permissionType === \"accessibility\" &&\n matchesAccessibilityPermissionError(message)\n ) {\n return createPermissionDeniedError({\n permissionType: \"accessibility\",\n operation: fallback.operation,\n message:\n \"Desktop automation requires macOS Accessibility permission. Grant access in System Settings > Privacy & Security > Accessibility, then retry.\",\n details: message,\n });\n }\n\n if (\n fallback.permissionType === \"screen_recording\" &&\n matchesScreenRecordingPermissionError(message)\n ) {\n return createPermissionDeniedError({\n permissionType: \"screen_recording\",\n operation: fallback.operation,\n message:\n \"Screenshots require macOS Screen Recording permission. Grant access in System Settings > Privacy & Security > Screen Recording, then retry.\",\n details: message,\n });\n }\n\n // Windows privacy classifier — matches Windows 10/11 surface forms.\n // PARITY: code-complete; not runtime-tested against a real Windows host.\n if (platform === \"win32\") {\n if (\n fallback.permissionType === \"screen_recording\" &&\n (matchesWindowsScreenCaptureDenied(message) ||\n matchesWindowsPrivacyDeniedError(message))\n ) {\n return createPermissionDeniedError({\n permissionType: \"screen_recording\",\n operation: fallback.operation,\n message:\n \"Screen capture is blocked by Windows privacy settings or Group Policy. Open Settings > Privacy & Security > Screen recording and enable access for this app, then retry.\",\n details: message,\n });\n }\n if (\n (fallback.permissionType === \"camera\" ||\n fallback.permissionType === \"microphone\") &&\n matchesWindowsPrivacyDeniedError(message)\n ) {\n const deviceLabel =\n fallback.permissionType === \"camera\" ? \"Camera\" : \"Microphone\";\n return createPermissionDeniedError({\n permissionType: fallback.permissionType,\n operation: fallback.operation,\n message: `${deviceLabel} access is denied by Windows privacy settings or Group Policy. Open Settings > Privacy & Security > ${deviceLabel} and enable access for this app, then retry.`,\n details: message,\n });\n }\n if (\n fallback.permissionType === \"accessibility\" &&\n matchesWindowsPrivacyDeniedError(message)\n ) {\n // Windows does not require an accessibility permission for SendInput,\n // but UAC and protected-process targets surface the same denial shape.\n return createPermissionDeniedError({\n permissionType: \"accessibility\",\n operation: fallback.operation,\n message:\n \"Input dispatch was refused by Windows. The target window is likely an elevated (UAC) or protected process; restart the host with matching elevation or target a different window.\",\n details: message,\n });\n }\n }\n\n return null;\n}\n\n// ── Probe helpers ────────────────────────────────────────────────────────────\n//\n// Best-effort, side-effect-free permission probes. They never throw — callers\n// use the returned `granted` field plus `details` to drive UX. macOS is the\n// only platform with a real privacy DB we can read without prompting; Windows\n// inspects the Capability Access Manager registry; Linux has no equivalent.\n\nexport interface PermissionProbeResult {\n /** True if the OS reports the permission is granted for this process. */\n readonly granted: boolean;\n /**\n * `null` when the OS doesn't expose a probe (Linux desktop, headless, etc.)\n * — caller should treat this as \"unknown, attempt the operation and rely on\n * runtime classification\".\n */\n readonly probed: boolean;\n readonly details?: string;\n}\n\nfunction probeWindowsCapabilityAccess(\n capability: \"webcam\" | \"microphone\" | \"graphicsCaptureProgrammatic\",\n): PermissionProbeResult {\n // Windows stores per-capability consent under\n // HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\CapabilityAccessManager\\ConsentStore\\<capability>\n // The `Value` REG_SZ is \"Allow\" / \"Deny\". This is read-only and never\n // triggers a consent prompt.\n // PARITY: code-complete; not runtime-tested against a real Windows host.\n const { execFileSync } = require(\"node:child_process\") as {\n execFileSync: (\n cmd: string,\n args: string[],\n opts?: { encoding?: string; timeout?: number; stdio?: unknown },\n ) => string;\n };\n const command = `try { (Get-ItemProperty -ErrorAction Stop -Path 'HKCU:\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\CapabilityAccessManager\\\\ConsentStore\\\\${capability}').Value } catch { 'Unknown' }`;\n const stdout = execFileSync(\n \"powershell\",\n [\"-NoProfile\", \"-Command\", command],\n {\n encoding: \"utf8\",\n timeout: 4000,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n },\n );\n const value = String(stdout).trim();\n return {\n granted: /^allow$/i.test(value),\n probed: value.length > 0 && !/^unknown$/i.test(value),\n details: `CapabilityAccessManager.${capability}=${value || \"<empty>\"}`,\n };\n}\n\nexport function probePermission(\n permissionType: PermissionType,\n): PermissionProbeResult {\n if (process.platform !== \"win32\") {\n return { granted: false, probed: false };\n }\n if (permissionType === \"camera\") {\n try {\n return probeWindowsCapabilityAccess(\"webcam\");\n } catch (err) {\n return { granted: false, probed: false, details: toMessage(err) };\n }\n }\n if (permissionType === \"microphone\") {\n try {\n return probeWindowsCapabilityAccess(\"microphone\");\n } catch (err) {\n return { granted: false, probed: false, details: toMessage(err) };\n }\n }\n if (permissionType === \"screen_recording\") {\n try {\n return probeWindowsCapabilityAccess(\"graphicsCaptureProgrammatic\");\n } catch (err) {\n return { granted: false, probed: false, details: toMessage(err) };\n }\n }\n // accessibility / shell — Windows has no per-app gate; treat as granted.\n return { granted: true, probed: false };\n}\n",
|
|
24
|
+
"import { execFileSync } from \"node:child_process\";\nimport { copyFileSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport { commandExists } from \"./helpers.js\";\nimport { createPermissionDeniedError } from \"./permissions.js\";\n\nconst PORTAL_BUS_NAME = \"org.freedesktop.portal.Desktop\";\nconst PORTAL_OBJECT_PATH = \"/org/freedesktop/portal/desktop\";\nconst PORTAL_SCREENSHOT_METHOD = \"org.freedesktop.portal.Screenshot.Screenshot\";\nconst DEFAULT_TIMEOUT_MS = 15000;\n\nconst WAYLAND_PORTAL_HELPER = String.raw`\nimport os\nimport re\nimport select\nimport subprocess\nimport sys\nimport time\nimport uuid\n\nbus_name = \"org.freedesktop.portal.Desktop\"\nobject_path = \"/org/freedesktop/portal/desktop\"\nmethod = \"org.freedesktop.portal.Screenshot.Screenshot\"\ntimeout_ms = int(os.environ.get(\"ELIZA_WAYLAND_PORTAL_TIMEOUT_MS\", \"15000\"))\ninteractive = os.environ.get(\"ELIZA_WAYLAND_PORTAL_INTERACTIVE\", \"0\") == \"1\"\ntoken = \"eliza_\" + str(os.getpid()) + \"_\" + uuid.uuid4().hex\noptions = \"{'handle_token': <'\" + token + \"'>, 'interactive': <\" + (\"true\" if interactive else \"false\") + \">}\"\n\nmonitor = subprocess.Popen(\n [\"gdbus\", \"monitor\", \"--session\", \"--dest\", bus_name],\n stdout=subprocess.PIPE,\n stderr=subprocess.PIPE,\n text=True,\n bufsize=1,\n)\n\ntry:\n time.sleep(0.05)\n call = subprocess.run(\n [\n \"gdbus\",\n \"call\",\n \"--session\",\n \"--dest\",\n bus_name,\n \"--object-path\",\n object_path,\n \"--method\",\n method,\n \"\",\n options,\n ],\n capture_output=True,\n text=True,\n timeout=max(1, timeout_ms / 1000),\n )\n if call.returncode != 0:\n print(call.stderr.strip() or call.stdout.strip() or \"portal screenshot call failed\", file=sys.stderr)\n sys.exit(2)\n\n match = re.search(r\"objectpath '([^']+)'\", call.stdout)\n if not match:\n print(\"portal screenshot call did not return a request handle: \" + call.stdout.strip(), file=sys.stderr)\n sys.exit(3)\n\n handle = match.group(1)\n deadline = time.monotonic() + (timeout_ms / 1000)\n buffer = \"\"\n\n while time.monotonic() < deadline:\n remaining = max(0, min(0.5, deadline - time.monotonic()))\n ready, _, _ = select.select([monitor.stdout], [], [], remaining)\n if not ready:\n continue\n line = monitor.stdout.readline()\n if not line:\n continue\n buffer += line\n if len(buffer) > 65536:\n buffer = buffer[-65536:]\n if handle not in buffer:\n continue\n tail = buffer[buffer.rfind(handle):]\n response = re.search(r\"uint32\\s+(\\d+)\", tail)\n if not response:\n continue\n response_code = int(response.group(1))\n if response_code != 0:\n print(\"portal screenshot request was denied or cancelled (response=%d)\" % response_code, file=sys.stderr)\n sys.exit(10 + response_code)\n uri = re.search(r\"['\\\"]uri['\\\"]\\s*:\\s*<['\\\"]([^'\\\"]+)['\\\"]>\", tail)\n if uri:\n print(uri.group(1))\n sys.exit(0)\n\n print(\"timed out waiting for portal screenshot response\", file=sys.stderr)\n sys.exit(4)\nfinally:\n monitor.terminate()\n try:\n monitor.wait(timeout=1)\n except Exception:\n monitor.kill()\n`;\n\nexport interface WaylandPortalCaptureOptions {\n readonly interactive?: boolean;\n readonly timeoutMs?: number;\n}\n\nexport interface PortalScreenshotResponse {\n readonly responseCode: number;\n readonly uri?: string;\n}\n\ninterface WaylandSessionEnv {\n readonly WAYLAND_DISPLAY?: string;\n readonly XDG_SESSION_TYPE?: string;\n}\n\nexport function isWaylandSession(env?: WaylandSessionEnv): boolean {\n const sessionType = (env?.XDG_SESSION_TYPE ?? process.env.XDG_SESSION_TYPE)\n ?.trim()\n .toLowerCase();\n const waylandDisplay =\n (env?.WAYLAND_DISPLAY ?? process.env.WAYLAND_DISPLAY)?.trim() ?? \"\";\n return sessionType === \"wayland\" || waylandDisplay.length > 0;\n}\n\nexport function canUseWaylandScreenshotPortal(): boolean {\n return (\n isWaylandSession() && commandExists(\"python3\") && commandExists(\"gdbus\")\n );\n}\n\nexport function captureWaylandPortalScreenshot(\n tmpFile: string,\n options: WaylandPortalCaptureOptions = {},\n): void {\n if (!isWaylandSession()) {\n throw new Error(\n \"Wayland screenshot portal requested outside a Wayland session.\",\n );\n }\n if (!commandExists(\"python3\") || !commandExists(\"gdbus\")) {\n throw new Error(\n \"Wayland screenshot portal requires python3 and gdbus on PATH.\",\n );\n }\n\n const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n let uri: string;\n try {\n uri = execFileSync(\"python3\", [\"-c\", WAYLAND_PORTAL_HELPER], {\n encoding: \"utf-8\",\n timeout: timeoutMs + 2000,\n env: {\n ...process.env,\n ELIZA_WAYLAND_PORTAL_INTERACTIVE: options.interactive ? \"1\" : \"0\",\n ELIZA_WAYLAND_PORTAL_TIMEOUT_MS: String(timeoutMs),\n },\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n }).trim();\n } catch (error) {\n const message = commandErrorMessage(error);\n if (/denied|cancelled|canceled/i.test(message)) {\n throw createPermissionDeniedError({\n permissionType: \"screen_recording\",\n operation: \"screenshot_capture\",\n message:\n \"Wayland screenshot permission was denied or cancelled by the portal.\",\n details: message,\n });\n }\n throw error;\n }\n\n const sourcePath = portalFileUriToPath(uri);\n copyFileSync(sourcePath, tmpFile);\n}\n\nfunction commandErrorMessage(error: unknown): string {\n if (!error || typeof error !== \"object\") return String(error);\n const parts: string[] = [];\n const candidate = error as {\n message?: unknown;\n stderr?: unknown;\n stdout?: unknown;\n };\n for (const value of [candidate.message, candidate.stderr, candidate.stdout]) {\n if (typeof value === \"string\" && value.length > 0) {\n parts.push(value);\n } else if (Buffer.isBuffer(value) && value.length > 0) {\n parts.push(value.toString(\"utf-8\"));\n }\n }\n return parts.join(\"\\n\") || String(error);\n}\n\nexport function parsePortalRequestHandle(output: string): string | null {\n return output.match(/objectpath '([^']+)'/)?.[1] ?? null;\n}\n\nexport function parsePortalScreenshotResponse(\n output: string,\n handle?: string,\n): PortalScreenshotResponse | null {\n const source =\n handle && output.includes(handle)\n ? output.slice(output.lastIndexOf(handle))\n : output;\n const responseCodeText = source.match(/uint32\\s+(\\d+)/)?.[1];\n if (!responseCodeText) return null;\n\n const responseCode = Number.parseInt(responseCodeText, 10);\n const uri = source.match(/['\"]uri['\"]\\s*:\\s*<['\"]([^'\"]+)['\"]>/)?.[1];\n return Number.isFinite(responseCode)\n ? { responseCode, ...(uri ? { uri } : {}) }\n : null;\n}\n\nexport function portalFileUriToPath(uri: string): string {\n if (!uri.startsWith(\"file://\")) {\n throw new Error(\n `Wayland screenshot portal returned a non-file URI: ${uri}`,\n );\n }\n return fileURLToPath(uri);\n}\n\nexport const WAYLAND_PORTAL_DBUS_TARGET = {\n busName: PORTAL_BUS_NAME,\n objectPath: PORTAL_OBJECT_PATH,\n method: PORTAL_SCREENSHOT_METHOD,\n} as const;\n",
|
|
25
|
+
"/**\n * Cross-platform screenshot capture.\n *\n * Ported from:\n * - coasty-ai/open-computer-use screenshot.ts (Apache 2.0)\n * - eliza sandbox-routes.ts captureScreenshot()\n *\n * Uses native CLI tools — no Electron dependency.\n * Full logical resolution is preserved (critical for accurate coordinate mapping).\n */\n\nimport { execSync } from \"node:child_process\";\nimport { readFileSync, unlinkSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { ScreenRegion } from \"../types.js\";\nimport { commandExists, currentPlatform, runCommandBuffer } from \"./helpers.js\";\nimport {\n classifyPermissionDeniedError,\n createPermissionDeniedError,\n isPermissionDeniedError,\n} from \"./permissions.js\";\nimport { tagScreenshotError } from \"./screenshot-errors.js\";\nimport {\n canUseWaylandScreenshotPortal,\n captureWaylandPortalScreenshot,\n isWaylandSession,\n} from \"./wayland-portal.js\";\n\nconst SCREEN_RECORDING_OPERATION_MESSAGE =\n \"macOS Screen Recording permission is required for screenshots. Grant access in System Settings > Privacy & Security > Screen Recording, then retry.\";\n\n/**\n * Capture a screenshot of the entire screen (or a region) and return as a Buffer (PNG).\n */\nexport function captureScreenshot(region?: ScreenRegion): Buffer {\n const os = currentPlatform();\n const tmpFile = join(tmpdir(), `computeruse-screenshot-${Date.now()}.png`);\n\n try {\n if (os === \"darwin\") {\n captureDarwin(tmpFile, region);\n } else if (os === \"linux\") {\n captureLinux(tmpFile, region);\n } else if (os === \"win32\") {\n captureWindows(tmpFile, region);\n }\n\n const data = readFileSync(tmpFile);\n if (os === \"darwin\" && data.length === 0) {\n throw createPermissionDeniedError({\n permissionType: \"screen_recording\",\n operation: \"screenshot_capture\",\n message: SCREEN_RECORDING_OPERATION_MESSAGE,\n details: \"screencapture returned an empty file.\",\n });\n }\n\n try {\n unlinkSync(tmpFile);\n } catch {\n /* cleanup best effort */\n }\n return data;\n } catch (err) {\n try {\n unlinkSync(tmpFile);\n } catch {\n /* ignore */\n }\n\n const operation = region ? \"screenshot_region\" : \"screenshot_capture\";\n\n if (isPermissionDeniedError(err)) {\n throw tagScreenshotError(err, operation);\n }\n\n const permissionError = classifyPermissionDeniedError(err, {\n permissionType: \"screen_recording\",\n operation,\n });\n if (permissionError) {\n throw tagScreenshotError(permissionError, operation);\n }\n\n throw tagScreenshotError(err, operation);\n }\n}\n\n// ── macOS ───────────────────────────────────────────────────────────────────\n\nfunction captureDarwin(tmpFile: string, region?: ScreenRegion): void {\n try {\n if (region) {\n runCommandBuffer(\n \"screencapture\",\n [\n `-R${region.x},${region.y},${region.width},${region.height}`,\n \"-x\",\n tmpFile,\n ],\n 10000,\n );\n } else {\n // -x suppresses the shutter sound\n runCommandBuffer(\"screencapture\", [\"-x\", tmpFile], 10000);\n }\n } catch (error) {\n const permissionError = classifyPermissionDeniedError(error, {\n permissionType: \"screen_recording\",\n operation: region ? \"screenshot_region\" : \"screenshot_capture\",\n });\n if (permissionError) {\n throw permissionError;\n }\n throw error;\n }\n}\n\n// ── Linux ───────────────────────────────────────────────────────────────────\n\nfunction captureLinux(tmpFile: string, region?: ScreenRegion): void {\n if (!region && tryCaptureWaylandPortal(tmpFile)) return;\n\n // Try tools in preference order\n if (commandExists(\"import\")) {\n if (region) {\n runCommandBuffer(\n \"import\",\n [\n \"-window\",\n \"root\",\n \"-crop\",\n `${region.width}x${region.height}+${region.x}+${region.y}`,\n tmpFile,\n ],\n 10000,\n );\n } else {\n runCommandBuffer(\"import\", [\"-window\", \"root\", tmpFile], 10000);\n }\n } else if (commandExists(\"scrot\")) {\n runCommandBuffer(\"scrot\", [tmpFile], 10000);\n } else if (commandExists(\"gnome-screenshot\")) {\n runCommandBuffer(\"gnome-screenshot\", [\"-f\", tmpFile], 10000);\n } else {\n throw new Error(\n isWaylandSession()\n ? \"No screenshot tool available. Install xdg-desktop-portal with gdbus/python3 for Wayland, or ImageMagick (import), scrot, or gnome-screenshot for X11 fallback.\"\n : \"No screenshot tool available. Install ImageMagick (import), scrot, or gnome-screenshot.\",\n );\n }\n}\n\nfunction tryCaptureWaylandPortal(tmpFile: string): boolean {\n if (!canUseWaylandScreenshotPortal()) return false;\n try {\n captureWaylandPortalScreenshot(tmpFile);\n return true;\n } catch (error) {\n if (isPermissionDeniedError(error)) throw error;\n return false;\n }\n}\n\n// ── Windows ─────────────────────────────────────────────────────────────────\n\nfunction captureWindows(tmpFile: string, _region?: ScreenRegion): void {\n const escapedPath = tmpFile.replace(/\\//g, \"\\\\\");\n const psCmd = [\n \"Add-Type -AssemblyName System.Windows.Forms\",\n \"$screen = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds\",\n \"$bitmap = New-Object System.Drawing.Bitmap($screen.Width, $screen.Height)\",\n \"$graphics = [System.Drawing.Graphics]::FromImage($bitmap)\",\n \"$graphics.CopyFromScreen($screen.Location, [System.Drawing.Point]::Empty, $screen.Size)\",\n `$bitmap.Save('${escapedPath}')`,\n \"$graphics.Dispose()\",\n \"$bitmap.Dispose()\",\n ].join(\"; \");\n\n execSync(`powershell -Command \"${psCmd}\"`, {\n timeout: 15000,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n}\n",
|
|
26
|
+
"/**\n * Structured screenshot error contract (issue #9105, M3.5).\n *\n * Capture can fail for several distinct reasons, and a caller (the CUA Brain,\n * the GET_SCREEN op, the approval/telemetry layer) wants to react differently\n * to each: a missing OS permission needs a \"grant access\" prompt; a missing CLI\n * tool needs an \"install scrot/ImageMagick\" hint; an empty buffer or a timeout\n * is a transient retry. Before this contract, those were indistinguishable —\n * callers had to regex the human-readable message.\n *\n * This module adds a machine-readable {@link ScreenshotErrorCode} **additively**:\n * `tagScreenshotError` annotates the *existing* thrown error object with a code\n * rather than replacing it, so a `PermissionDeniedError` keeps its identity\n * (`isPermissionDeniedError` stays true) while also gaining a\n * `screenshotErrorCode` of `\"permission_denied\"`. No existing caller breaks; new\n * callers can switch on the code.\n */\n\nimport { isPermissionDeniedError } from \"./permissions.js\";\n\nexport type ScreenshotErrorCode =\n /** An OS privacy permission (Screen Recording / Accessibility) is denied. */\n | \"permission_denied\"\n /** No screenshot CLI tool is installed (e.g. Linux without scrot/import). */\n | \"tool_missing\"\n /** The capture tool ran but produced an empty/zero-byte image. */\n | \"empty_output\"\n /** The capture command exceeded its timeout. */\n | \"timeout\"\n /** Any other capture failure. */\n | \"capture_failed\";\n\n/** An `Error` carrying a machine-readable {@link ScreenshotErrorCode}. */\nexport interface ScreenshotError extends Error {\n readonly screenshotErrorCode: ScreenshotErrorCode;\n /** The capture operation that failed (e.g. `screenshot_capture`). */\n readonly operation: string;\n /** Underlying error message, when this wraps a lower-level failure. */\n readonly details?: string;\n}\n\ntype Mutable<T> = { -readonly [K in keyof T]: T[K] };\n\nfunction toMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nexport function isScreenshotError(value: unknown): value is ScreenshotError {\n return (\n value instanceof Error &&\n \"screenshotErrorCode\" in value &&\n typeof (value as { screenshotErrorCode?: unknown }).screenshotErrorCode ===\n \"string\"\n );\n}\n\nexport function createScreenshotError(\n code: ScreenshotErrorCode,\n operation: string,\n message: string,\n details?: string,\n): ScreenshotError {\n const error = new Error(message) as Mutable<ScreenshotError>;\n error.name = \"ScreenshotError\";\n error.screenshotErrorCode = code;\n error.operation = operation;\n if (details !== undefined) error.details = details;\n return error;\n}\n\n/**\n * Map any thrown value to a {@link ScreenshotErrorCode} by inspecting its type\n * and message. Permission denials win first (they are typed); the rest are\n * recognized from the well-known message shapes the capture functions throw.\n * Pure — exported so the mapping has a single, testable source of truth.\n */\nexport function classifyScreenshotErrorCode(\n error: unknown,\n): ScreenshotErrorCode {\n if (isPermissionDeniedError(error)) return \"permission_denied\";\n if (isScreenshotError(error)) return error.screenshotErrorCode;\n\n const message = toMessage(error).toLowerCase();\n if (\n /no screenshot tool|install (imagemagick|scrot|gnome-screenshot)|command not found|\\benoent\\b|not recognized as (?:the name of )?an? (?:internal|cmdlet)/.test(\n message,\n )\n ) {\n return \"tool_missing\";\n }\n if (\n /empty (?:file|output|image|buffer)|zero[- ]?byte|returned an empty/.test(\n message,\n )\n ) {\n return \"empty_output\";\n }\n if (/timed out|timeout|\\betimedout\\b/.test(message)) {\n return \"timeout\";\n }\n return \"capture_failed\";\n}\n\n/**\n * Annotate `error` with a {@link ScreenshotErrorCode} and return it. Additive:\n * an `Error` (including a `PermissionDeniedError`) is mutated in place so its\n * identity and existing fields are preserved; a non-`Error` value is wrapped in\n * a fresh {@link ScreenshotError}. Idempotent — an already-tagged error is\n * returned unchanged.\n */\nexport function tagScreenshotError(\n error: unknown,\n operation: string,\n): ScreenshotError {\n if (isScreenshotError(error)) return error;\n\n const code = classifyScreenshotErrorCode(error);\n if (error instanceof Error) {\n const tagged = error as Mutable<ScreenshotError>;\n tagged.screenshotErrorCode = code;\n if (typeof tagged.operation !== \"string\") tagged.operation = operation;\n return tagged;\n }\n return createScreenshotError(code, operation, toMessage(error));\n}\n",
|
|
27
|
+
"/**\n * Cross-platform desktop automation — mouse, keyboard, scroll, drag.\n *\n * Ported from coasty-ai/open-computer-use desktop-automation.ts (Apache 2.0)\n * and eliza sandbox-routes.ts performClick/performType/performKeypress.\n *\n * Platform backends:\n * macOS — cliclick (preferred, brew install cliclick) or AppleScript fallback\n * Linux — xdotool (required: sudo apt install xdotool)\n * Windows — PowerShell with user32.dll P/Invoke\n *\n * All coordinate inputs are validated via validateInt() to prevent injection.\n */\n\nimport {\n canonicalKeyName,\n commandExists,\n currentPlatform,\n escapeAppleScript,\n runCommand,\n safeXdotoolKey,\n toCliclickKeyName,\n toWindowsSendKey,\n toXdotoolKeyName,\n validateInt,\n validateKeypress,\n validateText,\n} from \"./helpers.js\";\nimport {\n classifyPermissionDeniedError,\n isPermissionDeniedError,\n} from \"./permissions.js\";\n\nfunction _toAppleScriptModifier(key: string): string {\n const normalized = key.trim().toLowerCase();\n const mapping: Record<string, string> = {\n cmd: \"command\",\n command: \"command\",\n meta: \"command\",\n super: \"command\",\n ctrl: \"control\",\n control: \"control\",\n alt: \"option\",\n option: \"option\",\n shift: \"shift\",\n fn: \"function\",\n };\n const modifier = mapping[normalized];\n if (!modifier) {\n throw new Error(`Unsupported modifier key: \"${key}\"`);\n }\n return modifier;\n}\n\nfunction _toAppleScriptKeyCode(key: string): number | null {\n const canonical = canonicalKeyName(key);\n const keyCodes: Record<string, number> = {\n enter: 36,\n return: 36,\n tab: 48,\n space: 49,\n escape: 53,\n delete: 51,\n backspace: 51,\n left: 123,\n right: 124,\n down: 125,\n up: 126,\n home: 115,\n end: 119,\n pageup: 116,\n pagedown: 121,\n f1: 122,\n f2: 120,\n f3: 99,\n f4: 118,\n f5: 96,\n f6: 97,\n f7: 98,\n f8: 100,\n f9: 101,\n f10: 109,\n f11: 103,\n f12: 111,\n };\n return keyCodes[canonical] ?? null;\n}\n\nfunction runDarwinJxa(script: string, timeoutMs = 5000): void {\n runCommand(\"osascript\", [\"-l\", \"JavaScript\", \"-e\", script], timeoutMs);\n}\n\nfunction _moveMouseDarwin(x: number, y: number): void {\n runDarwinJxa(\n `\nObjC.import(\"ApplicationServices\");\nconst point = $.CGPointMake(${x}, ${y});\nconst event = $.CGEventCreateMouseEvent(\n null,\n $.kCGEventMouseMoved,\n point,\n $.kCGMouseButtonLeft\n);\n$.CGEventPost($.kCGHIDEventTap, event);\n`,\n );\n}\n\nfunction _clickDarwinWithCoreGraphics(\n x: number,\n y: number,\n button: \"left\" | \"right\",\n clickCount = 1,\n): void {\n const downEvent =\n button === \"right\" ? \"$.kCGEventRightMouseDown\" : \"$.kCGEventLeftMouseDown\";\n const upEvent =\n button === \"right\" ? \"$.kCGEventRightMouseUp\" : \"$.kCGEventLeftMouseUp\";\n const mouseButton =\n button === \"right\" ? \"$.kCGMouseButtonRight\" : \"$.kCGMouseButtonLeft\";\n runDarwinJxa(\n `\nObjC.import(\"ApplicationServices\");\nconst point = $.CGPointMake(${x}, ${y});\nfor (let clickIndex = 1; clickIndex <= ${clickCount}; clickIndex += 1) {\n const down = $.CGEventCreateMouseEvent(null, ${downEvent}, point, ${mouseButton});\n $.CGEventSetIntegerValueField(down, $.kCGMouseEventClickState, clickIndex);\n $.CGEventPost($.kCGHIDEventTap, down);\n const up = $.CGEventCreateMouseEvent(null, ${upEvent}, point, ${mouseButton});\n $.CGEventSetIntegerValueField(up, $.kCGMouseEventClickState, clickIndex);\n $.CGEventPost($.kCGHIDEventTap, up);\n}\n`,\n );\n}\n\nfunction _scrollDarwin(\n x: number,\n y: number,\n direction: \"up\" | \"down\" | \"left\" | \"right\",\n amount: number,\n): void {\n const vertical =\n direction === \"up\" ? amount : direction === \"down\" ? -amount : 0;\n const horizontal =\n direction === \"left\" ? amount : direction === \"right\" ? -amount : 0;\n runDarwinJxa(\n `\nObjC.import(\"ApplicationServices\");\nconst point = $.CGPointMake(${x}, ${y});\nconst moveEvent = $.CGEventCreateMouseEvent(\n null,\n $.kCGEventMouseMoved,\n point,\n $.kCGMouseButtonLeft\n);\n$.CGEventPost($.kCGHIDEventTap, moveEvent);\nconst scrollEvent = $.CGEventCreateScrollWheelEvent(\n null,\n $.kCGScrollEventUnitLine,\n 2,\n ${vertical},\n ${horizontal}\n);\n$.CGEventPost($.kCGHIDEventTap, scrollEvent);\n`,\n );\n}\n\n// ── Cursor query ────────────────────────────────────────────────────────────\n\n/**\n * Read the current OS cursor position (legacy shell driver). Returns global\n * logical pixels. Windows uses `System.Windows.Forms.Cursor` (must Add-Type the\n * assembly first or the type is unresolved); macOS uses `cliclick p:.`; Linux\n * uses `xdotool getmouselocation`.\n */\nexport function legacyGetCursorPosition(): { x: number; y: number } {\n const os = currentPlatform();\n if (os === \"win32\") {\n const out = runCommand(\n \"powershell\",\n [\n \"-NoProfile\",\n \"-Command\",\n 'Add-Type -AssemblyName System.Windows.Forms; $p=[System.Windows.Forms.Cursor]::Position; \"$($p.X),$($p.Y)\"',\n ],\n 5000,\n );\n const [x, y] = out.trim().split(\",\").map(Number);\n return { x: validateInt(x), y: validateInt(y) };\n }\n if (os === \"darwin\") {\n const out = runCommand(\"cliclick\", [\"p:.\"], 5000); // prints \"x,y\"\n const [x, y] = out.trim().split(\",\").map(Number);\n return { x: validateInt(x), y: validateInt(y) };\n }\n // Linux / X11\n const out = runCommand(\"xdotool\", [\"getmouselocation\", \"--shell\"], 5000);\n const mx = /X=(-?\\d+)/.exec(out);\n const my = /Y=(-?\\d+)/.exec(out);\n return {\n x: mx ? validateInt(Number(mx[1])) : 0,\n y: my ? validateInt(Number(my[1])) : 0,\n };\n}\n\n// ── Mouse Click ─────────────────────────────────────────────────────────────\n\nexport function desktopClick(x: number, y: number): void {\n runWithAccessibilityPermission(\n \"desktop_click\",\n () => {\n const sx = validateInt(x);\n const sy = validateInt(y);\n const os = currentPlatform();\n\n if (os === \"darwin\") {\n if (commandExists(\"cliclick\")) {\n runCommand(\"cliclick\", [`c:${sx},${sy}`], 5000);\n } else {\n runCommand(\n \"osascript\",\n [\n \"-e\",\n `tell application \"System Events\" to click at {${sx}, ${sy}}`,\n ],\n 5000,\n );\n }\n } else if (os === \"linux\") {\n requireXdotool();\n runCommand(\n \"xdotool\",\n [\"mousemove\", String(sx), String(sy), \"click\", \"1\"],\n 5000,\n );\n } else if (os === \"win32\") {\n const ps = [\n \"Add-Type -AssemblyName System.Windows.Forms\",\n `[System.Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point(${sx},${sy})`,\n `Add-Type -MemberDefinition '[DllImport(\"user32.dll\")] public static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);' -Name Win32Mouse -Namespace Win32`,\n \"[Win32.Win32Mouse]::mouse_event(0x0002, 0, 0, 0, 0); [Win32.Win32Mouse]::mouse_event(0x0004, 0, 0, 0, 0)\",\n ].join(\"; \");\n runCommand(\"powershell\", [\"-Command\", ps], 5000);\n }\n },\n \"desktop_click\",\n );\n}\n\nexport function desktopClickWithModifiers(\n x: number,\n y: number,\n modifiers: string[],\n): void {\n runWithAccessibilityPermission(\n \"desktop_click_with_modifiers\",\n () => {\n const sx = validateInt(x);\n const sy = validateInt(y);\n const os = currentPlatform();\n const normalizedModifiers = normalizeModifiers(modifiers);\n\n if (normalizedModifiers.length === 0) {\n desktopClick(sx, sy);\n return;\n }\n\n if (os === \"darwin\") {\n const flagMap: Record<string, string> = {\n cmd: \".maskCommand\",\n command: \".maskCommand\",\n meta: \".maskCommand\",\n super: \".maskCommand\",\n ctrl: \".maskControl\",\n control: \".maskControl\",\n alt: \".maskAlternate\",\n option: \".maskAlternate\",\n shift: \".maskShift\",\n };\n const flags = normalizedModifiers\n .map((modifier) => flagMap[modifier])\n .filter(Boolean);\n const flagExpr = flags.length > 0 ? `[${flags.join(\", \")}]` : \"[]\";\n const swiftScript = `\nimport Cocoa\nlet point = CGPoint(x: ${sx}, y: ${sy})\nlet flags: CGEventFlags = ${flagExpr}\nlet down = CGEvent(mouseEventSource: nil, mouseType: .leftMouseDown, mouseCursorPosition: point, mouseButton: .left)\ndown?.flags = flags\ndown?.post(tap: .cghidEventTap)\nlet up = CGEvent(mouseEventSource: nil, mouseType: .leftMouseUp, mouseCursorPosition: point, mouseButton: .left)\nup?.flags = flags\nup?.post(tap: .cghidEventTap)\n`;\n runCommand(\"swift\", [\"-e\", swiftScript], 10000);\n return;\n }\n\n if (os === \"linux\") {\n requireXdotool();\n const modMap: Record<string, string> = {\n cmd: \"super\",\n command: \"super\",\n meta: \"super\",\n super: \"super\",\n ctrl: \"ctrl\",\n control: \"ctrl\",\n alt: \"alt\",\n option: \"alt\",\n shift: \"shift\",\n };\n const keys = normalizedModifiers.map(\n (modifier) => modMap[modifier] ?? modifier,\n );\n runCommand(\n \"xdotool\",\n [\n ...keys.flatMap((key) => [\"keydown\", key]),\n \"mousemove\",\n String(sx),\n String(sy),\n \"click\",\n \"1\",\n ...[...keys].reverse().flatMap((key) => [\"keyup\", key]),\n ],\n 5000,\n );\n return;\n }\n\n if (os === \"win32\") {\n const vkMap: Record<string, number> = {\n cmd: 0x5b,\n command: 0x5b,\n meta: 0x5b,\n super: 0x5b,\n ctrl: 0x11,\n control: 0x11,\n alt: 0x12,\n option: 0x12,\n shift: 0x10,\n };\n const keyDown = normalizedModifiers\n .map((modifier) => vkMap[modifier])\n .filter((code): code is number => Number.isFinite(code))\n .map(\n (code) => `[Win32.Win32Keyboard]::keybd_event(${code}, 0, 0, 0)`,\n );\n const keyUp = [...normalizedModifiers]\n .reverse()\n .map((modifier) => vkMap[modifier])\n .filter((code): code is number => Number.isFinite(code))\n .map(\n (code) => `[Win32.Win32Keyboard]::keybd_event(${code}, 0, 2, 0)`,\n );\n const ps = [\n \"Add-Type -AssemblyName System.Windows.Forms\",\n `[System.Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point(${sx},${sy})`,\n `Add-Type -MemberDefinition '[DllImport(\"user32.dll\")] public static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo); [DllImport(\"user32.dll\")] public static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);' -Name Win32Keyboard -Namespace Win32`,\n ...keyDown,\n \"[Win32.Win32Keyboard]::mouse_event(0x0002, 0, 0, 0, 0); [Win32.Win32Keyboard]::mouse_event(0x0004, 0, 0, 0, 0)\",\n ...keyUp,\n ].join(\"; \");\n runCommand(\"powershell\", [\"-Command\", ps], 5000);\n }\n },\n \"desktop_click_with_modifiers\",\n );\n}\n\n// ── Double Click ────────────────────────────────────────────────────────────\n\nexport function desktopDoubleClick(x: number, y: number): void {\n runWithAccessibilityPermission(\n \"desktop_double_click\",\n () => {\n const sx = validateInt(x);\n const sy = validateInt(y);\n const os = currentPlatform();\n\n if (os === \"darwin\") {\n if (commandExists(\"cliclick\")) {\n runCommand(\"cliclick\", [`dc:${sx},${sy}`], 5000);\n } else {\n const swiftScript = `\nimport Cocoa\nlet point = CGPoint(x: ${sx}, y: ${sy})\nlet down1 = CGEvent(mouseEventSource: nil, mouseType: .leftMouseDown, mouseCursorPosition: point, mouseButton: .left)\ndown1?.setIntegerValueField(.mouseEventClickState, value: 1)\ndown1?.post(tap: .cghidEventTap)\nlet up1 = CGEvent(mouseEventSource: nil, mouseType: .leftMouseUp, mouseCursorPosition: point, mouseButton: .left)\nup1?.setIntegerValueField(.mouseEventClickState, value: 1)\nup1?.post(tap: .cghidEventTap)\nusleep(50000)\nlet down2 = CGEvent(mouseEventSource: nil, mouseType: .leftMouseDown, mouseCursorPosition: point, mouseButton: .left)\ndown2?.setIntegerValueField(.mouseEventClickState, value: 2)\ndown2?.post(tap: .cghidEventTap)\nlet up2 = CGEvent(mouseEventSource: nil, mouseType: .leftMouseUp, mouseCursorPosition: point, mouseButton: .left)\nup2?.setIntegerValueField(.mouseEventClickState, value: 2)\nup2?.post(tap: .cghidEventTap)\n`;\n runCommand(\"swift\", [\"-e\", swiftScript], 10000);\n }\n } else if (os === \"linux\") {\n requireXdotool();\n runCommand(\n \"xdotool\",\n [\"mousemove\", String(sx), String(sy), \"click\", \"--repeat\", \"2\", \"1\"],\n 5000,\n );\n } else if (os === \"win32\") {\n const ps = [\n \"Add-Type -AssemblyName System.Windows.Forms\",\n `[System.Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point(${sx},${sy})`,\n `Add-Type -MemberDefinition '[DllImport(\"user32.dll\")] public static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);' -Name Win32Mouse -Namespace Win32`,\n \"[Win32.Win32Mouse]::mouse_event(0x0002, 0, 0, 0, 0); [Win32.Win32Mouse]::mouse_event(0x0004, 0, 0, 0, 0)\",\n \"[Win32.Win32Mouse]::mouse_event(0x0002, 0, 0, 0, 0); [Win32.Win32Mouse]::mouse_event(0x0004, 0, 0, 0, 0)\",\n ].join(\"; \");\n runCommand(\"powershell\", [\"-Command\", ps], 5000);\n }\n },\n \"desktop_double_click\",\n );\n}\n\n// ── Right Click ─────────────────────────────────────────────────────────────\n\nexport function desktopRightClick(x: number, y: number): void {\n runWithAccessibilityPermission(\n \"desktop_right_click\",\n () => {\n const sx = validateInt(x);\n const sy = validateInt(y);\n const os = currentPlatform();\n\n if (os === \"darwin\") {\n if (commandExists(\"cliclick\")) {\n runCommand(\"cliclick\", [`rc:${sx},${sy}`], 5000);\n } else {\n const swiftScript = `\nimport Cocoa\nlet point = CGPoint(x: ${sx}, y: ${sy})\nCGEvent(mouseEventSource: nil, mouseType: .rightMouseDown, mouseCursorPosition: point, mouseButton: .right)?.post(tap: .cghidEventTap)\nCGEvent(mouseEventSource: nil, mouseType: .rightMouseUp, mouseCursorPosition: point, mouseButton: .right)?.post(tap: .cghidEventTap)\n`;\n runCommand(\"swift\", [\"-e\", swiftScript], 10000);\n }\n } else if (os === \"linux\") {\n requireXdotool();\n runCommand(\n \"xdotool\",\n [\"mousemove\", String(sx), String(sy), \"click\", \"3\"],\n 5000,\n );\n } else if (os === \"win32\") {\n const ps = [\n \"Add-Type -AssemblyName System.Windows.Forms\",\n `[System.Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point(${sx},${sy})`,\n `Add-Type -MemberDefinition '[DllImport(\"user32.dll\")] public static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);' -Name Win32Mouse -Namespace Win32`,\n \"[Win32.Win32Mouse]::mouse_event(0x0008, 0, 0, 0, 0); [Win32.Win32Mouse]::mouse_event(0x0010, 0, 0, 0, 0)\",\n ].join(\"; \");\n runCommand(\"powershell\", [\"-Command\", ps], 5000);\n }\n },\n \"desktop_right_click\",\n );\n}\n\n// ── Mouse Move ──────────────────────────────────────────────────────────────\n\nexport function desktopMouseMove(x: number, y: number): void {\n runWithAccessibilityPermission(\n \"desktop_mouse_move\",\n () => {\n const sx = validateInt(x);\n const sy = validateInt(y);\n const os = currentPlatform();\n\n if (os === \"darwin\") {\n if (commandExists(\"cliclick\")) {\n runCommand(\"cliclick\", [`m:${sx},${sy}`], 5000);\n } else {\n // JXA (JavaScript for Automation) CoreGraphics fallback — no deps.\n const jxa = `ObjC.import('CoreGraphics'); const e = $.CGEventCreateMouseEvent($(), $.kCGEventMouseMoved, {x:${sx}, y:${sy}}, $.kCGMouseButtonLeft); $.CGEventPost($.kCGHIDEventTap, e);`;\n runCommand(\"osascript\", [\"-l\", \"JavaScript\", \"-e\", jxa], 5000);\n }\n } else if (os === \"linux\") {\n requireXdotool();\n runCommand(\"xdotool\", [\"mousemove\", String(sx), String(sy)], 5000);\n } else if (os === \"win32\") {\n const ps = [\n \"Add-Type -AssemblyName System.Windows.Forms\",\n `[System.Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point(${sx},${sy})`,\n ].join(\"; \");\n runCommand(\"powershell\", [\"-Command\", ps], 5000);\n }\n },\n \"desktop_mouse_move\",\n );\n}\n\n// ── Drag ────────────────────────────────────────────────────────────────────\n\nexport function desktopDrag(\n x1: number,\n y1: number,\n x2: number,\n y2: number,\n): void {\n runWithAccessibilityPermission(\n \"desktop_drag\",\n () => {\n const sx1 = validateInt(x1);\n const sy1 = validateInt(y1);\n const sx2 = validateInt(x2);\n const sy2 = validateInt(y2);\n const os = currentPlatform();\n\n if (os === \"darwin\") {\n if (commandExists(\"cliclick\")) {\n runCommand(\n \"cliclick\",\n [`dd:${sx1},${sy1}`, `du:${sx2},${sy2}`],\n 10000,\n );\n } else {\n // AppleScript drag is limited; best-effort\n const script = [\n `tell application \"System Events\"`,\n ` click at {${sx1}, ${sy1}}`,\n ` delay 0.1`,\n ` click at {${sx2}, ${sy2}}`,\n `end tell`,\n ].join(\"\\n\");\n runCommand(\"osascript\", [\"-e\", script], 10000);\n }\n } else if (os === \"linux\") {\n requireXdotool();\n runCommand(\n \"xdotool\",\n [\n \"mousemove\",\n String(sx1),\n String(sy1),\n \"mousedown\",\n \"1\",\n \"mousemove\",\n \"--sync\",\n String(sx2),\n String(sy2),\n \"mouseup\",\n \"1\",\n ],\n 10000,\n );\n } else if (os === \"win32\") {\n const ps = [\n \"Add-Type -AssemblyName System.Windows.Forms\",\n `Add-Type -MemberDefinition '[DllImport(\"user32.dll\")] public static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);' -Name Win32Mouse -Namespace Win32`,\n `[System.Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point(${sx1},${sy1})`,\n \"Start-Sleep -Milliseconds 50\",\n \"[Win32.Win32Mouse]::mouse_event(0x0002, 0, 0, 0, 0)\", // left down\n \"Start-Sleep -Milliseconds 50\",\n `[System.Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point(${sx2},${sy2})`,\n \"Start-Sleep -Milliseconds 50\",\n \"[Win32.Win32Mouse]::mouse_event(0x0004, 0, 0, 0, 0)\", // left up\n ].join(\"; \");\n runCommand(\"powershell\", [\"-Command\", ps], 10000);\n }\n },\n \"desktop_drag\",\n );\n}\n\n// ── Scroll ──────────────────────────────────────────────────────────────────\n\nexport function desktopScroll(\n x: number,\n y: number,\n direction: \"up\" | \"down\" | \"left\" | \"right\",\n amount = 3,\n): void {\n runWithAccessibilityPermission(\n \"desktop_scroll\",\n () => {\n const sx = validateInt(x);\n const sy = validateInt(y);\n const clicks = Math.max(1, Math.min(validateInt(amount), 20));\n const os = currentPlatform();\n\n if (os === \"darwin\") {\n // JXA CGEventCreateScrollWheelEvent — works without cliclick.\n // For vertical scrolls, positive Y deltas scroll up, negative scrolls down.\n // For horizontal, positive X deltas scroll right, negative scrolls left.\n const axis =\n direction === \"left\" || direction === \"right\"\n ? \"horizontal\"\n : \"vertical\";\n const delta =\n direction === \"up\" || direction === \"left\" ? clicks : -clicks;\n const jxa =\n axis === \"vertical\"\n ? `ObjC.import('CoreGraphics'); const e = $.CGEventCreateScrollWheelEvent($(), $.kCGScrollEventUnitLine, 1, ${delta}); $.CGEventPost($.kCGHIDEventTap, e);`\n : `ObjC.import('CoreGraphics'); const e = $.CGEventCreateScrollWheelEvent($(), $.kCGScrollEventUnitLine, 2, 0, ${delta}); $.CGEventPost($.kCGHIDEventTap, e);`;\n runCommand(\"osascript\", [\"-l\", \"JavaScript\", \"-e\", jxa], 5000);\n } else if (os === \"linux\") {\n requireXdotool();\n // Move to position first\n runCommand(\"xdotool\", [\"mousemove\", String(sx), String(sy)], 3000);\n // xdotool: button 4=scroll up, 5=scroll down, 6=scroll left, 7=scroll right\n const button =\n direction === \"up\"\n ? \"4\"\n : direction === \"down\"\n ? \"5\"\n : direction === \"left\"\n ? \"6\"\n : \"7\";\n for (let i = 0; i < clicks; i++) {\n runCommand(\"xdotool\", [\"click\", button], 2000);\n }\n } else if (os === \"win32\") {\n // MOUSEEVENTF_WHEEL = 0x0800, positive = up, negative = down\n // Each wheel click is 120 units\n const wheelDelta =\n (direction === \"up\" || direction === \"left\" ? 1 : -1) * 120 * clicks;\n const ps = [\n \"Add-Type -AssemblyName System.Windows.Forms\",\n `[System.Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point(${sx},${sy})`,\n `Add-Type -MemberDefinition '[DllImport(\"user32.dll\")] public static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);' -Name Win32Mouse -Namespace Win32`,\n `[Win32.Win32Mouse]::mouse_event(0x0800, 0, 0, ${wheelDelta}, 0)`,\n ].join(\"; \");\n runCommand(\"powershell\", [\"-Command\", ps], 5000);\n }\n },\n \"desktop_scroll\",\n );\n}\n\n// ── Type Text ───────────────────────────────────────────────────────────────\n\nexport function desktopType(text: string): void {\n runWithAccessibilityPermission(\n \"desktop_type\",\n () => {\n const safeText = validateText(text);\n const os = currentPlatform();\n\n if (os === \"darwin\") {\n if (commandExists(\"cliclick\")) {\n runCommand(\"cliclick\", [`t:${safeText}`], 10000);\n } else {\n runCommand(\n \"osascript\",\n [\n \"-e\",\n `tell application \"System Events\" to keystroke ${escapeAppleScript(safeText)}`,\n ],\n 10000,\n );\n }\n } else if (os === \"linux\") {\n requireXdotool();\n runCommand(\"xdotool\", [\"type\", \"--\", safeText], 10000);\n } else if (os === \"win32\") {\n const escaped = safeText.replace(/'/g, \"''\");\n runCommand(\n \"powershell\",\n [\n \"-Command\",\n `Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.SendKeys]::SendWait('${escaped}')`,\n ],\n 10000,\n );\n }\n },\n \"desktop_type\",\n );\n}\n\n// ── Key Press ───────────────────────────────────────────────────────────────\n\n/**\n * Press a single key by name (e.g. \"Return\", \"Tab\", \"Escape\", \"F5\").\n */\nexport function desktopKeyPress(key: string): void {\n runWithAccessibilityPermission(\n \"desktop_key_press\",\n () => {\n const safeKey = validateKeypress(key);\n const os = currentPlatform();\n\n if (os === \"darwin\") {\n if (commandExists(\"cliclick\")) {\n runCommand(\"cliclick\", [`kp:${toCliclickKeyName(safeKey)}`], 5000);\n } else {\n // Map common key names to macOS key codes\n const keyCodes: Record<string, number> = {\n return: 36,\n enter: 36,\n tab: 48,\n space: 49,\n escape: 53,\n esc: 53,\n delete: 51,\n backspace: 51,\n forwarddelete: 117,\n left: 123,\n right: 124,\n down: 125,\n up: 126,\n home: 115,\n end: 119,\n pageup: 116,\n pagedown: 121,\n f1: 122,\n f2: 120,\n f3: 99,\n f4: 118,\n f5: 96,\n f6: 97,\n f7: 98,\n f8: 100,\n f9: 101,\n f10: 109,\n f11: 103,\n f12: 111,\n };\n const normalized = safeKey.trim().toLowerCase();\n const code = keyCodes[normalized];\n if (code !== undefined) {\n runCommand(\n \"osascript\",\n [\"-e\", `tell application \"System Events\" to key code ${code}`],\n 5000,\n );\n } else {\n runCommand(\n \"osascript\",\n [\n \"-e\",\n `tell application \"System Events\" to keystroke ${escapeAppleScript(safeKey)}`,\n ],\n 5000,\n );\n }\n }\n } else if (os === \"linux\") {\n requireXdotool();\n const xKey = safeXdotoolKey(safeKey);\n runCommand(\"xdotool\", [\"key\", xKey], 5000);\n } else if (os === \"win32\") {\n const escaped = safeKey.replace(/'/g, \"''\");\n runCommand(\n \"powershell\",\n [\n \"-Command\",\n `Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.SendKeys]::SendWait('${escaped}')`,\n ],\n 5000,\n );\n }\n },\n \"desktop_key_press\",\n );\n}\n\n// ── Key Combo ───────────────────────────────────────────────────────────────\n\n/**\n * Press a key combination like \"ctrl+c\", \"cmd+shift+s\", \"alt+F4\".\n * Modifier names: ctrl, shift, alt, cmd/meta/super.\n *\n * Ported from open-computer-use desktopKeyCombo().\n */\nexport function desktopKeyCombo(combo: string): void {\n runWithAccessibilityPermission(\n \"desktop_key_combo\",\n () => {\n const safeCombo = validateKeypress(combo);\n const parts = safeCombo.split(\"+\").map((p) => p.trim().toLowerCase());\n const os = currentPlatform();\n\n if (os === \"darwin\") {\n // Map modifier names to AppleScript \"using\" clauses\n const modifierMap: Record<string, string> = {\n cmd: \"command down\",\n command: \"command down\",\n meta: \"command down\",\n super: \"command down\",\n ctrl: \"control down\",\n control: \"control down\",\n shift: \"shift down\",\n alt: \"option down\",\n option: \"option down\",\n };\n const macKeyCodes: Record<string, number> = {\n return: 36,\n enter: 36,\n tab: 48,\n space: 49,\n escape: 53,\n esc: 53,\n delete: 51,\n backspace: 51,\n forwarddelete: 117,\n left: 123,\n right: 124,\n down: 125,\n up: 126,\n home: 115,\n end: 119,\n pageup: 116,\n pagedown: 121,\n f1: 122,\n f2: 120,\n f3: 99,\n f4: 118,\n f5: 96,\n f6: 97,\n f7: 98,\n f8: 100,\n f9: 101,\n f10: 109,\n f11: 103,\n f12: 111,\n };\n const modifiers: string[] = [];\n let key = \"\";\n for (const part of parts) {\n if (modifierMap[part]) {\n modifiers.push(modifierMap[part]);\n } else {\n key = part;\n }\n }\n const using =\n modifiers.length > 0 ? ` using {${modifiers.join(\", \")}}` : \"\";\n const canonical = canonicalKeyName(key);\n const keyCode = macKeyCodes[canonical];\n const command =\n keyCode !== undefined\n ? `tell application \"System Events\" to key code ${keyCode}${using}`\n : `tell application \"System Events\" to keystroke ${escapeAppleScript(key)}${using}`;\n runCommand(\"osascript\", [\"-e\", command], 5000);\n } else if (os === \"linux\") {\n requireXdotool();\n // xdotool key combo: \"ctrl+c\" → \"ctrl+c\" (xdotool understands this directly)\n const xParts = parts.map((p) => {\n const xMap: Record<string, string> = {\n cmd: \"super\",\n command: \"super\",\n meta: \"super\",\n ctrl: \"ctrl\",\n control: \"ctrl\",\n };\n return xMap[p] ?? toXdotoolKeyName(p);\n });\n runCommand(\"xdotool\", [\"key\", xParts.join(\"+\")], 5000);\n } else if (os === \"win32\") {\n // PowerShell SendKeys: ^ = Ctrl, + = Shift, % = Alt\n const psModMap: Record<string, string> = {\n ctrl: \"^\",\n control: \"^\",\n shift: \"+\",\n alt: \"%\",\n cmd: \"^\",\n command: \"^\",\n meta: \"^\",\n super: \"^\", // Map cmd → ctrl on Windows\n };\n let prefix = \"\";\n let key = \"\";\n for (const part of parts) {\n if (psModMap[part]) {\n prefix += psModMap[part];\n } else {\n key = part;\n }\n }\n const mappedKey = toWindowsSendKey(key);\n const sendKey = `${prefix}${mappedKey}`.replace(/'/g, \"''\");\n runCommand(\n \"powershell\",\n [\n \"-Command\",\n `Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.SendKeys]::SendWait('${sendKey}')`,\n ],\n 5000,\n );\n }\n },\n \"desktop_key_combo\",\n );\n}\n\nfunction runWithAccessibilityPermission<T>(\n operation: string,\n handler: () => T,\n _command?: string,\n): T {\n try {\n return handler();\n } catch (error) {\n if (isPermissionDeniedError(error)) {\n throw error;\n }\n const permissionError = classifyPermissionDeniedError(error, {\n permissionType: \"accessibility\",\n operation,\n });\n if (permissionError) {\n throw permissionError;\n }\n throw error;\n }\n}\n\n// ── Helpers ─────────────────────────────────────────────────────────────────\n\nfunction normalizeModifiers(modifiers: string[]): string[] {\n const normalized = modifiers\n .map((modifier) => modifier.trim().toLowerCase())\n .filter(Boolean);\n\n for (const modifier of normalized) {\n if (\n ![\n \"cmd\",\n \"command\",\n \"meta\",\n \"super\",\n \"ctrl\",\n \"control\",\n \"alt\",\n \"option\",\n \"shift\",\n ].includes(modifier)\n ) {\n throw new Error(`Unsupported modifier key: ${modifier}`);\n }\n }\n\n return normalized;\n}\n\nfunction requireXdotool(): void {\n if (!commandExists(\"xdotool\")) {\n throw new Error(\n \"xdotool is required for mouse/keyboard control on Linux. Install via: sudo apt install xdotool\",\n );\n }\n}\n\n// ── Set value (a11y write) ────────────────────────────────────────────────────\n\n/**\n * Windows fast-path for `set_value` (#9170 — trycua/cua `set_value`): use UI\n * Automation `ValuePattern.SetValue` on the element under (x,y) to set its value\n * directly, without synthesizing keystrokes. Returns `true` if the element\n * exposed ValuePattern and was set; `false` (incl. on any error) so the caller\n * falls back to the universal focus → select-all → type path.\n *\n * Uses `Add-Type -AssemblyName` (signed framework assemblies), not a\n * runtime-compiled inline class. Real actuation is exercised by the interactive\n * real-driver lane; this box's session can't host a ValuePattern control to\n * probe it (see #9170).\n */\nexport function win32TrySetValueByPattern(\n x: number,\n y: number,\n value: string,\n): boolean {\n if (currentPlatform() !== \"win32\") return false;\n const sx = validateInt(x);\n const sy = validateInt(y);\n const escaped = validateText(value).replace(/'/g, \"''\");\n const ps = [\n \"Add-Type -AssemblyName UIAutomationClient,UIAutomationTypes,WindowsBase\",\n `$pt = New-Object System.Windows.Point(${sx}, ${sy})`,\n \"$el = [System.Windows.Automation.AutomationElement]::FromPoint($pt)\",\n \"if ($el -eq $null) { 'NO_ELEMENT'; exit 0 }\",\n \"$hasVal = $el.GetCurrentPropertyValue([System.Windows.Automation.AutomationElement]::IsValuePatternAvailableProperty)\",\n \"if (-not $hasVal) { 'NO_PATTERN'; exit 0 }\",\n \"$vp = $el.GetCurrentPattern([System.Windows.Automation.ValuePattern]::Pattern)\",\n `$vp.SetValue('${escaped}')`,\n \"'VALUE_SET'\",\n ].join(\"; \");\n try {\n const out = runCommand(\"powershell\", [\"-Command\", ps], 10000);\n return out.includes(\"VALUE_SET\");\n } catch {\n return false;\n }\n}\n",
|
|
28
|
+
"/**\n * Cross-platform desktop driver backed by @nut-tree-fork/nut-js.\n *\n * Wraps native libnut bindings into the same input surface exposed by\n * the legacy per-OS shell drivers in `desktop.ts` and `screenshot.ts`.\n * Selected at runtime via `ELIZA_COMPUTERUSE_DRIVER=nutjs` (default) — the\n * legacy shell drivers remain the fallback when the env var is set to\n * `legacy` or when the native module fails to load.\n *\n * Native module loading: nut-js ships prebuilt binaries via `libnut`. We\n * load it eagerly at module init and surface a clean diagnostic if the\n * binary is missing for the current arch (`isAvailable()` reports false).\n */\n\nimport { readFileSync, unlinkSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type {} from \"@nut-tree-fork/nut-js\";\nimport type { ScreenRegion } from \"../types.js\";\nimport { canonicalKeyName, validateInt, validateText } from \"./helpers.js\";\n\nconst requireFromHere = createRequire(import.meta.url);\n\ninterface NutModule {\n mouse: {\n config: { mouseSpeed: number; autoDelayMs: number };\n setPosition: (point: { x: number; y: number }) => Promise<unknown>;\n getPosition: () => Promise<{ x: number; y: number }>;\n move: (path: Promise<unknown> | unknown) => Promise<unknown>;\n click: (button: number) => Promise<unknown>;\n doubleClick: (button: number) => Promise<unknown>;\n pressButton: (button: number) => Promise<unknown>;\n releaseButton: (button: number) => Promise<unknown>;\n scrollUp: (amount: number) => Promise<unknown>;\n scrollDown: (amount: number) => Promise<unknown>;\n scrollLeft: (amount: number) => Promise<unknown>;\n scrollRight: (amount: number) => Promise<unknown>;\n };\n keyboard: {\n config: { autoDelayMs: number };\n type: (input: string) => Promise<unknown>;\n pressKey: (...keys: number[]) => Promise<unknown>;\n releaseKey: (...keys: number[]) => Promise<unknown>;\n };\n screen: {\n width: () => Promise<number>;\n height: () => Promise<number>;\n capture: (\n fileName: string,\n fileFormat: number,\n filePath?: string,\n ) => Promise<string>;\n captureRegion: (\n fileName: string,\n region: { left: number; top: number; width: number; height: number },\n fileFormat: number,\n filePath?: string,\n ) => Promise<string>;\n };\n Button: { LEFT: number; MIDDLE: number; RIGHT: number };\n Key: Record<string, number>;\n Point: new (x: number, y: number) => { x: number; y: number };\n straightTo: (target: { x: number; y: number }) => Promise<unknown> | unknown;\n FileType: { PNG: number; JPG: number };\n}\n\nlet cachedModule: NutModule | null = null;\nlet loadError: Error | null = null;\n\nfunction loadNut(): NutModule | null {\n if (cachedModule !== null) return cachedModule;\n if (loadError !== null) return null;\n try {\n const mod = requireFromHere(\"@nut-tree-fork/nut-js\") as NutModule;\n mod.mouse.config.mouseSpeed = 1000;\n mod.mouse.config.autoDelayMs = 0;\n mod.keyboard.config.autoDelayMs = 0;\n cachedModule = mod;\n return mod;\n } catch (err) {\n loadError = err instanceof Error ? err : new Error(String(err));\n return null;\n }\n}\n\nexport function isAvailable(): boolean {\n return loadNut() !== null;\n}\n\nexport function loadFailureReason(): string | null {\n if (cachedModule) return null;\n loadNut();\n return loadError ? loadError.message : null;\n}\n\nfunction nut(): NutModule {\n const m = loadNut();\n if (!m) {\n throw new Error(\n `nutjs driver unavailable: ${loadError?.message ?? \"module did not load\"}`,\n );\n }\n return m;\n}\n\nconst MODIFIER_KEYS: Record<string, string[]> = {\n cmd: [\"LeftSuper\"],\n command: [\"LeftSuper\"],\n meta: [\"LeftSuper\"],\n super: [\"LeftSuper\"],\n win: [\"LeftSuper\"],\n ctrl: [\"LeftControl\"],\n control: [\"LeftControl\"],\n alt: [\"LeftAlt\"],\n option: [\"LeftAlt\"],\n shift: [\"LeftShift\"],\n};\n\nconst NAMED_KEY_TO_NUT: Record<string, string> = {\n enter: \"Return\",\n return: \"Return\",\n tab: \"Tab\",\n space: \"Space\",\n escape: \"Escape\",\n esc: \"Escape\",\n backspace: \"Backspace\",\n delete: \"Delete\",\n forwarddelete: \"Delete\",\n left: \"Left\",\n right: \"Right\",\n up: \"Up\",\n down: \"Down\",\n home: \"Home\",\n end: \"End\",\n pageup: \"PageUp\",\n pagedown: \"PageDown\",\n};\n\nfunction resolveKeyCode(key: string): number {\n const m = nut();\n const canonical = canonicalKeyName(key);\n // Function keys F1..F24\n const fnMatch = canonical.match(/^f(\\d{1,2})$/);\n if (fnMatch) {\n const name = `F${fnMatch[1]}`;\n const code = m.Key[name];\n if (code !== undefined) return code;\n }\n const mapped = NAMED_KEY_TO_NUT[canonical];\n if (mapped !== undefined) {\n const code = m.Key[mapped];\n if (code !== undefined) return code;\n }\n // Modifier names (shift / ctrl / alt / cmd / meta / super / win) — needed so\n // key_down/key_up can hold a bare modifier. These live in MODIFIER_KEYS as\n // nutjs Key names (e.g. \"LeftShift\"); resolve to the left-hand variant.\n const modifierNames = MODIFIER_KEYS[canonical] ?? MODIFIER_KEYS[key.trim().toLowerCase()];\n if (modifierNames && modifierNames.length > 0) {\n const code = m.Key[modifierNames[0]];\n if (code !== undefined) return code;\n }\n // Single character — map A-Z / 0-9 directly via Key enum\n if (key.length === 1) {\n const upper = key.toUpperCase();\n if (m.Key[upper] !== undefined) return m.Key[upper];\n const digitName = `Num${key}`;\n if (m.Key[digitName] !== undefined) return m.Key[digitName];\n }\n // Last resort: lookup by raw name as-typed\n const raw = m.Key[key];\n if (raw !== undefined) return raw;\n throw new Error(`Unsupported key for nutjs driver: \"${key}\"`);\n}\n\n/** Resolve a POSIX-style button name to the nutjs `Button` enum value. Pure-ish\n * (reads the loaded module). Throws on an unknown button. */\nfunction resolveButton(button: \"left\" | \"middle\" | \"right\"): number {\n const m = nut();\n switch (button) {\n case \"left\":\n return m.Button.LEFT;\n case \"middle\":\n return m.Button.MIDDLE;\n case \"right\":\n return m.Button.RIGHT;\n default:\n throw new Error(`Unsupported mouse button: \"${button}\"`);\n }\n}\n\nfunction resolveModifierCodes(modifier: string): number[] {\n const m = nut();\n const names = MODIFIER_KEYS[modifier.trim().toLowerCase()];\n if (!names) {\n throw new Error(`Unsupported modifier: \"${modifier}\"`);\n }\n return names.map((name) => {\n const code = m.Key[name];\n if (code === undefined) {\n throw new Error(`nutjs Key enum missing entry for \"${name}\"`);\n }\n return code;\n });\n}\n\n// ── Mouse ───────────────────────────────────────────────────────────────────\n\nexport async function nutClick(x: number, y: number): Promise<void> {\n const m = nut();\n const sx = validateInt(x);\n const sy = validateInt(y);\n await m.mouse.setPosition(new m.Point(sx, sy));\n await m.mouse.click(m.Button.LEFT);\n}\n\nexport async function nutClickWithModifiers(\n x: number,\n y: number,\n modifiers: string[],\n): Promise<void> {\n const m = nut();\n const sx = validateInt(x);\n const sy = validateInt(y);\n const modCodes = modifiers.flatMap((mod) => resolveModifierCodes(mod));\n await m.mouse.setPosition(new m.Point(sx, sy));\n if (modCodes.length === 0) {\n await m.mouse.click(m.Button.LEFT);\n return;\n }\n await m.keyboard.pressKey(...modCodes);\n try {\n await m.mouse.click(m.Button.LEFT);\n } finally {\n await m.keyboard.releaseKey(...modCodes.reverse());\n }\n}\n\nexport async function nutDoubleClick(x: number, y: number): Promise<void> {\n const m = nut();\n await m.mouse.setPosition(new m.Point(validateInt(x), validateInt(y)));\n await m.mouse.doubleClick(m.Button.LEFT);\n}\n\nexport async function nutRightClick(x: number, y: number): Promise<void> {\n const m = nut();\n await m.mouse.setPosition(new m.Point(validateInt(x), validateInt(y)));\n await m.mouse.click(m.Button.RIGHT);\n}\n\nexport async function nutMiddleClick(x: number, y: number): Promise<void> {\n const m = nut();\n await m.mouse.setPosition(new m.Point(validateInt(x), validateInt(y)));\n await m.mouse.click(m.Button.MIDDLE);\n}\n\nexport async function nutMouseMove(x: number, y: number): Promise<void> {\n const m = nut();\n await m.mouse.setPosition(new m.Point(validateInt(x), validateInt(y)));\n}\n\n/**\n * Press (and hold) a mouse button at `(x, y)` without releasing it. Pairs with\n * `nutMouseUp` to express hold-drags, marquee selection, and press-and-hold\n * gestures that a single `click` cannot. The caller is responsible for the\n * matching release.\n */\nexport async function nutMouseDown(\n x: number,\n y: number,\n button: \"left\" | \"middle\" | \"right\" = \"left\",\n): Promise<void> {\n const m = nut();\n await m.mouse.setPosition(new m.Point(validateInt(x), validateInt(y)));\n await m.mouse.pressButton(resolveButton(button));\n}\n\n/** Release a previously-held mouse button at `(x, y)`. See {@link nutMouseDown}. */\nexport async function nutMouseUp(\n x: number,\n y: number,\n button: \"left\" | \"middle\" | \"right\" = \"left\",\n): Promise<void> {\n const m = nut();\n await m.mouse.setPosition(new m.Point(validateInt(x), validateInt(y)));\n await m.mouse.releaseButton(resolveButton(button));\n}\n\n/** Inter-notch / inter-step pacing (ms) — small, just enough to defeat event\n * coalescing in fast consumers (e.g. Chromium's MouseWheelEventQueue) without\n * making input feel sluggish. */\nconst SCROLL_NOTCH_DELAY_MS = 8;\nconst DRAG_STEP_DELAY_MS = 8;\nconst DRAG_STEPS = 20;\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n}\n\n/** Clamp a requested scroll amount to a safe per-notch count (1..20). Pure. */\nexport function clampScrollNotches(amount: number): number {\n return Math.max(1, Math.min(validateInt(amount), 20));\n}\n\n/**\n * Interpolated integer waypoints from (x1,y1) to (x2,y2) over `steps` moves\n * (excludes the start, includes the end). Pure — exported for unit tests.\n */\nexport function interpolateDragSteps(\n x1: number,\n y1: number,\n x2: number,\n y2: number,\n steps: number = DRAG_STEPS,\n): Array<{ x: number; y: number }> {\n const n = Math.max(1, Math.floor(steps));\n const points: Array<{ x: number; y: number }> = [];\n for (let i = 1; i <= n; i += 1) {\n const t = i / n;\n points.push({\n x: Math.round(x1 + (x2 - x1) * t),\n y: Math.round(y1 + (y2 - y1) * t),\n });\n }\n return points;\n}\n\nasync function manualDragMove(\n m: NutModule,\n x1: number,\n y1: number,\n x2: number,\n y2: number,\n): Promise<void> {\n // Interpolated move with the button held — fallback for libnut builds whose\n // `mouse.move(straightTo)` does not carry a real button-down on Windows.\n const points = interpolateDragSteps(x1, y1, x2, y2);\n for (let i = 0; i < points.length; i += 1) {\n await m.mouse.setPosition(new m.Point(points[i].x, points[i].y));\n if (i < points.length - 1) await sleep(DRAG_STEP_DELAY_MS);\n }\n}\n\nexport async function nutDrag(\n x1: number,\n y1: number,\n x2: number,\n y2: number,\n): Promise<void> {\n const m = nut();\n const sx1 = validateInt(x1);\n const sy1 = validateInt(y1);\n const sx2 = validateInt(x2);\n const sy2 = validateInt(y2);\n await m.mouse.setPosition(new m.Point(sx1, sy1));\n await m.mouse.pressButton(m.Button.LEFT);\n try {\n try {\n await m.mouse.move(m.straightTo(new m.Point(sx2, sy2)));\n } catch {\n await manualDragMove(m, sx1, sy1, sx2, sy2);\n }\n } finally {\n await m.mouse.releaseButton(m.Button.LEFT);\n }\n}\n\n/**\n * Densify a polyline by interpolating integer waypoints along every segment so\n * a held-button drag traces curves/corners instead of teleporting corner to\n * corner. Includes the very first point and every segment endpoint. Pure —\n * exported for unit tests.\n *\n * `perSegmentSteps` controls how many intermediate points are inserted between\n * consecutive vertices (≥1; the endpoint is always included).\n */\nexport function densifyDragPath(\n path: Array<{ x: number; y: number }>,\n perSegmentSteps: number = DRAG_STEPS,\n): Array<{ x: number; y: number }> {\n if (path.length === 0) return [];\n const first = { x: validateInt(path[0].x), y: validateInt(path[0].y) };\n const out: Array<{ x: number; y: number }> = [first];\n for (let i = 1; i < path.length; i += 1) {\n const a = out[out.length - 1];\n const b = { x: validateInt(path[i].x), y: validateInt(path[i].y) };\n out.push(...interpolateDragSteps(a.x, a.y, b.x, b.y, perSegmentSteps));\n }\n return out;\n}\n\n/**\n * Press the left button at the first point, move through every interpolated\n * waypoint with the button held, then release at the last point. Backs\n * multi-point `drag(path)` and AOSP swipe paths. Requires ≥2 points.\n */\nexport async function nutDragPath(\n path: Array<{ x: number; y: number }>,\n): Promise<void> {\n if (path.length < 2) {\n throw new Error(\"nutDragPath requires at least two points\");\n }\n const m = nut();\n const points = densifyDragPath(path);\n const start = points[0];\n const end = points[points.length - 1];\n await m.mouse.setPosition(new m.Point(start.x, start.y));\n await m.mouse.pressButton(m.Button.LEFT);\n try {\n for (let i = 1; i < points.length; i += 1) {\n await m.mouse.setPosition(new m.Point(points[i].x, points[i].y));\n if (i < points.length - 1) await sleep(DRAG_STEP_DELAY_MS);\n }\n } finally {\n await m.mouse.setPosition(new m.Point(end.x, end.y));\n await m.mouse.releaseButton(m.Button.LEFT);\n }\n}\n\nexport async function nutGetCursorPosition(): Promise<{\n x: number;\n y: number;\n}> {\n const m = nut();\n const p = await m.mouse.getPosition();\n return { x: Math.round(p.x), y: Math.round(p.y) };\n}\n\nexport async function nutScroll(\n x: number,\n y: number,\n direction: \"up\" | \"down\" | \"left\" | \"right\",\n amount: number,\n): Promise<void> {\n const m = nut();\n const sx = validateInt(x);\n const sy = validateInt(y);\n const clicks = clampScrollNotches(amount);\n await m.mouse.setPosition(new m.Point(sx, sy));\n // Emit one wheel notch at a time so coalescing consumers register each notch.\n for (let i = 0; i < clicks; i += 1) {\n if (direction === \"up\") await m.mouse.scrollUp(1);\n else if (direction === \"down\") await m.mouse.scrollDown(1);\n else if (direction === \"left\") await m.mouse.scrollLeft(1);\n else await m.mouse.scrollRight(1);\n if (i < clicks - 1) await sleep(SCROLL_NOTCH_DELAY_MS);\n }\n}\n\n// ── Keyboard ────────────────────────────────────────────────────────────────\n\nexport async function nutType(text: string): Promise<void> {\n const m = nut();\n const safe = validateText(text);\n await m.keyboard.type(safe);\n}\n\nexport async function nutKeyPress(key: string): Promise<void> {\n const m = nut();\n const code = resolveKeyCode(key);\n await m.keyboard.pressKey(code);\n await m.keyboard.releaseKey(code);\n}\n\n/** Press (and hold) a single key without releasing it. Pairs with `nutKeyUp`\n * to express press-and-hold (e.g. holding Shift while issuing other input). */\nexport async function nutKeyDown(key: string): Promise<void> {\n const m = nut();\n await m.keyboard.pressKey(resolveKeyCode(key));\n}\n\n/** Release a previously-held key. See {@link nutKeyDown}. */\nexport async function nutKeyUp(key: string): Promise<void> {\n const m = nut();\n await m.keyboard.releaseKey(resolveKeyCode(key));\n}\n\nexport async function nutKeyCombo(combo: string): Promise<void> {\n const m = nut();\n const parts = combo.split(\"+\").map((p) => p.trim());\n const modifierCodes: number[] = [];\n let mainKey: string | null = null;\n for (const part of parts) {\n const lower = part.toLowerCase();\n if (MODIFIER_KEYS[lower]) {\n modifierCodes.push(...resolveModifierCodes(lower));\n } else {\n mainKey = part;\n }\n }\n if (!mainKey) {\n throw new Error(\n `Combo \"${combo}\" must include at least one non-modifier key`,\n );\n }\n const mainCode = resolveKeyCode(mainKey);\n if (modifierCodes.length > 0) {\n await m.keyboard.pressKey(...modifierCodes);\n }\n try {\n await m.keyboard.pressKey(mainCode);\n await m.keyboard.releaseKey(mainCode);\n } finally {\n if (modifierCodes.length > 0) {\n await m.keyboard.releaseKey(...modifierCodes.reverse());\n }\n }\n}\n\n// ── Screenshot ──────────────────────────────────────────────────────────────\n\nexport async function nutCaptureScreenshot(\n region?: ScreenRegion,\n): Promise<Buffer> {\n const m = nut();\n const fileName = `computeruse-nutjs-${Date.now()}.png`;\n const dir = tmpdir();\n let absolutePath = \"\";\n try {\n if (region) {\n const r = {\n left: validateInt(region.x),\n top: validateInt(region.y),\n width: validateInt(region.width),\n height: validateInt(region.height),\n };\n absolutePath = await m.screen.captureRegion(\n fileName,\n r,\n m.FileType.PNG,\n dir,\n );\n } else {\n absolutePath = await m.screen.capture(fileName, m.FileType.PNG, dir);\n }\n if (!absolutePath) absolutePath = join(dir, fileName);\n return readFileSync(absolutePath);\n } finally {\n if (absolutePath) {\n try {\n unlinkSync(absolutePath);\n } catch {\n /* best effort */\n }\n }\n }\n}\n\nexport async function nutScreenSize(): Promise<{\n width: number;\n height: number;\n}> {\n const m = nut();\n const [width, height] = await Promise.all([\n m.screen.width(),\n m.screen.height(),\n ]);\n return { width, height };\n}\n",
|
|
29
|
+
"/**\n * Driver-selection seam for desktop input + screenshot capture.\n *\n * Default = `nutjs` (cross-platform native bindings via @nut-tree-fork/nut-js).\n * Set `ELIZA_COMPUTERUSE_DRIVER=legacy` to fall back to the per-OS shell\n * drivers (cliclick/xdotool/PowerShell). The legacy drivers also activate\n * automatically when the nutjs native module fails to load.\n *\n * Each exported function dispatches to the chosen backend. Callers (the\n * service, actions, tests) use these wrappers; the underlying `desktop.ts`\n * and `screenshot.ts` modules remain importable for the legacy code path.\n */\n\nimport type { ScreenRegion } from \"../types.js\";\nimport {\n desktopClick,\n desktopClickWithModifiers,\n desktopDoubleClick,\n desktopDrag,\n desktopKeyCombo,\n desktopKeyPress,\n desktopMouseMove,\n desktopRightClick,\n desktopScroll,\n desktopType,\n legacyGetCursorPosition,\n win32TrySetValueByPattern,\n} from \"./desktop.js\";\nimport {\n loadFailureReason,\n isAvailable as nutAvailable,\n nutCaptureScreenshot,\n nutClick,\n nutClickWithModifiers,\n nutDoubleClick,\n nutDrag,\n nutDragPath,\n nutGetCursorPosition,\n nutKeyCombo,\n nutKeyDown,\n nutKeyPress,\n nutKeyUp,\n nutMiddleClick,\n nutMouseDown,\n nutMouseMove,\n nutMouseUp,\n nutRightClick,\n nutScroll,\n nutType,\n} from \"./nut-driver.js\";\nimport { captureScreenshot as legacyCaptureScreenshot } from \"./screenshot.js\";\n\nexport type DriverName = \"nutjs\" | \"legacy\";\n\nlet warned = false;\n\nexport function selectedDriver(): DriverName {\n const requested = (process.env.ELIZA_COMPUTERUSE_DRIVER ?? \"nutjs\")\n .trim()\n .toLowerCase();\n if (requested === \"legacy\") return \"legacy\";\n if (requested !== \"nutjs\") {\n if (!warned) {\n // eslint-disable-next-line no-console\n console.warn(\n `[computeruse] Unknown ELIZA_COMPUTERUSE_DRIVER=${requested}; falling back to legacy.`,\n );\n warned = true;\n }\n return \"legacy\";\n }\n if (!nutAvailable()) {\n if (!warned) {\n // eslint-disable-next-line no-console\n console.warn(\n `[computeruse] nutjs driver unavailable (${loadFailureReason()}); falling back to legacy shell drivers.`,\n );\n warned = true;\n }\n return \"legacy\";\n }\n return \"nutjs\";\n}\n\n// ── Mouse ───────────────────────────────────────────────────────────────────\n\nexport async function driverClick(x: number, y: number): Promise<void> {\n if (selectedDriver() === \"nutjs\") return nutClick(x, y);\n desktopClick(x, y);\n}\n\nexport async function driverClickWithModifiers(\n x: number,\n y: number,\n modifiers: string[],\n): Promise<void> {\n if (selectedDriver() === \"nutjs\")\n return nutClickWithModifiers(x, y, modifiers);\n desktopClickWithModifiers(x, y, modifiers);\n}\n\nexport async function driverDoubleClick(x: number, y: number): Promise<void> {\n if (selectedDriver() === \"nutjs\") return nutDoubleClick(x, y);\n desktopDoubleClick(x, y);\n}\n\nexport async function driverRightClick(x: number, y: number): Promise<void> {\n if (selectedDriver() === \"nutjs\") return nutRightClick(x, y);\n desktopRightClick(x, y);\n}\n\n/** The legacy shell drivers (cliclick/xdotool/PowerShell) do not expose the\n * granular press/hold primitives below. Throw a clear, actionable error rather\n * than silently no-op'ing — set `ELIZA_COMPUTERUSE_DRIVER=nutjs` to use them. */\nfunction requireNutForGranular(verb: string): never {\n throw new Error(\n `[computeruse] \"${verb}\" requires the nutjs driver (granular press/hold ` +\n `is not available on the legacy shell drivers). The nutjs native module ` +\n `is unavailable (${loadFailureReason() ?? \"unknown reason\"}). ` +\n `Set ELIZA_COMPUTERUSE_DRIVER=nutjs once the native binding loads.`,\n );\n}\n\nexport async function driverMiddleClick(x: number, y: number): Promise<void> {\n if (selectedDriver() === \"nutjs\") return nutMiddleClick(x, y);\n return requireNutForGranular(\"middle_click\");\n}\n\nexport async function driverMouseDown(\n x: number,\n y: number,\n button: \"left\" | \"middle\" | \"right\" = \"left\",\n): Promise<void> {\n if (selectedDriver() === \"nutjs\") return nutMouseDown(x, y, button);\n return requireNutForGranular(\"mouse_down\");\n}\n\nexport async function driverMouseUp(\n x: number,\n y: number,\n button: \"left\" | \"middle\" | \"right\" = \"left\",\n): Promise<void> {\n if (selectedDriver() === \"nutjs\") return nutMouseUp(x, y, button);\n return requireNutForGranular(\"mouse_up\");\n}\n\nexport async function driverMouseMove(x: number, y: number): Promise<void> {\n if (selectedDriver() === \"nutjs\") return nutMouseMove(x, y);\n desktopMouseMove(x, y);\n}\n\nexport async function driverGetCursorPosition(): Promise<{\n x: number;\n y: number;\n}> {\n // nutjs `mouse.getPosition()` returns a stale/constant value on Windows\n // (empirically verified), so always use the reliable OS query there\n // (System.Windows.Forms.Cursor). Elsewhere prefer nutjs when it is active.\n if (process.platform === \"win32\") return legacyGetCursorPosition();\n if (selectedDriver() === \"nutjs\") return nutGetCursorPosition();\n return legacyGetCursorPosition();\n}\n\nexport async function driverDrag(\n x1: number,\n y1: number,\n x2: number,\n y2: number,\n): Promise<void> {\n if (selectedDriver() === \"nutjs\") return nutDrag(x1, y1, x2, y2);\n desktopDrag(x1, y1, x2, y2);\n}\n\nexport async function driverDragPath(\n path: Array<{ x: number; y: number }>,\n): Promise<void> {\n if (selectedDriver() === \"nutjs\") return nutDragPath(path);\n // Legacy fallback: collapse the polyline to a straight start→end drag.\n if (path.length < 2) {\n throw new Error(\"[computeruse] drag path requires at least two points\");\n }\n const start = path[0];\n const end = path[path.length - 1];\n desktopDrag(start.x, start.y, end.x, end.y);\n}\n\nexport async function driverScroll(\n x: number,\n y: number,\n direction: \"up\" | \"down\" | \"left\" | \"right\",\n amount = 3,\n): Promise<void> {\n if (selectedDriver() === \"nutjs\") return nutScroll(x, y, direction, amount);\n desktopScroll(x, y, direction, amount);\n}\n\n// ── Keyboard ────────────────────────────────────────────────────────────────\n\nexport async function driverType(text: string): Promise<void> {\n if (selectedDriver() === \"nutjs\") return nutType(text);\n desktopType(text);\n}\n\nexport async function driverKeyPress(key: string): Promise<void> {\n if (selectedDriver() === \"nutjs\") return nutKeyPress(key);\n desktopKeyPress(key);\n}\n\n/**\n * Set the value of the UI element at (x,y) (#9170 — trycua/cua `set_value`).\n * On Windows, first try UI Automation `ValuePattern.SetValue` (direct, no\n * keystrokes — best for text inputs / combo boxes). Universal fallback (all\n * platforms, incl. elements without ValuePattern): click to focus, select-all,\n * then type the value — composed of the already-verified click/key-combo/type\n * primitives. `value` is validated by the underlying type primitive.\n */\nexport async function driverSetValue(\n x: number,\n y: number,\n value: string,\n): Promise<void> {\n if (process.platform === \"win32\" && win32TrySetValueByPattern(x, y, value)) {\n return;\n }\n await driverClick(x, y);\n await driverKeyCombo(process.platform === \"darwin\" ? \"cmd+a\" : \"ctrl+a\");\n await driverType(value);\n}\n\nexport async function driverKeyCombo(combo: string): Promise<void> {\n if (selectedDriver() === \"nutjs\") return nutKeyCombo(combo);\n desktopKeyCombo(combo);\n}\n\nexport async function driverKeyDown(key: string): Promise<void> {\n if (selectedDriver() === \"nutjs\") return nutKeyDown(key);\n return requireNutForGranular(\"key_down\");\n}\n\nexport async function driverKeyUp(key: string): Promise<void> {\n if (selectedDriver() === \"nutjs\") return nutKeyUp(key);\n return requireNutForGranular(\"key_up\");\n}\n\n// ── Screenshot ──────────────────────────────────────────────────────────────\n\nexport async function driverCaptureScreenshot(\n region?: ScreenRegion,\n): Promise<Buffer> {\n if (selectedDriver() === \"nutjs\") {\n try {\n return await nutCaptureScreenshot(region);\n } catch {\n return legacyCaptureScreenshot(region);\n }\n }\n return legacyCaptureScreenshot(region);\n}\n",
|
|
30
|
+
"/**\n * WS7 — BaseComputerInterface (TypeScript port).\n *\n * Shape ported from trycua/cua's `BaseComputerInterface` (MIT). The original\n * provides one standard API surface for screenshot + mouse + keyboard + screen\n * geometry that the Brain/Actor cascade can call without knowing what OS or\n * driver is underneath.\n *\n * Origin: https://github.com/trycua/cua/blob/main/libs/python/computer/\n * computer/interface/base.py\n * License: MIT, Copyright (c) 2025 trycua\n *\n * This is NOT a verbatim re-implementation — Eliza's underlying drivers\n * (`platform/driver.ts`, `platform/capture.ts`) already cover most of the same\n * surface. We give the cascade one well-typed seam so tests can swap in a\n * fake driver, and so the Brain doesn't need to know about display-id\n * resolution, retina scaling, or coord-source switches.\n *\n * Coordinate contract (matches WS5):\n * - Every method that takes `(displayId, x, y)` uses LOCAL pixel coords for\n * that display. The interface routes those through `localToGlobalDefault`\n * before any input fires.\n * - VLMs producing coords in image-space (i.e. against the downscaled max-\n * pixels frame) MUST first call `toScreenCoordinates(...)` to get the\n * real OS-pixel coord. The inverse `toScreenshotCoordinates(...)` is for\n * logging / replay.\n * - `displayId` must be a known display from `listDisplays()`. Unknown ids\n * throw — this is the safety net the dispatch layer relies on.\n */\n\nimport { captureDisplay, type DisplayCapture } from \"../platform/capture.js\";\nimport { getPrimaryDisplay, listDisplays } from \"../platform/displays.js\";\nimport {\n driverClick,\n driverDoubleClick,\n driverDrag,\n driverDragPath,\n driverKeyCombo,\n driverKeyDown,\n driverKeyPress,\n driverKeyUp,\n driverMouseDown,\n driverMouseMove,\n driverMouseUp,\n driverRightClick,\n driverScroll,\n driverType,\n} from \"../platform/driver.js\";\nimport type { Scene, SceneAxNode } from \"../scene/scene-types.js\";\nimport type { DisplayDescriptor } from \"../types.js\";\n\n/** A POSIX-style mouse button. */\nexport type MouseButton = \"left\" | \"middle\" | \"right\";\n\nexport interface ScreenshotResult {\n displayId: number;\n /** PNG bytes at backing-store resolution. */\n frame: Buffer;\n /** Backing-store / logical-pixel ratio. */\n scaleFactor: number;\n /** [x, y, w, h] in OS-global pixel space, for the display this frame belongs to. */\n bounds: [number, number, number, number];\n}\n\nexport interface DisplayPoint {\n displayId: number;\n /** LOCAL pixel coords inside the display's logical bounds. */\n x: number;\n y: number;\n}\n\nexport interface DragPath {\n displayId: number;\n path: Array<{ x: number; y: number }>;\n}\n\nexport interface ScrollDelta {\n displayId: number;\n x: number;\n y: number;\n /** Negative = scroll up/left, positive = scroll down/right. */\n dx: number;\n dy: number;\n}\n\nexport interface CursorPosition {\n displayId: number;\n x: number;\n y: number;\n}\n\n/**\n * The single seam the cascade calls. All methods are safe to await\n * concurrently within one display (driver semantics permitting); callers\n * serialize at the dispatch layer.\n */\nexport interface ComputerInterface {\n screenshot(opts?: { displayId?: number }): Promise<ScreenshotResult>;\n mouseDown(point: DisplayPoint & { button?: MouseButton }): Promise<void>;\n mouseUp(point: DisplayPoint & { button?: MouseButton }): Promise<void>;\n leftClick(point: DisplayPoint): Promise<void>;\n rightClick(point: DisplayPoint): Promise<void>;\n doubleClick(point: DisplayPoint): Promise<void>;\n moveCursor(point: DisplayPoint): Promise<void>;\n dragTo(point: DisplayPoint): Promise<void>;\n drag(path: DragPath): Promise<void>;\n keyDown(args: { key: string }): Promise<void>;\n keyUp(args: { key: string }): Promise<void>;\n typeText(args: { text: string }): Promise<void>;\n pressKey(args: { key: string }): Promise<void>;\n hotkey(args: { keys: string[] }): Promise<void>;\n scroll(delta: ScrollDelta): Promise<void>;\n scrollUp(args: { displayId: number; clicks: number }): Promise<void>;\n scrollDown(args: { displayId: number; clicks: number }): Promise<void>;\n getScreenSize(args: { displayId: number }): { w: number; h: number };\n getCursorPosition(): CursorPosition;\n\n /**\n * Convert from VLM-image-space (the downscaled max-pixels frame the model\n * was shown) into OS-LOCAL-pixel-space for the same display.\n *\n * `(imgX, imgY)` are pixel coords inside an `imgW × imgH` image. Returned\n * `(x, y)` are the same physical point but in the display's logical bounds.\n */\n toScreenCoordinates(args: {\n displayId: number;\n imgX: number;\n imgY: number;\n imgW: number;\n imgH: number;\n }): { x: number; y: number };\n\n /** Inverse of `toScreenCoordinates`. */\n toScreenshotCoordinates(args: {\n displayId: number;\n x: number;\n y: number;\n imgW: number;\n imgH: number;\n }): { imgX: number; imgY: number };\n\n /**\n * Return the AX (accessibility) tree the scene-builder snapshot already\n * collected. We don't re-snapshot here — that's WS6's job. Cascade calls\n * this to enumerate clickable AX nodes by display.\n */\n getAccessibilityTree(args: { displayId?: number }): SceneAxNode[];\n}\n\n/**\n * Reference implementation that delegates to `platform/driver.ts` and\n * `platform/capture.ts`. The constructor takes a `Scene` accessor so the\n * AX tree is read from the latest WS6 snapshot without re-walking the OS.\n */\nexport interface ComputerInterfaceDeps {\n /** Latest scene accessor — used for `getAccessibilityTree`. */\n getScene?: () => Scene | null;\n /** Capture override (mostly for tests). */\n capture?: (displayId: number) => Promise<DisplayCapture>;\n /** Driver overrides for tests. */\n driver?: Partial<{\n click: (x: number, y: number) => Promise<void>;\n doubleClick: (x: number, y: number) => Promise<void>;\n rightClick: (x: number, y: number) => Promise<void>;\n mouseMove: (x: number, y: number) => Promise<void>;\n mouseDown: (x: number, y: number, button: MouseButton) => Promise<void>;\n mouseUp: (x: number, y: number, button: MouseButton) => Promise<void>;\n drag: (x1: number, y1: number, x2: number, y2: number) => Promise<void>;\n dragPath: (path: Array<{ x: number; y: number }>) => Promise<void>;\n scroll: (\n x: number,\n y: number,\n direction: \"up\" | \"down\" | \"left\" | \"right\",\n amount: number,\n ) => Promise<void>;\n type: (text: string) => Promise<void>;\n keyPress: (key: string) => Promise<void>;\n keyCombo: (combo: string) => Promise<void>;\n keyDown: (key: string) => Promise<void>;\n keyUp: (key: string) => Promise<void>;\n }>;\n listDisplays?: () => DisplayDescriptor[];\n /**\n * Where the implementation should remember the last cursor target.\n * Set whenever a movement-bearing call resolves successfully.\n */\n cursorState?: { current: CursorPosition };\n}\n\nexport class DefaultComputerInterface implements ComputerInterface {\n private readonly deps: Required<\n Omit<ComputerInterfaceDeps, \"driver\" | \"getScene\">\n > & {\n driver: ComputerInterfaceDeps[\"driver\"];\n getScene: ComputerInterfaceDeps[\"getScene\"];\n };\n\n constructor(deps: ComputerInterfaceDeps = {}) {\n const primary = (() => {\n try {\n return getPrimaryDisplay();\n } catch {\n return { id: 0 } as DisplayDescriptor;\n }\n })();\n this.deps = {\n getScene: deps.getScene,\n capture: deps.capture ?? captureDisplay,\n listDisplays:\n deps.listDisplays ??\n (() =>\n listDisplays().map((d) => ({\n id: d.id,\n bounds: d.bounds,\n scaleFactor: d.scaleFactor,\n primary: d.primary,\n name: d.name,\n }))),\n cursorState: deps.cursorState ?? {\n current: { displayId: primary.id, x: 0, y: 0 },\n },\n driver: deps.driver,\n };\n }\n\n async screenshot(\n opts: { displayId?: number } = {},\n ): Promise<ScreenshotResult> {\n const displayId = opts.displayId ?? this.primaryId();\n const captured = await this.deps.capture(displayId);\n return {\n displayId: captured.display.id,\n frame: captured.frame,\n scaleFactor: captured.display.scaleFactor,\n bounds: captured.display.bounds,\n };\n }\n\n async mouseDown(\n point: DisplayPoint & { button?: MouseButton },\n ): Promise<void> {\n // Real button press-and-hold (nutjs `pressButton`). Pairs with `mouseUp`\n // to express hold-drags, marquee selection, and press-and-hold gestures.\n const g = this.toGlobalChecked(point);\n const button = point.button ?? \"left\";\n const fn = this.deps.driver?.mouseDown ?? driverMouseDown;\n await fn(g.x, g.y, button);\n this.deps.cursorState.current = {\n displayId: point.displayId,\n x: point.x,\n y: point.y,\n };\n }\n\n async mouseUp(point: DisplayPoint & { button?: MouseButton }): Promise<void> {\n const g = this.toGlobalChecked(point);\n const button = point.button ?? \"left\";\n const fn = this.deps.driver?.mouseUp ?? driverMouseUp;\n await fn(g.x, g.y, button);\n this.deps.cursorState.current = {\n displayId: point.displayId,\n x: point.x,\n y: point.y,\n };\n }\n\n async leftClick(point: DisplayPoint): Promise<void> {\n const g = this.toGlobalChecked(point);\n const fn = this.deps.driver?.click ?? driverClick;\n await fn(g.x, g.y);\n this.deps.cursorState.current = { ...point };\n }\n\n async rightClick(point: DisplayPoint): Promise<void> {\n const g = this.toGlobalChecked(point);\n const fn = this.deps.driver?.rightClick ?? driverRightClick;\n await fn(g.x, g.y);\n this.deps.cursorState.current = { ...point };\n }\n\n async doubleClick(point: DisplayPoint): Promise<void> {\n const g = this.toGlobalChecked(point);\n const fn = this.deps.driver?.doubleClick ?? driverDoubleClick;\n await fn(g.x, g.y);\n this.deps.cursorState.current = { ...point };\n }\n\n async moveCursor(point: DisplayPoint): Promise<void> {\n const g = this.toGlobalChecked(point);\n const fn = this.deps.driver?.mouseMove ?? driverMouseMove;\n await fn(g.x, g.y);\n this.deps.cursorState.current = { ...point };\n }\n\n async dragTo(point: DisplayPoint): Promise<void> {\n const start = this.deps.cursorState.current;\n if (start.displayId !== point.displayId) {\n throw new Error(\n `[computeruse/actor] drag across displays not supported (${start.displayId} -> ${point.displayId})`,\n );\n }\n const startG = this.toGlobalChecked(start);\n const endG = this.toGlobalChecked(point);\n const fn = this.deps.driver?.drag ?? driverDrag;\n await fn(startG.x, startG.y, endG.x, endG.y);\n this.deps.cursorState.current = { ...point };\n }\n\n async drag(args: DragPath): Promise<void> {\n if (args.path.length < 2) {\n throw new Error(\n \"[computeruse/actor] drag path requires at least two points\",\n );\n }\n const end = args.path[args.path.length - 1];\n if (!args.path[0] || !end) {\n throw new Error(\n \"[computeruse/actor] drag path requires concrete start and end points\",\n );\n }\n // Real multi-segment polyline drag — traces every waypoint with the button\n // held (curves, corners, marquee). The driver densifies between vertices.\n const globalPath = args.path.map((p) =>\n this.toGlobalChecked({ displayId: args.displayId, x: p.x, y: p.y }),\n );\n const fn = this.deps.driver?.dragPath ?? driverDragPath;\n await fn(globalPath);\n this.deps.cursorState.current = {\n displayId: args.displayId,\n x: end.x,\n y: end.y,\n };\n }\n\n async keyDown(args: { key: string }): Promise<void> {\n // Real key press-and-hold (nutjs `pressKey` without release). Pairs with\n // `keyUp` for held-modifier sequences (e.g. hold Shift across other input).\n const fn = this.deps.driver?.keyDown ?? driverKeyDown;\n await fn(args.key);\n }\n\n async keyUp(args: { key: string }): Promise<void> {\n const fn = this.deps.driver?.keyUp ?? driverKeyUp;\n await fn(args.key);\n }\n\n async typeText(args: { text: string }): Promise<void> {\n const fn = this.deps.driver?.type ?? driverType;\n await fn(args.text);\n }\n\n async pressKey(args: { key: string }): Promise<void> {\n const fn = this.deps.driver?.keyPress ?? driverKeyPress;\n await fn(args.key);\n }\n\n async hotkey(args: { keys: string[] }): Promise<void> {\n if (args.keys.length === 0) {\n throw new Error(\"[computeruse/actor] hotkey requires at least one key\");\n }\n const combo = args.keys.join(\"+\");\n const fn = this.deps.driver?.keyCombo ?? driverKeyCombo;\n await fn(combo);\n }\n\n async scroll(delta: ScrollDelta): Promise<void> {\n const g = this.toGlobalChecked({\n displayId: delta.displayId,\n x: delta.x,\n y: delta.y,\n });\n const fn = this.deps.driver?.scroll ?? driverScroll;\n if (delta.dy !== 0) {\n const direction = delta.dy > 0 ? \"down\" : \"up\";\n await fn(g.x, g.y, direction, Math.abs(delta.dy));\n }\n if (delta.dx !== 0) {\n const direction = delta.dx > 0 ? \"right\" : \"left\";\n await fn(g.x, g.y, direction, Math.abs(delta.dx));\n }\n }\n\n async scrollUp(args: { displayId: number; clicks: number }): Promise<void> {\n const display = this.requireDisplay(args.displayId);\n const cx = Math.round(display.bounds[2] / 2);\n const cy = Math.round(display.bounds[3] / 2);\n await this.scroll({\n displayId: args.displayId,\n x: cx,\n y: cy,\n dx: 0,\n dy: -Math.abs(args.clicks),\n });\n }\n\n async scrollDown(args: { displayId: number; clicks: number }): Promise<void> {\n const display = this.requireDisplay(args.displayId);\n const cx = Math.round(display.bounds[2] / 2);\n const cy = Math.round(display.bounds[3] / 2);\n await this.scroll({\n displayId: args.displayId,\n x: cx,\n y: cy,\n dx: 0,\n dy: Math.abs(args.clicks),\n });\n }\n\n getScreenSize(args: { displayId: number }): { w: number; h: number } {\n const display = this.requireDisplay(args.displayId);\n return { w: display.bounds[2], h: display.bounds[3] };\n }\n\n getCursorPosition(): CursorPosition {\n return { ...this.deps.cursorState.current };\n }\n\n toScreenCoordinates(args: {\n displayId: number;\n imgX: number;\n imgY: number;\n imgW: number;\n imgH: number;\n }): { x: number; y: number } {\n const display = this.requireDisplay(args.displayId);\n if (args.imgW <= 0 || args.imgH <= 0) {\n throw new Error(\n \"[computeruse/actor] toScreenCoordinates requires positive image dimensions\",\n );\n }\n const sx = display.bounds[2] / args.imgW;\n const sy = display.bounds[3] / args.imgH;\n return {\n x: Math.round(args.imgX * sx),\n y: Math.round(args.imgY * sy),\n };\n }\n\n toScreenshotCoordinates(args: {\n displayId: number;\n x: number;\n y: number;\n imgW: number;\n imgH: number;\n }): { imgX: number; imgY: number } {\n const display = this.requireDisplay(args.displayId);\n if (display.bounds[2] <= 0 || display.bounds[3] <= 0) {\n throw new Error(\n \"[computeruse/actor] toScreenshotCoordinates: display has zero bounds\",\n );\n }\n const sx = args.imgW / display.bounds[2];\n const sy = args.imgH / display.bounds[3];\n return {\n imgX: Math.round(args.x * sx),\n imgY: Math.round(args.y * sy),\n };\n }\n\n getAccessibilityTree(args: { displayId?: number }): SceneAxNode[] {\n const scene = this.deps.getScene?.() ?? null;\n if (!scene) return [];\n if (args.displayId === undefined) return scene.ax;\n return scene.ax.filter((n) => n.displayId === args.displayId);\n }\n\n private primaryId(): number {\n const ds = this.deps.listDisplays();\n return ds.find((d) => d.primary)?.id ?? ds[0]?.id ?? 0;\n }\n\n private requireDisplay(displayId: number): DisplayDescriptor {\n const d = this.deps.listDisplays().find((x) => x.id === displayId);\n if (!d) {\n const known = this.deps\n .listDisplays()\n .map((x) => `${x.id}(${x.name})`)\n .join(\", \");\n throw new Error(\n `[computeruse/actor] unknown displayId ${displayId}. Known: ${known}`,\n );\n }\n return d;\n }\n\n private toGlobalChecked(point: DisplayPoint): { x: number; y: number } {\n const display = this.requireDisplay(point.displayId);\n if (!Number.isFinite(point.x) || !Number.isFinite(point.y)) {\n throw new Error(\n `[computeruse/actor] non-finite coords (${point.x}, ${point.y})`,\n );\n }\n // Translate using the injected display list so tests with fake displays\n // work correctly. `localToGlobal` from platform/coords uses the real OS\n // display list and would break test isolation.\n return {\n x: Math.round(display.bounds[0] + point.x),\n y: Math.round(display.bounds[1] + point.y),\n };\n }\n}\n\n/** Convenience factory used by the cascade. */\nexport function makeComputerInterface(\n deps: ComputerInterfaceDeps = {},\n): ComputerInterface {\n return new DefaultComputerInterface(deps);\n}\n",
|
|
31
|
+
"/**\n * WS7 — Dispatch layer.\n *\n * Single entry point that validates a resolved `ProposedAction` and routes\n * it to a `ComputerInterface`. Errors are returned as structured\n * `ActionResult.error` values — we don't let exceptions escape the cascade\n * boundary, so the agent loop can recover by re-prompting the Brain.\n *\n * Validation:\n * - displayId must exist\n * - point coords (when present) must be inside the display's local bounds\n * - text/key/keys/dx/dy must match the action kind\n *\n * No business logic lives here. The dispatcher is dumb on purpose.\n */\n\nimport type { DisplayDescriptor } from \"../types.js\";\nimport type { ComputerInterface, DisplayPoint } from \"./computer-interface.js\";\nimport type { ActionResult, ProposedAction } from \"./types.js\";\n\nexport interface DispatchDeps {\n interface: ComputerInterface;\n listDisplays: () => DisplayDescriptor[];\n}\n\nexport async function dispatch(\n action: ProposedAction,\n deps: DispatchDeps,\n): Promise<ActionResult> {\n const displays = deps.listDisplays();\n const target = displays.find((d) => d.id === action.displayId);\n if (action.kind !== \"wait\" && action.kind !== \"finish\") {\n if (!target) {\n return {\n success: false,\n error: {\n code: \"unknown_display\",\n message: `Unknown displayId ${action.displayId}. Known: ${displays.map((d) => d.id).join(\", \")}`,\n },\n };\n }\n }\n\n if (action.kind === \"wait\" || action.kind === \"finish\") {\n return { success: true, issued: action };\n }\n\n if (\n action.kind === \"click\" ||\n action.kind === \"double_click\" ||\n action.kind === \"right_click\"\n ) {\n if (!target) {\n return unknownDisplay(action, displays);\n }\n const point = resolvePoint(action);\n if (!point) {\n return invalidArgs(action, \"click action requires finite (x, y) coords\");\n }\n const oob = checkBounds(target, point.x, point.y);\n if (oob) return oob;\n const displayPoint: DisplayPoint = {\n displayId: action.displayId,\n x: point.x,\n y: point.y,\n };\n try {\n if (action.kind === \"click\") await deps.interface.leftClick(displayPoint);\n else if (action.kind === \"double_click\")\n await deps.interface.doubleClick(displayPoint);\n else await deps.interface.rightClick(displayPoint);\n } catch (err) {\n return driverError(err);\n }\n return { success: true, issued: action };\n }\n\n if (action.kind === \"type\") {\n if (typeof action.text !== \"string\" || action.text.length === 0) {\n return invalidArgs(action, \"type action requires non-empty text\");\n }\n try {\n await deps.interface.typeText({ text: action.text });\n } catch (err) {\n return driverError(err);\n }\n return { success: true, issued: action };\n }\n\n if (action.kind === \"key\") {\n if (typeof action.key !== \"string\" || action.key.length === 0) {\n return invalidArgs(action, \"key action requires non-empty key\");\n }\n try {\n await deps.interface.pressKey({ key: action.key });\n } catch (err) {\n return driverError(err);\n }\n return { success: true, issued: action };\n }\n\n if (action.kind === \"hotkey\") {\n if (!Array.isArray(action.keys) || action.keys.length === 0) {\n return invalidArgs(action, \"hotkey action requires non-empty keys[]\");\n }\n try {\n await deps.interface.hotkey({ keys: action.keys });\n } catch (err) {\n return driverError(err);\n }\n return { success: true, issued: action };\n }\n\n if (action.kind === \"scroll\") {\n if (!target) {\n return unknownDisplay(action, displays);\n }\n const point = resolvePoint(action);\n if (\n !point ||\n typeof action.dx !== \"number\" ||\n typeof action.dy !== \"number\"\n ) {\n return invalidArgs(\n action,\n \"scroll action requires (x, y) anchor and (dx, dy)\",\n );\n }\n const oob = checkBounds(target, point.x, point.y);\n if (oob) return oob;\n try {\n await deps.interface.scroll({\n displayId: action.displayId,\n x: point.x,\n y: point.y,\n dx: action.dx,\n dy: action.dy,\n });\n } catch (err) {\n return driverError(err);\n }\n return { success: true, issued: action };\n }\n\n if (action.kind === \"drag\") {\n if (!target) {\n return unknownDisplay(action, displays);\n }\n const start = resolveStartPoint(action);\n const end = resolvePoint(action);\n if (!start || !end) {\n return invalidArgs(action, \"drag requires startX/startY and x/y\");\n }\n const oobStart = checkBounds(target, start.x, start.y);\n if (oobStart) return oobStart;\n const oobEnd = checkBounds(target, end.x, end.y);\n if (oobEnd) return oobEnd;\n try {\n await deps.interface.drag({\n displayId: action.displayId,\n path: [\n { x: start.x, y: start.y },\n { x: end.x, y: end.y },\n ],\n });\n } catch (err) {\n return driverError(err);\n }\n return { success: true, issued: action };\n }\n\n return invalidArgs(\n action,\n `unknown action kind \"${(action as ProposedAction).kind}\"`,\n );\n}\n\nfunction resolvePoint(action: ProposedAction): { x: number; y: number } | null {\n const { x, y } = action;\n return typeof x === \"number\" &&\n Number.isFinite(x) &&\n typeof y === \"number\" &&\n Number.isFinite(y)\n ? { x, y }\n : null;\n}\n\nfunction resolveStartPoint(\n action: ProposedAction,\n): { x: number; y: number } | null {\n const { startX, startY } = action;\n return typeof startX === \"number\" &&\n Number.isFinite(startX) &&\n typeof startY === \"number\" &&\n Number.isFinite(startY)\n ? { x: startX, y: startY }\n : null;\n}\n\nfunction checkBounds(\n display: DisplayDescriptor,\n x: number,\n y: number,\n): ActionResult | null {\n const [, , w, h] = display.bounds;\n if (x < 0 || y < 0 || x >= w || y >= h) {\n return {\n success: false,\n error: {\n code: \"out_of_bounds\",\n message: `Coordinates (${x}, ${y}) are outside display ${display.id} bounds (0,0)-(${w},${h})`,\n },\n };\n }\n return null;\n}\n\nfunction invalidArgs(action: ProposedAction, message: string): ActionResult {\n return {\n success: false,\n error: {\n code: \"invalid_args\",\n message: `${message} (action.kind=${action.kind})`,\n },\n };\n}\n\nfunction unknownDisplay(\n action: ProposedAction,\n displays: DisplayDescriptor[],\n): ActionResult {\n return {\n success: false,\n error: {\n code: \"unknown_display\",\n message: `Unknown displayId ${action.displayId}. Known: ${displays.map((d) => d.id).join(\", \")}`,\n },\n };\n}\n\nfunction driverError(err: unknown): ActionResult {\n return {\n success: false,\n error: {\n code: \"driver_error\",\n message: err instanceof Error ? err.message : String(err),\n },\n };\n}\n",
|
|
32
|
+
"/**\n * Pure handler for the WINDOW parent action. Takes the live\n * `ComputerUseService` and resolved params, executes the underlying\n * window-management call, and returns an `ActionResult`.\n */\n\nimport type { ActionResult, HandlerCallback } from \"@elizaos/core\";\nimport type { ComputerUseService } from \"../services/computer-use-service.js\";\nimport type { WindowActionParams, WindowActionResult } from \"../types.js\";\nimport { toComputerUseActionResult } from \"./helpers.js\";\nimport { type ApprovalRelayOptions, withApprovalRelay } from \"./progress.js\";\n\nconst MAX_WINDOW_ROWS = 50;\nconst MAX_WINDOW_ROW_BYTES = 120;\n\nfunction formatWindowResultText(\n params: WindowActionParams,\n result: WindowActionResult,\n): string {\n if (result.windows) {\n const windowText =\n result.windows.length > 0\n ? result.windows\n .map((w) => `[${w.id}] ${w.app} - ${w.title}`)\n .join(\"\\n\")\n : \"No visible windows found.\";\n return `Open windows:\\n${windowText}`;\n }\n\n return result.success\n ? (result.message ?? `Window ${params.action} completed.`)\n : result.approvalRequired\n ? `Window action is waiting for approval (${result.approvalId}).`\n : `Window action failed: ${result.error}`;\n}\n\nexport async function handleWindowOp(\n service: ComputerUseService,\n params: WindowActionParams,\n callback?: HandlerCallback,\n approvalOptions: ApprovalRelayOptions = {},\n): Promise<ActionResult> {\n params.action ??= \"list\";\n\n const result = await withApprovalRelay(\n service,\n callback,\n () => service.executeWindowAction(params),\n approvalOptions,\n );\n const text = formatWindowResultText(params, result).slice(\n 0,\n MAX_WINDOW_ROWS * MAX_WINDOW_ROW_BYTES,\n );\n\n if (callback) {\n await callback({ text });\n }\n\n return toComputerUseActionResult({\n action: params.action,\n result,\n text,\n suppressClipboard: true,\n });\n}\n",
|
|
33
|
+
"/**\n * WINDOW parent action — manages local desktop windows (list / focus /\n * switch / arrange / move / minimize / maximize / restore / close).\n *\n * Pointer and keyboard primitives live on COMPUTER_USE. File and shell\n * operations live on the FILE and SHELL actions in their own plugins —\n * this plugin no longer exposes them.\n */\n\nimport type {\n Action,\n ActionResult,\n HandlerCallback,\n HandlerOptions,\n IAgentRuntime,\n Memory,\n State,\n} from \"@elizaos/core\";\nimport type { ComputerUseService } from \"../services/computer-use-service.js\";\nimport type { WindowActionParams, WindowActionType } from \"../types.js\";\nimport { resolveActionParams } from \"./helpers.js\";\nimport { handleWindowOp } from \"./window-handlers.js\";\n\nconst WINDOW_ACTIONS = [\n \"list\",\n \"focus\",\n \"switch\",\n \"arrange\",\n \"move\",\n \"minimize\",\n \"maximize\",\n \"restore\",\n \"close\",\n \"get_current_window_id\",\n \"get_application_windows\",\n \"set_bounds\",\n \"get_window_size\",\n \"get_window_position\",\n] as const satisfies readonly WindowActionType[];\n\n/**\n * Resolved WINDOW payload. Canonical `action` chooses the verb; legacy\n * callers may still send `subaction` or `op`.\n */\ntype WindowParameters = Omit<Partial<WindowActionParams>, \"action\"> & {\n action?: WindowActionType;\n subaction?: WindowActionType;\n op?: WindowActionType;\n};\n\nfunction normalizeWindowToken(value: unknown): WindowActionType | undefined {\n if (typeof value !== \"string\") return undefined;\n const normalized = value\n .trim()\n .toLowerCase()\n .replace(/[\\s-]+/g, \"_\");\n if ((WINDOW_ACTIONS as readonly string[]).includes(normalized)) {\n return normalized as WindowActionType;\n }\n return undefined;\n}\n\nfunction resolveWindowAction(\n params: WindowParameters,\n): WindowActionType | undefined {\n return (\n normalizeWindowToken(params.action) ??\n normalizeWindowToken(params.subaction) ??\n normalizeWindowToken(params.op)\n );\n}\n\nfunction approvalOwnerIdFromMemory(message: Memory): string | undefined {\n const metadata = message.metadata;\n if (!metadata || typeof metadata !== \"object\") return undefined;\n const telegramUserId = (metadata as Record<string, unknown>).telegramUserId;\n return typeof telegramUserId === \"string\" && telegramUserId.length > 0\n ? telegramUserId\n : undefined;\n}\n\nexport const windowAction: Action = {\n name: \"WINDOW\",\n contexts: [\"screen_time\", \"automation\"],\n contextGate: {\n anyOf: [\"screen_time\", \"automation\"],\n },\n roleGate: { minRole: \"USER\" },\n similes: [\n // Old per-verb name — preserved so older planner callers and training\n // data still resolve to WINDOW.\n \"MANAGE_WINDOW\",\n // Generic aliases.\n \"WINDOW\",\n \"USE_WINDOW\",\n \"WINDOW_ACTION\",\n ],\n description:\n \"WINDOW action. Manage local desktop windows via computer-use service. actions: list, focus, switch, arrange, move, minimize, maximize, restore, close. Pointer/keyboard use COMPUTER_USE; file/shell use FILE/SHELL.\",\n descriptionCompressed:\n \"WINDOW action=list|focus|switch|arrange|move|minimize|maximize|restore|close\",\n parameters: [\n {\n name: \"action\",\n description: \"Window operation verb.\",\n required: true,\n schema: {\n type: \"string\",\n enum: [...WINDOW_ACTIONS],\n },\n },\n {\n name: \"windowId\",\n description: \"Window identifier.\",\n required: false,\n schema: { type: \"string\" },\n },\n {\n name: \"windowTitle\",\n description: \"Window title or app-name query.\",\n required: false,\n schema: { type: \"string\" },\n },\n {\n name: \"arrangement\",\n description: \"For arrange: tile, cascade, vertical, horizontal.\",\n required: false,\n schema: { type: \"string\" },\n },\n {\n name: \"x\",\n description: \"Target X coordinate for window move / set_bounds.\",\n required: false,\n schema: { type: \"number\" },\n },\n {\n name: \"y\",\n description: \"Target Y coordinate for window move / set_bounds.\",\n required: false,\n schema: { type: \"number\" },\n },\n {\n name: \"width\",\n description: \"Window width for set_bounds.\",\n required: false,\n schema: { type: \"number\", minimum: 1 },\n },\n {\n name: \"height\",\n description: \"Window height for set_bounds.\",\n required: false,\n schema: { type: \"number\", minimum: 1 },\n },\n ],\n validate: async (\n runtime: IAgentRuntime,\n _message: Memory,\n _state?: State,\n ): Promise<boolean> => {\n const service =\n (runtime.getService(\"computeruse\") as ComputerUseService) ?? null;\n if (!service) return false;\n return service.getCapabilities().windowList.available;\n },\n handler: async (\n runtime: IAgentRuntime,\n message: Memory,\n _state?: State,\n options?: HandlerOptions,\n callback?: HandlerCallback,\n ): Promise<ActionResult> => {\n const service =\n (runtime.getService(\"computeruse\") as ComputerUseService) ?? null;\n if (!service) {\n return { success: false, error: \"ComputerUseService not available\" };\n }\n\n const params = resolveActionParams<WindowParameters>(message, options);\n const action = resolveWindowAction(params) ?? \"list\";\n\n return handleWindowOp(\n service,\n { ...params, action } as WindowActionParams,\n callback,\n { ownerId: approvalOwnerIdFromMemory(message) },\n );\n },\n\n examples: [\n [\n {\n name: \"{{name1}}\",\n content: {\n text: \"List the open windows on my desktop.\",\n source: \"chat\",\n },\n },\n {\n name: \"{{agentName}}\",\n content: {\n text: \"Listing windows.\",\n actions: [\"WINDOW\"],\n thought: \"Window inventory routes to WINDOW action=list.\",\n },\n },\n ],\n [\n {\n name: \"{{name1}}\",\n content: {\n text: \"Bring the Slack window to the front.\",\n source: \"chat\",\n },\n },\n {\n name: \"{{agentName}}\",\n content: {\n text: \"Focusing Slack.\",\n actions: [\"WINDOW\"],\n thought:\n \"Activating a window by app name routes to WINDOW action=focus with windowTitle='Slack'.\",\n },\n },\n ],\n [\n {\n name: \"{{name1}}\",\n content: {\n text: \"Tile all my open windows.\",\n source: \"chat\",\n },\n },\n {\n name: \"{{agentName}}\",\n content: {\n text: \"Tiling the windows.\",\n actions: [\"WINDOW\"],\n thought:\n \"Arrangement requests route to WINDOW action=arrange with the chosen arrangement.\",\n },\n },\n ],\n ],\n};\n",
|
|
34
|
+
"/**\n * ComputerStateProvider — injects current computer state into the LLM context.\n *\n * Provides platform info, screen dimensions, available capabilities,\n * and a summary of recent actions so the agent has continuity.\n */\n\nimport type {\n IAgentRuntime,\n Memory,\n Provider,\n ProviderResult,\n State,\n} from \"@elizaos/core\";\nimport { currentPlatform } from \"../platform/helpers.js\";\nimport type { ComputerUseService } from \"../services/computer-use-service.js\";\n\nexport const computerStateProvider: Provider = {\n name: \"computerState\",\n description:\n \"Current computer state: platform, screen size, available tools, recent computer-use actions, and approval queue\",\n\n descriptionCompressed:\n \"Platform, screen size, tools, recent actions, approval queue.\",\n contexts: [\"browser\", \"files\", \"terminal\", \"automation\", \"admin\"],\n contextGate: {\n anyOf: [\"browser\", \"files\", \"terminal\", \"automation\", \"admin\"],\n },\n cacheStable: false,\n cacheScope: \"turn\",\n get: async (\n runtime: IAgentRuntime,\n _message: Memory,\n _state: State,\n ): Promise<ProviderResult> => {\n try {\n const service = runtime.getService(\"computeruse\") as\n | ComputerUseService\n | undefined;\n if (!service) {\n return { text: \"\" };\n }\n\n const caps = service.getCapabilities();\n const screen = service.getScreenDimensions();\n const recent = service.getRecentActions();\n const approvals = service.getApprovalSnapshot();\n const displays = service.getDisplays();\n\n const text = `\\`\\`\\`json\\n${JSON.stringify(\n {\n computer_use: {\n platform: currentPlatform(),\n screen: { width: screen.width, height: screen.height },\n displays: displays.map((d) => ({\n id: d.id,\n name: d.name,\n bounds: d.bounds,\n scaleFactor: d.scaleFactor,\n primary: d.primary,\n })),\n approvals: {\n mode: approvals.mode,\n pendingCount: approvals.pendingCount,\n pending: approvals.pendingApprovals\n .slice(0, 5)\n .map((approval) => ({\n id: approval.id,\n command: approval.command,\n })),\n },\n capabilities: {\n screenshot: caps.screenshot.available\n ? caps.screenshot.tool\n : \"unavailable\",\n mouseKeyboard: caps.computerUse.available\n ? caps.computerUse.tool\n : \"unavailable\",\n browser: caps.browser.available\n ? caps.browser.tool\n : \"unavailable\",\n windowList: caps.windowList.available\n ? caps.windowList.tool\n : \"unavailable\",\n terminal: caps.terminal.available\n ? caps.terminal.tool\n : \"unavailable\",\n fileSystem: caps.fileSystem.available\n ? caps.fileSystem.tool\n : \"unavailable\",\n },\n recentActions: recent.slice(-5).map((entry) => ({\n action: entry.action,\n success: entry.success,\n })),\n },\n },\n null,\n 2,\n )}\\n\\`\\`\\``;\n\n return {\n text,\n values: {\n platform: currentPlatform(),\n screenWidth: screen.width,\n screenHeight: screen.height,\n displayCount: displays.length,\n primaryDisplayId: displays.find((d) => d.primary)?.id ?? 0,\n },\n data: {\n approvals: {\n ...approvals,\n pendingApprovals: approvals.pendingApprovals.slice(0, 5),\n },\n capabilities: caps,\n screenSize: screen,\n displays,\n recentActions: recent.slice(-5),\n },\n };\n } catch {\n return { text: \"\", values: {}, data: {} };\n }\n },\n};\n",
|
|
35
|
+
"/**\n * `scene` provider — surfaces the latest Scene from the computeruse service's\n * SceneBuilder into the agent prompt and provider data.\n *\n * Contract:\n * - On every turn, we run `onAgentTurn()` to refresh the scene before\n * reading it. WS7 (Brain) re-reads via `service.getCurrentScene()` for\n * deeper introspection.\n * - The provider text is a token-efficient JSON fence built by\n * `serializeSceneForPrompt`. We never emit raw pixels.\n * - The provider data is the FULL Scene so downstream pieces can crop /\n * correlate / filter without re-serializing.\n *\n * Cache:\n * - `cacheStable: false` — the Scene is by definition turn-specific.\n * - `cacheScope: \"turn\"` — re-use within a single turn so multiple\n * consumers don't double-tick the builder.\n */\n\nimport type {\n IAgentRuntime,\n Memory,\n Provider,\n ProviderResult,\n State,\n} from \"@elizaos/core\";\nimport { serializeSceneForPrompt } from \"../scene/serialize.js\";\nimport type { ComputerUseService } from \"../services/computer-use-service.js\";\n\nexport const sceneProvider: Provider = {\n name: \"scene\",\n description:\n \"Live desktop scene: displays, focused window, apps, OCR text boxes, accessibility elements, and (when set) VLM annotations. Coordinates are local to displayId.\",\n descriptionCompressed:\n \"display, focused window, apps, OCR boxes, AX nodes, VLM annotations; coords local\",\n contexts: [\"browser\", \"automation\", \"admin\"],\n contextGate: { anyOf: [\"browser\", \"automation\", \"admin\"] },\n cacheStable: false,\n cacheScope: \"turn\",\n get: async (\n runtime: IAgentRuntime,\n _message: Memory,\n _state: State,\n ): Promise<ProviderResult> => {\n const service = runtime.getService(\"computeruse\") as\n | ComputerUseService\n | undefined;\n if (!service) {\n return { text: \"\" };\n }\n let scene = service.getCurrentScene();\n if (!scene) {\n try {\n scene = await service.refreshScene(\"agent-turn\");\n } catch {\n return { text: \"\" };\n }\n }\n if (!scene) return { text: \"\" };\n const text = serializeSceneForPrompt(scene);\n return {\n text,\n values: {\n sceneTimestamp: scene.timestamp,\n sceneDisplayCount: scene.displays.length,\n sceneOcrCount: scene.ocr.length,\n sceneAxCount: scene.ax.length,\n },\n data: { scene },\n };\n },\n};\n",
|
|
36
|
+
"/**\n * Computer-use compat HTTP routes — moved out of\n * `packages/app-core/src/api/computer-use-compat-routes.ts`.\n *\n * Exposes:\n * GET /api/computer-use/approvals (auth)\n * GET /api/computer-use/approvals/stream (token-or-header auth, SSE)\n * POST /api/computer-use/approval-mode (sensitive auth)\n * POST /api/computer-use/approvals/:id (sensitive auth)\n *\n * Service injection: pulls the running ComputerUseService off the agent\n * runtime via `runtime.getService(\"computeruse\")`. Uses a structural\n * `ComputerUseServiceLike` interface so the runtime type stays loose.\n */\n\nimport crypto from \"node:crypto\";\nimport type http from \"node:http\";\n\ntype CompatRuntimeState = {\n current: {\n getService?: (name: string) => unknown;\n } | null;\n};\n\nconst MAX_BODY_BYTES = 1_048_576;\n\nfunction firstHeaderValue(value: string | string[] | undefined): string | null {\n if (typeof value === \"string\") return value;\n return Array.isArray(value) && typeof value[0] === \"string\" ? value[0] : null;\n}\n\nfunction isTrustedLocalRequest(\n req: Pick<http.IncomingMessage, \"headers\" | \"socket\">,\n): boolean {\n const remoteAddress = req.socket.remoteAddress?.trim().toLowerCase();\n if (\n remoteAddress &&\n remoteAddress !== \"127.0.0.1\" &&\n remoteAddress !== \"::1\" &&\n remoteAddress !== \"0:0:0:0:0:0:0:1\" &&\n remoteAddress !== \"::ffff:127.0.0.1\" &&\n remoteAddress !== \"::ffff:0:127.0.0.1\"\n ) {\n return false;\n }\n\n const origin = firstHeaderValue(req.headers.origin);\n if (origin) {\n try {\n const parsed = new URL(origin);\n if (parsed.hostname !== \"localhost\" && parsed.hostname !== \"127.0.0.1\") {\n return false;\n }\n } catch {\n return false;\n }\n }\n\n return true;\n}\n\nfunction tokenMatches(expected: string, provided: string): boolean {\n const expectedBuf = Buffer.from(expected);\n const providedBuf = Buffer.from(provided);\n return (\n expectedBuf.length === providedBuf.length &&\n crypto.timingSafeEqual(expectedBuf, providedBuf)\n );\n}\n\nfunction getCompatApiToken(): string | null {\n return process.env.ELIZA_API_TOKEN?.trim() || null;\n}\n\nfunction getProvidedApiToken(\n req: Pick<http.IncomingMessage, \"headers\">,\n): string | null {\n const authHeader = firstHeaderValue(req.headers.authorization)\n ?.slice(0, 1024)\n ?.trim();\n if (authHeader) {\n const match = /^Bearer\\s{1,8}(.+)$/i.exec(authHeader);\n if (match?.[1]) return match[1].trim();\n }\n\n return (\n (\n firstHeaderValue(req.headers[\"x-eliza-token\"]) ??\n firstHeaderValue(req.headers[\"x-elizaos-token\"]) ??\n firstHeaderValue(req.headers[\"x-api-key\"]) ??\n firstHeaderValue(req.headers[\"x-api-token\"])\n )?.trim() || null\n );\n}\n\nfunction sendJsonResponse(\n res: http.ServerResponse,\n status: number,\n body: unknown,\n): void {\n if (res.headersSent) return;\n res.statusCode = status;\n res.setHeader(\"content-type\", \"application/json; charset=utf-8\");\n res.end(JSON.stringify(body));\n}\n\nfunction sendJsonErrorResponse(\n res: http.ServerResponse,\n status: number,\n message: string,\n): void {\n sendJsonResponse(res, status, { error: message });\n}\n\nfunction ensureCompatSensitiveRouteAuthorized(\n req: Pick<http.IncomingMessage, \"headers\" | \"socket\">,\n res: http.ServerResponse,\n): boolean {\n if (isTrustedLocalRequest(req)) return true;\n\n const expected = getCompatApiToken();\n const provided = getProvidedApiToken(req);\n if (expected && provided && tokenMatches(expected, provided)) {\n return true;\n }\n\n sendJsonErrorResponse(res, expected ? 401 : 403, \"Unauthorized\");\n return false;\n}\n\nasync function ensureRouteAuthorized(\n req: Pick<http.IncomingMessage, \"headers\" | \"socket\">,\n res: http.ServerResponse,\n _state?: CompatRuntimeState,\n): Promise<boolean> {\n if (isTrustedLocalRequest(req)) return true;\n\n const expected = getCompatApiToken();\n const provided = getProvidedApiToken(req);\n if (expected && provided && tokenMatches(expected, provided)) {\n return true;\n }\n\n sendJsonErrorResponse(res, 401, \"Unauthorized\");\n return false;\n}\n\nasync function readCompatJsonBody(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n): Promise<Record<string, unknown> | null> {\n const preParsed = (req as { body?: unknown }).body;\n if (preParsed && typeof preParsed === \"object\" && !Array.isArray(preParsed)) {\n return preParsed as Record<string, unknown>;\n }\n\n const chunks: Buffer[] = [];\n let totalBytes = 0;\n try {\n for await (const chunk of req) {\n const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n totalBytes += buf.length;\n if (totalBytes > MAX_BODY_BYTES) {\n req.destroy();\n sendJsonErrorResponse(res, 413, \"Request body too large\");\n return null;\n }\n chunks.push(buf);\n }\n } catch {\n sendJsonErrorResponse(res, 400, \"Invalid request body\");\n return null;\n }\n\n if (chunks.length === 0) return {};\n\n try {\n const parsed = JSON.parse(\n Buffer.concat(chunks).toString(\"utf8\"),\n ) as unknown;\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n sendJsonErrorResponse(res, 400, \"Invalid JSON body\");\n return null;\n }\n return parsed as Record<string, unknown>;\n } catch {\n sendJsonErrorResponse(res, 400, \"Invalid JSON body\");\n return null;\n }\n}\n\ntype ComputerUseApprovalMode =\n | \"full_control\"\n | \"smart_approve\"\n | \"approve_all\"\n | \"off\";\n\ntype ComputerUseApprovalSnapshot = {\n mode: ComputerUseApprovalMode;\n pendingCount: number;\n pendingApprovals: Array<{\n id: string;\n command: string;\n parameters: Record<string, unknown>;\n requestedAt: string;\n }>;\n};\n\ntype ComputerUseApprovalResolution = {\n id: string;\n command: string;\n approved: boolean;\n cancelled: boolean;\n mode: ComputerUseApprovalMode;\n requestedAt: string;\n resolvedAt: string;\n reason?: string;\n};\n\ntype ComputerUseServiceLike = {\n getApprovalSnapshot(): ComputerUseApprovalSnapshot;\n setApprovalMode(mode: ComputerUseApprovalMode): ComputerUseApprovalMode;\n resolveApproval(\n id: string,\n approved: boolean,\n reason?: string,\n ): ComputerUseApprovalResolution | null;\n subscribeApprovals?(\n listener: (snapshot: ComputerUseApprovalSnapshot) => void,\n ): () => void;\n};\n\nconst VALID_APPROVAL_MODES: ComputerUseApprovalMode[] = [\n \"full_control\",\n \"smart_approve\",\n \"approve_all\",\n \"off\",\n];\n\nconst EMPTY_APPROVAL_SNAPSHOT: ComputerUseApprovalSnapshot = {\n mode: \"full_control\",\n pendingCount: 0,\n pendingApprovals: [],\n};\n\nfunction isApprovalMode(value: string): value is ComputerUseApprovalMode {\n return VALID_APPROVAL_MODES.includes(value as ComputerUseApprovalMode);\n}\n\nfunction getComputerUseService(\n state: CompatRuntimeState,\n): ComputerUseServiceLike | null {\n const runtime = state.current as {\n getService?: (name: string) => unknown;\n } | null;\n if (!runtime?.getService) {\n return null;\n }\n\n const service = runtime.getService(\"computeruse\");\n if (!service || typeof service !== \"object\") {\n return null;\n }\n\n const candidate = service as Partial<ComputerUseServiceLike>;\n if (\n typeof candidate.getApprovalSnapshot !== \"function\" ||\n typeof candidate.setApprovalMode !== \"function\" ||\n typeof candidate.resolveApproval !== \"function\"\n ) {\n return null;\n }\n\n return candidate as ComputerUseServiceLike;\n}\n\nfunction isStreamAuthorized(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n url: URL,\n): boolean {\n const expectedToken = getCompatApiToken();\n if (!expectedToken) {\n return true;\n }\n\n const headerToken = getProvidedApiToken(req);\n const providedToken = url.searchParams.get(\"token\")?.trim();\n if (\n (headerToken && tokenMatches(expectedToken, headerToken)) ||\n (providedToken && tokenMatches(expectedToken, providedToken))\n ) {\n return true;\n }\n\n res.writeHead(401, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Unauthorized\" }));\n return false;\n}\n\nfunction writeSseEvent(\n res: http.ServerResponse,\n payload: Record<string, unknown>,\n): void {\n res.write(`data: ${JSON.stringify(payload)}\\n\\n`);\n}\n\nexport async function handleComputerUseCompatRoutes(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n state: CompatRuntimeState,\n): Promise<boolean> {\n const method = (req.method ?? \"GET\").toUpperCase();\n const url = new URL(req.url ?? \"/\", \"http://localhost\");\n\n if (!url.pathname.startsWith(\"/api/computer-use/\")) {\n return false;\n }\n\n if (\n method === \"GET\" &&\n url.pathname === \"/api/computer-use/approvals/stream\"\n ) {\n if (!isStreamAuthorized(req, res, url)) {\n return true;\n }\n\n const service = getComputerUseService(state);\n if (!service) {\n res.writeHead(200, {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache, no-transform\",\n Connection: \"keep-alive\",\n \"X-Accel-Buffering\": \"no\",\n });\n writeSseEvent(res, {\n type: \"snapshot\",\n snapshot: EMPTY_APPROVAL_SNAPSHOT,\n });\n res.end();\n return true;\n }\n\n res.writeHead(200, {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache, no-transform\",\n Connection: \"keep-alive\",\n \"X-Accel-Buffering\": \"no\",\n });\n\n writeSseEvent(res, {\n type: \"snapshot\",\n snapshot: service.getApprovalSnapshot(),\n });\n\n const heartbeat = setInterval(() => {\n res.write(\": heartbeat\\n\\n\");\n }, 15_000);\n if (typeof heartbeat === \"object\" && \"unref\" in heartbeat) {\n heartbeat.unref();\n }\n\n const unsubscribe = service.subscribeApprovals?.((snapshot) => {\n writeSseEvent(res, {\n type: \"snapshot\",\n snapshot,\n });\n });\n\n const cleanup = () => {\n clearInterval(heartbeat);\n unsubscribe?.();\n };\n\n req.on(\"close\", cleanup);\n req.on(\"aborted\", cleanup);\n return true;\n }\n\n if (method === \"GET\" && url.pathname === \"/api/computer-use/approvals\") {\n if (!(await ensureRouteAuthorized(req, res, state))) {\n return true;\n }\n\n const service = getComputerUseService(state);\n if (!service) {\n sendJsonResponse(res, 200, EMPTY_APPROVAL_SNAPSHOT);\n return true;\n }\n\n sendJsonResponse(res, 200, service.getApprovalSnapshot());\n return true;\n }\n\n if (method === \"POST\" && url.pathname === \"/api/computer-use/approval-mode\") {\n if (!ensureCompatSensitiveRouteAuthorized(req, res)) {\n return true;\n }\n\n const body = await readCompatJsonBody(req, res);\n if (!body) {\n return true;\n }\n\n if (typeof body.mode !== \"string\" || !isApprovalMode(body.mode)) {\n sendJsonErrorResponse(\n res,\n 400,\n \"mode must be one of full_control, smart_approve, approve_all, off\",\n );\n return true;\n }\n\n const service = getComputerUseService(state);\n if (!service) {\n sendJsonErrorResponse(res, 404, \"Computer use service not available\");\n return true;\n }\n\n sendJsonResponse(res, 200, {\n mode: service.setApprovalMode(body.mode),\n });\n return true;\n }\n\n const match = url.pathname.match(/^\\/api\\/computer-use\\/approvals\\/([^/]+)$/);\n if (method === \"POST\" && match) {\n if (!ensureCompatSensitiveRouteAuthorized(req, res)) {\n return true;\n }\n\n const body = await readCompatJsonBody(req, res);\n if (!body) {\n return true;\n }\n\n if (typeof body.approved !== \"boolean\") {\n sendJsonErrorResponse(res, 400, \"approved must be a boolean\");\n return true;\n }\n\n const service = getComputerUseService(state);\n if (!service) {\n sendJsonErrorResponse(res, 404, \"Computer use service not available\");\n return true;\n }\n\n const approvalId = match[1];\n if (approvalId === undefined) {\n sendJsonErrorResponse(res, 400, \"Missing approval id\");\n return true;\n }\n\n const resolution = service.resolveApproval(\n decodeURIComponent(approvalId),\n body.approved,\n typeof body.reason === \"string\" ? body.reason : undefined,\n );\n\n if (!resolution) {\n sendJsonErrorResponse(res, 404, \"Approval not found\");\n return true;\n }\n\n sendJsonResponse(res, 200, resolution);\n return true;\n }\n\n sendJsonErrorResponse(res, 404, \"Not found\");\n return true;\n}\n\n/**\n * Runtime plugin route adapter. The runtime plugin route bridge passes\n * `(req, res, runtime)` — wrap into a CompatRuntimeState adapter for the\n * shared dispatcher.\n */\nexport function computerUseRouteHandler() {\n return async (\n req: unknown,\n res: unknown,\n runtime: unknown,\n ): Promise<void> => {\n const httpReq = req as http.IncomingMessage;\n const httpRes = res as http.ServerResponse;\n const state = { current: runtime } as CompatRuntimeState;\n await handleComputerUseCompatRoutes(httpReq, httpRes, state);\n };\n}\n",
|
|
37
|
+
"import os from \"node:os\";\nimport path from \"node:path\";\nimport { type IAgentRuntime, logger, Service } from \"@elizaos/core\";\nimport {\n ComputerUseApprovalManager,\n isApprovalMode,\n} from \"../approval-manager.js\";\nimport {\n getCoordOcrProvider,\n getSetOfMarksProvider,\n} from \"../mobile/ocr-provider.js\";\nimport {\n clickBrowser,\n closeBrowser,\n closeBrowserTab,\n executeBrowser,\n getBrowserClickables,\n getBrowserContext,\n getBrowserDom,\n getBrowserInfo,\n getBrowserState,\n isBrowserAvailable,\n listBrowserTabs,\n navigateBrowser,\n openBrowser,\n openBrowserTab,\n screenshotBrowser,\n scrollBrowser,\n setBrowserRuntimeOptions,\n switchBrowserTab,\n typeBrowser,\n waitBrowser,\n} from \"../platform/browser.js\";\nimport { detectPlatformCapabilities } from \"../platform/capabilities.js\";\nimport { captureDisplay, capturePrimaryDisplay } from \"../platform/capture.js\";\nimport { localToGlobalDefault } from \"../platform/coords.js\";\nimport {\n getPrimaryDisplay,\n listDisplays,\n warmDisplaysCache,\n} from \"../platform/displays.js\";\nimport {\n driverCaptureScreenshot,\n driverClick,\n driverClickWithModifiers,\n driverDoubleClick,\n driverDrag,\n driverDragPath,\n driverGetCursorPosition,\n driverKeyCombo,\n driverKeyDown,\n driverKeyPress,\n driverKeyUp,\n driverMiddleClick,\n driverMouseDown,\n driverMouseMove,\n driverMouseUp,\n driverRightClick,\n driverScroll,\n driverSetValue,\n driverType,\n} from \"../platform/driver.js\";\nimport {\n appendFile,\n createDirectory,\n deleteDirectory,\n deleteFile,\n directoryExists,\n editFile,\n fileExists,\n getFileSize,\n listDirectory,\n readBytes,\n readFile,\n writeBytes,\n writeFile,\n} from \"../platform/file-ops.js\";\nimport { commandExists, currentPlatform } from \"../platform/helpers.js\";\nimport { killApp, launchApp, openTarget } from \"../platform/launch.js\";\nimport { classifyPermissionDeniedError } from \"../platform/permissions.js\";\nimport { disposePsHost, warmPsHost } from \"../platform/ps-host.js\";\nimport {\n clearTerminal,\n closeAllTerminalSessions,\n closeTerminal,\n connectTerminal,\n executeTerminal,\n readTerminal,\n typeTerminal,\n} from \"../platform/terminal.js\";\nimport {\n arrangeWindows,\n closeWindow,\n focusWindow,\n getActiveWindow,\n getApplicationWindows,\n getScreenSize,\n getWindowBounds,\n listWindows,\n maximizeWindow,\n minimizeWindow,\n moveWindow,\n resizeWindow,\n restoreWindow,\n switchWindow,\n} from \"../platform/windows-list.js\";\nimport { SceneBuilder, type SceneUpdateEvent } from \"../scene/scene-builder.js\";\nimport type { Scene, SceneVlmElement } from \"../scene/scene-types.js\";\nimport {\n type ScreenState,\n type ScreenStateChange,\n ScreenStateStore,\n} from \"../scene/screen-state.js\";\nimport type {\n ActionHistoryEntry,\n ApprovalMode,\n ApprovalResolution,\n ApprovalSnapshot,\n BrowserActionParams,\n BrowserActionResult,\n ComputerActionResult,\n ComputerUseConfig,\n ComputerUseResult,\n DesktopActionParams,\n DisplayDescriptor,\n FileActionParams,\n FileActionResult,\n PlatformCapabilities,\n ScreenSize,\n TerminalActionParams,\n TerminalActionResult,\n WindowActionParams,\n WindowActionResult,\n} from \"../types.js\";\n\nconst MAX_RECENT_ACTIONS = 10;\nconst BROWSER_NOT_OPEN_ERROR = \"Browser not open\";\nconst BROWSER_LIFECYCLE_ACTIONS = new Set<BrowserActionParams[\"action\"]>([\n \"open\",\n \"connect\",\n \"close\",\n]);\nconst COORDINATE_BEARING_ACTIONS = new Set<DesktopActionParams[\"action\"]>([\n \"click\",\n \"click_with_modifiers\",\n \"double_click\",\n \"right_click\",\n \"mouse_move\",\n \"middle_click\",\n \"mouse_down\",\n \"mouse_up\",\n \"scroll\",\n \"drag\",\n \"set_value\",\n]);\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction isBrowserNotOpenMessage(message: unknown): boolean {\n const text =\n typeof message === \"string\"\n ? message\n : message instanceof Error\n ? message.message\n : \"\";\n return text.includes(BROWSER_NOT_OPEN_ERROR);\n}\n\nfunction commandParameters<TParams extends object>(\n parameters: Record<string, unknown>,\n): Omit<TParams, \"action\"> {\n return parameters as Omit<TParams, \"action\">;\n}\n\nfunction stringifyData(value: unknown): string {\n if (typeof value === \"string\") {\n return value;\n }\n return renderPlainData(value);\n}\n\nfunction renderPlainData(value: unknown, indent = 0): string {\n const prefix = \" \".repeat(indent);\n if (value === null || value === undefined) {\n return \"none\";\n }\n if (Array.isArray(value)) {\n if (value.length === 0) {\n return \"items[0]:\";\n }\n return [\n `items[${value.length}]:`,\n ...value.map((item) => `${prefix}- ${renderPlainData(item, indent + 1)}`),\n ].join(\"\\n\");\n }\n if (typeof value === \"object\") {\n return Object.entries(value as Record<string, unknown>)\n .map(([key, nestedValue]) => {\n if (nestedValue && typeof nestedValue === \"object\") {\n return `${key}:\\n${renderPlainData(nestedValue, indent + 1)}`;\n }\n return `${key}: ${renderPlainData(nestedValue, indent + 1)}`;\n })\n .join(\"\\n\");\n }\n return String(value);\n}\n\nexport class ComputerUseService extends Service {\n static serviceType = \"computeruse\";\n\n capabilityDescription =\n \"Desktop automation, screenshots, browser control, file operations, terminal access, window management, and approval-gated local actions\";\n\n private capabilities!: PlatformCapabilities;\n private recentActions: ActionHistoryEntry[] = [];\n private screenSize: ScreenSize = { width: 1920, height: 1080 };\n private approvalManager = new ComputerUseApprovalManager();\n private displayIdDeprecationWarned = false;\n private sceneBuilder: SceneBuilder = new SceneBuilder({\n log: (msg) => logger.warn(msg),\n });\n /**\n * Single shared per-display capture for the turn (#9105 M3). OCR, the Brain,\n * and the DirtyTileDescriber all read through this store so the screen is\n * grabbed once per tick instead of once per consumer.\n */\n private screenStateStore: ScreenStateStore = new ScreenStateStore({\n capture: (displayId) => captureDisplay(displayId),\n });\n private cuConfig: ComputerUseConfig = {\n screenshotAfterAction: true,\n actionTimeoutMs: 10000,\n maxRecentActions: MAX_RECENT_ACTIONS,\n approvalMode: \"smart_approve\",\n browserHeadless: false,\n mode: \"yolo\",\n };\n\n static async start(runtime: IAgentRuntime): Promise<Service> {\n const instance = new ComputerUseService(runtime);\n instance.loadConfig(runtime);\n instance.capabilities = instance.detectCapabilities();\n\n try {\n instance.screenSize = getScreenSize();\n } catch (error) {\n logger.warn(\n `[computeruse] Falling back to default screen size: ${errorMessage(error)}`,\n );\n }\n\n logger.info(\n `[computeruse] Service started on ${currentPlatform()} (${instance.screenSize.width}x${instance.screenSize.height}) approval=${instance.getApprovalMode()}`,\n );\n\n // Windows: pre-warm the persistent PowerShell host (and seed the display\n // cache through it) so the first capture/clipboard/scene turn doesn't pay\n // the ~10-16s cold `powershell.exe` spawn tax. Fire-and-forget — never\n // blocks startup, and every consumer falls back to one-shot spawns if the\n // host fails to warm. No-op off Windows.\n if (currentPlatform() === \"win32\") {\n void warmPsHost()\n .then(() => warmDisplaysCache())\n .catch(() => {});\n }\n\n return instance;\n }\n\n async stop(): Promise<void> {\n this.approvalManager.cancelAll(\"computer-use service stopped\");\n closeAllTerminalSessions();\n try {\n await closeBrowser();\n } catch {\n // ignore browser shutdown failures\n }\n // Tear down the persistent PowerShell host and latch spawning off so a\n // late fire-and-forget warm continuation can't resurrect it post-stop.\n disposePsHost();\n logger.info(\"[computeruse] Service stopped\");\n }\n\n async executeCommand(\n command: string,\n parameters: Record<string, unknown> = {},\n ): Promise<ComputerUseResult> {\n switch (command) {\n case \"screenshot\":\n case \"click\":\n case \"click_with_modifiers\":\n case \"double_click\":\n case \"right_click\":\n case \"mouse_move\":\n case \"middle_click\":\n case \"mouse_down\":\n case \"mouse_up\":\n case \"type\":\n case \"key_press\":\n case \"key_combo\":\n case \"key_down\":\n case \"key_up\":\n case \"scroll\":\n case \"drag\":\n case \"get_cursor_position\":\n case \"detect_elements\":\n case \"ocr\":\n case \"open\":\n case \"launch\":\n case \"kill_app\":\n case \"set_value\":\n return this.executeDesktopAction({\n ...commandParameters<DesktopActionParams>(parameters),\n action: this.mapDesktopCommandToAction(command),\n });\n case \"browser_open\":\n case \"browser_connect\":\n case \"browser_close\":\n case \"browser_navigate\":\n case \"browser_click\":\n case \"browser_type\":\n case \"browser_scroll\":\n case \"browser_screenshot\":\n case \"browser_dom\":\n case \"browser_get_dom\":\n case \"browser_clickables\":\n case \"browser_get_clickables\":\n case \"browser_execute\":\n case \"browser_state\":\n case \"browser_info\":\n case \"browser_get_context\":\n case \"browser_wait\":\n case \"browser_list_tabs\":\n case \"browser_open_tab\":\n case \"browser_close_tab\":\n case \"browser_switch_tab\":\n return this.executeBrowserAction({\n ...commandParameters<BrowserActionParams>(parameters),\n action: this.mapBrowserCommandToAction(command),\n });\n case \"list_windows\":\n case \"switch_to_window\":\n case \"arrange_windows\":\n case \"move_window\":\n case \"minimize_window\":\n case \"maximize_window\":\n case \"restore_window\":\n case \"close_window\":\n return this.executeWindowAction({\n ...commandParameters<WindowActionParams>(parameters),\n action: this.mapWindowCommandToAction(command),\n });\n case \"file_read\":\n case \"file_write\":\n case \"file_edit\":\n case \"file_append\":\n case \"file_delete\":\n case \"file_exists\":\n case \"directory_list\":\n case \"directory_delete\":\n case \"file_upload\":\n case \"file_download\":\n case \"file_list_downloads\":\n case \"file_read_bytes\":\n case \"file_write_bytes\":\n case \"file_create_dir\":\n case \"file_directory_exists\":\n case \"file_get_file_size\":\n return this.executeFileAction({\n ...commandParameters<FileActionParams>(parameters),\n action: this.mapFileCommandToAction(command),\n });\n case \"terminal_connect\":\n case \"terminal_execute\":\n case \"terminal_read\":\n case \"terminal_type\":\n case \"terminal_clear\":\n case \"terminal_close\":\n case \"execute_command\":\n return this.executeTerminalAction({\n ...commandParameters<TerminalActionParams>(parameters),\n action: this.mapTerminalCommandToAction(command),\n });\n default:\n return {\n success: false,\n error: `Unknown computer-use command: ${command}`,\n };\n }\n }\n\n async executeDesktopAction(\n rawParams: DesktopActionParams,\n ): Promise<ComputerActionResult> {\n const params = this.normalizeDesktopActionParams(rawParams);\n const entry = this.createEntry(params.action, this.toParamsRecord(params));\n\n try {\n const approvalError = await this.awaitApproval(\n this.desktopApprovalCommand(params.action),\n this.toParamsRecord(params),\n );\n if (approvalError) {\n return this.failEntry(entry, { success: false, error: approvalError });\n }\n\n if (params.action === \"ocr\" || params.action === \"detect_elements\") {\n return this.runOcrOrDetect(entry, params);\n }\n\n const targetDisplayId = this.resolveDisplayIdForAction(params);\n switch (params.action) {\n case \"screenshot\": {\n const captured = await this.captureScreenshotForDisplay(\n params.displayId ?? targetDisplayId,\n );\n return this.succeedEntry(entry, {\n success: true,\n screenshot: captured.base64,\n displayId: captured.displayId,\n });\n }\n case \"click\": {\n this.requireCoordinate(params.coordinate, \"click\");\n const g = this.toGlobal(params, params.coordinate);\n await driverClick(g.x, g.y);\n break;\n }\n case \"click_with_modifiers\": {\n this.requireCoordinate(params.coordinate, \"click_with_modifiers\");\n const g = this.toGlobal(params, params.coordinate);\n await driverClickWithModifiers(g.x, g.y, params.modifiers ?? []);\n break;\n }\n case \"double_click\": {\n this.requireCoordinate(params.coordinate, \"double_click\");\n const g = this.toGlobal(params, params.coordinate);\n await driverDoubleClick(g.x, g.y);\n break;\n }\n case \"right_click\": {\n this.requireCoordinate(params.coordinate, \"right_click\");\n const g = this.toGlobal(params, params.coordinate);\n await driverRightClick(g.x, g.y);\n break;\n }\n case \"mouse_move\": {\n this.requireCoordinate(params.coordinate, \"mouse_move\");\n const g = this.toGlobal(params, params.coordinate);\n await driverMouseMove(g.x, g.y);\n break;\n }\n case \"middle_click\": {\n this.requireCoordinate(params.coordinate, \"middle_click\");\n const g = this.toGlobal(params, params.coordinate);\n await driverMiddleClick(g.x, g.y);\n break;\n }\n case \"mouse_down\": {\n this.requireCoordinate(params.coordinate, \"mouse_down\");\n const g = this.toGlobal(params, params.coordinate);\n await driverMouseDown(g.x, g.y, params.button ?? \"left\");\n break;\n }\n case \"mouse_up\": {\n this.requireCoordinate(params.coordinate, \"mouse_up\");\n const g = this.toGlobal(params, params.coordinate);\n await driverMouseUp(g.x, g.y, params.button ?? \"left\");\n break;\n }\n case \"type\":\n if (!params.text) throw new Error(\"text is required for type action\");\n await driverType(params.text);\n break;\n case \"key\":\n if (!params.key) throw new Error(\"key is required for key action\");\n await driverKeyPress(params.key);\n break;\n case \"key_combo\":\n if (!params.key) {\n throw new Error(\"key is required for key_combo action\");\n }\n await driverKeyCombo(params.key);\n break;\n case \"key_down\":\n if (!params.key) {\n throw new Error(\"key is required for key_down action\");\n }\n await driverKeyDown(params.key);\n break;\n case \"key_up\":\n if (!params.key) {\n throw new Error(\"key is required for key_up action\");\n }\n await driverKeyUp(params.key);\n break;\n case \"scroll\": {\n this.requireCoordinate(params.coordinate, \"scroll\");\n const g = this.toGlobal(params, params.coordinate);\n await driverScroll(\n g.x,\n g.y,\n params.scrollDirection ?? \"down\",\n params.scrollAmount ?? 3,\n );\n break;\n }\n case \"get_cursor_position\": {\n // Read-only query — no coordinate, no post-action screenshot.\n const pos = await driverGetCursorPosition();\n return this.succeedEntry(entry, {\n success: true,\n cursorPosition: pos,\n message: `Cursor is at (${pos.x}, ${pos.y}).`,\n });\n }\n case \"drag\": {\n // A `path` of ≥2 points traces a real polyline (curves, corners,\n // marquee, swipe paths); otherwise fall back to a straight\n // startCoordinate→coordinate drag.\n if (params.path && params.path.length >= 2) {\n const global = params.path.map((p) => this.toGlobal(params, p));\n await driverDragPath(global);\n break;\n }\n this.requireCoordinate(\n params.startCoordinate,\n \"drag\",\n \"startCoordinate\",\n );\n this.requireCoordinate(params.coordinate, \"drag\");\n const start = this.toGlobal(params, params.startCoordinate);\n const end = this.toGlobal(params, params.coordinate);\n await driverDrag(start.x, start.y, end.x, end.y);\n break;\n }\n case \"open\": {\n if (!params.target) {\n throw new Error(\"target is required for open action\");\n }\n await openTarget(params.target);\n return this.succeedEntry(entry, {\n success: true,\n message: `Opened ${params.target}.`,\n });\n }\n case \"launch\": {\n if (!params.app) {\n throw new Error(\"app is required for launch action\");\n }\n const launched = await launchApp(params.app, params.appArgs ?? []);\n return this.succeedEntry(entry, {\n success: true,\n data: { pid: launched.pid, command: launched.command },\n message: `Launched ${params.app} (pid ${launched.pid}).`,\n });\n }\n case \"kill_app\": {\n // Accepts a pid or an app/process name via `target` (pairs with launch).\n const target = params.target ?? params.app;\n if (!target) {\n throw new Error(\n \"target (pid or app name) is required for kill_app action\",\n );\n }\n const killed = await killApp(String(target));\n return this.succeedEntry(entry, {\n success: true,\n data: killed,\n message: `Terminated ${killed.target}.`,\n });\n }\n case \"set_value\": {\n this.requireCoordinate(params.coordinate, \"set_value\");\n if (typeof params.text !== \"string\") {\n throw new Error(\"text (the value) is required for set_value action\");\n }\n const g = this.toGlobal(params, params.coordinate);\n await driverSetValue(g.x, g.y, params.text);\n break;\n }\n default:\n return this.failEntry(entry, {\n success: false,\n error: `Unknown desktop action: ${(params as { action: string }).action}`,\n });\n }\n\n const result: ComputerActionResult = { success: true };\n if (this.shouldCaptureAfterDesktopAction(params.action)) {\n try {\n const captured = await this.captureScreenshotForDisplay(\n params.displayId ?? targetDisplayId,\n );\n result.screenshot = captured.base64;\n result.displayId = captured.displayId;\n } catch (error) {\n logger.warn(\n `[computeruse] Post-action screenshot failed: ${errorMessage(error)}`,\n );\n }\n }\n return this.succeedEntry(entry, result);\n } catch (error) {\n const permissionError = classifyPermissionDeniedError(error, {\n permissionType:\n params.action === \"screenshot\" ? \"screen_recording\" : \"accessibility\",\n operation: params.action,\n });\n if (permissionError) {\n return this.failEntry(entry, {\n success: false,\n error: permissionError.message,\n permissionDenied: true,\n permissionType: permissionError.permissionType,\n });\n }\n return this.failEntry(entry, {\n success: false,\n error: errorMessage(error),\n });\n }\n }\n\n /**\n * `ocr` / `detect_elements` — real on-device OCR via the registered\n * CoordOcrProvider (plugin-vision contributes native Windows.Media.Ocr / Apple\n * Vision / docTR through `registerCoordOcrProvider`). Replaces the former\n * \"not available on local machines\" stub. Read-only; coordinates are\n * display-local so the agent can click them directly.\n */\n private async runOcrOrDetect(\n entry: ActionHistoryEntry,\n params: DesktopActionParams,\n ): Promise<ComputerActionResult> {\n const displayId =\n params.displayId ?? this.resolveDisplayIdForAction(params);\n\n // detect_elements prefers Set-of-Marks grounding when a provider is\n // registered (GGUF YOLO icons + OCR text fused into 1-indexed numbered\n // marks + overlay, #9170 M9). Falls back to OCR-only text elements.\n if (params.action === \"detect_elements\") {\n const somResult = await this.runSetOfMarksDetect(entry, displayId);\n if (somResult) return somResult;\n }\n\n const provider = getCoordOcrProvider();\n if (!provider) {\n return this.failEntry(entry, {\n success: false,\n error:\n \"No OCR provider is registered. Enable @elizaos/plugin-vision for on-device OCR (Windows.Media.Ocr / Apple Vision / docTR).\",\n });\n }\n try {\n const cap = await captureDisplay(displayId);\n const { blocks } = await provider.describe({\n displayId: String(cap.display.id),\n sourceX: 0,\n sourceY: 0,\n pngBytes: new Uint8Array(cap.frame),\n });\n if (params.action === \"detect_elements\") {\n const elements = blocks.map((b, i) => ({\n id: `e${i + 1}`,\n kind: \"text\" as const,\n text: b.text,\n bbox: [b.bbox.x, b.bbox.y, b.bbox.width, b.bbox.height] as [\n number,\n number,\n number,\n number,\n ],\n semantic_position: b.semantic_position,\n displayId: cap.display.id,\n }));\n return this.succeedEntry(entry, {\n success: true,\n displayId: cap.display.id,\n data: { elements, count: elements.length },\n message: `Detected ${elements.length} text element(s) on display ${cap.display.id}.`,\n });\n }\n const text = blocks.map((b) => b.text).join(\"\\n\");\n return this.succeedEntry(entry, {\n success: true,\n displayId: cap.display.id,\n data: { text, blocks },\n message: `OCR found ${blocks.length} text block(s) on display ${cap.display.id}.`,\n });\n } catch (error) {\n return this.failEntry(entry, {\n success: false,\n error: errorMessage(error),\n });\n }\n }\n\n /**\n * Set-of-Marks `detect_elements` path (#9170 M9). Returns `null` when no SoM\n * provider is registered so the caller falls back to OCR-only detection.\n * Each numbered mark becomes an element whose `center` is the click target\n * the VLM's chosen number resolves to; the numbered-overlay PNG is returned\n * for the prompt under `data.setOfMarks.overlay`.\n */\n private async runSetOfMarksDetect(\n entry: ActionHistoryEntry,\n displayId: number,\n ): Promise<ComputerActionResult | null> {\n const som = getSetOfMarksProvider();\n if (!som) return null;\n try {\n const cap = await captureDisplay(displayId);\n const { marks, overlayPngBase64 } = await som.describe({\n displayId: String(cap.display.id),\n sourceX: 0,\n sourceY: 0,\n pngBytes: new Uint8Array(cap.frame),\n renderOverlay: true,\n });\n const elements = marks.map((m) => ({\n id: `m${m.index}`,\n mark: m.index,\n kind: m.source,\n text: m.label ?? \"\",\n bbox: [m.bbox[0], m.bbox[1], m.bbox[2], m.bbox[3]] as [\n number,\n number,\n number,\n number,\n ],\n center: [m.center[0], m.center[1]] as [number, number],\n score: m.score,\n displayId: cap.display.id,\n }));\n return this.succeedEntry(entry, {\n success: true,\n displayId: cap.display.id,\n data: {\n elements,\n count: elements.length,\n setOfMarks: {\n marks,\n ...(overlayPngBase64 ? { overlay: overlayPngBase64 } : {}),\n },\n },\n message: `Set-of-Marks detected ${elements.length} numbered element(s) on display ${cap.display.id}.`,\n });\n } catch (error) {\n // SoM is best-effort; surface a clear failure rather than silently\n // dropping to OCR (the caller already chose SoM by registering it).\n return this.failEntry(entry, {\n success: false,\n error: `Set-of-Marks detection failed: ${errorMessage(error)}`,\n });\n }\n }\n\n async executeBrowserAction(\n rawParams: BrowserActionParams,\n ): Promise<BrowserActionResult> {\n const params = this.normalizeBrowserActionParams(rawParams);\n const entry = this.createEntry(\n `browser_${params.action}`,\n this.toParamsRecord(params),\n );\n\n try {\n const approvalError = await this.awaitApproval(\n this.browserApprovalCommand(params.action),\n this.toParamsRecord(params),\n );\n if (approvalError) {\n return this.failEntry(entry, { success: false, error: approvalError });\n }\n\n const result = await this.runBrowserAction(params);\n if (this.shouldAutoOpenBrowser(params.action, result.error)) {\n return await this.retryBrowserActionAfterOpen(entry, params);\n }\n return result.success\n ? this.succeedEntry(entry, result)\n : this.failEntry(entry, result);\n } catch (error) {\n if (this.shouldAutoOpenBrowser(params.action, error)) {\n return await this.retryBrowserActionAfterOpen(entry, params);\n }\n return this.failEntry(entry, {\n success: false,\n error: errorMessage(error),\n });\n }\n }\n\n private async retryBrowserActionAfterOpen(\n entry: ActionHistoryEntry,\n params: BrowserActionParams,\n ): Promise<BrowserActionResult> {\n try {\n const openResult = await this.runBrowserAction({\n ...params,\n action: \"open\",\n });\n if (!openResult.success) {\n return this.failEntry(entry, openResult);\n }\n\n const retryResult = await this.runBrowserAction(params);\n return retryResult.success\n ? this.succeedEntry(entry, retryResult)\n : this.failEntry(entry, retryResult);\n } catch (error) {\n return this.failEntry(entry, {\n success: false,\n error: errorMessage(error),\n });\n }\n }\n\n private shouldAutoOpenBrowser(\n action: BrowserActionParams[\"action\"],\n error: unknown,\n ): boolean {\n return (\n !BROWSER_LIFECYCLE_ACTIONS.has(action) && isBrowserNotOpenMessage(error)\n );\n }\n\n private async runBrowserAction(\n params: BrowserActionParams,\n ): Promise<BrowserActionResult> {\n switch (params.action) {\n case \"open\":\n case \"connect\": {\n const state = await openBrowser(params.url);\n return {\n success: true,\n url: state.url,\n title: state.title,\n isOpen: true,\n is_open: true,\n data: state,\n content: stringifyData(state),\n message: `Opened browser: ${state.url}`,\n };\n }\n case \"close\":\n await closeBrowser();\n return {\n success: true,\n isOpen: false,\n is_open: false,\n message: \"Browser closed.\",\n };\n case \"navigate\": {\n const url = this.requireIdentifier(\n params.url,\n \"url is required for navigate\",\n );\n const state = await navigateBrowser(url);\n return {\n success: true,\n url: state.url,\n title: state.title,\n isOpen: true,\n is_open: true,\n data: state,\n content: stringifyData(state),\n message: `Navigated to ${state.url}`,\n };\n }\n case \"click\":\n await clickBrowser(params.selector, params.coordinate, params.text);\n return {\n success: true,\n message: \"Clicked browser target.\",\n };\n case \"type\":\n if (!params.text) {\n throw new Error(\"text is required for browser type\");\n }\n await typeBrowser(params.text, params.selector);\n return {\n success: true,\n message: \"Typed browser text.\",\n };\n case \"scroll\":\n await scrollBrowser(params.direction ?? \"down\", params.amount ?? 300);\n return {\n success: true,\n message: `Scrolled browser ${params.direction ?? \"down\"}.`,\n };\n case \"screenshot\": {\n const screenshot = await screenshotBrowser();\n return {\n success: true,\n screenshot,\n frontendScreenshot: screenshot,\n message: \"Captured browser screenshot.\",\n };\n }\n case \"dom\":\n case \"get_dom\": {\n const content = await getBrowserDom();\n return {\n success: true,\n content,\n message: \"Fetched browser DOM.\",\n };\n }\n case \"clickables\":\n case \"get_clickables\": {\n const elements = await getBrowserClickables();\n return {\n success: true,\n elements,\n count: elements.length,\n data: elements,\n content: stringifyData(elements),\n message: \"Fetched browser clickables.\",\n };\n }\n case \"execute\": {\n const code = this.requireIdentifier(\n params.code,\n \"code is required for browser execute\",\n );\n const content = await executeBrowser(code);\n return {\n success: true,\n content,\n message: \"Executed browser JavaScript.\",\n };\n }\n case \"state\": {\n const data = await getBrowserState();\n return {\n success: true,\n url: data.url,\n title: data.title,\n isOpen: true,\n is_open: true,\n data,\n content: stringifyData(data),\n };\n }\n case \"info\": {\n const info = await getBrowserInfo();\n return {\n success: info.success,\n url: info.url,\n title: info.title,\n isOpen: info.isOpen,\n is_open: info.is_open,\n data: info,\n content: stringifyData(info),\n ...(info.success ? {} : { error: info.error }),\n };\n }\n case \"context\":\n case \"get_context\": {\n const data = await getBrowserContext();\n return {\n success: true,\n url: data.url,\n title: data.title,\n isOpen: true,\n is_open: true,\n data,\n content: stringifyData(data),\n };\n }\n case \"wait\":\n await waitBrowser(\n params.selector,\n params.text,\n params.timeout ?? this.cuConfig.actionTimeoutMs,\n );\n return {\n success: true,\n message: \"Browser wait condition satisfied.\",\n };\n case \"list_tabs\": {\n const tabs = await listBrowserTabs();\n return {\n success: true,\n tabs,\n count: tabs.length,\n data: tabs,\n content: stringifyData(tabs),\n };\n }\n case \"open_tab\": {\n const tab = await openBrowserTab(params.url);\n return {\n success: true,\n data: tab,\n content: stringifyData(tab),\n message: `Opened tab ${tab.id}.`,\n };\n }\n case \"close_tab\": {\n const tabId = this.requireIdentifier(\n params.tabId,\n \"tabId is required for close_tab\",\n );\n await closeBrowserTab(tabId);\n return {\n success: true,\n message: `Closed tab ${tabId}.`,\n };\n }\n case \"switch_tab\": {\n const tabId = this.requireIdentifier(\n params.tabId,\n \"tabId is required for switch_tab\",\n );\n const state = await switchBrowserTab(tabId);\n return {\n success: true,\n url: state.url,\n title: state.title,\n isOpen: true,\n is_open: true,\n data: state,\n content: stringifyData(state),\n message: `Switched to tab ${tabId}.`,\n };\n }\n default:\n return {\n success: false,\n error: `Unknown browser action: ${(params as { action: string }).action}`,\n };\n }\n }\n\n async executeWindowAction(\n rawParams: WindowActionParams,\n ): Promise<WindowActionResult> {\n const params = this.normalizeWindowActionParams(rawParams);\n const entry = this.createEntry(\n `window_${params.action}`,\n this.toParamsRecord(params),\n );\n\n try {\n const approvalError = await this.awaitApproval(\n this.windowApprovalCommand(params.action),\n this.toParamsRecord(params),\n );\n if (approvalError) {\n return this.failEntry(entry, { success: false, error: approvalError });\n }\n\n switch (params.action) {\n case \"list\": {\n const windows = listWindows();\n return this.succeedEntry(entry, {\n success: true,\n windows,\n count: windows.length,\n });\n }\n case \"focus\":\n focusWindow(this.requireWindowTarget(params));\n return this.succeedEntry(entry, {\n success: true,\n message: \"Focused window.\",\n });\n case \"switch\":\n switchWindow(this.requireWindowTarget(params));\n return this.succeedEntry(entry, {\n success: true,\n message: \"Switched window.\",\n });\n case \"arrange\":\n return this.succeedEntry(entry, arrangeWindows(params.arrangement));\n case \"move\": {\n const result = moveWindow(\n this.requireWindowTarget(params),\n this.requireNumber(params.x, \"x is required for window move\"),\n this.requireNumber(params.y, \"y is required for window move\"),\n );\n return this.succeedEntry(entry, result);\n }\n case \"minimize\":\n minimizeWindow(this.requireWindowTarget(params));\n return this.succeedEntry(entry, {\n success: true,\n message: \"Window minimized.\",\n });\n case \"maximize\":\n maximizeWindow(this.requireWindowTarget(params));\n return this.succeedEntry(entry, {\n success: true,\n message: \"Window maximized.\",\n });\n case \"restore\":\n restoreWindow(this.requireWindowTarget(params));\n return this.succeedEntry(entry, {\n success: true,\n message: \"Window restored.\",\n });\n case \"close\":\n closeWindow(this.requireWindowTarget(params));\n return this.succeedEntry(entry, {\n success: true,\n message: \"Window closed.\",\n });\n case \"get_current_window_id\": {\n const active = getActiveWindow();\n return this.succeedEntry(entry, {\n success: true,\n windowId: active?.id ?? null,\n window: active,\n message: active\n ? `Focused window: [${active.id}] ${active.app} - ${active.title}`\n : \"No focused window.\",\n });\n }\n case \"get_application_windows\": {\n const appName = params.appName ?? params.title ?? params.window;\n if (!appName) {\n throw new Error(\"appName is required for get_application_windows\");\n }\n const windows = getApplicationWindows(appName);\n return this.succeedEntry(entry, {\n success: true,\n windows,\n count: windows.length,\n });\n }\n case \"set_bounds\": {\n const result = resizeWindow(\n this.requireWindowTarget(params),\n this.requireNumber(params.x, \"x is required for set_bounds\"),\n this.requireNumber(params.y, \"y is required for set_bounds\"),\n params.width,\n params.height,\n );\n return this.succeedEntry(entry, result);\n }\n case \"get_window_size\":\n case \"get_window_position\": {\n // windowId is optional — defaults to the focused/foreground window.\n const bounds = getWindowBounds(params.windowId);\n return this.succeedEntry(entry, {\n success: true,\n bounds,\n message:\n params.action === \"get_window_size\"\n ? `Window size: ${bounds.width}x${bounds.height}.`\n : `Window position: (${bounds.x}, ${bounds.y}).`,\n });\n }\n default:\n return this.failEntry(entry, {\n success: false,\n error: `Unknown window action: ${(params as { action: string }).action}`,\n });\n }\n } catch (error) {\n const permissionError = classifyPermissionDeniedError(error, {\n permissionType: \"accessibility\",\n operation: params.action,\n });\n if (permissionError) {\n return this.failEntry(entry, {\n success: false,\n error: permissionError.message,\n permissionDenied: true,\n permissionType: permissionError.permissionType,\n });\n }\n return this.failEntry(entry, {\n success: false,\n error: errorMessage(error),\n });\n }\n }\n\n async executeFileAction(\n rawParams: FileActionParams,\n ): Promise<FileActionResult> {\n const params = this.normalizeFileActionParams(rawParams);\n const entry = this.createEntry(\n `file_${params.action}`,\n this.toParamsRecord(params),\n );\n\n try {\n const approvalError = await this.awaitApproval(\n this.fileApprovalCommand(params.action),\n this.toParamsRecord(params),\n );\n if (approvalError) {\n return this.failEntry(entry, { success: false, error: approvalError });\n }\n\n const targetPath =\n params.action === \"list_downloads\"\n ? this.defaultDownloadsPath()\n : this.requireIdentifier(\n params.path,\n \"path is required for file action\",\n );\n\n switch (params.action) {\n case \"read\":\n case \"download\":\n return this.finishFileEntry(\n entry,\n await readFile(targetPath, this.normalizeEncoding(params.encoding)),\n );\n case \"write\":\n case \"upload\":\n if (typeof params.content !== \"string\") {\n throw new Error(\"content is required for file write\");\n }\n return this.finishFileEntry(\n entry,\n await writeFile(targetPath, params.content),\n );\n case \"edit\":\n if (typeof params.old_text !== \"string\") {\n throw new Error(\"old_text is required for file edit\");\n }\n if (typeof params.new_text !== \"string\") {\n throw new Error(\"new_text is required for file edit\");\n }\n return this.finishFileEntry(\n entry,\n await editFile(targetPath, params.old_text, params.new_text),\n );\n case \"append\":\n if (typeof params.content !== \"string\") {\n throw new Error(\"content is required for file append\");\n }\n return this.finishFileEntry(\n entry,\n await appendFile(targetPath, params.content),\n );\n case \"delete\":\n return this.finishFileEntry(entry, await deleteFile(targetPath));\n case \"exists\":\n return this.finishFileEntry(entry, await fileExists(targetPath));\n case \"list\":\n case \"list_downloads\":\n return this.finishFileEntry(entry, await listDirectory(targetPath));\n case \"delete_directory\":\n return this.finishFileEntry(entry, await deleteDirectory(targetPath));\n case \"read_bytes\":\n return this.finishFileEntry(\n entry,\n await readBytes(targetPath, params.offset, params.length),\n );\n case \"write_bytes\":\n if (typeof params.base64 !== \"string\") {\n throw new Error(\"base64 is required for file write_bytes\");\n }\n return this.finishFileEntry(\n entry,\n await writeBytes(targetPath, params.base64),\n );\n case \"create_dir\":\n return this.finishFileEntry(\n entry,\n await createDirectory(targetPath),\n );\n case \"directory_exists\":\n return this.finishFileEntry(\n entry,\n await directoryExists(targetPath),\n );\n case \"get_file_size\":\n return this.finishFileEntry(entry, await getFileSize(targetPath));\n default:\n return this.failEntry(entry, {\n success: false,\n error: `Unknown file action: ${(params as { action: string }).action}`,\n });\n }\n } catch (error) {\n return this.failEntry(entry, {\n success: false,\n error: errorMessage(error),\n });\n }\n }\n\n async executeTerminalAction(\n rawParams: TerminalActionParams,\n ): Promise<TerminalActionResult> {\n const params = this.normalizeTerminalActionParams(rawParams);\n const entry = this.createEntry(\n `terminal_${params.action}`,\n this.toParamsRecord(params),\n );\n\n try {\n const approvalError = await this.awaitApproval(\n this.terminalApprovalCommand(params.action),\n this.toParamsRecord(params),\n );\n if (approvalError) {\n return this.failEntry(entry, { success: false, error: approvalError });\n }\n\n switch (params.action) {\n case \"connect\":\n return this.finishTerminalEntry(\n entry,\n await connectTerminal(params.cwd),\n );\n case \"execute\":\n return this.finishTerminalEntry(\n entry,\n await executeTerminal({\n command: this.requireIdentifier(\n params.command,\n \"command is required for terminal execute\",\n ),\n timeoutSeconds:\n params.timeout ??\n Math.max(1, Math.ceil(this.cuConfig.actionTimeoutMs / 1000)),\n sessionId: params.sessionId,\n cwd: params.cwd,\n }),\n );\n case \"read\":\n return this.finishTerminalEntry(\n entry,\n await readTerminal(params.sessionId),\n );\n case \"type\":\n return this.finishTerminalEntry(\n entry,\n await typeTerminal(\n this.requireIdentifier(\n params.text,\n \"text is required for terminal type\",\n ),\n ),\n );\n case \"clear\":\n return this.finishTerminalEntry(\n entry,\n await clearTerminal(params.sessionId),\n );\n case \"close\":\n return this.finishTerminalEntry(\n entry,\n await closeTerminal(params.sessionId),\n );\n case \"execute_command\":\n return this.finishTerminalEntry(\n entry,\n await executeTerminal({\n command: this.requireIdentifier(\n params.command,\n \"command is required for execute_command\",\n ),\n timeoutSeconds:\n params.timeout ??\n Math.max(1, Math.ceil(this.cuConfig.actionTimeoutMs / 1000)),\n sessionId: params.sessionId,\n cwd: params.cwd,\n }),\n );\n default:\n return this.failEntry(entry, {\n success: false,\n error: `Unknown terminal action: ${(params as { action: string }).action}`,\n });\n }\n } catch (error) {\n return this.failEntry(entry, {\n success: false,\n error: errorMessage(error),\n });\n }\n }\n\n async captureScreen(): Promise<Buffer> {\n return driverCaptureScreenshot();\n }\n\n getCapabilities(): PlatformCapabilities {\n return this.capabilities;\n }\n\n getConfig(): ComputerUseConfig {\n return {\n ...this.cuConfig,\n sandbox: this.cuConfig.sandbox\n ? {\n ...this.cuConfig.sandbox,\n options: this.cuConfig.sandbox.options\n ? { ...this.cuConfig.sandbox.options }\n : undefined,\n }\n : undefined,\n };\n }\n\n getRecentActions(): ActionHistoryEntry[] {\n return [...this.recentActions];\n }\n\n getScreenDimensions(): ScreenSize {\n return this.screenSize;\n }\n\n getApprovalMode(): ApprovalMode {\n return this.approvalManager.getMode();\n }\n\n setApprovalMode(mode: ApprovalMode): ApprovalMode {\n const nextMode = this.approvalManager.setMode(mode);\n this.cuConfig.approvalMode = nextMode;\n logger.info(`[computeruse] Approval mode set to ${nextMode}`);\n return nextMode;\n }\n\n getApprovalSnapshot(): ApprovalSnapshot {\n return this.approvalManager.getSnapshot();\n }\n\n subscribeApprovals(\n listener: (snapshot: ApprovalSnapshot) => void,\n ): () => void {\n return this.approvalManager.subscribe(listener);\n }\n\n resolveApproval(\n id: string,\n approved: boolean,\n reason?: string,\n ): ApprovalResolution | null {\n return this.approvalManager.resolveApproval(id, approved, reason);\n }\n\n private normalizeDesktopActionParams(\n params: DesktopActionParams,\n ): DesktopActionParams {\n const coordinate =\n params.coordinate ??\n (params.x !== undefined && params.y !== undefined\n ? [Number(params.x), Number(params.y)]\n : undefined);\n const startCoordinate =\n params.startCoordinate ??\n (params.x1 !== undefined && params.y1 !== undefined\n ? [Number(params.x1), Number(params.y1)]\n : undefined);\n const endCoordinate =\n coordinate ??\n (params.x2 !== undefined && params.y2 !== undefined\n ? [Number(params.x2), Number(params.y2)]\n : undefined);\n\n return {\n ...params,\n coordinate: endCoordinate,\n startCoordinate,\n modifiers: params.modifiers ?? params.hold_keys,\n scrollAmount: params.scrollAmount ?? params.amount,\n };\n }\n\n private normalizeBrowserActionParams(\n params: BrowserActionParams,\n ): BrowserActionParams {\n const tabIdCandidate = params.tabId ?? params.index ?? params.tab_index;\n return {\n ...params,\n tabId: tabIdCandidate !== undefined ? String(tabIdCandidate) : undefined,\n action: this.normalizeBrowserAction(params.action),\n };\n }\n\n private normalizeWindowActionParams(\n params: WindowActionParams,\n ): WindowActionParams {\n return {\n ...params,\n windowId: params.windowId ?? params.window ?? params.title,\n windowTitle: params.windowTitle ?? params.window ?? params.title,\n };\n }\n\n private normalizeFileActionParams(\n params: FileActionParams,\n ): FileActionParams {\n return {\n ...params,\n path: params.path ?? params.filepath ?? params.dirpath,\n old_text: params.old_text ?? params.oldText ?? params.find,\n new_text: params.new_text ?? params.newText ?? params.replace,\n };\n }\n\n private normalizeTerminalActionParams(\n params: TerminalActionParams,\n ): TerminalActionParams {\n return {\n ...params,\n timeout: params.timeout ?? params.timeoutSeconds,\n sessionId: params.sessionId ?? params.session_id,\n action:\n params.action === \"execute_command\" ? \"execute_command\" : params.action,\n };\n }\n\n private normalizeBrowserAction(\n action: BrowserActionParams[\"action\"],\n ): BrowserActionParams[\"action\"] {\n switch (action) {\n case \"get_dom\":\n return \"dom\";\n case \"get_clickables\":\n return \"clickables\";\n case \"get_context\":\n return \"context\";\n default:\n return action;\n }\n }\n\n private desktopApprovalCommand(\n action: DesktopActionParams[\"action\"],\n ): string {\n return action === \"key\" ? \"key_press\" : action;\n }\n\n private browserApprovalCommand(\n action: BrowserActionParams[\"action\"],\n ): string {\n switch (action) {\n case \"open\":\n return \"browser_open\";\n case \"connect\":\n return \"browser_connect\";\n case \"close\":\n return \"browser_close\";\n case \"navigate\":\n return \"browser_navigate\";\n case \"click\":\n return \"browser_click\";\n case \"type\":\n return \"browser_type\";\n case \"scroll\":\n return \"browser_scroll\";\n case \"screenshot\":\n return \"browser_screenshot\";\n case \"dom\":\n return \"browser_get_dom\";\n case \"clickables\":\n return \"browser_get_clickables\";\n case \"execute\":\n return \"browser_execute\";\n case \"state\":\n return \"browser_state\";\n case \"info\":\n return \"browser_info\";\n case \"context\":\n return \"browser_get_context\";\n case \"wait\":\n return \"browser_wait\";\n case \"list_tabs\":\n return \"browser_list_tabs\";\n case \"open_tab\":\n return \"browser_open_tab\";\n case \"close_tab\":\n return \"browser_close_tab\";\n case \"switch_tab\":\n return \"browser_switch_tab\";\n case \"get_dom\":\n return \"browser_get_dom\";\n case \"get_clickables\":\n return \"browser_get_clickables\";\n default:\n return `browser_${action as string}`;\n }\n }\n\n private windowApprovalCommand(action: WindowActionParams[\"action\"]): string {\n switch (action) {\n case \"list\":\n return \"list_windows\";\n case \"focus\":\n case \"switch\":\n return \"switch_to_window\";\n case \"arrange\":\n return \"arrange_windows\";\n case \"move\":\n return \"move_window\";\n case \"minimize\":\n return \"minimize_window\";\n case \"maximize\":\n return \"maximize_window\";\n case \"restore\":\n return \"restore_window\";\n case \"close\":\n return \"close_window\";\n case \"get_current_window_id\":\n case \"get_application_windows\":\n case \"get_window_size\":\n case \"get_window_position\":\n // Read-only getters — auto-approve (mapped to the SAFE list_windows).\n return \"list_windows\";\n case \"set_bounds\":\n return \"move_window\";\n }\n }\n\n private fileApprovalCommand(action: FileActionParams[\"action\"]): string {\n switch (action) {\n case \"read\":\n return \"file_read\";\n case \"write\":\n return \"file_write\";\n case \"edit\":\n return \"file_edit\";\n case \"append\":\n return \"file_append\";\n case \"delete\":\n return \"file_delete\";\n case \"exists\":\n return \"file_exists\";\n case \"list\":\n return \"directory_list\";\n case \"delete_directory\":\n return \"directory_delete\";\n case \"upload\":\n return \"file_upload\";\n case \"download\":\n return \"file_download\";\n case \"list_downloads\":\n return \"file_list_downloads\";\n case \"list_directory\":\n return \"directory_list\";\n default:\n return `file_${action as string}`;\n }\n }\n\n private terminalApprovalCommand(\n action: TerminalActionParams[\"action\"],\n ): string {\n switch (action) {\n case \"connect\":\n return \"terminal_connect\";\n case \"execute\":\n return \"terminal_execute\";\n case \"read\":\n return \"terminal_read\";\n case \"type\":\n return \"terminal_type\";\n case \"clear\":\n return \"terminal_clear\";\n case \"close\":\n return \"terminal_close\";\n case \"execute_command\":\n return \"execute_command\";\n }\n }\n\n private mapDesktopCommandToAction(\n command: string,\n ): DesktopActionParams[\"action\"] {\n switch (command) {\n case \"key_press\":\n return \"key\";\n default:\n return command as DesktopActionParams[\"action\"];\n }\n }\n\n private mapBrowserCommandToAction(\n command: string,\n ): BrowserActionParams[\"action\"] {\n const value = command.replace(/^browser_/, \"\");\n switch (value) {\n case \"get_dom\":\n return \"get_dom\";\n case \"get_clickables\":\n return \"get_clickables\";\n case \"get_context\":\n return \"context\";\n default:\n return value as BrowserActionParams[\"action\"];\n }\n }\n\n private mapWindowCommandToAction(\n command: string,\n ): WindowActionParams[\"action\"] {\n switch (command) {\n case \"list_windows\":\n return \"list\";\n case \"switch_to_window\":\n return \"switch\";\n case \"arrange_windows\":\n return \"arrange\";\n case \"move_window\":\n return \"move\";\n case \"minimize_window\":\n return \"minimize\";\n case \"maximize_window\":\n return \"maximize\";\n case \"restore_window\":\n return \"restore\";\n case \"close_window\":\n return \"close\";\n default:\n return \"list\";\n }\n }\n\n private mapFileCommandToAction(command: string): FileActionParams[\"action\"] {\n switch (command) {\n case \"file_read\":\n return \"read\";\n case \"file_write\":\n return \"write\";\n case \"file_edit\":\n return \"edit\";\n case \"file_append\":\n return \"append\";\n case \"file_delete\":\n return \"delete\";\n case \"file_exists\":\n return \"exists\";\n case \"directory_list\":\n return \"list\";\n case \"directory_delete\":\n return \"delete_directory\";\n case \"file_upload\":\n return \"upload\";\n case \"file_download\":\n return \"download\";\n case \"file_list_downloads\":\n return \"list_downloads\";\n case \"file_read_bytes\":\n return \"read_bytes\";\n case \"file_write_bytes\":\n return \"write_bytes\";\n case \"file_create_dir\":\n return \"create_dir\";\n case \"file_directory_exists\":\n return \"directory_exists\";\n case \"file_get_file_size\":\n return \"get_file_size\";\n default:\n return \"read\";\n }\n }\n\n private mapTerminalCommandToAction(\n command: string,\n ): TerminalActionParams[\"action\"] {\n switch (command) {\n case \"terminal_connect\":\n return \"connect\";\n case \"terminal_execute\":\n return \"execute\";\n case \"terminal_read\":\n return \"read\";\n case \"terminal_type\":\n return \"type\";\n case \"terminal_clear\":\n return \"clear\";\n case \"terminal_close\":\n return \"close\";\n case \"execute_command\":\n return \"execute_command\";\n default:\n return \"connect\";\n }\n }\n\n private async awaitApproval(\n command: string,\n parameters: Record<string, unknown>,\n ): Promise<string | null> {\n if (this.approvalManager.shouldAutoApprove(command)) {\n return null;\n }\n if (this.approvalManager.isDenyAll()) {\n return `Computer use is paused. \"${command}\" was blocked by approval mode \"${this.approvalManager.getMode()}\".`;\n }\n const decision = await this.approvalManager.requestApproval(\n command,\n parameters,\n );\n if (decision.approved) {\n return null;\n }\n if (decision.cancelled) {\n return decision.reason\n ? `Computer-use approval cancelled: ${decision.reason}`\n : `Computer-use approval cancelled for \"${command}\".`;\n }\n return decision.reason\n ? `Computer-use approval rejected: ${decision.reason}`\n : `Computer-use approval rejected for \"${command}\".`;\n }\n\n /**\n * Capture a specific display's frame as base64 PNG. Falls back to the\n * legacy single-display path if the per-display capture throws.\n */\n private async captureScreenshotForDisplay(\n displayId: number | undefined,\n ): Promise<{ base64: string; displayId: number }> {\n try {\n const result =\n displayId === undefined\n ? await capturePrimaryDisplay()\n : await captureDisplay(displayId);\n return {\n base64: result.frame.toString(\"base64\"),\n displayId: result.display.id,\n };\n } catch (error) {\n logger.debug(\n `[computeruse] per-display capture failed (${errorMessage(error)}); falling back to driver capture`,\n );\n const buf = await driverCaptureScreenshot();\n return {\n base64: buf.toString(\"base64\"),\n displayId: displayId ?? getPrimaryDisplay().id,\n };\n }\n }\n\n /**\n * Resolve which display a coordinate-bearing action targets.\n * Emits a deprecation warning when displayId is omitted on multi-monitor\n * setups; defaults to the primary display.\n */\n private resolveDisplayIdForAction(params: DesktopActionParams): number {\n const needsCoord = COORDINATE_BEARING_ACTIONS.has(params.action);\n if (params.displayId !== undefined) return params.displayId;\n if (!needsCoord) return getPrimaryDisplay().id;\n if (!this.displayIdDeprecationWarned) {\n this.displayIdDeprecationWarned = true;\n const displays = listDisplays();\n if (displays.length > 1) {\n logger.warn(\n `[computeruse] DEPRECATED: action \"${params.action}\" was called without displayId on a ${displays.length}-display host. Defaulting to primary display ${getPrimaryDisplay().id}. Set displayId explicitly; this fallback will be removed.`,\n );\n } else {\n logger.debug(\n `[computeruse] action \"${params.action}\" omitted displayId; defaulting to primary on single-display host.`,\n );\n }\n }\n return getPrimaryDisplay().id;\n }\n\n private toGlobal(\n params: DesktopActionParams,\n coordinate: [number, number],\n ): { x: number; y: number } {\n return localToGlobalDefault(\n {\n displayId: params.displayId,\n x: coordinate[0],\n y: coordinate[1],\n },\n params.coordSource ?? \"logical\",\n );\n }\n\n /** Surface the live display layout for the agent state provider. */\n getDisplays(): DisplayDescriptor[] {\n return listDisplays().map((d) => ({\n id: d.id,\n bounds: d.bounds,\n scaleFactor: d.scaleFactor,\n primary: d.primary,\n name: d.name,\n }));\n }\n\n /**\n * Return the most recently built Scene (WS6). Returns null before the\n * first tick. The `scene` provider seeds an initial tick on first read\n * so this is rarely null in practice.\n */\n getCurrentScene(): Scene | null {\n return this.sceneBuilder.getCurrentScene();\n }\n\n /**\n * Force a fresh Scene build. Used by the `scene` provider on first read\n * and by WS7's Brain to refresh before a new turn.\n */\n async refreshScene(\n mode: \"idle\" | \"active\" | \"agent-turn\" = \"agent-turn\",\n ): Promise<Scene> {\n return this.sceneBuilder.tick(mode);\n }\n\n /**\n * Subscribe to scene updates. Returns an unsubscribe function. The\n * SceneBuilder ticks only on explicit `refreshScene` calls — subscribers\n * are notified whenever a tick completes.\n */\n subscribeToSceneUpdates(\n handler: (event: SceneUpdateEvent) => void,\n ): () => void {\n return this.sceneBuilder.subscribe(handler);\n }\n\n /**\n * Shared single-capture `ScreenState` for a display (#9105 M3). Reuses the\n * last capture inside the freshness window; pass `force` to re-capture. This\n * is the one capture per turn that OCR, the Brain, and the DirtyTileDescriber\n * all read instead of grabbing their own frame.\n */\n async getScreenState(displayId = 0, force = false): Promise<ScreenState> {\n return this.screenStateStore.get(displayId, force);\n }\n\n /** Subscribe to screen-change events (dHash moved ≥ threshold). */\n subscribeScreenChange(\n listener: (change: ScreenStateChange) => void,\n ): () => void {\n return this.screenStateStore.onChange(listener);\n }\n\n /** Capture-accounting snapshot proving the per-turn capture saving. */\n getScreenStateStats(): ReturnType<ScreenStateStore[\"getStats\"]> {\n return this.screenStateStore.getStats();\n }\n\n /**\n * Populate the current scene's VLM annotations (#9105 M3). The Brain and the\n * DirtyTileDescriber produce `vlm_scene` / `vlm_elements`; this persists them\n * so the next `scene` provider read carries the cheap understanding instead\n * of forcing a fresh describe.\n */\n setSceneVlmAnnotations(\n vlmScene: string | null,\n vlmElements: SceneVlmElement[] | null,\n ): void {\n this.sceneBuilder.setVlmAnnotations(vlmScene, vlmElements);\n }\n\n private shouldCaptureAfterDesktopAction(\n action: DesktopActionParams[\"action\"],\n ): boolean {\n return action !== \"screenshot\" &&\n action !== \"detect_elements\" &&\n action !== \"ocr\"\n ? this.cuConfig.screenshotAfterAction\n : false;\n }\n\n private createEntry(\n action: string,\n params: Record<string, unknown>,\n ): ActionHistoryEntry {\n return {\n action,\n timestamp: Date.now(),\n params,\n success: false,\n };\n }\n\n private succeedEntry<T extends { success: boolean }>(\n entry: ActionHistoryEntry,\n result: T,\n ): T {\n entry.success = true;\n this.pushAction(entry);\n return result;\n }\n\n private failEntry<T extends { success: boolean }>(\n entry: ActionHistoryEntry,\n result: T,\n ): T {\n entry.success = false;\n this.pushAction(entry);\n return result;\n }\n\n private finishFileEntry(\n entry: ActionHistoryEntry,\n result: FileActionResult,\n ): FileActionResult {\n const normalized: FileActionResult = {\n ...result,\n isFile: result.isFile ?? result.is_file,\n isDirectory: result.isDirectory ?? result.is_directory,\n is_file: result.is_file ?? result.isFile,\n is_directory: result.is_directory ?? result.isDirectory,\n };\n return normalized.success\n ? this.succeedEntry(entry, normalized)\n : this.failEntry(entry, normalized);\n }\n\n private finishTerminalEntry(\n entry: ActionHistoryEntry,\n result: TerminalActionResult,\n ): TerminalActionResult {\n const normalized: TerminalActionResult = {\n ...result,\n exitCode: result.exitCode ?? result.exit_code,\n exit_code: result.exit_code ?? result.exitCode,\n sessionId: result.sessionId ?? result.session_id,\n session_id: result.session_id ?? result.sessionId,\n };\n return normalized.success\n ? this.succeedEntry(entry, normalized)\n : this.failEntry(entry, normalized);\n }\n\n private requireCoordinate(\n coordinate: [number, number] | undefined,\n action: string,\n fieldName: string = \"coordinate\",\n ): asserts coordinate is [number, number] {\n if (!coordinate || coordinate.length < 2) {\n throw new Error(`${fieldName} [x, y] is required for ${action}`);\n }\n }\n\n private requireIdentifier(\n value: string | undefined,\n message: string,\n ): string {\n if (!value) {\n throw new Error(message);\n }\n return value;\n }\n\n private requireNumber(value: number | undefined, message: string): number {\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n throw new Error(message);\n }\n return value;\n }\n\n private requireWindowTarget(params: WindowActionParams): string {\n return (\n params.windowId ??\n params.windowTitle ??\n this.requireIdentifier(undefined, \"windowId or windowTitle is required\")\n );\n }\n\n private normalizeEncoding(\n value: string | BufferEncoding | undefined,\n ): BufferEncoding {\n switch (String(value ?? \"utf8\").toLowerCase()) {\n case \"ascii\":\n return \"ascii\";\n case \"base64\":\n return \"base64\";\n case \"hex\":\n return \"hex\";\n case \"latin1\":\n case \"binary\":\n return \"latin1\";\n case \"ucs2\":\n case \"ucs-2\":\n case \"utf16le\":\n case \"utf-16le\":\n return \"utf16le\";\n default:\n return \"utf8\";\n }\n }\n\n private defaultDownloadsPath(): string {\n return path.join(os.homedir(), \"Downloads\");\n }\n\n private toParamsRecord(value: object): Record<string, unknown> {\n return Object.fromEntries(\n Object.entries(value).filter(\n ([, entryValue]) => entryValue !== undefined,\n ),\n );\n }\n\n private pushAction(entry: ActionHistoryEntry): void {\n this.recentActions.push(entry);\n if (this.recentActions.length > this.cuConfig.maxRecentActions) {\n this.recentActions.shift();\n }\n }\n\n private loadConfig(runtime: IAgentRuntime): void {\n const getSetting = (key: string): string | undefined => {\n try {\n const value = runtime.getSetting(key);\n if (\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n ) {\n return String(value);\n }\n } catch {\n // ignore runtime setting lookup failures\n }\n return process.env[key] ?? process.env[`ELIZA_${key}`];\n };\n\n const screenshotAfter = getSetting(\"COMPUTER_USE_SCREENSHOT_AFTER_ACTION\");\n if (screenshotAfter !== undefined) {\n this.cuConfig.screenshotAfterAction =\n screenshotAfter !== \"false\" && screenshotAfter !== \"0\";\n }\n\n const timeout = getSetting(\"COMPUTER_USE_ACTION_TIMEOUT_MS\");\n if (timeout) {\n const numericTimeout = Number.parseInt(timeout, 10);\n if (Number.isFinite(numericTimeout) && numericTimeout > 0) {\n this.cuConfig.actionTimeoutMs = numericTimeout;\n }\n }\n\n const approvalMode = getSetting(\"COMPUTER_USE_APPROVAL_MODE\");\n if (approvalMode && isApprovalMode(approvalMode)) {\n this.cuConfig.approvalMode = approvalMode;\n this.approvalManager.setMode(approvalMode);\n }\n\n const browserHeadless = getSetting(\"COMPUTER_USE_BROWSER_HEADLESS\");\n if (browserHeadless !== undefined) {\n this.cuConfig.browserHeadless =\n browserHeadless === \"true\" || browserHeadless === \"1\";\n }\n\n const mode =\n getSetting(\"COMPUTERUSE_MODE\") ?? getSetting(\"COMPUTER_USE_MODE\");\n this.cuConfig.mode = mode === \"sandbox\" ? \"sandbox\" : \"yolo\";\n if (this.cuConfig.mode === \"sandbox\") {\n const backend =\n getSetting(\"COMPUTERUSE_SANDBOX_BACKEND\") ??\n getSetting(\"COMPUTER_USE_SANDBOX_BACKEND\");\n const image =\n getSetting(\"COMPUTERUSE_SANDBOX_IMAGE\") ??\n getSetting(\"COMPUTER_USE_SANDBOX_IMAGE\");\n const trimmedImage = image?.trim();\n // Remote-guest RPC options for the VM providers (#9170 M13).\n const rpcUrl = (\n getSetting(\"COMPUTERUSE_SANDBOX_RPC_URL\") ??\n getSetting(\"COMPUTER_USE_SANDBOX_RPC_URL\")\n )?.trim();\n const rpcPortRaw =\n getSetting(\"COMPUTERUSE_SANDBOX_RPC_PORT\") ??\n getSetting(\"COMPUTER_USE_SANDBOX_RPC_PORT\");\n const rpcPort = rpcPortRaw ? Number(rpcPortRaw) : undefined;\n const options =\n rpcUrl || (rpcPort !== undefined && Number.isFinite(rpcPort))\n ? {\n ...(rpcUrl ? { rpcUrl } : {}),\n ...(rpcPort !== undefined && Number.isFinite(rpcPort)\n ? { rpcPort }\n : {}),\n }\n : undefined;\n // docker + qemu require an image; wsb (Windows Sandbox) is imageless.\n if (\n (backend === \"docker\" || backend === \"qemu\") &&\n trimmedImage &&\n trimmedImage.length > 0\n ) {\n this.cuConfig.sandbox = {\n backend,\n image: trimmedImage,\n ...(options ? { options } : {}),\n };\n } else if (backend === \"wsb\") {\n this.cuConfig.sandbox = {\n backend,\n image:\n trimmedImage && trimmedImage.length > 0\n ? trimmedImage\n : \"windows-sandbox\",\n ...(options ? { options } : {}),\n };\n } else {\n this.cuConfig.sandbox = undefined;\n }\n } else {\n this.cuConfig.sandbox = undefined;\n }\n\n setBrowserRuntimeOptions({\n headless: this.cuConfig.browserHeadless ?? false,\n });\n }\n\n private detectCapabilities(): PlatformCapabilities {\n return detectPlatformCapabilities({\n osName: currentPlatform(),\n commandExists,\n isBrowserAvailable,\n shell: process.env.SHELL,\n });\n }\n}\n",
|
|
38
|
+
"import fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport type {\n ApprovalMode,\n ApprovalResolution,\n ApprovalSnapshot,\n PendingApproval,\n} from \"./types.js\";\n\nconst VALID_APPROVAL_MODES: ApprovalMode[] = [\n \"full_control\",\n \"smart_approve\",\n \"approve_all\",\n \"off\",\n];\n\nconst SAFE_COMMANDS = new Set<string>([\n \"screenshot\",\n \"get_cursor_position\",\n \"ocr\",\n \"detect_elements\",\n \"browser_screenshot\",\n \"browser_state\",\n \"browser_info\",\n \"browser_get_dom\",\n \"browser_dom\",\n \"browser_get_clickables\",\n \"browser_clickables\",\n \"browser_get_context\",\n \"browser_list_tabs\",\n \"browser_wait\",\n \"file_read\",\n \"file_exists\",\n \"directory_list\",\n \"file_list_downloads\",\n \"file_download\",\n \"file_read_bytes\",\n \"file_directory_exists\",\n \"file_get_file_size\",\n \"terminal_read\",\n \"terminal_connect\",\n \"list_windows\",\n]);\n\ntype ApprovalDecision = {\n approved: boolean;\n cancelled: boolean;\n reason?: string;\n};\n\ntype PendingApprovalRecord = PendingApproval & {\n resolve: (result: ApprovalDecision) => void;\n};\n\ntype ApprovalListener = (snapshot: ApprovalSnapshot) => void;\n\nexport function isApprovalMode(value: string): value is ApprovalMode {\n return VALID_APPROVAL_MODES.includes(value as ApprovalMode);\n}\n\nexport class ComputerUseApprovalManager {\n private mode: ApprovalMode = \"smart_approve\";\n private pending = new Map<string, PendingApprovalRecord>();\n private listeners = new Set<ApprovalListener>();\n private readonly configPath = path.join(\n os.homedir(),\n \".eliza\",\n \"computer-use-approval.json\",\n );\n\n constructor() {\n this.loadConfig();\n }\n\n getMode(): ApprovalMode {\n return this.mode;\n }\n\n setMode(mode: string): ApprovalMode {\n if (isApprovalMode(mode)) {\n this.mode = mode;\n this.saveConfig();\n this.emit();\n }\n return this.mode;\n }\n\n shouldAutoApprove(command: string): boolean {\n switch (this.mode) {\n case \"full_control\":\n return true;\n case \"smart_approve\":\n return SAFE_COMMANDS.has(command);\n case \"approve_all\":\n case \"off\":\n return false;\n }\n }\n\n isDenyAll(): boolean {\n return this.mode === \"off\";\n }\n\n requestApproval(\n command: string,\n parameters: Record<string, unknown> = {},\n ): Promise<ApprovalDecision> {\n const id = `approval_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;\n const requestedAt = new Date().toISOString();\n\n return new Promise((resolve) => {\n this.pending.set(id, {\n id,\n command,\n parameters,\n requestedAt,\n resolve,\n });\n this.emit();\n });\n }\n\n getSnapshot(): ApprovalSnapshot {\n return {\n mode: this.mode,\n pendingCount: this.pending.size,\n pendingApprovals: Array.from(this.pending.values()).map(\n ({ id, command, parameters, requestedAt }) => ({\n id,\n command,\n parameters,\n requestedAt,\n }),\n ),\n };\n }\n\n resolveApproval(\n id: string,\n approved: boolean,\n reason?: string,\n ): ApprovalResolution | null {\n const pending = this.pending.get(id);\n if (!pending) {\n return null;\n }\n\n this.pending.delete(id);\n pending.resolve({ approved, cancelled: false, reason });\n this.emit();\n\n return {\n id: pending.id,\n command: pending.command,\n approved,\n cancelled: false,\n mode: this.mode,\n requestedAt: pending.requestedAt,\n resolvedAt: new Date().toISOString(),\n ...(reason ? { reason } : {}),\n };\n }\n\n cancelAll(reason?: string): void {\n for (const pending of this.pending.values()) {\n pending.resolve({ approved: false, cancelled: true, reason });\n }\n this.pending.clear();\n this.emit();\n }\n\n subscribe(listener: ApprovalListener): () => void {\n this.listeners.add(listener);\n listener(this.getSnapshot());\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n private loadConfig(): void {\n try {\n const raw = fs.readFileSync(this.configPath, \"utf8\");\n const parsed = JSON.parse(raw) as { mode?: unknown };\n if (typeof parsed.mode === \"string\" && isApprovalMode(parsed.mode)) {\n this.mode = parsed.mode;\n }\n } catch {\n // Keep the default mode when the config file is missing or invalid.\n }\n }\n\n private saveConfig(): void {\n try {\n fs.mkdirSync(path.dirname(this.configPath), { recursive: true });\n fs.writeFileSync(\n this.configPath,\n JSON.stringify({ mode: this.mode }, null, 2),\n \"utf8\",\n );\n } catch {\n // Ignore persistence failures; approval mode still applies in-memory.\n }\n }\n\n private emit(): void {\n const snapshot = this.getSnapshot();\n for (const listener of this.listeners) {\n listener(snapshot);\n }\n }\n}\n",
|
|
39
|
+
"/**\n * OCR provider chain — used by WS6 (scene-builder) and any other consumer\n * that needs text-from-image extraction.\n *\n * Defined here in plugin-computeruse so the mobile bridge can publish the\n * iOS Apple Vision implementation alongside the rest of the iOS surface.\n * WS6 will register additional providers (cloud, Tesseract fallback) and\n * pick a provider per-call via `selectOcrProvider`.\n *\n * Contract:\n * - `name` : stable string id for routing/telemetry.\n * - `priority` : higher wins when multiple providers report `available`.\n * - `available()` : cheap synchronous availability probe; the registry\n * caches the result for the process lifetime.\n * - `recognize()` : async OCR call. Throws on hard failures so callers can\n * fall back to the next provider; never returns empty\n * lines silently.\n */\n\nimport type {\n IosComputerUseBridge,\n VisionOcrLine,\n VisionOcrOptions,\n VisionOcrResult,\n} from \"./ios-bridge.js\";\n\nexport interface OcrLine {\n readonly text: string;\n readonly confidence: number;\n readonly boundingBox: {\n readonly x: number;\n readonly y: number;\n readonly width: number;\n readonly height: number;\n };\n}\n\nexport interface OcrResult {\n readonly lines: readonly OcrLine[];\n readonly fullText: string;\n readonly elapsedMs: number;\n readonly providerName: string;\n readonly languagesUsed: readonly string[];\n}\n\nexport interface OcrRecognizeOptions {\n readonly languages?: readonly string[];\n readonly recognitionLevel?: \"fast\" | \"accurate\";\n readonly minimumTextHeight?: number;\n}\n\nexport interface OcrProvider {\n readonly name: string;\n readonly priority: number;\n available(): boolean;\n recognize(input: OcrInput, options?: OcrRecognizeOptions): Promise<OcrResult>;\n}\n\n/**\n * Image input. Either a base64-encoded PNG/JPEG or raw bytes. The provider\n * is responsible for normalizing into whatever its native side expects.\n */\nexport type OcrInput =\n | { readonly kind: \"base64\"; readonly data: string }\n | { readonly kind: \"bytes\"; readonly data: Uint8Array };\n\n// ── Registry ─────────────────────────────────────────────────────────────────\n\nconst REGISTRY = new Map<string, OcrProvider>();\n\nexport function registerOcrProvider(provider: OcrProvider): void {\n REGISTRY.set(provider.name, provider);\n}\n\nexport function unregisterOcrProvider(name: string): void {\n REGISTRY.delete(name);\n}\n\nexport function listOcrProviders(): readonly OcrProvider[] {\n return [...REGISTRY.values()].sort((a, b) => b.priority - a.priority);\n}\n\n/**\n * Returns the highest-priority provider that reports `available()`. Throws if\n * none are available — callers must handle that explicitly rather than\n * silently degrading. WS6's scene-builder catches and reports.\n */\nexport function selectOcrProvider(): OcrProvider {\n for (const provider of listOcrProviders()) {\n if (provider.available()) return provider;\n }\n throw new Error(\n \"No OCR provider available. Register at least one provider before calling selectOcrProvider().\",\n );\n}\n\n// ── iOS Apple Vision provider ────────────────────────────────────────────────\n\n/**\n * Builds an OcrProvider that delegates to the Capacitor `ComputerUse` plugin's\n * `visionOcr` method. Pass in a getter that lazily resolves the bridge so this\n * module stays free of Capacitor imports (which would break Node test runs).\n */\nexport function createIosVisionOcrProvider(\n getBridge: () => IosComputerUseBridge | null,\n options: { readonly priority?: number } = {},\n): OcrProvider {\n return {\n name: \"ios-apple-vision\",\n priority: options.priority ?? 100,\n available(): boolean {\n return getBridge() !== null;\n },\n async recognize(input, recognizeOptions): Promise<OcrResult> {\n const bridge = getBridge();\n if (!bridge) {\n throw new Error(\n \"ios-apple-vision provider invoked but Capacitor ComputerUse plugin is not registered.\",\n );\n }\n const imageBase64 = toBase64(input);\n const visionOptions: VisionOcrOptions = {\n ...(recognizeOptions?.languages\n ? { languages: recognizeOptions.languages }\n : {}),\n ...(recognizeOptions?.recognitionLevel\n ? { recognitionLevel: recognizeOptions.recognitionLevel }\n : {}),\n ...(recognizeOptions?.minimumTextHeight !== undefined\n ? { minimumTextHeight: recognizeOptions.minimumTextHeight }\n : {}),\n };\n const result = await bridge.visionOcr({\n imageBase64,\n options: visionOptions,\n });\n if (!result.ok) {\n // Narrow to the failure arm explicitly — some consumer tsconfigs\n // run with `strict: false`, which disables discriminated-union\n // narrowing on `!result.ok` and surfaces TS2339 on `result.code`\n // / `result.message`. The runtime invariant is unchanged.\n const failure = result as Extract<typeof result, { ok: false }>;\n throw new Error(\n `ios-apple-vision OCR failed: ${failure.code} — ${failure.message}`,\n );\n }\n return mapVisionResult(result.data);\n },\n };\n}\n\nfunction toBase64(input: OcrInput): string {\n if (input.kind === \"base64\") return input.data;\n return uint8ArrayToBase64(input.data);\n}\n\nfunction uint8ArrayToBase64(bytes: Uint8Array): string {\n if (typeof Buffer !== \"undefined\") {\n return Buffer.from(bytes).toString(\"base64\");\n }\n let binary = \"\";\n for (let i = 0; i < bytes.length; i += 1) {\n binary += String.fromCharCode(bytes[i]);\n }\n // btoa is the only universal browser/Capacitor path.\n // eslint-disable-next-line no-undef\n return btoa(binary);\n}\n\nfunction mapVisionResult(result: VisionOcrResult): OcrResult {\n return {\n lines: result.lines.map(mapLine),\n fullText: result.fullText,\n elapsedMs: result.elapsedMs,\n providerName: \"ios-apple-vision\",\n languagesUsed: result.languagesUsed,\n };\n}\n\nfunction mapLine(line: VisionOcrLine): OcrLine {\n return {\n text: line.text,\n confidence: line.confidence,\n boundingBox: line.boundingBox,\n };\n}\n\n/**\n * Test helper. Drops every provider from the registry; callers re-register\n * in `beforeEach`.\n */\nexport function _resetOcrProvidersForTests(): void {\n REGISTRY.clear();\n}\n\n// ── Coord-aware OCR provider slot ────────────────────────────────────────────\n\n/**\n * Hierarchical (block / line / word) OCR with absolute source-display\n * coordinates and a coarse 3x3 semantic position label per element. This is\n * a *separate* slot from `OcrProvider` above — that one is line-only and\n * shaped around Apple Vision's API, while this one carries the structure\n * that plugin-computeruse needs to compute action targets without re-running\n * detection.\n *\n * The provider implementation lives in `@elizaos/plugin-vision`'s\n * `ocr-with-coords.ts`. plugin-computeruse intentionally does not take a\n * runtime dep on plugin-vision (computeruse is the higher-level seam), so\n * the runtime registers a provider here at boot.\n *\n * The current in-tree provider is the RapidOCR-backed adapter registered by\n * `@elizaos/plugin-vision`; native providers can register the same interface\n * when they are available.\n */\nexport interface CoordOcrSemantic {\n readonly position:\n | \"upper-left\"\n | \"upper-center\"\n | \"upper-right\"\n | \"middle-left\"\n | \"center\"\n | \"middle-right\"\n | \"lower-left\"\n | \"lower-center\"\n | \"lower-right\";\n}\n\nexport interface CoordOcrWord {\n readonly text: string;\n readonly bbox: {\n readonly x: number;\n readonly y: number;\n readonly width: number;\n readonly height: number;\n };\n readonly semantic_position: CoordOcrSemantic[\"position\"];\n}\n\nexport interface CoordOcrBlock {\n readonly text: string;\n readonly bbox: {\n readonly x: number;\n readonly y: number;\n readonly width: number;\n readonly height: number;\n };\n readonly words: ReadonlyArray<CoordOcrWord>;\n readonly semantic_position: CoordOcrSemantic[\"position\"];\n}\n\nexport interface CoordOcrResult {\n readonly blocks: ReadonlyArray<CoordOcrBlock>;\n}\n\nexport interface CoordOcrInput {\n readonly displayId: string;\n readonly sourceX: number;\n readonly sourceY: number;\n readonly pngBytes: Uint8Array;\n}\n\nexport interface CoordOcrProvider {\n readonly name: string;\n describe(input: CoordOcrInput): Promise<CoordOcrResult>;\n}\n\nlet registeredCoordOcrProvider: CoordOcrProvider | null = null;\n\n/**\n * Register the hierarchical / coord-aware OCR provider. Idempotent — last\n * call wins so a hot-reload of the bridge swaps cleanly. Pass `null` to\n * unregister.\n */\nexport function registerCoordOcrProvider(\n provider: CoordOcrProvider | null,\n): void {\n registeredCoordOcrProvider = provider;\n}\n\nexport function getCoordOcrProvider(): CoordOcrProvider | null {\n return registeredCoordOcrProvider;\n}\n\n// ── Set-of-Marks provider slot (#9170 M9) ────────────────────────────────────\n\n/**\n * Set-of-Marks grounding (trycua/cua's OmniParser technique): fuse GGUF YOLO\n * icon detections + OCR text boxes into ONE deduplicated, 1-indexed set of\n * numbered targets, optionally with a numbered-overlay PNG. The VLM picks a\n * *number* instead of regressing raw pixels.\n *\n * The fusion + overlay implementation lives in `@elizaos/plugin-vision`\n * (`som.ts`) because that package owns the YOLO detector and OCR engines.\n * computeruse exposes this registration slot (same no-hard-dep pattern as the\n * CoordOcrProvider above); `detect_elements` consumes whatever is registered.\n */\nexport interface SetOfMarksMark {\n /** 1-indexed mark number shown in the overlay. */\n readonly index: number;\n /** Display-local box `[x, y, w, h]`. */\n readonly bbox: readonly [number, number, number, number];\n /** Box center `[x, y]` — the click target the number resolves to. */\n readonly center: readonly [number, number];\n readonly source: \"icon\" | \"text\";\n readonly label?: string;\n readonly score: number;\n}\n\nexport interface SetOfMarksResult {\n readonly marks: ReadonlyArray<SetOfMarksMark>;\n /** Base64 PNG of the numbered overlay (present only when requested). */\n readonly overlayPngBase64?: string;\n}\n\nexport interface SetOfMarksInput {\n readonly displayId: string;\n readonly sourceX: number;\n readonly sourceY: number;\n readonly pngBytes: Uint8Array;\n /** Render and return the numbered-overlay PNG. Default false (marks only). */\n readonly renderOverlay?: boolean;\n}\n\nexport interface SetOfMarksProvider {\n readonly name: string;\n describe(input: SetOfMarksInput): Promise<SetOfMarksResult>;\n}\n\nlet registeredSetOfMarksProvider: SetOfMarksProvider | null = null;\n\n/**\n * Register the Set-of-Marks provider. Idempotent — last call wins. Pass `null`\n * to unregister.\n */\nexport function registerSetOfMarksProvider(\n provider: SetOfMarksProvider | null,\n): void {\n registeredSetOfMarksProvider = provider;\n}\n\nexport function getSetOfMarksProvider(): SetOfMarksProvider | null {\n return registeredSetOfMarksProvider;\n}\n",
|
|
40
|
+
"/**\n * Browser automation via Puppeteer Core + Chrome DevTools Protocol.\n *\n * Ported from coasty-ai/open-computer-use browser-automation.ts (Apache 2.0).\n *\n * Uses puppeteer-core (not full puppeteer) to avoid bundling Chromium.\n * Auto-detects installed Chrome, Edge, or Brave at launch.\n * Each session uses a temp user data directory to prevent conflicts.\n */\n\nimport { execFileSync } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { mkdtemp, rm } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type {\n BrowserInfo,\n BrowserState,\n BrowserTab,\n ClickableElement,\n} from \"../types.js\";\nimport { assertBrowserExecuteAllowed } from \"../security/browser-script-policy.js\";\nimport { currentPlatform } from \"./helpers.js\";\nimport { assertScreenshotBase64NotBlank } from \"./screenshot-quality.js\";\n\n// Lazy-load puppeteer-core so the plugin still loads if it's not installed\nlet puppeteer: typeof import(\"puppeteer-core\") | null = null;\ntype Browser = import(\"puppeteer-core\").Browser;\ntype Page = import(\"puppeteer-core\").Page;\n\nasync function getPuppeteer() {\n if (!puppeteer) {\n try {\n puppeteer = await import(\"puppeteer-core\");\n } catch {\n throw new Error(\n \"puppeteer-core is required for browser automation. Install via: bun add puppeteer-core\",\n );\n }\n }\n return puppeteer;\n}\n\n// ── State ───────────────────────────────────────────────────────────────────\n\nlet browser: Browser | null = null;\nlet activePage: Page | null = null;\nlet tempUserDataDir: string | null = null;\nlet browserHeadless = false;\nconst BROWSER_LAUNCH_ATTEMPTS = 3;\n\nexport function setBrowserRuntimeOptions(options: {\n headless?: boolean;\n}): void {\n if (typeof options.headless === \"boolean\") {\n browserHeadless = options.headless;\n }\n}\n\nfunction _envFlagEnabled(value: string | undefined): boolean {\n if (!value) return false;\n const normalized = value.trim().toLowerCase();\n return normalized === \"1\" || normalized === \"true\" || normalized === \"yes\";\n}\n\n// ── Browser Detection ───────────────────────────────────────────────────────\n\nfunction detectBrowserPath(): string | null {\n const os = currentPlatform();\n const candidates: string[] = [];\n\n if (os === \"darwin\") {\n candidates.push(\n \"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome\",\n \"/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge\",\n \"/Applications/Brave Browser.app/Contents/MacOS/Brave Browser\",\n \"/Applications/Chromium.app/Contents/MacOS/Chromium\",\n );\n } else if (os === \"linux\") {\n candidates.push(\n \"/usr/bin/google-chrome\",\n \"/usr/bin/google-chrome-stable\",\n \"/usr/bin/chromium-browser\",\n \"/usr/bin/chromium\",\n \"/usr/bin/microsoft-edge\",\n \"/usr/bin/brave-browser\",\n \"/snap/bin/chromium\",\n );\n } else if (os === \"win32\") {\n const programFiles = process.env.PROGRAMFILES || \"C:\\\\Program Files\";\n const programFilesX86 =\n process.env[\"PROGRAMFILES(X86)\"] || \"C:\\\\Program Files (x86)\";\n const localAppData = process.env.LOCALAPPDATA || \"\";\n candidates.push(\n join(programFiles, \"Google\\\\Chrome\\\\Application\\\\chrome.exe\"),\n join(programFilesX86, \"Google\\\\Chrome\\\\Application\\\\chrome.exe\"),\n join(localAppData, \"Google\\\\Chrome\\\\Application\\\\chrome.exe\"),\n join(programFiles, \"Microsoft\\\\Edge\\\\Application\\\\msedge.exe\"),\n join(programFilesX86, \"Microsoft\\\\Edge\\\\Application\\\\msedge.exe\"),\n join(\n programFiles,\n \"BraveSoftware\\\\Brave-Browser\\\\Application\\\\brave.exe\",\n ),\n );\n }\n\n for (const path of candidates) {\n if (existsSync(path)) {\n return path;\n }\n }\n\n const lookup = os === \"win32\" ? \"where\" : \"which\";\n for (const candidate of [\n \"google-chrome\",\n \"google-chrome-stable\",\n \"chromium-browser\",\n \"chromium\",\n \"microsoft-edge\",\n \"brave-browser\",\n \"chrome.exe\",\n \"msedge.exe\",\n ]) {\n try {\n const output = execFileSync(lookup, [candidate], {\n encoding: \"utf8\",\n timeout: 3000,\n });\n const match = output\n .split(/\\r?\\n/)\n .map((value) => value.trim())\n .find((value) => value && existsSync(value));\n if (match) {\n return match;\n }\n } catch {\n // Ignore PATH misses.\n }\n }\n\n return null;\n}\n\n/**\n * Check if a Chromium-based browser is available.\n */\nexport function isBrowserAvailable(): boolean {\n return detectBrowserPath() !== null;\n}\n\n// ── Lifecycle ───────────────────────────────────────────────────────────────\n\nasync function ensureBrowser(): Promise<Page> {\n if (browser && activePage) {\n try {\n await activePage.evaluate(\"1\");\n return activePage;\n } catch {\n // Page disconnected, reset\n browser = null;\n activePage = null;\n }\n }\n throw new Error(\"Browser not open. Use the open action first.\");\n}\n\nexport async function openBrowser(url?: string): Promise<BrowserState> {\n const pup = await getPuppeteer();\n const executablePath = detectBrowserPath();\n if (!executablePath) {\n throw new Error(\n \"No Chromium-based browser found. Install Chrome, Edge, or Brave.\",\n );\n }\n\n // Close existing browser if any\n if (browser) {\n await closeBrowser();\n }\n\n const isCi =\n process.env.CI === \"true\" || process.env.GITHUB_ACTIONS === \"true\";\n const launchArgs = [\n \"--no-first-run\",\n \"--no-default-browser-check\",\n \"--disable-infobars\",\n `--window-size=1280,900`,\n ];\n if (isCi) {\n launchArgs.push(\n \"--no-sandbox\",\n \"--disable-setuid-sandbox\",\n \"--disable-dev-shm-usage\",\n \"--disable-gpu\",\n );\n }\n let lastError: unknown = null;\n\n for (let attempt = 1; attempt <= BROWSER_LAUNCH_ATTEMPTS; attempt += 1) {\n tempUserDataDir = await mkdtemp(join(tmpdir(), \"computeruse-browser-\"));\n\n try {\n browser = await pup.default.launch({\n executablePath,\n headless: browserHeadless,\n userDataDir: tempUserDataDir,\n args: launchArgs,\n defaultViewport: { width: 1280, height: 900 },\n });\n\n const pages = await browser.pages();\n activePage = pages[0] ?? (await browser.newPage());\n\n if (url) {\n await activePage.goto(url, {\n waitUntil: \"domcontentloaded\",\n timeout: 30000,\n });\n }\n\n return {\n url: activePage.url(),\n title: await activePage.title(),\n isOpen: true,\n is_open: true,\n };\n } catch (error) {\n lastError = error;\n await closeBrowser();\n if (attempt < BROWSER_LAUNCH_ATTEMPTS) {\n await new Promise((resolve) => setTimeout(resolve, attempt * 500));\n }\n }\n }\n\n const message =\n lastError instanceof Error ? lastError.message : String(lastError);\n throw new Error(`Failed to launch browser after retries: ${message}`);\n}\n\nexport async function closeBrowser(): Promise<void> {\n if (browser) {\n try {\n await browser.close();\n } catch {\n /* ignore */\n }\n browser = null;\n activePage = null;\n }\n\n if (tempUserDataDir) {\n try {\n await rm(tempUserDataDir, { recursive: true, force: true });\n } catch {\n /* ignore */\n }\n tempUserDataDir = null;\n }\n}\n\n// ── Navigation ──────────────────────────────────────────────────────────────\n\nexport async function navigateBrowser(url: string): Promise<BrowserState> {\n const page = await ensureBrowser();\n await page.goto(url, { waitUntil: \"domcontentloaded\", timeout: 30000 });\n return {\n url: page.url(),\n title: await page.title(),\n isOpen: true,\n is_open: true,\n };\n}\n\n// ── Click ───────────────────────────────────────────────────────────────────\n\nexport async function clickBrowser(\n selector?: string,\n coordinate?: [number, number],\n text?: string,\n): Promise<void> {\n const page = await ensureBrowser();\n\n if (selector) {\n await page.click(selector);\n } else if (coordinate) {\n await page.mouse.click(coordinate[0], coordinate[1]);\n } else if (text) {\n const el = await page.evaluateHandle((t) => {\n const walker = document.createTreeWalker(\n document.body,\n NodeFilter.SHOW_TEXT,\n );\n while (walker.nextNode()) {\n const node = walker.currentNode;\n if (node.textContent?.includes(t)) {\n return node.parentElement;\n }\n }\n return null;\n }, text);\n const element = el.asElement() as\n | import(\"puppeteer-core\").ElementHandle<Element>\n | null;\n if (!element) {\n await el.dispose();\n throw new Error(`Element with text \"${text}\" not found`);\n }\n await element.click();\n await el.dispose();\n } else {\n throw new Error(\n \"selector, coordinate, or text is required for browser click\",\n );\n }\n}\n\n// ── Type ────────────────────────────────────────────────────────────────────\n\nexport async function typeBrowser(\n text: string,\n selector?: string,\n): Promise<void> {\n const page = await ensureBrowser();\n\n if (selector) {\n await page.click(selector);\n await page.type(selector, text);\n } else {\n await page.keyboard.type(text);\n }\n}\n\n// ── Scroll ──────────────────────────────────────────────────────────────────\n\nexport async function scrollBrowser(\n direction: \"up\" | \"down\",\n amount = 300,\n): Promise<void> {\n const page = await ensureBrowser();\n const delta = direction === \"up\" ? -amount : amount;\n await page.evaluate((d) => window.scrollBy(0, d), delta);\n}\n\n// ── State ───────────────────────────────────────────────────────────────────\n\nexport async function getBrowserState(): Promise<BrowserState> {\n const page = await ensureBrowser();\n return {\n url: page.url(),\n title: await page.title(),\n isOpen: true,\n is_open: true,\n };\n}\n\nexport async function getBrowserContext(): Promise<BrowserState> {\n return getBrowserState();\n}\n\nexport async function getBrowserInfo(): Promise<BrowserInfo> {\n try {\n const state = await getBrowserState();\n return {\n success: true,\n isOpen: true,\n is_open: true,\n ...state,\n };\n } catch (error) {\n return {\n success: false,\n isOpen: false,\n is_open: false,\n url: \"\",\n title: \"\",\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\n// ── DOM ─────────────────────────────────────────────────────────────────────\n\nexport async function getBrowserDom(): Promise<string> {\n const page = await ensureBrowser();\n const html = await page.content();\n // Limit to first 5000 chars to prevent context overflow\n return html.slice(0, 5000);\n}\n\n// ── Clickable Elements ──────────────────────────────────────────────────────\n\nexport async function getBrowserClickables(): Promise<ClickableElement[]> {\n const page = await ensureBrowser();\n return page.evaluate(() => {\n const selectors =\n \"a, button, input, select, textarea, [role='button'], [role='link'], [onclick]\";\n const elements = document.querySelectorAll(selectors);\n const result: Array<{\n tag: string;\n text: string;\n selector: string;\n type?: string;\n href?: string;\n ariaLabel?: string;\n }> = [];\n\n for (const el of elements) {\n if (result.length >= 50) break;\n const tag = el.tagName.toLowerCase();\n const text = el.textContent.trim().slice(0, 100);\n const id = el.id ? `#${el.id}` : \"\";\n const cls =\n el.className && typeof el.className === \"string\"\n ? `.${el.className.split(\" \").filter(Boolean).join(\".\")}`\n : \"\";\n result.push({\n tag,\n text,\n selector: id || `${tag}${cls}`,\n type: (el as HTMLInputElement).type || undefined,\n href: (el as HTMLAnchorElement).href || undefined,\n ariaLabel: el.getAttribute(\"aria-label\") || undefined,\n });\n }\n return result;\n });\n}\n\n// ── Screenshot ──────────────────────────────────────────────────────────────\n\nexport async function screenshotBrowser(): Promise<string> {\n const page = await ensureBrowser();\n const buffer = await page.screenshot({ encoding: \"base64\", type: \"png\" });\n assertScreenshotBase64NotBlank(buffer as string, \"browser screenshot\");\n return buffer as string;\n}\n\n// ── Execute JavaScript (disabled — GHSA-rcvr-766c-4phv) ─────────────────────\n\nexport async function executeBrowser(_code: string): Promise<string> {\n assertBrowserExecuteAllowed();\n}\n\nfunction renderPlainData(value: unknown, indent = 0): string {\n const prefix = \" \".repeat(indent);\n if (value === null || value === undefined) {\n return \"none\";\n }\n if (Array.isArray(value)) {\n if (value.length === 0) {\n return \"items[0]:\";\n }\n return [\n `items[${value.length}]:`,\n ...value.map((item) => `${prefix}- ${renderPlainData(item, indent + 1)}`),\n ].join(\"\\n\");\n }\n if (typeof value === \"object\") {\n return Object.entries(value as Record<string, unknown>)\n .map(([key, nestedValue]) => {\n if (nestedValue && typeof nestedValue === \"object\") {\n return `${key}:\\n${renderPlainData(nestedValue, indent + 1)}`;\n }\n return `${key}: ${renderPlainData(nestedValue, indent + 1)}`;\n })\n .join(\"\\n\");\n }\n return String(value);\n}\n\n// ── Wait ────────────────────────────────────────────────────────────────────\n\nexport async function waitBrowser(\n selector?: string,\n text?: string,\n timeout = 5000,\n): Promise<void> {\n const page = await ensureBrowser();\n if (selector) {\n await page.waitForSelector(selector, { timeout });\n } else if (text) {\n await page.waitForFunction(\n (t) => document.body.textContent.includes(t),\n { timeout },\n text,\n );\n } else {\n await new Promise((resolve) =>\n setTimeout(resolve, Math.min(timeout, 5000)),\n );\n }\n}\n\nexport async function browserWait(\n selector?: string,\n text?: string,\n timeout = 5000,\n): Promise<{ success: boolean; message?: string; error?: string }> {\n try {\n await waitBrowser(selector, text, timeout);\n if (selector) {\n return { success: true, message: `Element \"${selector}\" found` };\n }\n if (text) {\n return { success: true, message: `Text \"${text}\" found on page` };\n }\n return { success: true, message: `Waited ${Math.min(timeout, 5000)}ms` };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\n// ── Tab Management ──────────────────────────────────────────────────────────\n\nexport async function listBrowserTabs(): Promise<BrowserTab[]> {\n if (!browser) throw new Error(\"Browser not open.\");\n const pages = await browser.pages();\n const tabs: BrowserTab[] = [];\n for (const [i, page] of pages.entries()) {\n tabs.push({\n id: String(i),\n url: page.url(),\n title: await page.title(),\n active: page === activePage,\n });\n }\n return tabs;\n}\n\nexport async function openBrowserTab(url?: string): Promise<BrowserTab> {\n if (!browser) throw new Error(\"Browser not open.\");\n const page = await browser.newPage();\n activePage = page;\n if (url) {\n await page.goto(url, { waitUntil: \"domcontentloaded\", timeout: 30000 });\n }\n const pages = await browser.pages();\n return {\n id: String(pages.indexOf(page)),\n url: page.url(),\n title: await page.title(),\n active: true,\n };\n}\n\nexport async function closeBrowserTab(tabId: string): Promise<void> {\n if (!browser) throw new Error(\"Browser not open.\");\n const pages = await browser.pages();\n const idx = Number.parseInt(tabId, 10);\n const page = pages[idx];\n if (!page) throw new Error(`Tab ${tabId} not found.`);\n if (page === activePage) {\n // Switch to another tab before closing\n activePage = pages.find((p) => p !== page) ?? null;\n }\n await page.close();\n}\n\nexport async function switchBrowserTab(tabId: string): Promise<BrowserState> {\n if (!browser) throw new Error(\"Browser not open.\");\n const pages = await browser.pages();\n const idx = Number.parseInt(tabId, 10);\n const page = pages[idx];\n if (!page) throw new Error(`Tab ${tabId} not found.`);\n activePage = page;\n await page.bringToFront();\n return {\n url: page.url(),\n title: await page.title(),\n isOpen: true,\n is_open: true,\n };\n}\n\nexport const browser_open = openBrowser;\nexport const browser_connect = openBrowser;\nexport const browser_navigate = navigateBrowser;\nexport const browser_click = clickBrowser;\nexport const browser_type = typeBrowser;\nexport const browser_scroll = scrollBrowser;\nexport const browser_close = closeBrowser;\nexport const browser_execute = executeBrowser;\nexport const browser_screenshot = screenshotBrowser;\nexport const browser_dom = getBrowserDom;\nexport const browser_get_dom = getBrowserDom;\nexport const browser_get_clickables = getBrowserClickables;\nexport const browser_state = getBrowserState;\nexport const browser_get_context = getBrowserContext;\nexport const browser_info = getBrowserInfo;\nexport const browser_wait = browserWait;\nexport const browser_list_tabs = listBrowserTabs;\nexport const browser_open_tab = openBrowserTab;\nexport const browser_close_tab = closeBrowserTab;\nexport const browser_switch_tab = switchBrowserTab;\n",
|
|
41
|
+
"/** GHSA-rcvr-766c-4phv: arbitrary page.evaluate + AsyncFunction must not run agent-supplied code. */\n\nexport const BROWSER_EXECUTE_DISABLED_MESSAGE =\n \"Arbitrary browser JavaScript execution is disabled for security (GHSA-rcvr-766c-4phv). \" +\n \"Use browser DOM, clickables, click, type, navigate, screenshot, and wait actions instead.\";\n\nexport class BrowserExecuteDisabledError extends Error {\n readonly code = \"browser_execute_disabled\" as const;\n\n constructor(message = BROWSER_EXECUTE_DISABLED_MESSAGE) {\n super(message);\n this.name = \"BrowserExecuteDisabledError\";\n }\n}\n\nexport function assertBrowserExecuteAllowed(): never {\n throw new BrowserExecuteDisabledError();\n}\n\nexport function isBrowserExecuteAllowed(): boolean {\n return false;\n}\n",
|
|
42
|
+
"import { inflateSync } from \"node:zlib\";\n\ntype PngColorType = 0 | 2 | 6;\n\nexport interface ScreenshotQuality {\n width: number;\n height: number;\n sampledPixels: number;\n colorBuckets: number;\n dominantRatio: number;\n}\n\nconst PNG_SIGNATURE = Buffer.from([\n 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a,\n]);\n\nfunction bytesPerPixel(colorType: PngColorType): number {\n if (colorType === 0) return 1;\n if (colorType === 2) return 3;\n return 4;\n}\n\nfunction paeth(left: number, up: number, upLeft: number): number {\n const estimate = left + up - upLeft;\n const leftDistance = Math.abs(estimate - left);\n const upDistance = Math.abs(estimate - up);\n const upLeftDistance = Math.abs(estimate - upLeft);\n if (leftDistance <= upDistance && leftDistance <= upLeftDistance) {\n return left;\n }\n return upDistance <= upLeftDistance ? up : upLeft;\n}\n\nfunction unfilterScanline(\n filter: number,\n current: Buffer,\n previous: Buffer,\n bpp: number,\n): Buffer<ArrayBufferLike> {\n const output = Buffer.alloc(current.length);\n for (let index = 0; index < current.length; index += 1) {\n const left = index >= bpp ? output[index - bpp] : 0;\n const up = previous[index] ?? 0;\n const upLeft = index >= bpp ? previous[index - bpp] : 0;\n const raw = current[index];\n if (filter === 0) {\n output[index] = raw;\n } else if (filter === 1) {\n output[index] = (raw + left) & 0xff;\n } else if (filter === 2) {\n output[index] = (raw + up) & 0xff;\n } else if (filter === 3) {\n output[index] = (raw + Math.floor((left + up) / 2)) & 0xff;\n } else if (filter === 4) {\n output[index] = (raw + paeth(left, up, upLeft)) & 0xff;\n } else {\n throw new Error(`unsupported PNG filter ${filter}`);\n }\n }\n return output;\n}\n\nexport function analyzePngScreenshot(buffer: Buffer): ScreenshotQuality {\n if (!buffer.subarray(0, PNG_SIGNATURE.length).equals(PNG_SIGNATURE)) {\n throw new Error(\"screenshot is not a PNG\");\n }\n\n let offset = PNG_SIGNATURE.length;\n let width = 0;\n let height = 0;\n let bitDepth = 0;\n let colorType: PngColorType | null = null;\n const idatChunks: Buffer[] = [];\n\n while (offset + 12 <= buffer.length) {\n const length = buffer.readUInt32BE(offset);\n const type = buffer.subarray(offset + 4, offset + 8).toString(\"ascii\");\n const data = buffer.subarray(offset + 8, offset + 8 + length);\n offset += 12 + length;\n\n if (type === \"IHDR\") {\n width = data.readUInt32BE(0);\n height = data.readUInt32BE(4);\n bitDepth = data[8];\n const rawColorType = data[9];\n if (rawColorType === 0 || rawColorType === 2 || rawColorType === 6) {\n colorType = rawColorType;\n }\n } else if (type === \"IDAT\") {\n idatChunks.push(data);\n } else if (type === \"IEND\") {\n break;\n }\n }\n\n if (!width || !height || colorType === null || bitDepth !== 8) {\n throw new Error(\n `unsupported PNG format: width=${width}, height=${height}, bitDepth=${bitDepth}, colorType=${colorType}`,\n );\n }\n\n const bpp = bytesPerPixel(colorType);\n const stride = width * bpp;\n const inflated = inflateSync(Buffer.concat(idatChunks));\n const buckets = new Map<string, number>();\n let previous: Buffer<ArrayBufferLike> = Buffer.alloc(stride);\n let cursor = 0;\n\n for (let row = 0; row < height; row += 1) {\n const filter = inflated[cursor];\n const scanline = inflated.subarray(cursor + 1, cursor + 1 + stride);\n const unfiltered = unfilterScanline(filter, scanline, previous, bpp);\n cursor += stride + 1;\n previous = unfiltered;\n\n for (let column = 0; column < width; column += 1) {\n const pixel = column * bpp;\n const r = unfiltered[pixel];\n const g = colorType === 0 ? r : unfiltered[pixel + 1];\n const b = colorType === 0 ? r : unfiltered[pixel + 2];\n const a = colorType === 6 ? unfiltered[pixel + 3] : 255;\n const key = [\n Math.round(r / 16),\n Math.round(g / 16),\n Math.round(b / 16),\n Math.round(a / 16),\n ].join(\",\");\n buckets.set(key, (buckets.get(key) ?? 0) + 1);\n }\n }\n\n const sampledPixels = width * height;\n const dominantCount = Math.max(0, ...buckets.values());\n return {\n width,\n height,\n sampledPixels,\n colorBuckets: buckets.size,\n dominantRatio: sampledPixels === 0 ? 1 : dominantCount / sampledPixels,\n };\n}\n\nexport function screenshotQualityIssues(\n label: string,\n quality: ScreenshotQuality,\n): string[] {\n const issues: string[] = [];\n if (quality.sampledPixels === 0) {\n issues.push(`${label}: screenshot is empty`);\n }\n if (quality.colorBuckets <= 1) {\n issues.push(`${label}: screenshot is one color`);\n } else if (quality.colorBuckets <= 2 && quality.dominantRatio > 0.995) {\n issues.push(\n `${label}: screenshot is effectively one color (${quality.colorBuckets} color buckets, ${\n Math.round(quality.dominantRatio * 1000) / 10\n }% dominant)`,\n );\n }\n return issues;\n}\n\nexport function assertScreenshotBase64NotBlank(\n screenshot: string | undefined,\n label: string,\n minBytes = 100,\n): void {\n if (!screenshot) {\n throw new Error(`${label}: screenshot base64 should exist`);\n }\n const buffer = Buffer.from(screenshot, \"base64\");\n const quality = analyzePngScreenshot(buffer);\n const issues = screenshotQualityIssues(label, quality);\n if (buffer.length <= minBytes) {\n issues.unshift(\n `${label}: decoded PNG byte length ${buffer.length} <= ${minBytes}`,\n );\n }\n if (issues.length > 0) {\n throw new Error(\n `${label}: screenshot quality failed: ${issues.join(\"; \")}; metrics=${JSON.stringify({\n byteLength: buffer.length,\n ...quality,\n })}`,\n );\n }\n}\n",
|
|
43
|
+
"import type { PlatformCapabilities } from \"../types.js\";\nimport type { PlatformOS } from \"./helpers.js\";\n\nexport interface CapabilityDetectionOptions {\n osName: PlatformOS;\n commandExists: (command: string) => boolean;\n isBrowserAvailable: () => boolean;\n shell?: string;\n}\n\n/**\n * Per-capability parity classification, kept in lock-step with\n * `plugins/plugin-computeruse/src/mobile/parity-status.md`.\n *\n * verified — exercised on real hardware (Linux/macOS in CI today)\n * code-parity — feature-equivalent code path exists, runtime untested\n * unavailable — surface present but not available in this delivery model\n * blocked — OS does not allow the operation in our delivery model\n *\n * iOS / Android live in `mobile/parity-status.md`; they are not desktop OSes\n * and don't pass through `detectPlatformCapabilities`.\n */\nexport type ParityStatus =\n | \"verified\"\n | \"code-parity\"\n | \"unavailable\"\n | \"blocked\";\n\nexport interface ParityNote {\n readonly status: ParityStatus;\n readonly note?: string;\n}\n\n/**\n * Static parity table for desktop targets, derived from the per-file audit.\n * Linux is the reference implementation.\n */\nexport const DESKTOP_PARITY: Readonly<\n Record<PlatformOS, Readonly<Record<keyof PlatformCapabilities, ParityNote>>>\n> = {\n linux: {\n screenshot: { status: \"verified\" },\n computerUse: { status: \"verified\" },\n windowList: { status: \"verified\" },\n browser: { status: \"verified\" },\n terminal: { status: \"verified\" },\n fileSystem: { status: \"verified\" },\n clipboard: { status: \"verified\", note: \"wl-clipboard / xclip / xsel\" },\n },\n darwin: {\n screenshot: { status: \"code-parity\", note: \"screencapture (built-in)\" },\n computerUse: {\n status: \"code-parity\",\n note: \"cliclick + AppleScript / Swift fallbacks\",\n },\n windowList: { status: \"code-parity\", note: \"AppleScript System Events\" },\n browser: {\n status: \"code-parity\",\n note: \"Chrome / Edge / Brave / Brave Beta / Arc / Vivaldi detection\",\n },\n terminal: { status: \"code-parity\", note: \"/bin/bash via execFile\" },\n fileSystem: { status: \"verified\" },\n clipboard: { status: \"code-parity\", note: \"pbpaste / pbcopy (built-in)\" },\n },\n win32: {\n screenshot: { status: \"code-parity\", note: \"PowerShell System.Drawing\" },\n computerUse: { status: \"code-parity\", note: \"PowerShell user32.dll\" },\n windowList: {\n status: \"code-parity\",\n note: \"PowerShell Get-Process MainWindowTitle + ProcessName\",\n },\n browser: {\n status: \"code-parity\",\n note: \"Chrome / Edge / Brave / Arc / Vivaldi detection\",\n },\n terminal: {\n status: \"code-parity\",\n note: \"powershell.exe -NoProfile -Command + Win-specific blocklist\",\n },\n fileSystem: { status: \"verified\" },\n clipboard: { status: \"code-parity\", note: \"PowerShell Get-Clipboard\" },\n },\n};\n\nexport function parityFor(\n osName: PlatformOS,\n capability: keyof PlatformCapabilities,\n): ParityNote {\n return DESKTOP_PARITY[osName][capability];\n}\n\nexport function detectPlatformCapabilities(\n options: CapabilityDetectionOptions,\n): PlatformCapabilities {\n const caps: PlatformCapabilities = {\n screenshot: { available: false, tool: \"none\" },\n computerUse: { available: false, tool: \"none\" },\n windowList: { available: false, tool: \"none\" },\n browser: { available: false, tool: \"none\" },\n terminal: { available: false, tool: \"none\" },\n fileSystem: { available: true, tool: \"node:fs\" },\n clipboard: { available: false, tool: \"none\" },\n };\n\n if (options.osName === \"darwin\") {\n caps.screenshot = { available: true, tool: \"screencapture (built-in)\" };\n caps.computerUse = options.commandExists(\"cliclick\")\n ? { available: true, tool: \"cliclick\" }\n : {\n available: true,\n tool: \"AppleScript / Swift fallbacks (mouse_move requires cliclick)\",\n };\n caps.windowList = {\n available: true,\n tool: \"AppleScript System Events\",\n };\n caps.clipboard = { available: true, tool: \"pbpaste / pbcopy (built-in)\" };\n } else if (options.osName === \"linux\") {\n if (options.commandExists(\"import\")) {\n caps.screenshot = { available: true, tool: \"ImageMagick import\" };\n } else if (options.commandExists(\"scrot\")) {\n caps.screenshot = { available: true, tool: \"scrot\" };\n } else if (options.commandExists(\"gnome-screenshot\")) {\n caps.screenshot = { available: true, tool: \"gnome-screenshot\" };\n } else {\n caps.screenshot = {\n available: false,\n tool: \"none (install ImageMagick, scrot, or gnome-screenshot)\",\n };\n }\n\n caps.computerUse = options.commandExists(\"xdotool\")\n ? { available: true, tool: \"xdotool\" }\n : { available: false, tool: \"none (install xdotool)\" };\n\n if (options.commandExists(\"wmctrl\")) {\n caps.windowList = { available: true, tool: \"wmctrl\" };\n } else if (options.commandExists(\"xdotool\")) {\n caps.windowList = { available: true, tool: \"xdotool\" };\n } else {\n caps.windowList = {\n available: false,\n tool: \"none (install wmctrl or xdotool)\",\n };\n }\n\n if (options.commandExists(\"wl-paste\")) {\n caps.clipboard = { available: true, tool: \"wl-clipboard\" };\n } else if (options.commandExists(\"xclip\")) {\n caps.clipboard = { available: true, tool: \"xclip\" };\n } else if (options.commandExists(\"xsel\")) {\n caps.clipboard = { available: true, tool: \"xsel\" };\n } else {\n caps.clipboard = {\n available: false,\n tool: \"none (install wl-clipboard, xclip, or xsel)\",\n };\n }\n } else if (options.osName === \"win32\") {\n caps.screenshot = { available: true, tool: \"PowerShell System.Drawing\" };\n caps.computerUse = { available: true, tool: \"PowerShell user32.dll\" };\n caps.windowList = { available: true, tool: \"PowerShell Get-Process\" };\n caps.clipboard = { available: true, tool: \"PowerShell Get-Clipboard\" };\n }\n\n caps.browser = options.isBrowserAvailable()\n ? { available: true, tool: \"puppeteer-core (Chromium detected)\" }\n : { available: false, tool: \"none (no Chrome/Edge/Brave found)\" };\n\n caps.terminal =\n options.osName === \"win32\"\n ? { available: true, tool: \"powershell.exe\" }\n : options.commandExists(options.shell ?? \"/bin/bash\")\n ? { available: true, tool: options.shell ?? \"/bin/bash\" }\n : { available: true, tool: options.shell ?? \"/bin/sh\" };\n\n return caps;\n}\n",
|
|
44
|
+
"/**\n * Coordinate translation between display-local and OS-global pixel space (WS5).\n *\n * Contract:\n * - Every public mouse-bearing action accepts `{displayId, x, y}` where\n * `(x, y)` is LOCAL to that display (top-left = 0,0, units = pixels of the\n * display's logical bounds).\n * - This module translates to the OS-global space the input drivers expect.\n *\n * Why local-first:\n * - The model sees each display independently (one capture, no virtual\n * desktop stitching). Local coords match what the model just looked at.\n * - Virtual-desktop coords are a perpetual DPI / negative-origin bug source.\n *\n * Per-OS behavior of the input drivers we wrap (nutjs / xdotool / cliclick /\n * PowerShell `SetCursorPos`):\n * - Linux/X11: drivers expect global pixel coords matching xrandr origins.\n * Translation = display.x + local.x. No DPI conversion.\n * - Windows: `SetCursorPos` and nutjs both take physical pixel coords\n * when the process is PerMonitorV2 DPI aware. Translation = display.x +\n * local.x. No multiplier here — caller is responsible for declaring\n * dpiAwareness.\n * - macOS: Quartz event coords are in points (logical), not backing-\n * store pixels. Translation = display.x + local.x with no scale multiply\n * IF the local coords are also in points. We document the local coord\n * space as \"logical pixels\" matching the capture's render at logical\n * resolution; for retina captures the screenshot is upsampled to backing-\n * store pixels and the model is expected to scale clicks back down\n * before sending. The translator divides by scaleFactor when local\n * coords were sourced from a backing-store-resolution screenshot.\n */\n\nimport type { DisplayInfo } from \"./displays.js\";\nimport { findDisplay, getPrimaryDisplay, listDisplays } from \"./displays.js\";\nimport { currentPlatform } from \"./helpers.js\";\n\nexport interface LocalPoint {\n displayId: number;\n x: number;\n y: number;\n}\n\nexport interface GlobalPoint {\n x: number;\n y: number;\n}\n\n/**\n * Resolve a LocalPoint to a GlobalPoint the input driver can act on.\n *\n * `coordSource` describes the coordinate reference:\n * - `\"logical\"` (default) — local coords are in logical pixels matching the\n * display's `bounds[2..3]`. No scale conversion is applied.\n * - `\"backing\"` — local coords were taken against a capture rendered at\n * `bounds * scaleFactor` (e.g. raw retina PNG). They are divided by\n * scaleFactor before translation. macOS-only relevant.\n */\nexport function localToGlobal(\n point: LocalPoint,\n coordSource: \"logical\" | \"backing\" = \"logical\",\n): GlobalPoint {\n const display = findDisplay(point.displayId);\n if (!display) {\n throw new Error(\n `Unknown displayId ${point.displayId}. Known displays: ${listDisplays()\n .map((d) => `${d.id}(${d.name})`)\n .join(\", \")}`,\n );\n }\n return translate(display, point.x, point.y, coordSource);\n}\n\n/**\n * As `localToGlobal`, but tolerates a missing displayId by defaulting to the\n * primary display. Logs nothing — callers should warn before using this.\n */\nexport function localToGlobalDefault(\n point: { displayId?: number; x: number; y: number },\n coordSource: \"logical\" | \"backing\" = \"logical\",\n): GlobalPoint {\n if (point.displayId === undefined) {\n const primary = getPrimaryDisplay();\n return translate(primary, point.x, point.y, coordSource);\n }\n return localToGlobal(\n { displayId: point.displayId, x: point.x, y: point.y },\n coordSource,\n );\n}\n\nfunction translate(\n display: DisplayInfo,\n localX: number,\n localY: number,\n coordSource: \"logical\" | \"backing\",\n): GlobalPoint {\n let lx = localX;\n let ly = localY;\n if (coordSource === \"backing\" && currentPlatform() === \"darwin\") {\n const s = display.scaleFactor || 1;\n if (s > 0) {\n lx = localX / s;\n ly = localY / s;\n }\n }\n return {\n x: Math.round(display.bounds[0] + lx),\n y: Math.round(display.bounds[1] + ly),\n };\n}\n\n/**\n * Inverse: given an OS-global point, return the (displayId, x, y) of the\n * display containing it. Returns null if no display contains the point.\n * Useful for translating OS-reported cursor positions back to local coords.\n */\nexport function globalToLocal(point: GlobalPoint): LocalPoint | null {\n for (const d of listDisplays()) {\n const [x, y, w, h] = d.bounds;\n if (point.x >= x && point.x < x + w && point.y >= y && point.y < y + h) {\n return { displayId: d.id, x: point.x - x, y: point.y - y };\n }\n }\n return null;\n}\n\n/**\n * Validate a local point is inside its display's bounds. Returns the clamped\n * point — never throws. Use this before sending to drivers that crash on\n * out-of-bounds coords on some Linux versions.\n */\nexport function clampToDisplay(point: LocalPoint): LocalPoint {\n const display = findDisplay(point.displayId);\n if (!display) return point;\n const [, , w, h] = display.bounds;\n return {\n displayId: point.displayId,\n x: Math.max(0, Math.min(point.x, Math.max(0, w - 1))),\n y: Math.max(0, Math.min(point.y, Math.max(0, h - 1))),\n };\n}\n",
|
|
45
|
+
"import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { FileActionResult, FileEntry } from \"../types.js\";\nimport { resolveSafeFileTarget } from \"./security.js\";\n\nexport async function readFile(\n targetPath: string,\n encoding: BufferEncoding = \"utf8\",\n): Promise<FileActionResult> {\n const check = await resolveSafeFileTarget(targetPath, \"read\");\n if (!check.allowed || !check.resolvedPath) {\n return { success: false, error: check.reason ?? \"Path not allowed.\" };\n }\n\n try {\n const content = await fs.readFile(check.resolvedPath, { encoding });\n return {\n success: true,\n path: check.resolvedPath,\n content: String(content).slice(0, 10000),\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\nexport async function writeFile(\n targetPath: string,\n content: string,\n): Promise<FileActionResult> {\n const check = await resolveSafeFileTarget(targetPath, \"write\");\n if (!check.allowed || !check.resolvedPath) {\n return { success: false, error: check.reason ?? \"Path not allowed.\" };\n }\n\n try {\n await fs.mkdir(path.dirname(check.resolvedPath), { recursive: true });\n await fs.writeFile(check.resolvedPath, content, \"utf8\");\n return {\n success: true,\n path: check.resolvedPath,\n message: \"File written.\",\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\nexport async function editFile(\n targetPath: string,\n oldText: string,\n newText: string,\n): Promise<FileActionResult> {\n const check = await resolveSafeFileTarget(targetPath, \"write\");\n if (!check.allowed || !check.resolvedPath) {\n return { success: false, error: check.reason ?? \"Path not allowed.\" };\n }\n\n try {\n const content = await fs.readFile(check.resolvedPath, \"utf8\");\n if (!content.includes(oldText)) {\n return {\n success: false,\n error: \"Old text not found in file.\",\n };\n }\n await fs.writeFile(\n check.resolvedPath,\n content.replace(oldText, newText),\n \"utf8\",\n );\n return {\n success: true,\n path: check.resolvedPath,\n message: \"File edited.\",\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\nexport async function appendFile(\n targetPath: string,\n content: string,\n): Promise<FileActionResult> {\n const check = await resolveSafeFileTarget(targetPath, \"write\");\n if (!check.allowed || !check.resolvedPath) {\n return { success: false, error: check.reason ?? \"Path not allowed.\" };\n }\n\n try {\n await fs.mkdir(path.dirname(check.resolvedPath), { recursive: true });\n await fs.appendFile(check.resolvedPath, content, \"utf8\");\n return {\n success: true,\n path: check.resolvedPath,\n message: \"Content appended.\",\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\nexport async function deleteFile(\n targetPath: string,\n): Promise<FileActionResult> {\n const check = await resolveSafeFileTarget(targetPath, \"delete\");\n if (!check.allowed || !check.resolvedPath) {\n return { success: false, error: check.reason ?? \"Path not allowed.\" };\n }\n\n try {\n await fs.unlink(check.resolvedPath);\n return {\n success: true,\n path: check.resolvedPath,\n message: \"File deleted.\",\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\nexport async function fileExists(\n targetPath: string,\n): Promise<FileActionResult> {\n const check = await resolveSafeFileTarget(targetPath, \"read\");\n if (!check.allowed || !check.resolvedPath) {\n return { success: false, error: check.reason ?? \"Path not allowed.\" };\n }\n\n try {\n await fs.access(check.resolvedPath);\n const stat = await fs.stat(check.resolvedPath);\n return {\n success: true,\n path: check.resolvedPath,\n exists: true,\n isFile: stat.isFile(),\n isDirectory: stat.isDirectory(),\n is_file: stat.isFile(),\n is_directory: stat.isDirectory(),\n size: stat.size,\n };\n } catch {\n return {\n success: true,\n path: check.resolvedPath,\n exists: false,\n isFile: false,\n isDirectory: false,\n is_file: false,\n is_directory: false,\n size: 0,\n };\n }\n}\n\nexport async function listDirectory(\n targetPath: string,\n): Promise<FileActionResult> {\n const check = await resolveSafeFileTarget(targetPath, \"read\");\n if (!check.allowed || !check.resolvedPath) {\n return { success: false, error: check.reason ?? \"Path not allowed.\" };\n }\n const resolvedPath = check.resolvedPath;\n\n try {\n const entries = await fs.readdir(resolvedPath, { withFileTypes: true });\n const items: FileEntry[] = entries.map((entry) => ({\n name: entry.name,\n type: entry.isDirectory() ? \"directory\" : \"file\",\n path: path.join(resolvedPath, entry.name),\n }));\n return {\n success: true,\n path: resolvedPath,\n items,\n count: items.length,\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\nexport async function deleteDirectory(\n targetPath: string,\n): Promise<FileActionResult> {\n const check = await resolveSafeFileTarget(targetPath, \"delete\");\n if (!check.allowed || !check.resolvedPath) {\n return { success: false, error: check.reason ?? \"Path not allowed.\" };\n }\n\n try {\n await fs.rm(check.resolvedPath, { recursive: true, force: true });\n return {\n success: true,\n path: check.resolvedPath,\n message: \"Directory deleted.\",\n };\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\nfunction fileOpError(error: unknown): FileActionResult {\n return {\n success: false,\n error: error instanceof Error ? error.message : String(error),\n };\n}\n\n/**\n * Read raw bytes as base64 (#9170 — cua `read_bytes`). Optional byte `offset` /\n * `length` window for chunked transfer of a sandbox guest file. Unlike `readFile`\n * (text, truncated to 10k chars) this is binary-safe and returns the exact bytes.\n */\nexport async function readBytes(\n targetPath: string,\n offset?: number,\n length?: number,\n): Promise<FileActionResult> {\n const check = await resolveSafeFileTarget(targetPath, \"read\");\n if (!check.allowed || !check.resolvedPath) {\n return { success: false, error: check.reason ?? \"Path not allowed.\" };\n }\n try {\n let buf = await fs.readFile(check.resolvedPath);\n if (typeof offset === \"number\" || typeof length === \"number\") {\n const start = Math.max(0, Math.floor(offset ?? 0));\n const end =\n typeof length === \"number\"\n ? start + Math.max(0, Math.floor(length))\n : undefined;\n buf = buf.subarray(start, end);\n }\n return {\n success: true,\n path: check.resolvedPath,\n bytes: buf.toString(\"base64\"),\n size: buf.length,\n };\n } catch (error) {\n return fileOpError(error);\n }\n}\n\n/**\n * Write base64-encoded bytes to a file (#9170 — cua `write_bytes`), creating\n * parent directories. Binary-safe counterpart to `writeFile`.\n */\nexport async function writeBytes(\n targetPath: string,\n base64: string,\n): Promise<FileActionResult> {\n const check = await resolveSafeFileTarget(targetPath, \"write\");\n if (!check.allowed || !check.resolvedPath) {\n return { success: false, error: check.reason ?? \"Path not allowed.\" };\n }\n try {\n const buf = Buffer.from(base64 ?? \"\", \"base64\");\n await fs.mkdir(path.dirname(check.resolvedPath), { recursive: true });\n await fs.writeFile(check.resolvedPath, buf);\n return {\n success: true,\n path: check.resolvedPath,\n size: buf.length,\n message: `Wrote ${buf.length} bytes.`,\n };\n } catch (error) {\n return fileOpError(error);\n }\n}\n\n/** Create a directory (recursive) (#9170 — cua `create_dir`). */\nexport async function createDirectory(\n targetPath: string,\n): Promise<FileActionResult> {\n const check = await resolveSafeFileTarget(targetPath, \"write\");\n if (!check.allowed || !check.resolvedPath) {\n return { success: false, error: check.reason ?? \"Path not allowed.\" };\n }\n try {\n await fs.mkdir(check.resolvedPath, { recursive: true });\n return {\n success: true,\n path: check.resolvedPath,\n is_directory: true,\n isDirectory: true,\n message: \"Directory created.\",\n };\n } catch (error) {\n return fileOpError(error);\n }\n}\n\n/** Whether a path exists AND is a directory (#9170 — cua `directory_exists`). */\nexport async function directoryExists(\n targetPath: string,\n): Promise<FileActionResult> {\n const check = await resolveSafeFileTarget(targetPath, \"read\");\n if (!check.allowed || !check.resolvedPath) {\n return { success: false, error: check.reason ?? \"Path not allowed.\" };\n }\n try {\n const stat = await fs.stat(check.resolvedPath);\n const isDir = stat.isDirectory();\n return {\n success: true,\n path: check.resolvedPath,\n exists: isDir,\n is_directory: isDir,\n isDirectory: isDir,\n };\n } catch {\n return {\n success: true,\n path: check.resolvedPath,\n exists: false,\n is_directory: false,\n isDirectory: false,\n };\n }\n}\n\n/** File/dir size in bytes (#9170 — cua `get_file_size`). */\nexport async function getFileSize(\n targetPath: string,\n): Promise<FileActionResult> {\n const check = await resolveSafeFileTarget(targetPath, \"read\");\n if (!check.allowed || !check.resolvedPath) {\n return { success: false, error: check.reason ?? \"Path not allowed.\" };\n }\n try {\n const stat = await fs.stat(check.resolvedPath);\n return {\n success: true,\n path: check.resolvedPath,\n size: stat.size,\n is_file: stat.isFile(),\n isFile: stat.isFile(),\n is_directory: stat.isDirectory(),\n isDirectory: stat.isDirectory(),\n };\n } catch (error) {\n return fileOpError(error);\n }\n}\n",
|
|
46
|
+
"import fs from \"node:fs\";\nimport { lstat, realpath } from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\n\nexport interface PathValidationResult {\n allowed: boolean;\n reason?: string;\n}\n\nexport interface CommandRiskResult {\n blocked: boolean;\n reason?: string;\n}\n\ninterface LabelledPattern {\n pattern: RegExp;\n label: string;\n}\n\ninterface DangerousPattern {\n pattern: RegExp;\n reason: string;\n}\n\nconst CREDENTIAL_PATTERNS: LabelledPattern[] = [\n {\n pattern: /^\\/\\.ssh\\/(?:id_|.*\\.pem$|authorized_keys$|config$)/i,\n label: \"SSH key/config\",\n },\n { pattern: /^\\/\\.gnupg\\//i, label: \"GPG keyring\" },\n { pattern: /^\\/\\.aws\\/credentials$/i, label: \"AWS credentials\" },\n {\n pattern: /^\\/\\.config\\/gcloud\\/application_default_credentials\\.json$/i,\n label: \"GCP credentials\",\n },\n { pattern: /^\\/\\.docker\\/config\\.json$/i, label: \"Docker credentials\" },\n { pattern: /^\\/\\.kube\\/config$/i, label: \"Kubernetes config\" },\n { pattern: /^\\/\\.netrc$/i, label: \"netrc credentials\" },\n { pattern: /^\\/\\.npmrc$/i, label: \"npm credentials\" },\n { pattern: /^\\/\\.git-credentials$/i, label: \"Git stored credentials\" },\n { pattern: /^\\/Library\\/Keychains\\//i, label: \"macOS Keychain\" },\n {\n pattern:\n /\\/(?:Google\\/Chrome|Microsoft\\/Edge|BraveSoftware\\/Brave-Browser)\\/.*\\/Login Data$/i,\n label: \"browser password database\",\n },\n {\n pattern:\n /\\/(?:Google\\/Chrome|Microsoft\\/Edge|BraveSoftware\\/Brave-Browser)\\/.*\\/Cookies$/i,\n label: \"browser cookie database\",\n },\n {\n pattern:\n /\\/\\.mozilla\\/firefox\\/.*\\/(?:logins\\.json|key[34]\\.db|cookies\\.sqlite)$/i,\n label: \"Firefox credential/cookie store\",\n },\n];\n\nconst SYSTEM_DIR_PATTERNS_WIN32: LabelledPattern[] = [\n { pattern: /^[A-Z]:\\/Windows\\//i, label: \"Windows system directory\" },\n { pattern: /^[A-Z]:\\/Program Files/i, label: \"Program Files directory\" },\n { pattern: /^[A-Z]:\\/ProgramData\\//i, label: \"ProgramData directory\" },\n {\n pattern: /^[A-Z]:\\/PROGRA~[1-4]\\//i,\n label: \"Program Files (8.3 short name)\",\n },\n];\n\nconst SYSTEM_DIR_PATTERNS_UNIX: LabelledPattern[] = [\n { pattern: /^\\/boot\\//i, label: \"boot directory\" },\n { pattern: /^\\/sbin\\//i, label: \"system binary directory\" },\n { pattern: /^\\/usr\\/sbin\\//i, label: \"system admin binary directory\" },\n { pattern: /^\\/usr\\/lib\\//i, label: \"system library directory\" },\n {\n pattern: /^\\/etc\\/(?:shadow|sudoers|pam\\.d|master\\.passwd)/i,\n label: \"system auth config\",\n },\n { pattern: /^\\/System\\//i, label: \"macOS System directory\" },\n {\n pattern: /^\\/private\\/var\\/db\\/dslocal/i,\n label: \"macOS Directory Services\",\n },\n { pattern: /^\\/dev\\//i, label: \"device node\" },\n { pattern: /^\\/proc\\//i, label: \"proc filesystem\" },\n { pattern: /^\\/sys\\//i, label: \"sys filesystem\" },\n];\n\nconst WINDOWS_DEVICE_NAME = /^(CON|PRN|AUX|NUL|COM\\d|LPT\\d)(\\..+)?$/i;\n\nconst STRIP_EXACT_ENV = new Set([\n \"INTERNAL_API_KEY\",\n \"CSRF_SECRET\",\n \"ENCRYPTION_KEY\",\n \"SUPABASE_SERVICE_ROLE\",\n \"STRIPE_API_KEY\",\n \"STRIPE_WEBHOOK_SECRET\",\n \"POSTHOG_API_KEY\",\n]);\n\nconst STRIP_PATTERN_ENV: RegExp[] = [\n /^SUPABASE_.*(?:SERVICE_ROLE|SECRET)/i,\n /^STRIPE_.*(?:SECRET|WEBHOOK)/i,\n /^ELIZA_.*(?:SECRET|KEY|TOKEN)/i,\n // LLM provider + connector credentials must not leak into spawned commands.\n /^(?:ANTHROPIC|OPENAI|OPENROUTER|GROQ|XAI|GOOGLE|GEMINI|GOOGLE_GENERATIVE_AI|ELEVENLABS|DEEPGRAM|MISTRAL|COHERE|DISCORD|TELEGRAM|SLACK|FARCASTER|TWITTER|AWS)_.*(?:KEY|TOKEN|SECRET|PASSWORD)/i,\n // Catch-all for credential-suffixed keys from any other provider/connector.\n /_(?:API_KEY|SECRET|TOKEN|PASSWORD|PRIVATE_KEY)$/i,\n];\n\nconst DANGEROUS_COMMAND_PATTERNS: DangerousPattern[] = [\n {\n pattern: /\\brm\\s+-[^\\n;|&]*r[^\\n;|&]*\\s+\\/(\\s*$|\\s*;|\\s*&|\\s*\\|)/im,\n reason: \"Recursive deletion of the root filesystem (rm -rf /).\",\n },\n {\n pattern: /\\brm\\s+-[^\\n;|&]*r[^\\n;|&]*\\s+\\/\\*/im,\n reason: \"Recursive deletion of all root contents (rm -rf /*).\",\n },\n {\n pattern: /\\brm\\s+-[^\\n;|&]*r[^\\n;|&]*\\s+~\\/?(\\s|$|;|&|\\|)/im,\n reason: \"Recursive deletion of the entire home directory.\",\n },\n {\n pattern:\n /\\bRemove-Item\\b(?=[^;|&]*-Recurse)(?=[^;|&]*[\\s'\"][A-Z]:[\\\\/](?=[^a-zA-Z0-9]|$))/im,\n reason: \"PowerShell recursive deletion of drive root.\",\n },\n {\n pattern:\n /\\bRemove-Item\\b(?=[^;|&]*-Recurse)(?=[^;|&]*[\\s'\"]\\/{1,2}['\"\\s])/im,\n reason: \"PowerShell recursive deletion of filesystem root.\",\n },\n {\n pattern:\n /\\b(?:powershell|pwsh)(?:\\.exe)?\\b[^|]*-(?:enc|encodedcommand)\\b/im,\n reason: \"Encoded PowerShell command.\",\n },\n {\n pattern: /\\bmkfs(?:\\.\\w+)?\\s/i,\n reason: \"Filesystem format command (mkfs).\",\n },\n {\n pattern: /\\bdd\\s+[^;|&]*\\bof=\\/dev\\/[hs]d/i,\n reason: \"Raw disk write (dd of=/dev/sdX).\",\n },\n {\n pattern: /:\\(\\)\\s*\\{[^}]*:\\s*\\|\\s*:/,\n reason: \"Fork bomb detected.\",\n },\n {\n pattern: /\\breg\\s+delete\\s+HKLM\\\\/i,\n reason: \"System registry deletion.\",\n },\n];\n\n/**\n * Build the set of \"home-relative\" candidate strings a credential pattern is\n * tested against. The anchored CREDENTIAL_PATTERNS (e.g. `^/.ssh/...`) expect a\n * path with the home root stripped, so we strip the agent's own home plus any\n * `/root` or `/home/<user>` prefix. The full normalized path is always included\n * so the non-anchored browser-store patterns continue to match anywhere.\n */\nfunction credentialRelativePaths(normalized: string): string[] {\n const candidates = new Set<string>([normalized]);\n\n const home = os.homedir().replace(/\\\\/g, \"/\");\n if (home && normalized.startsWith(`${home}/`)) {\n candidates.add(normalized.slice(home.length));\n }\n\n // /root/... and /home/<user>/... — strip the home root so reads of other\n // users' (and root's) credential files are caught regardless of os.homedir().\n const otherHomeMatch = normalized.match(\n /^\\/root(?=\\/)|^\\/home\\/[^/]+(?=\\/)/i,\n );\n if (otherHomeMatch) {\n candidates.add(normalized.slice(otherHomeMatch[0].length));\n }\n\n // /Users/<user>/... (macOS) home root.\n const macHomeMatch = normalized.match(/^\\/Users\\/[^/]+(?=\\/)/i);\n if (macHomeMatch) {\n candidates.add(normalized.slice(macHomeMatch[0].length));\n }\n\n // C:/Users/<user>/... (Windows) home root. The optional leading path segment\n // lets POSIX test runners exercise Windows-style paths after path.resolve().\n const windowsHomeMatch = normalized.match(\n /(?:^|\\/)[A-Z]:\\/Users\\/[^/]+(?=\\/)/i,\n );\n if (windowsHomeMatch) {\n const root = windowsHomeMatch[0].startsWith(\"/\")\n ? windowsHomeMatch[0].slice(1)\n : windowsHomeMatch[0];\n const rootIndex = normalized.indexOf(root);\n if (rootIndex >= 0) {\n candidates.add(normalized.slice(rootIndex + root.length));\n }\n }\n\n return [...candidates];\n}\n\nexport function validateFilePath(\n filePath: string,\n operation: \"read\" | \"write\" | \"delete\",\n): PathValidationResult {\n if (!filePath || typeof filePath !== \"string\") {\n return { allowed: false, reason: \"No file path provided.\" };\n }\n\n if (filePath.includes(\"\\0\")) {\n return {\n allowed: false,\n reason: \"Path contains null bytes (possible injection attack).\",\n };\n }\n\n let resolved = path.resolve(filePath);\n if (resolved.startsWith(\"\\\\\\\\\")) {\n return {\n allowed: false,\n reason: \"Network (UNC) paths are blocked. Only local files are allowed.\",\n };\n }\n\n if (process.platform === \"win32\" && /~\\d/.test(resolved)) {\n try {\n const expanded = fs.realpathSync.native(resolved);\n if (expanded !== resolved) {\n resolved = expanded;\n }\n } catch {\n // Ignore nonexistent paths; the static blocklists still apply.\n }\n }\n\n const normalized = resolved.replace(/\\\\/g, \"/\");\n\n if (process.platform === \"win32\" && operation !== \"read\") {\n const basename = path.basename(resolved);\n if (WINDOWS_DEVICE_NAME.test(basename)) {\n return {\n allowed: false,\n reason: `Blocked: \"${basename}\" is a Windows reserved device name.`,\n };\n }\n }\n\n // Evaluate credential patterns against the path relative to ANY user's home\n // (the agent's own home, /root, and /home/<user>), not just the current home,\n // so reads of e.g. /root/.ssh/id_rsa or /home/other/.aws/credentials are\n // still blocked. The anchored patterns expect a \"/.ssh/...\" style suffix.\n for (const relativeToHome of credentialRelativePaths(normalized)) {\n for (const { pattern, label } of CREDENTIAL_PATTERNS) {\n if (pattern.test(relativeToHome)) {\n return {\n allowed: false,\n reason: `Blocked: \"${path.basename(resolved)}\" is a ${label} file.`,\n };\n }\n }\n }\n\n // Sensitive UNIX system paths (/etc/shadow, /proc, /sys, /dev, …) are blocked\n // for EVERY operation, including reads, so they cannot be exfiltrated via a\n // read. The Windows program-directory patterns stay write/delete-only because\n // reading config/log files there is a legitimate use case.\n if (process.platform !== \"win32\") {\n for (const { pattern, label } of SYSTEM_DIR_PATTERNS_UNIX) {\n if (pattern.test(normalized)) {\n return {\n allowed: false,\n reason: `Blocked: cannot ${operation} in ${label}.`,\n };\n }\n }\n }\n\n if (operation !== \"read\") {\n if (process.platform === \"win32\") {\n for (const { pattern, label } of SYSTEM_DIR_PATTERNS_WIN32) {\n if (pattern.test(normalized)) {\n return {\n allowed: false,\n reason: `Blocked: cannot ${operation} in ${label}.`,\n };\n }\n }\n }\n\n if (/^[A-Z]:\\/?$/i.test(normalized) || normalized === \"/\") {\n return {\n allowed: false,\n reason: `Blocked: cannot ${operation} the filesystem root.`,\n };\n }\n }\n\n return { allowed: true };\n}\n\nexport type SafeFileTargetResult = PathValidationResult & {\n resolvedPath?: string;\n};\n\nfunction errnoCode(error: unknown): string {\n return error && typeof error === \"object\" && \"code\" in error\n ? String((error as NodeJS.ErrnoException).code)\n : \"\";\n}\n\n/**\n * Resolve and re-validate file paths after lstat/realpath to reduce TOCTOU /\n * symlink escapes (GHSA-qmf5-p9x5-9xr5).\n */\nexport async function resolveSafeFileTarget(\n filePath: string,\n operation: \"read\" | \"write\" | \"delete\",\n): Promise<SafeFileTargetResult> {\n const check = validateFilePath(filePath, operation);\n if (!check.allowed) {\n return check;\n }\n\n const resolved = path.resolve(filePath);\n\n try {\n const stat = await lstat(resolved);\n if (stat.isSymbolicLink()) {\n return {\n allowed: false,\n reason: \"Symbolic links are not allowed for file operations.\",\n };\n }\n const canonical = await realpath(resolved);\n const recheck = validateFilePath(canonical, operation);\n if (!recheck.allowed) {\n return recheck;\n }\n return { allowed: true, resolvedPath: canonical };\n } catch (error) {\n if (errnoCode(error) === \"ENOENT\" && operation === \"read\") {\n const fallback = validateFilePath(resolved, operation);\n if (!fallback.allowed) {\n return fallback;\n }\n return { allowed: true, resolvedPath: resolved };\n }\n\n if (errnoCode(error) === \"ENOENT\" && operation === \"write\") {\n const parent = path.dirname(resolved);\n try {\n const parentStat = await lstat(parent);\n if (parentStat.isSymbolicLink()) {\n return {\n allowed: false,\n reason: \"Parent path is a symbolic link.\",\n };\n }\n const parentReal = await realpath(parent);\n const target = path.join(parentReal, path.basename(resolved));\n const parentCheck = validateFilePath(target, operation);\n if (!parentCheck.allowed) {\n return parentCheck;\n }\n return { allowed: true, resolvedPath: target };\n } catch (parentError) {\n if (errnoCode(parentError) === \"ENOENT\") {\n const fallback = validateFilePath(resolved, operation);\n if (!fallback.allowed) {\n return fallback;\n }\n return { allowed: true, resolvedPath: resolved };\n }\n return {\n allowed: false,\n reason:\n parentError instanceof Error\n ? parentError.message\n : String(parentError),\n };\n }\n }\n\n return {\n allowed: false,\n reason: error instanceof Error ? error.message : String(error),\n };\n }\n}\n\nexport function sanitizeChildEnv(): Record<string, string | undefined> {\n const env = { ...process.env };\n for (const key of Object.keys(env)) {\n if (STRIP_EXACT_ENV.has(key)) {\n delete env[key];\n continue;\n }\n for (const pattern of STRIP_PATTERN_ENV) {\n if (pattern.test(key)) {\n delete env[key];\n break;\n }\n }\n }\n return env;\n}\n\nexport function checkDangerousCommand(command: string): CommandRiskResult {\n if (!command || typeof command !== \"string\") {\n return { blocked: false };\n }\n\n const trimmed = command.trim();\n for (const { pattern, reason } of DANGEROUS_COMMAND_PATTERNS) {\n if (pattern.test(trimmed)) {\n return {\n blocked: true,\n reason:\n `Command blocked: ${reason}\\n` +\n \"If you genuinely need to run this, execute it manually in a terminal.\",\n };\n }\n }\n\n return { blocked: false };\n}\n",
|
|
47
|
+
"/**\n * Open a target (file / URL / folder) and launch applications (#9170 M12).\n *\n * trycua/cua exposes `open(target)` and `launch(app, args) -> pid`. Eliza had\n * neither as a COMPUTER_USE verb. These are real desktop automation (the agent\n * opening a document or starting an app), so they live in the COMPUTER_USE\n * action and pass through the approval manager like every other non-read verb.\n *\n * Implementation notes:\n * - `open` shells the OS default-handler (`open` / `xdg-open` / `start`), so a\n * URL opens in the browser, a file in its default app, a folder in the file\n * manager — exactly the OS double-click behavior.\n * - `launch` spawns the executable DETACHED and returns its pid so the caller\n * can track / focus it. The child is unref'd so it outlives the agent turn.\n */\n\nimport { type ChildProcess, execFile, spawn } from \"node:child_process\";\nimport { currentPlatform } from \"./helpers.js\";\n\n/** Result of a launch — the spawned process id (and the resolved command). */\nexport interface LaunchResult {\n pid: number;\n command: string;\n args: string[];\n}\n\nconst OPEN_TIMEOUT_MS = 10_000;\n\n/**\n * Open a file / URL / folder with the OS default handler. Resolves once the\n * launcher returns (the launcher exits immediately; the opened app keeps\n * running). Rejects on a non-zero launcher exit.\n */\nexport function openTarget(target: string): Promise<void> {\n const value = target?.trim();\n if (!value) {\n return Promise.reject(new Error(\"open requires a non-empty target\"));\n }\n const os = currentPlatform();\n let command: string;\n let args: string[];\n if (os === \"darwin\") {\n command = \"open\";\n args = [value];\n } else if (os === \"linux\") {\n command = \"xdg-open\";\n args = [value];\n } else if (os === \"win32\") {\n // `start` is a cmd builtin; the empty \"\" is the window-title arg so a\n // quoted path/URL isn't mistaken for the title.\n command = \"cmd\";\n args = [\"/c\", \"start\", \"\", value];\n } else {\n return Promise.reject(new Error(`open unsupported on platform \"${os}\"`));\n }\n return new Promise<void>((resolve, reject) => {\n execFile(command, args, { timeout: OPEN_TIMEOUT_MS }, (err) => {\n if (err) reject(err);\n else resolve();\n });\n });\n}\n\n/**\n * Launch an application detached and return its pid. `app` is an executable\n * name/path (or, on macOS, an app-bundle name launched via `open -a`). The\n * child is unref'd so it survives the agent turn.\n */\nexport function launchApp(\n app: string,\n args: string[] = [],\n): Promise<LaunchResult> {\n const value = app?.trim();\n if (!value) {\n return Promise.reject(new Error(\"launch requires a non-empty app\"));\n }\n const os = currentPlatform();\n // macOS app-bundle names (e.g. \"Safari\", \"Visual Studio Code\") launch via\n // `open -a NAME --args ...`; absolute executable paths spawn directly.\n const useMacOpen = os === \"darwin\" && !value.includes(\"/\");\n const command = useMacOpen ? \"open\" : value;\n const spawnArgs = useMacOpen\n ? [\"-a\", value, ...(args.length ? [\"--args\", ...args] : [])]\n : args;\n\n return new Promise<LaunchResult>((resolve, reject) => {\n let child: ChildProcess;\n try {\n child = spawn(command, spawnArgs, {\n detached: true,\n stdio: \"ignore\",\n });\n } catch (err) {\n reject(err instanceof Error ? err : new Error(String(err)));\n return;\n }\n let settled = false;\n child.once(\"error\", (err) => {\n if (settled) return;\n settled = true;\n reject(err);\n });\n // `spawn` assigns the pid synchronously on success; resolve on next tick so\n // an immediate spawn `error` (e.g. ENOENT) rejects first.\n setImmediate(() => {\n if (settled) return;\n if (typeof child.pid !== \"number\") {\n settled = true;\n reject(new Error(`launch failed to start \"${value}\"`));\n return;\n }\n settled = true;\n child.unref();\n resolve({ pid: child.pid, command, args: spawnArgs });\n });\n });\n}\n\n/** Result of a kill — the resolved target and how it was addressed. */\nexport interface KillResult {\n target: string;\n /** Numeric pid when the target was a pid; omitted for a process-name kill. */\n pid?: number;\n killed: true;\n}\n\n/**\n * Terminate a running application by pid (all-digits) or process name\n * (#9170 — trycua/cua `kill_app`). Pairs with `launchApp`. Destructive, so it\n * routes through the approval manager like every other non-read verb. Uses\n * `execFile` (no shell) so the target can't inject a command.\n *\n * - Windows: `taskkill /F /PID <n>` or `/F /IM <name>.exe`.\n * - macOS / Linux: `kill -9 <pid>` or `pkill -f <name>`.\n *\n * Rejects when the target does not exist (non-zero exit) so the caller gets\n * clear feedback rather than a silent no-op.\n */\nexport function killApp(target: string): Promise<KillResult> {\n const value = String(target ?? \"\").trim();\n if (!value) {\n return Promise.reject(\n new Error(\"kill_app requires a non-empty target (pid or app name)\"),\n );\n }\n const isPid = /^\\d+$/.test(value);\n const os = currentPlatform();\n let command: string;\n let args: string[];\n if (os === \"win32\") {\n command = \"taskkill\";\n args = isPid\n ? [\"/F\", \"/PID\", value]\n : [\"/F\", \"/IM\", value.toLowerCase().endsWith(\".exe\") ? value : `${value}.exe`];\n } else if (os === \"darwin\" || os === \"linux\") {\n if (isPid) {\n command = \"kill\";\n args = [\"-9\", value];\n } else {\n command = \"pkill\";\n args = [\"-f\", value];\n }\n } else {\n return Promise.reject(new Error(`kill_app unsupported on platform \"${os}\"`));\n }\n return new Promise<KillResult>((resolve, reject) => {\n execFile(command, args, { timeout: OPEN_TIMEOUT_MS }, (err) => {\n if (err) {\n reject(\n new Error(\n `kill_app failed for \"${value}\": ${err.message} (target may not be running)`,\n ),\n );\n } else {\n resolve({ target: value, ...(isPid ? { pid: Number(value) } : {}), killed: true });\n }\n });\n });\n}\n",
|
|
48
|
+
"import { execFile } from \"node:child_process\";\nimport os from \"node:os\";\nimport type { TerminalActionResult } from \"../types.js\";\nimport { checkDangerousCommand, sanitizeChildEnv } from \"./security.js\";\n\nexport type TerminalSession = {\n id: string;\n cwd: string;\n createdAt: string;\n lastOutput?: string;\n};\n\nconst sessions = new Map<string, TerminalSession>();\nlet sessionCounter = 0;\nlet lastOutputBuffer = \"\";\n\nfunction truncateOutput(output: string): string {\n return output.slice(0, 5000);\n}\n\nfunction resolveShell(): {\n command: string;\n argsFor: (command: string) => string[];\n} {\n if (process.platform === \"win32\") {\n return {\n command: \"powershell.exe\",\n argsFor: (command) => [\"-NoProfile\", \"-Command\", command],\n };\n }\n\n return {\n command: \"/bin/bash\",\n argsFor: (command) => [\"-c\", command],\n };\n}\n\nexport function connectTerminal(\n arg?: string | { cwd?: string },\n): TerminalActionResult {\n const cwd = typeof arg === \"string\" ? arg : arg?.cwd;\n const sessionId = `term_${++sessionCounter}`;\n const sessionCwd = cwd || os.homedir();\n sessions.set(sessionId, {\n id: sessionId,\n cwd: sessionCwd,\n createdAt: new Date().toISOString(),\n });\n return {\n success: true,\n sessionId,\n session_id: sessionId,\n cwd: sessionCwd,\n message: `Terminal session ${sessionId} created.`,\n };\n}\n\nexport async function executeTerminal(params: {\n command: string;\n timeoutSeconds?: number;\n sessionId?: string;\n cwd?: string;\n}): Promise<TerminalActionResult> {\n const risk = checkDangerousCommand(params.command);\n if (risk.blocked) {\n return {\n success: false,\n output: \"\",\n exitCode: -1,\n error: risk.reason,\n };\n }\n\n const shell = resolveShell();\n const sessionCwd =\n (params.sessionId ? sessions.get(params.sessionId)?.cwd : undefined) ||\n params.cwd ||\n os.homedir();\n const timeoutSeconds = params.timeoutSeconds ?? 30;\n\n return await new Promise<TerminalActionResult>((resolve) => {\n const child = execFile(\n shell.command,\n shell.argsFor(params.command),\n {\n cwd: sessionCwd,\n timeout: timeoutSeconds * 1000,\n maxBuffer: 1024 * 1024,\n env: sanitizeChildEnv(),\n },\n (error, stdout, stderr) => {\n const output = truncateOutput(\n `${stdout}${stderr ? `\\n${stderr}` : \"\"}`,\n );\n lastOutputBuffer = output;\n if (params.sessionId) {\n const existing = sessions.get(params.sessionId);\n if (existing) {\n existing.lastOutput = output;\n }\n }\n if (!error) {\n resolve({\n success: true,\n output,\n exitCode: 0,\n exit_code: 0,\n cwd: sessionCwd,\n sessionId: params.sessionId,\n session_id: params.sessionId,\n });\n return;\n }\n\n const exitCode =\n typeof error.code === \"number\" ? error.code : error.killed ? -1 : 1;\n resolve({\n success: false,\n output,\n exitCode,\n exit_code: exitCode,\n cwd: sessionCwd,\n sessionId: params.sessionId,\n session_id: params.sessionId,\n error: error.message,\n });\n },\n );\n\n const killTimer = setTimeout(\n () => {\n child.kill(\"SIGKILL\");\n resolve({\n success: false,\n output: \"\",\n exitCode: -1,\n exit_code: -1,\n cwd: sessionCwd,\n sessionId: params.sessionId,\n session_id: params.sessionId,\n error: `Command timed out after ${timeoutSeconds}s.`,\n });\n },\n (timeoutSeconds + 1) * 1000,\n );\n\n child.once(\"exit\", () => {\n clearTimeout(killTimer);\n });\n });\n}\n\nexport function readTerminal(\n arg?: string | { session_id?: string; sessionId?: string },\n): TerminalActionResult {\n const sessionId =\n typeof arg === \"string\" ? arg : (arg?.session_id ?? arg?.sessionId);\n const output =\n (sessionId ? sessions.get(sessionId)?.lastOutput : undefined) ??\n lastOutputBuffer;\n return {\n success: true,\n sessionId,\n session_id: sessionId,\n output,\n message: output.length > 0 ? undefined : \"No pending terminal output.\",\n };\n}\n\nexport function typeTerminal(\n arg: string | { text: string; session_id?: string; sessionId?: string },\n): TerminalActionResult {\n const text = typeof arg === \"string\" ? arg : arg.text;\n const sessionId =\n typeof arg === \"string\" ? undefined : (arg.session_id ?? arg.sessionId);\n return {\n success: true,\n sessionId,\n session_id: sessionId,\n message: `queued terminal text: ${text.slice(0, 50)}`,\n };\n}\n\nexport function clearTerminal(\n arg?: string | { session_id?: string; sessionId?: string },\n): TerminalActionResult {\n const sessionId =\n typeof arg === \"string\" ? arg : (arg?.session_id ?? arg?.sessionId);\n return {\n success: true,\n sessionId,\n session_id: sessionId,\n message: \"Terminal cleared.\",\n };\n}\n\nexport function closeTerminal(\n arg?: string | { session_id?: string; sessionId?: string },\n): TerminalActionResult {\n const sessionId =\n typeof arg === \"string\" ? arg : (arg?.session_id ?? arg?.sessionId);\n if (sessionId) {\n sessions.delete(sessionId);\n } else {\n sessions.clear();\n }\n\n return {\n success: true,\n sessionId,\n session_id: sessionId,\n message: `Terminal session ${sessionId ?? \"default\"} closed.`,\n };\n}\n\nexport function closeAllTerminalSessions(): void {\n sessions.clear();\n}\n\nexport function listTerminalSessions(): TerminalSession[] {\n return Array.from(sessions.values());\n}\n\n/** Alias of executeTerminal — upstream calls it execute_command. */\nexport const executeCommand = executeTerminal;\n",
|
|
49
|
+
"/**\n * Cross-platform window listing and management.\n *\n * Ported from:\n * - coasty-ai/open-computer-use local-executor.ts window handlers (Apache 2.0)\n * - eliza sandbox-routes.ts listWindows()\n */\n\nimport { execSync } from \"node:child_process\";\nimport type { ScreenRegion, ScreenSize, WindowInfo } from \"../types.js\";\nimport {\n commandExists,\n currentPlatform,\n runCommand,\n validateInt,\n validateWindowId,\n} from \"./helpers.js\";\n\nfunction escapeAppleScriptString(value: string): string {\n return value.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\n}\n\nfunction normalizeWindowQuery(value: string): string {\n return value.trim().toLowerCase();\n}\n\nfunction matchesWindowQuery(win: WindowInfo, query: string): boolean {\n const normalized = normalizeWindowQuery(query);\n if (!normalized) return false;\n\n return [win.id, win.title, win.app].some((field) =>\n normalizeWindowQuery(field).includes(normalized),\n );\n}\n\nexport function findWindowsByQuery(\n query: string,\n windows: WindowInfo[] = listWindows(),\n): WindowInfo[] {\n const normalized = normalizeWindowQuery(query);\n if (!normalized) return [];\n\n const exact = windows.filter(\n (win) => normalizeWindowQuery(win.id) === normalized,\n );\n if (exact.length > 0) return exact;\n\n return windows.filter((win) => matchesWindowQuery(win, normalized));\n}\n\nfunction resolveWindowTarget(queryOrId: string): WindowInfo | null {\n const matches = findWindowsByQuery(queryOrId);\n return matches[0] ?? null;\n}\n\nfunction resolveWindowTargetOrThrow(queryOrId: string): WindowInfo {\n const target = resolveWindowTarget(queryOrId);\n if (!target) {\n throw new Error(`Window not found: ${queryOrId}`);\n }\n return target;\n}\n\nfunction resolveWindowCommandId(queryOrId: string): string {\n const target = resolveWindowTarget(queryOrId);\n return validateWindowId(target?.id ?? queryOrId);\n}\n\nexport function resolveWindowMatch(\n queryOrId: string,\n windows: WindowInfo[] = listWindows(),\n): WindowInfo | null {\n return findWindowsByQuery(queryOrId, windows)[0] ?? null;\n}\n\nfunction appleScriptWindowMatchTerms(target: WindowInfo): string[] {\n return [target.id, target.title, target.app]\n .map((value) => normalizeWindowQuery(value))\n .filter((value) => value.length > 0 && value !== \"unknown\");\n}\n\nfunction runDarwinWindowScript(target: WindowInfo, body: string): string {\n const terms = appleScriptWindowMatchTerms(target);\n const termList =\n terms.length > 0\n ? `{${terms.map((term) => `\"${escapeAppleScriptString(term)}\"`).join(\", \")}}`\n : \"{}\";\n const script = `\n tell application \"System Events\"\n repeat with proc in (every process whose visible is true)\n try\n set procName to name of proc\n set matched to false\n repeat with term in ${termList}\n if procName contains term then\n set matched to true\n exit repeat\n end if\n end repeat\n if not matched then\n repeat with w in (every window of proc)\n set winName to name of w\n repeat with term in ${termList}\n if winName contains term then\n set matched to true\n exit repeat\n end if\n end repeat\n if matched then exit repeat\n end repeat\n end if\n if matched then\n ${body}\n exit repeat\n end if\n end try\n end repeat\n end tell`;\n\n return runCommand(\"osascript\", [\"-e\", script], 5000);\n}\n\n// ── List Windows ────────────────────────────────────────────────────────────\n\nexport function listWindows(): WindowInfo[] {\n const os = currentPlatform();\n\n if (os === \"darwin\") {\n return listWindowsDarwin();\n }\n if (os === \"linux\") {\n return listWindowsLinux();\n }\n if (os === \"win32\") {\n return listWindowsWindows();\n }\n return [];\n}\n\nfunction listWindowsDarwin(): WindowInfo[] {\n try {\n const script = `\n tell application \"System Events\"\n set windowList to {}\n repeat with proc in (every process whose visible is true)\n try\n repeat with w in (every window of proc)\n set end of windowList to (name of proc) & \"|||\" & (name of w) & \"|||\" & (id of w as text)\n end repeat\n end try\n end repeat\n return windowList as text\n end tell`;\n const output = execSync(`osascript -e '${script}'`, {\n encoding: \"utf-8\",\n timeout: 10000,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n });\n return output\n .split(\", \")\n .filter(Boolean)\n .map((entry) => {\n const parts = entry.split(\"|||\");\n return {\n app: parts[0] ?? \"unknown\",\n title: parts[1] ?? \"unknown\",\n id: parts[2] ?? \"0\",\n };\n });\n } catch {\n return [];\n }\n}\n\nfunction listWindowsLinux(): WindowInfo[] {\n try {\n if (commandExists(\"wmctrl\")) {\n const output = execSync(\"wmctrl -l\", {\n encoding: \"utf-8\",\n timeout: 5000,\n });\n return output\n .split(\"\\n\")\n .filter(Boolean)\n .map((line) => {\n // wmctrl format: 0x0400000a 0 hostname Title\n const parts = line.trim().split(/\\s+/);\n const id = parts[0] ?? \"0\";\n const title = parts.slice(3).join(\" \") || \"unknown\";\n return { id, title, app: \"unknown\" };\n });\n }\n const output = execSync(\n 'xdotool search --name \"\" getwindowname 2>/dev/null || true',\n { encoding: \"utf-8\", timeout: 5000 },\n );\n return output\n .split(\"\\n\")\n .filter(Boolean)\n .map((line, i) => ({\n id: String(i),\n title: line.trim(),\n app: \"unknown\",\n }));\n } catch {\n return [];\n }\n}\n\nfunction listWindowsWindows(): WindowInfo[] {\n try {\n const output = execSync(\n `powershell -Command \"Get-Process | Where-Object {$_.MainWindowTitle} | Select-Object Id, MainWindowTitle | ConvertTo-Json\"`,\n { encoding: \"utf-8\", timeout: 10000 },\n );\n const parsed = JSON.parse(output);\n const list = Array.isArray(parsed) ? parsed : [parsed];\n return list.map((p: { Id: number; MainWindowTitle: string }) => ({\n id: String(p.Id),\n title: p.MainWindowTitle,\n app: \"unknown\",\n }));\n } catch {\n return [];\n }\n}\n\n// ── Focus Window ────────────────────────────────────────────────────────────\n\n/**\n * The currently-focused / frontmost window (#9170 M12 — cua\n * `get_current_window_id`). Best-effort per-OS query; returns `null` when no\n * window is focused or the platform query is unavailable.\n */\nexport function getActiveWindow(): WindowInfo | null {\n const os = currentPlatform();\n try {\n if (os === \"darwin\") {\n const script = `\n tell application \"System Events\"\n set proc to first process whose frontmost is true\n set procName to name of proc\n try\n set w to window 1 of proc\n return procName & \"|||\" & (name of w) & \"|||\" & (id of w as text)\n on error\n return procName & \"|||\" & \"\" & \"|||\" & \"0\"\n end try\n end tell`;\n const out = execSync(`osascript -e '${script}'`, {\n encoding: \"utf-8\",\n timeout: 8000,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n }).trim();\n const [app, title, id] = out.split(\"|||\");\n if (!app) return null;\n return { id: id || \"0\", title: title ?? \"\", app };\n }\n if (os === \"linux\") {\n if (!commandExists(\"xdotool\")) return null;\n const id = runCommand(\"xdotool\", [\"getactivewindow\"], 5000).trim();\n if (!id) return null;\n const title = runCommand(\"xdotool\", [\"getwindowname\", id], 5000).trim();\n return { id, title, app: title };\n }\n if (os === \"win32\") {\n const ps =\n \"Add-Type 'using System;using System.Runtime.InteropServices;\" +\n 'public class W{[DllImport(\"user32.dll\")]public static extern IntPtr GetForegroundWindow();}\\';' +\n \"$h=[W]::GetForegroundWindow();\" +\n \"$p=Get-Process | Where-Object { $_.MainWindowHandle -eq $h } | Select-Object -First 1;\" +\n 'if($p){ \"$($p.Id)|||$($p.MainWindowTitle)|||$($p.ProcessName)\" }';\n const out = execSync(\n `powershell -NoProfile -Command \"${ps.replace(/\"/g, '\\\\\"')}\"`,\n {\n encoding: \"utf-8\",\n timeout: 8000,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n },\n ).trim();\n if (!out) return null;\n const [id, title, app] = out.split(\"|||\");\n if (!id) return null;\n return { id, title: title ?? \"\", app: app ?? \"\" };\n }\n } catch {\n return null;\n }\n return null;\n}\n\n/**\n * Windows belonging to a given application name (#9170 M12 — cua\n * `get_application_windows`). Pure filter over `listWindows()`; case-insensitive\n * substring match on the window's `app` (with a `title` fallback).\n */\nexport function getApplicationWindows(appName: string): WindowInfo[] {\n const needle = normalizeWindowQuery(appName);\n if (!needle) return [];\n return listWindows().filter(\n (w) =>\n normalizeWindowQuery(w.app).includes(needle) ||\n normalizeWindowQuery(w.title).includes(needle),\n );\n}\n\n/**\n * Set a window's position AND size in one call (#9170 M12 — cua set window\n * size+position). Position is required; width/height optional (position-only\n * when omitted).\n */\nexport function resizeWindow(\n windowId: string,\n x: number,\n y: number,\n width?: number,\n height?: number,\n): { success: true; message: string } {\n if (typeof x !== \"number\" || typeof y !== \"number\") {\n throw new Error(\"x and y are required for window set_bounds\");\n }\n setWindowBounds(windowId, x, y, width, height);\n const size =\n width !== undefined && height !== undefined\n ? ` size (${validateInt(width)}x${validateInt(height)})`\n : \"\";\n return {\n success: true,\n message: `Set window to (${validateInt(x)}, ${validateInt(y)})${size}.`,\n };\n}\n\n/**\n * Read a window's bounds — position AND size — in OS-global logical pixels\n * (#9170 M12 — cua `get_window_size` / `get_window_position`). When `windowId`\n * is omitted, reads the currently-focused/foreground window. Returns\n * `{ x, y, width, height }`.\n *\n * Windows: `GetWindowRect` via the window's `MainWindowHandle`. macOS: AppleScript\n * `position`/`size` of the matched process window. Linux: `xdotool\n * getwindowgeometry --shell`.\n */\nexport function getWindowBounds(windowId?: string): ScreenRegion {\n const os = currentPlatform();\n const id = windowId ?? getActiveWindow()?.id;\n if (!id) {\n throw new Error(\n \"No windowId provided and no active window to read bounds from\",\n );\n }\n\n if (os === \"darwin\") {\n const target = resolveWindowTargetOrThrow(id);\n const out = runDarwinWindowScript(\n target,\n `set winPos to position of window 1 of proc\n set winSize to size of window 1 of proc\n return ((item 1 of winPos) as text) & \",\" & ((item 2 of winPos) as text) & \",\" & ((item 1 of winSize) as text) & \",\" & ((item 2 of winSize) as text)`,\n ).trim();\n const [x, y, width, height] = out.split(\",\").map((v) => Number(v.trim()));\n if ([x, y, width, height].some((n) => !Number.isFinite(n))) {\n throw new Error(`Could not read window bounds for: ${id}`);\n }\n return { x, y, width, height };\n }\n\n if (os === \"linux\") {\n if (!commandExists(\"xdotool\")) {\n throw new Error(\"getWindowBounds requires xdotool on Linux\");\n }\n const commandId = resolveWindowCommandId(id);\n const out = runCommand(\n \"xdotool\",\n [\"getwindowgeometry\", \"--shell\", commandId],\n 5000,\n );\n const mx = /X=(-?\\d+)/.exec(out);\n const my = /Y=(-?\\d+)/.exec(out);\n const mw = /WIDTH=(\\d+)/.exec(out);\n const mh = /HEIGHT=(\\d+)/.exec(out);\n if (!mx || !my || !mw || !mh) {\n throw new Error(`Could not parse xdotool geometry for: ${id}`);\n }\n return {\n x: validateInt(Number(mx[1])),\n y: validateInt(Number(my[1])),\n width: validateInt(Number(mw[1])),\n height: validateInt(Number(mh[1])),\n };\n }\n\n if (os === \"win32\") {\n const commandId = resolveWindowCommandId(id);\n // GetWindowRect via the process MainWindowHandle. Uses -MemberDefinition\n // (signed-assembly P/Invoke, NOT a runtime-compiled inline class) to declare\n // the RECT struct + the import together; see desktop.ts / setWindowBounds.\n // NOTE: do NOT pass -UsingNamespace System.Runtime.InteropServices — Add-Type\n // already imports it for the DllImport attribute, and a duplicate using is a\n // warning-as-error that silently fails the type and yields a zeroed rect.\n const ps = `\n Add-Type -MemberDefinition '[StructLayout(LayoutKind.Sequential)] public struct RECT { public int Left; public int Top; public int Right; public int Bottom; } [DllImport(\"user32.dll\")] public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);' -Name Win32Rect -Namespace Win32\n $proc = Get-Process -Id ${commandId} -ErrorAction SilentlyContinue\n if (-not $proc) { throw \"Window not found: ${commandId}\" }\n $r = New-Object \"Win32.Win32Rect+RECT\"\n [void][Win32.Win32Rect]::GetWindowRect($proc.MainWindowHandle, [ref]$r)\n \"$($r.Left),$($r.Top),$($r.Right),$($r.Bottom)\"\n `;\n // 10s: the first Add-Type call JIT-compiles the P/Invoke shim (cold csc),\n // which can exceed the 5s used elsewhere when the box is under load.\n const out = runCommand(\"powershell\", [\"-Command\", ps], 10000).trim();\n const [left, top, right, bottom] = out.split(\",\").map((v) => Number(v.trim()));\n if ([left, top, right, bottom].some((n) => !Number.isFinite(n))) {\n throw new Error(`Could not read window bounds for: ${id}`);\n }\n return {\n x: left,\n y: top,\n width: Math.max(0, right - left),\n height: Math.max(0, bottom - top),\n };\n }\n\n throw new Error(`getWindowBounds is not supported on ${os}`);\n}\n\nexport function focusWindow(windowId: string): void {\n const os = currentPlatform();\n const target = resolveWindowTarget(windowId);\n\n if (os === \"darwin\") {\n const commandTarget = target ?? resolveWindowTargetOrThrow(windowId);\n try {\n runDarwinWindowScript(commandTarget, \"set frontmost of proc to true\");\n } catch {\n runCommand(\n \"osascript\",\n [\n \"-e\",\n `tell application \"${escapeAppleScriptString(commandTarget.app)}\" to activate`,\n ],\n 5000,\n );\n }\n } else if (os === \"linux\") {\n const commandId = resolveWindowCommandId(windowId);\n if (commandExists(\"wmctrl\")) {\n runCommand(\"wmctrl\", [\"-i\", \"-a\", commandId], 5000);\n } else if (commandExists(\"xdotool\")) {\n runCommand(\"xdotool\", [\"windowactivate\", commandId], 5000);\n } else {\n throw new Error(\"Window focus requires wmctrl or xdotool on Linux\");\n }\n } else if (os === \"win32\") {\n const commandId = resolveWindowCommandId(windowId);\n const ps = `\n Add-Type -MemberDefinition '[DllImport(\"user32.dll\")] public static extern bool SetForegroundWindow(IntPtr hWnd);' -Name Win32 -Namespace Win32\n $proc = Get-Process -Id ${commandId} -ErrorAction SilentlyContinue\n if (-not $proc) { throw \"Window not found: ${commandId}\" }\n [Win32.Win32]::SetForegroundWindow($proc.MainWindowHandle)\n `;\n runCommand(\"powershell\", [\"-Command\", ps], 5000);\n }\n}\n\nexport function switchWindow(windowQuery: string): void {\n focusWindow(windowQuery);\n}\n\nfunction setWindowBounds(\n windowId: string,\n x: number,\n y: number,\n width?: number,\n height?: number,\n): void {\n const safeX = validateInt(x);\n const safeY = validateInt(y);\n const safeWidth =\n width === undefined ? undefined : Math.max(1, validateInt(width));\n const safeHeight =\n height === undefined ? undefined : Math.max(1, validateInt(height));\n const os = currentPlatform();\n\n if (os === \"darwin\") {\n const target = resolveWindowTargetOrThrow(windowId);\n runDarwinWindowScript(\n target,\n `\n set position of window 1 of proc to {${safeX}, ${safeY}}\n ${\n safeWidth !== undefined && safeHeight !== undefined\n ? `set size of window 1 of proc to {${safeWidth}, ${safeHeight}}`\n : \"\"\n }`,\n );\n return;\n }\n\n const commandId = resolveWindowCommandId(windowId);\n if (os === \"linux\") {\n if (commandExists(\"wmctrl\")) {\n runCommand(\n \"wmctrl\",\n [\n \"-i\",\n \"-r\",\n commandId,\n \"-e\",\n `0,${safeX},${safeY},${safeWidth ?? -1},${safeHeight ?? -1}`,\n ],\n 5000,\n );\n return;\n }\n if (commandExists(\"xdotool\")) {\n runCommand(\n \"xdotool\",\n [\"windowmove\", commandId, String(safeX), String(safeY)],\n 5000,\n );\n if (safeWidth !== undefined && safeHeight !== undefined) {\n runCommand(\n \"xdotool\",\n [\"windowsize\", commandId, String(safeWidth), String(safeHeight)],\n 5000,\n );\n }\n return;\n }\n throw new Error(\"Window move requires wmctrl or xdotool on Linux\");\n }\n\n if (os === \"win32\") {\n const noSizeFlag =\n safeWidth === undefined || safeHeight === undefined ? \"0x0001\" : \"0\";\n const widthArg = safeWidth ?? 0;\n const heightArg = safeHeight ?? 0;\n const ps = `\n Add-Type -MemberDefinition '[DllImport(\"user32.dll\")] public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);' -Name Win32 -Namespace Win32\n $proc = Get-Process -Id ${commandId} -ErrorAction SilentlyContinue\n if (-not $proc) { throw \"Window not found: ${commandId}\" }\n [Win32.Win32]::SetWindowPos($proc.MainWindowHandle, [IntPtr]::Zero, ${safeX}, ${safeY}, ${widthArg}, ${heightArg}, ${noSizeFlag})\n `;\n runCommand(\"powershell\", [\"-Command\", ps], 5000);\n return;\n }\n\n throw new Error(`Window move is not supported on ${os}`);\n}\n\nexport function arrangeWindows(arrangement = \"tile\"): {\n success: true;\n message: string;\n} {\n const windows = listWindows();\n if (windows.length === 0) {\n return {\n success: true,\n message: \"No visible windows found to arrange.\",\n };\n }\n\n const screen = getScreenSize();\n const normalized = arrangement.trim().toLowerCase();\n const count = windows.length;\n const cascadeOffset = 32;\n\n windows.forEach((windowInfo, index) => {\n if (normalized === \"cascade\") {\n const width = Math.max(480, Math.floor(screen.width * 0.72));\n const height = Math.max(360, Math.floor(screen.height * 0.72));\n const maxOffsetX = Math.max(0, screen.width - width);\n const maxOffsetY = Math.max(0, screen.height - height);\n setWindowBounds(\n windowInfo.id,\n Math.min(index * cascadeOffset, maxOffsetX),\n Math.min(index * cascadeOffset, maxOffsetY),\n width,\n height,\n );\n return;\n }\n\n if (normalized === \"vertical\") {\n const width = Math.max(1, Math.floor(screen.width / count));\n setWindowBounds(windowInfo.id, index * width, 0, width, screen.height);\n return;\n }\n\n if (normalized === \"horizontal\") {\n const height = Math.max(1, Math.floor(screen.height / count));\n setWindowBounds(windowInfo.id, 0, index * height, screen.width, height);\n return;\n }\n\n const columns = Math.ceil(Math.sqrt(count));\n const rows = Math.ceil(count / columns);\n const width = Math.max(1, Math.floor(screen.width / columns));\n const height = Math.max(1, Math.floor(screen.height / rows));\n const column = index % columns;\n const row = Math.floor(index / columns);\n setWindowBounds(windowInfo.id, column * width, row * height, width, height);\n });\n\n return {\n success: true,\n message: `Arranged ${windows.length} window${windows.length === 1 ? \"\" : \"s\"} using ${normalized || \"tile\"} layout.`,\n };\n}\n\nexport function moveWindow(\n windowId: string,\n x?: number,\n y?: number,\n): {\n success: true;\n message: string;\n} {\n if (typeof x !== \"number\" || typeof y !== \"number\") {\n throw new Error(\"x and y are required for window move\");\n }\n setWindowBounds(windowId, x, y);\n return {\n success: true,\n message: `Moved window to (${validateInt(x)}, ${validateInt(y)}).`,\n };\n}\n\n// ── Minimize Window ─────────────────────────────────────────────────────────\n\nexport function minimizeWindow(windowId: string): void {\n const os = currentPlatform();\n const target = resolveWindowTarget(windowId);\n\n if (os === \"darwin\") {\n runDarwinWindowScript(\n target ?? resolveWindowTargetOrThrow(windowId),\n \"set miniaturized of window 1 of proc to true\",\n );\n } else if (os === \"linux\") {\n const commandId = resolveWindowCommandId(windowId);\n if (commandExists(\"xdotool\")) {\n runCommand(\"xdotool\", [\"windowminimize\", commandId], 5000);\n } else {\n throw new Error(\"Window minimize requires xdotool on Linux\");\n }\n } else if (os === \"win32\") {\n const commandId = resolveWindowCommandId(windowId);\n const ps = `\n Add-Type -MemberDefinition '[DllImport(\"user32.dll\")] public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);' -Name Win32 -Namespace Win32\n $proc = Get-Process -Id ${commandId} -ErrorAction SilentlyContinue\n if (-not $proc) { throw \"Window not found: ${commandId}\" }\n [Win32.Win32]::ShowWindow($proc.MainWindowHandle, 6)\n `;\n runCommand(\"powershell\", [\"-Command\", ps], 5000);\n }\n}\n\n// ── Maximize Window ─────────────────────────────────────────────────────────\n\nexport function maximizeWindow(windowId: string): void {\n const os = currentPlatform();\n const target = resolveWindowTarget(windowId);\n\n if (os === \"darwin\") {\n runDarwinWindowScript(\n target ?? resolveWindowTargetOrThrow(windowId),\n 'set value of attribute \"AXFullScreen\" of window 1 of proc to true',\n );\n } else if (os === \"linux\") {\n const commandId = resolveWindowCommandId(windowId);\n if (commandExists(\"wmctrl\")) {\n runCommand(\n \"wmctrl\",\n [\"-i\", \"-r\", commandId, \"-b\", \"add,maximized_vert,maximized_horz\"],\n 5000,\n );\n } else {\n throw new Error(\"Window maximize requires wmctrl on Linux\");\n }\n } else if (os === \"win32\") {\n const commandId = resolveWindowCommandId(windowId);\n const ps = `\n Add-Type -MemberDefinition '[DllImport(\"user32.dll\")] public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);' -Name Win32 -Namespace Win32\n $proc = Get-Process -Id ${commandId} -ErrorAction SilentlyContinue\n if (-not $proc) { throw \"Window not found: ${commandId}\" }\n [Win32.Win32]::ShowWindow($proc.MainWindowHandle, 3)\n `;\n runCommand(\"powershell\", [\"-Command\", ps], 5000);\n }\n}\n\nexport function restoreWindow(windowId: string): void {\n const os = currentPlatform();\n const target = resolveWindowTarget(windowId);\n\n if (os === \"darwin\") {\n runDarwinWindowScript(\n target ?? resolveWindowTargetOrThrow(windowId),\n `\n try\n set miniaturized of window 1 of proc to false\n end try\n set frontmost of proc to true`,\n );\n } else if (os === \"linux\") {\n const commandId = resolveWindowCommandId(windowId);\n if (commandExists(\"wmctrl\")) {\n runCommand(\n \"wmctrl\",\n [\"-i\", \"-r\", commandId, \"-b\", \"remove,maximized_vert,maximized_horz\"],\n 5000,\n );\n runCommand(\"wmctrl\", [\"-i\", \"-a\", commandId], 5000);\n } else if (commandExists(\"xdotool\")) {\n runCommand(\"xdotool\", [\"windowactivate\", commandId], 5000);\n } else {\n throw new Error(\"Window restore requires wmctrl or xdotool on Linux\");\n }\n } else if (os === \"win32\") {\n const commandId = resolveWindowCommandId(windowId);\n const ps = `\n Add-Type -MemberDefinition '[DllImport(\"user32.dll\")] public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);' -Name Win32 -Namespace Win32\n $proc = Get-Process -Id ${commandId} -ErrorAction SilentlyContinue\n if (-not $proc) { throw \"Window not found: ${commandId}\" }\n [Win32.Win32]::ShowWindow($proc.MainWindowHandle, 9)\n `;\n runCommand(\"powershell\", [\"-Command\", ps], 5000);\n }\n}\n\n// ── Close Window ────────────────────────────────────────────────────────────\n\nexport function closeWindow(windowId: string): void {\n const os = currentPlatform();\n const target = resolveWindowTarget(windowId);\n\n if (os === \"darwin\") {\n runDarwinWindowScript(\n target ?? resolveWindowTargetOrThrow(windowId),\n \"click button 1 of window 1 of proc\",\n );\n } else if (os === \"linux\") {\n const commandId = resolveWindowCommandId(windowId);\n if (commandExists(\"wmctrl\")) {\n runCommand(\"wmctrl\", [\"-i\", \"-c\", commandId], 5000);\n } else if (commandExists(\"xdotool\")) {\n runCommand(\"xdotool\", [\"windowclose\", commandId], 5000);\n } else {\n throw new Error(\"Window close requires wmctrl or xdotool on Linux\");\n }\n } else if (os === \"win32\") {\n const commandId = resolveWindowCommandId(windowId);\n const ps = `Stop-Process -Id ${commandId} -ErrorAction SilentlyContinue`;\n runCommand(\"powershell\", [\"-Command\", ps], 5000);\n }\n}\n\nexport const list_windows = listWindows;\nexport const focus_window = focusWindow;\nexport const switch_to_window = switchWindow;\nexport const arrange_windows = arrangeWindows;\nexport const move_window = moveWindow;\nexport const minimize_window = minimizeWindow;\nexport const maximize_window = maximizeWindow;\nexport const restore_window = restoreWindow;\nexport const close_window = closeWindow;\n\n// ── Screen Size ─────────────────────────────────────────────────────────────\n\n/**\n * PowerShell command that reads the primary screen bounds on Windows.\n *\n * `Add-Type -AssemblyName System.Windows.Forms` MUST run before\n * `[System.Windows.Forms.Screen]` is referenced — on a clean PowerShell session\n * the type is otherwise unresolved (`TypeNotFound`) and the screen size silently\n * falls back to a hard-coded default. Exported so a cross-platform unit test can\n * guard against the assembly-load regression without spawning PowerShell.\n */\nexport const WINDOWS_PRIMARY_SCREEN_SIZE_COMMAND =\n 'powershell -NoProfile -Command \"Add-Type -AssemblyName System.Windows.Forms; ' +\n '[System.Windows.Forms.Screen]::PrimaryScreen.Bounds | ConvertTo-Json -Compress\"';\n\nexport function getScreenSize(): ScreenSize {\n const os = currentPlatform();\n\n if (os === \"darwin\") {\n try {\n const output = execSync(\n `osascript -l JavaScript -e 'ObjC.import(\"CoreGraphics\"); const bounds = $.CGDisplayBounds($.CGMainDisplayID()); String(Math.round(bounds.size.width)) + \",\" + String(Math.round(bounds.size.height));'`,\n { encoding: \"utf-8\", timeout: 3000 },\n );\n const [width, height] = output\n .trim()\n .split(\",\")\n .map((part) => Number.parseInt(part.trim(), 10));\n if (\n Number.isFinite(width) &&\n Number.isFinite(height) &&\n width > 0 &&\n height > 0\n ) {\n return { width, height };\n }\n } catch {\n /* fallback */\n }\n try {\n const output = execSync(\n `osascript -e 'tell application \"Finder\" to get bounds of window of desktop'`,\n { encoding: \"utf-8\", timeout: 5000 },\n );\n // Returns: \"0, 0, 2560, 1440\"\n const parts = output\n .trim()\n .split(\",\")\n .map((p) => Number.parseInt(p.trim(), 10));\n const width = parts[2];\n const height = parts[3];\n if (Number.isFinite(width) && Number.isFinite(height)) {\n return { width, height };\n }\n } catch {\n /* fallback */\n }\n // Fallback: system_profiler\n try {\n const output = execSync(\n \"system_profiler SPDisplaysDataType 2>/dev/null | grep Resolution\",\n { encoding: \"utf-8\", timeout: 5000 },\n );\n const match = output.match(/(\\d+)\\s*x\\s*(\\d+)/);\n if (match) {\n const [, width, height] = match;\n if (width === undefined || height === undefined) {\n return { width: 1920, height: 1080 };\n }\n return {\n width: Number.parseInt(width, 10),\n height: Number.parseInt(height, 10),\n };\n }\n } catch {\n /* fallback */\n }\n return { width: 1920, height: 1080 };\n }\n\n if (os === \"linux\") {\n if (commandExists(\"xdotool\")) {\n try {\n const output = runCommand(\"xdotool\", [\"getdisplaygeometry\"], 3000);\n const parts = output.trim().split(\" \");\n const [width, height] = parts;\n if (width !== undefined && height !== undefined) {\n return {\n width: Number.parseInt(width, 10),\n height: Number.parseInt(height, 10),\n };\n }\n } catch {\n /* fallback */\n }\n }\n if (commandExists(\"xrandr\")) {\n try {\n const output = execSync(\"xrandr 2>/dev/null | grep '*'\", {\n encoding: \"utf-8\",\n timeout: 5000,\n });\n const match = output.match(/(\\d+)x(\\d+)/);\n if (match) {\n const [, width, height] = match;\n if (width === undefined || height === undefined) {\n return { width: 1920, height: 1080 };\n }\n return {\n width: Number.parseInt(width, 10),\n height: Number.parseInt(height, 10),\n };\n }\n } catch {\n /* fallback */\n }\n }\n return { width: 1920, height: 1080 };\n }\n\n if (os === \"win32\") {\n try {\n const output = execSync(WINDOWS_PRIMARY_SCREEN_SIZE_COMMAND, {\n encoding: \"utf-8\",\n timeout: 5000,\n });\n const bounds = JSON.parse(output);\n if (\n typeof bounds?.Width === \"number\" &&\n typeof bounds?.Height === \"number\" &&\n bounds.Width > 0 &&\n bounds.Height > 0\n ) {\n return { width: bounds.Width, height: bounds.Height };\n }\n } catch {\n /* fallback */\n }\n return { width: 1920, height: 1080 };\n }\n\n return { width: 1920, height: 1080 };\n}\n",
|
|
50
|
+
"/**\n * WS6 — Scene Builder\n *\n * Produces a single compact `Scene` JSON object per scene update. The runtime\n * lifecycle is:\n *\n * 1. Idle poll @ 1 Hz — capture each display, compute frame dHash.\n * If no change observed for >2s, skip OCR + AX.\n * 2. Active poll @ 4 Hz — capture, dHash, block-grid diff, run OCR on\n * the dirty blocks only, fold in AX snapshot.\n * 3. Agent turn (onAgentTurn) — full pipeline including the WS7 VLM hook.\n * We surface a clean entry point but do NOT\n * call the VLM here.\n *\n * Caches:\n * - Whole-display scene cache keyed by `(displayId, frameDhash)`, TTL 30s.\n * - Per-display previous BlockGrid kept in memory; dirtied on every active\n * frame.\n * - AX subtree cache: we re-snapshot every agent turn and every active\n * poll when no AX focus-change notifications are available (which is\n * the case on every desktop OS today). The AT-SPI signal route would\n * remove that polling — call out as a follow-up.\n *\n * The builder is dependency-injectable for tests: pass an in-memory\n * `captureDisplays`, `enumerateApps`, `accessibilityProvider`, and OCR adapter\n * to assert pipeline behavior without a real screen.\n */\n\nimport { EventEmitter } from \"node:events\";\nimport type { DisplayCapture } from \"../platform/capture.js\";\nimport {\n captureAllDisplays,\n captureDisplay,\n captureDisplayRegion,\n} from \"../platform/capture.js\";\nimport { findDisplay, listDisplays } from \"../platform/displays.js\";\nimport type { DisplayDescriptor } from \"../types.js\";\nimport {\n type AccessibilityProvider,\n resolveAccessibilityProvider,\n} from \"./a11y-provider.js\";\nimport { enumerateApps } from \"./apps.js\";\nimport {\n type BlockGrid,\n blockGrid,\n coalesceDirtyBlocks,\n diffBlocks,\n frameDhash,\n hamming,\n pngDimensions,\n} from \"./dhash.js\";\nimport {\n makeOcrIdState,\n type OcrAdapterIdState,\n runOcrOnPng,\n runOcrOnRegions,\n setOcrLoggingHook,\n} from \"./ocr-adapter.js\";\nimport type {\n Scene,\n SceneApp,\n SceneAxNode,\n SceneFocusedWindow,\n SceneOcrBox,\n SceneVlmElement,\n} from \"./scene-types.js\";\n\nconst IDLE_THRESHOLD_MS = 2000;\nconst CACHE_TTL_MS = 30_000;\nconst FRAME_HAMMING_THRESHOLD = 5;\n\nexport interface SceneBuilderDeps {\n captureAll?: () => Promise<DisplayCapture[]>;\n captureOne?: (displayId: number) => Promise<DisplayCapture>;\n /**\n * Capture a region within a display in display-local coordinates. Used by\n * the dirty-block re-OCR fast path to avoid full-frame OCR when only a\n * small slice of the screen changed. Default: `captureDisplayRegion`.\n */\n captureRegion?: (\n displayId: number,\n region: { x: number; y: number; width: number; height: number },\n ) => Promise<DisplayCapture>;\n enumerateApps?: () => SceneApp[];\n listDisplays?: () => DisplayDescriptor[];\n accessibilityProvider?: AccessibilityProvider;\n runOcrOnFrame?: (\n png: Buffer,\n displayId: number,\n idState: OcrAdapterIdState,\n ) => Promise<SceneOcrBox[]>;\n /**\n * Run OCR on a list of cropped PNGs, each carrying its display-local bbox.\n * Returned boxes have their bboxes translated back into source-frame\n * display-local coordinates. Default: `runOcrOnRegions`.\n */\n runOcrOnCrops?: (\n crops: Array<{ png: Buffer; bbox: [number, number, number, number] }>,\n displayId: number,\n idState: OcrAdapterIdState,\n ) => Promise<SceneOcrBox[]>;\n log?: (msg: string) => void;\n}\n\ninterface PerDisplayState {\n lastDhash: bigint | null;\n lastChangeAt: number;\n lastBlockGrid: BlockGrid | null;\n lastScene: { scene: Partial<Scene>; cachedAt: number; dhash: bigint | null };\n}\n\nexport interface SceneUpdateEvent {\n scene: Scene;\n reason: \"idle\" | \"active\" | \"agent-turn\";\n}\n\nexport class SceneBuilder extends EventEmitter {\n private readonly deps: Required<Omit<SceneBuilderDeps, \"log\">> & {\n log: (msg: string) => void;\n };\n private readonly perDisplay = new Map<number, PerDisplayState>();\n private readonly ocrIdState: OcrAdapterIdState = makeOcrIdState();\n private latestScene: Scene | null = null;\n private inFlight: Promise<Scene> | null = null;\n\n constructor(deps: SceneBuilderDeps = {}) {\n super();\n const log = deps.log ?? (() => {});\n this.deps = {\n captureAll: deps.captureAll ?? captureAllDisplays,\n captureOne: deps.captureOne ?? captureDisplay,\n enumerateApps: deps.enumerateApps ?? (() => enumerateApps()),\n listDisplays:\n deps.listDisplays ??\n (() =>\n listDisplays().map((d) => ({\n id: d.id,\n bounds: d.bounds,\n scaleFactor: d.scaleFactor,\n primary: d.primary,\n name: d.name,\n }))),\n accessibilityProvider:\n deps.accessibilityProvider ?? resolveAccessibilityProvider(),\n captureRegion:\n deps.captureRegion ??\n ((displayId, region) => captureDisplayRegion(displayId, region)),\n runOcrOnFrame:\n deps.runOcrOnFrame ??\n ((png, displayId, idState) => runOcrOnPng(png, displayId, idState)),\n runOcrOnCrops:\n deps.runOcrOnCrops ??\n ((crops, displayId, idState) =>\n runOcrOnRegions(crops, displayId, idState)),\n log,\n };\n setOcrLoggingHook(log);\n }\n\n /**\n * Pulse the pipeline. Mode chooses how much work to do:\n * - \"idle\" — capture + dHash only; reuses cached OCR/AX if unchanged.\n * - \"active\" — capture + dHash + dirty-block OCR + AX.\n * - \"agent-turn\" — full pipeline; WS7's `onAgentTurn` should call this.\n *\n * Returns the produced Scene. Subscribers are notified after.\n */\n async tick(\n mode: \"idle\" | \"active\" | \"agent-turn\" = \"active\",\n ): Promise<Scene> {\n if (this.inFlight) return this.inFlight;\n const promise = this.run(mode);\n this.inFlight = promise;\n try {\n return await promise;\n } finally {\n this.inFlight = null;\n }\n }\n\n /** Called by WS7 when a real agent turn starts. Always full pipeline. */\n async onAgentTurn(): Promise<Scene> {\n return this.tick(\"agent-turn\");\n }\n\n /** Returns the most recently emitted Scene, or null before first tick. */\n getCurrentScene(): Scene | null {\n return this.latestScene;\n }\n\n /**\n * Populate the VLM annotations on the current scene (#9105 M3). The Brain /\n * DirtyTileDescriber produce `vlm_scene` (a one-paragraph description) and\n * `vlm_elements` (described tiles); these were previously always `null`\n * because nothing ever wrote them. Persisting them here lets the next\n * provider read carry the cheap understanding instead of re-describing, and\n * they survive subsequent ticks via the `latestScene?.vlm_*` pass-through.\n */\n setVlmAnnotations(\n vlmScene: string | null,\n vlmElements: SceneVlmElement[] | null,\n ): void {\n if (!this.latestScene) return;\n this.latestScene = {\n ...this.latestScene,\n vlm_scene: vlmScene,\n vlm_elements: vlmElements,\n };\n }\n\n /** Subscribe to scene updates. Returns an unsubscribe function. */\n subscribe(handler: (event: SceneUpdateEvent) => void): () => void {\n const listener = (event: SceneUpdateEvent): void => handler(event);\n this.on(\"scene\", listener);\n return () => this.off(\"scene\", listener);\n }\n\n // ── internal ──────────────────────────────────────────────────────────────\n\n private async run(mode: \"idle\" | \"active\" | \"agent-turn\"): Promise<Scene> {\n const t0 = Date.now();\n const displays = this.deps.listDisplays();\n const captures = await this.captureWithFallback(displays);\n\n const ocr: SceneOcrBox[] = [];\n for (const capture of captures) {\n const displayId = capture.display.id;\n const state = this.ensureState(displayId);\n const dHash = frameDhash(capture.frame);\n const changed =\n state.lastDhash === null ||\n dHash === null ||\n hamming(state.lastDhash, dHash) >= FRAME_HAMMING_THRESHOLD;\n if (changed) {\n state.lastChangeAt = t0;\n }\n // Agent turns ALWAYS re-OCR — the planner has to see fresh text even\n // if the screen looks pixel-identical (e.g. blinking cursor in a\n // text box that just received an enter key).\n const wholeFrameMatch =\n mode !== \"agent-turn\" &&\n !changed &&\n state.lastScene.dhash !== null &&\n dHash !== null &&\n hamming(state.lastScene.dhash, dHash) < FRAME_HAMMING_THRESHOLD &&\n t0 - state.lastScene.cachedAt < CACHE_TTL_MS;\n\n const idleNow = t0 - state.lastChangeAt > IDLE_THRESHOLD_MS;\n const wantOcr = mode === \"agent-turn\" || (mode === \"active\" && !idleNow);\n\n // Compute block-grid diff up-front so the dirty-block fast path can\n // fire even when the whole-frame dHash is unchanged. A single text\n // field flipping characters typically does not shift the resampled\n // 8×8 frame dHash but does flip one or two 16×16 blocks.\n const grid = wantOcr ? blockGrid(capture.frame) : null;\n const dims = wantOcr ? pngDimensions(capture.frame) : null;\n const dirty =\n wantOcr && grid && state.lastBlockGrid && dims\n ? diffBlocks(state.lastBlockGrid, grid, dims.width, dims.height)\n : null;\n const totalBlocks = grid ? grid.cols * grid.rows : 0;\n const dirtyFraction =\n dirty && totalBlocks > 0 ? dirty.length / totalBlocks : 1;\n const prevOcr = state.lastScene.scene.ocr ?? [];\n\n // 1. Whole-frame match + zero dirty blocks → cache hit.\n if (\n wholeFrameMatch &&\n state.lastScene.scene.ocr &&\n dirty !== null &&\n dirty.length === 0\n ) {\n const cached = state.lastScene.scene.ocr.filter(\n (b) => b.displayId === displayId,\n );\n ocr.push(...cached);\n } else if (wantOcr) {\n // 2. Dirty-block fast path: only re-capture + re-OCR the changed\n // rectangles. We coalesce adjacent dirty blocks so a single\n // changed text field is one OS region capture, not a dozen.\n if (\n dirty &&\n grid &&\n dims &&\n dirtyFraction > 0 &&\n dirtyFraction < 0.5 &&\n prevOcr.length > 0\n ) {\n const rects = coalesceDirtyBlocks(\n dirty,\n grid,\n dims.width,\n dims.height,\n );\n // Capture all dirty regions concurrently — they are independent OS\n // grabs, so wall-clock is max(region) not sum(region). If ANY region\n // fails we drop to full-frame OCR for this display (unchanged\n // semantics). Promise.all preserves order, so OCR id assignment\n // downstream stays deterministic.\n let crops: Array<{\n png: Buffer;\n bbox: [number, number, number, number];\n }> = [];\n try {\n crops = await Promise.all(\n rects.map(async (rect) => {\n const regionCapture = await this.deps.captureRegion(displayId, {\n x: rect.bbox[0],\n y: rect.bbox[1],\n width: rect.bbox[2],\n height: rect.bbox[3],\n });\n return { png: regionCapture.frame, bbox: rect.bbox };\n }),\n );\n } catch (err) {\n this.deps.log(\n `[scene-builder] captureRegion(${displayId}) failed: ${\n err instanceof Error ? err.message : String(err)\n } — falling back to full-frame OCR for this display`,\n );\n crops = [];\n }\n if (crops.length > 0) {\n const refreshed = await this.deps.runOcrOnCrops(\n crops,\n displayId,\n this.ocrIdState,\n );\n // Drop previous OCR boxes that intersect any dirty rect; keep the rest.\n const keep = prevOcr.filter(\n (b) =>\n b.displayId === displayId && !intersectsAnyRect(b.bbox, rects),\n );\n ocr.push(...keep, ...refreshed);\n } else {\n const refreshed = await this.deps.runOcrOnFrame(\n capture.frame,\n displayId,\n this.ocrIdState,\n );\n ocr.push(...refreshed);\n }\n } else {\n // 3. Full-frame OCR (no usable dirty diff, or too many blocks dirty).\n const refreshed = await this.deps.runOcrOnFrame(\n capture.frame,\n displayId,\n this.ocrIdState,\n );\n ocr.push(...refreshed);\n }\n state.lastBlockGrid = grid ?? state.lastBlockGrid;\n } else if (state.lastScene.scene.ocr) {\n ocr.push(\n ...state.lastScene.scene.ocr.filter((b) => b.displayId === displayId),\n );\n }\n\n state.lastDhash = dHash;\n }\n\n // Always refresh apps + AX on active and agent-turn modes. On pure idle\n // ticks we reuse the previously-built lists.\n let apps: SceneApp[];\n let ax: SceneAxNode[];\n if (mode === \"idle\" && this.latestScene) {\n apps = this.latestScene.apps;\n ax = this.latestScene.ax;\n } else {\n apps = this.safeEnumerateApps();\n ax = await this.safeSnapshotAx();\n }\n\n const focused = inferFocusedWindow(apps, ax, displays);\n const scene: Scene = {\n timestamp: t0,\n displays,\n focused_window: focused,\n apps,\n ocr,\n ax,\n vlm_scene: this.latestScene?.vlm_scene ?? null,\n vlm_elements: this.latestScene?.vlm_elements ?? null,\n };\n\n // Update caches.\n for (const cap of captures) {\n const state = this.ensureState(cap.display.id);\n state.lastScene = {\n scene: {\n ocr: scene.ocr,\n ax: scene.ax,\n apps: scene.apps,\n },\n cachedAt: t0,\n dhash: state.lastDhash,\n };\n }\n\n this.latestScene = scene;\n const reason: SceneUpdateEvent[\"reason\"] = mode;\n this.emit(\"scene\", { scene, reason });\n return scene;\n }\n\n private async captureWithFallback(\n displays: DisplayDescriptor[],\n ): Promise<DisplayCapture[]> {\n try {\n return await this.deps.captureAll();\n } catch (err) {\n this.deps.log(\n `[scene-builder] captureAllDisplays failed: ${err instanceof Error ? err.message : String(err)} — falling back to per-display capture`,\n );\n }\n const out: DisplayCapture[] = [];\n for (const d of displays) {\n try {\n out.push(await this.deps.captureOne(d.id));\n } catch (err) {\n this.deps.log(\n `[scene-builder] captureDisplay(${d.id}) failed: ${err instanceof Error ? err.message : String(err)} — display will be missing from scene`,\n );\n }\n }\n return out;\n }\n\n private safeEnumerateApps(): SceneApp[] {\n try {\n return this.deps.enumerateApps();\n } catch (err) {\n this.deps.log(\n `[scene-builder] enumerateApps failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n return [];\n }\n }\n\n private async safeSnapshotAx(): Promise<SceneAxNode[]> {\n try {\n return await this.deps.accessibilityProvider.snapshot();\n } catch (err) {\n this.deps.log(\n `[scene-builder] accessibilityProvider.snapshot failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n return [];\n }\n }\n\n private ensureState(displayId: number): PerDisplayState {\n let state = this.perDisplay.get(displayId);\n if (!state) {\n state = {\n lastDhash: null,\n lastChangeAt: 0,\n lastBlockGrid: null,\n lastScene: { scene: {}, cachedAt: 0, dhash: null },\n };\n this.perDisplay.set(displayId, state);\n }\n return state;\n }\n}\n\nfunction inferFocusedWindow(\n apps: SceneApp[],\n ax: SceneAxNode[],\n displays: DisplayDescriptor[],\n): SceneFocusedWindow | null {\n // Heuristic: prefer the AX node that overlaps the largest display area —\n // typically the foreground window. This avoids platform-specific focus\n // queries while still producing a usable hint for WS7.\n let bestAx: SceneAxNode | null = null;\n let bestArea = 0;\n for (const node of ax) {\n const area = (node.bbox[2] ?? 0) * (node.bbox[3] ?? 0);\n if (area > bestArea) {\n bestArea = area;\n bestAx = node;\n }\n }\n if (!bestAx) return null;\n // Resolve display.\n const display =\n displays.find((d) => d.id === bestAx.displayId) ?? displays[0];\n if (!display) return null;\n // Try to find a matching app via title contains.\n const lcLabel = (bestAx.label ?? \"\").toLowerCase();\n let app: SceneApp | undefined;\n for (const a of apps) {\n if (a.windows.some((w) => w.title.toLowerCase() === lcLabel)) {\n app = a;\n break;\n }\n }\n return {\n app: app?.name ?? bestAx.label ?? \"unknown\",\n pid: app?.pid ?? null,\n bounds: bestAx.bbox,\n title: bestAx.label ?? \"\",\n displayId: display.id,\n };\n}\n\nlet singleton: SceneBuilder | null = null;\nexport function getDefaultSceneBuilder(): SceneBuilder {\n if (!singleton) singleton = new SceneBuilder();\n return singleton;\n}\n\n/** Test-only reset. */\nexport function _resetDefaultSceneBuilderForTests(): void {\n singleton = null;\n}\n\nfunction intersectsAnyRect(\n bbox: [number, number, number, number],\n rects: Array<{ bbox: [number, number, number, number] }>,\n): boolean {\n const [bx, by, bw, bh] = bbox;\n for (const r of rects) {\n const [rx, ry, rw, rh] = r.bbox;\n const overlap =\n bx < rx + rw && bx + bw > rx && by < ry + rh && by + bh > ry;\n if (overlap) return true;\n }\n return false;\n}\n",
|
|
51
|
+
"/**\n * AccessibilityProvider — thin abstraction over platform-specific a11y trees.\n *\n * The scene-builder needs structured a11y nodes (role, label, bbox, actions)\n * tagged with a stable id so the planner can say \"click element a47\" across\n * turns. The existing `platform/a11y.ts::extractA11yTree()` returns a single\n * flat string — useful for prompts but not structured. This module wraps it\n * with a typed-node interface and adds:\n *\n * - Native impls per-OS that prefer structured JSON output where the\n * platform supports it (AT-SPI emits structured data we just need to\n * marshal; UIA/AX similarly).\n * - A Wayland-compositor fallback (`hyprctl clients -j`, `swaymsg -t\n * get_tree`) so Linux Wayland-only environments still surface windowable\n * nodes even when AT-SPI is locked down.\n * - A `NullAccessibilityProvider` for platforms / contexts where a11y is\n * intentionally disabled (CI, headless runners).\n *\n * Stable id strategy:\n * - Each provider emits `a<displayId>-<seq>` IDs. The same logical element\n * keeps the same id across consecutive frames AS LONG AS the provider's\n * in-memory map is preserved — we re-key when role + label + bbox\n * intersect significantly with a previous frame's node. This is the\n * contract WS7's \"click element a47\" depends on.\n *\n * The Android `AccessibilityService` impl is owned by WS8 and registers via\n * `setAccessibilityProvider()` at runtime — this module exposes the seam\n * but does not ship a JS-side implementation.\n */\n\nimport { execFileSync } from \"node:child_process\";\nimport { commandExists, currentPlatform } from \"../platform/helpers.js\";\nimport type { SceneAxNode } from \"./scene-types.js\";\n\nexport interface AccessibilityProvider {\n readonly name: string;\n /**\n * Whether this provider can produce structured nodes on the current host.\n * Used by `resolveAccessibilityProvider` to pick the best chain entry.\n */\n available(): boolean;\n /**\n * Capture the live a11y tree and return per-display node lists. Returns\n * an empty array when no nodes are reachable (vs throwing) so the\n * scene-builder always produces a Scene.\n */\n snapshot(): Promise<SceneAxNode[]>;\n}\n\nclass NullAccessibilityProvider implements AccessibilityProvider {\n readonly name = \"null\";\n available(): boolean {\n return true;\n }\n async snapshot(): Promise<SceneAxNode[]> {\n return [];\n }\n}\n\nlet activeProvider: AccessibilityProvider | null = null;\n\n/**\n * Replace the active provider (used by Android/WS8 to inject the native\n * `AccessibilityService` adapter, and by tests).\n */\nexport function setAccessibilityProvider(\n provider: AccessibilityProvider,\n): void {\n activeProvider = provider;\n}\n\nexport function resolveAccessibilityProvider(): AccessibilityProvider {\n if (activeProvider) return activeProvider;\n const os = currentPlatform();\n if (os === \"linux\") return new LinuxAccessibilityProvider();\n if (os === \"darwin\") return new DarwinAccessibilityProvider();\n if (os === \"win32\") return new WindowsAccessibilityProvider();\n return new NullAccessibilityProvider();\n}\n\ninterface IdAssignerState {\n seq: Map<number, number>;\n}\n\nexport function makeIdAssigner(): IdAssignerState {\n return { seq: new Map() };\n}\n\nexport function assignAxId(state: IdAssignerState, displayId: number): string {\n const cur = state.seq.get(displayId) ?? 0;\n const next = cur + 1;\n state.seq.set(displayId, next);\n return `a${displayId}-${next}`;\n}\n\n// ── Linux ───────────────────────────────────────────────────────────────────\n\nexport class LinuxAccessibilityProvider implements AccessibilityProvider {\n readonly name = \"linux\";\n\n available(): boolean {\n // AT-SPI requires python3 + python3-atspi/gi. Wayland fallback requires\n // hyprctl or swaymsg.\n return (\n commandExists(\"python3\") ||\n commandExists(\"hyprctl\") ||\n commandExists(\"swaymsg\")\n );\n }\n\n async snapshot(): Promise<SceneAxNode[]> {\n // Try AT-SPI first (richest data on X11 / GNOME-Wayland), then fall\n // back to compositor-specific IPC.\n const atspiNodes = this.tryAtspi();\n if (atspiNodes.length > 0) return atspiNodes;\n const wayland = this.tryWaylandCompositor();\n return wayland;\n }\n\n private tryAtspi(): SceneAxNode[] {\n if (!commandExists(\"python3\")) return [];\n const py = `\nimport json, sys\ntry:\n import gi\n gi.require_version('Atspi', '2.0')\n from gi.repository import Atspi\n out = []\n desktop = Atspi.get_desktop(0)\n for i in range(desktop.get_child_count()):\n app = desktop.get_child_at_index(i)\n if not app: continue\n appname = app.get_name() or \"unknown\"\n for j in range(min(app.get_child_count(), 30)):\n win = app.get_child_at_index(j)\n if not win: continue\n try:\n ext = win.get_extents(Atspi.CoordType.SCREEN)\n bbox = [ext.x, ext.y, ext.width, ext.height]\n except Exception:\n bbox = [0,0,0,0]\n try:\n action_iface = win.get_action_iface()\n actions = []\n if action_iface:\n n = action_iface.get_n_actions()\n for k in range(n):\n try: actions.append(action_iface.get_name(k))\n except Exception: pass\n except Exception:\n actions = []\n out.append({\n \"role\": win.get_role_name() or \"unknown\",\n \"label\": win.get_name() or appname,\n \"bbox\": bbox,\n \"actions\": actions,\n })\n print(json.dumps(out))\nexcept Exception as e:\n print(\"[]\")\n`;\n try {\n const text = execFileSync(\"python3\", [\"-c\", py], {\n timeout: 4000,\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n });\n const parsed = JSON.parse(text || \"[]\");\n if (!Array.isArray(parsed)) return [];\n return parsed\n .filter((n) => n && typeof n === \"object\")\n .map((n, i) => mapAtspiNode(n as Record<string, unknown>, i));\n } catch {\n return [];\n }\n }\n\n private tryWaylandCompositor(): SceneAxNode[] {\n const xdgDesktop = (process.env.XDG_CURRENT_DESKTOP ?? \"\").toLowerCase();\n if (xdgDesktop.includes(\"hyprland\") || commandExists(\"hyprctl\")) {\n const nodes = this.tryHyprland();\n if (nodes.length > 0) return nodes;\n }\n if (xdgDesktop.includes(\"sway\") || commandExists(\"swaymsg\")) {\n const nodes = this.trySway();\n if (nodes.length > 0) return nodes;\n }\n return [];\n }\n\n private tryHyprland(): SceneAxNode[] {\n try {\n const text = execFileSync(\"hyprctl\", [\"clients\", \"-j\"], {\n timeout: 3000,\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n });\n return parseHyprlandClients(text);\n } catch {\n return [];\n }\n }\n\n private trySway(): SceneAxNode[] {\n try {\n const text = execFileSync(\"swaymsg\", [\"-t\", \"get_tree\"], {\n timeout: 3000,\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n });\n return parseSwayTree(text);\n } catch {\n return [];\n }\n }\n}\n\ninterface HyprClient {\n address?: string;\n workspace?: { id?: number };\n monitor?: number;\n class?: string;\n title?: string;\n at?: [number, number];\n size?: [number, number];\n focusHistoryID?: number;\n}\n\nexport function parseHyprlandClients(text: string): SceneAxNode[] {\n let raw: unknown;\n try {\n raw = JSON.parse(text);\n } catch {\n return [];\n }\n if (!Array.isArray(raw)) return [];\n const out: SceneAxNode[] = [];\n let idx = 0;\n for (const item of raw as HyprClient[]) {\n if (!item || typeof item !== \"object\") continue;\n const at = Array.isArray(item.at) ? item.at : [0, 0];\n const size = Array.isArray(item.size) ? item.size : [0, 0];\n const displayId = Number.isFinite(Number(item.monitor))\n ? Number(item.monitor)\n : 0;\n out.push({\n id: `a${displayId}-${idx + 1}`,\n role: \"window\",\n label: item.title || item.class || \"unknown\",\n bbox: [\n Number(at[0] ?? 0),\n Number(at[1] ?? 0),\n Number(size[0] ?? 0),\n Number(size[1] ?? 0),\n ],\n actions: [\"focus\", \"close\"],\n displayId,\n });\n idx += 1;\n }\n return out;\n}\n\ninterface SwayNode {\n name?: string;\n app_id?: string;\n window?: number;\n type?: string;\n rect?: { x?: number; y?: number; width?: number; height?: number };\n nodes?: SwayNode[];\n floating_nodes?: SwayNode[];\n output?: string;\n focused?: boolean;\n}\n\nexport function parseSwayTree(text: string): SceneAxNode[] {\n let raw: SwayNode | null;\n try {\n raw = JSON.parse(text) as SwayNode;\n } catch {\n return [];\n }\n if (!raw) return [];\n const out: SceneAxNode[] = [];\n let seq = 0;\n const outputToDisplay = new Map<string, number>();\n // First pass — assign display ids by output name encounter order.\n const visit = (node: SwayNode, currentOutput: string): void => {\n if (node.type === \"output\" && typeof node.name === \"string\") {\n if (!outputToDisplay.has(node.name)) {\n outputToDisplay.set(node.name, outputToDisplay.size);\n }\n currentOutput = node.name;\n }\n if (node.type === \"con\" || node.type === \"floating_con\") {\n if (node.window !== undefined || node.app_id) {\n const displayId = outputToDisplay.get(currentOutput) ?? 0;\n seq += 1;\n const rect = node.rect ?? {};\n out.push({\n id: `a${displayId}-${seq}`,\n role: \"window\",\n label: node.name || node.app_id || \"unknown\",\n bbox: [\n Number(rect.x ?? 0),\n Number(rect.y ?? 0),\n Number(rect.width ?? 0),\n Number(rect.height ?? 0),\n ],\n actions: [\"focus\", \"close\"],\n displayId,\n });\n }\n }\n for (const child of node.nodes ?? []) visit(child, currentOutput);\n for (const child of node.floating_nodes ?? []) visit(child, currentOutput);\n };\n visit(raw, \"\");\n return out;\n}\n\nfunction mapAtspiNode(raw: Record<string, unknown>, idx: number): SceneAxNode {\n const bbox = Array.isArray(raw.bbox)\n ? (raw.bbox as unknown[]).map((v) => Number(v))\n : [0, 0, 0, 0];\n const actions = Array.isArray(raw.actions)\n ? (raw.actions as unknown[]).filter(\n (v): v is string => typeof v === \"string\",\n )\n : [];\n return {\n id: `a0-${idx + 1}`,\n role: typeof raw.role === \"string\" ? raw.role : \"unknown\",\n label: typeof raw.label === \"string\" ? raw.label : undefined,\n bbox: [bbox[0] ?? 0, bbox[1] ?? 0, bbox[2] ?? 0, bbox[3] ?? 0],\n actions,\n displayId: 0,\n };\n}\n\n// ── macOS ───────────────────────────────────────────────────────────────────\n\nexport class DarwinAccessibilityProvider implements AccessibilityProvider {\n readonly name = \"darwin\";\n\n available(): boolean {\n return true; // osascript always present; user permission needed at runtime.\n }\n\n async snapshot(): Promise<SceneAxNode[]> {\n try {\n const script = `\n const SE = Application(\"System Events\");\n const procs = SE.processes.whose({visible: true})();\n const out = [];\n for (let p of procs) {\n try {\n const appName = p.name();\n for (let w of p.windows()) {\n try {\n const pos = w.position();\n const sz = w.size();\n out.push({\n app: appName,\n title: w.name(),\n bbox: [pos[0], pos[1], sz[0], sz[1]],\n });\n } catch (e) {}\n }\n } catch (e) {}\n }\n JSON.stringify(out);\n `;\n const text = execFileSync(\n \"osascript\",\n [\"-l\", \"JavaScript\", \"-e\", script],\n {\n timeout: 8000,\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n },\n );\n const parsed = JSON.parse(text || \"[]\");\n if (!Array.isArray(parsed)) return [];\n return parsed.map((n, i) => {\n const bbox = Array.isArray(n?.bbox) ? n.bbox : [0, 0, 0, 0];\n return {\n id: `a0-${i + 1}`,\n role: \"window\",\n label: typeof n?.title === \"string\" ? n.title : n?.app,\n bbox: [\n Number(bbox[0]) || 0,\n Number(bbox[1]) || 0,\n Number(bbox[2]) || 0,\n Number(bbox[3]) || 0,\n ],\n actions: [\"focus\", \"close\"],\n displayId: 0,\n } as SceneAxNode;\n });\n } catch {\n return [];\n }\n }\n}\n\n// ── Windows ─────────────────────────────────────────────────────────────────\n\nexport class WindowsAccessibilityProvider implements AccessibilityProvider {\n readonly name = \"win32\";\n\n available(): boolean {\n return true; // PowerShell UIA always available on supported Windows.\n }\n\n async snapshot(): Promise<SceneAxNode[]> {\n const ps = `\nAdd-Type -AssemblyName UIAutomationClient,UIAutomationTypes\n$root = [System.Windows.Automation.AutomationElement]::RootElement\n$walker = [System.Windows.Automation.TreeWalker]::ContentViewWalker\n$child = $walker.GetFirstChild($root)\n$out = @()\n$count = 0\nwhile ($child -and $count -lt 50) {\n try {\n $rect = $child.Current.BoundingRectangle\n $row = [PSCustomObject]@{\n role = $child.Current.ControlType.ProgrammaticName\n label = $child.Current.Name\n bbox = @($rect.X, $rect.Y, $rect.Width, $rect.Height)\n }\n $out += $row\n } catch {}\n $child = $walker.GetNextSibling($child)\n $count++\n}\n$out | ConvertTo-Json -Depth 4 -Compress\n`;\n try {\n const text = execFileSync(\"powershell\", [\"-NoProfile\", \"-Command\", ps], {\n timeout: 10_000,\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n });\n const parsed = JSON.parse(text || \"[]\");\n const list = Array.isArray(parsed) ? parsed : [parsed];\n return list\n .filter((n) => n && typeof n === \"object\")\n .map((n, i) => {\n const bbox = Array.isArray(n.bbox) ? n.bbox : [0, 0, 0, 0];\n return {\n id: `a0-${i + 1}`,\n role: typeof n.role === \"string\" ? n.role : \"unknown\",\n label: typeof n.label === \"string\" ? n.label : undefined,\n bbox: [\n Number(bbox[0]) || 0,\n Number(bbox[1]) || 0,\n Number(bbox[2]) || 0,\n Number(bbox[3]) || 0,\n ],\n actions: [],\n displayId: 0,\n } as SceneAxNode;\n });\n } catch {\n return [];\n }\n }\n}\n\nexport { NullAccessibilityProvider };\n",
|
|
52
|
+
"/**\n * App enumeration — join `listProcesses()` with `listWindows()` to produce\n * a per-pid `SceneApp[]` shape with embedded windows.\n *\n * This is intentionally a join over what we already have. The existing\n * `windows-list.ts` doesn't surface pid on every OS:\n * - Windows: `Get-Process` already keys by pid; `MainWindowTitle` lives on\n * the same row. The join is implicit.\n * - Linux : `wmctrl -l -p` gives pid per window. We re-invoke wmctrl with\n * `-p` here when available; otherwise the per-pid map carries an\n * empty `windows` list.\n * - macOS : AppleScript gives `name of proc` but not the pid. We do a\n * name-based join on `comm`. Close enough for \"click in Safari\"\n * — the planner has app-name + window-title to disambiguate.\n *\n * Edge cases:\n * - A process with no visible windows still appears in `apps[]` with an\n * empty `windows` list. The planner uses this to know \"Slack is running\n * but minimized\" without firing an extra query.\n * - A window with no resolvable pid (Linux X11 without `_NET_WM_PID`) maps\n * to a synthetic `{ pid: 0, name: <appField> }` bucket.\n */\n\nimport { execFileSync } from \"node:child_process\";\nimport { commandExists, currentPlatform } from \"../platform/helpers.js\";\nimport { listProcesses } from \"../platform/process-list.js\";\nimport { listWindows } from \"../platform/windows-list.js\";\nimport type { WindowInfo } from \"../types.js\";\nimport type { SceneApp, SceneAppWindow } from \"./scene-types.js\";\n\nexport interface AppEnumerationDeps {\n /** Override for tests. */\n processes?: typeof listProcesses;\n windows?: typeof listWindows;\n}\n\nexport function enumerateApps(deps: AppEnumerationDeps = {}): SceneApp[] {\n const processFn = deps.processes ?? listProcesses;\n const windowsFn = deps.windows ?? listWindows;\n const procs = processFn();\n const wins = windowsFn();\n return joinAppsAndWindows(procs, wins, currentPlatform());\n}\n\ninterface RawProc {\n pid: number;\n name: string;\n}\n\ninterface WindowPidJoin {\n win: WindowInfo;\n pid: number | null;\n bounds: [number, number, number, number];\n displayId: number;\n}\n\nexport function joinAppsAndWindows(\n procs: RawProc[],\n windows: WindowInfo[],\n platform: \"linux\" | \"darwin\" | \"win32\" | string,\n): SceneApp[] {\n const linuxPidMap =\n platform === \"linux\" && commandExists(\"wmctrl\")\n ? linuxPidMapFromWmctrl()\n : new Map<string, number>();\n\n const joined: WindowPidJoin[] = windows.map((win) => {\n let pid: number | null = null;\n if (platform === \"win32\") {\n pid = Number.parseInt(win.id, 10);\n if (!Number.isFinite(pid)) pid = null;\n } else if (platform === \"linux\") {\n pid = linuxPidMap.get(win.id) ?? null;\n } else if (platform === \"darwin\") {\n // We don't have pid on the darwin window list; resolve later by\n // name during the buckets pass.\n pid = null;\n }\n return {\n win,\n pid,\n bounds: [0, 0, 0, 0],\n displayId: 0,\n };\n });\n\n // Build buckets keyed by pid (preferred) or appName (fallback for darwin).\n const buckets = new Map<string, SceneApp>();\n for (const proc of procs) {\n if (!buckets.has(`pid:${proc.pid}`)) {\n buckets.set(`pid:${proc.pid}`, {\n name: proc.name,\n pid: proc.pid,\n windows: [],\n });\n }\n }\n // Index by lower-case name for darwin name-based join.\n const nameIndex = new Map<string, RawProc>();\n for (const proc of procs) {\n const key = proc.name.toLowerCase();\n if (!nameIndex.has(key)) nameIndex.set(key, proc);\n }\n\n for (const j of joined) {\n let bucket: SceneApp | undefined;\n if (j.pid !== null && j.pid > 0) {\n bucket = buckets.get(`pid:${j.pid}`);\n if (!bucket) {\n bucket = {\n name:\n j.win.app && j.win.app !== \"unknown\" ? j.win.app : `pid-${j.pid}`,\n pid: j.pid,\n windows: [],\n };\n buckets.set(`pid:${j.pid}`, bucket);\n }\n } else if (platform === \"darwin\") {\n const proc = nameIndex.get(j.win.app.toLowerCase());\n if (proc) {\n bucket = buckets.get(`pid:${proc.pid}`);\n }\n if (!bucket) {\n const fallback = `app:${j.win.app}`;\n bucket = buckets.get(fallback);\n if (!bucket) {\n bucket = { name: j.win.app, pid: 0, windows: [] };\n buckets.set(fallback, bucket);\n }\n }\n } else {\n const fallback = `app:${j.win.app}`;\n bucket = buckets.get(fallback);\n if (!bucket) {\n bucket = {\n name: j.win.app && j.win.app !== \"unknown\" ? j.win.app : \"unknown\",\n pid: 0,\n windows: [],\n };\n buckets.set(fallback, bucket);\n }\n }\n const sceneWin: SceneAppWindow = {\n id: j.win.id,\n title: j.win.title,\n bounds: j.bounds,\n displayId: j.displayId,\n };\n bucket.windows.push(sceneWin);\n }\n\n return [...buckets.values()];\n}\n\nfunction linuxPidMapFromWmctrl(): Map<string, number> {\n const out = new Map<string, number>();\n try {\n const text = execFileSync(\"wmctrl\", [\"-l\", \"-p\"], {\n timeout: 3000,\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n });\n for (const line of text.split(/\\r?\\n/)) {\n // Format: 0x0400000a 0 12345 hostname Title\n const m = line.match(/^(\\S+)\\s+\\S+\\s+(\\d+)\\s+/);\n if (!m) continue;\n const pid = Number.parseInt(m[2] ?? \"0\", 10);\n if (Number.isFinite(pid) && pid > 0) {\n out.set(m[1] ?? \"\", pid);\n }\n }\n } catch {\n /* best effort */\n }\n return out;\n}\n",
|
|
53
|
+
"/**\n * Cross-platform process listing.\n *\n * The WS6 scene-builder joins running processes with windows to produce the\n * `apps[]` field of a Scene. The contract is intentionally minimal — pid,\n * executable/display name, and a best-effort foreground flag if cheap to\n * obtain. Anything richer (memory, cpu, parent pid) is out of scope here\n * because the scene-builder runs every active-poll frame and must stay\n * cheap.\n *\n * Per-OS source:\n * - Linux : `/proc/<pid>/comm` and `/proc/<pid>/status`. Pure FS read,\n * no shell out. ~5ms for 300 processes.\n * - macOS : `ps -axo pid=,comm=` — built-in BSD ps.\n * - Windows: PowerShell `Get-Process | Select Id, ProcessName`.\n * - Android: returns `[]` in this JS helper; the `UsageStatsManager`\n * integration is owned by WS8's native side. We expose the\n * function shape so the scene-builder doesn't have to branch.\n *\n * Failure semantics:\n * - A single un-readable process is skipped, not propagated.\n * - A complete enumeration failure returns `[]` and the scene-builder logs\n * once per platform-mode at warn.\n */\n\nimport { execFileSync, execSync } from \"node:child_process\";\nimport { readdirSync, readFileSync } from \"node:fs\";\nimport { currentPlatform } from \"./helpers.js\";\n\nexport interface ProcessInfo {\n pid: number;\n name: string;\n}\n\nexport function listProcesses(): ProcessInfo[] {\n const os = currentPlatform();\n if (os === \"linux\") return listLinux();\n if (os === \"darwin\") return listDarwin();\n if (os === \"win32\") return listWindows();\n return [];\n}\n\nfunction listLinux(): ProcessInfo[] {\n const out: ProcessInfo[] = [];\n let entries: string[];\n try {\n entries = readdirSync(\"/proc\");\n } catch {\n return out;\n }\n for (const entry of entries) {\n if (!/^\\d+$/.test(entry)) continue;\n const pid = Number.parseInt(entry, 10);\n if (!Number.isFinite(pid)) continue;\n let name = \"\";\n try {\n // `comm` is the 15-char truncated executable basename. Good enough for\n // join-with-windows; a longer name (cmdline arg0 basename) is overkill.\n name = readFileSync(`/proc/${pid}/comm`, \"utf8\").trim();\n } catch {\n continue;\n }\n if (!name) continue;\n out.push({ pid, name });\n }\n return out;\n}\n\nfunction listDarwin(): ProcessInfo[] {\n try {\n const text = execFileSync(\"ps\", [\"-axco\", \"pid=,comm=\"], {\n timeout: 4000,\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n });\n return parsePsOutput(text);\n } catch {\n try {\n // Fallback: BSD ps without `-c` (gives full path in comm).\n const text = execFileSync(\"ps\", [\"-axo\", \"pid=,comm=\"], {\n timeout: 4000,\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n });\n return parsePsOutput(text);\n } catch {\n return [];\n }\n }\n}\n\nexport function parsePsOutput(text: string): ProcessInfo[] {\n const out: ProcessInfo[] = [];\n for (const line of text.split(/\\r?\\n/)) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n const m = trimmed.match(/^(\\d+)\\s+(.+)$/);\n if (!m) continue;\n const pid = Number.parseInt(m[1] ?? \"0\", 10);\n if (!Number.isFinite(pid) || pid <= 0) continue;\n const rawName = (m[2] ?? \"\").trim();\n if (!rawName) continue;\n // For `ps -axo pid=,comm=` without `-c` the comm column holds an absolute\n // path. We strip to the basename so the scene-builder's join key matches\n // the AppleScript window enumerator's `name of proc`.\n const name = rawName.split(\"/\").pop() ?? rawName;\n out.push({ pid, name });\n }\n return out;\n}\n\nfunction listWindows(): ProcessInfo[] {\n try {\n const text = execSync(\n 'powershell -NoProfile -Command \"Get-Process | Select-Object Id,ProcessName | ConvertTo-Json -Compress\"',\n { timeout: 8000, encoding: \"utf8\", stdio: [\"ignore\", \"pipe\", \"ignore\"] },\n );\n return parseWindowsProcessJson(text);\n } catch {\n return [];\n }\n}\n\ninterface WinProcessRow {\n Id?: number;\n ProcessName?: string;\n}\n\nexport function parseWindowsProcessJson(text: string): ProcessInfo[] {\n let raw: unknown;\n try {\n raw = JSON.parse(text);\n } catch {\n return [];\n }\n const items: WinProcessRow[] = Array.isArray(raw)\n ? (raw as WinProcessRow[])\n : [raw as WinProcessRow];\n const out: ProcessInfo[] = [];\n for (const row of items) {\n if (!row || typeof row !== \"object\") continue;\n const pid = Number(row.Id);\n const name = typeof row.ProcessName === \"string\" ? row.ProcessName : \"\";\n if (!Number.isFinite(pid) || pid <= 0 || !name) continue;\n out.push({ pid, name });\n }\n return out;\n}\n",
|
|
54
|
+
"/**\n * OCR adapter for the WS6 scene-builder.\n *\n * The scene-builder needs text-from-image extraction on full frames and\n * (much more often) on cropped dirty blocks. There are two registry seams it\n * can draw from, in priority order:\n *\n * 1. The coord-aware `CoordOcrProvider` (`mobile/ocr-provider.ts`,\n * `registerCoordOcrProvider` / `getCoordOcrProvider`). This is the\n * canonical seam: `@elizaos/plugin-vision` registers a bridge to its\n * hierarchical OCR (docTR / Apple Vision) at boot, returning blocks with\n * bbox + words + semantic position in display-absolute coords. Preferred\n * whenever a provider is registered.\n * 2. The line-only `OcrProvider` registry (`listOcrProviders()`), used by\n * the on-device iOS Apple-Vision provider and unit-test fakes. Fallback\n * when no coord provider is registered.\n *\n * **Integration choice (justified):**\n *\n * plugin-computeruse cannot take a hard `@elizaos/plugin-vision` dependency —\n * that creates a cycle (vision -> capture -> computeruse) and forces every\n * computeruse consumer to install the vision OCR stack even when they only\n * want desktop control. Instead, computeruse *publishes* both registries and\n * a consumer (plugin-vision, or an integrator) registers a provider at\n * startup. The chain degrades to \"no OCR\" when nothing is registered; the\n * scene-builder logs that condition once.\n *\n * This module exposes:\n * - `runOcrOnPng(png, displayId, options)` — the scene-builder calls this.\n * - `runOcrOnRegions(...)` — same, but for cropped dirty blocks. Falls back\n * to whole-frame OCR if the provider can't crop in place.\n * - `setOcrLoggingHook(fn)` — the scene-builder injects a logger so this\n * module doesn't have to take a `@elizaos/core` dep itself.\n */\n\nimport type {\n CoordOcrBlock,\n CoordOcrProvider,\n OcrLine,\n OcrProvider,\n} from \"../mobile/ocr-provider.js\";\nimport {\n getCoordOcrProvider,\n listOcrProviders,\n} from \"../mobile/ocr-provider.js\";\nimport type { SceneOcrBox } from \"./scene-types.js\";\n\nlet logFn: (message: string) => void = () => {};\nexport function setOcrLoggingHook(fn: (message: string) => void): void {\n logFn = fn;\n}\n\nexport interface OcrAdapterIdState {\n /** Per-display sequence counter so ids stay stable per Scene. */\n perDisplay: Map<number, number>;\n}\n\nexport function makeOcrIdState(): OcrAdapterIdState {\n return { perDisplay: new Map() };\n}\n\nexport function nextOcrId(state: OcrAdapterIdState, displayId: number): string {\n const cur = state.perDisplay.get(displayId) ?? 0;\n const next = cur + 1;\n state.perDisplay.set(displayId, next);\n return `t${displayId}-${next}`;\n}\n\nfunction pickProvider(): OcrProvider | null {\n for (const p of listOcrProviders()) {\n if (p.available()) return p;\n }\n return null;\n}\n\nlet warnedNoProvider = false;\n\nfunction warnNoProviderOnce(): void {\n if (!warnedNoProvider) {\n warnedNoProvider = true;\n logFn(\n \"[scene-builder] no OCR provider registered — scene.ocr will be empty until a CoordOcrProvider is registered (registerCoordOcrProvider, e.g. by plugin-vision) or an OcrProvider via registerOcrProvider().\",\n );\n }\n}\n\n/**\n * Run OCR on a whole PNG buffer. Prefers the coord-aware provider; falls back\n * to the line-only registry. Returns boxes tagged with `displayId` and stable\n * `t<displayId>-<seq>` ids drawn from `idState`. Empty array if no provider is\n * registered.\n */\nexport async function runOcrOnPng(\n png: Buffer,\n displayId: number,\n idState: OcrAdapterIdState,\n): Promise<SceneOcrBox[]> {\n const coord = getCoordOcrProvider();\n if (coord) {\n try {\n const result = await coord.describe({\n displayId: String(displayId),\n sourceX: 0,\n sourceY: 0,\n pngBytes: new Uint8Array(png.buffer, png.byteOffset, png.byteLength),\n });\n return result.blocks.map((block) =>\n coordBlockToSceneBox(block, displayId, idState),\n );\n } catch (err) {\n logFn(\n `[scene-builder] CoordOcrProvider '${coord.name}' failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n return [];\n }\n }\n\n const provider = pickProvider();\n if (!provider) {\n warnNoProviderOnce();\n return [];\n }\n try {\n const result = await provider.recognize({\n kind: \"bytes\",\n data: new Uint8Array(png.buffer, png.byteOffset, png.byteLength),\n });\n return result.lines.map((line) => toSceneBox(line, displayId, idState));\n } catch (err) {\n logFn(\n `[scene-builder] OCR provider '${provider.name}' failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n return [];\n }\n}\n\n/**\n * Run OCR on a list of cropped region buffers, each tied to a bbox in the\n * source frame. Used for dirty-block re-OCR.\n *\n * `crops[i].png` is a standalone PNG of the dirty region. `crops[i].bbox` is\n * the region's location in the source frame (display-local). The returned\n * boxes are translated back into display-local source coordinates.\n */\nexport async function runOcrOnRegions(\n crops: Array<{ png: Buffer; bbox: [number, number, number, number] }>,\n displayId: number,\n idState: OcrAdapterIdState,\n): Promise<SceneOcrBox[]> {\n const coord = getCoordOcrProvider();\n if (coord) {\n // OCR each dirty region concurrently (independent calls), then assign ids\n // sequentially. Promise.all preserves input order, so ocr ids stay stable\n // turn-to-turn regardless of which region's OCR finishes first.\n const perCrop = await Promise.all(\n crops.map(async (crop) => {\n try {\n // The coord provider shifts block bboxes by sourceX/sourceY, so the\n // returned coordinates are already in display-local source space.\n const result = await coord.describe({\n displayId: String(displayId),\n sourceX: crop.bbox[0] ?? 0,\n sourceY: crop.bbox[1] ?? 0,\n pngBytes: new Uint8Array(\n crop.png.buffer,\n crop.png.byteOffset,\n crop.png.byteLength,\n ),\n });\n return result.blocks;\n } catch (err) {\n logFn(\n `[scene-builder] CoordOcr region failed at ${crop.bbox.join(\",\")}: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n return [];\n }\n }),\n );\n const out: SceneOcrBox[] = [];\n for (const blocks of perCrop) {\n for (const block of blocks) {\n out.push(coordBlockToSceneBox(block, displayId, idState));\n }\n }\n return out;\n }\n\n const provider = pickProvider();\n if (!provider) return [];\n // Same concurrency pattern as the coord path: recognize regions in parallel,\n // assign ids in input order afterward (Promise.all preserves order).\n const perCrop = await Promise.all(\n crops.map(async (crop) => {\n try {\n const result = await provider.recognize({\n kind: \"bytes\",\n data: new Uint8Array(\n crop.png.buffer,\n crop.png.byteOffset,\n crop.png.byteLength,\n ),\n });\n return { crop, lines: result.lines };\n } catch (err) {\n logFn(\n `[scene-builder] OCR region failed at ${crop.bbox.join(\",\")}: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n return { crop, lines: [] };\n }\n }),\n );\n const out: SceneOcrBox[] = [];\n for (const { crop, lines } of perCrop) {\n const offset = crop.bbox;\n for (const line of lines) {\n out.push({\n id: nextOcrId(idState, displayId),\n text: line.text,\n bbox: [\n (offset[0] ?? 0) + line.boundingBox.x,\n (offset[1] ?? 0) + line.boundingBox.y,\n line.boundingBox.width,\n line.boundingBox.height,\n ],\n conf: line.confidence,\n displayId,\n });\n }\n }\n return out;\n}\n\n/**\n * Map a coord-aware OCR block to a SceneOcrBox. The coord seam does not carry\n * a per-block confidence, so we default to 1 (present). The block bbox is\n * already in display-absolute source coordinates.\n */\nfunction coordBlockToSceneBox(\n block: CoordOcrBlock,\n displayId: number,\n idState: OcrAdapterIdState,\n): SceneOcrBox {\n return {\n id: nextOcrId(idState, displayId),\n text: block.text,\n bbox: [block.bbox.x, block.bbox.y, block.bbox.width, block.bbox.height],\n conf: 1,\n displayId,\n };\n}\n\nfunction toSceneBox(\n line: OcrLine,\n displayId: number,\n idState: OcrAdapterIdState,\n): SceneOcrBox {\n return {\n id: nextOcrId(idState, displayId),\n text: line.text,\n bbox: [\n line.boundingBox.x,\n line.boundingBox.y,\n line.boundingBox.width,\n line.boundingBox.height,\n ],\n conf: line.confidence,\n displayId,\n };\n}\n\n// Re-export so the optional coord provider type is reachable for consumers.\nexport type { CoordOcrProvider };\n",
|
|
55
|
+
"/**\n * Unified `ScreenState` — one capture per turn (#9105 M3).\n *\n * Before this seam the same display was captured/encoded multiple times per\n * turn: the SceneBuilder's dHash gate, the SceneBuilder's OCR pass, and the\n * Brain's `encodeForBrain` each pulled their own frame. `ScreenStateStore`\n * makes the capture a single shared artifact: it grabs one PNG per display,\n * computes the frame dHash and the 16×16 block grid once, and hands every\n * consumer (OCR adapter, DirtyTileDescriber, scene provider, Brain) the same\n * `ScreenState`. Re-asking for a display within `freshnessMs` reuses the prior\n * capture instead of hitting the OS again.\n *\n * Change detection rides the existing `scene/dhash.ts`: a refresh only emits a\n * change event when the frame dHash moved by at least `hammingThreshold` bits,\n * so subscribers (e.g. the continuous describer loop) don't re-run on a\n * pixel-identical screen. `getStats()` exposes how many captures were served\n * from cache vs taken fresh so a test can prove the per-turn saving.\n *\n * Pure + injectable: pass a `capture` fn to drive the store from synthetic PNGs\n * with no real screen.\n */\n\nimport type { DisplayCapture } from \"../platform/capture.js\";\nimport {\n type BlockGrid,\n blockGrid,\n type DirtyBlock,\n diffBlocks,\n frameDhash,\n hamming,\n pngDimensions,\n} from \"./dhash.js\";\n\n/** Frame-dHash hamming distance below which two frames are \"unchanged\". */\nexport const SCREEN_STATE_HAMMING_THRESHOLD = 5;\n/** Default reuse window: a capture younger than this is served from cache. */\nexport const SCREEN_STATE_DEFAULT_FRESHNESS_MS = 400;\n\n/** A single shared per-display capture for one turn. */\nexport interface ScreenState {\n displayId: number;\n /** ms epoch when the underlying frame was captured. */\n capturedAt: number;\n width: number;\n height: number;\n /** PNG bytes at backing-store resolution. */\n png: Buffer;\n /** 64-bit frame dHash, or null when the PNG could not be decoded. */\n dhash: bigint | null;\n /** 16×16 block grid of the frame, or null when undecodable. */\n blockGrid: BlockGrid | null;\n /**\n * Blocks that changed vs the previously stored frame for this display.\n * `null` on the very first capture (no prior to diff against). Bboxes are in\n * display-local pixel space when dimensions were available.\n */\n dirtyBlocks: DirtyBlock[] | null;\n}\n\nexport interface ScreenStateChange {\n state: ScreenState;\n /** dHash hamming distance from the previous frame (Infinity on first frame). */\n distance: number;\n}\n\n/** Capture-accounting snapshot for a store. */\nexport interface ScreenStateStats {\n /** Fresh OS captures actually taken. */\n captures: number;\n /** Capture requests served from the freshness cache (no OS hit). */\n cacheHits: number;\n /** Refreshes that changed the screen enough to fire a change event. */\n changes: number;\n}\n\nexport interface ScreenStateStoreOptions {\n /**\n * Capture one display to a PNG. Defaults to the platform `captureDisplay`.\n * Injected in tests to drive synthetic frames.\n */\n capture: (displayId: number) => Promise<DisplayCapture>;\n /** Reuse window in ms. Default `SCREEN_STATE_DEFAULT_FRESHNESS_MS`. */\n freshnessMs?: number;\n /** Hamming threshold for \"changed\". Default `SCREEN_STATE_HAMMING_THRESHOLD`. */\n hammingThreshold?: number;\n /** Clock injection for deterministic freshness tests. Default `Date.now`. */\n now?: () => number;\n}\n\n/**\n * Owns the single shared capture per display. `ComputerUseService` holds one\n * store; SceneBuilder, the Brain, and the DirtyTileDescriber loop all read it.\n */\nexport class ScreenStateStore {\n private readonly capture: (displayId: number) => Promise<DisplayCapture>;\n private readonly freshnessMs: number;\n private readonly hammingThreshold: number;\n private readonly now: () => number;\n private readonly states = new Map<number, ScreenState>();\n private readonly listeners = new Set<(change: ScreenStateChange) => void>();\n private stats: ScreenStateStats = { captures: 0, cacheHits: 0, changes: 0 };\n\n constructor(options: ScreenStateStoreOptions) {\n this.capture = options.capture;\n this.freshnessMs = options.freshnessMs ?? SCREEN_STATE_DEFAULT_FRESHNESS_MS;\n this.hammingThreshold =\n options.hammingThreshold ?? SCREEN_STATE_HAMMING_THRESHOLD;\n this.now = options.now ?? Date.now;\n }\n\n getStats(): ScreenStateStats {\n return { ...this.stats };\n }\n\n /** Latest stored state for a display, or null if never captured. */\n peek(displayId: number): ScreenState | null {\n return this.states.get(displayId) ?? null;\n }\n\n /**\n * Return a `ScreenState` for `displayId`, reusing the last capture when it is\n * younger than the freshness window. Pass `force` to always re-capture.\n */\n async get(displayId: number, force = false): Promise<ScreenState> {\n const prior = this.states.get(displayId);\n if (!force && prior && this.now() - prior.capturedAt < this.freshnessMs) {\n this.stats.cacheHits += 1;\n return prior;\n }\n return this.refresh(displayId);\n }\n\n /**\n * Force a fresh capture, recompute dHash + block grid + dirty diff against the\n * prior frame, store it, and emit a change event when the frame moved by at\n * least the hamming threshold.\n */\n async refresh(displayId: number): Promise<ScreenState> {\n const prior = this.states.get(displayId);\n const captured = await this.capture(displayId);\n this.stats.captures += 1;\n const png = captured.frame;\n const dims = pngDimensions(png);\n const dhash = frameDhash(png);\n const grid = blockGrid(png);\n const dirtyBlocks =\n prior && grid\n ? diffBlocks(prior.blockGrid, grid, dims?.width, dims?.height)\n : null;\n const state: ScreenState = {\n displayId,\n capturedAt: this.now(),\n width: dims?.width ?? 0,\n height: dims?.height ?? 0,\n png,\n dhash,\n blockGrid: grid,\n dirtyBlocks,\n };\n this.states.set(displayId, state);\n\n const distance =\n prior && prior.dhash !== null && dhash !== null\n ? hamming(prior.dhash, dhash)\n : Number.POSITIVE_INFINITY;\n if (distance >= this.hammingThreshold) {\n this.stats.changes += 1;\n const change: ScreenStateChange = { state, distance };\n for (const listener of this.listeners) listener(change);\n }\n return state;\n }\n\n /** Subscribe to change events. Returns an unsubscribe function. */\n onChange(listener: (change: ScreenStateChange) => void): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n}\n",
|
|
56
|
+
"import { type IAgentRuntime, logger, Service } from \"@elizaos/core\";\nimport { listProcesses } from \"../platform/process-list.js\";\nimport { listWindows } from \"../platform/windows-list.js\";\nimport type { Scene } from \"../scene/scene-types.js\";\nimport type { ActionHistoryEntry } from \"../types.js\";\n\nexport const VISION_CONTEXT_SERVICE_TYPE = \"vision-context\";\nexport const VISION_CONTEXT_TASK_GOAL_CACHE_KEY = \"vision-context:task-goal\";\n\nexport type VisionContextBBox = [number, number, number, number];\n\nexport interface VisionContextFocusedWindow {\n app: string;\n title: string;\n bbox: VisionContextBBox | null;\n}\n\nexport interface VisionContextRecentAction {\n action: string;\n ts: number;\n}\n\nexport interface VisionContext {\n openApps: string[];\n focusedWindow: VisionContextFocusedWindow | null;\n recentActions: VisionContextRecentAction[];\n currentTaskGoal: string | null;\n}\n\ninterface ComputerUseContextSource {\n getCurrentScene(): Scene | null;\n refreshScene?(mode?: \"idle\" | \"active\" | \"agent-turn\"): Promise<Scene>;\n getRecentActions?(): ActionHistoryEntry[];\n}\n\ninterface RuntimeCacheReader {\n getCache?<T>(key: string): Promise<T | undefined>;\n}\n\nfunction isComputerUseContextSource(\n candidate: unknown,\n): candidate is ComputerUseContextSource {\n return (\n typeof candidate === \"object\" &&\n candidate !== null &&\n typeof (candidate as { getCurrentScene?: unknown }).getCurrentScene ===\n \"function\"\n );\n}\n\nfunction uniqueProcessNames(): string[] {\n const names = new Set<string>();\n for (const process of listProcesses()) {\n const name = process.name.trim();\n if (name) names.add(name);\n if (names.size >= 50) break;\n }\n const out = [...names];\n if (out[0] === \"launchd\") return [];\n return out;\n}\n\nfunction uniqueVisibleAppNames(scene: Scene | null): string[] {\n if (!scene) return [];\n const names = new Set<string>();\n for (const app of scene.apps) {\n if (app.windows.length === 0) continue;\n const name = app.name.trim();\n if (name) names.add(name);\n }\n return [...names];\n}\n\nfunction focusedWindowFromScene(\n scene: Scene | null,\n): VisionContextFocusedWindow | null {\n if (!scene?.focused_window) return null;\n const focused = scene.focused_window;\n return {\n app: focused.app,\n title: focused.title,\n bbox: focused.bounds,\n };\n}\n\nfunction focusedWindowFromPlatform(): VisionContextFocusedWindow | null {\n const [window] = listWindows();\n if (!window) return null;\n const app = window.app.trim();\n const title = window.title.trim();\n if (!app && !title) return null;\n if (!app && title === \"unknown\") return null;\n return {\n app,\n title,\n bbox: null,\n };\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nexport class VisionContextProvider extends Service {\n static override serviceType = VISION_CONTEXT_SERVICE_TYPE;\n\n private readonly recentActions: VisionContextRecentAction[] = [];\n\n override capabilityDescription =\n \"Provides compact desktop scene context for vision prompts.\";\n\n static override async start(\n runtime: IAgentRuntime,\n ): Promise<VisionContextProvider> {\n return new VisionContextProvider(runtime);\n }\n\n override async stop(): Promise<void> {\n this.recentActions.length = 0;\n }\n\n async getContext(): Promise<VisionContext> {\n const computerUse = this.runtime.getService(\"computeruse\");\n const source = isComputerUseContextSource(computerUse) ? computerUse : null;\n const scene = await this.getScene(source);\n const processNames = uniqueProcessNames();\n const sceneAppNames = uniqueVisibleAppNames(scene);\n return {\n openApps: sceneAppNames.length > 0 ? sceneAppNames : processNames,\n focusedWindow:\n focusedWindowFromScene(scene) ?? focusedWindowFromPlatform(),\n recentActions: this.getRecentActions(source),\n currentTaskGoal: await this.getCurrentTaskGoal(),\n };\n }\n\n noteAction(action: string): void {\n const label = action.trim();\n if (!label) {\n throw new Error(\n \"VisionContextProvider requires a non-empty action label\",\n );\n }\n this.recentActions.push({ action: label, ts: Date.now() });\n if (this.recentActions.length > 10) {\n this.recentActions.splice(0, this.recentActions.length - 10);\n }\n }\n\n private async getScene(\n source: ComputerUseContextSource | null,\n ): Promise<Scene | null> {\n if (!source) return null;\n const current = source.getCurrentScene();\n if (current || !source.refreshScene) return current;\n try {\n return await source.refreshScene(\"agent-turn\");\n } catch (error) {\n logger.warn(\"[vision-context] refreshScene failed:\", errorMessage(error));\n return null;\n }\n }\n\n private getRecentActions(\n source: ComputerUseContextSource | null,\n ): VisionContextRecentAction[] {\n if (!source?.getRecentActions) return [...this.recentActions];\n const sourceActions = source.getRecentActions().map((entry) => ({\n action: entry.action,\n ts: entry.timestamp,\n }));\n return sourceActions.length > 0 ? sourceActions : [...this.recentActions];\n }\n\n private async getCurrentTaskGoal(): Promise<string | null> {\n const runtime = this.runtime as IAgentRuntime & RuntimeCacheReader;\n try {\n const cached = await runtime.getCache?.<unknown>(\n VISION_CONTEXT_TASK_GOAL_CACHE_KEY,\n );\n if (typeof cached === \"string\" && cached.trim()) return cached.trim();\n } catch (error) {\n logger.debug(\n \"[vision-context] task goal cache read failed:\",\n errorMessage(error),\n );\n }\n try {\n const setting = this.runtime.getSetting(\"VISION_CONTEXT_TASK_GOAL\");\n if (typeof setting === \"string\" && setting.trim()) return setting.trim();\n } catch {\n // Optional setting.\n }\n return null;\n }\n}\n",
|
|
57
|
+
"/**\n * Android computer-use bridge — Capacitor JS↔Kotlin contract.\n *\n * Android allows more cross-app surface than iOS, but the consumer-app\n * path still requires explicit permissions:\n *\n * 1. AccessibilityService (BIND_ACCESSIBILITY_SERVICE) — walk and drive\n * the active window's view hierarchy, dispatch gestures.\n * 2. MediaProjection — user-consent screen capture at 1–2 Hz.\n * 3. UsageStatsManager (PACKAGE_USAGE_STATS) — app history; manually\n * granted in Settings > Usage Access.\n * 4. Camera2 — CAMERA permission; service-friendly (no Activity).\n * 5. onTrimMemory → MemoryArbiter pressure (ComponentCallbacks2).\n *\n * The AOSP system-app path (SurfaceControl.captureDisplay, injectInputEvent,\n * IActivityManager) is documented separately in AOSP_SYSTEM_APP.md but is\n * never compiled into the consumer build.\n *\n * The Kotlin counterpart is:\n * plugin-capacitor-bridge/android/src/main/java/ai/elizaos/computeruse/ComputerUsePlugin.kt\n *\n * The Capacitor plugin jsName is \"ComputerUse\" — same as iOS. Both platforms\n * resolve through `Capacitor.Plugins.ComputerUse` so the planner layer can\n * dispatch without a platform branch at the call site.\n *\n * MARK: - Contract\n * Every method in AndroidComputerUseBridge below has a matching @PluginMethod\n * in ComputerUsePlugin.kt. Keep them in lock-step or the bridge silently drifts.\n */\n\n// ── Result envelope ───────────────────────────────────────────────────────────\n\n/**\n * Standard result envelope mirroring IosBridgeResult<T> from ios-bridge.ts.\n * `ok=true` means the native side completed and `data` is shaped per-method.\n * `ok=false` carries a machine-readable `code` and human-readable `message`.\n */\nexport type AndroidBridgeResult<T> =\n | { readonly ok: true; readonly data: T }\n | {\n readonly ok: false;\n readonly code: AndroidBridgeErrorCode;\n readonly message: string;\n };\n\nexport type AndroidBridgeErrorCode =\n | \"unsupported_platform\" // API level below minimum\n | \"permission_denied\" // runtime or special permission not granted\n | \"permission_pending\" // consent dialog shown, result pending\n | \"accessibility_unavailable\" // ElizaAccessibilityService not running\n | \"capture_unavailable\" // MediaProjection not started or no frame yet\n | \"camera_not_open\" // startCamera not called\n | \"invalid_argument\" // unknown gesture type / action name\n | \"internal_error\";\n\n// ── 1. MediaProjection screen capture ────────────────────────────────────────\n\nexport interface MediaProjectionStartOptions {\n /** Capture frame rate, Hz. Default 1. */\n readonly fps?: number;\n}\n\nexport interface MediaProjectionHandle {\n readonly running: boolean;\n}\n\nexport interface CapturedScreenFrame {\n /** Base64-encoded JPEG at quality 75. */\n readonly jpegBase64: string;\n readonly width: number;\n readonly height: number;\n /** Wall-clock ms when the frame was committed to the ImageReader. */\n readonly timestampMs: number;\n}\n\n// ── 2. AccessibilityService — element tree ────────────────────────────────────\n\n/**\n * Compact node shape matching WS6 Scene.ax:\n * [{ id, role, label, bbox, actions }]\n *\n * `id` — integer cast to string; stable within a single snapshot,\n * not across snapshots (AccessibilityNodeInfo has no stable ids).\n * `role` — Android class name, e.g. \"android.widget.Button\".\n * `label` — contentDescription or text, whichever is non-null.\n * `bbox` — screen-coordinates rectangle {x, y, w, h}.\n * `actions` — subset of {\"click\",\"longClick\",\"scroll\",\"type\",\"focus\"}.\n */\nexport interface AndroidAxNode {\n readonly id: string;\n readonly role: string;\n readonly label: string | null;\n readonly bbox: {\n readonly x: number;\n readonly y: number;\n readonly w: number;\n readonly h: number;\n };\n readonly actions: readonly string[];\n}\n\nexport interface AccessibilityTreeResult {\n /** JSON-serialized AndroidAxNode[]. Parsed by the JS caller. */\n readonly nodes: string;\n}\n\n// ── 3. Gesture dispatch ───────────────────────────────────────────────────────\n\nexport type GestureType = \"tap\" | \"swipe\";\n\nexport interface TapGestureArgs {\n readonly type: \"tap\";\n readonly x: number;\n readonly y: number;\n}\n\nexport interface SwipeGestureArgs {\n readonly type: \"swipe\";\n readonly x: number;\n readonly y: number;\n readonly x2: number;\n readonly y2: number;\n /** Swipe duration in ms. Minimum 50ms enforced on native side. Default 300. */\n readonly durationMs?: number;\n}\n\nexport type GestureArgs = TapGestureArgs | SwipeGestureArgs;\n\nexport interface GestureResult {\n readonly ok: boolean;\n}\n\n// ── 4. Global actions ─────────────────────────────────────────────────────────\n\nexport type GlobalAction = \"back\" | \"home\" | \"recents\" | \"notifications\";\n\nexport interface GlobalActionResult {\n readonly ok: boolean;\n}\n\nexport interface SetTextArgs {\n readonly text: string;\n}\n\nexport interface SetTextResult {\n readonly ok: boolean;\n}\n\n// ── 5. UsageStats / app enumeration ──────────────────────────────────────────\n\n/**\n * Mirrors WS6's `enumerateApps()` interface.\n * `isForeground` is true when the package appears as the last\n * MOVE_TO_FOREGROUND event in the past 5 minutes.\n */\nexport interface AppUsageEntry {\n readonly packageName: string;\n readonly label: string;\n readonly lastUsedMs: number;\n readonly totalForegroundMs: number;\n readonly isForeground: boolean;\n}\n\nexport interface EnumerateAppsResult {\n /** JSON-serialized AppUsageEntry[]. Parsed by the JS caller. */\n readonly apps: string;\n}\n\n// ── 6. Memory pressure ────────────────────────────────────────────────────────\n\nexport type AndroidPressureLevel = \"nominal\" | \"low\" | \"critical\";\n\n/**\n * Snapshot of the Android process memory state.\n * Aligns with IPressureSignal from ios-bridge.ts (source = \"android-low-memory\").\n */\nexport interface AndroidMemoryPressureSnapshot {\n readonly level: AndroidPressureLevel;\n readonly freeMb: number;\n readonly maxMb: number;\n readonly usedMb: number;\n readonly source: \"android-runtime\";\n}\n\n// ── 7. Camera (MobileCameraSource) ───────────────────────────────────────────\n\nexport interface AndroidCameraOpenOptions {\n readonly cameraId?: string;\n readonly width?: number;\n readonly height?: number;\n readonly fps?: number;\n}\n\nexport interface AndroidCameraOpenResult {\n /** JSON-serialized CameraEntry[]. */\n readonly cameras: string;\n}\n\nexport interface AndroidCameraEntry {\n readonly id: string;\n readonly label: string;\n readonly position: \"back\" | \"front\" | \"external\";\n}\n\nexport interface AndroidCameraFrameResult {\n /** Base64-encoded JPEG. */\n readonly jpegBase64: string;\n}\n\n// ── 8. Probe ──────────────────────────────────────────────────────────────────\n\nexport interface AndroidBridgeProbe {\n readonly platform: \"android\";\n /** e.g. \"14\" — Build.VERSION.RELEASE. */\n readonly osVersion: string;\n /** SDK integer, e.g. 34. */\n readonly sdkInt: number;\n readonly capabilities: {\n readonly mediaProjection: boolean;\n readonly accessibilityService: boolean;\n readonly usageStats: boolean;\n readonly camera: boolean;\n readonly aospPrivileged: boolean;\n };\n}\n\n// ── Bridge interface ──────────────────────────────────────────────────────────\n\n/**\n * Strict TS interface for the Capacitor Android plugin. Every method returns\n * AndroidBridgeResult<T> — Kotlin never throws across the bridge.\n *\n * The Capacitor plugin name on the Kotlin side is \"ComputerUse\". The jsName\n * resolves to `Capacitor.Plugins.ComputerUse` on Android and iOS alike.\n */\nexport interface AndroidComputerUseBridge {\n // --- Probe ---\n readonly probe: () => Promise<AndroidBridgeResult<AndroidBridgeProbe>>;\n\n // --- MediaProjection ---\n /** Triggers the system screen-capture consent dialog, then starts the service. */\n readonly startMediaProjection: (\n options?: MediaProjectionStartOptions,\n ) => Promise<AndroidBridgeResult<MediaProjectionHandle>>;\n readonly stopMediaProjection: () => Promise<\n AndroidBridgeResult<{ readonly stopped: boolean }>\n >;\n /** Drain the latest frame from the ImageReader ring-buffer. */\n readonly captureFrame: () => Promise<\n AndroidBridgeResult<CapturedScreenFrame>\n >;\n\n // --- AccessibilityService ---\n /** Walk getRootInActiveWindow() and return compact JSON node array. */\n readonly getAccessibilityTree: () => Promise<\n AndroidBridgeResult<AccessibilityTreeResult>\n >;\n readonly dispatchGesture: (\n args: GestureArgs,\n ) => Promise<AndroidBridgeResult<GestureResult>>;\n readonly performGlobalAction: (args: {\n readonly action: GlobalAction;\n }) => Promise<AndroidBridgeResult<GlobalActionResult>>;\n readonly setText: (\n args: SetTextArgs,\n ) => Promise<AndroidBridgeResult<SetTextResult>>;\n\n // --- UsageStats ---\n readonly enumerateApps: () => Promise<\n AndroidBridgeResult<EnumerateAppsResult>\n >;\n\n // --- Memory ---\n readonly getMemoryPressureSnapshot: () => Promise<\n AndroidBridgeResult<AndroidMemoryPressureSnapshot>\n >;\n /**\n * Called from the onTrimMemory ComponentCallbacks2 listener to propagate\n * the pressure level to the JS-side WS1 MemoryArbiter.\n *\n * Call chain:\n * Kotlin ComponentCallbacks2.onTrimMemory(level)\n * → notifyListeners(\"memoryPressure\", { level, freeMb })\n * → JS capacitorPressureSource.dispatch(level, freeMb)\n * → MemoryArbiter pressure listener\n */\n readonly dispatchMemoryPressure: (args: {\n readonly level: AndroidPressureLevel;\n readonly freeMb?: number;\n }) => Promise<AndroidBridgeResult<{ readonly ok: boolean }>>;\n\n // --- Camera (MobileCameraSource) ---\n readonly startCamera: (\n options?: AndroidCameraOpenOptions,\n ) => Promise<AndroidBridgeResult<AndroidCameraOpenResult>>;\n readonly stopCamera: () => Promise<\n AndroidBridgeResult<{ readonly ok: boolean }>\n >;\n readonly captureFrameCamera: () => Promise<\n AndroidBridgeResult<AndroidCameraFrameResult>\n >;\n}\n\n// ── Default constants ─────────────────────────────────────────────────────────\n\n/** Capacitor plugin jsName — resolves to `Capacitor.Plugins.ComputerUse` on both platforms. */\nexport const ANDROID_BRIDGE_JS_NAME = \"ComputerUse\" as const;\n\n/** Default MediaProjection frame rate. Higher values drain battery significantly. */\nexport const ANDROID_DEFAULT_FPS = 1 as const;\n\n/** Default Camera2 capture resolution. */\nexport const ANDROID_DEFAULT_CAMERA_WIDTH = 640 as const;\nexport const ANDROID_DEFAULT_CAMERA_HEIGHT = 480 as const;\n\n// ── Runtime feature-detect ───────────────────────────────────────────────────\n\n/**\n * Result of `featureCheck()`. Callers use this to decide whether to invoke\n * any other method on the bridge — when `supported` is false they should\n * fall back to OCR / external orchestration instead of letting the call throw.\n */\nexport interface AndroidFeatureCheckResult {\n readonly supported: boolean;\n readonly reason?: string;\n}\n\ninterface CapacitorRuntime {\n Plugins?: Record<string, unknown>;\n}\n\nfunction readCapacitorRuntime(): CapacitorRuntime | null {\n const cap = (globalThis as { Capacitor?: unknown }).Capacitor;\n if (!cap || typeof cap !== \"object\") return null;\n return cap as CapacitorRuntime;\n}\n\n/**\n * Runtime feature-detect for the Android bridge. Synchronous and\n * side-effect-free so it can run during planner setup. Returns\n * `{supported:false}` whenever the JS↔Kotlin bridge cannot be reached:\n *\n * - Running on a non-Android host (desktop, iOS, browser).\n * - Capacitor is not initialized (no `globalThis.Capacitor`).\n * - The Kotlin `ComputerUsePlugin` is not registered.\n *\n * This does NOT call `bridge.probe()` — that is async and may surface a\n * permission dialog. Callers that need the per-capability matrix should\n * `await bridge.probe()` after `featureCheck().supported === true`.\n *\n * PARITY: untested on hardware — the lookup path mirrors what the Capacitor\n * runtime does, but has not been validated against a real Android build.\n */\nexport function featureCheck(): AndroidFeatureCheckResult {\n const cap = readCapacitorRuntime();\n if (!cap) {\n return { supported: false, reason: \"Capacitor runtime not present\" };\n }\n const plugins = cap.Plugins;\n if (!plugins || typeof plugins !== \"object\") {\n return { supported: false, reason: \"Capacitor.Plugins not available\" };\n }\n if (!plugins[ANDROID_BRIDGE_JS_NAME]) {\n return {\n supported: false,\n reason: `Capacitor.Plugins.${ANDROID_BRIDGE_JS_NAME} is not registered`,\n };\n }\n return { supported: true };\n}\n\n/**\n * Resolve the live bridge handle, or `null` when unavailable. Pairs with\n * `featureCheck()` for callers that want a typed handle in one step.\n *\n * PARITY: untested on hardware — feature-detect at runtime.\n */\nexport function getAndroidBridge(): AndroidComputerUseBridge | null {\n const cap = readCapacitorRuntime();\n const handle = cap?.Plugins?.[ANDROID_BRIDGE_JS_NAME];\n if (!handle) return null;\n return handle as AndroidComputerUseBridge;\n}\n",
|
|
58
|
+
"/**\n * AppIntent registry — per-app inventory of the intents we know about\n * statically. Every entry is something Apple has either shipped as a\n * documented system intent or a Shortcuts action with a stable identifier.\n *\n * The Swift bridge calls `appIntentList({ bundleIds })` to discover what is\n * actually donated on the device at runtime. This registry is the planner's\n * a-priori catalog: it lets the agent reason about Mail/Notes/etc. before\n * the user has ever opened those apps.\n *\n * Sources for each entry are linked in a comment block above the entry; do\n * not invent intents that Apple has not documented.\n */\n\nimport type { IntentParameterSpec, IntentSpec } from \"./ios-bridge.js\";\n\n// ── Helper ───────────────────────────────────────────────────────────────────\n\nfunction param(\n name: string,\n type: IntentParameterSpec[\"type\"],\n required: boolean,\n description?: string,\n enumValues?: readonly string[],\n): IntentParameterSpec {\n return enumValues\n ? { name, type, required, description, enumValues }\n : { name, type, required, description };\n}\n\n// ── Apple Mail ───────────────────────────────────────────────────────────────\n// https://developer.apple.com/documentation/sirikit/inteapomailintent\n// https://developer.apple.com/documentation/appintents — Send Email action.\n\nconst MAIL_INTENTS: readonly IntentSpec[] = [\n {\n bundleId: \"com.apple.mobilemail\",\n id: \"com.apple.mobilemail.send-email\",\n displayName: \"Send Email\",\n summary: \"Compose and send a new email through Apple Mail.\",\n parameters: [\n param(\"to\", \"string\", true, \"Comma-separated recipient emails.\"),\n param(\"subject\", \"string\", false, \"Email subject line.\"),\n param(\"body\", \"string\", false, \"Plain-text email body.\"),\n param(\"cc\", \"string\", false, \"Comma-separated CC recipients.\"),\n param(\"bcc\", \"string\", false, \"Comma-separated BCC recipients.\"),\n ],\n source: \"system\",\n },\n];\n\n// ── Messages ─────────────────────────────────────────────────────────────────\n// https://developer.apple.com/documentation/sirikit/intsendmessageintent\n\nconst MESSAGES_INTENTS: readonly IntentSpec[] = [\n {\n bundleId: \"com.apple.MobileSMS\",\n id: \"com.apple.MobileSMS.send-message\",\n displayName: \"Send Message\",\n summary:\n \"Send an iMessage or SMS to one or more recipients via the Messages app.\",\n parameters: [\n param(\n \"recipients\",\n \"string\",\n true,\n \"Comma-separated phone numbers or Apple IDs.\",\n ),\n param(\"body\", \"string\", true, \"Message text.\"),\n ],\n source: \"system\",\n },\n];\n\n// ── Notes ────────────────────────────────────────────────────────────────────\n// https://developer.apple.com/documentation/sirikit/intcreatenoteintent\n// https://support.apple.com/guide/shortcuts/notes-actions-apdb14d36829/ios\n\nconst NOTES_INTENTS: readonly IntentSpec[] = [\n {\n bundleId: \"com.apple.mobilenotes\",\n id: \"com.apple.mobilenotes.create-note\",\n displayName: \"Create Note\",\n summary: \"Create a new note in the Notes app.\",\n parameters: [\n param(\"title\", \"string\", false, \"Note title (first line).\"),\n param(\"body\", \"string\", true, \"Note body text.\"),\n param(\"folder\", \"string\", false, \"Destination folder name.\"),\n ],\n source: \"system\",\n },\n {\n bundleId: \"com.apple.mobilenotes\",\n id: \"com.apple.mobilenotes.append-to-note\",\n displayName: \"Append to Note\",\n summary: \"Append text to an existing note matched by title.\",\n parameters: [\n param(\"titleMatch\", \"string\", true, \"Exact title of the target note.\"),\n param(\"body\", \"string\", true, \"Text to append.\"),\n ],\n source: \"system\",\n },\n {\n bundleId: \"com.apple.mobilenotes\",\n id: \"com.apple.mobilenotes.search-notes\",\n displayName: \"Search Notes\",\n summary: \"Search Notes for a query string and return matching note titles.\",\n parameters: [param(\"query\", \"string\", true, \"Search query.\")],\n source: \"system\",\n },\n];\n\n// ── Reminders ────────────────────────────────────────────────────────────────\n// https://developer.apple.com/documentation/sirikit/intaddtaskstoreminderintent\n\nconst REMINDERS_INTENTS: readonly IntentSpec[] = [\n {\n bundleId: \"com.apple.reminders\",\n id: \"com.apple.reminders.add-reminder\",\n displayName: \"Add Reminder\",\n summary: \"Create a new reminder.\",\n parameters: [\n param(\"title\", \"string\", true, \"Reminder title.\"),\n param(\"notes\", \"string\", false, \"Optional notes.\"),\n param(\"dueDate\", \"date\", false, \"Optional due date (ISO 8601).\"),\n param(\"listName\", \"string\", false, \"Target reminder list.\"),\n param(\"priority\", \"enum\", false, \"Reminder priority.\", [\n \"none\",\n \"low\",\n \"medium\",\n \"high\",\n ]),\n ],\n source: \"system\",\n },\n {\n bundleId: \"com.apple.reminders\",\n id: \"com.apple.reminders.list-reminders\",\n displayName: \"List Reminders\",\n summary: \"List reminders, optionally filtered by list name and completion.\",\n parameters: [\n param(\"listName\", \"string\", false, \"Target reminder list.\"),\n param(\"includeCompleted\", \"boolean\", false, \"Default false.\"),\n ],\n source: \"system\",\n },\n];\n\n// ── Music ────────────────────────────────────────────────────────────────────\n// https://developer.apple.com/documentation/sirikit/intplaymediaintent\n\nconst MUSIC_INTENTS: readonly IntentSpec[] = [\n {\n bundleId: \"com.apple.Music\",\n id: \"com.apple.Music.play\",\n displayName: \"Play Music\",\n summary: \"Play a song, album, artist, or playlist in Apple Music.\",\n parameters: [\n param(\"query\", \"string\", true, \"Search query (song / album / artist).\"),\n param(\"kind\", \"enum\", false, \"Restrict the type of media to play.\", [\n \"song\",\n \"album\",\n \"artist\",\n \"playlist\",\n ]),\n param(\"shuffle\", \"boolean\", false, \"Shuffle the queue. Default false.\"),\n ],\n source: \"system\",\n },\n {\n bundleId: \"com.apple.Music\",\n id: \"com.apple.Music.pause\",\n displayName: \"Pause Music\",\n summary: \"Pause Apple Music playback.\",\n parameters: [],\n source: \"system\",\n },\n {\n bundleId: \"com.apple.Music\",\n id: \"com.apple.Music.next-track\",\n displayName: \"Next Track\",\n summary: \"Skip to the next track in Apple Music.\",\n parameters: [],\n source: \"system\",\n },\n];\n\n// ── Maps ─────────────────────────────────────────────────────────────────────\n// https://developer.apple.com/documentation/sirikit/intgetdirectionsintent\n\nconst MAPS_INTENTS: readonly IntentSpec[] = [\n {\n bundleId: \"com.apple.Maps\",\n id: \"com.apple.Maps.directions\",\n displayName: \"Get Directions\",\n summary: \"Open Apple Maps with directions to a destination.\",\n parameters: [\n param(\"destination\", \"string\", true, \"Address or place name.\"),\n param(\n \"origin\",\n \"string\",\n false,\n \"Starting address. Defaults to current location.\",\n ),\n param(\"transport\", \"enum\", false, \"Transport mode.\", [\n \"driving\",\n \"walking\",\n \"transit\",\n \"cycling\",\n ]),\n ],\n source: \"system\",\n },\n {\n bundleId: \"com.apple.Maps\",\n id: \"com.apple.Maps.search\",\n displayName: \"Search Maps\",\n summary: \"Search Apple Maps for a place.\",\n parameters: [\n param(\"query\", \"string\", true, \"Search query.\"),\n param(\"nearLatitude\", \"number\", false, \"Optional latitude bias.\"),\n param(\"nearLongitude\", \"number\", false, \"Optional longitude bias.\"),\n ],\n source: \"system\",\n },\n];\n\n// ── Safari ───────────────────────────────────────────────────────────────────\n// https://support.apple.com/guide/shortcuts/safari-actions-apd07c25323d/ios\n\nconst SAFARI_INTENTS: readonly IntentSpec[] = [\n {\n bundleId: \"com.apple.mobilesafari\",\n id: \"com.apple.mobilesafari.open-url\",\n displayName: \"Open URL in Safari\",\n summary: \"Open a URL in Mobile Safari.\",\n parameters: [\n param(\"url\", \"url\", true, \"Absolute URL to open.\"),\n param(\n \"inPrivateMode\",\n \"boolean\",\n false,\n \"Use private browsing. Default false.\",\n ),\n ],\n source: \"system\",\n },\n {\n bundleId: \"com.apple.mobilesafari\",\n id: \"com.apple.mobilesafari.add-bookmark\",\n displayName: \"Add Bookmark\",\n summary: \"Add a bookmark to Safari.\",\n parameters: [\n param(\"url\", \"url\", true, \"Absolute URL to bookmark.\"),\n param(\"title\", \"string\", false, \"Bookmark title.\"),\n ],\n source: \"system\",\n },\n];\n\n// ── Registry ─────────────────────────────────────────────────────────────────\n\nexport const IOS_APP_INTENT_REGISTRY: Readonly<\n Record<string, readonly IntentSpec[]>\n> = Object.freeze({\n \"com.apple.mobilemail\": MAIL_INTENTS,\n \"com.apple.MobileSMS\": MESSAGES_INTENTS,\n \"com.apple.mobilenotes\": NOTES_INTENTS,\n \"com.apple.reminders\": REMINDERS_INTENTS,\n \"com.apple.Music\": MUSIC_INTENTS,\n \"com.apple.Maps\": MAPS_INTENTS,\n \"com.apple.mobilesafari\": SAFARI_INTENTS,\n});\n\nexport const IOS_APP_INTENT_BUNDLE_IDS: readonly string[] = Object.freeze(\n Object.keys(IOS_APP_INTENT_REGISTRY),\n);\n\nexport function listIosAppIntents(): readonly IntentSpec[] {\n return Object.values(IOS_APP_INTENT_REGISTRY).flat();\n}\n\nexport function findIosAppIntent(intentId: string): IntentSpec | undefined {\n return listIosAppIntents().find((intent) => intent.id === intentId);\n}\n\nexport function findIosAppIntentsForBundle(\n bundleId: string,\n): readonly IntentSpec[] {\n return IOS_APP_INTENT_REGISTRY[bundleId] ?? [];\n}\n",
|
|
59
|
+
"/**\n * iOS computer-use bridge — Capacitor JS↔Swift contract.\n *\n * iOS does not let third-party apps drive other apps. The only surfaces\n * available to us are:\n *\n * 1. ReplayKit foreground capture — own-app screen frames\n * 2. ReplayKit broadcast extension — system-wide capture (~50MB ceiling,\n * iOS 26/26.1 beta regression noted)\n * 3. Apple Vision OCR — VNRecognizeTextRequest, on-device\n * 4. App Intents — invoke other apps' Shortcuts-style\n * intents (the only sanctioned UI driver)\n * 5. UIAccessibility (own app only)\n * 6. Apple Foundation Models (iOS 26) — opportunistic on-device LLM\n *\n * What is NOT exposed (and never will be on stock iOS):\n * - Cross-app input or pixel scraping\n * - Process listing of other running apps\n * - Background inference past ~30s outside `BGProcessingTask`\n *\n * See `eliza/plugins/plugin-computeruse/docs/IOS_CONSTRAINTS.md` for the\n * honest scope discussion and per-method validation checklist.\n *\n * The Swift counterpart lives at\n * `apps/app/ios/App/App/ComputerUseBridge.swift`. The `// MARK: - Contract`\n * block in that file mirrors the signatures below verbatim — keep them in\n * lock-step or the bridge silently drifts.\n */\n\n// ── Common envelope ──────────────────────────────────────────────────────────\n\n/**\n * Standard result envelope for every bridge call.\n *\n * `ok=true` means the native side completed successfully and `data` is shaped\n * to the per-method type. `ok=false` carries a `code` (machine-readable) and\n * `message` (human-readable). No fallbacks, no silent defaults — if the call\n * failed, the JS caller sees it.\n */\nexport type IosBridgeResult<T> =\n | { ok: true; data: T }\n | { ok: false; code: IosBridgeErrorCode; message: string };\n\nexport type IosBridgeErrorCode =\n | \"unsupported_platform\" // not iOS, or iOS version below required minimum\n | \"permission_denied\" // user dismissed system prompt\n | \"permission_pending\" // first-launch — prompt is being shown\n | \"extension_unavailable\" // broadcast extension not installed/registered\n | \"extension_died\" // iOS 26/26.1 beta regression: extension killed within ~3s\n | \"memory_pressure\" // os_proc_available_memory under threshold\n | \"intent_not_found\" // requested AppIntent not registered on this device\n | \"intent_invocation_failed\"\n | \"vision_no_text\" // OCR ran but found nothing\n | \"foundation_model_unavailable\" // Apple Intelligence disabled / OS too old\n | \"internal_error\";\n\n// ── 1. ReplayKit foreground (own-app) capture ────────────────────────────────\n\n/**\n * Configures `RPScreenRecorder.shared().startCapture(handler:completionHandler:)`.\n *\n * `frameRate` caps how often the Swift side forwards frames to JS — Apple\n * delivers at display refresh rate, we throttle. `maxDurationSec` is a\n * hard upper bound; anything past 30s requires `BGProcessingTask` and is\n * not supported by this method.\n */\nexport interface ReplayKitForegroundOptions {\n /** Hard cap, default 1. Apple delivers at display refresh; we drop frames. */\n readonly frameRate?: number;\n /** Max session duration in seconds, default 30. Capped at 30 server-side. */\n readonly maxDurationSec?: number;\n /** Include audio sample buffers (mic). Default false. */\n readonly includeAudio?: boolean;\n}\n\nexport interface ReplayKitForegroundFrame {\n /** Monotonic capture timestamp from CMSampleBuffer presentation time, ns. */\n readonly timestampNs: number;\n /** Pixel width in image-buffer coordinates. */\n readonly width: number;\n /** Pixel height. */\n readonly height: number;\n /** Base64-encoded JPEG of the frame at quality 0.7. */\n readonly jpegBase64: string;\n}\n\nexport interface ReplayKitForegroundHandle {\n /** Opaque session id; pass to `replayKitForegroundStop`. */\n readonly sessionId: string;\n /** Echoed effective options after server-side clamping. */\n readonly effective: Required<ReplayKitForegroundOptions>;\n}\n\n// ── 2. Broadcast extension (system-wide capture) ─────────────────────────────\n\n/**\n * Handshake with the broadcast extension. Returns whether the extension is\n * registered, the App Group container path used to stream frames, and a\n * pre-flight memory headroom check.\n *\n * The extension itself runs in a separate process with a ~50MB ceiling. The\n * main app cannot start the extension programmatically — the user must tap\n * the system share-sheet broadcast picker. This call only verifies the\n * pipeline is wired and the App Group container is writable.\n *\n * iOS 26 / 26.1 beta regression: extensions are killed within ~3 seconds even\n * when memory is well under the limit. The bridge surfaces this as\n * `extension_died` with `details.regressionFB` referencing the Apple feedback\n * id when known. The caller should fall back to foreground capture.\n */\nexport interface BroadcastHandshakeResult {\n /** True if the broadcast extension target is bundled with this build. */\n readonly extensionInstalled: boolean;\n /** App Group identifier (e.g. `group.com.elizaai.eliza`). */\n readonly appGroupId: string;\n /** Absolute path to the App Group container used for IPC frames. */\n readonly sharedContainerPath: string;\n /** Available memory in MB the extension would have at start time. */\n readonly availableMemoryMb: number;\n /** True if iOS reports an active broadcast session. */\n readonly broadcastActive: boolean;\n /** Last known iOS-26-beta regression status, if observed. */\n readonly regression?: {\n readonly observed: boolean;\n readonly note: string;\n };\n}\n\n// ── 3. Apple Vision OCR ──────────────────────────────────────────────────────\n\nexport interface VisionOcrOptions {\n /**\n * ISO 639-1 language hints. Vision falls back to autodetect when omitted.\n * Examples: [\"en-US\"], [\"zh-Hans\",\"en-US\"].\n */\n readonly languages?: readonly string[];\n /**\n * \"fast\" uses a smaller model with lower latency (~80ms typical),\n * \"accurate\" runs the higher-quality model (~250ms typical).\n */\n readonly recognitionLevel?: \"fast\" | \"accurate\";\n /** Minimum text height as a fraction of image height. Default 0.0 (off). */\n readonly minimumTextHeight?: number;\n /**\n * Whether to use language-correction post-pass. Default true on iOS 16+.\n * Adds ~30ms but materially improves CJK and handwriting accuracy.\n */\n readonly usesLanguageCorrection?: boolean;\n}\n\nexport interface VisionOcrLine {\n readonly text: string;\n readonly confidence: number;\n /** Normalized 0..1 origin-bottom-left rect, matching VNRectangleObservation. */\n readonly boundingBox: {\n readonly x: number;\n readonly y: number;\n readonly width: number;\n readonly height: number;\n };\n}\n\nexport interface VisionOcrResult {\n readonly lines: readonly VisionOcrLine[];\n readonly fullText: string;\n /** Total time spent in VNImageRequestHandler.perform, ms. */\n readonly elapsedMs: number;\n /** Languages Vision actually used. */\n readonly languagesUsed: readonly string[];\n}\n\n// ── 4. App Intents ───────────────────────────────────────────────────────────\n\n/**\n * Parameter spec for an AppIntent. Mirrors the subset of `IntentParameter`\n * shapes we can portably express across iOS 16+ AppIntent and the legacy\n * Intents framework. The Swift side validates and rejects extras.\n */\nexport interface IntentParameterSpec {\n readonly name: string;\n readonly type: \"string\" | \"number\" | \"boolean\" | \"date\" | \"url\" | \"enum\";\n readonly required: boolean;\n /** Present when type === \"enum\". */\n readonly enumValues?: readonly string[];\n /** Human-readable description for the planner. */\n readonly description?: string;\n}\n\nexport interface IntentSpec {\n /** Bundle id of the owning app, e.g. `com.apple.mobilenotes`. */\n readonly bundleId: string;\n /** Reverse-DNS intent identifier, e.g. `com.apple.mobilenotes.create-note`. */\n readonly id: string;\n /** Display name surfaced in the planner. */\n readonly displayName: string;\n /** Free-form summary used as planner context. */\n readonly summary: string;\n readonly parameters: readonly IntentParameterSpec[];\n /**\n * `donated` means the app has run at least once and donated this intent to\n * Shortcuts on this device. `system` is a known-stable Apple intent that\n * ships with the OS.\n */\n readonly source: \"donated\" | \"system\";\n}\n\nexport interface IntentInvocationRequest {\n readonly intentId: string;\n readonly parameters: Readonly<Record<string, IntentParameterValue>>;\n}\n\nexport type IntentParameterValue =\n | string\n | number\n | boolean\n | { readonly kind: \"date\"; readonly iso: string }\n | { readonly kind: \"url\"; readonly url: string };\n\nexport interface IntentInvocationResult {\n readonly intentId: string;\n /** Whether iOS reported the intent ran end-to-end. */\n readonly success: boolean;\n /** Optional structured response payload from the intent. */\n readonly response?: Readonly<Record<string, unknown>>;\n /** Time from invocation to completion, ms. */\n readonly elapsedMs: number;\n}\n\n// ── 5. UIAccessibility (own-app reading only) ────────────────────────────────\n\nexport interface AccessibilitySnapshotNode {\n readonly id: string;\n readonly role: string;\n readonly label?: string;\n readonly value?: string;\n readonly isFocused: boolean;\n readonly children: readonly AccessibilitySnapshotNode[];\n}\n\nexport interface AccessibilitySnapshotResult {\n readonly screenName: string;\n readonly tree: AccessibilitySnapshotNode;\n readonly capturedAt: number;\n}\n\n// ── 6. Apple Foundation Models (iOS 26+) ─────────────────────────────────────\n\nexport interface FoundationModelOptions {\n /** Sampling temperature in [0,1]. Default 0.2 for deterministic-ish output. */\n readonly temperature?: number;\n /** Max generated tokens. Default 256. */\n readonly maxTokens?: number;\n /** System-style instruction; mapped to the iOS 26 system role. */\n readonly instruction?: string;\n}\n\nexport interface FoundationModelResult {\n readonly text: string;\n readonly tokensIn: number;\n readonly tokensOut: number;\n readonly elapsedMs: number;\n}\n\n// ── Bridge interface (this is the JS↔Swift contract) ─────────────────────────\n\n/**\n * Strict TS interface for the Capacitor plugin. Every method returns an\n * `IosBridgeResult<T>` — Swift never throws across the bridge.\n *\n * The Capacitor plugin name on the Swift side is `ComputerUseBridge`. The\n * `jsName` is `ComputerUse`. Method names below are the exact strings\n * registered with `CAPPluginMethod`.\n */\nexport interface IosComputerUseBridge {\n /** `{ available: true }` if iOS 26+ with all four targets bundled. */\n readonly probe: () => Promise<IosBridgeResult<IosBridgeProbe>>;\n\n // --- ReplayKit foreground ---\n readonly replayKitForegroundStart: (\n options?: ReplayKitForegroundOptions,\n ) => Promise<IosBridgeResult<ReplayKitForegroundHandle>>;\n /** Stops capture and discards the in-flight buffer. */\n readonly replayKitForegroundStop: (args: {\n readonly sessionId: string;\n }) => Promise<IosBridgeResult<{ readonly sessionId: string }>>;\n /**\n * Drains the next batch of frames since last drain. Returns up to `max`\n * frames. The Swift side ring-buffers at most 30 frames; older ones drop.\n */\n readonly replayKitForegroundDrain: (args: {\n readonly sessionId: string;\n readonly max?: number;\n }) => Promise<\n IosBridgeResult<{ readonly frames: readonly ReplayKitForegroundFrame[] }>\n >;\n\n // --- Broadcast extension ---\n readonly broadcastExtensionHandshake: () => Promise<\n IosBridgeResult<BroadcastHandshakeResult>\n >;\n\n // --- Vision OCR ---\n readonly visionOcr: (args: {\n /** Base64-encoded image (PNG or JPEG), no data URI prefix. */\n readonly imageBase64: string;\n readonly options?: VisionOcrOptions;\n }) => Promise<IosBridgeResult<VisionOcrResult>>;\n\n // --- App Intents ---\n /** Lists intents iOS knows about for the given bundle ids (or all donated). */\n readonly appIntentList: (args: {\n readonly bundleIds?: readonly string[];\n }) => Promise<IosBridgeResult<{ readonly intents: readonly IntentSpec[] }>>;\n readonly appIntentInvoke: (\n request: IntentInvocationRequest,\n ) => Promise<IosBridgeResult<IntentInvocationResult>>;\n\n // --- UIAccessibility ---\n readonly accessibilitySnapshot: () => Promise<\n IosBridgeResult<AccessibilitySnapshotResult>\n >;\n\n // --- Foundation Models ---\n readonly foundationModelGenerate: (args: {\n readonly prompt: string;\n readonly options?: FoundationModelOptions;\n }) => Promise<IosBridgeResult<FoundationModelResult>>;\n\n // --- Memory pressure (used by WS1 arbiter) ---\n /**\n * One-shot read of `os_proc_available_memory()` plus a digest of recent\n * `UIApplicationDidReceiveMemoryWarningNotification` events. The arbiter\n * also subscribes to push events via `addPressureListener`.\n */\n readonly memoryPressureProbe: () => Promise<\n IosBridgeResult<MemoryPressureSample>\n >;\n}\n\nexport interface IosBridgeProbe {\n readonly platform: \"ios\";\n /** e.g. \"26.1\" — `UIDevice.current.systemVersion`. */\n readonly osVersion: string;\n /** Capability matrix discovered at probe time. */\n readonly capabilities: {\n readonly replayKitForeground: boolean;\n readonly broadcastExtension: boolean;\n readonly visionOcr: boolean;\n readonly appIntents: boolean;\n readonly accessibilityRead: boolean;\n readonly foundationModel: boolean;\n };\n}\n\n// ── Memory-pressure contract (WS1 arbiter handoff) ───────────────────────────\n\n/**\n * Thin contract WS1 owns. The iOS bridge implements the producer side; WS1's\n * arbiter consumes via this shape. Defined here so plugin-computeruse can\n * publish samples without taking a runtime dep on the arbiter package.\n */\nexport interface IPressureSignal {\n readonly source: \"ios-uikit\" | \"android-low-memory\" | \"host-os\" | \"synthetic\";\n readonly capturedAt: number;\n /** 0 = nominal, 1 = critical. iOS warning notification → 0.7. */\n readonly severity: number;\n /** Available process memory in MB, when the source can report it. */\n readonly availableMb?: number;\n /** Free-form details for diagnostics. Never load-bearing for arbiter logic. */\n readonly details?: Readonly<Record<string, string | number | boolean>>;\n}\n\nexport interface MemoryPressureSample extends IPressureSignal {\n readonly source: \"ios-uikit\";\n /** Last received `UIApplicationDidReceiveMemoryWarningNotification`, ms epoch. */\n readonly lastWarningAt?: number;\n /** Available process memory in MB from `os_proc_available_memory`. */\n readonly availableMb: number;\n /** True if the broadcast extension is currently active. */\n readonly broadcastActive: boolean;\n}\n\n// ── Default IDs (kept in sync with Swift) ────────────────────────────────────\n\n/** App Group identifier — must match the canonical\n * `eliza/packages/app-core/platforms/ios/App/App/App.entitlements`. */\nexport const IOS_APP_GROUP_ID = \"group.ai.elizaos.app\" as const;\n\n/** Capacitor plugin jsName (Capacitor injects `Capacitor.Plugins.ComputerUse`). */\nexport const IOS_BRIDGE_JS_NAME = \"ComputerUse\" as const;\n\n/** Maximum frames buffered server-side for ReplayKit foreground draining. */\nexport const REPLAYKIT_FOREGROUND_MAX_BUFFER = 30 as const;\n\n/** Hard cap on session duration; anything beyond requires BGProcessingTask. */\nexport const REPLAYKIT_FOREGROUND_MAX_SESSION_SEC = 30 as const;\n\n// ── Runtime feature-detect ───────────────────────────────────────────────────\n\n/**\n * Result of `featureCheck()`. Callers use this to decide whether to invoke\n * any other method on the bridge — when `supported` is false they should fall\n * back to OCR / external orchestration instead of letting the call throw.\n */\nexport interface IosFeatureCheckResult {\n readonly supported: boolean;\n readonly reason?: string;\n}\n\ninterface CapacitorRuntime {\n Plugins?: Record<string, unknown>;\n}\n\nfunction readCapacitorRuntime(): CapacitorRuntime | null {\n const cap = (globalThis as { Capacitor?: unknown }).Capacitor;\n if (!cap || typeof cap !== \"object\") return null;\n return cap as CapacitorRuntime;\n}\n\n/**\n * Runtime feature-detect for the iOS bridge. Synchronous and side-effect-free\n * so it can run during planner setup. Returns `{supported:false}` whenever\n * the JS↔Swift bridge cannot be reached:\n *\n * - Running on a non-iOS host (desktop, Android, browser).\n * - Capacitor is not initialized (no `globalThis.Capacitor`).\n * - The Swift `ComputerUseBridge` plugin is not registered.\n *\n * This does NOT call `bridge.probe()` — that is async and may prompt the user\n * for permissions. Callers that need the per-capability matrix should `await\n * bridge.probe()` after `featureCheck().supported === true`.\n *\n * PARITY: untested on hardware — the lookup path mirrors what the Capacitor\n * runtime does, but has not been validated against a real iOS build.\n */\nexport function featureCheck(): IosFeatureCheckResult {\n const cap = readCapacitorRuntime();\n if (!cap) {\n return { supported: false, reason: \"Capacitor runtime not present\" };\n }\n const plugins = cap.Plugins;\n if (!plugins || typeof plugins !== \"object\") {\n return { supported: false, reason: \"Capacitor.Plugins not available\" };\n }\n if (!plugins[IOS_BRIDGE_JS_NAME]) {\n return {\n supported: false,\n reason: `Capacitor.Plugins.${IOS_BRIDGE_JS_NAME} is not registered`,\n };\n }\n return { supported: true };\n}\n\n/**\n * Resolve the live bridge handle, or `null` when unavailable. Pairs with\n * `featureCheck()` for callers that want a typed handle in one step.\n *\n * PARITY: untested on hardware — feature-detect at runtime.\n */\nexport function getIosBridge(): IosComputerUseBridge | null {\n const cap = readCapacitorRuntime();\n const handle = cap?.Plugins?.[IOS_BRIDGE_JS_NAME];\n if (!handle) return null;\n return handle as IosComputerUseBridge;\n}\n",
|
|
60
|
+
"/**\n * WS7 ↔ WS9 — `IosComputerInterface` adapts the WS7 `ComputerInterface`\n * port to the iOS Capacitor `ComputerUse` plugin.\n *\n * iOS is fundamentally NOT a click-and-keyboard surface for third-party\n * apps. The only sanctioned UI driver is App Intents (Shortcuts-style\n * invocations). The mapping below reflects that — cascade dispatch\n * primitives that exist on Android (tap / swipe / type) throw a clear\n * \"use invokeAppIntent\" message on iOS.\n *\n * What *is* supported:\n *\n * screenshot() → drain one frame from `replayKitForegroundDrain`\n * (caller is responsible for having started a\n * session via `replayKitForegroundStart`).\n * getScreenSize, coord → metadata, no bridge call.\n * getAccessibilityTree() → scene-provided tree from WS6; iOS itself\n * cannot read cross-app AX, so this is\n * own-app only (`accessibilitySnapshot`).\n * invokeAppIntent(...) → the canonical iOS \"action\" — planner picks\n * an intent id + parameters, this method calls\n * `bridge.appIntentInvoke(...)`.\n *\n * What is NOT supported (and throws with a redirect message):\n *\n * leftClick / rightClick / doubleClick / dragTo / drag / mouseDown /\n * mouseUp / keyDown / keyUp / typeText / pressKey / hotkey / scroll\n *\n * The cascade detects iOS via the platform-capabilities probe and is\n * expected to plan in terms of `invokeAppIntent`, not synthetic taps. The\n * `IosComputerInterface.invokeAppIntent` accessor surfaces that contract\n * cleanly so callers don't have to reach into the raw Capacitor bridge.\n */\n\nimport { logger } from \"@elizaos/core\";\nimport type {\n ComputerInterface,\n CursorPosition,\n DisplayPoint,\n DragPath,\n MouseButton,\n ScreenshotResult,\n ScrollDelta,\n} from \"../actor/computer-interface.js\";\nimport type { Scene, SceneAxNode } from \"../scene/scene-types.js\";\nimport type { DisplayDescriptor } from \"../types.js\";\nimport type {\n IntentInvocationRequest,\n IntentInvocationResult,\n IosBridgeResult,\n IosComputerUseBridge,\n ReplayKitForegroundFrame,\n} from \"./ios-bridge.js\";\n\n/**\n * Stable logical display id for the iOS phone screen. Mirrors the\n * Android convention (`ANDROID_LOGICAL_DISPLAY_ID = 0`) so the cascade\n * doesn't branch on platform for display selection — there's exactly\n * one logical display on iOS.\n */\nexport const IOS_LOGICAL_DISPLAY_ID = 0 as const;\n\n/** Default physical bounds when the bridge hasn't reported a frame yet. */\nconst IOS_FALLBACK_BOUNDS: readonly [number, number, number, number] = [\n 0,\n 0,\n 393,\n 852, // iPhone 15 logical points; the cascade re-derives from frames.\n];\n\nexport interface IosComputerInterfaceDeps {\n /** Capacitor plugin handle (null when off-platform). */\n getBridge: () => IosComputerUseBridge | null;\n /** Latest scene accessor — used for `getAccessibilityTree`. */\n getScene?: () => Scene | null;\n /**\n * Active ReplayKit session id. The arbiter / scene-builder owns the\n * session lifecycle (start before cascade tick, stop when idle); this\n * interface only drains frames from it.\n */\n getReplayKitSessionId?: () => string | null;\n /** Display descriptor; iOS has exactly one logical display. */\n getDisplay?: () => DisplayDescriptor;\n /** Internal cursor-position state, mostly for tests. */\n cursorState?: { current: CursorPosition };\n /** Override JPEG decode (defaults to base64 → Buffer). */\n decodeJpeg?: (b64: string) => Buffer;\n}\n\n/**\n * iOS adapter implementing the WS7 `ComputerInterface`. All input-bearing\n * methods throw with a \"use invokeAppIntent\" redirect; metadata + the\n * screenshot path are functional.\n */\nexport class IosComputerInterface implements ComputerInterface {\n private readonly deps: IosComputerInterfaceDeps;\n private readonly cursorState: { current: CursorPosition };\n\n constructor(deps: IosComputerInterfaceDeps) {\n this.deps = deps;\n this.cursorState = deps.cursorState ?? {\n current: { displayId: IOS_LOGICAL_DISPLAY_ID, x: 0, y: 0 },\n };\n }\n\n // ── Screenshot ─────────────────────────────────────────────────────────────\n\n async screenshot(\n opts: { displayId?: number } = {},\n ): Promise<ScreenshotResult> {\n this.requireDisplayId(opts.displayId);\n const bridge = this.requireBridge();\n const sessionId = this.deps.getReplayKitSessionId?.();\n if (!sessionId) {\n throw new Error(\n \"[computeruse/ios] screenshot requires an active ReplayKit session — call replayKitForegroundStart first via the WS6 scene-capture orchestrator.\",\n );\n }\n const result = unwrap(\n await bridge.replayKitForegroundDrain({ sessionId, max: 1 }),\n \"replayKitForegroundDrain\",\n );\n const frame: ReplayKitForegroundFrame | undefined = result.frames[0];\n if (!frame) {\n throw new Error(\n \"[computeruse/ios] replayKitForegroundDrain returned no frames — caller must back off and retry next tick.\",\n );\n }\n const decoded = (this.deps.decodeJpeg ?? defaultDecodeJpeg)(\n frame.jpegBase64,\n );\n return {\n displayId: IOS_LOGICAL_DISPLAY_ID,\n frame: decoded,\n scaleFactor: 1,\n bounds: [0, 0, frame.width, frame.height],\n };\n }\n\n // ── Input-bearing primitives — all throw with a redirect to App Intents ──\n\n async mouseDown(\n point: DisplayPoint & { button?: MouseButton },\n ): Promise<void> {\n this.refuseInput(\"mouseDown\", point);\n }\n\n async mouseUp(point: DisplayPoint & { button?: MouseButton }): Promise<void> {\n this.refuseInput(\"mouseUp\", point);\n }\n\n async leftClick(point: DisplayPoint): Promise<void> {\n this.refuseInput(\"leftClick\", point);\n }\n\n async rightClick(point: DisplayPoint): Promise<void> {\n this.refuseInput(\"rightClick\", point);\n }\n\n async doubleClick(point: DisplayPoint): Promise<void> {\n this.refuseInput(\"doubleClick\", point);\n }\n\n async moveCursor(point: DisplayPoint): Promise<void> {\n // No-op (no cursor on iOS); we still update the tracker so downstream\n // metadata reads stay consistent with the planner's intent.\n this.requireDisplayId(point.displayId);\n this.requireFiniteCoords(point);\n this.cursorState.current = { ...point };\n }\n\n async dragTo(point: DisplayPoint): Promise<void> {\n this.refuseInput(\"dragTo\", point);\n }\n\n async drag(path: DragPath): Promise<void> {\n this.refuseInput(\"drag\", { displayId: path.displayId, x: 0, y: 0 });\n }\n\n async keyDown(args: { key: string }): Promise<void> {\n this.refuseKeyboard(\"keyDown\", args.key);\n }\n\n async keyUp(args: { key: string }): Promise<void> {\n this.refuseKeyboard(\"keyUp\", args.key);\n }\n\n async typeText(args: { text: string }): Promise<void> {\n this.refuseKeyboard(\"typeText\", args.text.slice(0, 16));\n }\n\n async pressKey(args: { key: string }): Promise<void> {\n this.refuseKeyboard(\"pressKey\", args.key);\n }\n\n async hotkey(args: { keys: string[] }): Promise<void> {\n this.refuseKeyboard(\"hotkey\", args.keys.join(\"+\"));\n }\n\n async scroll(delta: ScrollDelta): Promise<void> {\n this.refuseInput(\"scroll\", {\n displayId: delta.displayId,\n x: delta.x,\n y: delta.y,\n });\n }\n\n async scrollUp(args: { displayId: number; clicks: number }): Promise<void> {\n this.refuseInput(\"scrollUp\", { displayId: args.displayId, x: 0, y: 0 });\n }\n\n async scrollDown(args: { displayId: number; clicks: number }): Promise<void> {\n this.refuseInput(\"scrollDown\", { displayId: args.displayId, x: 0, y: 0 });\n }\n\n // ── Metadata (no bridge call) ──────────────────────────────────────────────\n\n getScreenSize(_args: { displayId: number }): { w: number; h: number } {\n const display = this.getDisplay();\n return { w: display.bounds[2], h: display.bounds[3] };\n }\n\n getCursorPosition(): CursorPosition {\n return { ...this.cursorState.current };\n }\n\n toScreenCoordinates(args: {\n displayId: number;\n imgX: number;\n imgY: number;\n imgW: number;\n imgH: number;\n }): { x: number; y: number } {\n this.requireDisplayId(args.displayId);\n if (args.imgW <= 0 || args.imgH <= 0) {\n throw new Error(\n \"[computeruse/ios] toScreenCoordinates requires positive image dimensions\",\n );\n }\n const display = this.getDisplay();\n const sx = display.bounds[2] / args.imgW;\n const sy = display.bounds[3] / args.imgH;\n return {\n x: Math.round(args.imgX * sx),\n y: Math.round(args.imgY * sy),\n };\n }\n\n toScreenshotCoordinates(args: {\n displayId: number;\n x: number;\n y: number;\n imgW: number;\n imgH: number;\n }): { imgX: number; imgY: number } {\n this.requireDisplayId(args.displayId);\n const display = this.getDisplay();\n if (display.bounds[2] <= 0 || display.bounds[3] <= 0) {\n throw new Error(\n \"[computeruse/ios] toScreenshotCoordinates: display has zero bounds\",\n );\n }\n const sx = args.imgW / display.bounds[2];\n const sy = args.imgH / display.bounds[3];\n return {\n imgX: Math.round(args.x * sx),\n imgY: Math.round(args.y * sy),\n };\n }\n\n getAccessibilityTree(args: { displayId?: number }): SceneAxNode[] {\n const scene = this.deps.getScene?.() ?? null;\n if (!scene) return [];\n if (args.displayId === undefined) return scene.ax;\n return scene.ax.filter((n) => n.displayId === args.displayId);\n }\n\n // ── iOS-only: App Intent invocation (the sanctioned UI driver) ─────────────\n\n /**\n * Invoke an AppIntent through the bridge. This is the iOS-only addition\n * to the WS7 surface — it does not exist on Android/desktop because\n * those platforms have direct input. Cascade planners that detect iOS\n * via the platform-capabilities probe should plan in `invokeAppIntent`\n * terms (intent id + parameters) instead of `leftClick`.\n */\n async invokeAppIntent(\n request: IntentInvocationRequest,\n ): Promise<IntentInvocationResult> {\n const bridge = this.requireBridge();\n const result = await bridge.appIntentInvoke(request);\n if (!result.ok) {\n const err = result as { ok: false; code: string; message: string };\n throw new Error(\n `[computeruse/ios] appIntentInvoke(${request.intentId}) failed: ${err.code} — ${err.message}`,\n );\n }\n return result.data;\n }\n\n // ── Internals ──────────────────────────────────────────────────────────────\n\n private refuseInput(method: string, point: DisplayPoint): never {\n logger.warn(\n `[computeruse/ios] ${method}(${point.x},${point.y}) refused — iOS has no third-party input dispatch. Plan in App Intents and call invokeAppIntent instead.`,\n );\n throw new Error(\n `[computeruse/ios] ${method} is not supported on iOS — use invokeAppIntent(intentId, parameters). See plugin-computeruse/docs/IOS_CONSTRAINTS.md.`,\n );\n }\n\n private refuseKeyboard(method: string, key: string): never {\n logger.warn(\n `[computeruse/ios] ${method}(\"${key}\") refused — iOS has no third-party key dispatch.`,\n );\n throw new Error(\n `[computeruse/ios] ${method} is not supported on iOS — keyboards are app-local only. See plugin-computeruse/docs/IOS_CONSTRAINTS.md.`,\n );\n }\n\n private requireBridge(): IosComputerUseBridge {\n const bridge = this.deps.getBridge();\n if (!bridge) {\n throw new Error(\n \"[computeruse/ios] Capacitor ComputerUse bridge is not registered (running off-platform?)\",\n );\n }\n return bridge;\n }\n\n private requireDisplayId(id: number | undefined): void {\n const effective = id ?? IOS_LOGICAL_DISPLAY_ID;\n if (effective !== IOS_LOGICAL_DISPLAY_ID) {\n throw new Error(\n `[computeruse/ios] unknown iOS displayId ${effective}; only ${IOS_LOGICAL_DISPLAY_ID} is supported`,\n );\n }\n }\n\n private requireFiniteCoords(p: DisplayPoint): void {\n if (!Number.isFinite(p.x) || !Number.isFinite(p.y)) {\n throw new Error(`[computeruse/ios] non-finite coords (${p.x}, ${p.y})`);\n }\n }\n\n private getDisplay(): DisplayDescriptor {\n if (this.deps.getDisplay) return this.deps.getDisplay();\n return {\n id: IOS_LOGICAL_DISPLAY_ID,\n bounds: [...IOS_FALLBACK_BOUNDS] as [number, number, number, number],\n scaleFactor: 1,\n primary: true,\n name: \"ios-screen\",\n };\n }\n}\n\n/** Convenience factory mirroring the Android side. */\nexport function makeIosComputerInterface(\n deps: IosComputerInterfaceDeps,\n): IosComputerInterface {\n return new IosComputerInterface(deps);\n}\n\nfunction unwrap<T>(result: IosBridgeResult<T>, label: string): T {\n if (result.ok) return result.data;\n // Narrow to the failure arm explicitly — see ocr-provider.ts for the\n // strict-mode rationale.\n const failure = result as Extract<typeof result, { ok: false }>;\n throw new Error(\n `[computeruse/ios] ${label} failed: ${failure.code} — ${failure.message}`,\n );\n}\n\nfunction defaultDecodeJpeg(b64: string): Buffer {\n return Buffer.from(b64, \"base64\");\n}\n",
|
|
61
|
+
"import type http from \"node:http\";\n\nconst EMPTY_APPROVAL_SNAPSHOT = {\n mode: \"full_control\",\n pendingCount: 0,\n pendingApprovals: [],\n} as const;\n\nfunction sendJson(\n res: http.ServerResponse,\n status: number,\n body: unknown,\n): void {\n if (res.headersSent) return;\n res.statusCode = status;\n res.setHeader(\"content-type\", \"application/json; charset=utf-8\");\n res.end(JSON.stringify(body));\n}\n\nfunction sendEmptyApprovalStream(res: http.ServerResponse): void {\n res.writeHead(200, {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache, no-transform\",\n Connection: \"keep-alive\",\n });\n res.write(\n `data: ${JSON.stringify({ type: \"snapshot\", snapshot: EMPTY_APPROVAL_SNAPSHOT })}\\n\\n`,\n );\n}\n\nexport async function handleComputerUseRoutes(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n pathname: string,\n method: string,\n): Promise<boolean> {\n if (!pathname.startsWith(\"/api/computer-use/\")) {\n return false;\n }\n\n if (method === \"GET\" && pathname === \"/api/computer-use/approvals\") {\n sendJson(res, 200, EMPTY_APPROVAL_SNAPSHOT);\n return true;\n }\n\n if (method === \"GET\" && pathname === \"/api/computer-use/approvals/stream\") {\n sendEmptyApprovalStream(res);\n req.on(\"close\", () => {\n res.end();\n });\n return true;\n }\n\n if (method === \"POST\" && pathname === \"/api/computer-use/approval-mode\") {\n sendJson(res, 200, { mode: EMPTY_APPROVAL_SNAPSHOT.mode });\n return true;\n }\n\n const approvalDecision = /^\\/api\\/computer-use\\/approvals\\/([^/]+)$/.exec(\n pathname,\n );\n if (method === \"POST\" && approvalDecision) {\n sendJson(res, 404, {\n error: \"Computer-use approval is not pending.\",\n id: decodeURIComponent(approvalDecision[1] ?? \"\"),\n });\n return true;\n }\n\n return false;\n}\n",
|
|
62
|
+
"/** Sandbox capability API routes: status, exec, browser, screen, audio, computer use. */\n\nimport { execFileSync, execSync } from \"node:child_process\";\nimport { readFileSync, unlinkSync, writeFileSync } from \"node:fs\";\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\nimport { platform, tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport {\n readJsonBody as parseJsonBody,\n readRequestBody,\n sendJson as sendJsonResponse,\n} from \"@elizaos/core\";\n\ninterface SandboxExecResult {\n exitCode: number;\n stdout: string;\n stderr: string;\n durationMs: number;\n executedInSandbox: boolean;\n}\n\ninterface SandboxManager {\n getStatus(): unknown;\n getEventLog(): unknown[];\n start(): Promise<void>;\n stop(): Promise<void>;\n recover(): Promise<void>;\n exec(options: {\n command: string;\n workdir?: string;\n timeoutMs?: number;\n }): Promise<SandboxExecResult>;\n getBrowserCdpEndpoint(): string | null;\n getBrowserWsEndpoint(): string | null;\n getBrowserNoVncEndpoint(): string | null;\n}\n\ninterface SigningRequest {\n requestId: string;\n chainId: number;\n to: string;\n value: string;\n data: string;\n nonce?: number;\n gasLimit?: string;\n createdAt: number;\n}\n\ninterface SigningResult {\n success: boolean;\n [key: string]: unknown;\n}\n\ninterface RemoteSigningService {\n submitSigningRequest(request: SigningRequest): Promise<SigningResult>;\n approveRequest(requestId: string): Promise<SigningResult>;\n rejectRequest(requestId: string): boolean;\n getPendingApprovals(): unknown[];\n getAddress(): Promise<string>;\n}\n\ninterface SandboxRouteState {\n sandboxManager: SandboxManager | null;\n signingService?: RemoteSigningService | null;\n}\n\nconst MAX_COMPUTER_INPUT_LENGTH = 4096;\nconst MAX_KEYPRESS_LENGTH = 128;\nconst SAFE_KEYPRESS_PATTERN = /^[A-Za-z0-9+_.,: -]+$/;\nconst ALLOWED_AUDIO_FORMATS = new Set([\"wav\", \"mp3\", \"ogg\", \"flac\", \"m4a\"]);\nconst MIN_AUDIO_RECORD_DURATION_MS = 250;\nconst MAX_AUDIO_RECORD_DURATION_MS = 30_000;\n\n// ── Route handler ────────────────────────────────────────────────────────────\n\n/** Returns `true` if handled, `false` to fall through. */\nexport async function handleSandboxRoute(\n req: IncomingMessage,\n res: ServerResponse,\n pathname: string,\n method: string,\n state: SandboxRouteState,\n): Promise<boolean> {\n if (!pathname.startsWith(\"/api/sandbox\")) {\n return false;\n }\n\n const mgr = state.sandboxManager;\n\n // Platform info doesn't require a running manager\n if (method === \"GET\" && pathname === \"/api/sandbox/platform\") {\n sendJson(res, 200, getPlatformInfo());\n return true;\n }\n\n // ── POST /api/sandbox/docker/start ────────────────────────────────\n // Attempt to start Docker Desktop (works on macOS/Windows desktop builds)\n if (method === \"POST\" && pathname === \"/api/sandbox/docker/start\") {\n try {\n const result = attemptDockerStart();\n sendJson(res, 200, result);\n } catch (err) {\n sendJson(res, 500, {\n success: false,\n error: `Failed to start Docker: ${String(err)}`,\n });\n }\n return true;\n }\n\n if (!mgr) {\n sendJson(res, 503, {\n error: \"Sandbox manager not initialized\",\n });\n return true;\n }\n\n // ── GET /api/sandbox/status ─────────────────────────────────────────\n if (method === \"GET\" && pathname === \"/api/sandbox/status\") {\n sendJson(res, 200, mgr.getStatus());\n return true;\n }\n\n // ── GET /api/sandbox/events ─────────────────────────────────────────\n if (method === \"GET\" && pathname === \"/api/sandbox/events\") {\n const events = mgr.getEventLog();\n sendJson(res, 200, { events: events.slice(-100) });\n return true;\n }\n\n // ── POST /api/sandbox/start ─────────────────────────────────────────\n if (method === \"POST\" && pathname === \"/api/sandbox/start\") {\n try {\n await mgr.start();\n sendJson(res, 200, mgr.getStatus());\n } catch (err) {\n sendJson(res, 500, {\n error: `Failed to start sandbox: ${String(err)}`,\n });\n }\n return true;\n }\n\n // ── POST /api/sandbox/stop ──────────────────────────────────────────\n if (method === \"POST\" && pathname === \"/api/sandbox/stop\") {\n try {\n await mgr.stop();\n sendJson(res, 200, mgr.getStatus());\n } catch (err) {\n sendJson(res, 500, {\n error: `Failed to stop sandbox: ${String(err)}`,\n });\n }\n return true;\n }\n\n // ── POST /api/sandbox/recover ───────────────────────────────────────\n if (method === \"POST\" && pathname === \"/api/sandbox/recover\") {\n try {\n await mgr.recover();\n sendJson(res, 200, mgr.getStatus());\n } catch (err) {\n sendJson(res, 500, {\n error: `Recovery failed: ${String(err)}`,\n });\n }\n return true;\n }\n\n // ── POST /api/sandbox/exec ──────────────────────────────────────────\n if (method === \"POST\" && pathname === \"/api/sandbox/exec\") {\n const parsed = await readJsonBody<{\n command?: string;\n workdir?: string;\n timeoutMs?: number;\n }>(req, res);\n if (!parsed) return true;\n\n if (!parsed.command || typeof parsed.command !== \"string\") {\n sendJson(res, 400, { error: \"Missing 'command' field\" });\n return true;\n }\n\n const result = await mgr.exec({\n command: parsed.command,\n workdir: parsed.workdir,\n timeoutMs: parsed.timeoutMs,\n });\n\n sendJson(res, result.exitCode === 0 ? 200 : 422, result);\n return true;\n }\n\n // ── GET /api/sandbox/browser ────────────────────────────────────────\n if (method === \"GET\" && pathname === \"/api/sandbox/browser\") {\n sendJson(res, 200, {\n cdpEndpoint: mgr.getBrowserCdpEndpoint(),\n wsEndpoint: mgr.getBrowserWsEndpoint(),\n noVncEndpoint: mgr.getBrowserNoVncEndpoint(),\n });\n return true;\n }\n\n // ── Capability bridges ──────────────────────────────────────────────\n if (method === \"GET\" && pathname === \"/api/sandbox/screen/screenshot\") {\n try {\n const screenshot = captureScreenshot();\n res.writeHead(200, {\n \"Content-Type\": \"image/png\",\n \"Content-Length\": screenshot.length,\n });\n res.end(screenshot);\n } catch (err) {\n sendJson(res, 500, {\n error: `Screenshot failed: ${String(err)}`,\n });\n }\n return true;\n }\n\n // ── POST /api/sandbox/screen/screenshot ─────────────────────────────\n // Returns base64-encoded screenshot for easy consumption by agents\n if (method === \"POST\" && pathname === \"/api/sandbox/screen/screenshot\") {\n const rawBody = await readBody(req);\n if (!rawBody?.trim()) {\n sendJson(res, 200, {\n format: \"png\",\n encoding: \"base64\",\n width: null,\n height: null,\n data: captureScreenshot().toString(\"base64\"),\n });\n return true;\n }\n\n let regionInput: unknown;\n try {\n regionInput = JSON.parse(rawBody);\n } catch {\n sendJson(res, 400, { error: \"Invalid JSON body\" });\n return true;\n }\n\n const region = resolveScreenshotRegion(regionInput);\n if (region.error) {\n sendJson(res, 400, { error: region.error });\n return true;\n }\n\n try {\n const screenshot = captureScreenshot(region.region);\n const base64 = screenshot.toString(\"base64\");\n sendJson(res, 200, {\n format: \"png\",\n encoding: \"base64\",\n width: null, // platform-dependent\n height: null,\n data: base64,\n });\n } catch (err) {\n sendJson(res, 500, {\n error: `Screenshot failed: ${String(err)}`,\n });\n }\n return true;\n }\n\n // ── GET /api/sandbox/screen/windows ─────────────────────────────────\n if (method === \"GET\" && pathname === \"/api/sandbox/screen/windows\") {\n try {\n const windows = listWindows();\n sendJson(res, 200, { windows });\n } catch (err) {\n sendJson(res, 200, { windows: [], error: String(err) });\n }\n return true;\n }\n\n // ── POST /api/sandbox/audio/record ──────────────────────────────────\n if (method === \"POST\" && pathname === \"/api/sandbox/audio/record\") {\n const body = await readBody(req);\n let durationMs = 5000;\n if (body) {\n let parsed: unknown;\n try {\n parsed = JSON.parse(body);\n } catch {\n sendJson(res, 400, {\n error: \"Invalid JSON in request body\",\n });\n return true;\n }\n\n if (\n parsed === null ||\n typeof parsed !== \"object\" ||\n Array.isArray(parsed)\n ) {\n sendJson(res, 400, { error: \"Request body must be a JSON object\" });\n return true;\n }\n\n const bodyValues = parsed as Record<string, unknown>;\n\n if (Object.hasOwn(bodyValues, \"durationMs\")) {\n const durationValue = bodyValues.durationMs;\n if (typeof durationValue !== \"number\") {\n sendJson(res, 400, {\n error: \"durationMs must be a finite number\",\n });\n return true;\n }\n // Defense in depth: JSON.parse only produces finite numbers, but this guard\n // keeps behavior explicit as parser/runtime behavior evolves.\n if (!Number.isFinite(durationValue)) {\n sendJson(res, 400, {\n error: \"durationMs must be a finite number\",\n });\n return true;\n }\n if (!Number.isInteger(durationValue)) {\n sendJson(res, 400, {\n error: \"durationMs must be an integer number of milliseconds\",\n });\n return true;\n }\n if (\n durationValue < MIN_AUDIO_RECORD_DURATION_MS ||\n durationValue > MAX_AUDIO_RECORD_DURATION_MS\n ) {\n sendJson(res, 400, {\n error: `durationMs must be between ${MIN_AUDIO_RECORD_DURATION_MS} and ${MAX_AUDIO_RECORD_DURATION_MS} milliseconds`,\n });\n return true;\n }\n durationMs = durationValue;\n }\n }\n try {\n const audio = await recordAudio(durationMs);\n sendJson(res, 200, {\n format: \"wav\",\n encoding: \"base64\",\n durationMs,\n data: audio.toString(\"base64\"),\n });\n } catch (err) {\n sendJson(res, 500, {\n error: `Audio recording failed: ${String(err)}`,\n });\n }\n return true;\n }\n\n // ── POST /api/sandbox/audio/play ────────────────────────────────────\n if (method === \"POST\" && pathname === \"/api/sandbox/audio/play\") {\n const parsed = await readJsonBody(req, res);\n if (!parsed) return true;\n\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n sendJson(res, 400, { error: \"Body must be a JSON object\" });\n return true;\n }\n\n const payload = parsed as { data?: unknown; format?: unknown };\n if (typeof payload.data !== \"string\" || !payload.data.trim()) {\n sendJson(res, 400, { error: \"Missing 'data' field (base64 audio)\" });\n return true;\n }\n\n const formatResult = resolveAudioFormat(payload.format);\n if (formatResult.error) {\n sendJson(res, 400, { error: formatResult.error });\n return true;\n }\n\n try {\n await playAudio(Buffer.from(payload.data, \"base64\"), formatResult.format);\n sendJson(res, 200, { success: true });\n } catch (err) {\n sendJson(res, 500, {\n error: `Audio playback failed: ${String(err)}`,\n });\n }\n return true;\n }\n\n // ── POST /api/sandbox/computer/click ────────────────────────────────\n if (method === \"POST\" && pathname === \"/api/sandbox/computer/click\") {\n const parsed = await readJsonBody(req, res);\n if (!parsed) return true;\n\n const clickPayload = resolveClickPayload(parsed);\n if (clickPayload.error) {\n sendJson(res, 400, { error: clickPayload.error });\n return true;\n }\n\n try {\n const { x, y, button } = clickPayload;\n performClick(x, y, button);\n sendJson(res, 200, { success: true, x, y, button });\n } catch (err) {\n sendJson(res, 500, {\n error: `Click failed: ${String(err)}`,\n });\n }\n return true;\n }\n\n // ── POST /api/sandbox/computer/type ─────────────────────────────────\n if (method === \"POST\" && pathname === \"/api/sandbox/computer/type\") {\n const parsed = await readJsonBody(req, res);\n if (!parsed) return true;\n\n const typePayload = resolveTypePayload(parsed);\n if (typePayload.error) {\n sendJson(res, 400, { error: typePayload.error });\n return true;\n }\n\n try {\n const { text } = typePayload;\n performType(text);\n sendJson(res, 200, { success: true, length: text.length });\n } catch (err) {\n sendJson(res, 500, {\n error: `Type failed: ${String(err)}`,\n });\n }\n return true;\n }\n\n // ── POST /api/sandbox/computer/keypress ─────────────────────────────\n if (method === \"POST\" && pathname === \"/api/sandbox/computer/keypress\") {\n const parsed = await readJsonBody(req, res);\n if (!parsed) return true;\n\n const keypressPayload = resolveKeypressPayload(parsed);\n if (keypressPayload.error) {\n sendJson(res, 400, { error: keypressPayload.error });\n return true;\n }\n\n try {\n const { keys } = keypressPayload;\n performKeypress(keys);\n sendJson(res, 200, { success: true, keys });\n } catch (err) {\n sendJson(res, 500, {\n error: `Keypress failed: ${String(err)}`,\n });\n }\n return true;\n }\n\n // ── Signing routes ─────────────────────────────────────────────────\n\n if (method === \"POST\" && pathname === \"/api/sandbox/sign\") {\n const signer = state.signingService;\n if (!signer) {\n sendJson(res, 503, { error: \"Signing service not configured\" });\n return true;\n }\n const body = await readJsonBody<unknown>(req, res);\n if (body === null) return true;\n const parsed = resolveSigningRequestPayload(body);\n if (\"error\" in parsed) {\n sendJson(res, 400, { error: parsed.error });\n return true;\n }\n try {\n const result = await signer.submitSigningRequest(parsed.request);\n sendJson(res, result.success ? 200 : 403, result);\n } catch (err) {\n sendJson(res, 400, {\n error: `Invalid request: ${String(err)}`,\n });\n }\n return true;\n }\n\n if (method === \"POST\" && pathname === \"/api/sandbox/sign/approve\") {\n const signer = state.signingService;\n if (!signer) {\n sendJson(res, 503, { error: \"Signing service not configured\" });\n return true;\n }\n const body = await readJsonBody<{ requestId?: string }>(req, res);\n if (!body) return true;\n try {\n const { requestId } = body as { requestId: string };\n const result = await signer.approveRequest(requestId);\n sendJson(res, result.success ? 200 : 403, result);\n } catch (err) {\n sendJson(res, 400, { error: String(err) });\n }\n return true;\n }\n\n if (method === \"POST\" && pathname === \"/api/sandbox/sign/reject\") {\n const signer = state.signingService;\n if (!signer) {\n sendJson(res, 503, { error: \"Signing service not configured\" });\n return true;\n }\n const body = await readJsonBody<{ requestId?: string }>(req, res);\n if (!body) return true;\n try {\n const { requestId } = body as { requestId: string };\n const rejected = signer.rejectRequest(requestId);\n sendJson(res, 200, { rejected });\n } catch (err) {\n sendJson(res, 400, { error: String(err) });\n }\n return true;\n }\n\n if (method === \"GET\" && pathname === \"/api/sandbox/sign/pending\") {\n const signer = state.signingService;\n if (!signer) {\n sendJson(res, 503, { error: \"Signing service not configured\" });\n return true;\n }\n sendJson(res, 200, { pending: signer.getPendingApprovals() });\n return true;\n }\n\n if (method === \"GET\" && pathname === \"/api/sandbox/sign/address\") {\n const signer = state.signingService;\n if (!signer) {\n sendJson(res, 503, { error: \"Signing service not configured\" });\n return true;\n }\n try {\n const address = await signer.getAddress();\n sendJson(res, 200, { address });\n } catch (err) {\n sendJson(res, 500, { error: String(err) });\n }\n return true;\n }\n\n // ── GET /api/sandbox/capabilities ───────────────────────────────────\n if (method === \"GET\" && pathname === \"/api/sandbox/capabilities\") {\n sendJson(res, 200, detectCapabilities());\n return true;\n }\n\n // ── Fallthrough ─────────────────────────────────────────────────────\n sendJson(res, 404, { error: `Unknown sandbox route: ${method} ${pathname}` });\n return true;\n}\n\nfunction asObject(value: unknown): Record<string, unknown> | null {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return null;\n return value as Record<string, unknown>;\n}\n\nfunction resolveSigningRequestPayload(\n input: unknown,\n): { request: SigningRequest } | { error: string } {\n const obj = asObject(input);\n if (!obj) {\n return { error: \"Signing payload must be a JSON object\" };\n }\n\n const requestId = obj.requestId;\n const chainId = parseFiniteInteger(obj.chainId);\n const to = obj.to;\n const value = obj.value;\n const data = obj.data;\n const nonce =\n obj.nonce === undefined ? undefined : parseFiniteInteger(obj.nonce);\n const rawGasLimit = obj.gasLimit;\n const createdAt = parseFiniteInteger(obj.createdAt);\n\n if (typeof requestId !== \"string\" || !requestId.trim()) {\n return { error: \"Signing payload requires a non-empty string 'requestId'\" };\n }\n if (chainId === null || chainId < 0) {\n return { error: \"Signing payload requires an integer 'chainId' >= 0\" };\n }\n if (typeof to !== \"string\" || !/^0x[0-9a-fA-F]{40}$/.test(to.trim())) {\n return {\n error:\n \"Signing payload requires a hex 'to' address (e.g., 0x followed by 40 hex characters)\",\n };\n }\n if (typeof value !== \"string\" || !value.trim()) {\n return { error: \"Signing payload requires a non-empty string 'value'\" };\n }\n if (typeof data !== \"string\" || !data.trim()) {\n return { error: \"Signing payload requires a non-empty string 'data'\" };\n }\n if (nonce === null) {\n return { error: \"'nonce' must be a non-negative integer when provided\" };\n }\n if (createdAt === null) {\n return { error: \"Signing payload requires an integer 'createdAt'\" };\n }\n if (rawGasLimit !== undefined && typeof rawGasLimit !== \"string\") {\n return {\n error: \"Signing payload 'gasLimit' must be a string when provided\",\n };\n }\n\n const gasLimit = (rawGasLimit as string | undefined)?.trim();\n if (gasLimit === \"\") {\n return {\n error: \"Signing payload 'gasLimit' cannot be empty when provided\",\n };\n }\n\n return {\n request: {\n requestId: requestId.trim(),\n chainId,\n to: to.trim(),\n value: value.trim(),\n data,\n ...(nonce === undefined ? {} : { nonce }),\n ...(gasLimit === undefined ? {} : { gasLimit }),\n createdAt,\n },\n };\n}\n\nfunction parseFiniteInteger(value: unknown): number | null {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return null;\n if (!Number.isInteger(value)) return null;\n return value;\n}\n\nfunction resolveScreenshotRegion(input: unknown): {\n region?: { x: number; y: number; width: number; height: number };\n error?: string;\n} {\n if (input === undefined || input === null) return {};\n const obj = asObject(input);\n if (!obj) return { error: \"Screenshot region payload must be a JSON object\" };\n\n const hasRegionField =\n \"x\" in obj || \"y\" in obj || \"width\" in obj || \"height\" in obj;\n if (!hasRegionField) return {};\n\n const x = parseFiniteInteger(obj.x);\n const y = parseFiniteInteger(obj.y);\n const width = parseFiniteInteger(obj.width);\n const height = parseFiniteInteger(obj.height);\n\n if (x === null || y === null || width === null || height === null) {\n return {\n error: \"Region requires integer x, y, width, and height values\",\n };\n }\n if (width <= 0 || height <= 0) {\n return { error: \"Region width and height must be greater than 0\" };\n }\n\n return {\n region: { x, y, width, height },\n };\n}\n\nfunction resolveClickPayload(input: unknown): {\n x: number;\n y: number;\n button: \"left\" | \"right\";\n error?: string;\n} {\n const obj = asObject(input);\n if (!obj) {\n return {\n x: 0,\n y: 0,\n button: \"left\",\n error: \"Click payload must be a JSON object\",\n };\n }\n\n const x = parseFiniteInteger(obj.x);\n const y = parseFiniteInteger(obj.y);\n if (x === null || y === null) {\n return {\n x: 0,\n y: 0,\n button: \"left\",\n error: \"Click payload requires integer x and y coordinates\",\n };\n }\n\n const rawButton = obj.button;\n let button: \"left\" | \"right\" = \"left\";\n if (rawButton !== undefined) {\n if (rawButton !== \"left\" && rawButton !== \"right\") {\n return {\n x,\n y,\n button,\n error: \"button must be either 'left' or 'right'\",\n };\n }\n button = rawButton;\n }\n\n return { x, y, button };\n}\n\nfunction resolveTypePayload(input: unknown): { text: string; error?: string } {\n const obj = asObject(input);\n if (!obj) return { text: \"\", error: \"Type payload must be a JSON object\" };\n if (typeof obj.text !== \"string\") {\n return { text: \"\", error: \"Type payload requires a string 'text' field\" };\n }\n if (obj.text.length === 0) {\n return { text: \"\", error: \"text cannot be empty\" };\n }\n if (obj.text.length > MAX_COMPUTER_INPUT_LENGTH) {\n return {\n text: \"\",\n error: `text exceeds maximum length (${MAX_COMPUTER_INPUT_LENGTH})`,\n };\n }\n return { text: obj.text };\n}\n\nfunction resolveKeypressPayload(input: unknown): {\n keys: string;\n error?: string;\n} {\n const obj = asObject(input);\n if (!obj) {\n return { keys: \"\", error: \"Keypress payload must be a JSON object\" };\n }\n if (typeof obj.keys !== \"string\") {\n return {\n keys: \"\",\n error: \"Keypress payload requires a string 'keys' field\",\n };\n }\n\n const keys = obj.keys.trim();\n if (!keys) return { keys: \"\", error: \"keys cannot be empty\" };\n if (keys.length > MAX_KEYPRESS_LENGTH) {\n return {\n keys: \"\",\n error: `keys exceeds maximum length (${MAX_KEYPRESS_LENGTH})`,\n };\n }\n if (!SAFE_KEYPRESS_PATTERN.test(keys)) {\n return {\n keys: \"\",\n error:\n \"keys contains unsupported characters; allowed: letters, numbers, space, +, _, ., ,, :, -\",\n };\n }\n\n return { keys };\n}\n\nfunction resolveAudioFormat(input: unknown): {\n format: string;\n error?: string;\n} {\n if (input === undefined || input === null) return { format: \"wav\" };\n if (typeof input !== \"string\") {\n return { format: \"wav\", error: \"format must be a string\" };\n }\n\n const normalized = input.trim().toLowerCase();\n if (!normalized) return { format: \"wav\" };\n if (!/^[a-z0-9]+$/.test(normalized)) {\n return {\n format: \"wav\",\n error:\n \"format contains unsupported characters; use one of: wav, mp3, ogg, flac, m4a\",\n };\n }\n if (!ALLOWED_AUDIO_FORMATS.has(normalized)) {\n return {\n format: \"wav\",\n error: \"format must be one of: wav, mp3, ogg, flac, m4a\",\n };\n }\n\n return { format: normalized };\n}\n\nfunction runCommand(command: string, args: string[], timeout: number): void {\n execFileSync(command, args, {\n timeout,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n}\n\nfunction captureScreenshot(region?: {\n x: number;\n y: number;\n width: number;\n height: number;\n}): Buffer {\n const os = platform();\n const tmpFile = join(tmpdir(), `sandbox-screenshot-${Date.now()}.png`);\n\n try {\n if (os === \"darwin\") {\n if (region) {\n runCommand(\n \"screencapture\",\n [\n `-R${region.x},${region.y},${region.width},${region.height}`,\n \"-x\",\n tmpFile,\n ],\n 10000,\n );\n } else {\n runCommand(\"screencapture\", [\"-x\", tmpFile], 10000);\n }\n } else if (os === \"linux\") {\n // Try tools in preference order\n if (commandExists(\"import\")) {\n if (region) {\n runCommand(\n \"import\",\n [\n \"-window\",\n \"root\",\n \"-crop\",\n `${region.width}x${region.height}+${region.x}+${region.y}`,\n tmpFile,\n ],\n 10000,\n );\n } else {\n runCommand(\"import\", [\"-window\", \"root\", tmpFile], 10000);\n }\n } else if (commandExists(\"scrot\")) {\n runCommand(\"scrot\", [tmpFile], 10000);\n } else if (commandExists(\"gnome-screenshot\")) {\n runCommand(\"gnome-screenshot\", [\"-f\", tmpFile], 10000);\n } else {\n throw new Error(\n \"No screenshot tool available. Install ImageMagick, scrot, or gnome-screenshot.\",\n );\n }\n } else if (os === \"win32\") {\n // PowerShell screenshot\n const psCmd = [\n `Add-Type -AssemblyName System.Windows.Forms`,\n `$screen = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds`,\n `$bitmap = New-Object System.Drawing.Bitmap($screen.Width, $screen.Height)`,\n `$graphics = [System.Drawing.Graphics]::FromImage($bitmap)`,\n `$graphics.CopyFromScreen($screen.Location, [System.Drawing.Point]::Empty, $screen.Size)`,\n `$bitmap.Save('${tmpFile.replace(/\\//g, \"\\\\\")}')`,\n `$graphics.Dispose()`,\n `$bitmap.Dispose()`,\n ].join(\"; \");\n execSync(`powershell -Command \"${psCmd}\"`, {\n timeout: 15000,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n } else {\n throw new Error(`Screenshot not supported on platform: ${os}`);\n }\n\n const data = readFileSync(tmpFile);\n try {\n unlinkSync(tmpFile);\n } catch {\n /* cleanup best effort */\n }\n return data;\n } catch (err) {\n // Clean up temp file on error\n try {\n unlinkSync(tmpFile);\n } catch {\n /* ignore */\n }\n throw err;\n }\n}\n\nfunction listWindows(): Array<{ id: string; title: string; app: string }> {\n const os = platform();\n\n if (os === \"darwin\") {\n try {\n const script = `\n tell application \"System Events\"\n set windowList to {}\n repeat with proc in (every process whose visible is true)\n try\n repeat with w in (every window of proc)\n set end of windowList to (name of proc) & \"|||\" & (name of w) & \"|||\" & (id of w as text)\n end repeat\n end try\n end repeat\n return windowList as text\n end tell`;\n const output = execSync(`osascript -e '${script}'`, {\n encoding: \"utf-8\",\n timeout: 10000,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n });\n return output\n .split(\", \")\n .filter(Boolean)\n .map((entry) => {\n const parts = entry.split(\"|||\");\n return {\n app: parts[0] ?? \"unknown\",\n title: parts[1] ?? \"unknown\",\n id: parts[2] ?? \"0\",\n };\n });\n } catch {\n return [];\n }\n }\n\n if (os === \"linux\") {\n try {\n const output = execSync(\n 'wmctrl -l 2>/dev/null || xdotool search --name \"\" getwindowname 2>/dev/null',\n {\n encoding: \"utf-8\",\n timeout: 5000,\n },\n );\n return output\n .split(\"\\n\")\n .filter(Boolean)\n .map((line, i) => ({\n id: String(i),\n title: line.trim(),\n app: \"unknown\",\n }));\n } catch {\n return [];\n }\n }\n\n if (os === \"win32\") {\n try {\n const output = execSync(\n `powershell -Command \"Get-Process | Where-Object {$_.MainWindowTitle} | Select-Object Id, MainWindowTitle | ConvertTo-Json\"`,\n { encoding: \"utf-8\", timeout: 10000 },\n );\n const processes = JSON.parse(output);\n const list = Array.isArray(processes) ? processes : [processes];\n return list.map((p: { Id: number; MainWindowTitle: string }) => ({\n id: String(p.Id),\n title: p.MainWindowTitle,\n app: \"unknown\",\n }));\n } catch {\n return [];\n }\n }\n\n return [];\n}\n\nasync function recordAudio(durationMs: number): Promise<Buffer> {\n const os = platform();\n const durationSec = Math.ceil(durationMs / 1000);\n const tmpFile = join(tmpdir(), `sandbox-audio-${Date.now()}.wav`);\n\n if (os === \"darwin\") {\n // Use sox (rec) on macOS\n if (commandExists(\"rec\")) {\n execSync(`rec -q ${tmpFile} trim 0 ${durationSec}`, {\n timeout: durationMs + 5000,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n } else if (commandExists(\"ffmpeg\")) {\n execSync(\n `ffmpeg -f avfoundation -i \":0\" -t ${durationSec} -y ${tmpFile} 2>/dev/null`,\n { timeout: durationMs + 10000, stdio: [\"ignore\", \"pipe\", \"pipe\"] },\n );\n } else {\n throw new Error(\n \"No audio recording tool available. Install sox or ffmpeg.\",\n );\n }\n } else if (os === \"linux\") {\n if (commandExists(\"arecord\")) {\n execSync(`arecord -d ${durationSec} -f cd ${tmpFile}`, {\n timeout: durationMs + 5000,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n } else if (commandExists(\"ffmpeg\")) {\n execSync(\n `ffmpeg -f pulse -i default -t ${durationSec} -y ${tmpFile} 2>/dev/null`,\n { timeout: durationMs + 10000, stdio: [\"ignore\", \"pipe\", \"pipe\"] },\n );\n } else {\n throw new Error(\n \"No audio recording tool available. Install alsa-utils or ffmpeg.\",\n );\n }\n } else if (os === \"win32\") {\n // Use ffmpeg on Windows (most portable)\n if (commandExists(\"ffmpeg\")) {\n execSync(\n `ffmpeg -f dshow -i audio=\"Microphone\" -t ${durationSec} -y \"${tmpFile.replace(/\\//g, \"\\\\\")}\" 2>NUL`,\n { timeout: durationMs + 10000, stdio: [\"ignore\", \"pipe\", \"pipe\"] },\n );\n } else {\n throw new Error(\"No audio recording tool available. Install ffmpeg.\");\n }\n } else {\n throw new Error(`Audio recording not supported on platform: ${os}`);\n }\n\n const data = readFileSync(tmpFile);\n try {\n unlinkSync(tmpFile);\n } catch {\n /* cleanup */\n }\n return data;\n}\n\nasync function playAudio(data: Buffer, format: string): Promise<void> {\n const os = platform();\n const tmpFile = join(tmpdir(), `sandbox-play-${Date.now()}.${format}`);\n writeFileSync(tmpFile, data);\n\n try {\n if (os === \"darwin\") {\n runCommand(\"afplay\", [tmpFile], 60000);\n } else if (os === \"linux\") {\n if (commandExists(\"aplay\")) {\n runCommand(\"aplay\", [tmpFile], 60000);\n } else if (commandExists(\"paplay\")) {\n runCommand(\"paplay\", [tmpFile], 60000);\n } else if (commandExists(\"ffplay\")) {\n runCommand(\"ffplay\", [\"-autoexit\", \"-nodisp\", tmpFile], 60000);\n } else {\n throw new Error(\"No audio playback tool available.\");\n }\n } else if (os === \"win32\") {\n const escapedPath = tmpFile.replace(/\\//g, \"\\\\\").replace(/'/g, \"''\");\n runCommand(\n \"powershell\",\n [\n \"-Command\",\n `(New-Object Media.SoundPlayer '${escapedPath}').PlaySync()`,\n ],\n 60000,\n );\n }\n } finally {\n try {\n unlinkSync(tmpFile);\n } catch {\n /* cleanup */\n }\n }\n}\n\nfunction toAppleScriptStringLiteral(value: string): string {\n return `\"${value.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"')}\"`;\n}\n\nfunction performClick(x: number, y: number, button: \"left\" | \"right\"): void {\n const os = platform();\n\n if (os === \"darwin\") {\n // Use cliclick on macOS (brew install cliclick)\n if (commandExists(\"cliclick\")) {\n const btn = button === \"right\" ? \"rc\" : \"c\";\n runCommand(\"cliclick\", [`${btn}:${x},${y}`], 5000);\n } else {\n // AppleScript fallback\n runCommand(\n \"osascript\",\n [\"-e\", `tell application \"System Events\" to click at {${x}, ${y}}`],\n 5000,\n );\n }\n } else if (os === \"linux\") {\n if (commandExists(\"xdotool\")) {\n const btn = button === \"right\" ? \"3\" : \"1\";\n runCommand(\n \"xdotool\",\n [\"mousemove\", String(x), String(y), \"click\", btn],\n 5000,\n );\n } else {\n throw new Error(\"xdotool required for mouse control on Linux.\");\n }\n } else if (os === \"win32\") {\n // Use Win32 API via PowerShell to perform an actual mouse click\n const psScript = [\n `Add-Type -AssemblyName System.Windows.Forms`,\n `[System.Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point(${x},${y})`,\n `Add-Type -MemberDefinition '[DllImport(\"user32.dll\")] public static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);' -Name Win32Mouse -Namespace Win32`,\n button === \"right\"\n ? `[Win32.Win32Mouse]::mouse_event(0x0008, 0, 0, 0, 0); [Win32.Win32Mouse]::mouse_event(0x0010, 0, 0, 0, 0)` // right down + up\n : `[Win32.Win32Mouse]::mouse_event(0x0002, 0, 0, 0, 0); [Win32.Win32Mouse]::mouse_event(0x0004, 0, 0, 0, 0)`, // left down + up\n ].join(\"; \");\n runCommand(\"powershell\", [\"-Command\", psScript], 5000);\n }\n}\n\nfunction performType(text: string): void {\n const os = platform();\n\n if (os === \"darwin\") {\n if (commandExists(\"cliclick\")) {\n runCommand(\"cliclick\", [`t:${text}`], 10000);\n } else {\n runCommand(\n \"osascript\",\n [\n \"-e\",\n `tell application \"System Events\" to keystroke ${toAppleScriptStringLiteral(text)}`,\n ],\n 10000,\n );\n }\n } else if (os === \"linux\") {\n if (commandExists(\"xdotool\")) {\n runCommand(\"xdotool\", [\"type\", \"--\", text], 10000);\n } else {\n throw new Error(\"xdotool required for keyboard input on Linux.\");\n }\n } else if (os === \"win32\") {\n const escaped = text.replace(/'/g, \"''\");\n runCommand(\n \"powershell\",\n [\n \"-Command\",\n `Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.SendKeys]::SendWait('${escaped}')`,\n ],\n 10000,\n );\n }\n}\n\nfunction performKeypress(keys: string): void {\n const os = platform();\n\n if (os === \"darwin\") {\n if (commandExists(\"cliclick\")) {\n runCommand(\"cliclick\", [`kp:${keys}`], 5000);\n } else {\n const symbolicKeyCodes: Record<string, number> = {\n return: 36,\n enter: 36,\n tab: 48,\n space: 49,\n escape: 53,\n esc: 53,\n left: 123,\n right: 124,\n down: 125,\n up: 126,\n };\n const normalized = keys.trim().toLowerCase();\n const mappedCode = symbolicKeyCodes[normalized];\n const numericCode =\n mappedCode ??\n (Number.isInteger(Number(keys.trim())) ? Number(keys.trim()) : null);\n\n if (numericCode !== null) {\n runCommand(\n \"osascript\",\n [\"-e\", `tell application \"System Events\" to key code ${numericCode}`],\n 5000,\n );\n } else {\n runCommand(\n \"osascript\",\n [\n \"-e\",\n `tell application \"System Events\" to keystroke ${toAppleScriptStringLiteral(keys)}`,\n ],\n 5000,\n );\n }\n }\n } else if (os === \"linux\") {\n if (commandExists(\"xdotool\")) {\n runCommand(\"xdotool\", [\"key\", keys], 5000);\n } else {\n throw new Error(\"xdotool required for key input on Linux.\");\n }\n } else if (os === \"win32\") {\n const escaped = keys.replace(/'/g, \"''\");\n runCommand(\n \"powershell\",\n [\n \"-Command\",\n `Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.SendKeys]::SendWait('${escaped}')`,\n ],\n 5000,\n );\n }\n}\n\nfunction detectCapabilities(): Record<\n string,\n { available: boolean; tool: string }\n> {\n const os = platform();\n const caps: Record<string, { available: boolean; tool: string }> = {};\n\n // Screenshot\n if (os === \"darwin\") {\n caps.screenshot = { available: true, tool: \"screencapture (built-in)\" };\n } else if (os === \"linux\") {\n if (commandExists(\"import\"))\n caps.screenshot = { available: true, tool: \"ImageMagick import\" };\n else if (commandExists(\"scrot\"))\n caps.screenshot = { available: true, tool: \"scrot\" };\n else if (commandExists(\"gnome-screenshot\"))\n caps.screenshot = { available: true, tool: \"gnome-screenshot\" };\n else\n caps.screenshot = {\n available: false,\n tool: \"none (install ImageMagick, scrot, or gnome-screenshot)\",\n };\n } else if (os === \"win32\") {\n caps.screenshot = { available: true, tool: \"PowerShell System.Drawing\" };\n } else {\n caps.screenshot = { available: false, tool: \"unsupported platform\" };\n }\n\n // Audio record\n if (os === \"darwin\") {\n if (commandExists(\"rec\"))\n caps.audioRecord = { available: true, tool: \"sox rec\" };\n else if (commandExists(\"ffmpeg\"))\n caps.audioRecord = { available: true, tool: \"ffmpeg\" };\n else\n caps.audioRecord = {\n available: false,\n tool: \"none (install sox or ffmpeg)\",\n };\n } else if (os === \"linux\") {\n if (commandExists(\"arecord\"))\n caps.audioRecord = { available: true, tool: \"arecord\" };\n else if (commandExists(\"ffmpeg\"))\n caps.audioRecord = { available: true, tool: \"ffmpeg\" };\n else\n caps.audioRecord = {\n available: false,\n tool: \"none (install alsa-utils or ffmpeg)\",\n };\n } else if (os === \"win32\") {\n if (commandExists(\"ffmpeg\"))\n caps.audioRecord = { available: true, tool: \"ffmpeg\" };\n else caps.audioRecord = { available: false, tool: \"none (install ffmpeg)\" };\n } else {\n caps.audioRecord = { available: false, tool: \"unsupported\" };\n }\n\n // Audio play\n if (os === \"darwin\")\n caps.audioPlay = { available: true, tool: \"afplay (built-in)\" };\n else if (os === \"linux\") {\n if (commandExists(\"aplay\"))\n caps.audioPlay = { available: true, tool: \"aplay\" };\n else if (commandExists(\"paplay\"))\n caps.audioPlay = { available: true, tool: \"paplay\" };\n else if (commandExists(\"ffplay\"))\n caps.audioPlay = { available: true, tool: \"ffplay\" };\n else caps.audioPlay = { available: false, tool: \"none\" };\n } else if (os === \"win32\") {\n caps.audioPlay = { available: true, tool: \"PowerShell SoundPlayer\" };\n } else {\n caps.audioPlay = { available: false, tool: \"unsupported\" };\n }\n\n // Mouse/keyboard control\n if (os === \"darwin\") {\n if (commandExists(\"cliclick\"))\n caps.computerUse = { available: true, tool: \"cliclick\" };\n else caps.computerUse = { available: true, tool: \"AppleScript (limited)\" };\n } else if (os === \"linux\") {\n if (commandExists(\"xdotool\"))\n caps.computerUse = { available: true, tool: \"xdotool\" };\n else\n caps.computerUse = { available: false, tool: \"none (install xdotool)\" };\n } else if (os === \"win32\") {\n caps.computerUse = { available: true, tool: \"PowerShell SendKeys\" };\n } else {\n caps.computerUse = { available: false, tool: \"unsupported\" };\n }\n\n // Window listing\n if (os === \"darwin\")\n caps.windowList = { available: true, tool: \"AppleScript\" };\n else if (os === \"linux\") {\n if (commandExists(\"wmctrl\"))\n caps.windowList = { available: true, tool: \"wmctrl\" };\n else if (commandExists(\"xdotool\"))\n caps.windowList = { available: true, tool: \"xdotool\" };\n else\n caps.windowList = {\n available: false,\n tool: \"none (install wmctrl or xdotool)\",\n };\n } else if (os === \"win32\") {\n caps.windowList = { available: true, tool: \"PowerShell Get-Process\" };\n } else {\n caps.windowList = { available: false, tool: \"unsupported\" };\n }\n\n // Browser\n caps.browser = { available: true, tool: \"CDP via sandbox browser container\" };\n\n // Shell\n caps.shell = { available: true, tool: \"docker exec\" };\n\n return caps;\n}\n\nfunction getPlatformInfo(): Record<string, string | boolean> {\n const os = platform();\n let dockerInstalled = false;\n let dockerRunning = false;\n let appleContainerAvailable = false;\n\n // Check if docker binary exists (installed)\n try {\n const which = os === \"win32\" ? \"where\" : \"which\";\n execSync(`${which} docker`, { stdio: \"ignore\", timeout: 3000 });\n dockerInstalled = true;\n } catch {\n /* not installed */\n }\n\n // Check if docker daemon is running (docker info succeeds only when daemon is up)\n if (dockerInstalled) {\n try {\n execSync(\"docker info\", { stdio: \"ignore\", timeout: 5000 });\n dockerRunning = true;\n } catch {\n /* installed but not running */\n }\n }\n\n if (os === \"darwin\") {\n try {\n execSync(\"which container\", { stdio: \"ignore\", timeout: 3000 });\n appleContainerAvailable = true;\n } catch {\n /* */\n }\n }\n\n return {\n platform: os,\n arch: require(\"node:os\").arch(),\n dockerInstalled,\n dockerRunning,\n // Legacy compat: dockerAvailable = running (old clients check this)\n dockerAvailable: dockerRunning,\n appleContainerAvailable,\n wsl2: os === \"win32\" ? isWsl2Available() : false,\n recommended:\n os === \"darwin\" && appleContainerAvailable ? \"apple-container\" : \"docker\",\n };\n}\n\nfunction isWsl2Available(): boolean {\n try {\n execSync(\"wsl --status\", { stdio: \"ignore\", timeout: 5000 });\n return true;\n } catch {\n return false;\n }\n}\n\nfunction attemptDockerStart(): {\n success: boolean;\n message: string;\n waitMs: number;\n} {\n const os = platform();\n\n try {\n if (os === \"darwin\") {\n execSync('open -a \"Docker\"', { timeout: 5000, stdio: \"ignore\" });\n return {\n success: true,\n message: \"Docker Desktop is starting on macOS. Give it a moment~\",\n waitMs: 15000,\n };\n }\n\n if (os === \"win32\") {\n // Try common install locations\n const paths = [\n '\"C:\\\\Program Files\\\\Docker\\\\Docker\\\\Docker Desktop.exe\"',\n '\"C:\\\\Program Files (x86)\\\\Docker\\\\Docker\\\\Docker Desktop.exe\"',\n ];\n let started = false;\n for (const p of paths) {\n try {\n execSync(`start \"\" ${p}`, {\n timeout: 5000,\n stdio: \"ignore\",\n shell: \"cmd.exe\",\n });\n started = true;\n break;\n } catch {\n /* try next path */\n }\n }\n if (!started) {\n // Try via start menu\n execSync('start \"\" \"Docker Desktop\"', {\n timeout: 5000,\n stdio: \"ignore\",\n shell: \"cmd.exe\",\n });\n }\n return {\n success: true,\n message:\n \"Docker Desktop is starting on Windows. This may take 30 seconds~\",\n waitMs: 30000,\n };\n }\n\n if (os === \"linux\") {\n // Try systemctl first (most common)\n try {\n execSync(\"sudo systemctl start docker\", {\n timeout: 10000,\n stdio: \"ignore\",\n });\n return {\n success: true,\n message: \"Docker daemon started via systemctl\",\n waitMs: 5000,\n };\n } catch {\n /* systemctl may not be available */\n }\n\n // Try service command\n try {\n execSync(\"sudo service docker start\", {\n timeout: 10000,\n stdio: \"ignore\",\n });\n return {\n success: true,\n message: \"Docker daemon started via service\",\n waitMs: 5000,\n };\n } catch {\n /* */\n }\n\n return {\n success: false,\n message:\n \"Could not auto-start Docker on Linux. Run: sudo systemctl start docker\",\n waitMs: 0,\n };\n }\n\n return {\n success: false,\n message: `Auto-start not supported on ${os}`,\n waitMs: 0,\n };\n } catch (err) {\n return {\n success: false,\n message: `Failed: ${String(err)}`,\n waitMs: 0,\n };\n }\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction commandExists(cmd: string): boolean {\n try {\n const which = platform() === \"win32\" ? \"where\" : \"which\";\n execSync(`${which} ${cmd}`, { stdio: \"ignore\", timeout: 3000 });\n return true;\n } catch {\n return false;\n }\n}\n\nfunction sendJson(res: ServerResponse, status: number, data: unknown): void {\n sendJsonResponse(res, data, status);\n}\n\nfunction readBody(req: IncomingMessage): Promise<string | null> {\n return readRequestBody(req, {\n maxBytes: 10 * 1024 * 1024,\n returnNullOnTooLarge: true,\n returnNullOnError: true,\n destroyOnTooLarge: true,\n });\n}\n\nfunction readJsonBody<T = unknown>(\n req: IncomingMessage,\n res: ServerResponse,\n): Promise<T | null> {\n return parseJsonBody(req, res, {\n maxBytes: 10 * 1024 * 1024,\n requireObject: false,\n readErrorStatus: 400,\n parseErrorStatus: 400,\n readErrorMessage: \"Missing request body\",\n parseErrorMessage: \"Invalid JSON in request body\",\n });\n}\n",
|
|
63
|
+
"import { execFileSync } from \"node:child_process\";\nimport { readFileSync, unlinkSync } from \"node:fs\";\nimport { platform, tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\n\nexport type DesktopInputButton = \"left\" | \"right\";\n\nexport interface DesktopScreenshotRegion {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport interface DesktopWindowInfo {\n id: string;\n title: string;\n app: string;\n}\n\nexport interface DesktopControlCapability {\n available: boolean;\n tool: string;\n}\n\nexport interface DesktopControlCapabilities {\n screenshot: DesktopControlCapability;\n computerUse: DesktopControlCapability;\n windowList: DesktopControlCapability;\n headfulGui: DesktopControlCapability;\n}\n\nexport function isHeadfulGuiAvailable(): boolean {\n const os = platform();\n if (os === \"darwin\" || os === \"win32\") {\n return true;\n }\n if (os === \"linux\") {\n return Boolean(\n process.env.DISPLAY?.trim() ||\n process.env.WAYLAND_DISPLAY?.trim() ||\n process.env.MIR_SOCKET?.trim(),\n );\n }\n return false;\n}\n\nexport function commandExists(command: string): boolean {\n try {\n const which = platform() === \"win32\" ? \"where\" : \"which\";\n execFileSync(which, [command], {\n stdio: \"ignore\",\n timeout: 3000,\n });\n return true;\n } catch {\n return false;\n }\n}\n\nexport function captureDesktopScreenshot(\n region?: DesktopScreenshotRegion,\n): Buffer {\n const os = platform();\n const tmpFile = join(tmpdir(), `desktop-screenshot-${Date.now()}.png`);\n\n try {\n if (os === \"darwin\") {\n if (region) {\n runMacScreenshotCommand([\n `-R${region.x},${region.y},${region.width},${region.height}`,\n \"-x\",\n tmpFile,\n ]);\n } else {\n runMacScreenshotCommand([\"-x\", tmpFile]);\n }\n } else if (os === \"linux\") {\n if (!isHeadfulGuiAvailable()) {\n throw new Error(\"No Linux GUI display is available.\");\n }\n if (commandExists(\"import\")) {\n if (region) {\n runCommand(\n \"import\",\n [\n \"-window\",\n \"root\",\n \"-crop\",\n `${region.width}x${region.height}+${region.x}+${region.y}`,\n tmpFile,\n ],\n 10000,\n );\n } else {\n runCommand(\"import\", [\"-window\", \"root\", tmpFile], 10000);\n }\n } else if (commandExists(\"scrot\")) {\n runCommand(\"scrot\", [tmpFile], 10000);\n } else if (commandExists(\"gnome-screenshot\")) {\n runCommand(\"gnome-screenshot\", [\"-f\", tmpFile], 10000);\n } else {\n throw new Error(\n \"No screenshot tool available. Install ImageMagick, scrot, or gnome-screenshot.\",\n );\n }\n } else if (os === \"win32\") {\n const windowsPath = tmpFile.replace(/\\//g, \"\\\\\").replace(/'/g, \"''\");\n const psCommand = [\n \"Add-Type -AssemblyName System.Windows.Forms\",\n \"$screen = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds\",\n \"$bitmap = New-Object System.Drawing.Bitmap($screen.Width, $screen.Height)\",\n \"$graphics = [System.Drawing.Graphics]::FromImage($bitmap)\",\n \"$graphics.CopyFromScreen($screen.Location, [System.Drawing.Point]::Empty, $screen.Size)\",\n `$bitmap.Save('${windowsPath}')`,\n \"$graphics.Dispose()\",\n \"$bitmap.Dispose()\",\n ].join(\"; \");\n execFileSync(\"powershell\", [\"-Command\", psCommand], {\n timeout: 15000,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n } else {\n throw new Error(`Screenshot not supported on platform: ${os}`);\n }\n\n const data = readFileSync(tmpFile);\n removeTempFile(tmpFile);\n return data;\n } catch (error) {\n removeTempFile(tmpFile);\n throw error;\n }\n}\n\nexport function listDesktopWindows(): DesktopWindowInfo[] {\n const os = platform();\n\n if (os === \"darwin\") {\n const script = `\n tell application \"System Events\"\n set previousDelimiters to AppleScript's text item delimiters\n set AppleScript's text item delimiters to linefeed\n set windowList to {}\n repeat with proc in (every process whose visible is true)\n try\n repeat with w in (every window of proc)\n set end of windowList to (name of proc) & \"|||\" & (name of w) & \"|||\" & (id of w as text)\n end repeat\n end try\n end repeat\n set serializedWindowList to windowList as text\n set AppleScript's text item delimiters to previousDelimiters\n return serializedWindowList\n end tell`;\n let output: string;\n try {\n output = execFileSync(\"osascript\", [\"-e\", script], {\n encoding: \"utf-8\",\n timeout: 5000,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n });\n } catch {\n throw new Error(\n \"Window listing failed. Grant Accessibility permission to this app or terminal and try again.\",\n );\n }\n return output\n .split(\"\\n\")\n .filter(Boolean)\n .map((entry) => {\n const parts = entry.split(\"|||\");\n return {\n app: parts[0] ?? \"unknown\",\n title: parts[1] ?? \"unknown\",\n id: parts[2] ?? \"0\",\n };\n });\n }\n\n if (os === \"linux\") {\n if (commandExists(\"wmctrl\")) {\n const output = execFileSync(\"wmctrl\", [\"-l\"], {\n encoding: \"utf-8\",\n timeout: 5000,\n });\n return output\n .split(\"\\n\")\n .filter(Boolean)\n .map((line) => {\n const match = line.match(/^(\\S+)\\s+\\S+\\s+\\S+\\s*(.*)$/);\n return {\n id: match?.[1] ?? \"0\",\n title: match?.[2]?.trim() || line.trim(),\n app: \"unknown\",\n };\n });\n }\n if (commandExists(\"xdotool\")) {\n const output = execFileSync(\n \"sh\",\n [\"-c\", 'xdotool search --name \"\" getwindowname 2>/dev/null'],\n {\n encoding: \"utf-8\",\n timeout: 5000,\n },\n );\n return output\n .split(\"\\n\")\n .filter(Boolean)\n .map((title, index) => ({\n id: String(index),\n title: title.trim(),\n app: \"unknown\",\n }));\n }\n }\n\n if (os === \"win32\") {\n const output = execFileSync(\n \"powershell\",\n [\n \"-Command\",\n \"Get-Process | Where-Object {$_.MainWindowTitle} | Select-Object Id, MainWindowTitle | ConvertTo-Json\",\n ],\n { encoding: \"utf-8\", timeout: 10000 },\n );\n if (!output.trim()) {\n return [];\n }\n const parsed = JSON.parse(output) as\n | { Id: number; MainWindowTitle: string }\n | Array<{ Id: number; MainWindowTitle: string }>;\n const processes = Array.isArray(parsed) ? parsed : [parsed];\n return processes.map((process) => ({\n id: String(process.Id),\n title: process.MainWindowTitle,\n app: \"unknown\",\n }));\n }\n\n return [];\n}\n\nexport function performDesktopClick(\n x: number,\n y: number,\n button: DesktopInputButton = \"left\",\n): void {\n const os = platform();\n\n if (os === \"darwin\") {\n if (commandExists(\"cliclick\")) {\n const clickCommand = button === \"right\" ? \"rc\" : \"c\";\n runCommand(\"cliclick\", [`${clickCommand}:${x},${y}`], 5000);\n return;\n }\n runCommand(\n \"osascript\",\n [\"-e\", `tell application \"System Events\" to click at {${x}, ${y}}`],\n 5000,\n );\n return;\n }\n\n if (os === \"linux\") {\n if (!commandExists(\"xdotool\")) {\n throw new Error(\"xdotool required for mouse control on Linux.\");\n }\n const clickButton = button === \"right\" ? \"3\" : \"1\";\n runCommand(\n \"xdotool\",\n [\"mousemove\", String(x), String(y), \"click\", clickButton],\n 5000,\n );\n return;\n }\n\n if (os === \"win32\") {\n runPowerShellMouseScript(x, y, button === \"right\" ? \"right\" : \"left\", 1);\n return;\n }\n\n throw new Error(`Mouse control not supported on platform: ${os}`);\n}\n\nexport function performDesktopDoubleClick(\n x: number,\n y: number,\n button: DesktopInputButton = \"left\",\n): void {\n const os = platform();\n\n if (os === \"darwin\" && commandExists(\"cliclick\") && button === \"left\") {\n runCommand(\"cliclick\", [`dc:${x},${y}`], 5000);\n return;\n }\n\n if (os === \"linux\") {\n if (!commandExists(\"xdotool\")) {\n throw new Error(\"xdotool required for mouse control on Linux.\");\n }\n const clickButton = button === \"right\" ? \"3\" : \"1\";\n runCommand(\n \"xdotool\",\n [\n \"mousemove\",\n String(x),\n String(y),\n \"click\",\n \"--repeat\",\n \"2\",\n clickButton,\n ],\n 5000,\n );\n return;\n }\n\n if (os === \"win32\") {\n runPowerShellMouseScript(x, y, button === \"right\" ? \"right\" : \"left\", 2);\n return;\n }\n\n performDesktopClick(x, y, button);\n performDesktopClick(x, y, button);\n}\n\nexport function performDesktopMouseMove(x: number, y: number): void {\n const os = platform();\n\n if (os === \"darwin\") {\n if (!commandExists(\"cliclick\")) {\n throw new Error(\"cliclick required for mouse move on macOS.\");\n }\n runCommand(\"cliclick\", [`m:${x},${y}`], 5000);\n return;\n }\n\n if (os === \"linux\") {\n if (!commandExists(\"xdotool\")) {\n throw new Error(\"xdotool required for mouse move on Linux.\");\n }\n runCommand(\"xdotool\", [\"mousemove\", String(x), String(y)], 5000);\n return;\n }\n\n if (os === \"win32\") {\n const psScript = [\n \"Add-Type -AssemblyName System.Windows.Forms\",\n `[System.Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point(${x},${y})`,\n ].join(\"; \");\n runCommand(\"powershell\", [\"-Command\", psScript], 5000);\n return;\n }\n\n throw new Error(`Mouse move not supported on platform: ${os}`);\n}\n\nexport function performDesktopScroll(deltaX: number, deltaY: number): void {\n const os = platform();\n const normalizedX = clampScrollDelta(deltaX);\n const normalizedY = clampScrollDelta(deltaY);\n\n if (normalizedX === 0 && normalizedY === 0) {\n return;\n }\n\n if (os === \"darwin\") {\n const psScript = [\n 'ObjC.import(\"ApplicationServices\")',\n `const event = $.CGEventCreateScrollWheelEvent(null, 1, 2, ${-normalizedY}, ${-normalizedX})`,\n \"$.CGEventPost(0, event)\",\n \"$.CFRelease(event)\",\n ].join(\"; \");\n runCommand(\"osascript\", [\"-l\", \"JavaScript\", \"-e\", psScript], 5000);\n return;\n }\n\n if (os === \"linux\") {\n if (!commandExists(\"xdotool\")) {\n throw new Error(\"xdotool required for scroll on Linux.\");\n }\n clickMouseWheel(normalizedY < 0 ? \"4\" : \"5\", Math.abs(normalizedY));\n clickMouseWheel(normalizedX < 0 ? \"6\" : \"7\", Math.abs(normalizedX));\n return;\n }\n\n if (os === \"win32\") {\n const psScript = [\n `Add-Type -MemberDefinition '[DllImport(\"user32.dll\")] public static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);' -Name Win32Mouse -Namespace Win32`,\n `[Win32.Win32Mouse]::mouse_event(0x0800, 0, 0, ${normalizedY * -120}, 0)`,\n ].join(\"; \");\n runCommand(\"powershell\", [\"-Command\", psScript], 5000);\n return;\n }\n\n throw new Error(`Scroll not supported on platform: ${os}`);\n}\n\nexport function performDesktopTextInput(text: string): void {\n const os = platform();\n\n if (os === \"darwin\") {\n if (commandExists(\"cliclick\")) {\n runCommand(\"cliclick\", [`t:${text}`], 10000);\n return;\n }\n runCommand(\n \"osascript\",\n [\n \"-e\",\n `tell application \"System Events\" to keystroke ${toAppleScriptStringLiteral(text)}`,\n ],\n 10000,\n );\n return;\n }\n\n if (os === \"linux\") {\n if (!commandExists(\"xdotool\")) {\n throw new Error(\"xdotool required for keyboard input on Linux.\");\n }\n runCommand(\"xdotool\", [\"type\", \"--\", text], 10000);\n return;\n }\n\n if (os === \"win32\") {\n const escaped = text.replace(/'/g, \"''\");\n runCommand(\n \"powershell\",\n [\n \"-Command\",\n `Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.SendKeys]::SendWait('${escaped}')`,\n ],\n 10000,\n );\n return;\n }\n\n throw new Error(`Text input not supported on platform: ${os}`);\n}\n\nexport function performDesktopKeypress(keys: string): void {\n const os = platform();\n\n if (os === \"darwin\") {\n if (commandExists(\"cliclick\")) {\n const cliclickKey = toCliclickKey(keys);\n if (cliclickKey) {\n runCommand(\"cliclick\", [`kp:${cliclickKey}`], 5000);\n } else {\n runCommand(\"cliclick\", [`t:${keys}`], 5000);\n }\n return;\n }\n\n const keyCode = macKeyCode(keys);\n if (keyCode !== null) {\n runCommand(\n \"osascript\",\n [\"-e\", `tell application \"System Events\" to key code ${keyCode}`],\n 5000,\n );\n return;\n }\n\n runCommand(\n \"osascript\",\n [\n \"-e\",\n `tell application \"System Events\" to keystroke ${toAppleScriptStringLiteral(keys)}`,\n ],\n 5000,\n );\n return;\n }\n\n if (os === \"linux\") {\n if (!commandExists(\"xdotool\")) {\n throw new Error(\"xdotool required for key input on Linux.\");\n }\n runCommand(\"xdotool\", [\"key\", toXdotoolKey(keys)], 5000);\n return;\n }\n\n if (os === \"win32\") {\n const escaped = toWindowsSendKey(keys).replace(/'/g, \"''\");\n runCommand(\n \"powershell\",\n [\n \"-Command\",\n `Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.SendKeys]::SendWait('${escaped}')`,\n ],\n 5000,\n );\n return;\n }\n\n throw new Error(`Key input not supported on platform: ${os}`);\n}\n\nfunction toCliclickKey(keys: string): string | null {\n const keyMap: Record<string, string> = {\n backspace: \"delete\",\n down: \"arrow-down\",\n enter: \"enter\",\n escape: \"esc\",\n esc: \"esc\",\n left: \"arrow-left\",\n right: \"arrow-right\",\n return: \"return\",\n space: \"space\",\n tab: \"tab\",\n up: \"arrow-up\",\n };\n return keyMap[keys.trim().toLowerCase()] ?? null;\n}\n\nfunction toXdotoolKey(keys: string): string {\n const keyMap: Record<string, string> = {\n backspace: \"BackSpace\",\n down: \"Down\",\n enter: \"Return\",\n escape: \"Escape\",\n esc: \"Escape\",\n left: \"Left\",\n right: \"Right\",\n return: \"Return\",\n space: \"space\",\n tab: \"Tab\",\n up: \"Up\",\n };\n const normalized = keys.trim().toLowerCase();\n return keyMap[normalized] ?? keys.trim();\n}\n\nfunction toWindowsSendKey(keys: string): string {\n const keyMap: Record<string, string> = {\n backspace: \"{BACKSPACE}\",\n down: \"{DOWN}\",\n enter: \"{ENTER}\",\n escape: \"{ESC}\",\n esc: \"{ESC}\",\n left: \"{LEFT}\",\n right: \"{RIGHT}\",\n return: \"{ENTER}\",\n space: \" \",\n tab: \"{TAB}\",\n up: \"{UP}\",\n };\n const normalized = keys.trim().toLowerCase();\n return keyMap[normalized] ?? keys;\n}\n\nexport function detectDesktopControlCapabilities(): DesktopControlCapabilities {\n const os = platform();\n const headfulGui = isHeadfulGuiAvailable();\n\n return {\n headfulGui: {\n available: headfulGui,\n tool: headfulGui ? \"desktop session\" : \"no GUI display detected\",\n },\n screenshot: detectScreenshotCapability(os),\n computerUse: detectComputerUseCapability(os),\n windowList: detectWindowListCapability(os),\n };\n}\n\nfunction detectScreenshotCapability(\n os: NodeJS.Platform,\n): DesktopControlCapability {\n if (os === \"darwin\") {\n return canCaptureMacScreen()\n ? { available: true, tool: \"screencapture (built-in)\" }\n : {\n available: false,\n tool: \"screencapture blocked (grant Screen Recording permission)\",\n };\n }\n if (os === \"linux\") {\n if (!isHeadfulGuiAvailable()) {\n return { available: false, tool: \"no GUI display detected\" };\n }\n if (commandExists(\"import\")) {\n return { available: true, tool: \"ImageMagick import\" };\n }\n if (commandExists(\"scrot\")) {\n return { available: true, tool: \"scrot\" };\n }\n if (commandExists(\"gnome-screenshot\")) {\n return { available: true, tool: \"gnome-screenshot\" };\n }\n return {\n available: false,\n tool: \"none (install ImageMagick, scrot, or gnome-screenshot)\",\n };\n }\n if (os === \"win32\") {\n return { available: true, tool: \"PowerShell System.Drawing\" };\n }\n return { available: false, tool: \"unsupported platform\" };\n}\n\nfunction detectComputerUseCapability(\n os: NodeJS.Platform,\n): DesktopControlCapability {\n if (os === \"darwin\") {\n if (commandExists(\"cliclick\")) {\n return { available: true, tool: \"cliclick\" };\n }\n return { available: true, tool: \"AppleScript (limited)\" };\n }\n if (os === \"linux\") {\n if (!isHeadfulGuiAvailable()) {\n return { available: false, tool: \"no GUI display detected\" };\n }\n if (commandExists(\"xdotool\")) {\n return { available: true, tool: \"xdotool\" };\n }\n return { available: false, tool: \"none (install xdotool)\" };\n }\n if (os === \"win32\") {\n return { available: true, tool: \"PowerShell SendKeys\" };\n }\n return { available: false, tool: \"unsupported platform\" };\n}\n\nfunction detectWindowListCapability(\n os: NodeJS.Platform,\n): DesktopControlCapability {\n if (os === \"darwin\") {\n return canUseMacSystemEvents()\n ? { available: true, tool: \"AppleScript\" }\n : {\n available: false,\n tool: \"AppleScript blocked (grant Accessibility permission)\",\n };\n }\n if (os === \"linux\") {\n if (commandExists(\"wmctrl\")) {\n return { available: true, tool: \"wmctrl\" };\n }\n if (commandExists(\"xdotool\")) {\n return { available: true, tool: \"xdotool\" };\n }\n return {\n available: false,\n tool: \"none (install wmctrl or xdotool)\",\n };\n }\n if (os === \"win32\") {\n return { available: true, tool: \"PowerShell Get-Process\" };\n }\n return { available: false, tool: \"unsupported platform\" };\n}\n\nfunction runCommand(command: string, args: string[], timeout: number): void {\n execFileSync(command, args, {\n timeout,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n}\n\nfunction runMacScreenshotCommand(args: string[]): void {\n try {\n runCommand(\"screencapture\", args, 10000);\n } catch {\n throw new Error(\n \"Screen capture failed. Grant Screen Recording permission to this app or terminal and try again.\",\n );\n }\n}\n\nfunction canCaptureMacScreen(): boolean {\n const tmpFile = join(tmpdir(), `desktop-screenshot-probe-${Date.now()}.png`);\n try {\n runCommand(\"screencapture\", [\"-x\", \"-R0,0,1,1\", tmpFile], 5000);\n return true;\n } catch {\n return false;\n } finally {\n removeTempFile(tmpFile);\n }\n}\n\nfunction canUseMacSystemEvents(): boolean {\n try {\n execFileSync(\n \"osascript\",\n [\"-e\", 'tell application \"System Events\" to count of processes'],\n {\n encoding: \"utf-8\",\n timeout: 3000,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n },\n );\n return true;\n } catch {\n return false;\n }\n}\n\nfunction removeTempFile(filePath: string): void {\n try {\n unlinkSync(filePath);\n } catch {\n // Temp cleanup is best effort.\n }\n}\n\nfunction toAppleScriptStringLiteral(value: string): string {\n return `\"${value.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"')}\"`;\n}\n\nfunction macKeyCode(keys: string): number | null {\n const symbolicKeyCodes: Record<string, number> = {\n return: 36,\n enter: 36,\n tab: 48,\n space: 49,\n escape: 53,\n esc: 53,\n left: 123,\n right: 124,\n down: 125,\n up: 126,\n };\n const normalized = keys.trim().toLowerCase();\n const mappedCode = symbolicKeyCodes[normalized];\n if (mappedCode !== undefined) {\n return mappedCode;\n }\n const numericCode = Number(keys.trim());\n return Number.isInteger(numericCode) ? numericCode : null;\n}\n\nfunction runPowerShellMouseScript(\n x: number,\n y: number,\n button: DesktopInputButton,\n repeat: number,\n): void {\n const downFlag = button === \"right\" ? \"0x0008\" : \"0x0002\";\n const upFlag = button === \"right\" ? \"0x0010\" : \"0x0004\";\n const clicks = Array.from(\n { length: Math.max(1, Math.min(2, repeat)) },\n () =>\n `[Win32.Win32Mouse]::mouse_event(${downFlag}, 0, 0, 0, 0); [Win32.Win32Mouse]::mouse_event(${upFlag}, 0, 0, 0, 0)`,\n ).join(\"; \");\n const psScript = [\n \"Add-Type -AssemblyName System.Windows.Forms\",\n `[System.Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point(${x},${y})`,\n `Add-Type -MemberDefinition '[DllImport(\"user32.dll\")] public static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);' -Name Win32Mouse -Namespace Win32`,\n clicks,\n ].join(\"; \");\n runCommand(\"powershell\", [\"-Command\", psScript], 5000);\n}\n\nfunction clampScrollDelta(value: number): number {\n if (!Number.isFinite(value)) {\n return 0;\n }\n return Math.trunc(Math.max(-20, Math.min(20, value)));\n}\n\nfunction clickMouseWheel(button: string, count: number): void {\n for (let index = 0; index < count; index += 1) {\n runCommand(\"xdotool\", [\"click\", button], 5000);\n }\n}\n\nexport function getDesktopPlatformName(): NodeJS.Platform {\n return platform();\n}\n"
|
|
64
|
+
],
|
|
65
|
+
"mappings": "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",
|
|
66
|
+
"debugId": "4873D054D66B6A1D64756E2164756E21",
|
|
67
|
+
"names": []
|
|
68
|
+
}
|