Commit Graph

161 Commits

Author SHA1 Message Date
copilot-swe-agent[bot]
d72c5510ec
test: add 22 new tests for WindowsNodeClient and OpenClawGatewayClient coverage
Agent-Logs-Url: https://github.com/openclaw/openclaw-windows-node/sessions/d2e01bd9-cb98-4298-9d46-adc8f56bb2d8

Co-authored-by: shanselman <2892+shanselman@users.noreply.github.com>
2026-04-01 20:59:38 +00:00
Scott Hanselman
0be021398c Merge PR #129: modernize string operations in GatewayUrlHelper and SettingsData 2026-04-01 10:00:39 -07:00
github-actions[bot]
84425718aa eng: enhance .editorconfig with modern C# idiom preferences
Add missing code style rules that codify the idioms already used in the
codebase, making IDE suggestions consistent for all contributors:

- csharp_style_prefer_range_operator / prefer_index_operator: prefer
  range indexers ([..n], [n..], [^1]) over Substring / Length-based
  arithmetic (directly reinforces the refactoring in GatewayUrlHelper)
- csharp_style_prefer_switch_expression: prefer switch expressions
  over if/else chains (already used throughout Models.cs etc.)
- csharp_style_prefer_pattern_matching / prefer_not_pattern
- csharp_prefer_simple_using_statement: prefer declaration-style
  'using var x = ...' without a nested block
- dotnet_style_prefer_simplified_boolean_expressions
- dotnet_style_prefer_inferred_tuple_names /
  prefer_inferred_anonymous_type_member_names

No functional changes. 521 shared + 99 tray tests pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-01 13:02:38 +00:00
github-actions[bot]
7b212f3824 refactor: modernize string operations in GatewayUrlHelper and SettingsData
- GatewayUrlHelper: replace Substring calls with C# range indexers ([..n],
  [n..]) and use string.Concat(ReadOnlySpan<char>, ...) for RemoveUserInfo
  to avoid an intermediate string allocation
- SettingsData.FromJson: narrow bare catch to catch (JsonException) so
  unexpected non-JSON errors (e.g. OutOfMemoryException) are not silently
  swallowed and masked

521 shared + 99 tray tests pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-01 13:02:34 +00:00
Scott Hanselman
344461d30d
fix: honour PreferStructuredCategories in notification pipeline
When PreferStructuredCategories is false, classification skips structured metadata (Intent, Channel) and goes straight to user rules + keyword fallback.

5 new tests. 521 shared tests pass.

Reimplements #104 on current master.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-01 00:05:50 -07:00
Sytone
1d836390e9
feat: SSH tunnel gateway, device identity, reconnect hardening
Adds SSH local port-forward support for secure remote gateway access, Ed25519 device identity for operator auth, enhanced Quick Send with error remediation, reconnect resilience, and OpenClaw.Cli validator tool.

Includes security fix: SSH user/host input validation to prevent command injection.

615 tests pass (516 shared + 99 tray).

