Commit Graph
250 Commits
Author SHA1 Message Date
Ljy-0827 4ba6fb45e1 feat(extension): recording hover 2026-08-06 17:33:46 +08:00
Zhang GH 93df62a356 Merge pull request #42 from shnpd/feat/popup-function-icon
feat(extension): use function launcher icon
2026-08-06 16:47:52 +08:00
Zhang GH 20002e1ff2 Merge pull request #63 from Tencent/feat/record-overlay-timer
feat(extension): compact recording overlay with live timer
2026-08-06 16:47:11 +08:00
“haonan” 674c53339f fix(extension): keep record overlay timer across navigations 2026-08-06 16:28:21 +08:00
Ljy-0827 9d4ac90592 fix(extension): ci and bug fix 2026-08-06 16:16:41 +08:00
Ljy-0827 cde6f22ecf fix(extension): ci and bug fix 2026-08-06 16:14:18 +08:00
Ljy-0827 d24bb6aa93 feat(extension): dispatcher fix 2026-08-06 15:48:11 +08:00
Ljy-0827 dbc4845c0d feat(extension): vom hover description bug fix 2026-08-06 15:30:11 +08:00
BB-fat d0bee1a09b feat(install-skill): add Kimi Code harness support (#65)
* feat(install-skill): add Kimi Code harness support

Add kimi-code to the install-skill harness list: installs the bundled SKILL.md into ~/.kimi/skills (Kimi Code CLI's brand-group user skills directory, highest priority per https://github.com/MoonshotAI/kimi-cli/blob/main/docs/en/customization/skills.md). Detection signals: ~/.kimi directory and kimi/kimi-cli on PATH. Aliases: kimi, kimi-code, kimi-cli, kimicode, kimi_cli.

* fix(install-skill): point kimi-code harness at ~/.kimi-code and honor KIMI_CODE_HOME

Kimi Code CLI's canonical repo is MoonshotAI/kimi-code: user-level skills live in $KIMI_CODE_HOME/skills (default ~/.kimi-code/skills), not kimi-cli's ~/.kimi/skills. Detection checks the kimi-code home dir (env-aware label) and the kimi binary on PATH. Serialize env-mutating kimi tests with a shared mutex to avoid a parallel-test race on KIMI_CODE_HOME.
2026-08-06 13:25:18 +08:00
Ljy-0827 91225e5fdb feat(extension): add bsk hover and adjust vom to support 2026-08-06 12:19:45 +08:00
“haonan” 66684c4ce3 feat(extension): compact recording overlay with live timer
Show the recording message for 10s, then switch to a fixed-width MM:SS
timer with the icon-only finish button.
2026-08-05 20:26:43 +08:00
BB-fat 0f264c5df1 feat(emulate): add mobile device emulation via CDP Emulation domain (#60)
* feat(emulate): add mobile device emulation via CDP Emulation domain

Add `bsk emulate` so agents can debug mobile page behaviour by
emulating a device environment on a session tab:

- Viewport metrics (Emulation.setDeviceMetricsOverride), User-Agent
  (Emulation.setUserAgentOverride, optional accept-language and UA
  client-hints metadata), and touch (Emulation.setTouchEmulationEnabled
  with maxTouchPoints).
- Seven CLI-side device presets (iphone-14, iphone-14-pro-max,
  iphone-se, pixel-7, galaxy-s23, ipad-mini, galaxy-tab-s8) via
  --device; manual flags (--width/--height/--dpr/--mobile/--ua/
  --accept-language/--touch/--max-touch-points) work standalone or
  override individual preset fields.
- `bsk emulate --off` clears every override (clearDeviceMetricsOverride
  + touch disabled + empty UA override) and restores the real
  environment.
- Overrides are per-tab (CDP per-target) and not inherited by new tabs;
  the result JSON carries a note reminding agents to re-apply.

Wire: new tool.emulate method end-to-end (bsk-protocol types + JSON
schemas + Method::ToolEmulate classified BrowserMutation, daemon
forwarding, CLI subcommand, extension tool handler + ChromiumCdp
Emulation wrappers, dispatcher registration), docs in both SKILL.md
copies, and unit tests on every layer.

* refine(emulate): merge per-tab state and align preset override semantics

- extension: remember the applied emulation state per tab and merge each new request onto it field by field before applying, so a later --width/--height no longer resets an earlier preset's dpr/mobile; --off clears the stored state along with the CDP overrides
- extension: cdp_failed errors now note that already-applied overrides were not rolled back and can be reset with --off
- cli: validate width/height pairing and metric requirements on the merged preset+flags result, so --device iphone-14 --width 500 keeps the preset height
- cli: add --no-mobile/--no-touch (conflicting with --mobile/--touch) to turn preset mobile/touch fields back off
- docs: describe the merge behaviour, --no-mobile/--no-touch and --off state clearing in both SKILL.md copies
2026-08-05 18:10:39 +08:00
BB-fat 49378d70de feat: support Agent Window sizing (session start --width/--height, window resize) (#52)
- `bsk session start --width <px> --height <px>` opens the Agent Window
  with the given outer size (chrome.windows.create)
- new `bsk window resize --session <id> --width <px> --height <px>`
  resizes the Agent Window at runtime (chrome.windows.update)
- both validated on CLI, daemon and extension sides (100..=7680 CSS px)
- protocol: new tool.window_resize method (BrowserMutation) and
  optional width/height on tool.session_start params; schemas regenerated
2026-08-05 11:19:10 +08:00
BB-fat d7f0f1e78c fix(install-skill): restrict --all to detected harnesses (#59)
`bsk install-skill --all` installed the bundled skill into every supported harness directory (detected or not), creating junk paths like ~/.claude/skills on machines without those harnesses. --all now targets detected harnesses only and errors with guidance when none are found; --harness remains the explicit override. The --yes non-interactive branch shares the same detected-only logic.
2026-08-04 21:35:01 +08:00
BB-fat 71255ae142 feat(request-help): add BSK_REQUEST_HELP=off to disable blocking help requests (#53)
* feat(request-help): add BSK_REQUEST_HELP=off to disable blocking help requests

* style(extension): format HelpOutcome union per biome

* docs(skill): condense BSK_REQUEST_HELP section
2026-07-31 23:54:30 +08:00
Ljy-0827 3f091318d0 chore(release): bsk 0.1.9 + extension 0.1.5 cli-v0.1.9 ext-v0.1.5 2026-07-29 15:01:59 +08:00
Zhang GH c6a2b3ec1e Merge pull request #45 from Tencent/vom
This PR brings the new VOM feature and greatly improves BrowserSkill. Some strategies may need user feedback to catch edge cases, so let's merge it now as a new version and continue polishing it iteratively.
2026-07-29 13:42:00 +08:00
Ljy-0827 d67c1a71b0 fix(vom): CI fix 2026-07-28 18:19:47 +08:00
Ljy-0827 03d2adc035 fix(vom): clean up pr 2026-07-28 17:36:41 +08:00
Ljy-0827 8f5df59b79 fix(vom): overlay 2026-07-28 17:31:33 +08:00
Ljy-0827 000fbf5540 fix(vom): bug fix 2026-07-28 16:45:40 +08:00
Ljy-0827 a52c2d6bf2 feat(vom): split function fix 2026-07-28 11:19:19 +08:00
Ljy-0827 c002c394e6 feat(vom): vom fix 2026-07-27 14:53:10 +08:00
Ljy-0827 4fb2e331a6 feat(vom): update vom algorithm, fix overlay problem with background state machine 2026-07-27 13:46:33 +08:00
Ljy-0827 e14ae9cea0 feat(vom): vom method bug fix 2026-07-24 17:25:57 +08:00
Ljy-0827 f319672721 feat(vom): method update, solve context over exposed problem 2026-07-24 17:25:57 +08:00
Ljy-0827 5e0d26ccb2 feat(vom): method update 2026-07-24 17:25:57 +08:00
Ljy-0827 9dbc553e33 feat(vom): vom base algorithm and infrastructure 2026-07-24 17:25:57 +08:00
Zhang GH b657ab574b Merge pull request #43 from Tencent/fix/early-control-return
fix(extension): fix early control return and preserve request-help handoff across tabs
LGTM
2026-07-24 15:27:41 +08:00
Ljy-0827 959bfac1ae fix(extension): human-loop fixed 2026-07-24 14:07:33 +08:00
Ljy-0827 c095128218 fix(extension): CI problem fixed, tab logic fixed 2026-07-24 14:07:33 +08:00
Ljy-0827 f73a0e9fb3 fix(runtime): incorrectly takeover the browser when user open up different tab within the same window 2026-07-24 14:07:33 +08:00
Ljy-0827 4e44fb2823 fix(runtime): fix early control return and update lifecycle 2026-07-24 14:07:33 +08:00
Zhang GH c8963e3a68 Merge pull request #37 from Tencent/fix-browser-keepalive-reconnect
Fix browser keepalive reconnect
2026-07-23 21:45:17 +08:00
“haonan”andCursor aab3b7a8e5 feat(extension): use function launcher icon
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-23 15:44:11 +08:00
Qiaochu HuandClaude 2dad162a87 fix(extension): retry console capture when a domain enable fails
`enableConsoleDomains` marked the tab in `consoleDomainsAttemptedTabs`
before issuing `Runtime.enable`/`Log.enable` and swallowed any errors,
so a transient failure (e.g. a restricted page during attach)
permanently disabled console capture for that tab: every later
`ensureConsoleCapture` was a no-op and the agent silently got an empty
console buffer with no indication that capture was broken.

This was inconsistent with `enableNetworkDomain`, which records the tab
only after `Network.enable` succeeds (and is explicitly tested as
"retries and surfaces failures"). Bring `enableConsoleDomains` in line:
mark the tab only after both domains enable successfully, so a later
`ensureConsoleCapture` can recover from a transient failure. Renamed
the flag `consoleDomainsAttemptedTabs` -> `consoleDomainsEnabledTabs`
to match `networkDomainsEnabledTabs` and reflect the new semantics.

Attach remains best-effort (it still succeeds when a domain can't be
enabled). Adds a regression test asserting `ensureConsoleCapture`
retries after a failed enable; it fails (no retry) on the previous code.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-22 20:12:51 +08:00
drakezhang aa63465050 Merge remote-tracking branch 'origin/main' into fix-browser-keepalive-reconnect
Co-authored-by: Cursor <cursoragent@cursor.com>

# Conflicts:
#	apps/extension/wxt.config.ts
#	crates/bsk-cli/src/cli/session.rs
2026-07-22 15:59:12 +08:00
Qiaochu HuandClaude 063b0bbc91 fix(extension): pass frame loaderId when waiting for navigation commit
handleNavigate's `Page.frameNavigated` handler called
`acceptLifecycleEvent("commit", frameId)` without the frame's loaderId.
Once `Page.navigate` resolves, the loader guard always carries the new
loaderId, so `eventLoaderIsRelevant(undefined, guard)` rejected the
commit event outright.

The navigation still completed in the common case only because the
readyState probe short-circuited first. On cross-origin navigations the
probe returns null (the old execution context has been destroyed), so
the wait fell back to `frameNavigated` — which was then rejected — and
`wait_until="commit"` timed out for the full `timeout_ms` instead of
resolving on commit.

Pass `p.frame?.loaderId` through, matching the sibling `lifecycleEvent`
branches. Adds a regression test that makes the readyState probe fail
and asserts commit is reached from the `frameNavigated` event; it fails
(reached "timeout") on the previous code.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-22 15:56:35 +08:00
Qiaochu HuandClaude 0de67c537a fix(extension): roll back CDP attach when a domain enable fails
If `chrome.debugger.attach` succeeds but a subsequent CDP domain enable
rejects — most notably `Page.enable`, when the tab navigates to a
chrome:// URL or the Web Store in the gap between the two calls — the
driver left the tab in an unrecoverable state. `attachedTabs` never
recorded the tabId, so the next `ensureAttached` re-attached and failed
permanently with "Another debugger is already attached" until the
extension was reloaded.

Detach the debuggee directly in the failure path (the public `detach()`
is a no-op here because the id is not cached yet) so the next attempt
starts from a clean slate. Adds a regression test that fails on the
previous code, where the rollback never ran and `detach` was never
called.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-22 15:43:29 +08:00
“haonan” ff74db48c8 chore(release): bsk 0.1.8 + extension 0.1.4 cli-v0.1.8 ext-v0.1.4 2026-07-22 15:29:02 +08:00
polarday bc8d6fa190 Merge pull request #28 from shnpd/feat/semantic-record-v3
feat: add semantic browser recording via bsk record
2026-07-22 15:17:56 +08:00
“haonan” 19981526c7 fix: record prompt copy 2026-07-22 15:05:54 +08:00
“haonan” d1de850b42 fix(record): use example.com as the default record start URL 2026-07-22 14:15:53 +08:00
“haonan” 585308df45 feat(record): add popup quick-actions launcher and make record --url optional
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.
2026-07-22 13:27:30 +08:00
drakezhangandCursor 29ff239726 Make liveness thresholds configurable and cover the reaper end-to-end
Move the reaper's silence timeout and scan cadence into DaemonConfig
(defaulting to the existing 60s/15s constants) with a
`with_browser_liveness` builder, so tests can drive the task in
sub-second windows.

Add an integration test that runs a real daemon and asserts a silent
heartbeat-capable browser — and its sessions — get reaped, while a
legacy browser that never heartbeated is left untouched.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-22 13:06:17 +08:00
drakezhangandCursor 31d2a1b3dc Gate liveness reaping on heartbeat capability
Only reap browsers that have sent at least one `system.heartbeat`.
A pre-heartbeat extension never opts in, so it is never dropped on
silence and keeps relying on socket-close detection exactly as before.
This removes a backward-compat regression where a new daemon paired
with an old extension would wrongly reap a live-but-idle connection
and then report `no_browser_connected` on the next command.

- Add a `heartbeat_seen` flag to `BrowserClient`, set when a heartbeat
  event arrives, and exclude never-heartbeated clients from
  `stale_browsers`.
- Cover both the opt-in and the legacy-survivor cases in unit tests.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-22 13:06:17 +08:00
drakezhangandCursor ed92e54dff Bump extension to 0.1.4
The manifest now declares a minimum Chrome version and requests the
`idle` permission, and the runtime gains the WebSocket heartbeat and
wake-driven reconnect. Publishing that update requires a new version.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-22 12:30:46 +08:00
drakezhangandCursor cb11cecdf6 Lock system.heartbeat wire name with a contract test
The extension emits the literal event string "system.heartbeat";
assert the daemon-side serde name serialises to the same value and
round-trips from the exact frame shape the extension sends, so a
future rename cannot silently break keepalive and liveness.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-22 12:30:46 +08:00
drakezhangandCursor ea03f36f3a Widen session.start browser-connect wait for cold reconnects
After a long idle the service worker is only revived on its next
keepalive-alarm tick (up to 30s away), so the previous 5s wait made
the first command after idle fail with `no_browser_connected` even
though the extension was about to reconnect.

- Raise the daemon's `EXTENSION_CONNECT_WAIT` (used by `session.start`)
  to 35s so it comfortably covers one alarm period plus handshake slack.
- Bump the CLI `session start` IPC timeout to that window plus slack so
  it never gives up before the daemon answers, and print a one-line
  "waiting for browser extension to connect…" hint when it actually
  waits.
- Keep `bsk status` / `browsers` on their own short 5s wait so quick
  informational commands are not slowed down.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-22 12:17:15 +08:00
drakezhangandCursor 234e9101ed Keep service worker alive with WS heartbeat and wake reconnect
Harden the extension's connection so the daemon link survives normal
idle periods and OS sleep instead of silently dropping.

- Send a `system.heartbeat` event every 20s while the post-handshake
  link is live. Since Chrome 116 WebSocket activity resets the MV3
  service-worker idle timer, so this keeps the worker (and the socket)
  alive during use rather than relying on the 30s keepalive alarm that
  sits right on the eviction boundary. Declare `minimum_chrome_version:
  "116"` accordingly.
- Reconnect on `runtime.onStartup` and `idle.onStateChanged` ("active"),
  which revive the worker after a browser restart or machine wake and
  let it reconnect immediately instead of waiting for the next alarm
  tick. Add the `idle` permission and document it.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-22 12:17:06 +08:00