Commit Graph

20 Commits

Author SHA1 Message Date
Junliang Feng e992b91ba3 feat: use CDP Accessibility tree for extension mode snapshot (#203)
* [packages/actionbook-rs]feat: use CDP Accessibility.getFullAXTree for extension mode snapshot

Extension mode previously used a primitive JS DOM walker (snapshot_js_fallback)
that couldn't compute accessible names, resulting in empty names for links,
headings, and other elements. Now extension mode uses CDP Accessibility.getFullAXTree
through the extension bridge, same as isolated mode.

Changes:
- Add DOM.enable, Accessibility.enable, Accessibility.getFullAXTree to CDP
  allowlist in both Rust bridge and Chrome extension
- Remove snapshot_js_fallback; extension mode now shares the CDP code path
- Skip noise roles: StaticText, LineBreak, ListMarker, strong, emphasis etc.
- Remove empty leaf structural nodes (empty <div>/<span> wrappers)
- Rewrite compact_tree_nodes (-c) to match agent-browser: keep only ref'd/valued
  nodes and their ancestors

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* [packages/actionbook-rs]refactor: remove level attribute from snapshot output

Level info (e.g. level=1 on listitem/heading) adds noise without
actionable value for agents. Remove it from format_compact output.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* [packages/actionbook-rs]feat: add /url: metadata to snapshot output for links and images

Extract URL property from CDP AX tree nodes and output as indented
`- /url: <href>` metadata line under link/image elements, matching
agent-browser's snapshot format.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* [packages/actionbook-rs]fix: address code review issues from Codex and self-review

- Fix scope filter pruning entire subtrees: traverse children even when
  ancestor is outside scope (Codex P1)
- Fix --interactive filter including non-interactive content roles like
  heading/navigation; now filters by interactive roles only (Codex P2)
- Fix compact_tree_nodes ancestor marking: only mark true ancestor chain
  (depth-1 walk) instead of all preceding lower-depth nodes (Codex P2)
- Fix cursor ref ID collision: use cache.next_ref from parse_ax_tree
  instead of nodes.len() which diverges after filtering
- Remove dead code: "Skip empty StaticText" guard unreachable since
  StaticText is already in SKIP_ROLES
- Fix format_compact doc comment: remove level=1 from format example
  since level is intentionally not emitted
- Fix estimate_tokens_compact test to use realistic format_compact output

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 00:23:52 +08:00
SenKe0x 9895c25b8b [packages/actionbook-rs]fix: stop extension bridge connect/disconnect loop
When two Chrome extension instances (CWS + dev) are both installed,
they compete for the single extension_tx slot on the bridge server,
causing an infinite connect/replace/disconnect cycle.

Fix: reject any new extension WebSocket connection before hello_ack
when an active connection already exists (first-wins strategy).
Same-extension SW restart is handled naturally — old WebSocket closes,
handler cleans up extension_tx = None, next retry succeeds.

Key insight: Chrome MV3 Service Worker WebSocket connections do NOT
send the Origin header, making origin-based differentiation impossible.
The fix uses a simple tx.is_closed() liveness check instead.
2026-03-09 12:34:12 +08:00
SenKe0x 52edfc69ca feat(setup): prefer Chrome Web Store extension flow with local fallback 2026-03-03 16:59:00 +08:00
sen c53ec19eea [packages/actionbook-extension]chore: bump version to 0.2.2 (#151)
Bump extension version for Chrome Web Store resubmission after
removing unused scripting permission in #150.
2026-02-23 11:48:41 +08:00
sen 7302e2e3f3 [packages/actionbook-extension]fix: remove unused scripting permission (#150)
Chrome Web Store rejected the extension (violation: Purple Potassium)
for requesting the `scripting` permission without using it. The
extension uses chrome.debugger for CDP commands and never calls
chrome.scripting APIs.

- Remove `scripting` from manifest.json permissions
- Remove corresponding entry from PRIVACY.md permissions table
2026-02-23 11:43:01 +08:00
sen c70683da86 [docs]docs: simplify browser workflow and make setup-first quickstart (#147) 2026-02-19 00:50:14 +08:00
sen 51e2af6798 chore(extension): bump to v0.2.1 and align release docs (#132) 2026-02-13 15:51:56 +08:00
SenKe0x 5407dbccb7 fix(extension): connect via fixed localhost bridge and remove native host dependency 2026-02-13 15:32:05 +08:00
SenKe0x 0cb25185bd [packages/actionbook-extension]chore: bump version to 0.2.0 2026-02-13 14:29:30 +08:00
sen f68a85686b Refactor browser extension architecture with backend trait and auto-lifecycle (#122)
* [packages/actionbook-rs]refactor: add BrowserMode::Isolated/Extension and ExtensionConfig (Phase 1)

- Replace BrowserMode::Builtin/System with Isolated/Extension in cli.rs
- Add serde derives + new --browser-mode flag, hide deprecated --extension
- Add ExtensionConfig (port, auto_install) and mode field to BrowserConfig
- Redesign setup wizard: mode selection → mode-specific config flow
- Default display mode to Visible (matching Playwright/Puppeteer convention)
- No behavior changes; mode stored in config but not acted on yet

* [packages/actionbook-rs]refactor: add BrowserBackend trait with Isolated and Extension implementations (Phase 2)

- Define BrowserBackend async trait with ~25 methods covering lifecycle,
  navigation, interaction, content extraction, and cookies
- Implement IsolatedBackend wrapping SessionManager for CDP-controlled browsers
- Implement ExtensionBackend with bridge communication and inline JS helpers
- Add async-trait dependency for object-safe dynamic dispatch

* [packages/actionbook-rs]fix: address dual review findings for Phase 1+2

- Wire --browser-mode flag and config.browser.mode to runtime via
  is_extension_mode() helper, replacing all 28 cli.extension checks
- Add serde aliases (builtin→isolated, system→extension) for backward
  compatible config parsing
- Implement snapshot() in both backends via shared SNAPSHOT_JS constant
- Fix IsolatedBackend::switch() to return Ok (matching current behavior)
- Harden escape_js_string with .expect() instead of unsafe fallback
- Add viewport bounds checking, clear_cookies domain warning log
- Fix immutability violations in screenshot/set_cookie params
- Use serde_json::to_value for browser_mode JSON serialization
- Add 8 unit tests for escape_js_string and js_resolve_selector

* [packages/actionbook-rs]refactor: replace all if/else branching with BrowserBackend dispatch (Phase 3)

Replace ~30 is_extension_mode() branch sites in browser.rs with single
backend.method() calls via the BrowserBackend trait, reducing the file
from ~3400 to ~1750 lines.

- Add resolve_mode() + create_backend() factory for backend instantiation
- Refactor all 28 command functions from fn(cli, config) to fn(cli, backend)
- Remove dead code: is_extension_mode, extension_send, extension_eval,
  escape_js_string, js_resolve_selector, cookies_extension, inline SNAPSHOT_JS
- Unify output messages (remove "(extension)" suffixes)
- Guard ensure_cdp_override to only run in isolated mode
- Remove unused OpenResult.url field
- Extract eval_with_options in ExtensionBackend to deduplicate eval logic

* [packages/actionbook-rs]feat: add bridge auto-lifecycle and error recovery (Phase 4)

Phase 4 of the browser extension refactoring:

- Add bridge_lifecycle.rs with ensure_bridge_running() and stop_bridge()
  - Auto-starts bridge daemon via setsid() when extension mode commands run
  - Returns bool to track whether bridge was auto-started (shared daemon safety)
  - PID file + port + process-alive validation to detect port conflicts
  - SIGTERM with SIGKILL escalation and PID reuse mitigation

- Add two-layer send architecture in ExtensionBackend:
  - send_once(): single attempt with auto-attach ("No tab attached" recovery)
  - send(): wraps send_once with 30s retry for "Extension not connected"
    and token rotation recovery via send_once (preserves auto-attach)

- Wire bridge lifecycle into create_backend() and close():
  - create_backend() returns (backend, bridge_auto_started)
  - close in extension mode uses close_extension() which bypasses
    create_backend entirely — no bridge auto-start, best-effort detach

Review fixes included:
- Finding 1 (High): close no longer auto-starts bridge or hangs 30s
- Finding 2 (Medium): bridge detection validates PID file, not just TCP
- Finding 3 (Medium): token retry routes through send_once for auto-attach

* [packages/actionbook-rs]refactor: add bridge_lifecycle tests and Phase 5 deprecation cleanup

Phase 4 completion:
- Add 4 unit tests to bridge_lifecycle.rs (stop_noop, port_conflict,
  spawn_when_free)
- All 194 tests passing

Phase 5 deprecation + cleanup:
- Add resolve_extension_port(cli, config) with config as source of truth;
  compare CLI against clap default (not config) to detect explicit override
- Add CLI_DEFAULT_EXTENSION_PORT constant synced with clap default_value
- Compute mode once in run(), pass through to create_backend(mode) and
  close(mode) — deprecation warning now prints exactly once
- Hide --extension-port flag (deprecated, config.toml is primary)
- Update error messages to reference config.toml instead of --extension-port
- Update design doc to reflect close_extension flow, create_backend(mode)
  signature, resolve_extension_port comparison logic, and Phase 5 status

* [skills/actionbook]refactor: rewrite SKILL.md — context not control

- Rewrite from 373 to 143 lines with informational tone
- Remove rigid Phase 1/Phase 2 workflow, "CRITICAL RULE" boxes, prohibited patterns
- Remove internal concepts (area_id format, data model hierarchy, Playbook terminology)
- Update search/get response descriptions to match actual CLI output
- Add Fallback section with selector source constraint
- Remove orphaned extension-troubleshooting.md reference file

* [packages/actionbook-rs]feat: implement extension auto-install and remove token auth

Phase 6 improvements:

1. Auto-install extension during setup
   - Check config.browser.extension.auto_install flag
   - Download latest release from GitHub if not installed
   - Show version and install path on success
   - Provide friendly error and manual install hint on failure
   - Use extension_installer module for correct paths

2. Remove token authentication
   - Remove token reading from send_command
   - Remove token field from hello handshake
   - Remove server-side token validation
   - Keep simple hello/hello_ack for version check
   - Extension connects directly to 127.0.0.1:19222

Impact:
- First-time setup success improved (auto-install removes manual step)
- Simplified authentication (no token file management)
- Better user experience (clear feedback during installation)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* [packages/actionbook-rs]refactor: remove unused token authentication mechanism

BREAKING CHANGE: Token-based authentication removed from bridge

Changes:
- Removed token generation, file I/O, and TTL watchdog
- Removed BridgeState.token and last_activity fields
- Simplified serve() signature (no token parameter)
- Updated native messaging to return bridge_info instead of token
- Enhanced audit logging to include L1 (read-only) operations

Rationale:
- Token was never validated during handshake (Line 869: "no token required")
- Reduces complexity without sacrificing security
- Loopback validation + CDP whitelist provide sufficient protection

Security impact: NEUTRAL
- Loopback still enforced (TCP + WebSocket layers)
- CDP method whitelist still active (L1/L2/L3 risk levels)
- No authentication bypass (token was unused)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* [packages/actionbook-rs]fix: complete token removal cleanup and fix test compilation

Fixes all CRITICAL and HIGH issues identified in dual code review (claude + codex):

CRITICAL fixes:
- Fix test compilation errors (8+ locations)
  * Remove generate_token(), TOKEN_PREFIX, send_command_with_token() references
  * Update start_bridge() to remove token parameter
  * Update hello_extension()/hello_cli() to remove token parameter
  * Delete token-related tests: generate_token_format, generate_token_uniqueness, invalid_token_closes_connection, send_command_fails_when_bridge_not_running
  * Delete test_token_format unit test from extension_bridge.rs

- Fix Chrome extension protocol compatibility
  * Update background.js to handle both "token" (legacy) and "bridge_info" (new) responses
  * Maintain backward compatibility with older extension versions
  * Use dummy token "connected" for storage compatibility

- Remove token retry dead code from extension_backend.rs
  * Delete "invalid token" / "Authentication failed" match arm (lines 91-101)

HIGH fixes:
- Update error messages to remove "invalid token" references
  * extension_bridge.rs: "invalid token?" → "by server"
  * extension_bridge.rs: "Authentication error" → "Handshake error"

- Update documentation and comments (6 locations)
  * native_messaging.rs: "token exchange" → "bridge connection information"
  * native_messaging.rs manifest: "bridge session tokens" → "bridge connection host"
  * extension.rs: "automatic token exchange" → "automatic bridge connection"
  * extension.rs: "Token auto-pairing" → "Auto-connect via native messaging"
  * bridge_lifecycle.rs: "PID/token/port" → "PID/port"

- Clean up Cargo dependencies
  * Remove unused rand and subtle crates (only used for token generation)

MEDIUM fixes:
- Add Extension ID whitelist for security
  * Only allow official Actionbook extension ID (dpfioflkmnkklgjldmaggkodhlidkdcd)
  * Document local trust security model
  * Reject connections from arbitrary chrome-extension:// origins

- Fix test process leak in bridge_lifecycle.rs
  * Add cleanup in ensure_bridge_attempts_spawn_when_port_free test
  * Prevent background process/file leaks after successful spawns

Impact:
- Test suite now compiles and runs (was broken)
- Extension auto-connect works with new bridge (was broken)
- Reduced binary size by removing crypto dependencies
- Improved security with extension ID validation
- No test process/file leaks

Security impact: IMPROVED
- Extension ID whitelist prevents arbitrary extensions from connecting
- Removed unused crypto code (reduced attack surface)
- Documented local trust model (loopback + CDP whitelist)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* [packages/actionbook-rs]fix: resolve dual review findings from fix commit 8f9701c

Fix CRITICAL + HIGH + MEDIUM issues identified by code-reviewer and codex-review:

**CRITICAL (must fix):**
- Fix failing test assertions in extension_bridge.rs (lines 886, 891)
  - Updated to use whitelisted extension ID "dpfioflkmnkklgjldmaggkodhlidkdcd" instead of arbitrary IDs
  - Added explicit rejection tests for non-whitelisted extension IDs
  - Verified with cargo test: all extension_bridge unit tests now pass

**HIGH (should fix):**
- Fix immutability violations in background.js (lines 968-985)
  - Replace property mutation with object spread syntax for storageData
  - Pattern: { ...base, ...(condition && { field }) } instead of mutating base.field
- Add response validation in background.js (lines 958-996)
  - Add explicit else branches for unexpected response formats
  - Add logging for unknown response types to aid debugging
- Add port validation in background.js (lines 969, 983)
  - Validate port is number in valid range (1-65535) before storing
  - Use conditional spread to avoid storing undefined values

**MEDIUM (nice to have):**
- Update stale "Authentication timeout" → "Handshake timeout" (extension_bridge.rs:785)
- Update stale docstring removing token rotation reference (extension_backend.rs:50-54)
- Update stale comment "valid token" → "handshake" (extension_bridge_test.rs:198)

Files changed:
- packages/actionbook-rs/src/browser/extension_bridge.rs: test assertions + wording
- packages/actionbook-rs/src/browser/extension_backend.rs: docstring update
- packages/actionbook-rs/tests/extension_bridge_test.rs: comment update
- packages/actionbook-extension/background.js: immutability + validation

Test verification:
- cargo test browser::extension_bridge::tests - all pass (3/3)
- Confirmed test_origin_allowed now correctly enforces extension ID whitelist

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* [packages/actionbook-rs]refactor: hide extension serve command (auto-starts with browser)

Implement方案 A: hide the `extension serve` command from user-facing help
while preserving functionality for debugging and internal auto-start.

**Changes:**

1. **CLI Definition (cli.rs)**
   - Added `#[command(hide = true)]` to hide `serve` from help output
   - Updated doc comment to clarify auto-start behavior
   - Command still works but invisible in `actionbook extension --help`

2. **User Experience Improvements (extension.rs)**
   - Added deprecation notice when manually running `serve`:
     "Note: The bridge now auto-starts with browser commands"
     "This manual start is only needed for debugging"
   - Updated installation guide (step 4):
     - Before: "Run actionbook extension serve"
     - After: "Run any browser command (bridge auto-starts)"
   - Updated status command error message:
     - Before: "Start with: actionbook extension serve"
     - After: "It will auto-start when you run browser commands"

3. **Error Messages (native_messaging.rs, bridge_lifecycle.rs)**
   - Updated bridge_not_running error to mention auto-start
   - Updated timeout error to remove manual serve suggestion

**Impact:**
- ✅ Zero breaking changes (command still works, tests unaffected)
- ✅ Users no longer see confusing manual start instructions
- ✅ High-level users can still use `actionbook extension serve` for debugging
- ✅ Aligns with Phase 4 bridge auto-lifecycle implementation

**User Workflow:**
Before: actionbook extension serve → actionbook browser open
After:  actionbook browser open (bridge auto-starts transparently)

Files changed: 4 (+27, -10)
- packages/actionbook-rs/src/cli.rs
- packages/actionbook-rs/src/commands/extension.rs
- packages/actionbook-rs/src/browser/native_messaging.rs
- packages/actionbook-rs/src/browser/bridge_lifecycle.rs

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* [docs]refactor: update all extension docs to reflect bridge auto-start

Remove references to manual `actionbook extension serve` and update
documentation to reflect that the bridge now auto-starts with browser commands.

**Files updated:**

1. **skills/actionbook/SKILL.md** (5 references removed)
   - Removed `serve` from command list
   - Updated setup flow: step 3 now runs browser commands instead of manual serve
   - Simplified troubleshooting: removed token expiration section
   - Updated workflow examples to use direct browser commands

2. **packages/actionbook-extension/README.md** (3 references removed)
   - Replaced "Start the bridge" section with "Use the extension"
   - Removed manual serve instructions and token pairing steps
   - Updated troubleshooting: removed token-related issues, added port conflict help
   - Clarified that bridge auto-starts transparently

3. **skills/actionbook/references/extension-troubleshooting.md** (3 references removed)
   - Completely rewrote "Bridge not running" section (now shows auto-start)
   - Removed "Token expired" section (no longer applicable)
   - Removed "Stale port/token files" section
   - Added "Port conflict" and "Stale bridge process" troubleshooting

**Key messaging changes:**
- Before: "Run `actionbook extension serve` to start bridge"
- After: "Bridge auto-starts when you run browser commands"

**User impact:**
- ✅ Documentation now matches actual behavior (Phase 4 auto-lifecycle)
- ✅ Simpler onboarding (one less manual step)
- ✅ No confusing token management instructions
- ✅ Clear troubleshooting for auto-start issues

Files changed: 3 (+52, -46)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* [packages/actionbook-rs]fix: unify directory structure to ~/.actionbook/

Fix inconsistent directory paths to use a unified ~/.actionbook/ structure
instead of platform-specific config/data directories.

**Problem:**
- Extension installed to: ~/Library/Application Support/actionbook/extension (macOS)
- Sessions stored in: ~/Library/Application Support/actionbook/sessions (macOS)
- Config stored in: ~/.actionbook/config.toml ✓ (correct)
- Inconsistent paths confuse users and break the expected ~/.actionbook/ structure

**Root Cause:**
- `extension_installer.rs` used `dirs::config_dir()` → platform-specific
- `session.rs` used `dirs::data_dir()` → platform-specific
- Should use `dirs::home_dir()` + `.actionbook` like config.rs does

**Changes:**

1. **extension_installer.rs:18-26**
   - Changed: `dirs::config_dir().join("actionbook").join("extension")`
   - To: `dirs::home_dir().join(".actionbook").join("extension")`
   - Result: ~/.actionbook/extension/ (all platforms)

2. **session.rs:57-74**
   - Changed: `dirs::data_dir().join("actionbook").join("sessions")`
   - To: `dirs::home_dir().join(".actionbook").join("sessions")`
   - Result: ~/.actionbook/sessions/ (all platforms)

**Unified Directory Structure:**
```
~/.actionbook/
├── config.toml           # ✓ Already correct
├── extension/            # ✓ Now fixed
│   ├── manifest.json
│   └── ...
└── sessions/             # ✓ Now fixed
    ├── default.json
    └── actionbook.json
```

**Platform Impact:**
- macOS: ~/Library/Application Support/actionbook/* → ~/.actionbook/*
- Linux: ~/.local/share/actionbook/* → ~/.actionbook/* (sessions)
         ~/.config/actionbook/* → ~/.actionbook/* (extension)
- Windows: %APPDATA%\actionbook\* → %USERPROFILE%\.actionbook\*

**Migration:**
Users with existing installations in old paths will need to:
1. Run `actionbook extension install --force` to reinstall to new path
2. Sessions will auto-recreate in new path on next launch

Files changed: 2 (+8, -8)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* [packages/actionbook-rs]fix: add missing CDP params to press_key for functional keys

Input.dispatchKeyEvent was only sending `key` and `text`, missing `code`
and `windowsVirtualKeyCode`. This caused keys like PageDown, Home, End
to be silently ignored by Chrome — no scroll or navigation occurred.

Also added F1-F12 and Insert key mappings.

* [packages/actionbook-rs]fix: make PID file writes mandatory and improve bridge lifecycle

Changes:
- Make PID file write errors fatal in extension serve command
- Clean up stale PID files regardless of port match
- Improve port conflict detection with platform-specific hints
- Add ActionbookError import for better error handling

Benefits:
- Prevents silent failures when PID file can't be written
- Cleaner automatic cleanup of orphaned files
- Better UX with actionable error messages (lsof/netstat hints)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* [packages/actionbook-extension]refactor: remove token validation for tokenless authentication

Changes:
- Remove token validation function (replaced with legacy compatibility)
- Remove token requirement in connect() flow
- Remove token field from WebSocket handshake
- Remove dummy token storage ("connected" placeholder)
- Update UI: "Token required" → "Waiting for bridge"
- Hide token input section by default
- Deprecate token handlers with backward compatibility

Benefits:
- Cleaner state machine aligned with tokenless backend
- Better UX without confusing token prompts
- Maintains backward compatibility with legacy handlers
- Aligns with localhost trust security model

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* [packages/actionbook-rs]refactor: improve browser mode selection UI clarity

Changes:
- Use lowercase mode names matching config: "extension", "isolated"
- Add detailed descriptions for each option explaining use cases
- Change prompt titles: "Browser mode" → "Browser Mode", etc.
- Update default selection to "isolated" (better for new users)
- Improve browser executable descriptions with clear benefits
- Update display mode options to lowercase: "visible", "headless"

Benefits:
- UI text now matches config.toml exactly (no confusion)
- Users can clearly understand the difference between modes
- Better defaults guide users to appropriate choices
- Consistent lowercase naming throughout

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* [packages/actionbook-rs]refactor: remove save confirmation step in setup

Changes:
- Remove interactive choice menu (Save/Restart/Discard)
- Auto-save configuration after showing summary
- Keep configuration summary display for user review
- Simplify setup flow: configure → review → auto-save

Benefits:
- Faster setup flow with fewer clicks
- Less interruption for users who know what they want
- Still shows summary for verification before saving
- Reduces decision fatigue in setup process

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* [packages/actionbook-rs]refactor: show API key input in plain text

Changes:
- Change Password input to Input for API key entry
- Display API key as user types (no masking)
- Keep allow_empty option for skipping

Benefits:
- Users can see what they're typing (avoid typos)
- Easier to paste and verify API keys
- More transparent input experience
- Still allows skipping by leaving blank

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* [packages/actionbook-rs]fix: correct browser selection descriptions in setup

Changes:
- Fix misleading "Built-in — Download Chromium" description
- Change to "Auto-detect — Will use Chrome (highest priority)"
- Show preview of what browser will be selected with auto-detect
- Update browser option descriptions from "Use system browser" to "Use this specific browser"
- Show detected browser name in confirmation output

Benefits:
- Users understand auto-detect doesn't download anything
- Clear preview of what will be selected
- Eliminates confusion about "Built-in" vs specific browser
- More transparent behavior

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* [packages/actionbook-rs]refactor: show only actual browsers, remove auto-detect option

Changes:
- Remove "Auto-detect" option from browser selection
- List only actual detected browsers (Chrome, Brave, Edge, Arc, Chromium)
- Show browser path in dimmed text for clarity
- Change prompt to "Select browser for isolated mode"
- Default to first detected browser (highest priority)
- Make browser selection explicit and deterministic

Benefits:
- Users clearly see which browser will be used
- No confusion between auto-detect and specific browser
- Transparent browser selection with full path shown
- Each browser choice directly maps to that browser in isolated mode

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* [packages/actionbook-rs]refactor: show full API key in setup summary (not masked)

Changes:
- Display complete API key in configuration summary
- Remove mask_key() call, show actual key value
- Keep "not configured" fallback for missing key

Benefits:
- Users can verify the exact API key saved
- No confusion from masked format (sk-p...c123)
- Easier to spot typos or incorrect keys
- More transparent configuration display

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* [packages/actionbook-rs]fix: show full API key in final setup recap (not masked)

Changes:
- Remove mask_key() call in final configuration recap
- Display complete API key after setup completion
- Show actual key value instead of "sk-p...c123" format

Benefits:
- Users can verify exact API key saved
- Consistent with setup summary (both show full key)
- No confusion from masked format

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* [skills/actionbook]chore: bump skill version to 0.3.0 and refine SKILL.md

Update marketplace.json version from 0.2.0 to 0.3.0. Rewrite SKILL.md
activation section for clearer trigger conditions and add Extension mode
mention.

* [packages/actionbook-rs]feat: improve browser setup and API key validation

- Reorder browser mode options: isolated first (default), extension second
- Add API key validation during setup using real search_actions request
- Display full API key (not masked) when validation succeeds
- Handle invalid API key format (code 10002) correctly
- Prompt user to retry if API key is invalid

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* [packages/actionbook-rs]feat: browser close now stops bridge server

Changes:
- Modified close_extension() to always call bridge_lifecycle::stop_bridge()
- Ensures extension shows "disconnected" status after browser close
- Prevents orphaned bridge processes when task is complete

Before:
- browser close only detached tab, left bridge running
- User had to manually run 'actionbook extension stop'

After:
- browser close automatically stops bridge server
- Extension displays disconnected state immediately

Tested:
- Bridge auto-starts on browser open
- Bridge stops on browser close
- Port 19222 released properly
- No orphaned processes

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* [packages/actionbook-rs]fix: print extension connected message after retry succeeds

- When extension is not initially connected, CLI prints waiting message
- After retry succeeds, now prints '✓ Extension connected' message
- Prevents external agents from thinking extension is still disconnected
- Only prints success message when retry loop succeeds, not on first success

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* [root]docs: add actionbook-rs development workflow script and documentation

- Created scripts/actionbook-dev.sh for streamlined development workflow
- Added install, test, build, clean, and watch commands
- Updated CLAUDE.md with actionbook-rs development guidelines
- Emphasizes running 'cargo install --path . --force' before testing

Key points:
- Always install before testing to use latest local build
- Avoids testing stale global binaries
- Provides convenient wrapper for common development tasks

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* [packages/actionbook-rs]feat: enhance bridge shutdown with PID recovery and extension notification

- Use lsof to find PID when PID file missing (Unix only)
- Send server_shutdown message to extension before closing
- Add 100ms delay for extension to update UI gracefully

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* [packages/actionbook-rs]fix: add missing timeout import for compilation

- Added 'use tokio::time::timeout;' import in browser.rs
- Fixes compilation failure at lines 188, 211, 217 where timeout() was used
- Resolves P0 blocking issue in refactor/browser-extension PR

* [packages/actionbook-rs]fix: preserve browser mode in non-interactive setup

- Removed forced 'config.browser.mode = Isolated' assignment
- Now preserves existing config.browser.mode (loaded from existing config or defaults)
- For Isolated mode: sets executable and headless as before
- For Extension mode: preserves existing config without modification
- Fixes P1 issue where --non-interactive would overwrite user's extension config
- Resolves scenario where users with extension mode would be forced to isolated

* [packages/actionbook-rs]fix: verify PID ownership before stop_bridge kills process

Security Enhancement:
- Added is_actionbook_bridge_process() to verify PID belongs to Actionbook
- Prevents accidentally terminating unrelated processes on shared ports
- Uses 'ps' (Unix) or 'wmic' (Windows) to check process command line

Implementation:
- New function: extension_bridge::is_actionbook_bridge_process(pid)
- Validates command line contains 'actionbook' before sending signals
- Added in bridge_lifecycle.rs when lsof finds PID without PID file
- Fail-safe: returns false if verification fails or process unreadable

Testing:
- Added 3 unit tests for current/invalid/system processes
- All tests passing

Resolves P1 Codex comment: 'Restrict stop_bridge to known bridge PIDs'
Fixes bridge_lifecycle.rs:173 security issue

* [packages/actionbook-rs]fix: optimize extension connection timing and reduce misleading prompts

**Extension-side changes (background.js)**:
- Reduced Native Messaging polling interval from 5s to 2s
- Faster bridge detection (max 2s instead of 5s)

**CLI-side changes (extension_backend.rs)**:
- Adjusted silent retry period from 10s to 6s (12 attempts × 500ms)
- Matches 2 extension polling cycles (2s × 2) + handshake timeout (2s)
- Only prompts user if extension not connected after 6s

**Connection timing**:
- Previous: Up to 7s (5s poll + 2s handshake), prompted after 10s
- New: Up to 4-6s (2s poll + 2s handshake), prompted after 6s
- Result: Faster connections and timely user prompts

**Previous behavior**:
- Extension polled every 5s (slow bridge detection)
- CLI prompted after 1.5s initially, then adjusted to 10s
- Caused misleading "Open Chrome..." messages during normal delays

**New behavior**:
- Extension polls every 2s (3x faster bridge detection)
- CLI silent retries for 6s (covers 2 polling cycles + handshake)
- Only prompts user if genuinely needed
- Success message only shown if user was previously notified

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* [skills/actionbook]docs: improve search query construction guidance

Added comprehensive guidance on constructing effective search queries:

**New content**:
- Detailed "Constructing an effective search query" section
- 4-step framework for building queries (site, verb, object, details)
- Comparison table showing bad vs good query examples
- Practical examples with user request → query translation
- Removed outdated --background flag documentation

**Examples added**:
- Airbnb booking: "airbnb search listings Tokyo dates..."
- arXiv papers: "arxiv advanced search papers NLP..."
- LinkedIn requests: "linkedin send connection request..."
- Twitter posts: "twitter compose new tweet post with image..."
- GitHub issues: "github repository issues filter by label..."

**Improvements**:
- Changed generic "Example" to specific "Examples" with context
- More actionable query construction rules
- Emphasizes packing full user intent into query string

This helps users write better queries and get more relevant results.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* [packages/actionbook-rs]fix: resolve merge-induced test compilation errors

After merging main into refactor/browser-extension, the Cli struct gained
`camofox` and `camofox_port` fields but two test helper functions were not
updated, breaking `cargo test`. Additionally, three example files from
main reference modules (camofox, fingerprint_generator, human_behavior)
that are not declared in mod.rs in this branch, so they are gated behind
the camoufox-server feature flag.

https://claude.ai/code/session_01QoVb55KEwd6wbsH1Za1N3y

* fix(actionbook-rs): honor browser mode and restore extension install path

* chore: sync marketplace and docs with main

* [packages/actionbook-rs]fix: restore backend and camofox_port fields to ProfileConfig

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* [packages/actionbook-rs]fix: restore extension bridge lifecycle in browser mode

---------

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-13 14:19:57 +08:00
Adcent 664f96af0f fix(review): address open-tab reuse feedback 2026-02-11 20:04:36 +08:00
Adcent 8d56c2aac1 fix(extension): reuse initial empty tab on open 2026-02-11 19:24:40 +08:00
sen 8261b18e44 [packages/actionbook-extension]feat: add CWS variant zip without manifest key field (#110)
- Add CWS build variant that strips the `key` field from manifest.json
- Update release workflow to produce both sideloading and CWS zips
- Bump extension version to 0.1.2
2026-02-10 19:39:27 +08:00
sen 71f1958323 [packages/actionbook-extension]chore: prepare Chrome Web Store publishing (#108)
* [packages/actionbook-extension]chore: prepare Chrome Web Store publishing

- Bump extension version to 0.2.0 (sync with bridge protocol)
- Add PRIVACY.md for Chrome Web Store submission
- Add store-assets/ to .gitignore

* [packages/actionbook-extension]chore: bump package.json version to 0.2.0

* [packages/actionbook-extension]chore: set version to 0.1.1
2026-02-10 18:45:50 +08:00
sen f2532d96c4 [packages/actionbook-extension]fix: read version from manifest dynamically instead of hardcoding (#102)
popup.html had hardcoded v0.2.0 while manifest.json was at 0.1.0.
Now popup.js reads chrome.runtime.getManifest().version to stay in sync.
2026-02-10 13:59:35 +08:00
sen 1484b5b59c feat: isolated extension profile + extension stop command (#99)
* [packages/actionbook-rs]feat: add isolated Chrome profile for extension bridge mode

Support running the extension bridge with a dedicated Chrome profile
that contains no personal data. This adds:

- `extension_isolated_profile` config field with backward-compatible default
- `--isolated` CLI flag on `extension serve`
- `serve_with_shutdown()` bridge refactor for external lifecycle control
- `isolated_extension` orchestrator: launches Chrome with extension
  pre-loaded on CDP port 9333, monitors process, handles cleanup
- `with_load_extension()` builder on BrowserLauncher
- Setup wizard prompt for isolated vs shared extension profile
- Recap and completion output updates

CUE-347

* [packages/actionbook-rs]fix: harden isolated extension bridge lifecycle

- Propagate bridge server errors (e.g. port-in-use) instead of
  swallowing them; callers now see a non-zero exit code
- Reset extension_isolated_profile flag when switching to built-in
  browser, preventing stale config from routing to isolated mode
- Replace shell-based `kill` command with libc::kill() to eliminate
  PATH-hijacking risk; only send signals when Chrome hasn't already
  exited to avoid hitting a recycled PID
- Tighten "already running" detection: require both SingletonLock in
  the isolated profile dir AND a responsive CDP endpoint, preventing
  mistaken reuse of a different Chrome instance on the same port

* [packages/actionbook-rs]fix: harden isolated extension bridge with CDP pipe transport

- Replace --load-extension (removed in Chrome 137+) with CDP pipe
  transport: launch Chrome with --remote-debugging-pipe, then send
  Extensions.loadUnpacked over fd 3/4 post-launch
- Add cdp_pipe.rs: null-terminated pipe protocol, PipeKeepAlive handle,
  and load_extension with blocking I/O for spawn_blocking
- Add cdp_http.rs: CDP /json/list target discovery and Runtime.evaluate
  for injecting bridge token directly into extension storage via CDP
- Add background.js storage.onChanged listener for CDP-injected tokens
- Fix non-Unix isolated mode: fail early with clear error instead of
  silently launching without extension loading capability
- Fix CLOEXEC on fd 3/4: when os_pipe fd already equals target fd
  number, clear FD_CLOEXEC via fcntl instead of skipping dup2
- Fix token injection safety: find_any_extension_service_worker now
  matches only SWs ending with /background.js to avoid injecting
  tokens into third-party extensions
- Fix cleanup cross-contamination: serve_with_shutdown and
  isolated_extension only delete files belonging to their own mode,
  preventing concurrent bridge interference
- Refactor resolve_cdp_endpoint for reuse across connect and --cdp
- Add session WS URL refresh on reconnect to handle browser restarts
- Update tests for pipe flags, SW filename filtering, stale WS URLs

* [packages/actionbook-rs]feat: add `extension stop` command to gracefully stop bridge server

Adds PID file mechanism so `actionbook extension stop` can locate and
terminate the running bridge process without manual Ctrl+C or `kill`.

- PID files written with 0600 permissions (atomic write) to prevent injection
- Validates bridge is listening on expected port before sending SIGTERM (no PID recycling risk)
- SIGKILL escalation after 2.5s timeout
- Platform guards: #[cfg(unix)] with Windows taskkill fallback
- Tracks isolated vs global PID files independently

* [skills/actionbook]docs: update skill with extension stop command and full lifecycle

- Add `actionbook extension stop` to command list
- Replace manual process kill comment with concrete `extension stop` command
  in the cleanup lifecycle (Step 2)
- Update extension mode example to include stop in cleanup

* [docs/guides]docs: add extension stop command to browser extension guide

- Setup Step 3: mention `extension stop` as the way to stop the bridge
- New "Shutdown" section with proper cleanup order (browser close → extension stop)
- Troubleshooting: reference `extension stop` for bridge restart flow

* [docs/guides]docs: add isolated extension mode to browser extension guide

- Overview: expand mode table with Extension (Isolated) as third option
- New "Isolated Mode" section: quick start, config, comparison table,
  when-to-use guidance
- Shutdown: separate instructions for standard vs isolated mode

* [packages/actionbook-rs]fix: resolve PID by port and preserve PID file when process alive

Fix two bugs in `extension stop` identified in PR review:

1. Use port files to match the requested port to the correct PID file
   (isolated vs standard), preventing SIGTERM to the wrong bridge when
   both are running on different ports.

2. Only delete the PID file when the process is confirmed dead (via
   kill(pid, 0)), not merely because the port probe failed. This
   preserves the PID file for a subsequent `extension stop --port
   <correct>` when the bridge is on a different port.

* [packages/actionbook-rs]fix: smart cleanup of cross-mode stale files and prevent ambiguous PID selection

Address follow-up review findings on extension stop and bridge startup:

1. Extract `is_pid_alive()` utility to extension_bridge for cross-platform
   PID liveness checks (kill(0) on Unix, tasklist on Windows).

2. Smart cross-mode cleanup at startup: instead of blindly deleting the
   other mode's files (breaks concurrent bridges) or never deleting them
   (leaves stale tokens that confuse send_command), check if the other
   mode's process is alive via PID probe before deciding.

3. Refuse to auto-stop when both PID files exist but no port file matches
   the requested port, preventing SIGTERM to the wrong bridge.

4. Make serve_with_shutdown mode-aware: only clean the current mode's
   stale port file instead of always cleaning the standard one.

* [packages/actionbook-rs]fix: atomic PID:PORT mapping to prevent SIGTERM to wrong process

Store port alongside PID in the same file (PID:PORT format) to create
an atomic PID-to-port mapping. This eliminates all port-file-based
guessing in `extension stop`, fixing the root cause of the P1 bug
where SIGTERM could be sent to the wrong process.

- write_pid_file/write_isolated_pid_file: write "PID:PORT" format
- read_pid_file/read_isolated_pid_file: return Option<(u32, u16)>
- stop(): deterministic PID selection via embedded port match
- is_pid_alive (Windows): fix tasklist substring match (exact field)
- taskkill: only delete PID file when process confirmed dead

* [packages/actionbook-rs]fix: select token by port in send_command for parallel bridges

Use PID:PORT mapping to select the correct token file based on target
port, so parallel bridges (standard + isolated) authenticate correctly.
Previously the fixed read order (standard first) caused auth failures
when sending commands to the isolated bridge while standard was running.

* [packages/actionbook-rs]fix: clean up Chrome and bridge on isolated extension load failure

When extension loading fails (CDP error, panic, or timeout), the early
return bypassed all cleanup logic, leaving the child Chrome process
running and stale bridge state files on disk. Now performs shutdown
signal, file cleanup, and Chrome termination before returning the error.
2026-02-10 13:56:03 +08:00
sen aed25e2aea fix: extension auto-reconnect on token mismatch with progressive backoff (#97)
* [packages/actionbook-extension]fix: auto-reconnect on token mismatch with progressive native messaging backoff

Bridge server now sends hello_error with "invalid_token" instead of
silently closing the connection, allowing the extension to immediately
clear the stale token and refresh via native messaging.

Extension changes:
- Handle invalid_token hello_error by clearing stored token and
  retrying native messaging immediately
- Replace fixed 60s native messaging recheck with progressive backoff
  (3s, 5s, 10s, 30s, 60s) that never permanently gives up
- Treat bridge_not_running as a transient error (not a native messaging
  failure) to avoid unnecessary backoff escalation
- Reset fail count on successful native messaging token exchange

This ensures users who install the extension after the bridge is already
running can auto-connect without manual token copy-paste or bridge restart.

* [skills/actionbook]docs: update SKILL.md for extension mode lifecycle and setup flow

- Rewrite Phase 2 extension mode with full lifecycle commands
- Move Extension Setup & Management section earlier for better flow
- Add connection check commands before automation
- Clarify browser close behavior in extension mode
2026-02-10 13:44:53 +08:00
sen caa5b34dc2 [packages/actionbook-extension]chore: set initial release version to 0.1.0 (#94) 2026-02-09 18:29:09 +08:00
sen 2d17e2ce3f refactor: decouple extension from CLI binary with independent release pipeline (#93)
* [packages/actionbook-extension]feat: add independent release infrastructure

- Add GitHub Actions workflow for tag-triggered releases (actionbook-extension-v*)
- Add package.json with npm run package script for local zip packaging
- Add scripts/package.js to build distributable .zip from extension files
- Add .gitignore for dist/ and node_modules/
- Rewrite README with install/release/troubleshooting docs

The extension now has its own independent release cycle via GitHub Releases,
decoupled from the CLI binary release process.

* [packages/actionbook-rs]refactor: replace embedded extension with GitHub download installer

Remove all include_str!/include_bytes! compile-time embedding of the Chrome
extension. The CLI now downloads the extension from GitHub Releases at install
time via `actionbook extension install`.

Key changes:
- Rename embedded_extension.rs → extension_installer.rs
- Add download_and_install() using reqwest with HTTPS-only, timeouts
- Add extract_zip() with zip-slip and zip-bomb protection
- Add download URL host validation (github.com whitelist)
- Add post-extraction manifest version verification
- Use semver crate for proper version comparison
- Add zip crate dependency for safe extraction
- Update extension command to use new installer module

Security measures:
- HTTPS-only with 30s request / 10s connect timeouts
- 10MB max download size, 50MB max uncompressed size
- Zip-slip protection via enclosed_name()
- Download host whitelist (github.com, githubusercontent.com)
- Manifest version verification after extraction

* [packages/actionbook-rs]fix: atomic install, better error display, and real zip test

- Display errors with thiserror format instead of Rust Debug
  ("Extension error: ..." not "ExtensionError("...")")
- Atomic install: extract to temp dir, verify manifest, then swap
  (existing install survives if download/extract fails)
- Move tempfile from dev-dependencies to dependencies
- Add test_extract_real_extension_zip using actual packaged zip

* [packages/actionbook-rs,actionbook-extension]fix: address review findings from dual review

- Remove early return in install command that blocked automatic upgrades;
  let download_and_install() handle semver comparison via new
  ExtensionAlreadyUpToDate error variant
- Remove redundant zip -j9 call in package.js, keep only zip -r9
- Add pagination NOTE on fetch_latest_release()
- Make test_extract_real_extension_zip read version from manifest.json
  dynamically instead of hardcoding "0.2.0"
2026-02-09 18:14:10 +08:00
sen 7f32f83815 feat: add browser extension bridge for CLI-to-browser communication (#89)
* [packages/actionbook-rs]feat: add browser extension

Implements the WebSocket bridge server and Chrome Extension skeleton
for controlling the user's own browser via extension mode.

New components:
- Chrome Extension (MV3): background service worker, popup UI,
  WebSocket client connecting to bridge on localhost:19222
- Bridge server: `actionbook extension serve` - routes commands
  between CLI and extension with request ID rewriting and timeouts
- CLI: --extension flag, `actionbook extension serve/status/ping`
- Extension mode routing for `eval` and `pages` browser commands

Architecture: CLI -> WebSocket -> Bridge -> Extension -> chrome.debugger

* [packages/actionbook-rs]fix: merge duplicate extension_send fns and fix is_bridge_running side effect

- Merge extension_send_cdp and extension_send into a single function
- Replace WebSocket-based is_bridge_running with plain TCP connect
  to avoid orphan connections and spurious bridge warnings

* [packages/actionbook-extension]feat: add offscreen keepalive, CDP event forwarding, createTab/activateTab

- Add offscreen document for Service Worker keepalive (ping every 20s)
- Forward CDP events from chrome.debugger.onEvent to CLI via WebSocket
- Add exponential backoff reconnect (1s base, 2x growth, 30s max)
- Auto-attach to active tab when no tab is attached
- Add Extension.createTab and Extension.activateTab command handlers
- Improve error handling for debugger detachment detection

* [packages/actionbook-rs]feat: add extension mode to all browser commands (Phase 2)

Add --extension flag support to all browser subcommands, routing CDP
operations through the WebSocket bridge instead of direct chromiumoxide.

Commands implemented: goto, back, forward, reload, open, switch, wait,
click, type, fill, select, hover, focus, press, screenshot, pdf, html,
text, snapshot, inspect, viewport, cookies, close, restart.

Includes js_resolve_selector helper for [ref=eN] snapshot references
and extension_eval helper with exception handling.

Also fixes escape order bug in js_resolve_selector (backslashes must
be escaped before single quotes).

* [packages/actionbook-rs]test: add extension bridge integration tests and mock extension

- Add [lib] crate to expose modules for integration tests
- Add 9 integration tests covering: CLI without extension error,
  full round-trip with id remapping, error forwarding, multiple
  concurrent CLIs, is_bridge_running detection, connection failure
- Add mock-extension.mjs for manual E2E testing with mock CDP responses

* [packages/actionbook-rs]test: add Chrome E2E test script and expand bridge unit tests

- Add extension-chrome-e2e.sh: real Chrome + arxiv.org E2E test covering
  navigation, content extraction, screenshots, cookies, tab management,
  interactions, and JSON output mode
- Expand bridge_tests module with additional assertions and helpers

* [packages/actionbook-rs]feat: add extension install/path/uninstall CLI commands

Embed all 9 Chrome extension files into the Rust binary via
include_str!/include_bytes! and provide CLI commands to extract them
to ~/.config/actionbook/extension/ for easy Chrome sideloading.

New commands:
- `actionbook extension install [--force]`
- `actionbook extension path`
- `actionbook extension uninstall`

Also updates `extension serve` to show the real installed path
with outdated/not-installed warnings. All commands support --json.

* [packages/actionbook-rs,actionbook-extension]feat: implement extension security Phase 0-2

Phase 0 - Connection Hardening:
- Lazy connect (idle start, user-triggered connection)
- Bounded reconnect with MAX_RETRIES=8 and exponential backoff
- Distinguish network errors from auth failures in pre-handshake close

Phase 1 - Session Token Auth:
- Token generation (abk_ + 32 hex), atomic file write (0600)
- Hello/hello_ack handshake protocol with token validation
- Constant-time token comparison (subtle crate) to prevent timing attacks
- TTL watchdog with 30min idle token rotation
- Token format validation (abk_ prefix + length) in both CLI and extension

Phase 2 - CDP Allowlist & Risk Levels:
- CDP method allowlist with L1/L2/L3 risk classification
- L3 human-in-the-loop confirmation via popup with nonce binding
- Sender validation (only popup.html can approve L3 or set tokens)
- Sensitive domain detection with L2→L3 risk elevation
- Origin validation (loopback + chrome-extension:// only)

Security hardening from dual review:
- Replace all console.log with debug utility behind DEBUG_ENABLED flag
- Remove token pre-population in popup input
- Reject concurrent L3 requests (no slot overwrite)

* [packages/actionbook-rs]chore: remove browser-extension-design.md from tracking

* [actionbook-extension]chore: replace placeholder icons with Actionbook logomark

Extract the logomark from docs/logo SVG and generate proper PNG icons
at 16x16, 48x48, and 128x128 to replace the blue placeholder squares.

* [packages/actionbook-rs,actionbook-extension]feat: switch cookie ops to chrome.cookies API with security gating

Replace CDP Network.* cookie methods (which required L3 popup confirmation
and always timed out in automated usage) with chrome.cookies.* API via
new Extension.getCookies/setCookie/removeCookie/clearCookies commands.

Security hardening from code review:
- All cookie ops require a valid http(s) URL scope — no cross-domain wildcard
- Cookie writes (set/remove/clear) gated by L3 confirmation on sensitive domains
- Input validation for url, name, value params in background.js
- Native messaging entry point validates exact extension ID (not prefix)
- setCookie checks for null return (browser rejection)
- clearCookies uses Promise.allSettled for parallel removal

Also adds native messaging auto-connect, bridge token rotation handling,
and fixes .gitignore typo (.doc -> .docs/).

* [packages/actionbook-rs]test: replace arxiv.org with automation-friendly test sites

Switch E2E test targets from arxiv.org (rate-limited) to
the-internet.herokuapp.com and example.com for reliable CI.

- Phase 2: use `browser open` to avoid chrome:// tab issues
- Phase 6: login form interactions on /login (public test creds)
- Phase 7: hover on /hovers `.figure`, focus link on homepage
- Phase 9: example.com for new-tab test
- login-result-page: check URL path instead of page title

* [actionbook-extension]docs: add extension usage guide

Cover installation, bridge setup, token pairing, all browser
subcommands (navigation, interaction, tabs, debug, cookies, connect),
Action Manual integration, and common troubleshooting.

* [packages/actionbook-rs,actionbook-extension]fix: address PR #89 review — bridge security, reliability, and correctness

- Add awaitPromise to Runtime.evaluate for async extension commands
- Fix origin validation prefix-matching bypass (exact host matching)
- Send token_expired notification before closing extension WebSocket
- Return immediate error when extension channel is closed
- Propagate custom bridge port to extension via native messaging
- Prioritize explicit --domain over current URL in cookie ops
- Retry native messaging with backoff instead of permanent disable
- Use serde_json for comprehensive JS string escaping
- Validate protocol version in bridge handshake with semver

* [packages/actionbook-rs,actionbook-extension]fix: tab auto-attach, profile validation, and cookie clear safety

1. (Critical) Extension.createTab and Extension.activateTab now auto-attach
   the Chrome debugger to the new/activated tab, so subsequent CDP commands
   target the correct tab instead of a stale attachedTabId.

2. (High) --profile flag combined with --extension now produces a hard error
   instead of being silently ignored.

3. (Medium) cookies clear gains --domain, --dry-run, and --yes flags.
   --yes is required to actually clear (both interactive and JSON modes).
   --dry-run previews which cookies would be cleared without deleting.
   --domain scopes the clear to a specific domain.
   CDP mode rejects --domain/--dry-run with a clear error message.

Tests: 6 new tests covering all three fixes (bridge-level + CLI parser).

* [skills/actionbook]docs: fix SKILL.md extension mode documentation

- Remove non-existent --path flag from extension install
- Add missing extension uninstall command and --extension-port flag
- Simplify Phase 2 alt to avoid redundant duplication of CDP example
- Move Extension Setup section after Browser Commands for logical flow
- Extract troubleshooting content to references/extension-troubleshooting.md
- Fix misleading "runs in background" description for serve (it's foreground)
- Replace opaque "L3 operations" term with concrete description
- Add browser close safety note for extension mode

* [packages/actionbook-rs,actionbook-extension]fix: use domain-based query for cookie clear to cover all paths

chrome.cookies.getAll({ url }) only returns cookies whose path matches
the URL path. When --domain builds https://domain/, cookies scoped to
/app, /account, etc. are silently missed. Pass an explicit domain param
so the extension uses getAll({ domain }) which covers all paths.
2026-02-09 14:06:44 +08:00