feat(instrument): browser_use adapter full implementation (replaces placeholder from #116)#126
Merged
m-peko merged 1 commit intoMay 12, 2026
Conversation
…laceholder from #116) Replaces the M7 placeholder shipped in PR #116 (truncation policy) with the full BrowserUseAdapter — every lifecycle hook wired, every event emitted, and every cross-cutting CLAUDE.md contract enforced from day one. What changed ------------ Full lifecycle adapter (src/layerlens/instrument/adapters/frameworks/ browser_use/lifecycle.py): * connect / disconnect / health_check / get_adapter_info / serialize_for_replay (all five abstract BaseAdapter methods). * on_session_start, on_session_end, on_navigation, on_action, on_screenshot, on_dom_extraction, on_llm_call (every spec'd hook). * Capability declaration: TRACE_TOOLS + TRACE_MODELS + TRACE_STATE + STREAMING + REPLAY (no longer the placeholder's TRACE_TOOLS-only set). * Canonical events: browser.session.start, browser.navigate, browser.action, browser.screenshot, browser.dom.extract, tool.call, model.invoke, agent.input/output/state.change, cost.record, environment.config — plus agent.error / tool.error / model.error per the PR #115 error-aware emission contract. * Per-callback resilience wrapper per PR #117 — observability errors NEVER crash the customer's agent, surfaced via resilience_snapshot(). * Multi-tenant org_id propagation per PR #118 — bound at construction (kwarg or resolved from stratix.org_id), stamped defensively on every emit, caller-supplied values overwritten to prevent cross-tenant leaks. * Truncation policy from day one (DEFAULT_POLICY) — screenshot bytes DROPPED to deterministic SHA-256 references, DOM/HTML capped at 16 KiB, prompts/completions/tool I/O at 4/2 KiB. * Browser-event layer mapping (_BROWSER_EVENT_LAYERS) so unknown browser.* event types respect CaptureConfig gating without falling through the unknown-event-drops-by-default path. * requires_pydantic = PydanticCompat.V2_ONLY (browser_use is a v2 lib). Public surface (src/layerlens/instrument/adapters/frameworks/ browser_use/__init__.py): * ADAPTER_CLASS = BrowserUseAdapter (registry). * instrument_agent(agent, stratix=, capture_config=, org_id=) one-liner returning the connected, wrapping adapter. * STRATIXBrowserUseAdapter top-level binding (legacy alias) — fires DeprecationWarning on construction. Exposed as a static binding so the manifest consistency lint's AST walk finds it. Pyproject: * Adds 'browser-use' optional extra: browser-use>=0.1.0,<2 with the python_version >= '3.11' marker (browser_use's own constraint). Tests (tests/instrument/adapters/frameworks/test_browser_use_adapter.py): * Replaces the 7-test scaffold from #116 with 40 tests covering: wiring + alias + lifecycle round-trip + truncation (screenshot drop, hash determinism, HTML cap, short-payload no-audit) + multi-tenancy (kwarg, client attribute, defensive overwrite) + resilience (poison stratix, exploding agent attribute access) + error-aware emission (agent.error / tool.error / model.error) + per-hook coverage + sync + async wrapping + replay round-trip + 10-case provider detection table. Sample (samples/instrument/browser_use/{main.py,__init__.py,README.md}): * Runs OFFLINE — no browser-use install, no Playwright, no API key, no network. Three-step duck-typed agent + happy/--fail paths exercise the full event surface and demonstrate screenshot drop + org_id stamping + agent.error emission before re-raise. Doc (docs/adapters/frameworks-browser_use.md): * Install + quickstart + capabilities matrix + 14-event reference table + truncation policy table + multi-tenancy + resilience + error-aware emission + capture config + browser_use specifics + BYOK + replay sections. Manifest (scripts/emit_adapter_manifest.py): * Promotes browser_use from _LIFECYCLE_PREVIEW to _MATURE — every required artifact (test file with >= 12 funcs, sample, doc, STRATIX→LayerLens deprecation alias) ships in this PR. Verification ------------ * uv run pytest tests/instrument/adapters/frameworks/test_browser_use_adapter.py → 40 passed * mypy --strict src/layerlens/instrument/adapters/frameworks/browser_use → Success: no issues found in 2 source files * ruff check on src + test + script → All checks passed! * Sample runs cleanly offline (happy + --fail) * pip install -e .[browser-use] resolves cleanly (browser-use only pulled on Python 3.11+ per the env marker) * tests/instrument/adapters/test_manifest_consistency.py:: test_mature_adapters_have_required_artifacts[browser_use] passes * Full instrument suite (excl. pre-existing crewai/protocols references not on this branch): 312 passed, 1 skipped, 12 xfailed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Replaces the M7 placeholder shipped in PR #116 (truncation policy) with the full
BrowserUseAdapter— every lifecycle hook wired, every event emitted, and every cross-cutting CLAUDE.md contract enforced from day one. Stacks onfeat/instrument-truncation-policy(PR #116).What changed
Full lifecycle adapter (
src/layerlens/instrument/adapters/frameworks/browser_use/lifecycle.py)connect/disconnect/health_check/get_adapter_info/serialize_for_replay(all five abstractBaseAdaptermethods).on_session_start,on_session_end,on_navigation,on_action,on_screenshot,on_dom_extraction,on_llm_call(every spec'd hook).TRACE_TOOLS+TRACE_MODELS+TRACE_STATE+STREAMING+REPLAY(no longer the placeholder'sTRACE_TOOLS-only set).browser.session.start,browser.navigate,browser.action,browser.screenshot,browser.dom.extract,tool.call,model.invoke,agent.input/output/state.change,cost.record,environment.config— plusagent.error/tool.error/model.errorper the PR feat(instrument): Error-aware event emission on framework exceptions across 10 lighter adapters (cross-poll #2) #115 error-aware emission contract.resilience_snapshot().org_idpropagation per PR fix(instrument): Propagate org_id through all event emissions (multi-tenancy CLAUDE.md fix) #118 — bound at construction, stamped defensively on every emit, caller-supplied values overwritten to prevent cross-tenant leaks.DEFAULT_POLICY) — screenshot bytes DROPPED to deterministic SHA-256 references, DOM/HTML capped at 16 KiB.requires_pydantic = PydanticCompat.V2_ONLY(browser_use is a v2 library).Public surface (
__init__.py)ADAPTER_CLASS = BrowserUseAdapterinstrument_agent(agent, stratix=, capture_config=, org_id=)one-linerSTRATIXBrowserUseAdapterlegacy alias — firesDeprecationWarningon constructionPyproject
browser-useoptional extra:browser-use>=0.1.0,<2; python_version >= '3.11'Tests (40 tests, replaces 7-test scaffold from #116)
Coverage: wiring + alias + lifecycle round-trip + truncation (screenshot drop, hash determinism, HTML cap, short-payload no-audit) + multi-tenancy (kwarg, client attribute, defensive overwrite) + resilience (poison stratix, exploding agent attribute access) + error-aware emission (
agent.error/tool.error/model.error) + per-hook coverage + sync + async wrapping + replay round-trip + 10-case provider detection table.Sample (
samples/instrument/browser_use/)Runs OFFLINE — no
browser-useinstall, no Playwright, no API key, no network. Three-step duck-typed agent + happy/--failpaths exercise the full event surface.Doc (
docs/adapters/frameworks-browser_use.md)Install + quickstart + capability matrix + 14-event reference + truncation table + multi-tenancy + resilience + error-aware emission + capture config + browser_use specifics + BYOK + replay.
Manifest
Promoted
browser_usefrom_LIFECYCLE_PREVIEWto_MATURE— every required artifact (test file with >= 12 funcs, sample, doc, STRATIX→LayerLens deprecation alias) ships in this PR.Test plan
uv run pytest tests/instrument/adapters/frameworks/test_browser_use_adapter.py -x→ 40 passedmypy --strict src/layerlens/instrument/adapters/frameworks/browser_use→ Success: no issues found in 2 source filesruff checkon src + test + script → All checks passed!--fail)pip install -e .[browser-use]resolves cleanlytest_manifest_consistency.py::test_mature_adapters_have_required_artifacts[browser_use]passes