Repository navigation
Description
Prerequisites
- I searched existing open/closed issues; the closest are bsk 在 Windows 上的两个会话可靠性问题:命令刚返回就报 unfinished command,以及 session stop 无法强制终止卡死命令、只能重启 daemon #185 (unfinished command on Windows 0.2.0), Report viewport and element screenshots time out while blank-tab capture succeeds (0.3.2, macOS) #418 (report screenshot timeouts 0.3.2 macOS), Cooperation: self-updating page text (clocks, counters) makes every action refuse with 'observed content changed' #495 (self-updating text causes
observed content changed), [Bug] A session is reclaimed mid-use and the borrowed tab's page state is lost, with no warning #386 (session reclaimed mid-use). None covers the 0.4.0 observation/context-expiry combination below. - All sensitive data redacted (no internal hosts, tokens, URLs, or user data).
BrowserSkill Version or Commit
0.4.0 (bsk 0.4.0, daemon protocol 1.7, extension 0.4.0, DSH plugin @wxg-prc-cpg/browser-skill-dsh-plugin@0.4.0)
Operating System
Linux (x86_64) — daemon/CLI run inside a container
OS Details and Architecture
Debian-based container x86_64; browsers run on a separate Windows host reached through the authenticated remote WSS gateway.
Installation Method
Prebuilt binary release from GitHub Releases
Browser and Browser Extension Version
Edge 156.0.0.0 + extension 0.4.0; Chrome 156.0.0.0 + extension 0.4.0 (two separate instances, both remote)
Exact Command or API Call
DSH tool calls (plugin 0.4.0):
bsk_session({action:"start", browser:"<instance>", noFocus:false, url:"https://example.com"})
bsk_session({action:"sync", session:"<sid>"}) # immediately after start
bsk_interact({action:"click", session:"<sid>", target:"@e2", contextId:"<ctx>"})
and the equivalent CLI calls (bsk session start --focus, bsk cooperate sync).
Minimal Reproduction Steps
Defect A — observation capture wedges the per-session command queue
- With the plugin default
observationEnabled: true, start a session against a remote browser (foreground or background) with a URL, then callsyncimmediately. syncfails withPrevious operation is still settling; this action was not dispatched.- From then on every command on that session fails:
bsk tab list --session <sid>→session already has an unfinished commandbsk reload→This action requires the context returned by the latest cooperate sync(but sync can never succeed)
→ hard deadlock; onlysession stopworks.
- Control A: start the same browser session through the CLI directly (no plugin observer) →
navigate+cooperate syncsucceed immediately. - Control B: set the plugin config
observationEnabled: falseand restart → the exact same plugin flow (start→ immediatesync) succeeds on the first attempt.
This reproduces on both Edge and Chrome, foreground and background, so it is not a browser/window-focus issue.
Defect B — action context expires before the next call, and "unchanged" sync does not renew it
syncreturnsstate.target.expires; measured TTL ≈ 15–20 s.- A second
syncreturnskind: "unchanged"with the sameexpiresvalue (no renewal). - A
clickissued after expiry fails withPage interaction coverage changed; wait and synchronize. - The click has nevertheless been executed (the page had already navigated when checked afterwards) — the error does not mean "not dispatched".
Expected Behavior
- Observation thumbnails must not block the session command queue; a hung capture should time out and release the queue.
- A successful
syncshould renew the action context (or expose a way to extend it), and an expired context should be reported as such, not as "page coverage changed". - Errors should state whether the action was dispatched.
Actual Behavior
- A stuck observation
screenshotholds the single in-flight command slot forever;sync,tab,navigate,reloadall queue behind it, andreload(the suggested recovery) itself requires a sync context → deadlock. - Action context TTL is shorter than a typical agent step latency, and
syncwithkind: "unchanged"keeps the staleexpires. coverage changedis returned even when the click completed.
Relevant Logs / Diagnostics Output
Error: bsk cooperate sync failed: Previous operation is still settling; this action was not dispatched
(hint: confirm the tab is still in a loaded state and retry; reloading the tab usually resets a stuck DevTools session)
error: previous session command is still running
hint: wait for the current command to finish, cancel it with Ctrl-C, or stop/restart the session
details: session already has an unfinished command
Error: bsk reload failed: This action requires the context returned by the latest cooperate sync
(hint: use `bsk cooperate wait --session SID`, then `bsk cooperate sync --session SID`; replan ...)
Error: bsk click failed: Page interaction coverage changed; wait and synchronize
# sync payload excerpt (second consecutive sync, note unchanged expires)
"kind":"unchanged","previous_context_id":"<redacted>",
"state":{"mode":"ready","revision":20,"target":{"expires":1793348168226,"x":406,"y":504.3}}
Is this a regression?
Yes (please specify the last known working version below)
Last Known Working Version (if regression)
Not observed on 0.3.3 with the same host topology, but 0.3.3 predates automatic shared control and automatic observation, so the comparison is not apples-to-apples.
Additional Context
Defect A disappears completely when the plugin's observationEnabled is set to false, which points at the periodic screenshot --session capture (ObservationService) as the command that hangs and blocks the queue. Suggested fixes: bound the capture with a timeout and abort/withdraw it on failure, never let observation occupy the action lane, and make reload usable while the queue is blocked (or offer a queue reset).
For Defect B, either renew the target on every successful sync or make the TTL explicit/configurable; and separate the "expired context" error from "page content actually changed".
Activity
tom613951 commentedon Oct 31, 2026
Additional reproduction:
kindnever converges frombaselineon pages with a sub-10-second live regionReporting a narrower trigger than a TTL expiry, measured on
bsk 0.4.0/ extension0.4.0/ protocol1.7, Windows + Chrome 156.0.0.0, local browser (no remote WSS gateway). Both defects reproduce.Environment
observationEnabledwastrueat first, then set tofalsein the DSH plugin config. Toggling it did not change CLI-side behaviour, which is consistent with the capture path living in the extension rather than the plugin.Controlled A/B on one session
Two pages, one daemon, one session (
zhwp),bsk cooperate syncrepeated 6× at 1.2 s intervals. Identical harness both times.A —
https://example.com(static):baselineon the first capture only, thenunchanged. Actions succeed:B —
https://bbs.huaweicloud.com/blogs/article(same session, after navigate):baselineon every capture, neverunchanged. Every action refused:Two stable differences:
kindnever leavesbaseline, andsynccosts ~1100 ms instead of ~20 ms — a ~55× increase, consistent with a full VOM capture each call rather than an incremental comparison.What the page does
The editor renders a live autosave counter in its footer —
"21 秒后保存","4 秒后保存", counting down and resetting on a sub-10-second cadence. That counter sits inside the editor's form container. PR #497 deliberately keeps form values, checked state, modals and the action's own region exact, and the<main>/landmark relaxation excludes positioned panels, so a counter inside the form container is never learnable as volatile. The result is that this page cannot reachunchangedat all.--depends-ondoes not help, because the refusal happens on the whole-page capture before target scoping:Session state also degrades
An earlier session (
opyq) showedunchangedonexample.comat first, then began returningbaselineon the same unchanged page after roughly 20 minutes of repeated sync/refuse cycles — after whichexample.comwas refused 6/6 as well. A brand-new session restoredunchangedimmediately. So there appear to be two independent ways to lose convergence:Defect A, as observed
After several refusals the session wedges, matching your report:
The
detailsline is a content-script messaging failure, not a cooperation refusal.bsk reloadcannot recover it because reload needs a context from the sync that just failed.bsk session stop --allis the only exit. Reproduced onabout:blankand onexample.comafter a daemon restart; cleared by a fresh session followed bybsk cooperate wait.Not reproduced
statein this build carries onlyediting,mode,revision— there is notargetand notarget.expires, so I could not reproduce the specificexpires-not-renewed path. Everything above is thebaseline-never-settles path.Suggested narrowing
The case worth isolating is live text inside a form/list/dialog/panel versus live text in a plain container. The first appears to guarantee a permanent
baseline. It may deserve either an escape hatch, or a documented note that such pages require a--depends-onnaming a container outside the live region — the current docs advise omitting--depends-onwhen unsure, which is exactly the state that cannot recover here.Happy to re-test against
mainonce #529 ships in a release and report whether thebaselinecase persists.MoyuP commentedon Oct 31, 2026
DSH plugin data point: the "still settling" refusal is not recoverable from DSH either
macOS arm64, local Chrome, bsk/extension/DSH plugin 0.4.0, DSH desktop 0.2.1-rc.5.
Sequence:
bsk_session startOK →bsk_page navigateOK (reached: load) → firstbsk_session syncfails 3/3 with "Previous operation is still settling; this action was not dispatched".settle: truefails identically. Sleeping ~5 s and syncing once succeeds; screenshot and stop are clean afterwards.0.4.0 mechanism (from source):
syncbypasses the plugin's per-session queue, while the observation thumbnail screenshot runs inside it. Every tool call first callsacquireForeground, which kills the runningobservation:...screenshot. The sync then reaches the extension while it is still settling the cancelled capture, so the dispatcher returnscdp_failed(apps/extension/src/tools/dispatcher.ts, "Previous operation is still settling; this action was not dispatched").ObservationService.acquireForegroundschedules a new thumbnail immediately (scheduleCapture(..., 0)), which the next retry preempts again. That matches 3/3 immediate retries failing and one ~5 s wait succeeding.--settlecannot help:crate::cli::cooperate::settle::recoverableonly retriespermission_denied+cooperation_sync_required+effect_state: none; this refusal iscdp_failed/dispatched: false, so settle returns on the first attempt without ever callingcooperate wait.reloadis a shared action and requires the latest sync context, so sync-fail → no context → reload refused.cooperate wait(DSH:bsk_session action:"wait-user") is the closest native equivalent, but it is named and described for hand-back, not for this recovery.Even on
main(1b395fd) the settle predicate, thecdp_failedhint and the context gate are unchanged, so #529 fixes the ordering trigger but not this recovery path.Suggestions:
settle::recoverable, also retry the transientcdp_failed+data.dispatched === false"still settling" refusal with a bounded wait, or surface it assession_busyso the DSH plugin'srunWithSessionBusyRetryapplies.reloadfor this condition (it is context-gated). Suggest waiting for the session to settle and syncing again, and/or expose an explicit wait/recovery action in DSH instead of onlywait-user.Happy to re-test against the next release.