Skip to content

Virtualize and harden native chat timeline#2

Closed
bkudiess wants to merge 92 commits into
mainfrom
chat-virtualized-refactor
Closed

Virtualize and harden native chat timeline#2
bkudiess wants to merge 92 commits into
mainfrom
chat-virtualized-refactor

Conversation

@bkudiess

@bkudiess bkudiess commented Jul 9, 2026

Copy link
Copy Markdown
Owner

Summary

  • virtualize the native chat timeline with a WinUI ItemsRepeater host while preserving the existing chat visual design
  • split chat timeline/composer internals into clearer UI-focused names and helper files
  • harden chat scroll behavior: default to latest on open, preserve intentional scrolled-up position, stabilize follow-bottom/load-earlier behavior
  • restore Allow always permission action rendering and AllowedAlways decided badge handling

Validation

  • ./build.ps1
  • dotnet test ./tests/OpenClaw.Shared.Tests/OpenClaw.Shared.Tests.csproj --no-restore
  • dotnet test ./tests/OpenClaw.Tray.Tests/OpenClaw.Tray.Tests.csproj --no-restore
  • dotnet test ./tests/OpenClawTray.FunctionalUI.Tests/OpenClawTray.FunctionalUI.Tests.csproj --no-restore

Notes

  • Manual/computer-use validation covered opening Chat, navigating away/back, and latest-row positioning behavior.
  • Unrelated WorkspacePage work was kept out of this branch and preserved only in local stashes.

bkudiess and others added 30 commits June 24, 2026 12:41
Adds app-managed WSL gateway recovery actions to the setup wizard, moves shared WSL gateway helpers into OpenClaw.Connection, and documents the recovery behavior.
Fixes the Settings hotkey to open the Settings page and refreshes the MXC helper restore so stale helper binaries are not reused while keeping npm restore incremental.
Ports the MXC probe/SDK 0.7.0 work and inbound pairing approval dialog from the mistaken master branch target onto main.

Maintainer repair included:
- Preserving non-actionable handling for ambiguous legacy pairing fallback IDs in the new approval queue.
- Adding regression coverage for device and node fallback ambiguity.
- Version-stamping MXC SDK restore so stale node_modules cannot satisfy the 0.7.0 port.

Validation:
- Local .\build.ps1 passed.
- Local Shared tests passed: 2411 passed / 29 skipped.
- Local Tray tests passed: 1127 passed.
- Local Connection tests passed: 373 passed.
- GitHub CI passed on repaired head 7be0688: test, E2E setup-connect, E2E revocation-recovery, E2E network-recovery, build win-x64, build win-arm64, repo-hygiene.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Routes local system.run approval prompts into native chat when an interactive chat surface is available, while preserving the native approval dialog fallback.

Maintainer updates:
- Rebased onto current main after the MXC/pairing port landed.
- Kept the deleted Chat Explorations fake provider removed during rebase.
- Removed a duplicate ChatWindow.Show() call introduced during the branch hardening pass.

Validation:
- Local .\build.ps1 passed.
- Local Shared tests passed: 2417 passed / 29 skipped.
- Local Tray tests passed: 1154 passed.
- Independent code review found only the duplicate Show() issue, now fixed.
- Independent security review found no concrete security vulnerabilities.
- GitHub CI passed on repaired head ae301c0: repo-hygiene, test, E2E setup-connect, E2E revocation-recovery, E2E network-recovery, build win-x64, build win-arm64, Socket Security.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Merged after daily triage: focused scope, green CI, and low-risk validation evidence.
Merged after daily triage: focused scope, green CI, and low-risk validation evidence.
Merged after daily triage: focused scope, green CI, and low-risk validation evidence.
Merged after rerunning the failed setup-connect shard successfully; follow-on win-x64 and win-arm64 builds also passed.
Adds a static gateway protocol snapshot guard covering sessions, files, commands, and compaction, with maintainer repair so no-parameter used request methods are also checked for payload drift.
Improves Cron History so users can inspect full sanitized run responses, preserves expanded/running state while refreshing, adds response-aware cron.run feedback, and includes compatibility coverage for legacy cron.run payload fallback.
Route selected background issues into the in-app Notifications page, including connection, sandbox, channel, pairing, and cron failures. Partially addresses openclaw#820; it does not close the broader notification-routing issue.
* Make A2UI dataModelUpdate.valueArray first-class

The v0.8 `dataModelUpdate.valueArray` typed value was silently dropped by the
WinUI parser: `DataModelEntry` had no `ValueArray` field and `ToJsonNode()`
returned null for it. Only `valueString/Number/Boolean/valueMap` were handled.
This broke seeding an array into a surface's data model (e.g. a multi-select
`MultipleChoice` bound to a path), even though `valueArray` is part of the v0.8
protocol (docs/a2ui/protocol.md §2.2 and data-and-actions.md).

