Add a popup launcher + action-recording panel that builds a copyable
`bsk record start` prompt, add `--browser` targeting, and default `--url`
to https://example.com/ when omitted. Drop the popup browser-alias field.
Capture user actions in the Agent Window and export a record-only
trace (pages[] + navigate/click/fill/select/press steps with target
descriptors). Adds the record overlay UI aligned with the control
overlay, and wires record start/stop/await through CLI, daemon,
protocol, and extension.
Add `bsk network` as a sibling of the `console` command from #7,
reading the buffered network responses / failures for a tab. Fills the
remaining half of the request in #2 (console landed in #7; network did
not).
Mirrors the console command's conventions exactly:
bsk network --session <id> [--tab-id N] [--since C]
[--limit N] [--max-text-chars N]
The extension enables `Network` on attach (best-effort) and buffers
`responseReceived` / `loadingFailed` events per tab with a monotonic
sequence, correlating them to `requestWillBeSent` for method/URL. Reads
are cursor-paginated (`since` -> `next_since`) and bounded (`limit`,
`max_text_chars`) for agent-context safety, same as console. Entries
carry the real HTTP status code (response) or the CDP failure reason
(failure) — things `performance.getEntriesByType('resource')` can't
give.
Classified read-only (pass-through under the pending-interrupt gate);
defaults to the Agent Window's active tab.
Wires bsk-protocol (Method + params/result/entry structs + schema),
bsk-cli (network subcommand + daemon dispatch allow-list) and the
extension (handler + dispatcher route), with unit / parse / IPC tests
paralleling the console command.
Refs #2.
Send borrow-cancel when the confirmation timeout denies, and add a
timer fallback so auto-deny does not depend only on CSS transitionend.
Co-authored-by: Cursor <cursoragent@cursor.com>
requestBorrowConfirmation returned `true` (approve the borrow) when
`chrome.tabs.get(tabId)` threw. That fail-open was not one of the
documented fail-open cases in the function's own doc comment (no
candidate window; abort signal; timeout), and the tab was already
fetched successfully moments earlier by the borrow pipeline
(validateBorrowTarget), so a failure here is a transient SW/page hiccup
— not a missing tab. Silently approving a borrow with no confirmation
UI shown defeats the entire human-in-the-loop gate for seizing a user's
logged-in tab.
On a tabs.get failure, fall back to a generic title (the numeric tab id)
and still run the overlay + OS-notification confirmation flow so the
user gets a real chance to approve or deny.
Adds two regression tests (both fail on the unpatched code). Full
extension suite green (361 tests).
Co-Authored-By: Claude <noreply@anthropic.com>
The daemon dispatched inbound `session.window_closed` and
`session.user_interrupt` events using only the payload — the sending
browser's identity was never checked against the session's owner.
Any connected extension could therefore emit window_closed with
another browser's session_id to tear down its session (forgetting it,
dropping its tool queue + interrupt marker), or emit user_interrupt
to cancel every inflight tool of another browser's session and arm
its interrupt marker. This is a cross-tenant integrity/DoS hole that
is exploitable even between two legitimate extensions, independent of
the (separately tracked) WS Origin allow-list gap.
Thread the sender's BrowserId (already in scope as `client.id` in
handle_inbound_text) into both handlers and ignore the event when the
named session is live and owned by a different browser. A session
that is already gone is left to the existing no-op forget path.
Adds four ownership tests (owner honoured / non-owner ignored for each
event); updated two existing tests for the new signature. Full bsk
suite green (165 lib + integration), no new clippy warnings.
Co-Authored-By: Claude <noreply@anthropic.com>
When a borrowed tab's original window is gone, tab_return's fallback
picker called getLastFocused({windowTypes:["normal"]}) and only
excluded the *current* session's Agent Window. Agent Windows are
created with type:"normal", so the picker could move a returned user
tab into *another* session's Agent Window. That session could then
write to the tab (it passes enforceAgentWindow), and the tab would be
destroyed when that session stops and closes its window — a
cross-session sandbox break plus silent user-data loss.
Thread an isAgentWindowId predicate (derived from SessionManager in
the production handlers, mirroring the existing filter in
borrow-confirmation's listConfirmationCandidates) through
returnBorrowedTab -> chooseFallbackWindow so every live Agent Window
is skipped as a fallback target.
Adds two regression tests (both fail on the unpatched code).
Co-Authored-By: Claude <noreply@anthropic.com>
- Add Add-ToBashProfile helper to append install dir to ~/.bashrc
- Converts Windows paths to Unix-style for Git Bash compatibility
- Integrate into Main install flow alongside Add-ToUserPath
- Update completion message to mention Git Bash
- Add install.ps1 mirrored from install.sh patterns
- Same env var overrides (BSK_REPO, BSK_VERSION, BSK_INSTALL_DIR)
- Default install dir ~/.local/bin
- Fetches latest version from version.json via Invoke-RestMethod
- Downloads, extracts zip, installs bsk.exe
- Adds to user PATH persistently with idempotent check
- Supports x64 and ARM64 architecture detection
- Update README.md Windows section with irm | iex one-liner
- Update AGENT_INSTALL.md with Windows PowerShell instructions