feat: robust controlBrowser — real xdotool input, tabs/back/forward/popups

- Install xdotool + wmctrl (late Docker layer, preserves the melo cache) so
  the on-screen Chrome gets real X input (visible cursor, char-by-char typing)
  instead of synthetic events; falls back to the Playwright API if absent.
- Fix active-tab detection (probe document.visibilityState instead of assuming
  tab 0) so sequential ops target the right tab.
- Add back / forward / refresh; new/switch/close tabs via real keyboard
  (Ctrl+T / Ctrl+<n> / Ctrl+W) when xdotool is present.
- Auto-dismiss native JS dialogs; closePopups clears blank/popup tabs.
- Report broadcast (Go-Live) state in status from the turn context.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
javis-bot
2026-06-14 02:33:59 +09:00
parent b18217fcdd
commit 109dbc7e16
3 changed files with 140 additions and 94 deletions

View File

@@ -57,9 +57,10 @@ class ControlBrowserTool(Tool):
"action": {
"type": "string",
"enum": [
"status", "listTabs", "navigate", "newTab", "closeTab",
"activateTab", "closePopups", "click", "type", "scroll",
"pressKey", "screenshot",
"status", "listTabs", "navigate", "back", "forward",
"refresh", "newTab", "closeTab", "activateTab",
"closePopups", "click", "type", "scroll", "pressKey",
"screenshot",
],
"description": "What to do in the browser.",
},
@@ -116,6 +117,12 @@ class ControlBrowserTool(Tool):
# Return a factual summary of what ACTUALLY happened so the reply engine
# describes the real outcome and doesn't confabulate.
summary = self._summarise(action, args, data)
if action == "status":
# The broadcast (Go-Live) state lives in the bot runtime, surfaced
# to the tool via the turn context — report it alongside the tabs.
bc = getattr(context, "broadcasting", None)
state = "켜짐" if bc else ("꺼짐" if bc is not None else "알 수 없음")
summary = f"📡 방송: {state}\n{summary}"
return ToolExecutionResult(success=True, reply_text=summary)
@staticmethod