Changes:
- Parser (A2UIProtocol.cs): add `DataModelEntry.ValueArray`; `ToJsonNode()`
  emits a `JsonArray`; new `ParseValueArray`/`ParseArrayElement` handle
  value-typed object elements, bare primitives (`["a",1,true]`), nested
  maps/arrays, and preserve JSON null as a stable index slot.
- DoS guard (DataModelStore.cs): the 32-deep depth bound now recurses
  `valueArray` as well as `valueMap`.
- Security (SecretRedactor.cs): the array branch now redacts registered/
  denylisted element paths instead of only recursing, so a secret seeded into
  an array (e.g. an obscured field bound to /codes/0) no longer leaks via
  canvas.a2ui.dump.
- Docs (SKILL.md): correct the stale "arrays are not first-class" note.

Tests: parser coverage for valueArray (strings, mixed scalars, maps, nested
arrays, bare primitives, empty, null slots) plus valueMap/scalar regressions;
secret-redaction regressions for secrets inside arrays; store-level base-path
landing and depth-guard rejection; and an end-to-end MultipleChoice surface
seeded via valueArray that asserts both the snapshot and the rendered
preselection.

Validation: build.ps1 (all projects), Shared.Tests, Tray.Tests, and A2UI
UITests all pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix valueArray redaction and notifications

Reject non-canonical array pointer indices for data-model array access, notify descendant subscribers when container values are replaced, and redact registered secret descendants when action contexts or snapshots include parent paths.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Scott Hanselman <scott@hanselman.com>
* Fix canvas navigation URL handling

* Fix canvas navigate dispatcher timeout

Route canvas.navigate through the same dispatcher timeout guard used by canvas.eval and canvas.snapshot so stalled UI dispatch cannot hang MCP tool calls indefinitely.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Scott Hanselman <scott@hanselman.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add TTS provider fallback and tts.status readiness command

When the requested/configured TTS provider isn't usable (no ElevenLabs key,
Piper voice not downloaded), gracefully fall back to Windows TTS instead of
throwing, and report the effective vs requested provider plus a fellBack flag.
A stale configured Windows voice now degrades to the system default voice so
the fallback always speaks.

Add a tts.status node command that reports per-provider readiness
(ready/needs-api-key/needs-voice/voice-not-downloaded/unavailable) plus the
configured/effective provider and willFallBack. PII-free. Wired across
DangerousCommands gating, MCP descriptions, skill.md, and the setup allowlist
export. Fix a stale pre-GA SHA-256 TODO docstring in PiperVoiceManager
(verification is already implemented and enforced by AssetHashPinningTests).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Preserve configured TTS fallback for chat playback

Leave chat playback provider unset so TextToSpeechService can distinguish configured/default playback from explicit provider requests and apply the new Windows fallback when the configured provider is unavailable.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Scott Hanselman <scott@hanselman.com>
Validate screen.snapshot image formats before invoking the capture backend, normalize jpg to jpeg, and derive the response data URI MIME type from the validated format instead of the backend echo.

Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…w#824)

* Wizard protocol resilience: progress/non-interactive steps, auth prompts, restart hardening

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Harden wizard progress polling budget

Allow a single long-running gateway progress step to use the full bounded progress budget instead of failing after the previous shorter per-step cap. Share the progress constants between the setup runner and UI and cover the intended budget in tests.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Scott Hanselman <scott@hanselman.com>
Measure the tray popup against its final client width and apply pixel-exact window sizing so wrapped content determines height deterministically.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Normalize the Sandbox page toggle off when MXC is definitively unavailable, reject turning it back on in the host-fallback mode, and preserve strict fallback blocking so users who opted into command denial remain protected.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Squashed from PR openclaw#800 after maintainer review and local fixes.\n\nLocal validation:\n- .\\build.ps1\n- dotnet test .\\tests\\OpenClaw.Shared.Tests\\OpenClaw.Shared.Tests.csproj --no-restore\n- dotnet test .\\tests\\OpenClaw.Tray.Tests\\OpenClaw.Tray.Tests.csproj --no-restore\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* test: add Gateway MXC runtime E2E proof

* test: probe MXC E2E gate with discovered wxc-exec

* test: extend Gateway MXC E2E timeout budgets

* test: avoid blocked redirection in Gateway MXC deny proof

* test: prove MXC denied copy reaches destination

* test: document serialized MXC E2E collection gate

* test: raise MXC E2E sandbox timeout cap

* test: approve MXC denied-write copy proof step

* test: sync MXC approval proof diagnostics

* test: narrow MXC exec approval proof policy

