Commit Graph

392 Commits

Author SHA1 Message Date
Scott Hanselman
1c0f497e28 feat: add read-only port diagnostics
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-26 23:55:28 -07:00
Scott Hanselman
a365839494 feat: surface gateway self metadata
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-26 23:52:45 -07:00
Scott Hanselman
652f552f0d feat: harden ssh tunnel command state
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-26 23:47:11 -07:00
Scott Hanselman
521cf14b92 feat: add mission control topology diagnostics
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-26 23:41:04 -07:00
Scott Hanselman
d95dd03cc2 fix: handle node-mode health checks
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-26 23:16:51 -07:00
Scott Hanselman
99f803e5ba feat: add tray command center diagnostics
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-26 23:11:00 -07:00
Scott Hanselman
f121395b06 feat: add safe device parity commands
Add canvas.a2ui.pushJSONL as a Mac-compatible alias for the existing A2UI JSONL push handler.

Add device.info and device.status using the shared OpenClawKit payload shape, with Windows metadata/status sources plus tests and docs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-26 22:43:16 -07:00
Scott Hanselman
ea6cf23add docs: update Windows node parity audit 2026-04-26 22:26:56 -07:00
Scott Hanselman
dba534250c feat: add screen recording parity
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-26 22:18:59 -07:00
dependabot[bot]
ff7ca9e0d3 chore(deps): bump azure/login from 2 to 3
Bumps [azure/login](https://github.com/azure/login) from 2 to 3.
- [Release notes](https://github.com/azure/login/releases)
- [Commits](https://github.com/azure/login/compare/v2...v3)

---
updated-dependencies:
- dependency-name: azure/login
  dependency-version: '3'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
(cherry picked from commit eab3d085b91c231197a7d735a0e7b91b13011a82)
2026-04-26 21:22:41 -07:00
dependabot[bot]
c7d6a16ab4 chore(deps): bump actions/download-artifact from 4 to 8
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4 to 8.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v4...v8)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: '8'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
(cherry picked from commit 20f3bd6608134b636a372aae633c2e59382d7f68)
2026-04-26 21:22:41 -07:00
Scott Hanselman
cb631b62c2 ci: pin MSIX packaging SDK for VS MSBuild
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-26 21:22:34 -07:00
AlexAlves87
24a4c15ca9 feat: add routing seam for system.run exec approvals
Introduce a stable handler seam behind system.run to allow incremental
exec approval work without touching the current legacy path.

When no handler is injected (default), system.run runs byte-for-byte
identical to today. The new seam is inert until explicitly activated.
Adds minimum observability at the routing boundary: correlation ID,
selected path, decision, and reason code.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
(cherry picked from commit a018dc054cbb85581baa37f92719bfcecee6d76f)
2026-04-26 21:07:43 -07:00
Scott Hanselman
902e1ee2b6 fix: sign bootstrap pairing requests
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-26 21:07:43 -07:00
dependabot[bot]
0bfa2efa4f
chore(deps): bump microsoft/setup-msbuild from 2 to 3 (#222)
Bumps [microsoft/setup-msbuild](https://github.com/microsoft/setup-msbuild) from 2 to 3.
- [Release notes](https://github.com/microsoft/setup-msbuild/releases)
- [Commits](https://github.com/microsoft/setup-msbuild/compare/v2...v3)

---
updated-dependencies:
- dependency-name: microsoft/setup-msbuild
  dependency-version: '3'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-26 21:06:03 -07:00
dependabot[bot]
77de937908
chore(deps): bump actions/upload-artifact from 4 to 7 (#220)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 7.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4...v7)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-26 21:05:59 -07:00
dependabot[bot]
72dbd3d5a1
Bump Microsoft.NET.Test.Sdk from 17.14.1 to 18.4.0 (#226)
---
updated-dependencies:
- dependency-name: Microsoft.NET.Test.Sdk
  dependency-version: 18.4.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-26 21:05:24 -07:00
dependabot[bot]
9914c684de
chore(deps): bump github/gh-aw-actions (#223)
Bumps [github/gh-aw-actions](https://github.com/github/gh-aw-actions) from ba90f2186d7ad780ec640f364005fa24e797b360 to abea67e08ee83539ea33aaae67bf0cddaa0b03b5.
- [Release notes](https://github.com/github/gh-aw-actions/releases)
- [Changelog](https://github.com/github/gh-aw-actions/blob/main/CHANGELOG.md)
- [Commits](ba90f2186d...abea67e08e)

---
updated-dependencies:
- dependency-name: github/gh-aw-actions
  dependency-version: abea67e08ee83539ea33aaae67bf0cddaa0b03b5
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-26 21:05:21 -07:00
dependabot[bot]
95c10a4369
Bump xunit.runner.visualstudio from 3.1.4 to 3.1.5
Dependabot patch update. Normal build/test checks passed; MSIX packaging failure is the existing SDK/MSBuild CI issue.
2026-04-26 21:03:59 -07:00
Scott Hanselman
395b090888 fix: dedupe System.Drawing.Common reference
Keep the newer System.Drawing.Common 10.0.7 override from PR #219 after merging QR setup work and package audit changes.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-26 20:25:40 -07:00
Scott Hanselman
a53d31016f Merge PR #219: fix NuGet audit packages 2026-04-26 20:24:00 -07:00
Scott Hanselman
0bd56ffb9a Merge PR #218: eng: handle repo-assist easy wins 2026-04-26 20:23:54 -07:00
Scott Hanselman
435b47fddc fix: override vulnerable System.Drawing.Common
Keep transitive NuGet vulnerability auditing enabled and add a direct System.Drawing.Common 10.0.7 reference so Microsoft.Toolkit.Uwp.Notifications no longer resolves vulnerable 4.7.0.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-26 20:20:55 -07:00
Scott Hanselman
00670860ed feat: improve QR setup pairing
Preserve setup bootstrap tokens separately from gateway tokens, support QR image and clipboard setup imports, and improve pairing notification copy flow.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-26 20:14:18 -07:00
Scott Hanselman
645856d1d6 eng: add shared analyzer and audit props
Add src/Directory.Build.props to align source projects on the recommended analyzer baseline and transitive NuGet vulnerability auditing.

Also allow .NET SDK feature-band roll-forward so the repo can build with installed 10.0.2xx SDKs while retaining the 10.0.100 baseline.

Supersedes #211

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-26 20:04:11 -07:00
Scott Hanselman
c84bff3a5f test: add exec auth and sanitizer coverage
Add test-only coverage from Repo Assist PRs #207 and #212 for terminal auth failures, shell wrapper parsing, and environment sanitization.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-26 19:56:52 -07:00
Scott Hanselman
864154bc2d test: add system capability coverage
Add coverage for system.run.prepare, exec approval get/set, and system.run environment sanitization from Repo Assist PR #209.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-26 19:51:15 -07:00
Scott Hanselman
d83e81d451 eng: handle repo-assist easy wins
Add root NuGet package source mapping and Dependabot config, allow .NET SDK feature-band roll-forward, and apply low-risk allocation cleanup from repo-assist suggestions.

Closes #208

Closes #214

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-26 19:46:27 -07:00
Scott Hanselman
c1296be7fd
feat: add camera.clip, location.get, and canvas local file serving
Some checks are pending
Build and Test / test (push) Waiting to run
Build and Test / build (win-arm64) (push) Blocked by required conditions
Build and Test / build (win-x64) (push) Blocked by required conditions
Build and Test / build-msix (ARM64, win-arm64) (push) Blocked by required conditions
Build and Test / build-msix (x64, win-x64) (push) Blocked by required conditions
Build and Test / build-extension (arm64) (push) Blocked by required conditions
Build and Test / build-extension (x64) (push) Blocked by required conditions
Build and Test / release (push) Blocked by required conditions
Adds Windows node camera.clip, location.get, canvas local file serving/reload support, gateway command parity docs, and aligns screen capture with gateway-canonical screen.snapshot. Also makes camera.clip choose a supported Windows MediaCapture record stream and skips startup update prompts in debug builds for local node debugging.\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-25 23:19:15 -07:00
Scott Hanselman
8283eaa794 fix: canvas URL rewriting, auth, and gateway trust for node-served content
Some checks failed
Build and Test / test (push) Has been cancelled
Build and Test / build-msix (ARM64, win-arm64) (push) Has been cancelled
Build and Test / build-msix (x64, win-x64) (push) Has been cancelled
Build and Test / build (win-arm64) (push) Has been cancelled
Build and Test / build (win-x64) (push) Has been cancelled
Build and Test / build-extension (arm64) (push) Has been cancelled
Build and Test / build-extension (x64) (push) Has been cancelled
Build and Test / release (push) Has been cancelled
Canvas windows now properly handle gateway-served content:

- Trust gateway origin: URLs from the connected gateway bypass the
  private-network security filter (the node authenticated with this
  gateway, so its content is trusted)
- URL rewriting: relative paths (/__openclaw__/...) are resolved to
  the node's effective gateway origin (localhost when SSH-tunneled,
  direct IP when on LAN)
- Bearer auth: WebView2 injects Authorization header for all gateway
  requests via WebResourceRequested filter
- Window icon: Canvas window now shows the OpenClaw icon

Fixes canvas.present failing with 'URL blocked for security' and
'Navigation failed: Unknown' (401 unauthorized).
2026-04-23 17:57:53 -07:00
Scott Hanselman
12eb2a4d7d
fix: stop aggressive retry on auth failures, add setup nudge (#206)
Some checks are pending
Build and Test / test (push) Waiting to run
Build and Test / build (win-arm64) (push) Blocked by required conditions
Build and Test / build (win-x64) (push) Blocked by required conditions
Build and Test / build-extension (arm64) (push) Blocked by required conditions
Build and Test / build-extension (x64) (push) Blocked by required conditions
Build and Test / release (push) Blocked by required conditions
Build and Test / build-msix (ARM64, win-arm64) (push) Blocked by required conditions
Build and Test / build-msix (x64, win-x64) (push) Blocked by required conditions
Part 1 (fixes #198): Move reconnect attempt counter reset from TCP
connect to application-level hello-ok handshake. Auth failures now
properly progress through backoff (1s→2s→4s→8s→15s→30s→60s) instead
of resetting to 1s on every attempt.

Part 2 (closes #199): Detect terminal auth errors (token mismatch,
origin not allowed, rate limited, signature exhausted) and stop
retrying entirely. Fire AuthenticationFailed event so the UI shows
a setup nudge in the tray menu.

Security: exhausted device signature modes (all 4 rejected) are now
treated as terminal — no infinite cycling. Error messages stay local
(log file + tray menu only, never sent externally).

Pairing success already sends a toast notification (Toast_NodePaired)
in all 5 locales.
2026-04-23 12:10:32 -07:00
Scott Hanselman
5a97268ec0
improve: FrozenDictionary command dispatch map in WindowsNodeClient (#205)
* improve: FrozenDictionary command dispatch map in WindowsNodeClient

Replace O(n) linear capability scans with O(1) FrozenDictionary lookup.

- Add _commandMap field (FrozenDictionary<string, INodeCapability>)
- Add BuildCommandMap() to (re)build the map after each RegisterCapability call
- Replace both FirstOrDefault dispatch calls with _commandMap.GetValueOrDefault
- First-registered capability wins on command collision (preserves original semantics)
- Add 3 tests: routing, unknown command, first-registered-wins collision

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

* improve: FrozenDictionary command dispatch map in WindowsNodeClient

Replace two O(n) FirstOrDefault(c => c.CanHandle(command)) scans
with O(1) FrozenDictionary lookup. TryAdd preserves first-registered-
wins semantics. Map rebuilt on each RegisterCapability() call
(startup only, before ConnectAsync).

Add event-path dispatch test to cover HandleNodeInvokeEventAsync
in addition to the request-path tests.

Based on Repo Assist PR #197, with additional test coverage.
Closes #197

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-23 10:54:20 -07:00
github-actions[bot]
c1e8955841
improve: modernize HandleRunAsync syntax; add policy+args regression tests (#181)
- Use range slice argv[1..] instead of argv.Skip(1).ToArray() (LINQ-free)
- Add SystemRun_SeparateArgsProperty_PolicyEvaluatesFullCommandLine: regression
  guard ensuring policy evaluates the full 'rm -rf /' when args come from the
  separate JSON 'args' property rather than the command argv array
- Add SystemRun_ShellFilter_PolicySkipsRuleForWrongShell: verifies that shell-
  filtered rules (Shells=["pwsh"]) are not applied when a different shell (cmd)
  is requested

588 Shared + 20 skipped; Tray unchanged.

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-23 10:26:23 -07:00
github-actions[bot]
0af3f95911
perf: pre-allocate arrays from JSON array length; replace LINQ sort with Array.Sort (#189)
Eliminates List<T>+ToArray() allocation in three JSON-parsing hot paths:

- TryGetHandshakeScopes: size string[] from GetArrayLength() upfront;
  avoid dynamic List<string> growth and second ToArray() copy.

- GetStringArrayArg (NodeCapabilities): same pattern; avoids List<string>
  on every capability command that receives an array argument.

- ParseNodeList: pre-size GatewayNodeInfo[] from GetArrayLength(); replace
  three-key LINQ sort chain with Array.Sort + static Comparison<T> delegate,
  eliminating the intermediate IOrderedEnumerable allocations.

Also adds 3 regression tests:
- ParseNodeListPayload_EmptyArray_ReturnsEmpty
- ParseNodeListPayload_SameOnlineStatus_SortsByLastSeenDescending
- ParseNodeListPayload_SkipsItemsWithNoNodeId

Test status: 633 Shared passed (+3), 20 skipped; 122 Tray passed.

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-23 10:26:13 -07:00
github-actions[bot]
9f1ef7bc16
improve: modernize Substring→range syntax; consolidate TruncateLabel duplicate (#180)
Replace all Substring(0, n) calls in OpenClaw.Shared with the equivalent
C# 8+ range syntax (str[..n]) for readability and consistency with the
rest of the codebase.

Also remove the private TruncateLabel helper from OpenClawGatewayClient —
its logic was identical to the public MenuDisplayHelper.TruncateText.
The three call sites now delegate to MenuDisplayHelper.TruncateText(..., 60)
directly, and the reflection-based test helper is updated to match.

586 Shared + 122 Tray tests pass.

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-23 10:26:02 -07:00
github-actions[bot]
022e5eff4f
improve: use FrozenSet for ExecEnvSanitizer blocked-names lookup (#194)
_blockedNames is initialised once at startup and never mutated.
FrozenSet gives lower constant-factor O(1) Contains() compared to
HashSet, and matches the pattern already used throughout the codebase
(ChannelHealth.s_healthyStatuses / s_intermediateStatuses in Models.cs,
NotificationCategorizer.ChannelMap / IntentMap, etc.).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-23 10:25:51 -07:00
github-actions[bot]
89322f294e
improve: pool receive buffer in WebSocketClientBase via ArrayPool (#204)
The ListenForMessagesAsync method previously allocated a new byte[] of
16-64 KB per connection, which can land on the Large Object Heap and
increase GC pressure on long-lived connections. SendRawAsync already
uses ArrayPool<byte>.Shared, so this change makes the receive path
consistent.

Key changes:
- Replace new byte[ReceiveBufferSize] with ArrayPool<byte>.Shared.Rent
- Slice ArraySegment to ReceiveBufferSize to prevent ArrayPool oversize
  from exposing extra bytes to ReceiveAsync
- Return buffer in a finally block covering all exit paths

No behaviour change; test suite unaffected (630 passed, 20 skipped).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-23 10:25:40 -07:00
github-actions[bot]
76fb1dc9e3
perf: eliminate LINQ Skip allocations in ExecShellWrapperParser (#193)
Replace string.Join(", ", tokens.Skip(i + 1)) with the indexed
string.Join(string, string[], int, int) overload in the three shell-
payload reconstruction sites (cmd /c, bash -c, powershell -Command).

Changes:
- Tokenize() now returns string[] instead of List<string>; callers
  already received it as an opaque list so the type narrowing is safe.
- ParsePowerShellPayload signature updated to string[] to match.
- Three string.Join(" ", tokens.Skip(i + 1)) calls replaced with
  string.Join(" ", tokens, i + 1, tokens.Length - i - 1) — uses the
  well-known BCL overload that slices directly into the array with no
  iterator allocation.
- Removes the now-unused 'using System.Linq;' import.

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-23 10:25:30 -07:00
github-actions[bot]
2c29677dc3
test: add HandleRequestError coverage for auth/scope/unknown-method paths (#202)
Add 13 new tests to OpenClawGatewayClientTests covering the
HandleRequestError private method via reflection:

Pairing required (3 tests):
- SetsPairingBlockFlag: verifies _pairingRequiredAwaitingApproval = true
- LogsWarning: verifies auto-reconnect-paused warning is emitted
- RaisesErrorStatus: verifies ConnectionStatus.Error is raised

Device signature invalid (2 tests):
- CyclesSignatureMode: verifies mode steps V3AuthToken -> V3EmptyToken
- LogsWarningWithMode: verifies rejection warning is logged

Missing operator.read scope (1 Theory x 4 cases):
- sessions.list, usage.status, usage.cost, node.list all set
  _operatorReadScopeUnavailable = true

Unknown method fallbacks (4 tests):
- usage.status, usage.cost, sessions.preview, node.list each set
  their respective _*Unsupported flags

Also adds GatewayClientTestHelper overloads:
- Constructor accepting IOpenClawLogger (for log capture)
- TrackPendingRequest, GetPairingRequiredFlag, GetSignatureTokenMode,
  GetOperatorReadScopeUnavailable, CaptureStatusChanges helpers

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-23 10:25:20 -07:00
github-actions[bot]
1c251dd9c7
eng: enable TreatWarningsAsErrors in test projects (#190)
Lock in the zero-warning baseline achieved by PR #177. Any future
compiler or analyser warning in the test suite now becomes a build
error, preventing warning accumulation over time.

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-23 10:25:11 -07:00
AlexAlves87
7454ffb09a
eng: add --no-restore to CI build steps after dotnet restore (#200)
Each dotnet build / dotnet publish step that followed an explicit
dotnet restore was redundantly re-checking NuGet dependencies.
Adding --no-restore eliminates that I/O on every CI run.

Five steps updated: Build Shared Library, Build Tests (x2),
Publish WinUI Tray App, Build Command Palette Extension.

The WinUI test build (-r win-x64) is excluded: the generic
dotnet restore in the test job runs without -r win-x64, so
project.assets.json lacks that RID target and --no-restore
would fail with NETSDK1047.

Closes #195.

Co-authored-by: AlexAlves87 <alexalves87@github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 10:04:26 -07:00
Scott Hanselman
1960a436e0
fix: address WinUI3 code review findings (#203)
Some checks failed
Build and Test / test (push) Has been cancelled
Build and Test / build (win-arm64) (push) Has been cancelled
Build and Test / build (win-x64) (push) Has been cancelled
Build and Test / build-msix (ARM64, win-arm64) (push) Has been cancelled
Build and Test / build-msix (x64, win-x64) (push) Has been cancelled
Build and Test / build-extension (arm64) (push) Has been cancelled
Build and Test / build-extension (x64) (push) Has been cancelled
Build and Test / release (push) Has been cancelled
- Add AutomationProperties.AutomationId to all interactive controls
- Add AutomationProperties.Name to 4 icon-only WebChat toolbar buttons
- Localize all SetupWizard strings via LocalizationHelper + .resw
- Replace hardcoded colors with ThemeResource brushes
- Replace raw FontSize with typography styles where appropriate

Prepares codebase for automated UI testing (winapp ui) and
proper Dark/Light/HighContrast theme support.
2026-04-22 22:28:53 -07:00
Scott Hanselman
5ecaa8427b fix: widen WebChat toolbar buttons to prevent icon clipping
Increase button width from 36 to 40px with explicit padding,
bump FontIcon size from 14 to 16, add right padding to toolbar.
2026-04-22 18:29:50 -07:00
Scott Hanselman
f235f3f999
feat: add setup wizard with pairing-aware connection test (#201)
Add SetupWizardWindow with 3-step onboarding flow:
- Step 1: Paste setup code (auto-decodes URL+token) or manual entry
  with connection test that understands pairing-required as success
- Step 2: Optional node mode with device ID and approve instructions
- Step 3: Done - saves settings and reconnects

Integration:
- Replace WelcomeDialog with wizard on first run (empty token)
- Add Setup Guide menu item to tray menu
- Add openclaw://setup deep link
- Guard node service against empty token (no crash)
- Contextual error messages for token mismatch, origin rejection,
  rate limiting, and pairing required

Addresses #199
2026-04-22 18:22:28 -07:00
Scott Hanselman
9134be49e1 test: strengthen audit coverage and enable CI integration checks
Some checks failed
Build and Test / test (push) Has been cancelled
Copilot Setup Steps / copilot-setup-steps (push) Has been cancelled
Build and Test / build (win-arm64) (push) Has been cancelled
Build and Test / build (win-x64) (push) Has been cancelled
Build and Test / build-msix (ARM64, win-arm64) (push) Has been cancelled
Build and Test / build-msix (x64, win-x64) (push) Has been cancelled
Build and Test / build-extension (arm64) (push) Has been cancelled
Build and Test / build-extension (x64) (push) Has been cancelled
Build and Test / release (push) Has been cancelled
Tighten weak assertions identified during the three-model test-suite audit and enable the Shared integration test lane in CI.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-19 22:55:52 -07:00
github-actions[bot]
0852ffee2e
perf: eliminate LINQ allocations in command execution path (#185)
Replace LINQ Select/Any with direct loops in three hot-path sites:

- ShellQuoting.FormatExecCommand: argv.Select(FormatSingleArg) →
  preallocated string[] + for loop; avoids enumerator state-machine alloc
- LocalCommandRunner.BuildProcessArgs: request.Args.Select(...) →
  preallocated string[] + for loop; same fix; drop unused System.Linq import
- ExecApprovalPolicy.Evaluate: rule.Shells.Any(...) → foreach with early
  break; avoids closure + enumerator alloc on every command approval check

All three sites are in the system.run execution path and can be called
repeatedly. The for-loop variants are allocation-free for the iteration
itself and improve throughput under load.

586 Shared + 122 Tray tests pass.

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-20 01:36:43 -04:00
github-actions[bot]
fd384574f5
fix: use integer truncation in FormatAge to prevent rounding past display boundaries (#183)
Math.Round with C# default banker's rounding (MidpointRounding.ToEven) can
produce counterintuitive results at display-threshold boundaries:

- 59.5 minutes -> Math.Round(59.5) = 60 -> displayed as '60m ago'
  instead of '59m ago' (or the correct transition to '1h ago')
- 47.5 hours -> Math.Round(47.5) = 48 -> displayed as '48h ago'
  instead of '47h ago' (near the 48h/days boundary)

Using integer truncation ((int)delta.TotalX) matches the idiomatic
convention for age display: show the floor of the elapsed time, which
is consistent, predictable, and never exceeds the guard condition.

Adds three regression tests covering:
- 59.5-minute boundary (was '60m ago', now '59m ago')
- 47.5-hour boundary (was '48h ago', now '47h ago')
- Exactly 60 seconds (correctly '1m ago')

Test status: Shared.Tests 589 passed, 20 skipped; Tray.Tests 122 passed.

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-20 01:36:39 -04:00
github-actions[bot]
e9f18f78c9
improve: use SearchValues<char> in ShellQuoting.NeedsQuoting for SIMD scan (#182)
Replace per-character foreach+switch with System.Buffers.SearchValues<char>,
which uses SSE2/AVX2 vectorized IndexOfAny to detect shell metacharacters
in a single SIMD pass instead of a character-by-character loop.

- Add static SearchValues<char> s_shellMetachars (same 25-char set as former
- Replace NeedsQuoting foreach body with arg.AsSpan().IndexOfAny(s_shellMetachars) >= 0
- Remove private IsShellMetachar helper (no longer needed)
- Add using System.Buffers (SearchValues<T> namespace)

SearchValues<char> is available since .NET 8; this project targets net10.0.
All existing ShellQuotingTests pass unchanged.

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-20 01:36:35 -04:00
github-actions[bot]
eeac8d5c7c
perf: replace HashSet/ToLowerInvariant with FrozenSet/FrozenDictionary in ChannelHealth; eliminate List<string> in GatewayUsageInfo.DisplayText (#175)
ChannelHealth:
- s_healthyStatuses/s_intermediateStatuses: HashSet<string> → FrozenSet<string>
  (O(1) lookup, no per-call allocation; consistent with existing FrozenDictionary
  pattern in NotificationCategorizer and OpenClawGatewayClient)
- DisplayText: Status.ToLowerInvariant() switch → FrozenDictionary<string,string>
  s_statusLabels lookup (eliminates the lowercase string allocation on every
  channel health update)

GatewayUsageInfo.DisplayText:
- List<string>/string.Join → nullable string?[4] accumulator + string.Join
  overload with offset+count (single array allocation; no List wrapper)

Tests (+8):
- ChannelHealth.DisplayText_CaseInsensitiveLabelLookup (6 cases: RUNNING,
  Connected, READY, NOT CONFIGURED, Connecting, STOPPED)
- GatewayUsageInfo.DisplayText_PreservesPartOrder_TokensBeforeCostBeforeRequests
- GatewayUsageInfo.DisplayText_ModelOnlyWithTokens_SeparatedBySeparator

Result: 594 Shared passed, 20 skipped; 122 Tray passed (was 586+122)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-20 01:36:31 -04:00
github-actions[bot]
c9255f9d94
perf: eliminate List<string> allocation in BuildProviderSummary (#173)
BuildProviderSummary is called on every gateway usage-status update.
The previous implementation allocated a List<string> (up to 3 entries)
and called string.Join, producing a heap-allocated list wrapper plus
join enumeration in addition to the final string.

With at most 2 provider slots + an optional overflow suffix, the
combinations fit into two nullable string variables and a switch
expression, producing only the final string allocation.

Also adds 9 unit tests covering all branch paths:
empty providers, single-provider with usage/error/no-windows,
two providers, three providers (overflow), missing display name,
all-empty providers, and overflow with one valid provider.

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-20 01:36:27 -04:00