Commit Graph

1001 Commits

Author SHA1 Message Date
mcfn f7cde0d9f7 [packages/cli-v2]test: add Batch 3 E2E tests for browser describe and browser state
14 tests in tests/e2e/describe_state.rs:
- describe: JSON happy path, text output, --nearby JSON, --nearby text
- state: JSON happy path (all 6 boolean fields), text output
- error cases: SESSION_NOT_FOUND, TAB_NOT_FOUND, ELEMENT_NOT_FOUND for both commands
- P1 regressions: JS_EXCEPTION monkeypatch for describe (getAttribute) and state (ownerDocument)

Tests only — no implementation. Compile-verified: 14/14 skip without RUN_E2E_TESTS.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-29 17:56:46 +08:00
Junliang Feng f81a1cb64f [packages/cli-v2] feat: add browser attrs/box/styles (Batch 2) (#360) 2026-03-29 17:50:08 +08:00
mcfn 7441667ad7 [packages/cli-v2]chore: fix pre-existing lint issues from base branch
Drive-by fixes for lint issues inherited from release/1.0.0 base branch:
- scroll.rs: cargo fmt formatting
- hover.rs: collapse nested if-let (clippy collapsible_if)

Unblocks CI lint check for PR #360.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 17:48:56 +08:00
mcfn 4558e2dfd0 [packages/cli-v2]test: add P1 JS exception propagation E2E tests
Add monkeypatch-based E2E tests for all three observation commands
(attrs, box, styles) to verify that when Runtime.callFunctionOn returns
exceptionDetails, the CLI surfaces ok=false / error.code=JS_EXCEPTION
instead of silently returning empty {}.

- styles_js_exception_propagated: patches window.getComputedStyle to throw
- box_js_exception_propagated: patches element.getBoundingClientRect to throw
- attrs_js_exception_propagated: patches element.attributes getter to throw

E2E suite now 13/13 green.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 17:48:56 +08:00
mcfn a70ed62ce0 [packages/cli-v2]test: add P1 E2E regression for JS_EXCEPTION via getComputedStyle monkeypatch 2026-03-29 17:48:56 +08:00
mcfn 41334bdc84 [packages/cli-v2]test: add P2 regression test for box no-scroll
Verifies browser box on off-screen element returns coordinates
without changing window.scrollY (read command must be stateless).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 17:48:56 +08:00
mcfn 97cf75efc1 [packages/cli-v2]fix: check exceptionDetails and remove scroll side-effect
P1: attrs.rs, box.rs, styles.rs now check CDP exceptionDetails after
Runtime.callFunctionOn — JS exceptions return JS_EXCEPTION error
instead of being silently swallowed as empty success.

P2: box.rs removes scroll_into_view before getBoundingClientRect —
read commands must be stateless with no viewport side-effects.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 17:48:56 +08:00
mcfn c2517be90c [packages/cli-v2]feat: add observation batch 2 2026-03-29 17:48:56 +08:00
adcentury 8397937d98 Merge branch 'release/1.0.0' of github.com:actionbook/actionbook into release/1.0.0 2026-03-29 17:40:43 +08:00
adcentury d5b3ba8e74 add cli building guides 2026-03-29 17:40:25 +08:00
asensagent e00c48fd28 feat: implement all interaction commands for CLI v1.0.0 (#361)
* test: add hover command cases

* test: add hover text error coverage

* feat: implement browser hover command

Add the `browser hover <selector>` command. Resolves the selector to a
DOM node via the shared element module, then dispatches mouseenter,
mouseover, and mousemove events via Runtime.callFunctionOn for reliable
hover semantics in headless Chrome. Wired up across CLI parsing, action
enum, router, and output formatting.

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

* test: add focus command cases

* feat: implement browser focus command

Add the `browser focus <selector>` command. Resolves the selector via
the shared element module, uses DOM.focus to set focus on the target,
and compares pre/post active element by JS reference identity (===) to
correctly report focus_changed even for anonymous elements. Wired up
across CLI parsing, action enum, router, and output formatting.

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

* test: add press command cases

* feat: implement browser press command

Add the `browser press <key-or-chord>` command. Parses single keys and
chord combinations (e.g. Control+A, Shift+Tab), validates modifier
segments, and dispatches keyDown/keyUp via CDP Input.dispatchKeyEvent
with the appropriate modifiers bitmask. Wired up across CLI parsing,
action enum, router, and output formatting.

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

* test: add drag command cases

* feat: implement browser drag command

Adds drag-and-drop via CDP Input.dispatchMouseEvent sequence:
mousePressed at source → mouseMoved along path → mouseReleased at
destination. Destination accepts either a selector or x,y coordinates.

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

* fix: drag dispatch via viewport resize + CDP Input events

CDP Input.dispatchMouseEvent requires elements to be within the visible
viewport. The drag fixture positions elements at top:780px which exceeds
the default headless Chrome viewport (~469px). Fix by temporarily
enlarging the viewport via Emulation.setDeviceMetricsOverride before
the drag sequence, then clearing the override after completion.

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

* fix: resize viewport before resolving drag coordinates

Move Emulation.setDeviceMetricsOverride before element resolution so
coordinates are captured under the final viewport. Avoids stale
coordinates on responsive pages where a post-resolution resize could
shift element positions.

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

* fix: preserve viewport width during drag, only expand height if needed

Read the current viewport dimensions and only override if the height is
too short for the drag endpoints. Width is preserved to avoid flipping
responsive breakpoints or triggering resize handlers. The override is
skipped entirely when the viewport is already tall enough.

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

* test: add upload command cases

* feat: implement browser upload command

Adds `browser upload <selector> <file...> --session --tab` which sets
files on a file input via CDP DOM.setFileInputFiles. Validates that all
paths are absolute, resolves the target node, and returns a value_summary
with file list and count. All 10 e2e tests pass.

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

* fix: require at least one file path in browser upload

Adds `#[arg(required = true, num_args = 1..)]` to the `files` field so
Clap rejects invocations with zero files at parse time, matching the
spec's `<file...>` contract. Adds a unit test for the missing-files case.

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

* test: add eval command cases

* fix: update browser eval to return typed value, type, and preview per spec

- Return `data.value` as typed JSON (number/bool/string) instead of
  always stringifying
- Add `data.type` (JS type from CDP) and `data.preview` (string repr)
- Return null context for SESSION_NOT_FOUND
- Extract exception description for better EVAL_FAILED error messages
- Update cloud eval tests to assert typed values

All 11 eval tests pass (8 interaction + 3 cloud).

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

* test: add eval context coverage

* fix: include tab URL and title in browser eval context

Fetches the current page URL and title after eval execution and returns
them in the response context, matching the spec contract for tab-scoped
commands. Tests now assert context.url and context.title are present.

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

* test: add mouse-move command cases

* feat: implement browser mouse-move command

Adds `browser mouse-move <x,y> --session --tab` which dispatches a CDP
Input.dispatchMouseEvent (mouseMoved) at the given coordinates. Parses
and validates x,y format, tracks url/focus changes, returns context with
tab URL and title. All 8 e2e tests pass.

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

* test: add cursor-position command cases

* test: add cursor-position text status check

* feat: implement browser cursor-position command

Adds cursor-position command that returns the last known cursor position
for a tab. Position is stored in SessionRegistry when mouse-move is
executed, using the existing session_id\0tab_id composite key pattern.

Wired in all 6 registration points: mod.rs, action.rs, cli.rs (enum +
to_action + command_name + context), router.rs, output.rs.

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

* fix: track cursor position in click, drag, and hover commands

cursor-position was only updated by mouse-move. Now click, drag, and
hover also store the final pointer coordinates in SessionRegistry so
that cursor-position reflects the true position after any mouse action.

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

* test: add regression test for click -> cursor-position tracking

Verifies that cursor-position reflects coordinates from a click action,
not just mouse-move. Covers the contract gap identified in review.

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

* test: add scroll command cases

* test: add scroll changed field checks

* feat: implement browser scroll commands

Adds scroll command with three subcommand forms:
- Directional: scroll up|down|left|right <pixels>
- Edge: scroll top|bottom
- Into-view: scroll into-view <selector> [--align start|center|end|nearest]

All forms support --container for scrolling within a specific element.
Tracks scroll_changed, url_changed, focus_changed in response data.
Wired in all 6 registration points.

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

* test: add scroll xpath selector coverage

* fix: use resolved CDP nodes for scroll selectors instead of querySelector

Refactored scroll to resolve selectors via element::resolve_node +
DOM.resolveNode → objectId, then use Runtime.callFunctionOn for all
scroll operations. This correctly supports CSS, XPath, and @eN selectors
per the API contract, instead of raw querySelector which only handles CSS.

Added DOM.getDocument init call to ensure XPath DOM.requestNode works.

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

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 15:13:54 +08:00
Junliang Feng 766a849404 [packages/cli-v2] feat: add browser html text value attr (#359) 2026-03-29 13:43:52 +08:00
mcfn 027c0d1c98 [packages/cli-v2]fix: cover xpath selector path 2026-03-29 12:32:14 +08:00
Junliang Feng 59cdb85289 [packages/cli-v2]fix: validate CDP navigate response and fix CLI subcommand routing (#357) 2026-03-29 12:30:26 +08:00
mcfn 6ab915258e [packages/cli-v2]fix: return null for missing reads 2026-03-29 12:21:07 +08:00
mcfn.feng f816a18690 [packages/cli-v2]fix: validate CDP navigate response error fields
cdp_navigate now checks both CDP-level errors (response.error) and
Page.navigate-level errors (result.errorText). Previously it returned
Ok(()) for any response with matching id, silently ignoring navigation
failures like invalid schemes or net errors.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 12:18:01 +08:00
mcfn 33019d55b6 [packages/cli-v2]feat: add observation batch 1 2026-03-29 12:16:09 +08:00
Junliang Feng c742975a96 [packages/cli-v2]refactor: improve E2E test harness reliability (#356) 2026-03-29 11:53:45 +08:00
mcfn.feng 8f5ba34f73 [packages/cli-v2]fix: adapt snapshot/interaction/page_info e2e tests to new SessionGuard API
Migrate from old SessionGuard::new() (kill-daemon) to new
SessionGuard::new(&sid) (per-session cleanup). Error-path tests
that don't create sessions no longer need a guard.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 11:45:39 +08:00
mcfn.feng 21dc96056e [packages/cli-v2]fix: address code review findings in E2E test harness
- SoloEnv::Drop: wait for daemon exit + clean up daemon.sock/ready/pid
  files (SIGKILL prevents daemon's own cleanup)
- cloud_crash_recovery_endpoint_gone: add real assertions to all branches
  (was a no-op test that could never fail)
- Restore cloud_crash_recovery_reconnect test (was deleted in refactor)
- Add SessionGuard to lifecycle_close_s1t2 and lifecycle_double_close
  tests (prevent session leak on panic)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 11:45:01 +08:00
mcfn.feng c18c65c280 [packages/cli-v2]refactor: improve E2E test harness for reliability and maintainability
- Extract common helpers to harness.rs (assert_meta, assert_error_envelope,
  assert_tab_id, start_session, close_session, new_tab_json, etc.)
- Add local HTTP server to eliminate external network dependency
- Introduce SoloEnv for tests needing isolated ACTIONBOOK_HOME
- Replace fixed sleep(500ms) with per-test session isolation
- Fix TempDir leak in cloud_mode (ChromeGuard now owns TempDir)
- Add PID to unique_session IDs to prevent cross-run collisions
- HTTP server: thread-per-connection + Connection: close header
- Restore all cloud_mode tests (groups 5b-15) that were missing

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 11:45:01 +08:00
Junliang Feng 936bf310a1 test: browser inspect-point E2E + UT baseline (TDD) (#352) 2026-03-29 11:36:42 +08:00
mcfn 0c52ad71c1 fix: use AX tree traversal for collect_parents, fix negative coords
- Switch collect_parents() from DOM.getAncestors/DOM.describeNode
  (unreliable across Chrome versions) to Accessibility.getPartialAXTree
  with fetchRelatives:true — single CDP call, proven to work, no DOM
  tree tracking dependency
- Add allow_hyphen_values=true to coordinates positional so negative
  coordinates like -9999,-9999 parse correctly instead of being treated
  as flags
- All 10 inspect_point E2E tests now pass locally

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-29 11:31:31 +08:00
mcfn b9370692f2 [packages/cli-v2]fix: add DOM.getDocument + use nodeId for parent traversal
DOM.describeNode only returns parentId when the DOM tree is tracked.
Call DOM.getDocument upfront and use nodeId (from getNodeForLocation)
instead of backendNodeId for reliable parent chain traversal.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 11:29:41 +08:00
mcfn 37b999052c [packages/cli-v2]fix: iterative parent traversal + fmt fix
- Replace DOM.getAncestors with iterative DOM.describeNode for broader
  Chrome version support in collect_parents()
- Add allow_hyphen_values for negative coordinates
- Fix rustfmt in click.rs (from PR #351 merge)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 11:25:15 +08:00
mcfn 90abb625b2 [packages/cli-v2]style: fix rustfmt formatting in inspect_point.rs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 11:19:57 +08:00
mcfn a7b4e71d8b tests(e2e): fix inspect-point B1/B2 contract gaps
B1 (context.url + text header URL not pinned):
Already present in current head — context.url is_string() asserted in
JSON happy-path; header contains "about:blank" asserted in text happy-path.

B2 (parent ordering not verifiable):
- Add aria-label="Inner Container" and aria-label="Outer Container" to
  fixture divs so parents are distinguishable in the AX tree
- Replace weak "refs must be distinct" assertion with exact name checks:
  parents[0].name == "Inner Container" (nearest parent)
  parents[1].name == "Outer Container" (grandparent)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-29 11:19:57 +08:00
mcfn 5e457deed8 feat: implement browser inspect-point command (§10.11)
CDP flow:
1. DOM.getNodeForLocation(x, y) → backendNodeId of hit element
2. Accessibility.getPartialAXTree(backendNodeId) → role + name
3. RefCache.get_or_assign(backendNodeId) → stable selector ref (e1, e2...)
4. When no element at coords → data.element = null
5. --parent-depth N: DOM.describeNode → DOM.getAncestors → collect first N
   element ancestors, each with role/name/selector ref

data contract:
- data.point: {x, y} (echoes requested coordinates)
- data.element: {role, name, selector} or null
- data.parents: [{role, name, selector}] nearest-first, up to parent_depth
- context.url populated via __ctx_url sideband

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-29 11:19:57 +08:00
mcfn 201d8e7703 [packages/cli-v2]fix: stub execute() resolves session/tab before NOT_IMPLEMENTED
Session/tab error-path tests need get_cdp_and_target to run before
the NOT_IMPLEMENTED return, otherwise they get NOT_IMPLEMENTED instead
of SESSION_NOT_FOUND / TAB_NOT_FOUND.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 11:19:57 +08:00
mcfn a2291720e4 [packages/cli-v2]test: strengthen inspect-point E2E with deterministic fixtures
Address Robin-Cx review (#116):
- Replace actionbook.dev with about:blank + injected DOM fixture
- Pin exact role/name/selector assertions on known button element
- Strengthen text happy-path: assert role "name", selector:, point: lines
- Assert exact parent count (2) and distinct refs for --parent-depth
- Pin INVALID_ARGUMENT error code for invalid coordinates
- Validate coordinates in stub execute() so error test passes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 11:19:57 +08:00
mcfn a06b293b66 [packages/cli-v2]test: browser inspect-point E2E + UT baseline (TDD)
§10.11 inspect-point command: TDD tests + NOT_IMPLEMENTED stub.

- 10 UTs for parse_coordinates (valid, decimals, spaces, negative, zero, errors)
- 10 E2E tests: happy JSON/text, parent-depth, no-element, session/tab not found, missing args, invalid coords
- Stub execute() returns NOT_IMPLEMENTED
- CLI/Action/Router/Output wiring complete
- Text format: role "name" / selector: ref / point: x,y

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 11:19:57 +08:00
Junliang Feng f3575a4d38 [packages/cli-v2] Setup PR2: interactive API key + browser config (#354) 2026-03-29 11:18:26 +08:00
Adcent 24c05c128c [codex] Implement browser interaction commands (#351)
* Add browser click interaction tests

* Expand browser click interaction coverage

* [packages/cli-v2]feat: implement browser click command with shared element resolution

Add full browser click implementation with CDP mouse event dispatch,
selector/coordinate parsing, --button/--count/--new-tab flags, navigation
detection, and XPath support. Extract element resolution into a shared
browser::element utility for reuse by future interaction commands.

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

* [packages/cli-v2]fix: use shared resolver for --new-tab href check and add click to help

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

* Add browser type interaction tests

* [packages/cli-v2]feat: implement browser type command

Keystroke-by-keystroke text input via CDP Input.dispatchKeyEvent.
Resolves element through shared element utility, focuses and positions
cursor at end before typing.

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

* [packages/cli-v2]fix: populate context URL/title and use char count in browser type

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

* Add browser fill interaction tests

* [packages/cli-v2]feat: implement browser fill command

Direct value setting via native input setter with synthetic input event
dispatch. No keystroke simulation — replaces existing value entirely.

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

* [packages/cli-v2]fix: pick native value setter based on element type in browser fill

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

* Add textarea fill regression test

* Add browser select interaction tests

* [packages/cli-v2]feat: implement browser select command

Select dropdown options by value or visible text (--by-text flag).
Dispatches input and change events after selection.

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

* [packages/cli-v2]fix: use resolved node for select instead of re-querying with querySelector

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

* Format interaction files for lint

* [packages/cli-v2]fix: scroll into view before click and replace fixed navigation delay

Scroll elements into the viewport via DOM.scrollIntoViewIfNeeded before
computing bounding-box coordinates, so clicks on off-screen elements
land correctly. Replace the hardcoded 500ms post-click sleep with a
polling loop that detects URL changes at 50ms intervals (2s timeout),
avoiding unnecessary delays for non-navigating clicks and catching
slow SPA transitions.

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-03-29 08:36:54 +08:00
mcfn 91cb301e99 [packages/cli-v2]fix: restore setup rerun defaults 2026-03-29 03:17:28 +08:00
mcfn 81398f2328 [packages/cli-v2]fix: clarify setup cloud migration 2026-03-29 03:12:51 +08:00
mcfn 01b59afe93 [packages/cli-v2]feat: add setup pr2 interactive flow 2026-03-29 03:07:32 +08:00
Junliang Feng 847afd8a16 [packages/cli-v2] feat: --cursor snapshot detection (#353) 2026-03-29 02:43:15 +08:00
mcfn.feng 816ae6fec5 [packages/cli-v2]fix: remove unused variable to pass clippy --all-targets
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 02:41:53 +08:00
mcfn.feng dbef6c9e40 [packages/cli-v2]fix: use run-unique nonce for data-__ab-ci to avoid page collision
Generate a nonce per detect_cursor_elements() call. Tag value is "nonce:idx",
querySelectorAll uses [data-__ab-ci^="nonce:"], cleanup only removes our
markers. Prevents destructive mutation of page-owned data-__ab-ci attributes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 02:40:11 +08:00
mcfn.feng acccd9cb60 [root]ci: E2E tests only on merge, PR runs lint + UT only
Add `if: github.event_name == 'push'` to e2e-tests job so E2E only runs
on merge to main/release branches. PRs only run lint and unit tests,
reducing CI time and avoiding flaky external-site dependencies in PR checks.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 02:37:53 +08:00
mcfn.feng 82bd3b50fb [packages/cli-v2]fix: --interactive --cursor must not drop cursor nodes
Move cursor_elements check before interactive filter in DFS — cursor nodes
survive --interactive filtering even if their ARIA role is non-interactive.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 00:40:03 +08:00
mcfn.feng cbbd57fc5a [packages/cli-v2]feat: implement --cursor detection for snapshot
Detect cursor-interactive elements (cursor:pointer, onclick, tabindex,
contenteditable) via JS eval + CDP DOM resolution. Non-ARIA interactive
elements get refs and show "clickable [cursor:pointer, onclick]" in output.

Implementation:
- detect_cursor_elements() with guaranteed cleanup on error paths
- DFS integration: cursor-mapped nodes get ref + interactive=true + CursorInfo
- render_content appends cursor kind + hints after ref bracket
- Unhide --cursor flag from CLI
- JS skip-list includes iframe to avoid double-counting with AX Iframe role

Review fixes:
- Cursor detection errors surface as meta.warnings (not silently swallowed)
- data-__ab-ci cleanup runs even on early-exit errors (restructured cleanup)
- compact ordering: compact_tree_nodes before remove_empty_leaves (depth gap fix)
- __warnings extracted to meta.warnings in output.rs

67 UT + E2E tests. Tested on x.com: detects 2 onclick elements.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 00:37:27 +08:00
Junliang Feng e4a768cf6c test: browser title/url/viewport E2E + UT baseline (TDD) (#349) 2026-03-29 00:12:48 +08:00
mcfn 1cb2c44e55 fix(e2e): add explicit goto after start_session in page_info tests
CI runners occasionally land on chrome-error://chromewebdata/ when
--open-url navigation races or fails on network hiccups. Adding an
explicit browser goto after browser start ensures the tab has a real
URL before any assertion runs.

Fixes url_text_happy_path CI failure:
  data.value must be a URL: got chrome-error://chromewebdata/

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-29 00:04:14 +08:00
mcfn 548007e52b [packages/cli-v2]fix: start_session explicit goto to ensure page load (#t111)
--open-url starts navigation but doesn't block until load completes.
CI saw chrome-error://chromewebdata/ in url_text_happy_path because the
tab was still loading when browser url was called. Explicit goto after
start guarantees the page is fully loaded before tests query the URL.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-29 00:02:31 +08:00
Junliang Feng bc893dbff5 [packages/cli-v2] fix: snapshot B2+W2+W3 — truncation, token cost, stale comment (#350) 2026-03-28 23:19:35 +08:00
mcfn 07e267e33b [packages/cli-v2]feat: implement browser title/url/viewport commands (#t111)
- title: Runtime.evaluate("document.title") → data.value; url in context
- url: Runtime.evaluate("document.URL") → data.value; url in context
- viewport: Runtime.evaluate innerWidth/innerHeight → data.width/height; url in context
- All context() fns populate url field from result data per §10.4/§10.5/§10.6
- fmt: reformat assert! in page_info.rs to satisfy cargo fmt

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-28 23:14:17 +08:00
mcfn.feng 57aa39f48f [packages/cli-v2]fix: clear RefCache on close-tab to prevent stale ref leak
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 23:12:25 +08:00
mcfn 8beb389640 feat: implement browser title/url/viewport commands (§10.4/§10.5/§10.6)
Implement the three observation commands using CDP Runtime.evaluate:
- browser.title: document.title → data.value (string)
- browser.url: document.URL → data.value (string)
- browser.viewport: window.innerWidth/innerHeight → data.width + data.height (numbers)

All three use __ctx_url sideband so context.url is populated per §2.5.
context() updated from stub (url: None) to extract __ctx_url from data.

Also resolve merge conflicts with release/1.0.0:
- observation/mod.rs: include both snapshot_transform and title/url/viewport
- tests/e2e/main.rs: include both snapshot and page_info test modules
- output.rs: include both browser.snapshot and browser.title/url/viewport cases

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-28 23:11:20 +08:00
mcfn.feng 3ea2e2ee91 [packages/cli-v2]fix: B2+W2+W3 — wire truncation, fix token cost, update stale comment
B2: Wire truncate_to_tokens into execute() with 100K token budget.
    meta.truncated now reflects actual truncation state via __truncated
    internal field, stripped by output.rs alongside __ctx_*.
W2: Add value.len() + JSON overhead to per-node token cost estimation.
W3: Remove stale "apply_selector deferred to P2" comment (already implemented).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 23:04:53 +08:00