* ci: extend setup-connect E2E timeout

Give only the setup-connect E2E shard extra time for the combined setup and MXC runtime proof fixtures while leaving the other E2E shards on the existing budget.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: omit unsupported MXC denied paths

Windows wxc-exec rejects filesystem.deniedPaths before launching the sandboxed command. Keep denied paths as the local allow-list filter, but omit the unsupported backend field so AppContainer default-deny can run the command while still stripping parent/exact grants over sensitive paths.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Vitor Cepeda Lopes <7040636+TheAngryPit@users.noreply.github.com>
Co-authored-by: Scott Hanselman <scott@hanselman.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
)

* Improve remote gateway setup and connection error recovery

Add RemoteGatewayClassifier + GatewayErrorClassifier in OpenClaw.Shared and
wire ConnectionPage remote setup advice, scope/token-drift/TLS recovery, and
localized strings.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Clear stale SSH fields for setup-code flow

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Scott Hanselman <scott@hanselman.com>
* Node mode UI: surface MCP-only/connecting states and repair gateway-node gating

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix MCP-only node status visibility

Surface the local MCP-only node card even when no gateway/operator session exists, and make the reconnect-backoff test wait for server-side accept publication.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Keep MCP-only mode from joining gateways

Gate the post-operator local NodeService auto-connect on EnableNodeMode so local MCP-only serving does not create gateway node pairing requests.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Request node reconnect in shared-token setup E2E

The shared-token setup path can now remain MCP-only after operator approval, so the E2E needs to request node reconnect explicitly before waiting for a node credential.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Scott Hanselman <scott@hanselman.com>
)

A connection/auth failure rendered two error bars: the global top-window
InfoBar plus an in-page "Connection Error" InfoBar on the Connection page.
The auth pipeline also published two global notifications for one failure,
which forced the banner action to degrade to "Show more".

Remove the in-page AuthErrorBar and consolidate to one top banner that:
- carries the gateway/node error states the in-page bar covered
- always routes the user to the Connection page via an "Open Connection"
  action (connection notifications are prioritized as the visible banner,
  preferring an actionable one over an action-less transient)
- renders as a single thin line: bold headline + " - detail", with the
  action as a right-aligned hyperlink (Windows-aligned InfoBar)

Other changes:
- Stop publishing the duplicate connection:authentication-failed banner;
  the snapshot-driven connection:issue notification is the single source.
- Re-home transient errors: WSL host-action failures use the inline card
  status (or a top notification when the card is hidden); connect/switch
  failures publish via ShowTransientConnectionError on the same banner id.
- Remove now-dead resw strings (ConnectionPage_AuthGuidance*,
  ConnectionPage_ConnectFailed) across all five locales.

Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add tray live dashboard glance

Add a compact status summary to the tray flyout that surfaces gateway health, refresh freshness, session and usage metrics, and the current session preview before the existing action rows.

Wire a Diagnostics action into the tray menu and keep the summary computation in a testable, render-free builder shared by existing usage/session rows.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Remove message previews from tray glance

Keep the tray dashboard focused on health, freshness, session metadata, and usage while avoiding conversation message text in the top-level flyout.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Avoid activity snippets in tray dashboard glance

Keep the top-level tray dashboard limited to stable metadata so command, query, path, or URL activity text stays out of the glance.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Scott Hanselman <scott@hanselman.com>
Move notifications from the footer rail into a title-bar bell flyout and replace the compact connection status dots with a status pill plus detail flyout. Keep the status presentation aligned with the Connection page by deriving node state from shared presenter logic and the node-mode/capability settings.

Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Port PR openclaw#562 onto current main and harden diagnostics redaction so JSONL remains parseable while sensitive values, metadata keys, paths, emails, headers, and compound JSON values are sanitized before export.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
TurboTheTurtle and others added 28 commits July 6, 2026 05:47
Virtualize native chat rows with stable recycled containers, bounded renderer state, and cleanup for removed component trees. Preserve history, update, append, and follow-to-bottom behavior with native WinUI proof.

Thanks @TurboTheTurtle for the contribution.

Co-authored-by: Andy Ye <35905412+TurboTheTurtle@users.noreply.github.com>
Keep notification previews compact while retaining the complete assistant response for Tray text-to-speech. Add legacy/null/empty fallback coverage at the Tray ownership boundary.

Thanks @ArtLupo for the contribution.

Co-authored-by: Master <artlupo3689@gmail.com>
Adds a native queued-message surface and one-at-a-time client-side dispatch, with exact local/gateway identity reconciliation across live and history updates.

Hardens abort, reset, reconnect, final-only completion, delayed lifecycle, and retransmit ordering so a prior run cannot consume or terminate the next queued prompt.

