| Age | Commit message (Collapse) | Author |
|
Browser.setDownloadBehavior was sent without a browserContextId, so the override applied to the
user's default context and outlived the session. browser_download now takes restore:true, tracks
the override this process set, and a clean session shutdown restores Chrome's default with a
bounded call that is skipped when the browser is already gone.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
|
Expose explicit set and clear tools so environment-routed pages can be opened without leaking header values or carrying headers across unrelated browsing.
Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com
Co-authored-by: zouzhigang <zouzhigang@bytedance.com>
|
|
src/ goes from 84 files to 75 at the same line count — every merge below
had exactly one consumer.
cdp/event-queue.ts and cdp/pending-requests.ts become daemon/queue.ts.
I split these in the daemon-internals commit on the grounds that they
held two unrelated concerns, but the transport commit had already deleted
the second transport, so both halves had one consumer and the split
bought nothing. They also sat in cdp/ while only daemon/ used them.
cdp/transport.ts held only the CdpTransport interface after the second
transport went; five of its six consumers import it type-only, so it
moves to cdp/types.ts. cdp/evaluate.ts moves into cdp/session.ts rather
than into its lone consumer isolated-tab.ts — it reaches session.call
directly, so under src/domains/ it would trip the raw-cdp-call rule.
util/keycodes.ts and util/time.ts fold into their only callers
(keyboard.ts, page.ts); util/bytes.ts into util/truncate.ts, which
already owns output-size formatting; readpage/capture.ts and
search/extract.ts into the tools beside them; profile/picker.ts into
profile/command.ts.
Kept deliberately: mutex.ts and domains/target.ts each have their own
test suite, and folding target.ts into click.ts would make a tool file
export a helper. sharp-shim.ts is an isolation boundary carrying two
allowlisted casts. result.ts, guards.ts, js-template.ts and paths.ts are
small but have 44, 12, 8 and 3 consumers.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
The harness ships browser tools; orchestrating a multi-agent research
workflow on top of them is the agent's job, not this extension's. Drops
the skill, the /deep-research command, and the web-search-researcher
subagent config.
browser_web_search and browser_read_page are untouched — the two tests
that covered their pure parsers move to test/domains/, where the test
glob still picks them up.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
runOnElement checked only whether Runtime.callFunctionOn reached Chrome, not
whether the function it ran threw. A page-side exception left result.value
undefined, the result guard rejected it, and browser_fill, browser_focus and
browser_select_option all reported "No element matched: <ref>" for an element
that was there — sending the agent to re-snapshot a ref that was fine and
discarding the real error. The throw is now surfaced as cdp_error carrying the
exception text, which is distinguishable from both the no-match and stale-ref
paths; those still fire for a genuinely missing or stale element. The selector
path already reported throws correctly via evaluateJs.
Report: docs/superpowers/reports/2026-07-26-bug-audit.md#f2
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
browser_fill and browser_fill_form carried separate in-page implementations that
disagreed on the same element. The worst case was silent: browser_fill on a
checkbox fired the HTMLInputElement value setter, which writes the submit value
and leaves `checked` alone, then reported status ok — a no-op the agent had no
reason to doubt. Both tools now share one engine, with browser_fill's documented
<select> rejection kept as an explicit pre-check and per-tool focus behaviour kept
as a parameter.
Deliberate, user-approved behaviour changes:
- browser_fill on a DISABLED input now returns an error instead of success. The
old success was the bug; browser_fill_form already refused it.
- browser_fill on a checkbox/radio now toggles `checked` instead of the value.
- browser_fill_form on a contenteditable now uses execCommand("insertText"),
so it drives ProseMirror/Slack-style editors as browser_fill already did.
browser_fill keeps appending interactiveDiff and republishing refs; fill_form
still does not.
Report: docs/superpowers/reports/2026-07-26-bug-audit.md#f5
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
interactiveDiff re-assigned refs by tree position after every fill, click and
select, so any element appearing or disappearing shifted the numbering and a ref
the agent was still holding silently resolved to a different element — while the
tools kept promising that refs survive re-renders. Refs are now carried over by
backendNodeId and only genuinely new elements draw a new number.
Report: docs/superpowers/reports/2026-07-26-bug-audit.md#f6
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
Wires a real CdpSession to a canned-response transport so domain tools can be
driven without Chrome. Unconfigured client methods return an error rather than a
success, so a test cannot pass by accident. Report:
docs/superpowers/reports/2026-07-26-bug-audit.md#f30
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
domains/forms.ts was a stale fork of form.ts imported only by a manual
test. It held two working tools the registry never registered: fill_form
and set_checked. Ported both onto the current pattern and deleted the
fork; form.ts versions of the shared tools win.
The fork's tools took ref as Type.Integer (a raw CDP backendNodeId).
browser_snapshot has since moved to string refs ('e7') resolved through
the session ref map, so as written the tools were not callable at all.
Ported them onto resolveRefToObjectId and Type.String refs; the only
user-facing strings that changed are the four that documented the old
[ref=N] syntax. All page-side JS is carried byte-for-byte.
form.ts exceeded 250 lines, so fillForm moved to form-batch.ts per the
single-field/batch split. form.ts is still 425 lines — the pre-existing
three tools account for that, so the split does not reach the target.
test/manual/forms-test.ts is repointed and adapted to publish an 'eN'
ref map, but NOT executed — it needs a live Chrome. Type-checked only.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
The ref-vs-x/y branch turned out to exist in one tool, not four; it is now
one helper with tests covering the half-specified-coordinate and stale-ref
cases. cdpCall folds the repeated cdp_error mapping at 24 active-session
call sites; target-scoped callOnTarget/callBrowser sites are left alone.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
serialized: true was applied in registry.ts, away from the tools it
describes. Now a required concurrency field on each definition, with a
test pinning the serialized set so the classes cannot drift.
The lock check defaults to taking the mutex for any class that is not
explicitly "parallel", so a definition that bypasses defineBrowserTool at
runtime fails safe rather than racing on shared CDP state.
The test script gains --conditions=import: pi-coding-agent publishes no
"require" condition, so importing any tool definition from a CJS-loaded
test could not resolve it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
Adopting isFocusProbe inverted the safety default: the guard was ANDed into
the condition gating the check, so a probe result the guard rejected skipped
the check and fell through to Input.insertText — text typed into nothing,
silently, which is the exact failure the block exists to prevent. The guard
now feeds a value that defaults to { ok: false }, so a rejected shape
produces the error instead of bypassing it.
The other four guard adoptions (isFillResult, isFocusResult, isSelectResult,
isPageResult) were already fail-closed: each feeds a value whose rejection
lands on a pre-existing error branch.
Also assert x/y in the box centre test — the fields snapshot's off-viewport
filter reads — and wrap the zero-size message to the surrounding width.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
ref-resolve.ts and snapshot.ts had the same box-model unwrap, both using
data.model! to work around an untyped response. Extracted to domains/box.ts;
the typed schema makes the assertions unnecessary. Both derived the centre
identically (quad corner + half the model width/height), so centreOf keeps
that derivation; the shared zero-size rejection moved into boxOf, and
snapshot keeps its own off-viewport (x/y < 0) filter.
evalInIsolatedTab now goes through evaluateJson with the tab's own sessionId
and a caller-supplied guard; both callers evaluate expressions ending in
JSON.stringify, so they pass isJsonText rather than a check that checks
nothing. Runtime.evaluate/callFunctionOn result casts in form.ts, forms.ts
and keyboard.ts are replaced by named guards over the in-page result shapes.
Runtime.callFunctionOn's params schema gained arguments/returnByValue/
awaitPromise/userGesture: four domain call sites legitimately pass them and
typebox's additionalProperties:true does not widen the static type, so the
params type was rejecting valid CDP fields. Params schemas are type-only
(only results are compiled), so this is a compile-time widening with no
runtime effect.
tsc is green again for both tsconfigs.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|