项目文件夹

文件
Magnus Müller 23ce2ec464 Fix daemon attaching to invisible omnibox popup (#60)
* fix daemon attaching to invisible omnibox popup on fresh Chrome

When Chrome opens fresh, the only page targets are chrome://
internal pages and the omnibox popup (1px invisible viewport).
The daemon's attach_first_page() fell back to the popup, making
all subsequent work invisible to the user.

Fix: when no real pages exist, create an about:blank tab via
Target.createTarget instead of attaching to the omnibox popup.

Tested configurations:
- Fresh start with no real tabs → creates about:blank (1112x817)
- Navigate without AppleScript → works, tab visible
- Recovery from stale socket → auto-reconnects
- Chrome restart from scratch → creates about:blank

Also adds interaction-skills/connection.md documenting the
omnibox popup problem and startup sequence.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* add connection skill reference to main SKILL.md

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-18 11:07:43 -07:00

48 行
1.6 KiB
Markdown

# Connection & Tab Visibility
## The omnibox popup problem
When Chrome opens fresh, the only CDP `type: "page"` targets are `chrome://inspect` and `chrome://omnibox-popup.top-chrome/` (a 1px invisible viewport). If the daemon attaches to the omnibox popup, all subsequent work — including `new_tab()` and `goto()` — happens on tabs that exist in CDP but may not be visible in the Chrome UI.
The daemon's `attach_first_page()` handles this by creating an `about:blank` tab when no real pages exist. If you still end up on an invisible tab, use `switch_tab()` which calls `Target.activateTarget` to bring the tab to front.
## Startup sequence
1. Check if a daemon is already running with `daemon_alive()`
2. If stale sockets exist but daemon is dead, clean them up
3. List open tabs with `list_tabs()` to see what's available
4. `ensure_real_tab()` attaches to a real page
5. `switch_tab(target_id)` both attaches AND activates (brings to front)
```python
if not daemon_alive():
import os
for f in ["/tmp/bu-default.sock", "/tmp/bu-default.pid"]:
if os.path.exists(f): os.unlink(f)
ensure_daemon()
tabs = list_tabs()
for t in tabs:
print(t["url"][:60])
tab = ensure_real_tab()
```
## Bringing Chrome to front
If Chrome is behind other windows or on another desktop:
```python
import subprocess
subprocess.run(["osascript", "-e", 'tell application "Google Chrome" to activate'])
```
## Navigating
Prefer navigating an existing tab over `new_tab()`. Tabs created via CDP's `Target.createTarget` are visible but may open behind the active tab.
```python
tab = ensure_real_tab()
goto("https://example.com")
```