mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-19 09:01:39 -06:00
aeee426180
* feat(control-ui): persistent Ask OpenClaw companion with global toggle The custodian surface now behaves like the persistent machine-wide agent it already is on the Gateway: the session id persists in localStorage so a reopened surface rebinds to the live engine (wizard and approval state survive close/reopen), the durable transcript is refetched when a surface opens or the gateway reconnects (idle-gated so active question/wizard cards are never clobbered), and the panel toggles from anywhere via the shared panel-toggle contract, a command-palette action, and an admin-gated lobster chrome button. One server-side line: the openclaw.chat owner-mismatch rejection now carries the existing structured session-invalidated details so persisted clients re-mint their id from a closed code instead of matching error prose. No gateway events, no protocol schema changes, no polling. Splits (session-identity/variant modules, session-lifecycle and panel-toggle test files) keep the touched files under the max-lines ratchet. * fix(control-ui): coerce custodian toggle detail without a type assertion The assertion-safety ratchet holds custodian-panel.ts at zero uncommented assertions; parse the toggle CustomEvent detail through the canonical record-coerce guard and literal narrowing instead of casting. * fix(control-ui): delete unused CustodianPanelToggleDetail export The record-coerce toggle parsing left the exported type without a production consumer; the deadcode gate rightly flags it. The palette test keeps a local shape. * test(control-ui): select the palette custodian item via keyboard Async session-search results can reflow the palette list mid-click on slow CI runners, silently dropping the positional click; keyboard selection of the asserted-active item is atomic against reflow. Also stage the reopen wait (panel section, then text) for sharper failure localization. * fix(control-ui): project live wizard state on rejoin and scope-gate the toggles Address both ClawSweeper P1 findings. The welcome-only rejoin of an existing session now routes through engine.decorateRejoinReply (the existing ChatWizardHost projection), so a reconnecting client re-renders the live wizard/question controls the session still awaits; the stale welcome question only fills in when no interaction is live. The chrome button, palette action, and deferred panel loading now use the scope-aware canCallGatewayMethod gate (operator.admin) that the session store already used, so advertised-but-read-scoped clients see nothing. * test(control-ui): fix the cloud-workers e2e flake at both roots The mocked config.get stayed frozen at the empty initial config while patch responses advanced, so a config-store reconciliation refetch could flap the snapshot to empty and saveProfile silently dropped the next save; the mock now stays consistent before each patch resolution. Also give waitForRequest an opt-in after-cursor: it is satisfied by any prior same-method request and returns the latest match, so a second wait could assert against the stale earlier request; the cloud-workers waits pin it (15x green locally, previously failing 1-in-3). * fix(ci): cover rejoin projection in sibling engine mocks; bump startup baseline The greeting-welcome and session-ownership suites' engine mocks now export decorateRejoinReply like the handler requires. The Control UI startup-JS baseline moves 337511 -> 338920 B via the documented update command: the shell chrome toggle, palette action, and scope-aware gating are genuine startup surface (~1.4 KiB gzip, within the committed ceiling). * fix(control-ui): settle interrupted structured replies and racing turns on rejoin Address both ClawSweeper reconnect P1s. A submitted question/wizard reply with an unknown outcome now triggers a full session rejoin on reconnect instead of being blocked by its own uncertainty flag: the Gateway projects whether the answer was consumed and which control is live. A restored persisted id also arms a one-shot rejoin barrier: the welcome-only request queues behind any in-flight turn on the Gateway's per-session queue, so a post-response history refresh deterministically surfaces rows a racing turn persisted after the initial fetch. The open-agent handoff moved to custodian-navigation (its owner) to keep the store under the size cap. Live-Gateway proof (isolated state dir, real gpt-5.6-luna turns): video and screenshots on the PR. * test(control-ui): reopen via the chrome toggle in the custodian e2e The palette click-through composition proved timing-flaky on loaded CI runners in three different ways while adding no coverage: the palette action's dispatch is pinned by the palette unit test and the event-opens- panel path by the chrome-toggle step. Keep the gated palette entry assertion + screenshot; reopen through the chrome path. * fix(control-ui): keep the agent-handoff path helper module-local The store now routes through performCustodianAgentHandoff, leaving the path builder without external callers; the deadcode gate rightly flags the export. * fix(control-ui): run the rejoin barrier even when a live control projects The racing-history refresh happens before the reply/control message is appended, so skipping it for projected wizard/question rejoins had no purpose and lost rows a turn persisted while the page was closed mid- wizard. Regression covers the live-step rejoin reconciling racing rows.