Contributed by @sytone
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-01 00:03:43 -07:00
Scott Hanselman
4e7225ba8c fix: add missing System.Collections.Frozen using in App.xaml.cs
PR #105 introduced ToFrozenDictionary but missed the using directive
for the WinUI project. Fixes build break on master.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-31 23:50:49 -07:00
github-actions[bot]
37a5f9453d
docs: add SETUP.md and POWERTOYS.md guides
Comprehensive Windows Node setup guide and PowerToys Command Palette extension documentation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-31 23:44:18 -07:00
github-actions[bot]
cfe9e1f75b
refactor: eliminate ToLowerInvariant allocations in ChannelHealth
HashSet lookups with OrdinalIgnoreCase instead of pattern matching on lowered strings.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-31 23:44:06 -07:00
github-actions[bot]
7aba505320
perf: skip StringBuilder in single-frame WebSocket receive
Fast-path single-frame messages to avoid StringBuilder allocation. Caches payload.ToString() in node logging.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-31 23:44:00 -07:00
github-actions[bot]
cca7493dce
perf: eliminate string allocations in ClassifyByKeywords
Replace .ToLowerInvariant() with OrdinalIgnoreCase, FrozenDictionary for tool kind map.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-31 23:43:54 -07:00
github-actions[bot]
10804c6305
perf: cache HTML sanitize regex, replace ToLowerInvariant in notification type lookup
Static compiled regexes for SanitizeHtml, FrozenDictionary for notification type map.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-31 23:43:49 -07:00
github-actions[bot]
52aa813129
fix: reset node/gateway state on settings save
Clears _isPendingApproval on disconnect/error, resets gateway state properly in OnSettingsSaved.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-31 23:43:33 -07:00
github-actions[bot]
9087ed21eb
fix: prevent double PairingStatusChanged fire in hello-ok handler
Guards gotNewToken flag to prevent event double-firing during pairing flow. Adds regression tests.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-31 23:43:27 -07:00
github-actions[bot]
180acbe7c1
fix: pass UserRules to NotificationCategorizer (closes #94)
UserRules from settings were never passed to Classify() — custom notification rules were silently ignored.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-31 23:43:12 -07:00
Nich Overend
b511e509e0
fix: constrain tray menu height to work area, enable scroll (fixes #82)
Fixes overheight menu that could extend beyond screen.

- Add MenuSizingHelper for DPI-aware work area clamping
- Use GetDpiForMonitor with proper fallback chain
- Set ScrollViewer to Visible vertical scrollbar
- 4 regression tests for clamping, DPI conversion, and markup

Contributed by @NichUK
2026-03-31 23:40:36 -07:00
github-actions[bot]
c39293cbaa
fix: add ReDoS timeout to ExecApprovalPolicy glob matching
Adds 100ms timeout to regex matching in exec approval policy to prevent ReDoS. Returns deny on timeout (safe default).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-31 23:39:29 -07:00
github-actions[bot]
178b0054a7
fix: add operator.write scope to gateway connect handshake
Adds missing operator.write permission scope to gateway connection.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-31 23:39:23 -07:00
github-actions[bot]
f086473c40
refactor: extract ModelFormatting helper
Eliminates duplicate FormatTokenCount/FormatCount methods across ModelInfo and GatewayUsageInfo.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-31 23:39:19 -07:00
github-actions[bot]
a9531e751b
refactor: use result.Parameters in DeepLinkHandler
Replaces manual query string parsing with result.Parameters dictionary lookup.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-31 23:39:05 -07:00
github-actions[bot]
937c6cab5d
refactor: remove dead ClassifyNotification method
Removes unused private ClassifyNotification from GatewayClient; updates tests to call NotificationCategorizer directly instead of via reflection.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-31 23:39:00 -07:00
github-actions[bot]
52597f8dca
eng: add .editorconfig for consistent C# style
Adds .editorconfig with Allman braces, underscore camelCase fields, file-scoped namespaces.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-31 23:38:56 -07:00
github-actions[bot]
b21ca94fb1
fix: null _gatewayClient after dispose in OnSettingsSaved
Prevents use-after-dispose by setting _gatewayClient = null after Dispose().

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-31 23:38:39 -07:00
Rundredoffi
dd487ab8a4
feat: add French (fr-fr) localization
Adds complete fr-fr (French) translation — all 163 resource keys.

Contributed by @rundredoffi in response to #61.
2026-03-31 17:34:57 -07:00
Tim0320
cf87a692d0
feat: add Traditional Chinese (zh-tw) localization
Adds complete zh-tw (Traditional Chinese) translation — all 163 resource keys.

Contributed by @Tim0320 in response to #61.
2026-03-31 17:34:54 -07:00
Scott Hanselman
519374c306
fix: notification sound + TryParseArgv refactor (closes #91, #92, #71)
- Extract TryParseArgv helper, consolidating ~40 lines of duplicated argv parsing
- Fix operator precedence in HandleExecApprovalsSet
- Add ShowToast helper applying NotificationSound setting to all 14 toast call sites
- 5 new argv parsing tests

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-31 15:54:37 -07:00
Scott Hanselman
de515926e1
chore: quick-win triage — global.json, test tooling, localization tests
- Pin .NET SDK via global.json (10.0.100, latestPatch) (closes #123)
- Sync xunit.runner.visualstudio 3.1.4 + add coverlet.collector to Tray.Tests (closes #90)
- Add localization key parity + format placeholder validation tests (closes #70)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-31 15:54:34 -07:00
Scott Hanselman
536d436989
perf: cache JsonSerializerOptions and compiled Regex in WindowsNodeClient
Cache hot-path allocations: static JsonSerializerOptions (WhenWritingNull, WriteIndented) and compiled Regex for command validation.
Eliminates per-message allocations in node.invoke handlers.

Supersedes Repo Assist #65.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-18 10:18:41 -07:00
Scott Hanselman
a9de0c77a5
ci: add NuGet package caching to test job
Adds actions/cache@v4 for ~/.nuget/packages keyed on csproj hashes.
Saves ~30-60s on subsequent CI runs.

Supersedes Repo Assist #66.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-18 10:18:37 -07:00
Scott Hanselman
76f7811a14
Refactor: Extract WebSocketClientBase (DRY #63)
Extracts ~200 lines of duplicated WebSocket lifecycle code into shared abstract base class.

- Template method pattern: base owns lifecycle, subclasses override hooks
- ProcessMessageAsync always async (Task.CompletedTask for sync gateway)
- Private _webSocket, subclasses use SendRawAsync only
- 20 new base class tests, 596 total pass
- 399 lines removed, net ~170 less production code

Closes #63

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-18 09:59:00 -07:00
Scott Hanselman
27b1de3600
fix: security hardening from triple-model review (#62)
7 fixes from Opus/Codex/Gemini triple-model review with cross-validation:

Consensus (2+ models agreed):
- ExecApprovalPolicy bypass: full argv evaluated, not just argv[0]
- Thread safety: lock pattern for _sessions/_nodes dictionaries
- SendRawAsync/Dispose races: defensive patterns from WindowsNodeClient

Cross-validated (different model confirmed):
- Canvas jsonlPath restricted to temp directory (arbitrary file read)
- ChannelHealth 'active' status shows [ON] not [OFF]
- OnSettingsSaved mirrors startup if/else (no dual connections)
- TryEnqueue checked in OnCanvasEval/OnCanvasSnapshot (prevents hang)

5 new security tests. All 576 tests pass.
2026-03-17 21:55:52 -07:00
Scott Hanselman
c85d4e7571
feat: complete Chinese localization + contributor guide (#60)
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
Localize ~40 remaining hardcoded English strings (toasts, canvas, webchat, download dialog). Both en-US and zh-CN now have 163 resource keys, fully in sync.

- Add LocalizationHelper.SetLanguageOverride() for unpackaged app locale testing
- Add docs/LOCALIZATION.md contributor guide
- File issue #61 calling for community translations

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-17 21:12:45 -07:00
Scott Hanselman
c8e55fe194 ci: sign ARM64 artifacts on x64 runner in release job
Some checks failed
Build and Test / test (push) Has been cancelled
Build and Test / build (win-x64) (push) Has been cancelled
Build and Test / build (win-arm64) (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
The Azure Trusted Signing dlib (x64) fails with exit code 3 when
running under emulation on the ARM64 runner (windows-11-arm).

Fix: Skip signing in the build/build-msix jobs for ARM64 targets.
Instead, sign ARM64 executables and MSIX packages in the release job,
which runs on windows-latest (x64) where the signing dlib works.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-17 20:46:33 -07:00
Scott Hanselman
882937299a docs: remove stale WinForms references, update test counts and capabilities
- README.md: Fix project table (OpenClaw.Tray → OpenClaw.Tray.WinUI),
  remove WinForms run command, add system.run.prepare and system.which
  to capability table and allowCommands JSON, remove '(investigating)'
  from canvas.a2ui commands
- DEVELOPMENT.md: Remove OpenClaw.Tray/ from structure, add
  OpenClaw.Tray.Tests/, update test counts (88 → 571), fix CI section
- build.ps1: Fix broken 'Tray' target to point at WinUI .csproj,
  remove WinForms from default build and run instructions
- docs/VERSIONING.md: Remove reference to deleted OpenClaw.Tray.csproj
- docs/TEST_COVERAGE.md: Full rewrite (88 → 571 tests, .NET 9 → 10)
- docs/CODE_REVIEW.md: Update project names, test counts, .NET version
- docs/WINDOWS_NODE_TESTING.md: Mark system.run as implemented, update
  capability descriptions
- docs/WINDOWS_NODE_ARCHITECTURE.md: Add historical planning note,
  update current state table (Node mode now implemented)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-17 20:38:13 -07:00
Scott Hanselman
3634f3d112 test: fix false-positive session sorting test and tautological menu assertion
- GetSessionList_SortsMainSessionFirst now populates 3 sessions via
  ParseSessions and verifies the main session is sorted first, instead
  of only asserting an empty list.
- Added ParseSessionsPayload helper to expose the private parser.
- TaskbarAtBottom_TypicalScenario assertion changed from the tautological
  'y + MenuHeight <= 1040 || y >= 0' to the strict 'y + MenuHeight <= 1040'.

571/571 tests pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-17 19:21:35 -07:00
Scott Hanselman
6817bbffcb
ci: add OpenClaw.Tray.Tests to the CI test job
The 93-test Tray test suite (added in PR #45) was never wired into CI. Adds build + run steps for OpenClaw.Tray.Tests so all 571 tests validate on every push/PR.

Closes #58

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-17 19:02:39 -07:00
Scott Hanselman
4549b62af5
[Repo Assist] fix: refresh channel list when channels are added/removed on gateway
Fixes two bugs that together caused issue #55:

1. Remove the healthList.Count > 0 guard so ChannelHealthUpdated fires even when all channels are removed.
2. Dispatch StatusDetailWindow.UpdateStatus when the window is already open.

3 new unit tests added. 478/478 shared tests pass.

Closes #55

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-17 10:49:23 -07:00
Scott Hanselman
302dfaa79f
fix: surface gateway error messages in Settings test connection (#54)
The TestLogger was silently swallowing all gateway client errors,
so connection failures showed a generic 'Connection failed' message.
Now captures the last error/warning and displays the actual gateway
message (e.g. 'origin not allowed') in the status label.

Also keeps verbose logging to Debug.WriteLine for dbgview-mcp
diagnostics.
2026-03-16 23:43:12 -07:00
Scott Hanselman
6e2069d0ad
feat: improve debug instrumentation across WinUI tray app (#53)
Add structured logging to under-instrumented windows and services:
- StatusDetailWindow, SettingsWindow, ActivityStreamWindow,
  NotificationHistoryWindow, QuickSendDialog, WelcomeDialog,
  UpdateDialog, ActivityStreamService
- Replace raw Debug.WriteLine in CanvasWindow with Logger
- Use appropriate log levels (ERROR/WARN/INFO/DEBUG)

Closes #52
2026-03-16 23:02:31 -07:00
Scott Hanselman
f0ccbc8403
chore: clean up stale files and fix repo URLs (#51)
- Remove input.json.bak (stray backup file)
- Update README project structure (remove old OpenClaw.Tray, add
  WinUI and test projects)
- Fix installer URLs to point at openclaw/openclaw-windows-node
  instead of old shanselman/moltbot-windows-hub
2026-03-16 22:25:32 -07:00
Scott Hanselman
8e4c7bd587
chore: remove WinForms tray app (OpenClaw.Tray) (#50)
WinUI tray has full feature parity plus Node Mode, Activity Stream,
session management, cost tracking, localization, and modern XAML UI.

- Remove src/OpenClaw.Tray/ (28 files, ~4900 lines)
- Remove from solution file
- Remove WinForms build step from CI

Installer already only references WinUI. Settings.json format is
unchanged — no migration needed.

Closes #44
2026-03-16 21:58:19 -07:00
Scott Hanselman
313e69e483
fix(winui): guard missing SendMessage deep link handler (#49)
Add null check on actions.SendMessage before invoking in the agent
deep link path. Removes null-forgiving operator that would throw
NullReferenceException inside Task.Run if the handler wasn't wired.
Adds warning log for diagnosability.

Fixes #47
Based on PR #48 by @Alix-007, adapted for current codebase.
2026-03-16 21:56:52 -07:00
Scott Hanselman
afaaa04447
feat: add localization infrastructure with English and Chinese resources (#46)
Add WinUI .resw resource files for proper multi-language support:
- Strings/en-us/Resources.resw with all extractable UI strings
- Strings/zh-cn/Resources.resw with Chinese Simplified translations
- x:Uid attributes on XAML elements for automatic resource lookup
- LocalizationHelper for C# runtime string localization
- Windows auto-selects language based on OS locale

Any language can now be added by contributing a new .resw file.

Addresses #40
2026-03-16 21:44:17 -07:00
Scott Hanselman
bc140e9cca
feat: add WinUI test project with extracted helpers (#45)
Extract testable pure logic from WinUI tray app into shared helpers:
- MenuDisplayHelper: status icons, text truncation, provider formatting
- DeepLinkParser: URI parsing for openclaw:// deep links
- MenuPositioner: tray popup positioning calculations

Create tests/OpenClaw.Tray.Tests with comprehensive coverage for
all extracted helpers plus settings serialization round-trips.

Closes #43
2026-03-16 21:40:55 -07:00
Scott Hanselman
b6b62390ef
fix: persist NotificationSound by stable key, not display text (#42)
Use Tag attribute on WinUI ComboBoxItems to decouple display text
from persisted settings values. Load and save by Tag instead of
Content in SettingsWindow.xaml.cs.

Add documentation comment in WinForms SettingsDialog.cs making
the persistence contract explicit.

Backward compatible — existing settings.json values already match
the Tag keys. Worst case for unknown values: falls back to Default.

Fixes #41
2026-03-16 19:21:02 -07:00
Scott Hanselman
530f645efe
perf: hoist shell normalisation and cache notification regex objects (#39)
ExecApprovalPolicy.Evaluate: normalizedShell was allocated inside the
foreach loop for every rule that carries a shell filter.  Moving the
computation before the loop avoids the repeated allocation on the hot
command-evaluation path.

NotificationCategorizer.MatchesRule: the static Regex.IsMatch overload
that accepts a matchTimeout bypasses .NET's internal regex cache, so a
new Regex object was compiled on every incoming notification for each
regex-pattern user rule.  Replace with a ConcurrentDictionary<string,
Regex?> that caches compiled instances (constructed with the 100 ms
timeout so ReDoS protection is preserved).  Subsequent notifications
reuse the same compiled automaton.

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-16 18:38:35 -07:00
Scott Hanselman
9818229c89
Merge pull request #38 from openclaw/fix/system-run-quoting-and-hang
Merges the consolidated fix for system.run hang (#29), argv quoting (#32), and review hardening. Fixes #28.
2026-03-16 18:31:57 -07:00
Scott Hanselman
8c1bd38f3f refactor: extract ShellQuoting helper, add comprehensive tests
Extract duplicated metacharacter quoting logic from LocalCommandRunner
and SystemCapability into a shared ShellQuoting static class, following
the established GatewayUrlHelper pattern.

- ShellQuoting.NeedsQuoting: single source of truth for metachar detection
- ShellQuoting.QuoteForShell: shell-aware quoting (cmd vs PowerShell)
- ShellQuoting.FormatExecCommand: display formatting for gateway
- IsShellMetachar: idiomatic switch expression instead of duplicated
  multi-case switch blocks
- 43 new unit tests covering all metacharacters, escaping edge cases,
  null handling, and both shell modes

Co-authored-by: danedane <1402819+danedane@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-16 18:26:06 -07:00
Scott Hanselman
419398e9ca fix: harden argv quoting and thread-safe output buffering
Address review findings from PRs #29 and #32:

- QuoteArgIfNeeded: check all shell metacharacters (& | ; < > etc.),
  not just whitespace/quotes — prevents command injection
- cmd.exe: use doubled-quote escaping (%"%") instead of backslash
  which cmd doesn't recognize
- FormatExecCommand: align metacharacter checks with QuoteArgIfNeeded
  so system.run.prepare shows the same command that actually executes
- StringBuilder: add lock around stdout/stderr event handlers and
  ToString() reads to prevent concurrent-access corruption

Co-authored-by: danedane <1402819+danedane@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-16 18:24:15 -07:00
Q
5dbf56a28f feat(system.run): add system.run.prepare pre-flight command
The gateway's nodes 'run' action requires system.run.prepare to build
an execution plan before the actual run. Without it, the only path is
the 'invoke' action which has a hardcoded 30s gateway timeout — too
short for long-running tools like Copilot CLI.

system.run.prepare echoes back the argv, cwd, rawCommand, agentId,
and sessionKey without executing anything, enabling the gateway to
use its configurable timeout path for the actual execution.
2026-03-16 18:24:15 -07:00