Co-authored-by: Caleb Eden <58373773+calebeden@users.noreply.github.com>
…w#659)

Integrate setup-owned Windows node guidance into the native onboarding flow.

Harden workspace resolution, retry behavior, CRLF-safe managed updates, and deterministic uninstall state. Add real-WSL regression coverage for idempotent context replacement.

Co-authored-by: Paul Campbell (AgOS) <paulcam@microsoft.com>
)

Bumps [github/gh-aw-actions/setup-cli](https://github.com/github/gh-aw-actions) from 0.81.6 to 0.82.2.
- [Release notes](https://github.com/github/gh-aw-actions/releases)
- [Changelog](https://github.com/github/gh-aw-actions/blob/main/CHANGELOG.md)
- [Commits](github/gh-aw-actions@ba6380c...3fac1cf)

---
updated-dependencies:
- dependency-name: github/gh-aw-actions/setup-cli
  dependency-version: 0.82.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
updated-dependencies:
- dependency-name: GitVersion.MsBuild
  dependency-version: 6.8.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
updated-dependencies:
- dependency-name: gitversion.tool
  dependency-version: 6.8.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Ranjesh Jaganathan <ranjeshj@microsoft.com>
Remove the broken Windows CA certificate sync setup step after validation showed it was dead on arrival.
Keep release identity as the default and require explicit opt-in for side-by-side dev builds.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Fix LocalizationHelper so runtime callers passing XAML property resource keys like ConnectionPage_Connect2.Content resolve through MRT path segments like ConnectionPage_Connect2/Content instead of displaying raw keys.

Validation: GitHub Build and Test, CodeQL gate, Socket checks all passed.
Refine the gateway setup wizard UX, improve accessibility names, make wizard text selectable, and fix the expanded-provider step id handling.

Follow-up included in this merge: remove the stale 'More' overflow button when resetting wizard steps so it cannot leak onto later steps.

Validation: local build.ps1, Shared tests, Tray tests; GitHub Build and Test, CodeQL gate, Socket checks all passed.
Remove the footer/sidebar Notifications navigation item so Notifications remains available through the title-bar bell only.

Validation: GitHub Build and Test, CodeQL, Socket checks all passed; UIA proof confirmed the bell remains and no sidebar/footer Notifications row is present.
Add a shared red-bot BrandMark control and replace lobster/generic robot brand marks across Hub, onboarding, dialogs, and Agent Events surfaces while keeping native Windows accent colors unchanged.

Validation: GitHub Build and Test, CodeQL gate, Socket checks all passed; current-head visual/UI proof included in PR.
Fix queued chat message parity by assigning stable queued send run IDs/idempotency keys, reconciling duplicate prompts by queue/run identity, handling deferred in_flight admission with bounded retries, adding per-entry queue cancel/remove controls, and exposing local MCP queue list/cancel commands.

Follow-up review blocker resolved: local echo suppressors are deduped and removed by queued message ID, with regression coverage for in_flight retry followed by a later same-text remote user message.

Validation: GitHub Build and Test, CodeQL gate, Socket checks all passed; PR includes local build/test counts plus winnode MCP list/cancel proof.
Add a clean-room virtualized chat timeline host backed by ItemsRepeater, preserve the existing chat visuals, and introduce the FunctionalUI native-control boundary needed to host native surfaces safely.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Split timeline and composer helpers into focused files, add a tested stable row-source synchronizer, and keep virtualization updates incremental without changing chat visuals.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Address final dual-review hardening items by removing per-render entry-id set allocation, stabilizing the thinking row key, locking session offset storage, preserving row host contexts across remounts, and reapplying prepend correction until virtualized extents stabilize.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Drop redundant OpenClaw prefixes from chat UI component and file names, and track realized virtualized rows explicitly instead of relying on ItemsRepeater parent semantics.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Rebase the chat virtualization changes onto latest main, restore the extracted timeline helper, preserve synchronous first row measurement, and replace the recursive bottom chase with a single-shot ScrollViewer state machine that has fallback completion.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Keep the chat virtualization branch scoped to chat changes; the WorkspacePage work remains preserved in the local stash.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Keep Chat opening at latest unless the user intentionally left it scrolled up, restore timeline helper contracts after rebasing onto latest main, and use a single-shot bring-into-view state machine with synchronous first row measurement.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Render all gateway-provided permission actions, map AllowedAlways decisions to the correct label, and add contract coverage for the Allow always action and badge.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@bkudiess

bkudiess commented Jul 9, 2026

Copy link
Copy Markdown
Owner Author

Closing; this PR was opened against the fork by mistake. Re-opening against the upstream OpenClaw repository.

@bkudiess bkudiess closed this Jul 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.