[codex] Implement Canvas A2UI visual workspace#78
Conversation
🤖 Augment PR SummarySummary: Adds a first-party, session-scoped Canvas + A2UI visual workspace for websocket clients. Changes:
🤖 Was this summary useful? React with 👍 or 👎 |
| <TextBlock Text="{Binding CanvasStatus}" TextWrapping="Wrap" /> | ||
| <TextBlock Text="{Binding CanvasHtmlStatus}" FontSize="11" Opacity="0.65" | ||
| TextWrapping="Wrap" | ||
| IsVisible="{Binding CanvasHtmlStatus, Converter={x:Static ObjectConverters.IsNotNull}}" /> |
There was a problem hiding this comment.
src/OpenClaw.Companion/Views/MainWindow.axaml:88 — CanvasHtmlStatus is initialized to "" (not null), so ObjectConverters.IsNotNull will keep this TextBlock visible even when there’s no status text, likely leaving an empty line in the Canvas header area.
Severity: low
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
| if (!root.TryGetProperty("value", out var value) || value.ValueKind != JsonValueKind.Number) | ||
| return 0; | ||
| var number = value.GetDouble(); | ||
| return number <= 1 ? number * 100 : Math.Clamp(number, 0, 100); |
There was a problem hiding this comment.
src/OpenClaw.Companion/ViewModels/A2UiFrameItem.cs:126 — BuildProgressValue() will return negative percentages if the incoming numeric value is negative (because the number <= 1 branch multiplies by 100 without clamping), which can drive the UI progress bar below its expected range.
Severity: low
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
| if (!TryGetRequiredString(args.RootElement, "frames", out var frames, out var error)) | ||
| return error; | ||
|
|
||
| var validation = A2UiFrameValidator.ValidateJsonl(frames, Config.Canvas.MaxFramesPerPush, Config.Canvas.MaxCommandBytes); |
There was a problem hiding this comment.
src/OpenClaw.Gateway/Tools/CanvasTools.cs:188 — ValidateJsonl(..., maxBytes: Config.Canvas.MaxCommandBytes) only bounds the raw frames payload, but the broker enforces MaxCommandBytes on the full serialized envelope; payloads near the limit can validate here and still fail later with “Canvas command exceeds … bytes.”
Severity: low
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
|
|
||
| private async Task SendCanvasSnapshotResultAsync(WsServerEnvelope envelope) | ||
| { | ||
| var snapshot = BuildCanvasSnapshotJson(envelope.SurfaceId); |
There was a problem hiding this comment.
src/OpenClaw.Companion/ViewModels/MainWindowViewModel.Canvas.cs:179 — BuildCanvasSnapshotJson() serializes all accumulated frames/values without any explicit bounding, so after many pushes the snapshot can exceed the gateway’s MaxSnapshotBytes and cause canvas_snapshot to fail even though the client returns success: true.
Severity: medium
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
Summary
Implements Canvas + A2UI v1 as a first-party, session-scoped visual workspace for websocket clients.
Changes
Validation
dotnet test src/OpenClaw.Tests/OpenClaw.Tests.csproj --no-restore --filter "FullyQualifiedName~A2UiFrameValidatorTests|FullyQualifiedName~CanvasCommandBrokerTests|FullyQualifiedName~CanvasToolTests|FullyQualifiedName~CompanionCanvasTests|FullyQualifiedName~WebSocketChannelTests|FullyQualifiedName~GatewaySecurityHardeningTests|FullyQualifiedName~GatewayBootstrapExtensionsTests|FullyQualifiedName~DocsConsistencyTests"passed: 54/54.dotnet test src/OpenClaw.Tests/OpenClaw.Tests.csproj --no-restorecurrently has one unrelated local environment failure: missing Playwright Chromium executable forBrowserToolTests.BrowserTool_CanNavigateAndGetText; the remaining 995 tests pass.